Coverage Report

Created: 2026-02-26 06:54

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