Coverage Report

Created: 2026-10-15 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/libfreerdp/codec/dsp.c
Line
Count
Source
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Digital Sound Processing
4
 *
5
 * Copyright 2010-2011 Vic Lee
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
20
#include <freerdp/config.h>
21
22
#include <winpr/assert.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include <winpr/crt.h>
28
29
#include <freerdp/types.h>
30
#include <freerdp/log.h>
31
#include <freerdp/codec/dsp.h>
32
33
#include "dsp.h"
34
35
#if defined(WITH_FDK_AAC)
36
#include "dsp_fdk_aac.h"
37
#endif
38
39
#if defined(WITH_MEDIACODEC)
40
#include "dsp_mediacodec.h"
41
#endif
42
43
#if !defined(WITH_DSP_FFMPEG)
44
#if defined(WITH_GSM)
45
#include <gsm/gsm.h>
46
#endif
47
48
#if defined(WITH_LAME)
49
#include <lame/lame.h>
50
#endif
51
52
#if defined(WITH_OPUS)
53
#include <opus/opus.h>
54
55
#define OPUS_MAX_FRAMES 5760ull
56
#endif
57
58
#if defined(WITH_FAAD2)
59
#include <neaacdec.h>
60
#endif
61
62
#if defined(WITH_FAAC)
63
#include <faac.h>
64
#endif
65
66
#if defined(WITH_SOXR)
67
#include <soxr.h>
68
#endif
69
70
#else
71
#include "dsp_ffmpeg.h"
72
#endif
73
74
#if !defined(WITH_DSP_FFMPEG)
75
76
#define TAG FREERDP_TAG("dsp")
77
78
typedef union
79
{
80
  struct
81
  {
82
    size_t packet_size;
83
    INT16 last_sample[2];
84
    INT16 last_step[2];
85
  } ima;
86
  struct
87
  {
88
    BYTE predictor[2];
89
    INT32 delta[2];
90
    INT32 sample1[2];
91
    INT32 sample2[2];
92
  } ms;
93
} ADPCM;
94
95
struct S_FREERDP_DSP_CONTEXT
96
{
97
  FREERDP_DSP_COMMON_CONTEXT common;
98
99
  ADPCM adpcm;
100
101
#if defined(WITH_GSM)
102
  gsm gsm;
103
#endif
104
#if defined(WITH_LAME)
105
  lame_t lame;
106
  hip_t hip;
107
#endif
108
#if defined(WITH_OPUS)
109
  OpusDecoder* opus_decoder;
110
  OpusEncoder* opus_encoder;
111
#endif
112
#if defined(WITH_FAAD2)
113
  NeAACDecHandle faad;
114
  BOOL faadSetup;
115
#endif
116
117
#if defined(WITH_FAAC)
118
  faacEncHandle faac;
119
  unsigned long faacInputSamples;
120
  unsigned long faacMaxOutputBytes;
121
#endif
122
123
#if defined(WITH_SOXR)
124
  soxr_t sox;
125
#endif
126
};
127
128
#if defined(WITH_OPUS)
129
static BOOL opus_is_valid_samplerate(const AUDIO_FORMAT* WINPR_RESTRICT format)
130
{
131
  WINPR_ASSERT(format);
132
133
  switch (format->nSamplesPerSec)
134
  {
135
    case 8000:
136
    case 12000:
137
    case 16000:
138
    case 24000:
139
    case 48000:
140
      return TRUE;
141
    default:
142
      return FALSE;
143
  }
144
}
145
#endif
146
147
static INT16 read_int16(const BYTE* WINPR_RESTRICT src)
148
0
{
149
0
  return (INT16)(src[0] | (src[1] << 8));
150
0
}
151
152
static BOOL freerdp_dsp_channel_mix(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
153
                                    const BYTE* WINPR_RESTRICT src, size_t size,
154
                                    const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,
155
                                    const BYTE** WINPR_RESTRICT data, size_t* WINPR_RESTRICT length)
156
0
{
157
0
  if (!context || !data || !length)
158
0
    return FALSE;
159
160
0
  if (srcFormat->wFormatTag != WAVE_FORMAT_PCM)
161
0
    return FALSE;
162
163
0
  const UINT32 bpp = srcFormat->wBitsPerSample > 8 ? 2 : 1;
164
0
  const size_t samples = size / bpp / srcFormat->nChannels;
165
166
0
  if (context->common.format.nChannels == srcFormat->nChannels)
167
0
  {
168
0
    *data = src;
169
0
    *length = size;
170
0
    return TRUE;
171
0
  }
172
173
0
  Stream_ResetPosition(context->common.channelmix);
174
175
  /* Destination has more channels than source */
176
0
  if (context->common.format.nChannels > srcFormat->nChannels)
177
0
  {
178
0
    switch (srcFormat->nChannels)
179
0
    {
180
0
      case 1:
181
0
        if (!Stream_EnsureCapacity(context->common.channelmix, size * 2))
182
0
          return FALSE;
183
184
0
        for (size_t x = 0; x < samples; x++)
185
0
        {
186
0
          for (size_t y = 0; y < bpp; y++)
187
0
            Stream_Write_UINT8(context->common.channelmix, src[x * bpp + y]);
188
189
0
          for (size_t y = 0; y < bpp; y++)
190
0
            Stream_Write_UINT8(context->common.channelmix, src[x * bpp + y]);
191
0
        }
192
193
0
        Stream_SealLength(context->common.channelmix);
194
0
        *data = Stream_Buffer(context->common.channelmix);
195
0
        *length = Stream_Length(context->common.channelmix);
196
0
        return TRUE;
197
198
0
      case 2:  /* We only support stereo, so we can not handle this case. */
199
0
      default: /* Unsupported number of channels */
200
0
        return FALSE;
201
0
    }
202
0
  }
203
204
  /* Destination has less channels than source */
205
0
  switch (srcFormat->nChannels)
206
0
  {
207
0
    case 2:
208
0
      if (!Stream_EnsureCapacity(context->common.channelmix, size / 2))
209
0
        return FALSE;
210
211
      /* Simply drop second channel.
212
       * TODO: Calculate average */
213
0
      for (size_t x = 0; x < samples; x++)
214
0
      {
215
0
        for (size_t y = 0; y < bpp; y++)
216
0
          Stream_Write_UINT8(context->common.channelmix, src[2 * x * bpp + y]);
217
0
      }
218
219
0
      Stream_SealLength(context->common.channelmix);
220
0
      *data = Stream_Buffer(context->common.channelmix);
221
0
      *length = Stream_Length(context->common.channelmix);
222
0
      return TRUE;
223
224
0
    case 1:  /* Invalid, do we want to use a 0 channel sound? */
225
0
    default: /* Unsupported number of channels */
226
0
      return FALSE;
227
0
  }
228
229
0
  return FALSE;
230
0
}
231
232
/**
233
 * Microsoft Multimedia Standards Update
234
 * http://download.microsoft.com/download/9/8/6/9863C72A-A3AA-4DDB-B1BA-CA8D17EFD2D4/RIFFNEW.pdf
235
 */
236
237
static BOOL freerdp_dsp_resample(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
238
                                 const BYTE* WINPR_RESTRICT src, size_t size,
239
                                 const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,
240
                                 const BYTE** WINPR_RESTRICT data, size_t* WINPR_RESTRICT length)
241
0
{
242
0
  AUDIO_FORMAT format;
243
244
0
  if (srcFormat->wFormatTag != WAVE_FORMAT_PCM)
245
0
  {
246
0
    WLog_ERR(TAG, "requires %s for sample input, got %s",
247
0
             audio_format_get_tag_string(WAVE_FORMAT_PCM),
248
0
             audio_format_get_tag_string(srcFormat->wFormatTag));
249
0
    return FALSE;
250
0
  }
251
252
  /* We want to ignore differences of source and destination format. */
253
0
  format = *srcFormat;
254
0
  format.wFormatTag = WAVE_FORMAT_UNKNOWN;
255
0
  format.wBitsPerSample = 0;
256
257
0
  if (audio_format_compatible(&format, &context->common.format))
258
0
  {
259
0
    *data = src;
260
0
    *length = size;
261
0
    return TRUE;
262
0
  }
263
264
#if defined(WITH_SOXR)
265
  const size_t srcBytesPerFrame = (srcFormat->wBitsPerSample > 8) ? 2 : 1;
266
  const size_t dstBytesPerFrame = (context->common.format.wBitsPerSample > 8) ? 2 : 1;
267
  const size_t srcChannels = srcFormat->nChannels;
268
  const size_t dstChannels = context->common.format.nChannels;
269
  const size_t sbytes = srcChannels * srcBytesPerFrame;
270
  const size_t sframes = size / sbytes;
271
  const size_t rbytes = dstBytesPerFrame * dstChannels;
272
  /* Integer rounding correct division */
273
  const size_t rframes =
274
      (sframes * context->common.format.nSamplesPerSec + (srcFormat->nSamplesPerSec + 1) / 2) /
275
      srcFormat->nSamplesPerSec;
276
  const size_t rsize = rframes * rbytes;
277
278
  if (!Stream_EnsureCapacity(context->common.resample, rsize))
279
    return FALSE;
280
281
  size_t idone = 0;
282
  size_t odone = 0;
283
  soxr_error_t error =
284
      soxr_process(context->sox, src, sframes, &idone, Stream_Buffer(context->common.resample),
285
                   Stream_Capacity(context->common.resample) / rbytes, &odone);
286
  if (!Stream_SetLength(context->common.resample, odone * rbytes))
287
    return FALSE;
288
289
  *data = Stream_Buffer(context->common.resample);
290
  *length = Stream_Length(context->common.resample);
291
  return (error == nullptr);
292
#else
293
0
  WLog_ERR(TAG, "Missing resample support, recompile -DWITH_SOXR=ON or -DWITH_DSP_FFMPEG=ON");
294
0
  return FALSE;
295
0
#endif
296
0
}
297
298
/**
299
 * Microsoft IMA ADPCM specification:
300
 *
301
 * http://wiki.multimedia.cx/index.php?title=Microsoft_IMA_ADPCM
302
 * http://wiki.multimedia.cx/index.php?title=IMA_ADPCM
303
 */
