/src/FreeRDP/libfreerdp/codec/dsp.c
Line  | Count  | Source (jump to first uncovered line)  | 
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 5760  | 
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  |  | #define TAG FREERDP_TAG("dsp") | 
71  |  |  | 
72  |  | #if !defined(WITH_DSP_FFMPEG)  | 
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] += 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 int 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 << 1)] = (decoded & 0xFF);  | 
402  | 0  |           dst[((i & 3) << 3) + (channel << 1) + 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 << 1) + 4] = (decoded & 0xFF);  | 
409  | 0  |           dst[((i & 3) << 3) + (channel << 1) + 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] = { 0 }; | 
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 = (short*)Stream_Buffer(context->common.buffer);  | 
522  |  |   pcm_r = (short*)Stream_Buffer(context->common.buffer) + 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, (int32_t*)Stream_Buffer(context->common.buffer),  | 
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  |  |   size_t max_size = 5760;  | 
617  |  |   int frames;  | 
618  |  |  | 
619  |  |   if (!context || !src || !out)  | 
620  |  |     return FALSE;  | 
621  |  |  | 
622  |  |   /* Max packet duration is 120ms (5760 at 48KHz) */  | 
623  |  |   max_size = OPUS_MAX_FRAMES * context->common.format.nChannels * sizeof(int16_t);  | 
624  |  |   if (!Stream_EnsureRemainingCapacity(context->common.buffer, max_size))  | 
625  |  |     return FALSE;  | 
626  |  |  | 
627  |  |   frames = opus_decode(context->opus_decoder, src, size, Stream_Pointer(out), OPUS_MAX_FRAMES, 0);  | 
628  |  |   if (frames < 0)  | 
629  |  |     return FALSE;  | 
630  |  |  | 
631  |  |   Stream_Seek(out, frames * context->common.format.nChannels * sizeof(int16_t));  | 
632  |  |  | 
633  |  |   return TRUE;  | 
634  |  | }  | 
635  |  |  | 
636  |  | static BOOL freerdp_dsp_encode_opus(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,  | 
637  |  |                                     const BYTE* WINPR_RESTRICT src, size_t size,  | 
638  |  |                                     wStream* WINPR_RESTRICT out)  | 
639  |  | { | 
640  |  |   if (!context || !src || !out)  | 
641  |  |     return FALSE;  | 
642  |  |  | 
643  |  |   /* Max packet duration is 120ms (5760 at 48KHz) */  | 
644  |  |   const size_t max_size = OPUS_MAX_FRAMES * context->common.format.nChannels * sizeof(int16_t);  | 
645  |  |   if (!Stream_EnsureRemainingCapacity(context->common.buffer, max_size))  | 
646  |  |     return FALSE;  | 
647  |  |  | 
648  |  |   const int src_frames = size / sizeof(opus_int16) / context->common.format.nChannels;  | 
649  |  |   const opus_int16* src_data = (const opus_int16*)src;  | 
650  |  |   const int frames =  | 
651  |  |       opus_encode(context->opus_encoder, src_data, src_frames, Stream_Pointer(out), max_size);  | 
652  |  |   if (frames < 0)  | 
653  |  |     return FALSE;  | 
654  |  |   return Stream_SafeSeek(out, frames * context->common.format.nChannels * sizeof(int16_t));  | 
655  |  | }  | 
656  |  | #endif  | 
657  |  |  | 
658  |  | #if defined(WITH_FAAD2)  | 
659  |  | static BOOL freerdp_dsp_decode_faad(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,  | 
660  |  |                                     const BYTE* WINPR_RESTRICT src, size_t size,  | 
661  |  |                                     wStream* WINPR_RESTRICT out)  | 
662  |  | { | 
663  |  |   NeAACDecFrameInfo info;  | 
664  |  |   size_t offset = 0;  | 
665  |  |  | 
666  |  |   if (!context || !src || !out)  | 
667  |  |     return FALSE;  | 
668  |  |  | 
669  |  |   if (!context->faadSetup)  | 
670  |  |   { | 
671  |  |     union  | 
672  |  |     { | 
673  |  |       const void* cpv;  | 
674  |  |       void* pv;  | 
675  |  |     } cnv;  | 
676  |  |     unsigned long samplerate;  | 
677  |  |     unsigned char channels;  | 
678  |  |     long err;  | 
679  |  |     cnv.cpv = src;  | 
680  |  |     err = NeAACDecInit(context->faad, /* API is not modifying content */ cnv.pv, size,  | 
681  |  |                        &samplerate, &channels);  | 
682  |  |  | 
683  |  |     if (err != 0)  | 
684  |  |       return FALSE;  | 
685  |  |  | 
686  |  |     if (channels != context->common.format.nChannels)  | 
687  |  |       return FALSE;  | 
688  |  |  | 
689  |  |     if (samplerate != context->common.format.nSamplesPerSec)  | 
690  |  |       return FALSE;  | 
691  |  |  | 
692  |  |     context->faadSetup = TRUE;  | 
693  |  |   }  | 
694  |  |  | 
695  |  |   while (offset < size)  | 
696  |  |   { | 
697  |  |     union  | 
698  |  |     { | 
699  |  |       const void* cpv;  | 
700  |  |       void* pv;  | 
701  |  |     } cnv;  | 
702  |  |     size_t outSize;  | 
703  |  |     void* sample_buffer;  | 
704  |  |     outSize = context->common.format.nSamplesPerSec * context->common.format.nChannels *  | 
705  |  |               context->common.format.wBitsPerSample / 8;  | 
706  |  |  | 
707  |  |     if (!Stream_EnsureRemainingCapacity(out, outSize))  | 
708  |  |       return FALSE;  | 
709  |  |  | 
710  |  |     sample_buffer = Stream_Pointer(out);  | 
711  |  |  | 
712  |  |     cnv.cpv = &src[offset];  | 
713  |  |     NeAACDecDecode2(context->faad, &info, cnv.pv, size - offset, &sample_buffer,  | 
714  |  |                     Stream_GetRemainingCapacity(out));  | 
715  |  |  | 
716  |  |     if (info.error != 0)  | 
717  |  |       return FALSE;  | 
718  |  |  | 
719  |  |     offset += info.bytesconsumed;  | 
720  |  |  | 
721  |  |     if (info.samples == 0)  | 
722  |  |       continue;  | 
723  |  |  | 
724  |  |     Stream_Seek(out, info.samples * context->common.format.wBitsPerSample / 8);  | 
725  |  |   }  | 
726  |  |  | 
727  |  |   return TRUE;  | 
728  |  | }  | 
729  |  |  | 
730  |  | #endif  | 
731  |  |  | 
732  |  | /**  | 
733  |  |  * 0     1     2     3  | 
734  |  |  * 2 0   6 4   10 8  14 12   <left>  | 
735  |  |  *  | 
736  |  |  * 4     5     6     7  | 
737  |  |  * 3 1   7 5   11 9  15 13   <right>  | 
738  |  |  */  | 
739  |  | static const struct  | 
740  |  | { | 
741  |  |   BYTE byte_num;  | 
742  |  |   BYTE byte_shift;  | 
743  |  | } ima_stereo_encode_map[] = { { 0, 0 }, { 4, 0 }, { 0, 4 }, { 4, 4 }, { 1, 0 }, { 5, 0 }, | 
744  |  |                             { 1, 4 }, { 5, 4 }, { 2, 0 }, { 6, 0 }, { 2, 4 }, { 6, 4 }, | 
745  |  |                             { 3, 0 }, { 7, 0 }, { 3, 4 }, { 7, 4 } }; | 
746  |  |  | 
747  |  | static BYTE dsp_encode_ima_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, int channel, INT16 sample)  | 
748  | 0  | { | 
749  | 0  |   INT32 ss = ima_step_size_table[adpcm->ima.last_step[channel]];  | 
750  | 0  |   INT32 e = sample - adpcm->ima.last_sample[channel];  | 
751  | 0  |   INT32 d = e;  | 
752  | 0  |   INT32 diff = ss >> 3;  | 
753  | 0  |   BYTE enc = 0;  | 
754  |  | 
  | 
755  | 0  |   if (e < 0)  | 
756  | 0  |   { | 
757  | 0  |     enc = 8;  | 
758  | 0  |     e = -e;  | 
759  | 0  |   }  | 
760  |  | 
  | 
761  | 0  |   if (e >= ss)  | 
762  | 0  |   { | 
763  | 0  |     enc |= 4;  | 
764  | 0  |     e -= ss;  | 
765  | 0  |   }  | 
766  |  | 
  | 
767  | 0  |   ss >>= 1;  | 
768  |  | 
  | 
769  | 0  |   if (e >= ss)  | 
770  | 0  |   { | 
771  | 0  |     enc |= 2;  | 
772  | 0  |     e -= ss;  | 
773  | 0  |   }  | 
774  |  | 
  | 
775  | 0  |   ss >>= 1;  | 
776  |  | 
  | 
777  | 0  |   if (e >= ss)  | 
778  | 0  |   { | 
779  | 0  |     enc |= 1;  | 
780  | 0  |     e -= ss;  | 
781  | 0  |   }  | 
782  |  | 
  | 
783  | 0  |   if (d < 0)  | 
784  | 0  |     diff = d + e - diff;  | 
785  | 0  |   else  | 
786  | 0  |     diff = d - e + diff;  | 
787  |  | 
  | 
788  | 0  |   diff += adpcm->ima.last_sample[channel];  | 
789  |  | 
  | 
790  | 0  |   if (diff < -32768)  | 
791  | 0  |     diff = -32768;  | 
792  | 0  |   else if (diff > 32767)  | 
793  | 0  |     diff = 32767;  | 
794  |  | 
  | 
795  | 0  |   adpcm->ima.last_sample[channel] = (INT16)diff;  | 
796  | 0  |   adpcm->ima.last_step[channel] += ima_step_index_table[enc];  | 
797  |  | 
  | 
798  | 0  |   if (adpcm->ima.last_step[channel] < 0)  | 
799  | 0  |     adpcm->ima.last_step[channel] = 0;  | 
800  | 0  |   else if (adpcm->ima.last_step[channel] > 88)  | 
801  | 0  |     adpcm->ima.last_step[channel] = 88;  | 
802  |  | 
  | 
803  | 0  |   return enc;  | 
804  | 0  | }  | 
805  |  |  | 
806  |  | static BOOL freerdp_dsp_encode_ima_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,  | 
807  |  |                                          const BYTE* WINPR_RESTRICT src, size_t size,  | 
808  |  |                                          wStream* WINPR_RESTRICT out)  | 
809  | 0  | { | 
810  | 0  |   if (!Stream_EnsureRemainingCapacity(out, size))  | 
811  | 0  |     return FALSE;  | 
812  | 0  |   if (!Stream_EnsureRemainingCapacity(context->common.buffer, size + 64))  | 
813  | 0  |     return FALSE;  | 
814  |  |  | 
815  | 0  |   const size_t align = (context->common.format.nChannels > 1) ? 32 : 4;  | 
816  |  | 
  | 
817  | 0  |   while (size >= align)  | 
818  | 0  |   { | 
819  | 0  |     if (Stream_GetPosition(context->common.buffer) % context->common.format.nBlockAlign == 0)  | 
820  | 0  |     { | 
821  | 0  |       Stream_Write_UINT8(context->common.buffer, context->adpcm.ima.last_sample[0] & 0xFF);  | 
822  | 0  |       Stream_Write_UINT8(context->common.buffer,  | 
823  | 0  |                          (context->adpcm.ima.last_sample[0] >> 8) & 0xFF);  | 
824  | 0  |       Stream_Write_UINT8(context->common.buffer, (BYTE)context->adpcm.ima.last_step[0]);  | 
825  | 0  |       Stream_Write_UINT8(context->common.buffer, 0);  | 
826  |  | 
  | 
827  | 0  |       if (context->common.format.nChannels > 1)  | 
828  | 0  |       { | 
829  | 0  |         Stream_Write_UINT8(context->common.buffer,  | 
830  | 0  |                            context->adpcm.ima.last_sample[1] & 0xFF);  | 
831  | 0  |         Stream_Write_UINT8(context->common.buffer,  | 
832  | 0  |                            (context->adpcm.ima.last_sample[1] >> 8) & 0xFF);  | 
833  | 0  |         Stream_Write_UINT8(context->common.buffer, (BYTE)context->adpcm.ima.last_step[1]);  | 
834  | 0  |         Stream_Write_UINT8(context->common.buffer, 0);  | 
835  | 0  |       }  | 
836  | 0  |     }  | 
837  |  | 
  | 
838  | 0  |     if (context->common.format.nChannels > 1)  | 
839  | 0  |     { | 
840  | 0  |       BYTE* dst = Stream_Pointer(context->common.buffer);  | 
841  | 0  |       ZeroMemory(dst, 8);  | 
842  |  | 
  | 
843  | 0  |       for (size_t i = 0; i < 16; i++)  | 
844  | 0  |       { | 
845  | 0  |         const INT16 sample = (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));  | 
846  | 0  |         src += 2;  | 
847  | 0  |         const BYTE encoded = dsp_encode_ima_adpcm_sample(&context->adpcm, i % 2, sample);  | 
848  | 0  |         dst[ima_stereo_encode_map[i].byte_num] |= encoded  | 
849  | 0  |                                                   << ima_stereo_encode_map[i].byte_shift;  | 
850  | 0  |       }  | 
851  |  | 
  | 
852  | 0  |       if (!Stream_SafeSeek(context->common.buffer, 8))  | 
853  | 0  |         return FALSE;  | 
854  | 0  |       size -= 32;  | 
855  | 0  |     }  | 
856  | 0  |     else  | 
857  | 0  |     { | 
858  | 0  |       INT16 sample = (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));  | 
859  | 0  |       src += 2;  | 
860  | 0  |       BYTE encoded = dsp_encode_ima_adpcm_sample(&context->adpcm, 0, sample);  | 
861  | 0  |       sample = (INT16)(((UINT16)(*src)) | (((UINT16)(*(src + 1))) << 8));  | 
862  | 0  |       src += 2;  | 
863  | 0  |       encoded |= dsp_encode_ima_adpcm_sample(&context->adpcm, 0, sample) << 4;  | 
864  | 0  |       Stream_Write_UINT8(context->common.buffer, encoded);  | 
865  | 0  |       size -= 4;  | 
866  | 0  |     }  | 
867  |  |  | 
868  | 0  |     if (Stream_GetPosition(context->common.buffer) >= context->adpcm.ima.packet_size)  | 
869  | 0  |     { | 
870  | 0  |       BYTE* bsrc = Stream_Buffer(context->common.buffer);  | 
871  | 0  |       Stream_Write(out, bsrc, context->adpcm.ima.packet_size);  | 
872  | 0  |       Stream_SetPosition(context->common.buffer, 0);  | 
873  | 0  |     }  | 
874  | 0  |   }  | 
875  |  |  | 
876  | 0  |   return TRUE;  | 
877  | 0  | }  | 
878  |  |  | 
879  |  | /**  | 
880  |  |  * Microsoft ADPCM Specification:  | 
881  |  |  *  | 
882  |  |  * http://wiki.multimedia.cx/index.php?title=Microsoft_ADPCM  | 
883  |  |  */  | 
884  |  |  | 
885  |  | static const INT32 ms_adpcm_adaptation_table[] = { 230, 230, 230, 230, 307, 409, 512, 614, | 
886  |  |                                                  768, 614, 512, 409, 307, 230, 230, 230 };  | 
887  |  |  | 
888  |  | static const INT32 ms_adpcm_coeffs1[7] = { 256, 512, 0, 192, 240, 460, 392 }; | 
889  |  |  | 
890  |  | static const INT32 ms_adpcm_coeffs2[7] = { 0, -256, 0, 64, 0, -208, -232 }; | 
891  |  |  | 
892  |  | static INLINE INT16 freerdp_dsp_decode_ms_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, BYTE sample,  | 
893  |  |                                                        int channel)  | 
894  | 0  | { | 
895  | 0  |   const INT8 nibble = (sample & 0x08 ? (INT8)sample - 16 : (INT8)sample);  | 
896  | 0  |   INT32 presample =  | 
897  | 0  |       ((adpcm->ms.sample1[channel] * ms_adpcm_coeffs1[adpcm->ms.predictor[channel]]) +  | 
898  | 0  |        (adpcm->ms.sample2[channel] * ms_adpcm_coeffs2[adpcm->ms.predictor[channel]])) /  | 
899  | 0  |       256;  | 
900  | 0  |   presample += nibble * adpcm->ms.delta[channel];  | 
901  |  | 
  | 
902  | 0  |   if (presample > 32767)  | 
903  | 0  |     presample = 32767;  | 
904  | 0  |   else if (presample < -32768)  | 
905  | 0  |     presample = -32768;  | 
906  |  | 
  | 
907  | 0  |   adpcm->ms.sample2[channel] = adpcm->ms.sample1[channel];  | 
908  | 0  |   adpcm->ms.sample1[channel] = presample;  | 
909  | 0  |   adpcm->ms.delta[channel] = adpcm->ms.delta[channel] * ms_adpcm_adaptation_table[sample] / 256;  | 
910  |  | 
  | 
911  | 0  |   if (adpcm->ms.delta[channel] < 16)  | 
912  | 0  |     adpcm->ms.delta[channel] = 16;  | 
913  |  | 
  | 
914  | 0  |   return (INT16)presample;  | 
915  | 0  | }  | 
916  |  |  | 
917  |  | static BOOL freerdp_dsp_decode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,  | 
918  |  |                                         const BYTE* WINPR_RESTRICT src, size_t size,  | 
919  |  |                                         wStream* WINPR_RESTRICT out)  | 
920  | 0  | { | 
921  | 0  |   const size_t out_size = size * 4;  | 
922  | 0  |   const UINT32 channels = context->common.format.nChannels;  | 
923  | 0  |   const UINT32 block_size = context->common.format.nBlockAlign;  | 
924  |  | 
  | 
925  | 0  |   if (!Stream_EnsureCapacity(out, out_size))  | 
926  | 0  |     return FALSE;  | 
927  |  |  | 
928  | 0  |   while (size > 0)  | 
929  | 0  |   { | 
930  | 0  |     if (size % block_size == 0)  | 
931  | 0  |     { | 
932  | 0  |       if (channels > 1)  | 
933  | 0  |       { | 
934  | 0  |         context->adpcm.ms.predictor[0] = *src++;  | 
935  | 0  |         context->adpcm.ms.predictor[1] = *src++;  | 
936  | 0  |         context->adpcm.ms.delta[0] = read_int16(src);  | 
937  | 0  |         src += 2;  | 
938  | 0  |         context->adpcm.ms.delta[1] = read_int16(src);  | 
939  | 0  |         src += 2;  | 
940  | 0  |         context->adpcm.ms.sample1[0] = read_int16(src);  | 
941  | 0  |         src += 2;  | 
942  | 0  |         context->adpcm.ms.sample1[1] = read_int16(src);  | 
943  | 0  |         src += 2;  | 
944  | 0  |         context->adpcm.ms.sample2[0] = read_int16(src);  | 
945  | 0  |         src += 2;  | 
946  | 0  |         context->adpcm.ms.sample2[1] = read_int16(src);  | 
947  | 0  |         src += 2;  | 
948  | 0  |         size -= 14;  | 
949  | 0  |         Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[0]);  | 
950  | 0  |         Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[1]);  | 
951  | 0  |         Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[0]);  | 
952  | 0  |         Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[1]);  | 
953  | 0  |       }  | 
954  | 0  |       else  | 
955  | 0  |       { | 
956  | 0  |         context->adpcm.ms.predictor[0] = *src++;  | 
957  | 0  |         context->adpcm.ms.delta[0] = read_int16(src);  | 
958  | 0  |         src += 2;  | 
959  | 0  |         context->adpcm.ms.sample1[0] = read_int16(src);  | 
960  | 0  |         src += 2;  | 
961  | 0  |         context->adpcm.ms.sample2[0] = read_int16(src);  | 
962  | 0  |         src += 2;  | 
963  | 0  |         size -= 7;  | 
964  | 0  |         Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[0]);  | 
965  | 0  |         Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[0]);  | 
966  | 0  |       }  | 
967  | 0  |     }  | 
968  |  | 
  | 
