Coverage Report

Created: 2026-03-04 06:17

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