20#include <freerdp/config.h>
22#include <winpr/assert.h>
29#include <freerdp/types.h>
30#include <freerdp/log.h>
31#include <freerdp/codec/dsp.h>
35#if defined(WITH_FDK_AAC)
36#include "dsp_fdk_aac.h"
39#if defined(WITH_MEDIACODEC)
40#include "dsp_mediacodec.h"
43#if !defined(WITH_DSP_FFMPEG)
55#define OPUS_MAX_FRAMES 5760ull
58#if defined(WITH_FAAD2)
71#include "dsp_ffmpeg.h"
74#if !defined(WITH_DSP_FFMPEG)
76#define TAG FREERDP_TAG("dsp")
95struct S_FREERDP_DSP_CONTEXT
104#if defined(WITH_LAME)
108#if defined(WITH_OPUS)
109 OpusDecoder* opus_decoder;
110 OpusEncoder* opus_encoder;
112 size_t opus_packet_frames;
114#if defined(WITH_FAAD2)
119#if defined(WITH_FAAC)
121 unsigned long faacInputSamples;
122 unsigned long faacMaxOutputBytes;
125#if defined(WITH_SOXR)
130#if defined(WITH_OPUS)
131static BOOL opus_is_valid_samplerate(
const AUDIO_FORMAT* WINPR_RESTRICT format)
133 WINPR_ASSERT(format);
135 switch (format->nSamplesPerSec)
149static INT16 read_int16(
const BYTE* WINPR_RESTRICT src)
151 return (INT16)(src[0] | (src[1] << 8));
154static BOOL freerdp_dsp_channel_mix(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
155 const BYTE* WINPR_RESTRICT src,
size_t size,
157 const BYTE** WINPR_RESTRICT data,
size_t* WINPR_RESTRICT length)
159 if (!context || !data || !length)
162 if (srcFormat->wFormatTag != WAVE_FORMAT_PCM)
165 const UINT32 bpp = srcFormat->wBitsPerSample > 8 ? 2 : 1;
166 const size_t samples = size / bpp / srcFormat->nChannels;
168 if (context->common.format.nChannels == srcFormat->nChannels)
175 Stream_ResetPosition(context->common.channelmix);
178 if (context->common.format.nChannels > srcFormat->nChannels)
180 switch (srcFormat->nChannels)
183 if (!Stream_EnsureCapacity(context->common.channelmix, size * 2))
186 for (
size_t x = 0; x < samples; x++)
188 for (
size_t y = 0; y < bpp; y++)
189 Stream_Write_UINT8(context->common.channelmix, src[x * bpp + y]);
191 for (
size_t y = 0; y < bpp; y++)
192 Stream_Write_UINT8(context->common.channelmix, src[x * bpp + y]);
195 Stream_SealLength(context->common.channelmix);
196 *data = Stream_Buffer(context->common.channelmix);
197 *length = Stream_Length(context->common.channelmix);
207 switch (srcFormat->nChannels)
210 if (!Stream_EnsureCapacity(context->common.channelmix, size / 2))
215 for (
size_t x = 0; x < samples; x++)
217 for (
size_t y = 0; y < bpp; y++)
218 Stream_Write_UINT8(context->common.channelmix, src[2 * x * bpp + y]);
221 Stream_SealLength(context->common.channelmix);
222 *data = Stream_Buffer(context->common.channelmix);
223 *length = Stream_Length(context->common.channelmix);
239static BOOL freerdp_dsp_resample(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
240 const BYTE* WINPR_RESTRICT src,
size_t size,
242 const BYTE** WINPR_RESTRICT data,
size_t* WINPR_RESTRICT length)
246 if (srcFormat->wFormatTag != WAVE_FORMAT_PCM)
248 WLog_ERR(TAG,
"requires %s for sample input, got %s",
249 audio_format_get_tag_string(WAVE_FORMAT_PCM),
250 audio_format_get_tag_string(srcFormat->wFormatTag));
256 format.wFormatTag = WAVE_FORMAT_UNKNOWN;
257 format.wBitsPerSample = 0;
259 if (audio_format_compatible(&format, &context->common.format))
266#if defined(WITH_SOXR)
267 const size_t srcBytesPerFrame = (srcFormat->wBitsPerSample > 8) ? 2 : 1;
268 const size_t dstBytesPerFrame = (context->common.format.wBitsPerSample > 8) ? 2 : 1;
269 const size_t srcChannels = srcFormat->nChannels;
270 const size_t dstChannels = context->common.format.nChannels;
271 const size_t sbytes = srcChannels * srcBytesPerFrame;
272 const size_t sframes = size / sbytes;
273 const size_t rbytes = dstBytesPerFrame * dstChannels;
275 const size_t rframes =
276 (sframes * context->common.format.nSamplesPerSec + (srcFormat->nSamplesPerSec + 1) / 2) /
277 srcFormat->nSamplesPerSec;
278 const size_t rsize = rframes * rbytes;
280 if (!Stream_EnsureCapacity(context->common.resample, rsize))
286 soxr_process(context->sox, src, sframes, &idone, Stream_Buffer(context->common.resample),
287 Stream_Capacity(context->common.resample) / rbytes, &odone);
288 if (!Stream_SetLength(context->common.resample, odone * rbytes))
291 *data = Stream_Buffer(context->common.resample);
292 *length = Stream_Length(context->common.resample);
293 return (error ==
nullptr);
295 WLog_ERR(TAG,
"Missing resample support, recompile -DWITH_SOXR=ON or -DWITH_DSP_FFMPEG=ON");
307static const INT16 ima_step_index_table[] = {
308 -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8
311static 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
321static inline void dsp_ima_clamp_step(ADPCM* WINPR_RESTRICT adpcm,
size_t channel)
324 if (adpcm->ima.last_step[channel] < 0)
325 adpcm->ima.last_step[channel] = 0;
327 const size_t size = ARRAYSIZE(ima_step_size_table);
328 if ((
size_t)adpcm->ima.last_step[channel] >= size)
329 adpcm->ima.last_step[channel] = (INT16)(size - 1);
332static UINT16 dsp_decode_ima_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm,
unsigned int channel,
335 WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_step));
336 WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_sample));
338 const INT16 offset = adpcm->ima.last_step[channel];
339 WINPR_ASSERT(offset >= 0);
340 WINPR_ASSERT(WINPR_CXX_COMPAT_CAST(
size_t, offset) < ARRAYSIZE(ima_step_size_table));
342 const INT32 ss = ima_step_size_table[offset];
357 d += adpcm->ima.last_sample[channel];
364 adpcm->ima.last_sample[channel] = (INT16)d;
366 WINPR_ASSERT(sample < ARRAYSIZE(ima_step_index_table));
367 const int32_t last = adpcm->ima.last_step[channel] + ima_step_index_table[sample];
368 adpcm->ima.last_step[channel] = WINPR_ASSERTING_INT_CAST(int16_t, last);
370 dsp_ima_clamp_step(adpcm, channel);
375static BOOL valid_ima_adpcm_format(
const FREERDP_DSP_CONTEXT* WINPR_RESTRICT context)
377 WINPR_ASSERT(context);
378 if (context->common.format.wFormatTag != WAVE_FORMAT_DVI_ADPCM)
380 if (context->common.format.nBlockAlign <= 4ULL)
382 if (context->common.format.nChannels < 1)
384 if (context->common.format.wBitsPerSample == 0)
389static BOOL freerdp_dsp_decode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
390 const BYTE* WINPR_RESTRICT src,
size_t size,
393 if (!valid_ima_adpcm_format(context))
396 size_t out_size = size * 4ull;
397 const UINT32 block_size = context->common.format.nBlockAlign;
398 const UINT32 channels = context->common.format.nChannels;
400 if (!Stream_EnsureCapacity(out, out_size))
405 if (size % block_size == 0)
410 context->adpcm.ima.last_sample[0] =
411 (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));
412 context->adpcm.ima.last_step[0] = (INT16)(*(src + 2));
414 dsp_ima_clamp_step(&context->adpcm, 0u);
424 context->adpcm.ima.last_sample[1] =
425 (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));
426 context->adpcm.ima.last_step[1] = (INT16)(*(src + 2));
428 dsp_ima_clamp_step(&context->adpcm, 1u);
439 for (
size_t i = 0; i < 8; i++)
441 BYTE* dst = Stream_Pointer(out);
443 const unsigned channel = (i < 4 ? 0 : 1);
445 const BYTE sample = ((*src) & 0x0f);
446 const UINT16 decoded =
447 dsp_decode_ima_adpcm_sample(&context->adpcm, channel, sample);
448 dst[((i & 3) << 3) + (channel << 1u)] = (decoded & 0xFF);
449 dst[((i & 3) << 3) + (channel << 1u) + 1] = (decoded >> 8);
452 const BYTE sample = ((*src) >> 4);
453 const UINT16 decoded =
454 dsp_decode_ima_adpcm_sample(&context->adpcm, channel, sample);
455 dst[((i & 3) << 3) + (channel << 1u) + 4] = (decoded & 0xFF);
456 dst[((i & 3) << 3) + (channel << 1u) + 5] = (decoded >> 8);
461 if (!Stream_SafeSeek(out, 32))
469 BYTE* dst = Stream_Pointer(out);
470 if (!Stream_SafeSeek(out, 4))
474 const BYTE sample = ((*src) & 0x0f);
475 const UINT16 decoded = dsp_decode_ima_adpcm_sample(&context->adpcm, 0, sample);
476 *dst++ = (decoded & 0xFF);
477 *dst++ = (decoded >> 8);
480 const BYTE sample = ((*src) >> 4);
481 const UINT16 decoded = dsp_decode_ima_adpcm_sample(&context->adpcm, 0, sample);
482 *dst++ = (decoded & 0xFF);
483 *dst++ = (decoded >> 8);
494static BOOL freerdp_dsp_decode_gsm610(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
495 const BYTE* WINPR_RESTRICT src,
size_t size,
500 while (offset < size)
505 const BOOL large = (offset % 65) == 0;
506 const size_t toadd = large ? 33 : 32;
507 if (size - offset < toadd)
510 gsm_signal gsmBlockBuffer[160] = WINPR_C_ARRAY_INIT;
512 gsm_decode(context->gsm,
513 WINPR_CAST_CONST_PTR_AWAY( &src[offset], gsm_byte*),
521 if (!Stream_EnsureRemainingCapacity(out,
sizeof(gsmBlockBuffer)))
524 Stream_Write(out, (
void*)gsmBlockBuffer,
sizeof(gsmBlockBuffer));
530static BOOL freerdp_dsp_encode_gsm610(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
531 const BYTE* WINPR_RESTRICT src,
size_t size,
536 while (offset < size)
538 const gsm_signal* signal = WINPR_PACKED_ALIGN_CAST(
const gsm_signal*, &src[offset]);
540 if (!Stream_EnsureRemainingCapacity(out,
sizeof(gsm_frame)))
543 gsm_encode(context->gsm,
544 WINPR_CAST_CONST_PTR_AWAY( signal, gsm_signal*),
545 Stream_Pointer(out));
547 if ((offset % 65) == 0)
548 Stream_Seek(out, 33);
550 Stream_Seek(out, 32);
559#if defined(WITH_LAME)
560static BOOL valid_mp3_format(
const FREERDP_DSP_CONTEXT* WINPR_RESTRICT context)
562 WINPR_ASSERT(context);
563 if (context->common.format.wFormatTag != WAVE_FORMAT_MPEGLAYER3)
565 if (context->common.format.nChannels < 1)
567 if (context->common.format.wBitsPerSample == 0)
569 if (context->common.format.nSamplesPerSec == 0)
574static BOOL freerdp_dsp_decode_mp3(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
575 const BYTE* WINPR_RESTRICT src,
size_t size,
578 if (!context || !src || !out)
580 if (!valid_mp3_format(context))
582 const size_t buffer_size =
583 2ull * context->common.format.nChannels * context->common.format.nSamplesPerSec;
585 if (!Stream_EnsureCapacity(context->common.buffer, 2ull * buffer_size))
588 short* pcm_l = Stream_BufferAs(context->common.buffer,
short);
589 short* pcm_r = Stream_BufferAs(context->common.buffer,
short) + (buffer_size /
sizeof(short));
590 const int rc = hip_decode(
592 WINPR_CAST_CONST_PTR_AWAY( src,
unsigned char*), size,
598 if (!Stream_EnsureRemainingCapacity(out, (
size_t)rc * context->common.format.nChannels * 2ull))
601 for (
int x = 0; x < rc; x++)
603 Stream_Write_UINT16(out, (UINT16)pcm_l[x]);
604 Stream_Write_UINT16(out, (UINT16)pcm_r[x]);
610static BOOL freerdp_dsp_encode_mp3(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
611 const BYTE* WINPR_RESTRICT src,
size_t size,
614 if (!context || !src || !out)
617 if (!valid_mp3_format(context))
620 size_t samples_per_channel =
621 size / context->common.format.nChannels / context->common.format.wBitsPerSample / 8;
624 if (!Stream_EnsureRemainingCapacity(out, 5ull / 4ull * samples_per_channel + 7200ull))
627 samples_per_channel = size / 2 / context->common.format.nChannels;
628 const size_t outLen = Stream_GetRemainingCapacity(out);
629 if ((outLen > INT_MAX) || (samples_per_channel > INT_MAX))
632 const int rc = lame_encode_buffer_interleaved(
634 WINPR_CAST_CONST_PTR_AWAY(WINPR_PACKED_ALIGN_CAST(
const short*, src),
short*),
635 WINPR_ASSERTING_INT_CAST(
int, samples_per_channel), Stream_Pointer(out),
636 WINPR_ASSERTING_INT_CAST(
int, outLen));
641 Stream_Seek(out, (
size_t)rc);
646#if defined(WITH_FAAC)
647static BOOL freerdp_dsp_encode_faac(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
648 const BYTE* WINPR_RESTRICT src,
size_t size,
651 const int16_t* inSamples = WINPR_PACKED_ALIGN_CAST(
const int16_t*, src);
653 if (!context || !src || !out)
656 const unsigned int bpp = context->common.format.wBitsPerSample / 8;
657 const size_t nrSamples = size / bpp;
659 if (!Stream_EnsureRemainingCapacity(context->common.buffer, nrSamples *
sizeof(int16_t)))
662 for (
size_t x = 0; x < nrSamples; x++)
664 Stream_Write_INT16(context->common.buffer, inSamples[x]);
665 if (Stream_GetPosition(context->common.buffer) / bpp >= context->faacInputSamples)
667 if (!Stream_EnsureRemainingCapacity(out, context->faacMaxOutputBytes))
670 const size_t outLen = Stream_GetRemainingCapacity(out);
671 if ((outLen > UINT_MAX) || (context->faacInputSamples > UINT_MAX))
674 faacEncEncode(context->faac, Stream_BufferAs(context->common.buffer, int32_t),
675 WINPR_ASSERTING_INT_CAST(
unsigned int, context->faacInputSamples),
676 Stream_Pointer(out), WINPR_ASSERTING_INT_CAST(
unsigned int, outLen));
680 Stream_Seek(out, (
size_t)rc);
681 Stream_ResetPosition(context->common.buffer);
689#if defined(WITH_OPUS)
690static BOOL freerdp_dsp_decode_opus(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
691 const BYTE* WINPR_RESTRICT src,
size_t size,
694 if (!context || !context->opus_decoder || !src || !out)
698 const size_t max_size = OPUS_MAX_FRAMES * context->common.format.nChannels *
sizeof(int16_t);
699 if (!Stream_EnsureRemainingCapacity(out, max_size))
702 const opus_int32 frames =
703 opus_decode(context->opus_decoder, src, WINPR_ASSERTING_INT_CAST(opus_int32, size),
704 Stream_Pointer(out), OPUS_MAX_FRAMES, 0);
708 Stream_Seek(out, (
size_t)frames * context->common.format.nChannels *
sizeof(int16_t));
714static const UINT32 opus_packet_units[] = { 24, 16, 8, 4, 2, 1 };
716static BOOL opus_is_packet_frames(UINT32 rate,
size_t frames)
718 for (
size_t x = 0; x < ARRAYSIZE(opus_packet_units); x++)
720 if (frames == 1ull * rate * opus_packet_units[x] / 400)
732static BOOL freerdp_dsp_encode_opus(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
733 const BYTE* WINPR_RESTRICT src,
size_t size,
736 if (!context || !context->opus_encoder || !context->opus_input || !src || !out)
739 wStream* input = context->opus_input;
740 const UINT32 rate = context->common.format.nSamplesPerSec;
741 const size_t frame_bytes =
sizeof(opus_int16) * context->common.format.nChannels;
742 if (!Stream_EnsureRemainingCapacity(input, size))
744 Stream_Write(input, src, size);
746 const size_t available = Stream_GetPosition(input) / frame_bytes;
747 if (available < context->opus_packet_frames)
751 for (
size_t x = 0; x < ARRAYSIZE(opus_packet_units); x++)
753 frames = 1ull * rate * opus_packet_units[x] / 400;
754 if (frames <= available)
759 const size_t max_size = OPUS_MAX_FRAMES * context->common.format.nChannels *
sizeof(int16_t);
760 if (!Stream_EnsureRemainingCapacity(out, max_size))
763 const opus_int16* src_data = WINPR_PACKED_ALIGN_CAST(
const opus_int16*, Stream_Buffer(input));
764 const opus_int32 bytes =
765 opus_encode(context->opus_encoder, src_data, WINPR_ASSERTING_INT_CAST(opus_int32, frames),
766 Stream_Pointer(out), WINPR_ASSERTING_INT_CAST(opus_int32, max_size));
769 Stream_Seek(out, (
size_t)bytes);
771 const size_t used = frames * frame_bytes;
772 const size_t left = Stream_GetPosition(input) - used;
773 memmove(Stream_Buffer(input), Stream_Buffer(input) + used, left);
774 return Stream_SetPosition(input, left);
778#if defined(WITH_FAAD2)
779static BOOL freerdp_dsp_decode_faad(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
780 const BYTE* WINPR_RESTRICT src,
size_t size,
783 NeAACDecFrameInfo info;
786 if (!context || !src || !out)
789 if (!context->faadSetup)
796 unsigned long samplerate = 0;
797 unsigned char channels = 0;
800 const long err = NeAACDecInit(context->faad, cnv.pv,
801 size, &samplerate, &channels);
806 if (channels != context->common.format.nChannels)
809 if (samplerate != context->common.format.nSamplesPerSec)
812 context->faadSetup = TRUE;
815 while (offset < size)
823 const size_t outSize = context->common.format.nSamplesPerSec *
824 context->common.format.nChannels *
825 context->common.format.wBitsPerSample / 8;
827 if (!Stream_EnsureRemainingCapacity(out, outSize))
830 void* sample_buffer = Stream_Pointer(out);
832 cnv.cpv = &src[offset];
833 NeAACDecDecode2(context->faad, &info, cnv.pv, size - offset, &sample_buffer,
834 Stream_GetRemainingCapacity(out));
839 offset += info.bytesconsumed;
841 if (info.samples == 0)
844 Stream_Seek(out, info.samples * context->common.format.wBitsPerSample / 8);
863} ima_stereo_encode_map[] = { { 0, 0 }, { 4, 0 }, { 0, 4 }, { 4, 4 }, { 1, 0 }, { 5, 0 },
864 { 1, 4 }, { 5, 4 }, { 2, 0 }, { 6, 0 }, { 2, 4 }, { 6, 4 },
865 { 3, 0 }, { 7, 0 }, { 3, 4 }, { 7, 4 } };
867static BYTE dsp_encode_ima_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm,
size_t channel, INT16 sample)
869 WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_step));
870 WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ima.last_sample));
872 const INT16 offset = adpcm->ima.last_step[channel];
873 WINPR_ASSERT(offset >= 0);
874 WINPR_ASSERT(WINPR_CXX_COMPAT_CAST(
size_t, offset) < ARRAYSIZE(ima_step_size_table));
876 INT32 ss = ima_step_size_table[offset];
877 INT32 e = sample - adpcm->ima.last_sample[channel];
879 INT32 diff = ss >> 3;
915 diff += adpcm->ima.last_sample[channel];
919 else if (diff > 32767)
922 adpcm->ima.last_sample[channel] = (INT16)diff;
924 WINPR_ASSERT(enc < ARRAYSIZE(ima_step_index_table));
925 const int32_t last = adpcm->ima.last_step[channel] + ima_step_index_table[enc];
926 adpcm->ima.last_step[channel] = WINPR_ASSERTING_INT_CAST(int16_t, last);
928 dsp_ima_clamp_step(adpcm, channel);
933static BOOL freerdp_dsp_encode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
934 const BYTE* WINPR_RESTRICT src,
size_t size,
937 if (!valid_ima_adpcm_format(context))
939 if (!Stream_EnsureRemainingCapacity(out, size))
941 if (!Stream_EnsureRemainingCapacity(context->common.buffer, size + 64ull))
944 const size_t align = (context->common.format.nChannels > 1) ? 32 : 4;
946 while (size >= align)
948 if (Stream_GetPosition(context->common.buffer) % context->common.format.nBlockAlign == 0)
950 Stream_Write_UINT8(context->common.buffer, context->adpcm.ima.last_sample[0] & 0xFF);
951 Stream_Write_UINT8(context->common.buffer,
952 (context->adpcm.ima.last_sample[0] >> 8) & 0xFF);
953 Stream_Write_UINT8(context->common.buffer, (BYTE)context->adpcm.ima.last_step[0]);
954 Stream_Write_UINT8(context->common.buffer, 0);
956 if (context->common.format.nChannels > 1)
958 Stream_Write_UINT8(context->common.buffer,
959 context->adpcm.ima.last_sample[1] & 0xFF);
960 Stream_Write_UINT8(context->common.buffer,
961 (context->adpcm.ima.last_sample[1] >> 8) & 0xFF);
962 Stream_Write_UINT8(context->common.buffer, (BYTE)context->adpcm.ima.last_step[1]);
963 Stream_Write_UINT8(context->common.buffer, 0);
967 if (context->common.format.nChannels > 1)
969 BYTE* dst = Stream_Pointer(context->common.buffer);
972 for (
size_t i = 0; i < 16; i++)
974 const INT16 sample = (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));
976 const BYTE encoded = dsp_encode_ima_adpcm_sample(&context->adpcm, i % 2, sample);
977 dst[ima_stereo_encode_map[i].byte_num] |= encoded
978 << ima_stereo_encode_map[i].byte_shift;
981 if (!Stream_SafeSeek(context->common.buffer, 8))
987 INT16 sample = (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));
989 BYTE encoded = dsp_encode_ima_adpcm_sample(&context->adpcm, 0, sample);
990 sample = (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));
992 encoded |= dsp_encode_ima_adpcm_sample(&context->adpcm, 0, sample) << 4;
993 Stream_Write_UINT8(context->common.buffer, encoded);
997 if (Stream_GetPosition(context->common.buffer) >= context->adpcm.ima.packet_size)
999 BYTE* bsrc = Stream_Buffer(context->common.buffer);
1000 Stream_Write(out, bsrc, context->adpcm.ima.packet_size);
1001 Stream_ResetPosition(context->common.buffer);
1014static const INT32 ms_adpcm_adaptation_table[] = { 230, 230, 230, 230, 307, 409, 512, 614,
1015 768, 614, 512, 409, 307, 230, 230, 230 };
1017static const INT32 ms_adpcm_coeffs1[7] = { 256, 512, 0, 192, 240, 460, 392 };
1019static const INT32 ms_adpcm_coeffs2[7] = { 0, -256, 0, 64, 0, -208, -232 };
1021static inline INT16 freerdp_dsp_decode_ms_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, BYTE sample,
1024 WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample1));
1025 WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample2));
1026 WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.delta));
1027 WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.predictor));
1029 const INT8 nibble = (INT8)((sample & 0x08) ? (sample - 16) : sample);
1030 const BYTE predictor = adpcm->ms.predictor[channel];
1032 if (predictor < ARRAYSIZE(ms_adpcm_coeffs1))
1033 coeff1 = ms_adpcm_coeffs1[predictor];
1036 if (predictor < ARRAYSIZE(ms_adpcm_coeffs2))
1037 coeff2 = ms_adpcm_coeffs2[predictor];
1039 ((adpcm->ms.sample1[channel] * coeff1) + (adpcm->ms.sample2[channel] * coeff2)) / 256;
1040 presample += nibble * adpcm->ms.delta[channel];
1042 if (presample > 32767)
1044 else if (presample < -32768)
1047 adpcm->ms.sample2[channel] = adpcm->ms.sample1[channel];
1048 adpcm->ms.sample1[channel] = presample;
1051 if (sample < ARRAYSIZE(ms_adpcm_adaptation_table))
1052 tableval = ms_adpcm_adaptation_table[sample];
1054 adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * tableval / 256;
1056 if (adpcm->ms.delta[channel] < 16)
1057 adpcm->ms.delta[channel] = 16;
1059 return (INT16)presample;
1062static BOOL valid_ms_adpcm_format(
const FREERDP_DSP_CONTEXT* WINPR_RESTRICT context)
1064 WINPR_ASSERT(context);
1065 if (context->common.format.wFormatTag != WAVE_FORMAT_ADPCM)
1067 if (context->common.format.nBlockAlign <= 4ULL)
1069 if (context->common.format.nChannels < 1)
1071 if (context->common.format.wBitsPerSample == 0)
1076static BOOL freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
1077 const BYTE* WINPR_RESTRICT src,
size_t size,
1080 if (!valid_ms_adpcm_format(context))
1082 const size_t out_size = size * 4;
1083 const UINT32 channels = context->common.format.nChannels;
1084 const UINT32 block_size = context->common.format.nBlockAlign;
1086 if (!Stream_EnsureCapacity(out, out_size))
1091 if (size % block_size == 0)
1098 context->adpcm.ms.predictor[0] = *src++;
1099 context->adpcm.ms.predictor[1] = *src++;
1100 context->adpcm.ms.delta[0] = read_int16(src);
1102 context->adpcm.ms.delta[1] = read_int16(src);
1104 context->adpcm.ms.sample1[0] = read_int16(src);
1106 context->adpcm.ms.sample1[1] = read_int16(src);
1108 context->adpcm.ms.sample2[0] = read_int16(src);
1110 context->adpcm.ms.sample2[1] = read_int16(src);
1113 Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[0]);
1114 Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[1]);
1115 Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[0]);
1116 Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[1]);
1123 context->adpcm.ms.predictor[0] = *src++;
1124 context->adpcm.ms.delta[0] = read_int16(src);
1126 context->adpcm.ms.sample1[0] = read_int16(src);
1128 context->adpcm.ms.sample2[0] = read_int16(src);
1131 Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[0]);
1132 Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[0]);
1141 const BYTE sample = *src++;
1144 out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0));
1146 out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 1));
1151 const BYTE sample = *src++;
1154 out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0));
1156 out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 1));
1163 const BYTE sample = *src++;
1165 Stream_Write_INT16(out,
1166 freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0));
1168 out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 0));
1175static BYTE freerdp_dsp_encode_ms_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, INT32 sample,
1178 WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample1));
1179 WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.sample2));
1180 WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.delta));
1181 WINPR_ASSERT(channel < ARRAYSIZE(adpcm->ms.predictor));
1184 ((adpcm->ms.sample1[channel] * ms_adpcm_coeffs1[adpcm->ms.predictor[channel]]) +
1185 (adpcm->ms.sample2[channel] * ms_adpcm_coeffs2[adpcm->ms.predictor[channel]])) /
1187 INT32 errordelta = (sample - presample) / adpcm->ms.delta[channel];
1189 if ((sample - presample) % adpcm->ms.delta[channel] > adpcm->ms.delta[channel] / 2)
1194 else if (errordelta < -8)
1197 presample += adpcm->ms.delta[channel] * errordelta;
1199 if (presample > 32767)
1201 else if (presample < -32768)
1204 adpcm->ms.sample2[channel] = adpcm->ms.sample1[channel];
1205 adpcm->ms.sample1[channel] = presample;
1206 const size_t offset = (((BYTE)errordelta) & 0x0F);
1207 WINPR_ASSERT(offset < ARRAYSIZE(ms_adpcm_adaptation_table));
1208 adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * ms_adpcm_adaptation_table[offset] / 256;
1210 if (adpcm->ms.delta[channel] < 16)
1211 adpcm->ms.delta[channel] = 16;
1213 return ((BYTE)errordelta) & 0x0F;
1216static BOOL freerdp_dsp_encode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
1217 const BYTE* WINPR_RESTRICT src,
size_t size,
1220 if (!valid_ms_adpcm_format(context))
1223 const size_t step = 8 + ((context->common.format.nChannels > 1) ? 4 : 0);
1225 if (!Stream_EnsureRemainingCapacity(out, size))
1228 const size_t start = Stream_GetPosition(out);
1230 if (context->adpcm.ms.delta[0] < 16)
1231 context->adpcm.ms.delta[0] = 16;
1233 if (context->adpcm.ms.delta[1] < 16)
1234 context->adpcm.ms.delta[1] = 16;
1236 while (size >= step)
1238 if ((Stream_GetPosition(out) - start) % context->common.format.nBlockAlign == 0)
1240 if (context->common.format.nChannels > 1)
1242 Stream_Write_UINT8(out, context->adpcm.ms.predictor[0]);
1243 Stream_Write_UINT8(out, context->adpcm.ms.predictor[1]);
1244 Stream_Write_UINT8(out, (context->adpcm.ms.delta[0] & 0xFF));
1245 Stream_Write_UINT8(out, ((context->adpcm.ms.delta[0] >> 8) & 0xFF));
1246 Stream_Write_UINT8(out, (context->adpcm.ms.delta[1] & 0xFF));
1247 Stream_Write_UINT8(out, ((context->adpcm.ms.delta[1] >> 8) & 0xFF));
1249 context->adpcm.ms.sample1[0] = read_int16(src + 4);
1250 context->adpcm.ms.sample1[1] = read_int16(src + 6);
1251 context->adpcm.ms.sample2[0] = read_int16(src + 0);
1252 context->adpcm.ms.sample2[1] = read_int16(src + 2);
1254 Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[0]);
1255 Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[1]);
1256 Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[0]);
1257 Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[1]);
1264 Stream_Write_UINT8(out, context->adpcm.ms.predictor[0]);
1265 Stream_Write_UINT8(out, (BYTE)(context->adpcm.ms.delta[0] & 0xFF));
1266 Stream_Write_UINT8(out, (BYTE)((context->adpcm.ms.delta[0] >> 8) & 0xFF));
1268 context->adpcm.ms.sample1[0] = read_int16(src + 2);
1269 context->adpcm.ms.sample2[0] = read_int16(src + 0);
1271 Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[0]);
1272 Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[0]);
1279 const INT16 sample = read_int16(src);
1282 out, (freerdp_dsp_encode_ms_adpcm_sample(&context->adpcm, sample, 0) << 4) & 0xFF);
1285 const INT16 sample = read_int16(src);
1289 Stream_Read_UINT8(out, val);
1290 val += freerdp_dsp_encode_ms_adpcm_sample(&context->adpcm, sample,
1291 context->common.format.nChannels > 1 ? 1 : 0);
1292 Stream_Write_UINT8(out, val);
1302FREERDP_DSP_CONTEXT* freerdp_dsp_context_new(BOOL encoder)
1304#if defined(WITH_DSP_FFMPEG)
1305 return freerdp_dsp_ffmpeg_context_new(encoder);
1307 FREERDP_DSP_CONTEXT* context = calloc(1,
sizeof(FREERDP_DSP_CONTEXT));
1312 if (!freerdp_dsp_common_context_init(&context->common, encoder))
1315#if defined(WITH_GSM)
1316 context->gsm = gsm_create();
1323 int rc = gsm_option(context->gsm, GSM_OPT_WAV49, &val);
1329#if defined(WITH_LAME)
1333 context->lame = lame_init();
1340 context->hip = hip_decode_init();
1347#if defined(WITH_FAAD2)
1351 context->faad = NeAACDecOpen();
1360 freerdp_dsp_context_free(context);
1365void freerdp_dsp_context_free(FREERDP_DSP_CONTEXT* context)
1370#if defined(WITH_FDK_AAC)
1373 fdk_aac_dsp_uninit(ctx);
1376#if defined(WITH_MEDIACODEC)
1380#if defined(WITH_DSP_FFMPEG)
1381 freerdp_dsp_ffmpeg_context_free(context);
1384 freerdp_dsp_common_context_uninit(&context->common);
1386#if defined(WITH_GSM)
1387 gsm_destroy(context->gsm);
1389#if defined(WITH_LAME)
1391 if (context->common.encoder)
1392 lame_close(context->lame);
1394 hip_decode_exit(context->hip);
1397#if defined(WITH_OPUS)
1399 if (context->opus_decoder)
1400 opus_decoder_destroy(context->opus_decoder);
1401 if (context->opus_encoder)
1402 opus_encoder_destroy(context->opus_encoder);
1403 Stream_Free(context->opus_input, TRUE);
1406#if defined(WITH_FAAD2)
1408 if (!context->common.encoder)
1409 NeAACDecClose(context->faad);
1412#if defined(WITH_FAAC)
1415 faacEncClose(context->faac);
1418#if defined(WITH_SOXR)
1419 soxr_delete(context->sox);
1426BOOL freerdp_dsp_encode(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
1428 const BYTE* WINPR_RESTRICT pdata,
size_t length,
1431#if defined(WITH_MEDIACODEC)
1433 if (mcctx && (mcctx->format.wFormatTag == WAVE_FORMAT_AAC_MS))
1434 return mediacodec_aac_dsp_encode(mcctx, srcFormat, pdata, length, out);
1437#if defined(WITH_FDK_AAC)
1440 switch (ctx->format.wFormatTag)
1442 case WAVE_FORMAT_AAC_MS:
1443 return fdk_aac_dsp_encode(ctx, srcFormat, pdata, length, out);
1449#if defined(WITH_DSP_FFMPEG)
1450 return freerdp_dsp_ffmpeg_encode(context, srcFormat, pdata, length, out);
1452 if (!context || !context->common.encoder || !srcFormat || !pdata || !out)
1456 const BYTE* resampleData =
nullptr;
1457 size_t resampleLength = 0;
1459 if (!freerdp_dsp_channel_mix(context, pdata, length, srcFormat, &resampleData, &resampleLength))
1462 format.nChannels = context->common.format.nChannels;
1464 const BYTE* data =
nullptr;
1465 if (!freerdp_dsp_resample(context, resampleData, resampleLength, &format, &data, &length))
1468 switch (context->common.format.wFormatTag)
1470 case WAVE_FORMAT_PCM:
1471 if (!Stream_EnsureRemainingCapacity(out, length))
1474 Stream_Write(out, data, length);
1477 case WAVE_FORMAT_ADPCM:
1478 return freerdp_dsp_encode_ms_adpcm(context, data, length, out);
1480 case WAVE_FORMAT_DVI_ADPCM:
1481 return freerdp_dsp_encode_ima_adpcm(context, data, length, out);
1482#if defined(WITH_GSM)
1484 case WAVE_FORMAT_GSM610:
1485 return freerdp_dsp_encode_gsm610(context, data, length, out);
1487#if defined(WITH_LAME)
1489 case WAVE_FORMAT_MPEGLAYER3:
1490 return freerdp_dsp_encode_mp3(context, data, length, out);
1492#if defined(WITH_FAAC)
1494 case WAVE_FORMAT_AAC_MS:
1495 return freerdp_dsp_encode_faac(context, data, length, out);
1497#if defined(WITH_OPUS)
1499 case WAVE_FORMAT_OPUS:
1500 return freerdp_dsp_encode_opus(context, data, length, out);
1510BOOL freerdp_dsp_decode(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
1512 const BYTE* WINPR_RESTRICT data,
size_t length,
wStream* WINPR_RESTRICT out)
1514#if defined(WITH_MEDIACODEC)
1516 if (mcctx && (mcctx->format.wFormatTag == WAVE_FORMAT_AAC_MS))
1517 return mediacodec_aac_dsp_decode(mcctx, srcFormat, data, length, out);
1520#if defined(WITH_FDK_AAC)
1523 switch (ctx->format.wFormatTag)
1525 case WAVE_FORMAT_AAC_MS:
1526 return fdk_aac_dsp_decode(ctx, srcFormat, data, length, out);
1532#if defined(WITH_DSP_FFMPEG)
1533 return freerdp_dsp_ffmpeg_decode(context, srcFormat, data, length, out);
1536 if (!context || context->common.encoder || !srcFormat || !data || !out)
1539 switch (context->common.format.wFormatTag)
1541 case WAVE_FORMAT_PCM:
1542 if (!Stream_EnsureRemainingCapacity(out, length))
1545 Stream_Write(out, data, length);
1548 case WAVE_FORMAT_ADPCM:
1549 return freerdp_dsp_decode_ms_adpcm(context, data, length, out);
1551 case WAVE_FORMAT_DVI_ADPCM:
1552 return freerdp_dsp_decode_ima_adpcm(context, data, length, out);
1553#if defined(WITH_GSM)
1555 case WAVE_FORMAT_GSM610:
1556 return freerdp_dsp_decode_gsm610(context, data, length, out);
1558#if defined(WITH_LAME)
1560 case WAVE_FORMAT_MPEGLAYER3:
1561 return freerdp_dsp_decode_mp3(context, data, length, out);
1563#if defined(WITH_FAAD2)
1565 case WAVE_FORMAT_AAC_MS:
1566 return freerdp_dsp_decode_faad(context, data, length, out);
1569#if defined(WITH_OPUS)
1570 case WAVE_FORMAT_OPUS:
1571 return freerdp_dsp_decode_opus(context, data, length, out);
1581BOOL freerdp_dsp_supports_format(
const AUDIO_FORMAT* WINPR_RESTRICT format, BOOL encode)
1583#if defined(WITH_MEDIACODEC)
1584 if (format && (format->wFormatTag == WAVE_FORMAT_AAC_MS))
1585 return mediacodec_aac_dsp_supports_format(format, encode);
1588#if defined(WITH_FDK_AAC)
1589 switch (format->wFormatTag)
1591 case WAVE_FORMAT_AAC_MS:
1599#if defined(WITH_DSP_FFMPEG)
1600 return freerdp_dsp_ffmpeg_supports_format(format, encode);
1603#if !defined(WITH_DSP_EXPERIMENTAL)
1604 WINPR_UNUSED(encode);
1606 switch (format->wFormatTag)
1608 case WAVE_FORMAT_PCM:
1610#if defined(WITH_DSP_EXPERIMENTAL)
1612 case WAVE_FORMAT_ADPCM:
1614 case WAVE_FORMAT_DVI_ADPCM:
1617#if defined(WITH_GSM)
1619 case WAVE_FORMAT_GSM610:
1620#if defined(WITH_DSP_EXPERIMENTAL)
1626#if defined(WITH_LAME)
1628 case WAVE_FORMAT_MPEGLAYER3:
1629#if defined(WITH_DSP_EXPERIMENTAL)
1636 case WAVE_FORMAT_AAC_MS:
1637#if defined(WITH_FAAD2)
1642#if defined(WITH_FAAC)
1648#if defined(WITH_FDK_AAC)
1654#if defined(WITH_OPUS)
1655 case WAVE_FORMAT_OPUS:
1656 return opus_is_valid_samplerate(format);
1666BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
1668 UINT32 FramesPerPacket)
1670#if defined(WITH_MEDIACODEC)
1671 if (!context || !targetFormat)
1674 if (targetFormat->wFormatTag == WAVE_FORMAT_AAC_MS)
1677 mediacodec_aac_dsp_uninit(ctx);
1678 ctx->format = *targetFormat;
1679 return mediacodec_aac_dsp_init(ctx, FramesPerPacket);
1683#if defined(WITH_FDK_AAC)
1684 WINPR_ASSERT(targetFormat);
1685 if (targetFormat->wFormatTag == WAVE_FORMAT_AAC_MS)
1688 fdk_aac_dsp_uninit(ctx);
1689 ctx->format = *targetFormat;
1690 return fdk_aac_dsp_init(ctx, FramesPerPacket);
1694#if defined(WITH_DSP_FFMPEG)
1695 return freerdp_dsp_ffmpeg_context_reset(context, targetFormat);
1698 if (!context || !targetFormat)
1701 context->common.format = *targetFormat;
1703 switch (context->common.format.wFormatTag)
1705#if defined(WITH_LAME)
1706 case WAVE_FORMAT_MPEGLAYER3:
1707 if (!valid_mp3_format(context))
1711 case WAVE_FORMAT_ADPCM:
1712 if (!valid_ms_adpcm_format(context))
1715 case WAVE_FORMAT_DVI_ADPCM:
1717 if (!valid_ima_adpcm_format(context))
1719 if (FramesPerPacket == 0)
1722 const size_t min_frame_data = 1ull * context->common.format.wBitsPerSample *
1723 context->common.format.nChannels * FramesPerPacket;
1724 const size_t data_per_block = (1ULL * context->common.format.nBlockAlign -
1725 4ULL * context->common.format.nChannels) *
1727 size_t nb_block_per_packet = min_frame_data / data_per_block;
1729 if (min_frame_data % data_per_block)
1730 nb_block_per_packet++;
1732 context->adpcm.ima.packet_size =
1733 nb_block_per_packet * context->common.format.nBlockAlign;
1734 if (!Stream_EnsureCapacity(context->common.buffer, context->adpcm.ima.packet_size))
1736 Stream_ResetPosition(context->common.buffer);
1743#if defined(WITH_OPUS)
1745 if (context->opus_decoder)
1746 opus_decoder_destroy(context->opus_decoder);
1747 context->opus_decoder =
nullptr;
1748 if (context->opus_encoder)
1749 opus_encoder_destroy(context->opus_encoder);
1750 context->opus_encoder =
nullptr;
1752 if (context->common.format.wFormatTag == WAVE_FORMAT_OPUS)
1754 if (!opus_is_valid_samplerate(&context->common.format))
1757 if (!context->common.encoder)
1759 int opus_error = OPUS_OK;
1761 context->opus_decoder = opus_decoder_create(
1762 WINPR_ASSERTING_INT_CAST(opus_int32, context->common.format.nSamplesPerSec),
1763 context->common.format.nChannels, &opus_error);
1764 if (opus_error != OPUS_OK)
1769 int opus_error = OPUS_OK;
1771 context->opus_encoder = opus_encoder_create(
1772 WINPR_ASSERTING_INT_CAST(opus_int32, context->common.format.nSamplesPerSec),
1773 context->common.format.nChannels, OPUS_APPLICATION_VOIP, &opus_error);
1774 if (opus_error != OPUS_OK)
1778 opus_encoder_ctl(context->opus_encoder,
1779 OPUS_SET_BITRATE(context->common.format.nAvgBytesPerSec * 8));
1780 if (opus_error != OPUS_OK)
1784 const UINT32 rate = context->common.format.nSamplesPerSec;
1785 context->opus_packet_frames =
1786 opus_is_packet_frames(rate, FramesPerPacket) ? FramesPerPacket : rate / 50;
1787 if (!context->opus_input)
1788 context->opus_input = Stream_New(
nullptr, OPUS_MAX_FRAMES *
sizeof(opus_int16) *
1789 context->common.format.nChannels);
1790 if (!context->opus_input)
1792 Stream_ResetPosition(context->opus_input);
1797#if defined(WITH_FAAD2)
1798 context->faadSetup = FALSE;
1800#if defined(WITH_FAAC)
1802 if (context->common.encoder)
1804 faacEncConfigurationPtr cfg =
nullptr;
1807 faacEncClose(context->faac);
1809 context->faac = faacEncOpen(targetFormat->nSamplesPerSec, targetFormat->nChannels,
1810 &context->faacInputSamples, &context->faacMaxOutputBytes);
1815 cfg = faacEncGetCurrentConfiguration(context->faac);
1816 cfg->inputFormat = FAAC_INPUT_16BIT;
1817 cfg->outputFormat = 0;
1818 cfg->mpegVersion = MPEG4;
1820 cfg->bandWidth = targetFormat->nAvgBytesPerSec;
1821 const int rc = faacEncSetConfiguration(context->faac, cfg);
1827#if defined(WITH_SOXR)
1829 soxr_io_spec_t iospec = soxr_io_spec(SOXR_INT16, SOXR_INT16);
1830 soxr_error_t error =
nullptr;
1832 soxr_delete(context->sox);
1834 soxr_create(context->common.format.nSamplesPerSec, targetFormat->nSamplesPerSec,
1835 targetFormat->nChannels, &error, &iospec,
nullptr,
nullptr);
1837 if (!context->sox || (error !=
nullptr))
1847 WINPR_ASSERT(context);
1848 context->encoder = encode;
1849 context->buffer = Stream_New(
nullptr, 1024);
1850 if (!context->buffer)
1853 context->channelmix = Stream_New(
nullptr, 1024);
1854 if (!context->channelmix)
1857 context->resample = Stream_New(
nullptr, 1024);
1858 if (!context->resample)
1864 freerdp_dsp_common_context_uninit(context);
1870 WINPR_ASSERT(context);
1872 Stream_Free(context->buffer, TRUE);
1873 Stream_Free(context->channelmix, TRUE);
1874 Stream_Free(context->resample, TRUE);
1876 context->buffer =
nullptr;
1877 context->channelmix =
nullptr;
1878 context->resample =
nullptr;