969  | 0  |     if (channels > 1)  | 
970  | 0  |     { | 
971  | 0  |       { | 
972  | 0  |         const BYTE sample = *src++;  | 
973  | 0  |         size--;  | 
974  | 0  |         Stream_Write_INT16(  | 
975  | 0  |             out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0));  | 
976  | 0  |         Stream_Write_INT16(  | 
977  | 0  |             out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 1));  | 
978  | 0  |       }  | 
979  | 0  |       { | 
980  | 0  |         const BYTE sample = *src++;  | 
981  | 0  |         size--;  | 
982  | 0  |         Stream_Write_INT16(  | 
983  | 0  |             out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0));  | 
984  | 0  |         Stream_Write_INT16(  | 
985  | 0  |             out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 1));  | 
986  | 0  |       }  | 
987  | 0  |     }  | 
988  | 0  |     else  | 
989  | 0  |     { | 
990  | 0  |       const BYTE sample = *src++;  | 
991  | 0  |       size--;  | 
992  | 0  |       Stream_Write_INT16(out,  | 
993  | 0  |                          freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample >> 4, 0));  | 
994  | 0  |       Stream_Write_INT16(  | 
995  | 0  |           out, freerdp_dsp_decode_ms_adpcm_sample(&context->adpcm, sample & 0x0F, 0));  | 
996  | 0  |     }  | 
997  | 0  |   }  | 
998  |  | 
  | 