304
305
static const INT16 ima_step_index_table[] = {
306
  -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8
307
};
308
309
static const INT16 ima_step_size_table[] = {
310
  7,     8,     9,     10,    11,    12,    13,    14,    16,    17,    19,   21,    23,
311
  25,    28,    31,    34,    37,    41,    45,    50,    55,    60,    66,   73,    80,
312
  88,    97,    107,   118,   130,   143,   157,   173,   190,   209,   230,  253,   279,
313
  307,   337,   371,   408,   449,   494,   544,   598,   658,   724,   796,  876,   963,
314
  1060,  1166,  1282,  1411,  1552,  1707,  1878,  2066,  2272,  2499,  2749, 3024,  3327,
315
  3660,  4026,  4428,  4871,  5358,  5894,  6484,  7132,  7845,  8630,  9493, 10442, 11487,
316
  12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
317
};
318
319
static inline void dsp_ima_clamp_step(ADPCM* WINPR_RESTRICT adpcm, size_t channel)
320
0
{
321
0
  WINPR_ASSERT(adpcm);
322
0
  if (adpcm->ima.last_step[channel] < 0)
323
0
    adpcm->ima.last_step[channel] = 0;
324
325
0
  const size_t size = ARRAYSIZE(ima_step_size_table);
326
0
  if ((size_t)adpcm->ima.last_step[channel] >= size)
327
0
    adpcm->ima.last_step[channel] = (INT16)(size - 1);
328
0
}
329
330
static UINT16 dsp_decode_ima_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, unsigned int channel,
331
                                          BYTE sample)
332
0
{
333
0
  WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_step));
334
0
  WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_sample));
335
336
0
  const INT16 offset = adpcm->ima.last_step[channel];
337
0
  WINPR_ASSERT(offset >= 0);
338
0
  WINPR_ASSERT(WINPR_CXX_COMPAT_CAST(size_t, offset) < ARRAYSIZE(ima_step_size_table));
339
340
0
  const INT32 ss = ima_step_size_table[offset];
341
0
  INT32 d = (ss >> 3);
342
343
0
  if (sample & 1)
344
0
    d += (ss >> 2);
345
346
0
  if (sample & 2)
347
0
    d += (ss >> 1);
348
349
0
  if (sample & 4)
350
0
    d += ss;
351
352
0
  if (sample & 8)
353
0
    d = -d;
354
355
0
  d += adpcm->ima.last_sample[channel];
356
357
0
  if (d < -32768)
358
0
    d = -32768;
359
0
  else if (d > 32767)
360
0
    d = 32767;
361
362
0
  adpcm->ima.last_sample[channel] = (INT16)d;
363
364
0
  WINPR_ASSERT(sample < ARRAYSIZE(ima_step_index_table));
365
0
  const int32_t last = adpcm->ima.last_step[channel] + ima_step_index_table[sample];
366
0
  adpcm->ima.last_step[channel] = WINPR_ASSERTING_INT_CAST(int16_t, last);
367
368
0
  dsp_ima_clamp_step(adpcm, channel);
369
370
0
  return (UINT16)d;
371
0
}
372
373
static BOOL valid_ima_adpcm_format(const FREERDP_DSP_CONTEXT* WINPR_RESTRICT context)
374
0
{
375
0
  WINPR_ASSERT(context);
376
0
  if (context->common.format.wFormatTag != WAVE_FORMAT_DVI_ADPCM)
377
0
    return FALSE;
378
0
  if (context->common.format.nBlockAlign <= 4ULL)
379
0
    return FALSE;
380
0
  if (context->common.format.nChannels < 1)
381
0
    return FALSE;
382
0
  if (context->common.format.wBitsPerSample == 0)
383
0
    return FALSE;
384
0
  return TRUE;
385
0
}
386
387
static BOOL freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
388
                                         const BYTE* WINPR_RESTRICT src, size_t size,
389
                                         wStream* WINPR_RESTRICT out)
390
0
{
391
0
  if (!valid_ima_adpcm_format(context))
392
0
    return FALSE;
393
394
0
  size_t out_size = size * 4ull;
395
0
  const UINT32 block_size = context->common.format.nBlockAlign;
396
0
  const UINT32 channels = context->common.format.nChannels;
397
398
0
  if (!Stream_EnsureCapacity(out, out_size))
399
0
    return FALSE;
400
401
0
  while (size > 0)
402
0
  {
403
0
    if (size % block_size == 0)
404
0
    {
405
0
      if (size < 4)
406
0
        return FALSE;
407
408
0
      context->adpcm.ima.last_sample[0] =
409
0
          (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));
410
0
      context->adpcm.ima.last_step[0] = (INT16)(*(src + 2));
411
412
0
      dsp_ima_clamp_step(&context->adpcm, 0u);
413
414
0
      src += 4;
415
0
      size -= 4;
416
0
      out_size -= 16;
417
418
0
      if (channels > 1)
419
0
      {
420
0
        if (size < 4)
421
0
          return FALSE;
422
0
        context->adpcm.ima.last_sample[1] =
423
0
            (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));
424
0
        context->adpcm.ima.last_step[1] = (INT16)(*(src + 2));
425
426
0
        dsp_ima_clamp_step(&context->adpcm, 1u);
427
0
        src += 4;
428
0
        size -= 4;
429
0
        out_size -= 16;
430
0
      }
431
0
    }
432
433
0
    if (channels > 1)
434
0
    {
435
0
      if (size < 8)
436
0
        return FALSE;
437
0
      for (size_t i = 0; i < 8; i++)
438
0
      {
439
0
        BYTE* dst = Stream_Pointer(out);
440
441
0
        const unsigned channel = (i < 4 ? 0 : 1);
442
0
        {
443
0
          const BYTE sample = ((*src) & 0x0f);
444
0
          const UINT16 decoded =
445
0
              dsp_decode_ima_adpcm_sample(&context->adpcm, channel, sample);
446
0
          dst[((i & 3) << 3) + (channel << 1u)] = (decoded & 0xFF);
447
0
          dst[((i & 3) << 3) + (channel << 1u) + 1] = (decoded >> 8);
448
0
        }
449
0
        {
450
0
          const BYTE sample = ((*src) >> 4);
451
0
          const UINT16 decoded =
452
0
              dsp_decode_ima_adpcm_sample(&context->adpcm, channel, sample);
453
0
          dst[((i & 3) << 3) + (channel << 1u) + 4] = (decoded & 0xFF);
454
0
          dst[((i & 3) << 3) + (channel << 1u) + 5] = (decoded >> 8);
455
0
        }
456
0
        src++;
457
0
      }
458
459
0
      if (!Stream_SafeSeek(out, 32))
460
0
        return FALSE;
461
0
      size -= 8;
462
0
    }
463
0
    else
464
0
    {
465
0
      if (size < 1)
466
0
        return FALSE;
467
0
      BYTE* dst = Stream_Pointer(out);
468
0
      if (!Stream_SafeSeek(out, 4))
469
0
        return FALSE;
470
471
0
      {
472
0
        const BYTE sample = ((*src) & 0x0f);
473
0
        const UINT16 decoded = dsp_decode_ima_adpcm_sample(&context->adpcm, 0, sample);
474
0
        *dst++ = (decoded & 0xFF);
475
0
        *dst++ = (decoded >> 8);
476
0
      }
477
0
      {
478
0
        const BYTE sample = ((*src) >> 4);
479
0
        const UINT16 decoded = dsp_decode_ima_adpcm_sample(&context->adpcm, 0, sample);
480
0
        *dst++ = (decoded & 0xFF);
481
0
        *dst++ = (decoded >> 8);
482
0
      }
483
0
      src++;
484
0
      size--;
485
0
    }
486
0
  }
487
488
0
  return TRUE;