999  | 0  |   return TRUE;  | 
1000  | 0  | }  | 
1001  |  |  | 
1002  |  | static BYTE freerdp_dsp_encode_ms_adpcm_sample(ADPCM* WINPR_RESTRICT adpcm, INT32 sample,  | 
1003  |  |                                                int channel)  | 
1004  | 0  | { | 
1005  | 0  |   INT32 presample =  | 
1006  | 0  |       ((adpcm->ms.sample1[channel] * ms_adpcm_coeffs1[adpcm->ms.predictor[channel]]) +  | 
1007  | 0  |        (adpcm->ms.sample2[channel] * ms_adpcm_coeffs2[adpcm->ms.predictor[channel]])) /  | 
1008  | 0  |       256;  | 
1009  | 0  |   INT32 errordelta = (sample - presample) / adpcm->ms.delta[channel];  | 
1010  |  | 
  | 
1011  | 0  |   if ((sample - presample) % adpcm->ms.delta[channel] > adpcm->ms.delta[channel] / 2)  | 
1012  | 0  |     errordelta++;  | 
1013  |  | 
  | 
1014  | 0  |   if (errordelta > 7)  | 
1015  | 0  |     errordelta = 7;  | 
1016  | 0  |   else if (errordelta < -8)  | 
1017  | 0  |     errordelta = -8;  | 
1018  |  | 
  | 
1019  | 0  |   presample += adpcm->ms.delta[channel] * errordelta;  | 
1020  |  | 
  | 
1021  | 0  |   if (presample > 32767)  | 
1022  | 0  |     presample = 32767;  | 
1023  | 0  |   else if (presample < -32768)  | 
1024  | 0  |     presample = -32768;  | 
1025  |  | 
  | 
1026  | 0  |   adpcm->ms.sample2[channel] = adpcm->ms.sample1[channel];  | 
1027  | 0  |   adpcm->ms.sample1[channel] = presample;  | 
1028  | 0  |   adpcm->ms.delta[channel] =  | 
1029  | 0  |       adpcm->ms.delta[channel] * ms_adpcm_adaptation_table[(((BYTE)errordelta) & 0x0F)] / 256;  | 
1030  |  | 
  | 
1031  | 0  |   if (adpcm->ms.delta[channel] < 16)  | 
1032  | 0  |     adpcm->ms.delta[channel] = 16;  | 
1033  |  | 
  | 
1034  | 0  |   return ((BYTE)errordelta) & 0x0F;  | 
1035  | 0  | }  | 
1036  |  |  | 
1037  |  | static BOOL freerdp_dsp_encode_ms_adpcm(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,  | 
1038  |  |                                         const BYTE* WINPR_RESTRICT src, size_t size,  | 
1039  |  |                                         wStream* WINPR_RESTRICT out)  | 
1040  | 0  | { | 
1041  | 0  |   const size_t step = 8 + ((context->common.format.nChannels > 1) ? 4 : 0);  | 
1042  |  | 
  | 
1043  | 0  |   if (!Stream_EnsureRemainingCapacity(out, size))  | 
1044  | 0  |     return FALSE;  | 
1045  |  |  | 
1046  | 0  |   const size_t start = Stream_GetPosition(out);  | 
1047  |  | 
  | 
1048  | 0  |   if (context->adpcm.ms.delta[0] < 16)  | 
1049  | 0  |     context->adpcm.ms.delta[0] = 16;  | 
1050  |  | 
  | 
1051  | 0  |   if (context->adpcm.ms.delta[1] < 16)  | 
1052  | 0  |     context->adpcm.ms.delta[1] = 16;  | 
1053  |  | 
  | 
1054  | 0  |   while (size >= step)  | 
1055  | 0  |   { | 
1056  | 0  |     if ((Stream_GetPosition(out) - start) % context->common.format.nBlockAlign == 0)  | 
1057  | 0  |     { | 
1058  | 0  |       if (context->common.format.nChannels > 1)  | 
1059  | 0  |       { | 
1060  | 0  |         Stream_Write_UINT8(out, context->adpcm.ms.predictor[0]);  | 
1061  | 0  |         Stream_Write_UINT8(out, context->adpcm.ms.predictor[1]);  | 
1062  | 0  |         Stream_Write_UINT8(out, (context->adpcm.ms.delta[0] & 0xFF));  | 
1063  | 0  |         Stream_Write_UINT8(out, ((context->adpcm.ms.delta[0] >> 8) & 0xFF));  | 
1064  | 0  |         Stream_Write_UINT8(out, (context->adpcm.ms.delta[1] & 0xFF));  | 
1065  | 0  |         Stream_Write_UINT8(out, ((context->adpcm.ms.delta[1] >> 8) & 0xFF));  | 
1066  |  | 
  | 
1067  | 0  |         context->adpcm.ms.sample1[0] = read_int16(src + 4);  | 
1068  | 0  |         context->adpcm.ms.sample1[1] = read_int16(src + 6);  | 
1069  | 0  |         context->adpcm.ms.sample2[0] = read_int16(src + 0);  | 
1070  | 0  |         context->adpcm.ms.sample2[1] = read_int16(src + 2);  | 
1071  |  | 
  | 
1072  | 0  |         Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[0]);  | 
1073  | 0  |         Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[1]);  | 
1074  | 0  |         Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[0]);  | 
1075  | 0  |         Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[1]);  | 
1076  |  | 
  | 