489
0
}
490
491
#if defined(WITH_GSM)
492
static BOOL freerdp_dsp_decode_gsm610(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
493
                                      const BYTE* WINPR_RESTRICT src, size_t size,
494
                                      wStream* WINPR_RESTRICT out)
495
{
496
  size_t offset = 0;
497
498
  while (offset < size)
499
  {
500
    /* gsm_decode(GSM_OPT_WAV49) requires alternating fixed 33/32 bytes as input.
501
     * abort if the data supplied was inconsistent.
502
     */
503
    const BOOL large = (offset % 65) == 0;
504
    const size_t toadd = large ? 33 : 32;
505
    if (size - offset < toadd)
506
      return FALSE;
507
508
    gsm_signal gsmBlockBuffer[160] = WINPR_C_ARRAY_INIT;
509
    const int rc =
510
        gsm_decode(context->gsm,
511
                   WINPR_CAST_CONST_PTR_AWAY(/* API does not modify */ &src[offset], gsm_byte*),
512
                   gsmBlockBuffer);
513
514
    if (rc < 0)
515
      return FALSE;
516
517
    offset += toadd;
518
519
    if (!Stream_EnsureRemainingCapacity(out, sizeof(gsmBlockBuffer)))
520
      return FALSE;
521
522
    Stream_Write(out, (void*)gsmBlockBuffer, sizeof(gsmBlockBuffer));
523
  }
524
525
  return TRUE;
526
}
527
528
static BOOL freerdp_dsp_encode_gsm610(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
529
                                      const BYTE* WINPR_RESTRICT src, size_t size,
530
                                      wStream* WINPR_RESTRICT out)
531
{
532
  size_t offset = 0;
533
534
  while (offset < size)
535
  {
536
    const gsm_signal* signal = WINPR_PACKED_ALIGN_CAST(const gsm_signal*, &src[offset]);
537
538
    if (!Stream_EnsureRemainingCapacity(out, sizeof(gsm_frame)))
539
      return FALSE;
540
541
    gsm_encode(context->gsm,
542
               WINPR_CAST_CONST_PTR_AWAY(/* API does not modify */ signal, gsm_signal*),
543
               Stream_Pointer(out));
544
545
    if ((offset % 65) == 0)
546
      Stream_Seek(out, 33);
547
    else
548
      Stream_Seek(out, 32);
549
550
    offset += 160;
551
  }
552
553
  return TRUE;
554
}
555
#endif
556
557
#if defined(WITH_LAME)
558
static BOOL valid_mp3_format(const FREERDP_DSP_CONTEXT* WINPR_RESTRICT context)
559
{
560
  WINPR_ASSERT(context);
561
  if (context->common.format.wFormatTag != WAVE_FORMAT_MPEGLAYER3)
562
    return FALSE;
563
  if (context->common.format.nChannels < 1)
564
    return FALSE;
565
  if (context->common.format.wBitsPerSample == 0)
566
    return FALSE;
567
  if (context->common.format.nSamplesPerSec == 0)
568
    return FALSE;
569
  return TRUE;
570
}
571
572
static BOOL freerdp_dsp_decode_mp3(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
573
                                   const BYTE* WINPR_RESTRICT src, size_t size,
574
                                   wStream* WINPR_RESTRICT out)
575
{
576
  if (!context || !src || !out)
577
    return FALSE;
578
  if (!valid_mp3_format(context))
579
    return FALSE;
580
  const size_t buffer_size =
581
      2ull * context->common.format.nChannels * context->common.format.nSamplesPerSec;
582
583
  if (!Stream_EnsureCapacity(context->common.buffer, 2ull * buffer_size))
584
    return FALSE;
585
586
  short* pcm_l = Stream_BufferAs(context->common.buffer, short);
587
  short* pcm_r = Stream_BufferAs(context->common.buffer, short) + (buffer_size / sizeof(short));
588
  const int rc = hip_decode(
589
      context->hip,
590
      WINPR_CAST_CONST_PTR_AWAY(/* API is not modifying content */ src, unsigned char*), size,
591
      pcm_l, pcm_r);
592
593
  if (rc <= 0)
594
    return FALSE;
595
596
  if (!Stream_EnsureRemainingCapacity(out, (size_t)rc * context->common.format.nChannels * 2ull))
597
    return FALSE;
598
599
  for (int x = 0; x < rc; x++)
600
  {
601
    Stream_Write_UINT16(out, (UINT16)pcm_l[x]);
602
    Stream_Write_UINT16(out, (UINT16)pcm_r[x]);
603
  }
604
605
  return TRUE;
606
}
607
608
static BOOL freerdp_dsp_encode_mp3(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
609
                                   const BYTE* WINPR_RESTRICT src, size_t size,
610
                                   wStream* WINPR_RESTRICT out)
611
{
612
  if (!context || !src || !out)
613
    return FALSE;
614
615
  if (!valid_mp3_format(context))
616
    return FALSE;
617
618
  size_t samples_per_channel =
619
      size / context->common.format.nChannels / context->common.format.wBitsPerSample / 8;
620
621
  /* Ensure worst case buffer size for mp3 stream taken from LAME header */
622
  if (!Stream_EnsureRemainingCapacity(out, 5ull / 4ull * samples_per_channel + 7200ull))
623
    return FALSE;
624
625
  samples_per_channel = size / 2 /* size of a sample */ / context->common.format.nChannels;
626
  const size_t outLen = Stream_GetRemainingCapacity(out);
627
  if ((outLen > INT_MAX) || (samples_per_channel > INT_MAX))
628
    return FALSE;
629
630
  const int rc = lame_encode_buffer_interleaved(
631
      context->lame,
632
      WINPR_CAST_CONST_PTR_AWAY(WINPR_PACKED_ALIGN_CAST(const short*, src), short*),
633
      WINPR_ASSERTING_INT_CAST(int, samples_per_channel), Stream_Pointer(out),
634
      WINPR_ASSERTING_INT_CAST(int, outLen));
635
636
  if (rc < 0)
637
    return FALSE;
638
639
  Stream_Seek(out, (size_t)rc);
640
  return TRUE;
641
}
642
#endif
643
644
#if defined(WITH_FAAC)
645
static BOOL freerdp_dsp_encode_faac(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
646
                                    const BYTE* WINPR_RESTRICT src, size_t size,
647
                                    wStream* WINPR_RESTRICT out)
648
{
649
  const int16_t* inSamples = WINPR_PACKED_ALIGN_CAST(const int16_t*, src);
650
651
  if (!context || !src || !out)
652
    return FALSE;
653
654
  const unsigned int bpp = context->common.format.wBitsPerSample / 8;
655
  const size_t nrSamples = size / bpp;
656
657
  if (!Stream_EnsureRemainingCapacity(context->common.buffer, nrSamples * sizeof(int16_t)))
658
    return FALSE;
659
660
  for (size_t x = 0; x < nrSamples; x++)
661
  {
662
    Stream_Write_INT16(context->common.buffer, inSamples[x]);
663
    if (Stream_GetPosition(context->common.buffer) / bpp >= context->faacInputSamples)
664
    {
665
      if (!Stream_EnsureRemainingCapacity(out, context->faacMaxOutputBytes))
666
        return FALSE;
667
668
      const size_t outLen = Stream_GetRemainingCapacity(out);
669
      if ((outLen > UINT_MAX) || (context->faacInputSamples > UINT_MAX))
670
        return FALSE;
671
      const int rc =
672
          faacEncEncode(context->faac, Stream_BufferAs(context->common.buffer, int32_t),
673
                        WINPR_ASSERTING_INT_CAST(unsigned int, context->faacInputSamples),
674
                        Stream_Pointer(out), WINPR_ASSERTING_INT_CAST(unsigned int, outLen));
675
      if (rc < 0)
676
        return FALSE;
677
      if (rc > 0)
678
        Stream_Seek(out, (size_t)rc);
679
      Stream_ResetPosition(context->common.buffer);
680
    }
681
  }
682
683
  return TRUE;
684
}
685
#endif
686
687
#if defined(WITH_OPUS)
688
static BOOL freerdp_dsp_decode_opus(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
689
                                    const BYTE* WINPR_RESTRICT src, size_t size,
690
                                    wStream* WINPR_RESTRICT out)
691
{
692
  if (!context || !context->opus_decoder || !src || !out)
693
    return FALSE;
694
695
  /* Max packet duration is 120ms (5760 at 48KHz) */
696
  const size_t max_size = OPUS_MAX_FRAMES * context->common.format.nChannels * sizeof(int16_t);
697
  if (!Stream_EnsureRemainingCapacity(out, max_size))
698
    return FALSE;
699
700
  const opus_int32 frames =
701
      opus_decode(context->opus_decoder, src, WINPR_ASSERTING_INT_CAST(opus_int32, size),
702
                  Stream_Pointer(out), OPUS_MAX_FRAMES, 0);
703
  if (frames < 0)
704
    return FALSE;
705
706
  Stream_Seek(out, (size_t)frames * context->common.format.nChannels * sizeof(int16_t));
707
708
  return TRUE;
709
}
710
711
static BOOL freerdp_dsp_encode_opus(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
712
                                    const BYTE* WINPR_RESTRICT src, size_t size,
713
                                    wStream* WINPR_RESTRICT out)