1077  | 0  |         src += 8;  | 
1078  | 0  |         size -= 8;  | 
1079  | 0  |       }  | 
1080  | 0  |       else  | 
1081  | 0  |       { | 
1082  | 0  |         Stream_Write_UINT8(out, context->adpcm.ms.predictor[0]);  | 
1083  | 0  |         Stream_Write_UINT8(out, (BYTE)(context->adpcm.ms.delta[0] & 0xFF));  | 
1084  | 0  |         Stream_Write_UINT8(out, (BYTE)((context->adpcm.ms.delta[0] >> 8) & 0xFF));  | 
1085  |  | 
  | 
1086  | 0  |         context->adpcm.ms.sample1[0] = read_int16(src + 2);  | 
1087  | 0  |         context->adpcm.ms.sample2[0] = read_int16(src + 0);  | 
1088  |  | 
  | 
1089  | 0  |         Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample1[0]);  | 
1090  | 0  |         Stream_Write_INT16(out, (INT16)context->adpcm.ms.sample2[0]);  | 
1091  | 0  |         src += 4;  | 
1092  | 0  |         size -= 4;  | 
1093  | 0  |       }  | 
1094  | 0  |     }  | 
1095  |  | 
  | 
1096  | 0  |     { | 
1097  | 0  |       const INT16 sample = read_int16(src);  | 
1098  | 0  |       src += 2;  | 
1099  | 0  |       Stream_Write_UINT8(  | 
1100  | 0  |           out, (freerdp_dsp_encode_ms_adpcm_sample(&context->adpcm, sample, 0) << 4) & 0xFF);  | 
1101  | 0  |     }  | 
1102  | 0  |     { | 
1103  | 0  |       const INT16 sample = read_int16(src);  | 
1104  | 0  |       src += 2;  | 
1105  |  | 
  | 
1106  | 0  |       BYTE val = 0;  | 
1107  | 0  |       Stream_Read_UINT8(out, val);  | 
1108  | 0  |       val += freerdp_dsp_encode_ms_adpcm_sample(&context->adpcm, sample,  | 
1109  | 0  |                                                 context->common.format.nChannels > 1 ? 1 : 0);  | 
1110  | 0  |       Stream_Write_UINT8(out, val);  | 
1111  | 0  |     }  | 
1112  | 0  |     size -= 4;  | 
1113  | 0  |   }  | 
1114  |  | 
  | 