714
{
715
  if (!context || !context->opus_encoder || !src || !out)
716
    return FALSE;
717
718
  /* Max packet duration is 120ms (5760 at 48KHz) */
719
  const size_t max_size = OPUS_MAX_FRAMES * context->common.format.nChannels * sizeof(int16_t);
720
  if (!Stream_EnsureRemainingCapacity(out, max_size))
721
    return FALSE;
722
723
  const size_t src_frames = size / sizeof(opus_int16) / context->common.format.nChannels;
724
  const opus_int16* src_data = WINPR_PACKED_ALIGN_CAST(const opus_int16*, src);
725
  const opus_int32 bytes = opus_encode(
726
      context->opus_encoder, src_data, WINPR_ASSERTING_INT_CAST(opus_int32, src_frames),
727
      Stream_Pointer(out), WINPR_ASSERTING_INT_CAST(opus_int32, max_size));
728
  if (bytes < 0)
729
    return FALSE;
730
  return Stream_SafeSeek(out, (size_t)bytes);
731
}
732
#endif
733
734
#if defined(WITH_FAAD2)
735
static BOOL freerdp_dsp_decode_faad(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
736
                                    const BYTE* WINPR_RESTRICT src, size_t size,
737
                                    wStream* WINPR_RESTRICT out)
738
{
739
  NeAACDecFrameInfo info;
740
  size_t offset = 0;
741
742
  if (!context || !src || !out)
743
    return FALSE;
744
745
  if (!context->faadSetup)
746
  {
747
    union
748
    {
749
      const void* cpv;
750
      void* pv;
751
    } cnv;
752
    unsigned long samplerate = 0;
753
    unsigned char channels = 0;
754
755
    cnv.cpv = src;
756
    const long err = NeAACDecInit(context->faad, /* API is not modifying content */ cnv.pv,
757
                                  size, &samplerate, &channels);
758
759
    if (err != 0)
760
      return FALSE;
761
762
    if (channels != context->common.format.nChannels)
763
      return FALSE;
764
765
    if (samplerate != context->common.format.nSamplesPerSec)
766
      return FALSE;
767
768
    context->faadSetup = TRUE;
769
  }
770
771
  while (offset < size)
772
  {
773
    union
774
    {
775
      const void* cpv;
776
      void* pv;
777
    } cnv;
778
779
    const size_t outSize = context->common.format.nSamplesPerSec *
780
                           context->common.format.nChannels *
781
                           context->common.format.wBitsPerSample / 8;
782
783
    if (!Stream_EnsureRemainingCapacity(out, outSize))
784
      return FALSE;
785
786
    void* sample_buffer = Stream_Pointer(out);
787
788
    cnv.cpv = &src[offset];
789
    NeAACDecDecode2(context->faad, &info, cnv.pv, size - offset, &sample_buffer,
790
                    Stream_GetRemainingCapacity(out));
791
792
    if (info.error != 0)
793
      return FALSE;
794
795
    offset += info.bytesconsumed;
796
797
    if (info.samples == 0)
798
      continue;
799
800
    Stream_Seek(out, info.samples * context->common.format.wBitsPerSample / 8);
801
  }
802
803
  return TRUE;
804
}
805
806
#endif
807
808
/**
809
 * 0     1     2     3
810
 * 2 0   6 4   10 8  14 12   <left>
811
 *
812
 * 4     5     6     7
813
 * 3 1   7 5   11 9  15 13   <right>
814
 */
815
static const struct
816
{
817
  BYTE byte_num;
818
  BYTE byte_shift;
819
} ima_stereo_encode_map[] = { { 0, 0 }, { 4, 0 }, { 0, 4 }, { 4, 4 }, { 1, 0 }, { 5, 0 },
820
                            { 1, 4 }, { 5, 4 }, { 2, 0 }, { 6, 0 }, { 2, 4 }, { 6, 4 },
821
                            { 3, 0 }, { 7, 0 }, { 3, 4 }, { 7, 4 } };
822
823
static BYTE dsp_encode_ima_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, size_t channel, INT16 sample)
824
0
{
825
0
  WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_step));
826
0
  WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_sample));
827
828
0
  const INT16 offset = adpcm->ima.last_step[channel];
829
0
  WINPR_ASSERT(offset >= 0);
830
0
  WINPR_ASSERT(WINPR_CXX_COMPAT_CAST(size_t, offset) < ARRAYSIZE(ima_step_size_table));
831
832
0
  INT32 ss = ima_step_size_table[offset];
833
0
  INT32 e = sample - adpcm->ima.last_sample[channel];
834
0
  INT32 d = e;
835
0
  INT32 diff = ss >> 3;
836
0
  BYTE enc = 0;
837
838
0
  if (e < 0)
839
0
  {
840
0
    enc = 8;
841
0
    e = -e;
842
0
  }
843
844
0
  if (e >= ss)
845
0
  {
846
0
    enc |= 4;
847
0
    e -= ss;
848
0
  }
849
850
0
  ss >>= 1;
851
852
0
  if (e >= ss)
853
0
  {
854
0
    enc |= 2;
855
0
    e -= ss;
856
0
  }
857
858
0
  ss >>= 1;
859
860
0
  if (e >= ss)
861
0
  {
862
0
    enc |= 1;
863
0
    e -= ss;
864
0
  }
865
866
0
  if (d < 0)
867
0
    diff = d + e - diff;
868
0
  else
869
0
    diff = d - e + diff;
870
871
0
  diff += adpcm->ima.last_sample[channel];
872
873
0
  if (diff < -32768)
874
0
    diff = -32768;
875
0
  else if (diff > 32767)
876
0
    diff = 32767;
877
878
0
  adpcm->ima.last_sample[channel] = (INT16)diff;
879
880
0
  WINPR_ASSERT(enc < ARRAYSIZE(ima_step_index_table));
881
0
  const int32_t last = adpcm->ima.last_step[channel] + ima_step_index_table[enc];
882
0
  adpcm->ima.last_step[channel] = WINPR_ASSERTING_INT_CAST(int16_t, last);
883
884
0
  dsp_ima_clamp_step(adpcm, channel);
885
886
0
  return enc;
887
0
}
888
889
static BOOL freerdp_dsp_encode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
890
                                         const BYTE* WINPR_RESTRICT src, size_t size,
891
                                         wStream* WINPR_RESTRICT out)
892
0
{
893
0
  if (!valid_ima_adpcm_format(context))
894
0
    return FALSE;
895
0
  if (!Stream_EnsureRemainingCapacity(out, size))
896
0
    return FALSE;
897
0
  if (!Stream_EnsureRemainingCapacity(context->common.buffer, size + 64ull))
898
0
    return FALSE;
899
900
0
  const size_t align = (context->common.format.nChannels > 1) ? 32 : 4;
901
902
0
  while (size >= align)
903
0
  {
904
0
    if (Stream_GetPosition(context->common.buffer) % context->common.format.nBlockAlign == 0)
905
0
    {
906
0
      Stream_Write_UINT8(context->common.buffer, context->adpcm.ima.last_sample[0] & 0xFF);
907
0
      Stream_Write_UINT8(context->common.buffer,
908
0
                         (context->adpcm.ima.last_sample[0] >> 8) & 0xFF);
909
0
      Stream_Write_UINT8(context->common.buffer, (BYTE)context->adpcm.ima.last_step[0]);
910
0
      Stream_Write_UINT8(context->common.buffer, 0);
911
912
0
      if (context->common.format.nChannels > 1)
913
0
      {
914
0
        Stream_Write_UINT8(context->common.buffer,
915
0
                           context->adpcm.ima.last_sample[1] & 0xFF);
916
0
        Stream_Write_UINT8(context->common.buffer,
917
0
                           (context->adpcm.ima.last_sample[1] >> 8) & 0xFF);
918
0
        Stream_Write_UINT8(context->common.buffer, (BYTE)context->adpcm.ima.last_step[1]);
919
0
        Stream_Write_UINT8(context->common.buffer, 0);
920
0
      }
921
0
    }
922
923
0
    if (context->common.format.nChannels > 1)
924
0
    {
925
0
      BYTE* dst = Stream_Pointer(context->common.buffer);
926
0
      ZeroMemory(dst, 8);
927
928
0
      for (size_t i = 0; i < 16; i++)
929
0
      {
930
0
        const INT16 sample = (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));
931
0
        src += 2;
932
0
        const BYTE encoded = dsp_encode_ima_adpcm_sample(&context->adpcm, i % 2, sample);
933
0
        dst[ima_stereo_encode_map[i].byte_num] |= encoded
934
0
                                                  << ima_stereo_encode_map[i].byte_shift;
935
0
      }
936
937
0
      if (!Stream_SafeSeek(context->common.buffer, 8))
938
0
        return FALSE;
939
0
      size -= 32;
940
0
    }
941
0
    else
942
0
    {
943
0
      INT16 sample = (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));
944
0
      src += 2;
945
0
      BYTE encoded = dsp_encode_ima_adpcm_sample(&context->adpcm, 0, sample);
946
0
      sample = (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));
947
0
      src += 2;
948
0
      encoded |= dsp_encode_ima_adpcm_sample(&context->adpcm, 0, sample) << 4;
949
0
      Stream_Write_UINT8(context->common.buffer, encoded);
950
0
      size -= 4;
951
0
    }
952
953
0
    if (Stream_GetPosition(context->common.buffer) >= context->adpcm.ima.packet_size)
954
0
    {
955
0
      BYTE* bsrc = Stream_Buffer(context->common.buffer);
956
0
      Stream_Write(out, bsrc, context->adpcm.ima.packet_size);
957
0
      Stream_ResetPosition(context->common.buffer);
958
0
    }
959
0
  }
960
961
0
  return TRUE;
962
0
}
963
964
/**
965
 * Microsoft ADPCM Specification:
966
 *
967
 * http://wiki.multimedia.cx/index.php?title=Microsoft_ADPCM
968
 */
969
970
static const INT32 ms_adpcm_adaptation_table[] = { 230, 230, 230, 230, 307, 409, 512, 614,
971
                                                 768, 614, 512, 409, 307, 230, 230, 230 };
972
973
static const INT32 ms_adpcm_coeffs1[7] = { 256, 512, 0, 192, 240, 460, 392 };
974
975
static const INT32 ms_adpcm_coeffs2[7] = { 0, -256, 0, 64, 0, -208, -232 };
976
977
static inline INT16 freerdp_dsp_decode_ms_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, BYTE sample,
978
                                                       size_t channel)
979
0
{
980
0
  WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample1));
981
0
  WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample2));
982
0
  WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.delta));
983
0
  WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.predictor));
984
985
0
  const INT8 nibble = (INT8)((sample & 0x08) ? (sample - 16) : sample);
986
0
  const BYTE predictor = adpcm->ms.predictor[channel];
987
0
  INT32 coeff1 = 0;
988
0
  if (predictor < ARRAYSIZE(ms_adpcm_coeffs1))
989
0
    coeff1 = ms_adpcm_coeffs1[predictor];
990
991
0
  INT32 coeff2 = 0;
992
0
  if (predictor < ARRAYSIZE(ms_adpcm_coeffs2))
993
0
    coeff2 = ms_adpcm_coeffs2[predictor];
994
0
  INT32 presample =
995
0
      ((adpcm->ms.sample1[channel] * coeff1) + (adpcm->ms.sample2[channel] * coeff2)) / 256;
996
0
  presample += nibble * adpcm->ms.delta[channel];
997
998
0
  if (presample > 32767)
999
0
    presample = 32767;
1000
0
  else if (presample < -32768)
1001
0
    presample = -32768;
1002
1003
0
  adpcm->ms.sample2[channel] = adpcm->ms.sample1[channel];
1004
0
  adpcm->ms.sample1[channel] = presample;
1005
1006
0
  INT32 tableval = 0;
1007
0
  if (sample < ARRAYSIZE(ms_adpcm_adaptation_table))
1008
0
    tableval = ms_adpcm_adaptation_table[sample];
1009
1010
0
  adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * tableval / 256;
1011
1012
0
  if (adpcm->ms.delta[channel] < 16)
1013
0
    adpcm->ms.delta[channel] = 16;
1014
1015
0
  return (INT16)presample;
1016
0
}
1017
1018
static BOOL valid_ms_adpcm_format(const FREERDP_DSP_CONTEXT* WINPR_RESTRICT context)
1019
0
{
1020
0
  WINPR_ASSERT(context);
1021
0
  if (context->common.format.wFormatTag != WAVE_FORMAT_ADPCM)
1022
0
    return FALSE;
1023
0
  if (context->common.format.nBlockAlign <= 4ULL)
1024
0
    return FALSE;
1025
0
  if (context->common.format.nChannels < 1)
1026
0
    return FALSE;
1027
0
  if (context->common.format.wBitsPerSample == 0)
1028
0
    return FALSE;
1029
0
  return TRUE;
1030
0
}
1031
1032
static BOOL freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
1033
                                        const BYTE* WINPR_RESTRICT src, size_t size,
1034
                                        wStream* WINPR_RESTRICT out)
1035
0
{
1036
0
  if (!valid_ms_adpcm_format(context))
1037
0
    return FALSE;
1038
0
  const size_t out_size = size * 4;
1039
0
  const UINT32 channels = context->common.format.nChannels;
1040
0
  const UINT32 block_size = context->common.format.nBlockAlign;
1041
1042
0
  if (!Stream_EnsureCapacity(out, out_size))
1043
0
    return FALSE;
1044
1045
0
  while (size > 0)
1046
0
  {
1047
0
    if (size % block_size == 0)
1048
0
    {
1049
0
      if (channels > 1)
1050
0
      {
1051
0
        if (size < 14)
1052
0
          return FALSE;
1053
1054
0
        context->adpcm.ms.predictor[0] = *src++;
1055
0
        context->adpcm.ms.predictor[1] = *src++;
1056
0
        context->adpcm.ms.delta[0] = read_int16(src);
1057
0
        src += 2;
1058
0
        context->adpcm.ms.delta[1] = read_int16(src);
1059
0
        src += 2;
1060
0
        context->adpcm.ms.sample1[0] = read_int16(src);
1061
0
        src += 2;
1062
0
        context->adpcm.ms.sample1[1] = read_int16(src);
1063
0
        src += 2;
1064
0
        context->adpcm.ms.sample2[0] = read_int16(src);
1065
0
        src += 2;
1066
0
        context->adpcm.ms.sample2[1] = read_int16(src);
1067
0
        src += 2;
1068
0
        size -= 14;
1069
0
        Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[0]);
1070
0
        Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[1]);
1071
0
        Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[0]);
1072
0
        Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[1]);
1073
0
      }
1074
0
      else
1075
0
      {
1076
0
        if (size < 7)
1077
0
          return FALSE;
1078
1079
0
        context->adpcm.ms.predictor[0] = *src++;
1080
0
        context->adpcm.ms.delta[0] = read_int16(src);
1081
0
        src += 2;
1082
0
        context->adpcm.ms.sample1[0] = read_int16(src);
1083
0
        src += 2;
1084
0
        context->adpcm.ms.sample2[0] = read_int16(src);
1085
0
        src += 2;
1086
0
        size -= 7;
1087
0
        Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[0]);
1088
0
        Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[0]);
1089
0
      }
1090
0
    }
1091
1092
0
    if (channels > 1)
1093
0
    {
1094
0
      {
1095
0
        if (size < 1)
1096
0
          return FALSE;
1097
0
        const BYTE sample = *src++;
1098
0
        size--;
1099
0
        Stream_Write_INT16(
1100
0
            out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0));
1101
0
        Stream_Write_INT16(
1102
0
            out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 1));
1103
0
      }
1104
0
      {
1105
0
        if (size < 1)
1106
0
          return FALSE;
1107
0
        const BYTE sample = *src++;
1108
0
        size--;
1109
0
        Stream_Write_INT16(
1110
0
            out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0));
1111
0
        Stream_Write_INT16(
1112
0
            out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 1));
1113
0
      }
1114
0
    }
1115
0
    else
1116
0
    {
1117
0
      if (size < 1)
1118
0
        return FALSE;
1119
0
      const BYTE sample = *src++;
1120
0
      size--;
1121
0
      Stream_Write_INT16(out,
1122
0
                         freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0));
1123
0
      Stream_Write_INT16(
1124
0
          out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 0));
1125
0
    }
1126
0
  }
1127
1128
0
  return TRUE;
1129
0
}
1130
1131
static BYTE freerdp_dsp_encode_ms_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, INT32 sample,
1132
                                               size_t channel)
1133
0
{
1134
0
  WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample1));
1135
0
  WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample2));
1136
0
  WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.delta));
1137
0
  WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.predictor));
1138
1139
0
  INT32 presample =
1140
0
      ((adpcm->ms.sample1[channel] * ms_adpcm_coeffs1[adpcm->ms.predictor[channel]]) +
1141
0
       (adpcm->ms.sample2[channel] * ms_adpcm_coeffs2[adpcm->ms.predictor[channel]])) /
1142
0
      256;
1143
0
  INT32 errordelta = (sample - presample) / adpcm->ms.delta[channel];
1144
1145
0
  if ((sample - presample) % adpcm->ms.delta[channel] > adpcm->ms.delta[channel] / 2)
1146
0
    errordelta++;
1147
1148
0
  if (errordelta > 7)
1149
0
    errordelta = 7;
1150
0
  else if (errordelta < -8)
1151
0
    errordelta = -8;