1115  | 0  |   return TRUE;  | 
1116  | 0  | }  | 
1117  |  |  | 
1118  |  | #endif  | 
1119  |  |  | 
1120  |  | FREERDP_DSP_CONTEXT* freerdp_dsp_context_new(BOOL encoder)  | 
1121  | 0  | { | 
1122  |  | #if defined(WITH_DSP_FFMPEG)  | 
1123  |  |   return freerdp_dsp_ffmpeg_context_new(encoder);  | 
1124  |  | #else  | 
1125  | 0  |   FREERDP_DSP_CONTEXT* context = calloc(1, sizeof(FREERDP_DSP_CONTEXT));  | 
1126  |  | 
  | 
1127  | 0  |   if (!context)  | 
1128  | 0  |     return NULL;  | 
1129  |  |  | 
1130  | 0  |   if (!freerdp_dsp_common_context_init(&context->common, encoder))  | 
1131  | 0  |     goto fail;  | 
1132  |  |  | 
1133  |  | #if defined(WITH_GSM)  | 
1134  |  |   context->gsm = gsm_create();  | 
1135  |  |  | 
1136  |  |   if (!context->gsm)  | 
1137  |  |     goto fail;  | 
1138  |  |  | 
1139  |  |   { | 
1140  |  |     int rc;  | 
1141  |  |     int val = 1;  | 
1142  |  |     rc = gsm_option(context->gsm, GSM_OPT_WAV49, &val);  | 
1143  |  |  | 
1144  |  |     if (rc < 0)  | 
1145  |  |       goto fail;  | 
1146  |  |   }  | 
1147  |  | #endif  | 
1148  |  | #if defined(WITH_LAME)  | 
1149  |  |  | 
1150  |  |   if (encoder)  | 
1151  |  |   { | 
1152  |  |     context->lame = lame_init();  | 
1153  |  |  | 
1154  |  |     if (!context->lame)  | 
1155  |  |       goto fail;  | 
1156  |  |   }  | 
1157  |  |   else  | 
1158  |  |   { | 
1159  |  |     context->hip = hip_decode_init();  | 
1160  |  |  | 
1161  |  |     if (!context->hip)  | 
1162  |  |       goto fail;  | 
1163  |  |   }  | 
1164  |  |  | 
1165  |  | #endif  | 
1166  |  | #if defined(WITH_FAAD2)  | 
1167  |  |  | 
1168  |  |   if (!encoder)  | 
1169  |  |   { | 
1170  |  |     context->faad = NeAACDecOpen();  | 
1171  |  |  | 
1172  |  |     if (!context->faad)  | 
1173  |  |       goto fail;  | 
1174  |  |   }  | 
1175  |  |  | 
1176  |  | #endif  | 
1177  | 0  |   return context;  | 
1178  | 0  | fail:  | 
1179  | 0  |   freerdp_dsp_context_free(context);  | 
1180  | 0  |   return NULL;  | 
1181  | 0  | #endif  | 
1182  | 0  | }  | 
1183  |  |  | 
1184  |  | void freerdp_dsp_context_free(FREERDP_DSP_CONTEXT* context)  | 
1185  | 0  | { | 
1186  |  | #if defined(WITH_DSP_FFMPEG)  | 
1187  |  |   freerdp_dsp_ffmpeg_context_free(context);  | 
1188  |  | #else  | 
1189  |  | 
  | 
1190  | 0  |   if (context)  | 
1191  | 0  |   { | 
1192  | 0  |     freerdp_dsp_common_context_uninit(&context->common);  | 
1193  |  | 
  | 
1194  |  | #if defined(WITH_GSM)  | 
1195  |  |     gsm_destroy(context->gsm);  | 
1196  |  | #endif  | 
1197  |  | #if defined(WITH_LAME)  | 
1198  |  |  | 
1199  |  |     if (context->common.encoder)  | 
1200  |  |       lame_close(context->lame);  | 
1201  |  |     else  | 
1202  |  |       hip_decode_exit(context->hip);  | 
1203  |  |  | 
1204  |  | #endif  | 
1205  |  | #if defined(WITH_OPUS)  | 
1206  |  |  | 
1207  |  |     if (context->opus_decoder)  | 
1208  |  |       opus_decoder_destroy(context->opus_decoder);  | 
1209  |  |     if (context->opus_encoder)  | 
1210  |  |       opus_encoder_destroy(context->opus_encoder);  | 
1211  |  |  | 
1212  |  | #endif  | 
1213  |  | #if defined(WITH_FAAD2)  | 
1214  |  |  | 
1215  |  |     if (!context->common.encoder)  | 
1216  |  |       NeAACDecClose(context->faad);  | 
1217  |  |  | 
1218  |  | #endif  | 
1219  |  | #if defined(WITH_FAAC)  | 
1220  |  |  | 
1221  |  |     if (context->faac)  | 
1222  |  |       faacEncClose(context->faac);  | 
1223  |  |  | 
1224  |  | #endif  | 
1225  |  | #if defined(WITH_SOXR)  | 
1226  |  |     soxr_delete(context->sox);  | 
1227  |  | #endif  | 
1228  | 0  |     free(context);  | 
1229  | 0  |   }  | 
1230  |  | 
  | 
1231  | 0  | #endif  | 
1232  | 0  | }  | 
1233  |  |  | 
1234  |  | BOOL freerdp_dsp_encode(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,  | 
1235  |  |                         const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,  | 
1236  |  |                         const BYTE* WINPR_RESTRICT pdata, size_t length,  | 
1237  |  |                         wStream* WINPR_RESTRICT out)  | 
1238  | 0  | { | 
1239  |  | #if defined(WITH_FDK_AAC)  | 
1240  |  |   FREERDP_DSP_COMMON_CONTEXT* ctx = (FREERDP_DSP_COMMON_CONTEXT*)context;  | 
1241  |  |   WINPR_ASSERT(ctx);  | 
1242  |  |   switch (ctx->format.wFormatTag)  | 
1243  |  |   { | 
1244  |  |     case WAVE_FORMAT_AAC_MS:  | 
1245  |  |       return fdk_aac_dsp_encode(ctx, srcFormat, pdata, length, out);  | 
1246  |  |     default:  | 
1247  |  |       break;  | 
1248  |  |   }  | 
1249  |  | #endif  | 
1250  |  | 
  | 
1251  |  | #if defined(WITH_DSP_FFMPEG)  | 
1252  |  |   return freerdp_dsp_ffmpeg_encode(context, srcFormat, pdata, length, out);  | 
1253  |  | #else  | 
1254  | 0  |   if (!context || !context->common.encoder || !srcFormat || !pdata || !out)  | 
1255  | 0  |     return FALSE;  | 
1256  |  |  | 
1257  | 0  |   AUDIO_FORMAT format = *srcFormat;  | 
1258  | 0  |   const BYTE* resampleData = NULL;  | 
1259  | 0  |   size_t resampleLength = 0;  | 
1260  |  | 
  | 
1261  | 0  |   if (!freerdp_dsp_channel_mix(context, pdata, length, srcFormat, &resampleData, &resampleLength))  | 
1262  | 0  |     return FALSE;  | 
1263  |  |  | 
1264  | 0  |   format.nChannels = context->common.format.nChannels;  | 
1265  |  | 
  | 
1266  | 0  |   const BYTE* data = NULL;  | 
1267  | 0  |   if (!freerdp_dsp_resample(context, resampleData, resampleLength, &format, &data, &length))  | 
1268  | 0  |     return FALSE;  | 
1269  |  |  | 
1270  | 0  |   switch (context->common.format.wFormatTag)  | 
1271  | 0  |   { | 
1272  | 0  |     case WAVE_FORMAT_PCM:  | 
1273  | 0  |       if (!Stream_EnsureRemainingCapacity(out, length))  | 
1274  | 0  |         return FALSE;  | 
1275  |  |  | 
1276  | 0  |       Stream_Write(out, data, length);  | 
1277  | 0  |       return TRUE;  | 
1278  |  |  | 
1279  | 0  |     case WAVE_FORMAT_ADPCM:  | 
1280  | 0  |       return freerdp_dsp_encode_ms_adpcm(context, data, length, out);  | 
1281  |  |  | 
1282  | 0  |     case WAVE_FORMAT_DVI_ADPCM:  | 
1283  | 0  |       return freerdp_dsp_encode_ima_adpcm(context, data, length, out);  | 
1284  |  | #if defined(WITH_GSM)  | 
1285  |  |  | 
1286  |  |     case WAVE_FORMAT_GSM610:  | 
1287  |  |       return freerdp_dsp_encode_gsm610(context, data, length, out);  | 
1288  |  | #endif  | 
1289  |  | #if defined(WITH_LAME)  | 
1290  |  |  | 
1291  |  |     case WAVE_FORMAT_MPEGLAYER3:  | 
1292  |  |       return freerdp_dsp_encode_mp3(context, data, length, out);  | 
1293  |  | #endif  | 
1294  |  | #if defined(WITH_FAAC)  | 
1295  |  |  | 
1296  |  |     case WAVE_FORMAT_AAC_MS:  | 
1297  |  |       return freerdp_dsp_encode_faac(context, data, length, out);  | 
1298  |  | #endif  | 
1299  |  | #if defined(WITH_OPUS)  | 
1300  |  |  | 
1301  |  |     case WAVE_FORMAT_OPUS:  | 
1302  |  |       return freerdp_dsp_encode_opus(context, data, length, out);  | 
1303  |  | #endif  | 
1304  | 0  |     default:  | 
1305  | 0  |       return FALSE;  | 
1306  | 0  |   }  | 
1307  |  |  | 
1308  | 0  |   return FALSE;  | 
1309  | 0  | #endif  | 
1310  | 0  | }  | 
1311  |  |  | 
1312  |  | BOOL freerdp_dsp_decode(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,  | 
1313  |  |                         const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,  | 
1314  |  |                         const BYTE* WINPR_RESTRICT data, size_t length, wStream* WINPR_RESTRICT out)  | 
1315  | 0  | { | 
1316  |  | #if defined(WITH_FDK_AAC)  | 
1317  |  |   FREERDP_DSP_COMMON_CONTEXT* ctx = (FREERDP_DSP_COMMON_CONTEXT*)context;  | 
1318  |  |   WINPR_ASSERT(ctx);  | 
1319  |  |   switch (ctx->format.wFormatTag)  | 
1320  |  |   { | 
1321  |  |     case WAVE_FORMAT_AAC_MS:  | 
1322  |  |       return fdk_aac_dsp_decode(ctx, srcFormat, data, length, out);  | 
1323  |  |     default:  | 
1324  |  |       break;  | 
1325  |  |   }  | 
1326  |  | #endif  | 
1327  |  | 
  | 
1328  |  | #if defined(WITH_DSP_FFMPEG)  | 
1329  |  |   return freerdp_dsp_ffmpeg_decode(context, srcFormat, data, length, out);  | 
1330  |  | #else  | 
1331  |  | 
  | 
1332  | 0  |   if (!context || context->common.encoder || !srcFormat || !data || !out)  | 
1333  | 0  |     return FALSE;  | 
1334  |  |  | 
1335  | 0  |   switch (context->common.format.wFormatTag)  | 
1336  | 0  |   { | 
1337  | 0  |     case WAVE_FORMAT_PCM:  | 
1338  | 0  |       if (!Stream_EnsureRemainingCapacity(out, length))  | 
1339  | 0  |         return FALSE;  | 
1340  |  |  | 
1341  | 0  |       Stream_Write(out, data, length);  | 
1342  | 0  |       return TRUE;  | 
1343  |  |  | 
1344  | 0  |     case WAVE_FORMAT_ADPCM:  | 
1345  | 0  |       return freerdp_dsp_decode_ms_adpcm(context, data, length, out);  | 
1346  |  |  | 
1347  | 0  |     case WAVE_FORMAT_DVI_ADPCM:  | 
1348  | 0  |       return freerdp_dsp_decode_ima_adpcm(context, data, length, out);  | 
1349  |  | #if defined(WITH_GSM)  | 
1350  |  |  | 
1351  |  |     case WAVE_FORMAT_GSM610:  | 
1352  |  |       return freerdp_dsp_decode_gsm610(context, data, length, out);  | 
1353  |  | #endif  | 
1354  |  | #if defined(WITH_LAME)  | 
1355  |  |  | 
1356  |  |     case WAVE_FORMAT_MPEGLAYER3:  | 
1357  |  |       return freerdp_dsp_decode_mp3(context, data, length, out);  | 
1358  |  | #endif  | 
1359  |  | #if defined(WITH_FAAD2)  | 
1360  |  |  | 
1361  |  |     case WAVE_FORMAT_AAC_MS:  | 
1362  |  |       return freerdp_dsp_decode_faad(context, data, length, out);  | 
1363  |  | #endif  | 
1364  |  |  | 
1365  |  | #if defined(WITH_OPUS)  | 
1366  |  |     case WAVE_FORMAT_OPUS:  | 
1367  |  |       return freerdp_dsp_decode_opus(context, data, length, out);  | 
1368  |  | #endif  | 
1369  | 0  |     default:  | 
1370  | 0  |       return FALSE;  | 
1371  | 0  |   }  | 
1372  |  |  | 
1373  | 0  |   return FALSE;  | 
1374  | 0  | #endif  | 
1375  | 0  | }  | 
1376  |  |  | 
1377  |  | BOOL freerdp_dsp_supports_format(const AUDIO_FORMAT* WINPR_RESTRICT format, BOOL encode)  | 
1378  | 0  | { | 
1379  |  | #if defined(WITH_FDK_AAC)  | 
1380  |  |   switch (format->wFormatTag)  | 
1381  |  |   { | 
1382  |  |     case WAVE_FORMAT_AAC_MS:  | 
1383  |  |       return TRUE;  | 
1384  |  |     default:  | 
1385  |  |       break;  | 
1386  |  |   }  | 
1387  |  |  | 
1388  |  | #endif  | 
1389  |  | 
  | 
1390  |  | #if defined(WITH_DSP_FFMPEG)  | 
1391  |  |   return freerdp_dsp_ffmpeg_supports_format(format, encode);  | 
1392  |  | #else  | 
1393  |  | 
  | 
1394  | 0  | #if !defined(WITH_DSP_EXPERIMENTAL)  | 
1395  | 0  |   WINPR_UNUSED(encode);  | 
1396  | 0  | #endif  | 
1397  | 0  |   switch (format->wFormatTag)  | 
1398  | 0  |   { | 
1399  | 0  |     case WAVE_FORMAT_PCM:  | 
1400  | 0  |       return TRUE;  | 
1401  |  | #if defined(WITH_DSP_EXPERIMENTAL)  | 
1402  |  |  | 
1403  |  |     case WAVE_FORMAT_ADPCM:  | 
1404  |  |       return FALSE;  | 
1405  |  |     case WAVE_FORMAT_DVI_ADPCM:  | 
1406  |  |       return TRUE;  | 
1407  |  | #endif  | 
1408  |  | #if defined(WITH_GSM)  | 
1409  |  |  | 
1410  |  |     case WAVE_FORMAT_GSM610:  | 
1411  |  | #if defined(WITH_DSP_EXPERIMENTAL)  | 
1412  |  |       return TRUE;  | 
1413  |  | #else  | 
1414  |  |       return !encode;  | 
1415  |  | #endif  | 
1416  |  | #endif  | 
1417  |  | #if defined(WITH_LAME)  | 
1418  |  |  | 
1419  |  |     case WAVE_FORMAT_MPEGLAYER3:  | 
1420  |  | #if defined(WITH_DSP_EXPERIMENTAL)  | 
1421  |  |       return TRUE;  | 
1422  |  | #else  | 
1423  |  |       return !encode;  | 
1424  |  | #endif  | 
1425  |  | #endif  | 
1426  |  |  | 
1427  | 0  |     case WAVE_FORMAT_AAC_MS:  | 
1428  |  | #if defined(WITH_FAAD2)  | 
1429  |  |       if (!encode)  | 
1430  |  |         return TRUE;  | 
1431  |  |  | 
1432  |  | #endif  | 
1433  |  | #if defined(WITH_FAAC)  | 
1434  |  |  | 
1435  |  |       if (encode)  | 
1436  |  |         return TRUE;  | 
1437  |  |  | 
1438  |  | #endif  | 
1439  |  | #if defined(WITH_OPUS)  | 
1440  |  |       /* fallthrough */  | 
1441  |  |       WINPR_FALLTHROUGH  | 
1442  |  |     case WAVE_FORMAT_OPUS:  | 
1443  |  |       return opus_is_valid_samplerate(format);  | 
1444  |  | #endif  | 
1445  |  |       /* fallthrough */  | 
1446  | 0  |       WINPR_FALLTHROUGH  | 
1447  | 0  |     default:  | 
1448  | 0  |       return FALSE;  | 
1449  | 0  |   }  | 
1450  |  |  | 
1451  | 0  |   return FALSE;  | 
1452  | 0  | #endif  | 
1453  | 0  | }  | 
1454  |  |  | 
1455  |  | BOOL freerdp_dsp_context_reset(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,  | 
1456  |  |                                const AUDIO_FORMAT* WINPR_RESTRICT targetFormat,  | 
1457  |  |                                UINT32 FramesPerPacket)  | 
1458  | 0  | { | 
1459  |  | #if defined(WITH_FDK_AAC)  | 
1460  |  |   WINPR_ASSERT(targetFormat);  | 
1461  |  |   if (targetFormat->wFormatTag == WAVE_FORMAT_AAC_MS)  | 
1462  |  |   { | 
1463  |  |     FREERDP_DSP_COMMON_CONTEXT* ctx = (FREERDP_DSP_COMMON_CONTEXT*)context;  | 
1464  |  |     fdk_aac_dsp_uninit(ctx);  | 
1465  |  |     ctx->format = *targetFormat;  | 
1466  |  |     return fdk_aac_dsp_init(ctx, FramesPerPacket);  | 
1467  |  |   }  | 
1468  |  | #endif  | 
1469  |  | 
  | 
1470  |  | #if defined(WITH_DSP_FFMPEG)  | 
1471  |  |   return freerdp_dsp_ffmpeg_context_reset(context, targetFormat);  | 
1472  |  | #else  | 
1473  |  | 
  | 
1474  | 0  |   if (!context || !targetFormat)  | 
1475  | 0  |     return FALSE;  | 
1476  |  |  | 
1477  | 0  |   context->common.format = *targetFormat;  | 
1478  |  | 
  | 
1479  | 0  |   if (context->common.format.wFormatTag == WAVE_FORMAT_DVI_ADPCM)  | 
1480  | 0  |   { | 
1481  | 0  |     size_t min_frame_data = 1ull * context->common.format.wBitsPerSample *  | 
1482  | 0  |                             context->common.format.nChannels * FramesPerPacket;  | 
1483  | 0  |     size_t data_per_block =  | 
1484  | 0  |         (1ULL * context->common.format.nBlockAlign - 4ULL * context->common.format.nChannels) *  | 
1485  | 0  |         8ULL;  | 
1486  | 0  |     size_t nb_block_per_packet = min_frame_data / data_per_block;  | 
1487  |  | 
  | 
1488  | 0  |     if (min_frame_data % data_per_block)  | 
1489  | 0  |       nb_block_per_packet++;  | 
1490  |  | 
  | 
1491  | 0  |     context->adpcm.ima.packet_size = nb_block_per_packet * context->common.format.nBlockAlign;  | 
1492  | 0  |     Stream_EnsureCapacity(context->common.buffer, context->adpcm.ima.packet_size);  | 
1493  | 0  |     Stream_SetPosition(context->common.buffer, 0);  | 
1494  | 0  |   }  | 
1495  |  | 
  | 
1496  |  | #if defined(WITH_OPUS)  | 
1497  |  |  | 
1498  |  |   if (opus_is_valid_samplerate(&context->common.format))  | 
1499  |  |   { | 
1500  |  |     if (!context->common.encoder)  | 
1501  |  |     { | 
1502  |  |       int opus_error = OPUS_OK;  | 
1503  |  |  | 
1504  |  |       context->opus_decoder =  | 
1505  |  |           opus_decoder_create(context->common.format.nSamplesPerSec,  | 
1506  |  |                               context->common.format.nChannels, &opus_error);  | 
1507  |  |       if (opus_error != OPUS_OK)  | 
1508  |  |         return FALSE;  | 
1509  |  |     }  | 
1510  |  |     else  | 
1511  |  |     { | 
1512  |  |       int opus_error = OPUS_OK;  | 
1513  |  |  | 
1514  |  |       context->opus_encoder = opus_encoder_create(context->common.format.nSamplesPerSec,  | 
1515  |  |                                                   context->common.format.nChannels,  | 
1516  |  |                                                   OPUS_APPLICATION_VOIP, &opus_error);  | 
1517  |  |       if (opus_error != OPUS_OK)  | 
1518  |  |         return FALSE;  | 
1519  |  |  | 
1520  |  |       opus_error =  | 
1521  |  |           opus_encoder_ctl(context->opus_encoder,  | 
1522  |  |                            OPUS_SET_BITRATE(context->common.format.nAvgBytesPerSec * 8));  | 
1523  |  |       if (opus_error != OPUS_OK)  | 
1524  |  |         return FALSE;  | 
1525  |  |     }  | 
1526  |  |   }  | 
1527  |  |  | 
1528  |  | #endif  | 
1529  |  | #if defined(WITH_FAAD2)  | 
1530  |  |   context->faadSetup = FALSE;  | 
1531  |  | #endif  | 
1532  |  | #if defined(WITH_FAAC)  | 
1533  |  |  | 
1534  |  |   if (context->encoder)  | 
1535  |  |   { | 
1536  |  |     faacEncConfigurationPtr cfg;  | 
1537  |  |  | 
1538  |  |     if (context->faac)  | 
1539  |  |       faacEncClose(context->faac);  | 
1540  |  |  | 
1541  |  |     context->faac = faacEncOpen(targetFormat->nSamplesPerSec, targetFormat->nChannels,  | 
1542  |  |                                 &context->faacInputSamples, &context->faacMaxOutputBytes);  | 
1543  |  |  | 
1544  |  |     if (!context->faac)  | 
1545  |  |       return FALSE;  | 
1546  |  |  | 
1547  |  |     cfg = faacEncGetCurrentConfiguration(context->faac);  | 
1548  |  |     cfg->inputFormat = FAAC_INPUT_16BIT;  | 
1549  |  |     cfg->outputFormat = 0;  | 
1550  |  |     cfg->mpegVersion = MPEG4;  | 
1551  |  |     cfg->useTns = 1;  | 
1552  |  |     cfg->bandWidth = targetFormat->nAvgBytesPerSec;  | 
1553  |  |     faacEncSetConfiguration(context->faac, cfg);  | 
1554  |  |   }  | 
1555  |  |  | 
1556  |  | #endif  | 
1557  |  | #if defined(WITH_SOXR)  | 
1558  |  |   { | 
1559  |  |     soxr_io_spec_t iospec = soxr_io_spec(SOXR_INT16, SOXR_INT16);  | 
1560  |  |     soxr_error_t error;  | 
1561  |  |     soxr_delete(context->sox);  | 
1562  |  |     context->sox =  | 
1563  |  |         soxr_create(context->common.format.nSamplesPerSec, targetFormat->nSamplesPerSec,  | 
1564  |  |                     targetFormat->nChannels, &error, &iospec, NULL, NULL);  | 
1565  |  |  | 
1566  |  |     if (!context->sox || (error != 0))  | 
1567  |  |       return FALSE;  | 
1568  |  |   }  | 
1569  |  | #endif  | 
1570  | 0  |   return TRUE;  | 
1571  | 0  | #endif  | 
1572  | 0  | }  | 
1573  |  |  | 
1574  |  | BOOL freerdp_dsp_common_context_init(FREERDP_DSP_COMMON_CONTEXT* context, BOOL encode)  | 
1575  | 0  | { | 
1576  | 0  |   WINPR_ASSERT(context);  | 
1577  | 0  |   context->encoder = encode;  | 
1578  | 0  |   context->buffer = Stream_New(NULL, 1024);  | 
1579  | 0  |   if (!context->buffer)  | 
1580  | 0  |     goto fail;  | 
1581  |  |  | 
1582  | 0  |   context->channelmix = Stream_New(NULL, 1024);  | 
1583  | 0  |   if (!context->channelmix)  | 
1584  | 0  |     goto fail;  | 
1585  |  |  | 
1586  | 0  |   context->resample = Stream_New(NULL, 1024);  | 
1587  | 0  |   if (!context->resample)  | 
1588  | 0  |     goto fail;  | 
1589  |  |  | 
1590  | 0  |   return TRUE;  | 
1591  |  |  | 
1592  | 0  | fail:  | 
1593  | 0  |   freerdp_dsp_common_context_uninit(context);  | 
1594  | 0  |   return FALSE;  | 
1595  | 0  | }  | 
1596  |  |  | 
1597  |  | void freerdp_dsp_common_context_uninit(FREERDP_DSP_COMMON_CONTEXT* context)  | 
1598  | 0  | { | 
1599  | 0  |   WINPR_ASSERT(context);  | 
1600  |  |  | 
1601  | 0  |   Stream_Free(context->buffer, TRUE);  | 
1602  | 0  |   Stream_Free(context->channelmix, TRUE);  | 
1603  | 0  |   Stream_Free(context->resample, TRUE);  | 
1604  |  | 
  | 
1605  | 0  |   context->buffer = NULL;  | 
1606  | 0  |   context->channelmix = NULL;  | 
1607  | 0  |   context->resample = NULL;  | 
1608  | 0  | }  |