1152
1153
0
  presample += adpcm->ms.delta[channel] * errordelta;
1154
1155
0
  if (presample > 32767)
1156
0
    presample = 32767;
1157
0
  else if (presample < -32768)
1158
0
    presample = -32768;
1159
1160
0
  adpcm->ms.sample2[channel] = adpcm->ms.sample1[channel];
1161
0
  adpcm->ms.sample1[channel] = presample;
1162
0
  const size_t offset = (((BYTE)errordelta) & 0x0F);
1163
0
  WINPR_ASSERT(offset < ARRAYSIZE(ms_adpcm_adaptation_table));
1164
0
  adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * ms_adpcm_adaptation_table[offset] / 256;
1165
1166
0
  if (adpcm->ms.delta[channel] < 16)
1167
0
    adpcm->ms.delta[channel] = 16;
1168
1169
0
  return ((BYTE)errordelta) & 0x0F;
1170
0
}
1171
1172
static BOOL freerdp_dsp_encode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
1173
                                        const BYTE* WINPR_RESTRICT src, size_t size,
1174
                                        wStream* WINPR_RESTRICT out)
1175
0
{
1176
0
  if (!valid_ms_adpcm_format(context))
1177
0
    return FALSE;
1178
1179
0
  const size_t step = 8 + ((context->common.format.nChannels > 1) ? 4 : 0);
1180
1181
0
  if (!Stream_EnsureRemainingCapacity(out, size))
1182
0
    return FALSE;
1183
1184
0
  const size_t start = Stream_GetPosition(out);
1185
1186
0
  if (context->adpcm.ms.delta[0] < 16)
1187
0
    context->adpcm.ms.delta[0] = 16;
1188
1189
0
  if (context->adpcm.ms.delta[1] < 16)
1190
0
    context->adpcm.ms.delta[1] = 16;
1191
1192
0
  while (size >= step)
1193
0
  {
1194
0
    if ((Stream_GetPosition(out) - start) % context->common.format.nBlockAlign == 0)
1195
0
    {
1196
0
      if (context->common.format.nChannels > 1)
1197
0
      {
1198
0
        Stream_Write_UINT8(out, context->adpcm.ms.predictor[0]);
1199
0
        Stream_Write_UINT8(out, context->adpcm.ms.predictor[1]);
1200
0
        Stream_Write_UINT8(out, (context->adpcm.ms.delta[0] & 0xFF));
1201
0
        Stream_Write_UINT8(out, ((context->adpcm.ms.delta[0] >> 8) & 0xFF));
1202
0
        Stream_Write_UINT8(out, (context->adpcm.ms.delta[1] & 0xFF));
1203
0
        Stream_Write_UINT8(out, ((context->adpcm.ms.delta[1] >> 8) & 0xFF));
1204
1205
0
        context->adpcm.ms.sample1[0] = read_int16(src + 4);
1206
0
        context->adpcm.ms.sample1[1] = read_int16(src + 6);
1207
0
        context->adpcm.ms.sample2[0] = read_int16(src + 0);
1208
0
        context->adpcm.ms.sample2[1] = read_int16(src + 2);
1209
1210
0
        Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[0]);
1211
0
        Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[1]);
1212
0
        Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[0]);
1213
0
        Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[1]);
1214
1215
0
        src += 8;
1216
0
        size -= 8;
1217
0
      }
1218
0
      else
1219
0
      {
1220
0
        Stream_Write_UINT8(out, context->adpcm.ms.predictor[0]);
1221
0
        Stream_Write_UINT8(out, (BYTE)(context->adpcm.ms.delta[0] & 0xFF));
1222
0
        Stream_Write_UINT8(out, (BYTE)((context->adpcm.ms.delta[0] >> 8) & 0xFF));
1223
1224
0
        context->adpcm.ms.sample1[0] = read_int16(src + 2);
1225
0
        context->adpcm.ms.sample2[0] = read_int16(src + 0);
1226
1227
0
        Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[0]);
1228
0
        Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[0]);
1229
0
        src += 4;
1230
0
        size -= 4;
1231
0
      }
1232
0
    }
1233
1234
0
    {
1235
0
      const INT16 sample = read_int16(src);
1236
0
      src += 2;
1237
0
      Stream_Write_UINT8(
1238
0
          out, (freerdp_dsp_encode_ms_adpcm_sample(&context->adpcm, sample, 0) << 4) & 0xFF);
1239
0
    }
1240
0
    {
1241
0
      const INT16 sample = read_int16(src);
1242
0
      src += 2;
1243
1244
0
      BYTE val = 0;
1245
0
      Stream_Read_UINT8(out, val);
1246
0
      val += freerdp_dsp_encode_ms_adpcm_sample(&context->adpcm, sample,
1247
0
                                                context->common.format.nChannels > 1 ? 1 : 0);
1248
0
      Stream_Write_UINT8(out, val);
1249
0
    }
1250
0
    size -= 4;
1251
0
  }
1252
1253
0
  return TRUE;
1254
0
}
1255
1256
#endif
1257
1258
FREERDP_DSP_CONTEXT* freerdp_dsp_context_new(BOOL encoder)
1259
0
{
1260
#if defined(WITH_DSP_FFMPEG)
1261
  return freerdp_dsp_ffmpeg_context_new(encoder);
1262
#else
1263
0
  FREERDP_DSP_CONTEXT* context = calloc(1, sizeof(FREERDP_DSP_CONTEXT));
1264
1265
0
  if (!context)
1266
0
    return nullptr;
1267
1268
0
  if (!freerdp_dsp_common_context_init(&context->common, encoder))
1269
0
    goto fail;
1270
1271
#if defined(WITH_GSM)
1272
  context->gsm = gsm_create();
1273
1274
  if (!context->gsm)
1275
    goto fail;
1276
1277
  {
1278
    int val = 1;
1279
    int rc = gsm_option(context->gsm, GSM_OPT_WAV49, &val);
1280
1281
    if (rc < 0)
1282
      goto fail;
1283
  }
1284
#endif
1285
#if defined(WITH_LAME)
1286
1287
  if (encoder)
1288
  {
1289
    context->lame = lame_init();
1290
1291
    if (!context->lame)
1292
      goto fail;
1293
  }
1294
  else
1295
  {
1296
    context->hip = hip_decode_init();
1297
1298
    if (!context->hip)
1299
      goto fail;
1300
  }
1301
1302
#endif
1303
#if defined(WITH_FAAD2)
1304
1305
  if (!encoder)
1306
  {
1307
    context->faad = NeAACDecOpen();
1308
1309
    if (!context->faad)
1310
      goto fail;
1311
  }
1312
1313
#endif
1314
0
  return context;
1315
0
fail:
1316
0
  freerdp_dsp_context_free(context);
1317
0
  return nullptr;
1318
0
#endif
1319
0
}
1320
1321
void freerdp_dsp_context_free(FREERDP_DSP_CONTEXT* context)
1322
0
{
1323
0
  if (!context)
1324
0
    return;
1325
1326
#if defined(WITH_FDK_AAC)
1327
  FREERDP_DSP_COMMON_CONTEXT* ctx = (FREERDP_DSP_COMMON_CONTEXT*)context;
1328
  WINPR_ASSERT(ctx);
1329
  fdk_aac_dsp_uninit(ctx);
1330
#endif
1331
1332
#if defined(WITH_MEDIACODEC)
1333
  mediacodec_aac_dsp_uninit((FREERDP_DSP_COMMON_CONTEXT*)context);
1334
#endif
1335
1336
#if defined(WITH_DSP_FFMPEG)
1337
  freerdp_dsp_ffmpeg_context_free(context);
1338
#else
1339
1340
0
  freerdp_dsp_common_context_uninit(&context->common);
1341
1342
#if defined(WITH_GSM)
1343
    gsm_destroy(context->gsm);
1344
#endif
1345
#if defined(WITH_LAME)
1346
1347
    if (context->common.encoder)
1348
      lame_close(context->lame);
1349
    else
1350
      hip_decode_exit(context->hip);
1351
1352
#endif
1353
#if defined(WITH_OPUS)
1354
1355
    if (context->opus_decoder)
1356
      opus_decoder_destroy(context->opus_decoder);
1357
    if (context->opus_encoder)
1358
      opus_encoder_destroy(context->opus_encoder);
1359
1360
#endif
1361
#if defined(WITH_FAAD2)
1362
1363
    if (!context->common.encoder)
1364
      NeAACDecClose(context->faad);
1365
1366
#endif
1367
#if defined(WITH_FAAC)
1368
1369
    if (context->faac)
1370
      faacEncClose(context->faac);
1371
1372
#endif
1373
#if defined(WITH_SOXR)
1374
    soxr_delete(context->sox);
1375
#endif
1376
0
      free(context);
1377
1378
0
#endif
1379
0
}
1380
1381
BOOL freerdp_dsp_encode(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
1382
                        const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,
1383
                        const BYTE* WINPR_RESTRICT pdata, size_t length,
1384
                        wStream* WINPR_RESTRICT out)
1385
0
{
1386
#if defined(WITH_MEDIACODEC)
1387
  FREERDP_DSP_COMMON_CONTEXT* mcctx = (FREERDP_DSP_COMMON_CONTEXT*)context;
1388
  if (mcctx && (mcctx->format.wFormatTag == WAVE_FORMAT_AAC_MS))
1389
    return mediacodec_aac_dsp_encode(mcctx, srcFormat, pdata, length, out);
1390
#endif
1391
1392
#if defined(WITH_FDK_AAC)
1393
  FREERDP_DSP_COMMON_CONTEXT* ctx = (FREERDP_DSP_COMMON_CONTEXT*)context;
1394
  WINPR_ASSERT(ctx);
1395
  switch (ctx->format.wFormatTag)
1396
  {
1397
    case WAVE_FORMAT_AAC_MS:
1398
      return fdk_aac_dsp_encode(ctx, srcFormat, pdata, length, out);
1399
    default:
1400
      break;
1401
  }
1402
#endif
1403
1404
#if defined(WITH_DSP_FFMPEG)
1405
  return freerdp_dsp_ffmpeg_encode(context, srcFormat, pdata, length, out);
1406
#else
1407
0
  if (!context || !context->common.encoder || !srcFormat || !pdata || !out)
1408
0
    return FALSE;
1409
1410
0
  AUDIO_FORMAT format = *srcFormat;
1411
0
  const BYTE* resampleData = nullptr;
1412
0
  size_t resampleLength = 0;
1413
1414
0
  if (!freerdp_dsp_channel_mix(context, pdata, length, srcFormat, &resampleData, &resampleLength))
1415
0
    return FALSE;
1416
1417
0
  format.nChannels = context->common.format.nChannels;
1418
1419
0
  const BYTE* data = nullptr;
1420
0
  if (!freerdp_dsp_resample(context, resampleData, resampleLength, &format, &data, &length))
1421
0
    return FALSE;
1422
1423
0
  switch (context->common.format.wFormatTag)
1424
0
  {
1425
0
    case WAVE_FORMAT_PCM:
1426
0
      if (!Stream_EnsureRemainingCapacity(out, length))
1427
0
        return FALSE;
1428
1429
0
      Stream_Write(out, data, length);
1430
0
      return TRUE;
1431
1432
0
    case WAVE_FORMAT_ADPCM:
1433
0
      return freerdp_dsp_encode_ms_adpcm(context, data, length, out);
1434
1435
0
    case WAVE_FORMAT_DVI_ADPCM:
1436
0
      return freerdp_dsp_encode_ima_adpcm(context, data, length, out);
1437
#if defined(WITH_GSM)
1438
1439
    case WAVE_FORMAT_GSM610:
1440
      return freerdp_dsp_encode_gsm610(context, data, length, out);
1441
#endif
1442
#if defined(WITH_LAME)
1443
1444
    case WAVE_FORMAT_MPEGLAYER3:
1445
      return freerdp_dsp_encode_mp3(context, data, length, out);
1446
#endif
1447
#if defined(WITH_FAAC)
1448
1449
    case WAVE_FORMAT_AAC_MS:
1450
      return freerdp_dsp_encode_faac(context, data, length, out);
1451
#endif
1452
#if defined(WITH_OPUS)
1453
1454
    case WAVE_FORMAT_OPUS:
1455
      return freerdp_dsp_encode_opus(context, data, length, out);
1456
#endif
1457
0
    default:
1458
0
      return FALSE;
1459
0
  }
1460
1461
0
  return FALSE;
1462
0
#endif
1463
0
}
1464
1465
BOOL freerdp_dsp_decode(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
1466
                        const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,
1467
                        const BYTE* WINPR_RESTRICT data, size_t length, wStream* WINPR_RESTRICT out)
1468
0
{
1469
#if defined(WITH_MEDIACODEC)
1470
  FREERDP_DSP_COMMON_CONTEXT* mcctx = (FREERDP_DSP_COMMON_CONTEXT*)context;
1471
  if (mcctx && (mcctx->format.wFormatTag == WAVE_FORMAT_AAC_MS))
1472
    return mediacodec_aac_dsp_decode(mcctx, srcFormat, data, length, out);
1473
#endif
1474
1475
#if defined(WITH_FDK_AAC)
1476
  FREERDP_DSP_COMMON_CONTEXT* ctx = (FREERDP_DSP_COMMON_CONTEXT*)context;
1477
  WINPR_ASSERT(ctx);
1478
  switch (ctx->format.wFormatTag)
1479
  {
1480
    case WAVE_FORMAT_AAC_MS:
1481
      return fdk_aac_dsp_decode(ctx, srcFormat, data, length, out);
1482
    default:
1483
      break;
1484
  }
1485
#endif
1486
1487
#if defined(WITH_DSP_FFMPEG)
1488
  return freerdp_dsp_ffmpeg_decode(context, srcFormat, data, length, out);
1489
#else
1490
1491
0
  if (!context || context->common.encoder || !srcFormat || !data || !out)
1492
0
    return FALSE;
1493
1494
0
  switch (context->common.format.wFormatTag)
1495
0
  {
1496
0
    case WAVE_FORMAT_PCM:
1497
0
      if (!Stream_EnsureRemainingCapacity(out, length))
1498
0
        return FALSE;
1499
1500
0
      Stream_Write(out, data, length);
1501
0
      return TRUE;
1502
1503
0
    case WAVE_FORMAT_ADPCM:
1504
0
      return freerdp_dsp_decode_ms_adpcm(context, data, length, out);
1505
1506
0
    case WAVE_FORMAT_DVI_ADPCM:
1507
0
      return freerdp_dsp_decode_ima_adpcm(context, data, length, out);
1508
#if defined(WITH_GSM)
1509
1510
    case WAVE_FORMAT_GSM610:
1511
      return freerdp_dsp_decode_gsm610(context, data, length, out);
1512
#endif
1513
#if defined(WITH_LAME)
1514
1515
    case WAVE_FORMAT_MPEGLAYER3:
1516
      return freerdp_dsp_decode_mp3(context, data, length, out);
1517
#endif
1518
#if defined(WITH_FAAD2)
1519
1520
    case WAVE_FORMAT_AAC_MS:
1521
      return freerdp_dsp_decode_faad(context, data, length, out);
1522
#endif
1523
1524
#if defined(WITH_OPUS)
1525
    case WAVE_FORMAT_OPUS:
1526
      return freerdp_dsp_decode_opus(context, data, length, out);
1527
#endif
1528
0
    default:
1529
0
      return FALSE;
1530
0
  }
1531
1532
0
  return FALSE;
1533
0
#endif
1534
0
}
1535
1536
BOOL freerdp_dsp_supports_format(const AUDIO_FORMAT* WINPR_RESTRICT format, BOOL encode)
1537
0
{
1538
#if defined(WITH_MEDIACODEC)
1539
  if (format && (format->wFormatTag == WAVE_FORMAT_AAC_MS))
1540
    return mediacodec_aac_dsp_supports_format(format, encode);
1541
#endif
1542
1543
#if defined(WITH_FDK_AAC)
1544
  switch (format->wFormatTag)
1545
  {
1546
    case WAVE_FORMAT_AAC_MS:
1547
      return TRUE;
1548
    default:
1549
      break;
1550
  }
1551
1552
#endif
1553
1554
#if defined(WITH_DSP_FFMPEG)
1555
  return freerdp_dsp_ffmpeg_supports_format(format, encode);
1556
#else
1557
1558
0
#if !defined(WITH_DSP_EXPERIMENTAL)
1559
0
  WINPR_UNUSED(encode);
1560
0
#endif
1561
0
  switch (format->wFormatTag)
1562
0
  {
1563
0
    case WAVE_FORMAT_PCM:
1564
0
      return TRUE;
1565
#if defined(WITH_DSP_EXPERIMENTAL)
1566
1567
    case WAVE_FORMAT_ADPCM:
1568
      return FALSE;
1569
    case WAVE_FORMAT_DVI_ADPCM:
1570
      return TRUE;
1571
#endif
1572
#if defined(WITH_GSM)
1573
1574
    case WAVE_FORMAT_GSM610:
1575
#if defined(WITH_DSP_EXPERIMENTAL)
1576
      return TRUE;
1577
#else
1578
      return !encode;
1579
#endif
1580
#endif
1581
#if defined(WITH_LAME)
1582
1583
    case WAVE_FORMAT_MPEGLAYER3:
1584
#if defined(WITH_DSP_EXPERIMENTAL)
1585
      return TRUE;
1586
#else
1587
      return !encode;
1588
#endif
1589
#endif
1590
1591
0
    case WAVE_FORMAT_AAC_MS:
1592
#if defined(WITH_FAAD2)
1593
      if (!encode)
1594
        return TRUE;
1595
1596
#endif
1597
#if defined(WITH_FAAC)
1598
1599
      if (encode)
1600
        return TRUE;
1601
1602
#endif
1603
#if defined(WITH_FDK_AAC)
1604
      return TRUE;
1605
#else
1606
0
      return FALSE;
1607
0
#endif
1608
1609
#if defined(WITH_OPUS)
1610
    case WAVE_FORMAT_OPUS:
1611
      return opus_is_valid_samplerate(format);
1612
#endif
1613
0
    default:
1614
0
      return FALSE;
1615
0
  }
1616
1617
0
  return FALSE;
1618
0
#endif
1619
0
}
1620
1621
BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
1622
                               const AUDIO_FORMAT* WINPR_RESTRICT targetFormat,
1623
                               WINPR_ATTR_UNUSED UINT32 FramesPerPacket)
1624
0
{
1625
#if defined(WITH_MEDIACODEC)
1626
  if (!context || !targetFormat)
1627
    return FALSE;
1628
1629
  if (targetFormat->wFormatTag == WAVE_FORMAT_AAC_MS)
1630
  {
1631
    FREERDP_DSP_COMMON_CONTEXT* ctx = (FREERDP_DSP_COMMON_CONTEXT*)context;
1632
    mediacodec_aac_dsp_uninit(ctx);
1633
    ctx->format = *targetFormat;
1634
    return mediacodec_aac_dsp_init(ctx, FramesPerPacket);
1635
  }
1636
#endif
1637
1638
#if defined(WITH_FDK_AAC)
1639
  WINPR_ASSERT(targetFormat);
1640
  if (targetFormat->wFormatTag == WAVE_FORMAT_AAC_MS)
1641
  {
1642
    FREERDP_DSP_COMMON_CONTEXT* ctx = (FREERDP_DSP_COMMON_CONTEXT*)context;
1643
    fdk_aac_dsp_uninit(ctx);
1644
    ctx->format = *targetFormat;
1645
    return fdk_aac_dsp_init(ctx, FramesPerPacket);
1646
  }
1647
#endif
1648
1649
#if defined(WITH_DSP_FFMPEG)
1650
  return freerdp_dsp_ffmpeg_context_reset(context, targetFormat);
1651
#else
1652
1653
0
  if (!context || !targetFormat)
1654
0
    return FALSE;
1655
1656
0
  context->common.format = *targetFormat;
1657
1658
0
  switch (context->common.format.wFormatTag)
1659
0
  {
1660
#if defined(WITH_LAME)
1661
    case WAVE_FORMAT_MPEGLAYER3:
1662
      if (!valid_mp3_format(context))
1663
        return FALSE;
1664
      break;
1665
#endif
1666
0
    case WAVE_FORMAT_ADPCM:
1667
0
      if (!valid_ms_adpcm_format(context))
1668
0
        return FALSE;
1669
0
      break;
1670
0
    case WAVE_FORMAT_DVI_ADPCM:
1671
0
    {
1672
0
      if (!valid_ima_adpcm_format(context))
1673
0
        return FALSE;
1674
0
      if (FramesPerPacket == 0)
1675
0
        return FALSE;
1676
1677
0
      const size_t min_frame_data = 1ull * context->common.format.wBitsPerSample *
1678
0
                                    context->common.format.nChannels * FramesPerPacket;
1679
0
      const size_t data_per_block = (1ULL * context->common.format.nBlockAlign -
1680
0
                                     4ULL * context->common.format.nChannels) *
1681
0
                                    8ULL;
1682
0
      size_t nb_block_per_packet = min_frame_data / data_per_block;
1683
1684
0
      if (min_frame_data % data_per_block)
1685
0
        nb_block_per_packet++;
1686
1687
0
      context->adpcm.ima.packet_size =
1688
0
          nb_block_per_packet * context->common.format.nBlockAlign;
1689
0
      if (!Stream_EnsureCapacity(context->common.buffer, context->adpcm.ima.packet_size))
1690
0
        return FALSE;
1691
0
      Stream_ResetPosition(context->common.buffer);
1692
0
    }
1693
0
    break;
1694
0
    default:
1695
0
      break;
1696
0
  }
1697
1698
#if defined(WITH_OPUS)
1699
1700
  if (context->opus_decoder)
1701
    opus_decoder_destroy(context->opus_decoder);
1702
  context->opus_decoder = nullptr;
1703
  if (context->opus_encoder)
1704
    opus_encoder_destroy(context->opus_encoder);
1705
  context->opus_encoder = nullptr;
1706
1707
  if (context->common.format.wFormatTag == WAVE_FORMAT_OPUS)
1708
  {
1709
    if (!opus_is_valid_samplerate(&context->common.format))
1710
      return FALSE;
1711
1712
    if (!context->common.encoder)
1713
    {
1714
      int opus_error = OPUS_OK;
1715
1716
      context->opus_decoder = opus_decoder_create(
1717
          WINPR_ASSERTING_INT_CAST(opus_int32, context->common.format.nSamplesPerSec),
1718
          context->common.format.nChannels, &opus_error);
1719
      if (opus_error != OPUS_OK)
1720
        return FALSE;
1721
    }
1722
    else
1723
    {
1724
      int opus_error = OPUS_OK;
1725
1726
      context->opus_encoder = opus_encoder_create(
1727
          WINPR_ASSERTING_INT_CAST(opus_int32, context->common.format.nSamplesPerSec),
1728
          context->common.format.nChannels, OPUS_APPLICATION_VOIP, &opus_error);
1729
      if (opus_error != OPUS_OK)
1730
        return FALSE;
1731
1732
      opus_error =
1733
          opus_encoder_ctl(context->opus_encoder,
1734
                           OPUS_SET_BITRATE(context->common.format.nAvgBytesPerSec * 8));
1735
      if (opus_error != OPUS_OK)
1736
        return FALSE;
1737
    }
1738
  }
1739
1740
#endif
1741
#if defined(WITH_FAAD2)
1742
  context->faadSetup = FALSE;
1743
#endif
1744
#if defined(WITH_FAAC)
1745
1746
  if (context->common.encoder)
1747
  {
1748
    faacEncConfigurationPtr cfg = nullptr;
1749
1750
    if (context->faac)
1751
      faacEncClose(context->faac);
1752
1753
    context->faac = faacEncOpen(targetFormat->nSamplesPerSec, targetFormat->nChannels,
1754
                                &context->faacInputSamples, &context->faacMaxOutputBytes);
1755
1756
    if (!context->faac)
1757
      return FALSE;
1758
1759
    cfg = faacEncGetCurrentConfiguration(context->faac);
1760
    cfg->inputFormat = FAAC_INPUT_16BIT;
1761
    cfg->outputFormat = 0;
1762
    cfg->mpegVersion = MPEG4;
1763
    cfg->useTns = 1;
1764
    cfg->bandWidth = targetFormat->nAvgBytesPerSec;
1765
    const int rc = faacEncSetConfiguration(context->faac, cfg);
1766
    if (rc <= 0)
1767
      return FALSE;
1768
  }
1769
1770
#endif
1771
#if defined(WITH_SOXR)
1772
  {
1773
    soxr_io_spec_t iospec = soxr_io_spec(SOXR_INT16, SOXR_INT16);
1774
    soxr_error_t error = nullptr;
1775
1776
    soxr_delete(context->sox);
1777
    context->sox =
1778
        soxr_create(context->common.format.nSamplesPerSec, targetFormat->nSamplesPerSec,
1779
                    targetFormat->nChannels, &error, &iospec, nullptr, nullptr);
1780
1781
    if (!context->sox || (error != nullptr))
1782
      return FALSE;
1783
  }
1784
#endif
1785
0
  return TRUE;
1786
0
#endif
1787
0
}
1788
1789
BOOL freerdp_dsp_common_context_init(FREERDP_DSP_COMMON_CONTEXT* context, BOOL encode)
1790
0
{
1791
0
  WINPR_ASSERT(context);
1792
0
  context->encoder = encode;
1793
0
  context->buffer = Stream_New(nullptr, 1024);
1794
0
  if (!context->buffer)
1795
0
    goto fail;
1796
1797
0
  context->channelmix = Stream_New(nullptr, 1024);
1798
0
  if (!context->channelmix)
1799
0
    goto fail;
1800
1801
0
  context->resample = Stream_New(nullptr, 1024);
1802
0
  if (!context->resample)
1803
0
    goto fail;
1804
1805
0
  return TRUE;
1806
1807
0
fail:
1808
0
  freerdp_dsp_common_context_uninit(context);
1809
0
  return FALSE;
1810
0
}
1811
1812
void freerdp_dsp_common_context_uninit(FREERDP_DSP_COMMON_CONTEXT* context)
1813
0
{
1814
0
  WINPR_ASSERT(context);
1815
1816
0
  Stream_Free(context->buffer, TRUE);
1817
0
  Stream_Free(context->channelmix, TRUE);
1818
0
  Stream_Free(context->resample, TRUE);
1819
1820
0
  context->buffer = nullptr;
1821
0
  context->channelmix = nullptr;
1822
0
  context->resample = nullptr;
1823
0
}