VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.3/rdpsnd_dsp.c@ 55121

Last change on this file since 55121 was 55121, checked in by vboxsync, 9 years ago

rdesktop 1.8.3 unmodified

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.4 KB
Line 
1/*
2 rdesktop: A Remote Desktop Protocol client.
3 Sound DSP routines
4 Copyright (C) Michael Gernoth <mike@zerfleddert.de> 2006-2008
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include <strings.h>
21
22#include "rdesktop.h"
23#include "rdpsnd.h"
24#include "rdpsnd_dsp.h"
25
26#ifdef HAVE_LIBSAMPLERATE
27#include <samplerate.h>
28
29#define SRC_CONVERTER SRC_SINC_MEDIUM_QUALITY
30#endif
31
32#define MAX_VOLUME 65535
33
34static uint16 softvol_left = MAX_VOLUME;
35static uint16 softvol_right = MAX_VOLUME;
36static uint32 resample_to_srate = 44100;
37static uint16 resample_to_bitspersample = 16;
38static uint16 resample_to_channels = 2;
39#ifdef HAVE_LIBSAMPLERATE
40static SRC_STATE *src_converter = NULL;
41#endif
42
43void
44rdpsnd_dsp_softvol_set(uint16 left, uint16 right)
45{
46 softvol_left = left;
47 softvol_right = right;
48 DEBUG(("rdpsnd_dsp_softvol_set: left: %u, right: %u\n", left, right));
49}
50
51void
52rdpsnd_dsp_softvol(unsigned char *buffer, unsigned int size, RD_WAVEFORMATEX * format)
53{
54 unsigned int factor_left, factor_right;
55 unsigned char *posin = buffer;
56 unsigned char *posout = buffer;
57
58 if ((softvol_left == MAX_VOLUME) && (softvol_right == MAX_VOLUME))
59 return;
60
61 factor_left = (softvol_left * 256) / MAX_VOLUME;
62 factor_right = (softvol_right * 256) / MAX_VOLUME;
63
64 if (format->nChannels == 1)
65 {
66 factor_left = factor_right = (factor_left + factor_right) / 2;
67 }
68
69 if (format->wBitsPerSample == 8)
70 {
71 sint8 val;
72
73 while (posout < buffer + size)
74 {
75 /* Left */
76 val = *posin++;
77 val = (val * factor_left) >> 8;
78 *posout++ = val;
79
80 /* Right */
81 val = *posin++;
82 val = (val * factor_right) >> 8;
83 *posout++ = val;
84 }
85 }
86 else
87 {
88 sint16 val;
89
90 while (posout < buffer + size)
91 {
92 /* Left */
93 val = *posin++;
94 val |= *posin++ << 8;
95 val = (val * factor_left) >> 8;
96 *posout++ = val & 0xff;
97 *posout++ = val >> 8;
98
99 /* Right */
100 val = *posin++;
101 val |= *posin++ << 8;
102 val = (val * factor_right) >> 8;
103 *posout++ = val & 0xff;
104 *posout++ = val >> 8;
105 }
106 }
107
108 DEBUG(("using softvol with factors left: %d, right: %d (%d/%d)\n", factor_left,
109 factor_right, format->wBitsPerSample, format->nChannels));
110}
111
112void
113rdpsnd_dsp_swapbytes(unsigned char *buffer, unsigned int size, RD_WAVEFORMATEX * format)
114{
115 int i;
116 uint8 swap;
117
118 if (format->wBitsPerSample == 8)
119 return;
120
121 if (size & 0x1)
122 warning("badly aligned sound data");
123
124 for (i = 0; i < (int) size; i += 2)
125 {
126 swap = *(buffer + i);
127 *(buffer + i) = *(buffer + i + 1);
128 *(buffer + i + 1) = swap;
129 }
130}
131
132RD_BOOL
133rdpsnd_dsp_resample_set(uint32 device_srate, uint16 device_bitspersample, uint16 device_channels)
134{
135#ifdef HAVE_LIBSAMPLERATE
136 int err;
137#endif
138
139 if (device_bitspersample != 16 && device_bitspersample != 8)
140 return False;
141
142 if (device_channels != 1 && device_channels != 2)
143 return False;
144
145 resample_to_srate = device_srate;
146 resample_to_bitspersample = device_bitspersample;
147 resample_to_channels = device_channels;
148
149#ifdef HAVE_LIBSAMPLERATE
150 if (src_converter != NULL)
151 src_converter = src_delete(src_converter);
152
153 if ((src_converter = src_new(SRC_CONVERTER, device_channels, &err)) == NULL)
154 {
155 warning("src_new failed: %d!\n", err);
156 return False;
157 }
158#endif
159
160 return True;
161}
162
163RD_BOOL
164rdpsnd_dsp_resample_supported(RD_WAVEFORMATEX * format)
165{
166 if (format->wFormatTag != WAVE_FORMAT_PCM)
167 return False;
168 if ((format->nChannels != 1) && (format->nChannels != 2))
169 return False;
170 if ((format->wBitsPerSample != 8) && (format->wBitsPerSample != 16))
171 return False;
172
173 return True;
174}
175
176uint32
177rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
178 RD_WAVEFORMATEX * format, RD_BOOL stream_be)
179{
180#ifdef HAVE_LIBSAMPLERATE
181 SRC_DATA resample_data;
182 float *infloat, *outfloat;
183 int err;
184#else
185 int ratio1k = (resample_to_srate * 1000) / format->nSamplesPerSec;
186#endif
187 int innum, outnum;
188 unsigned char *tmpdata = NULL, *tmp = NULL;
189 int samplewidth = format->wBitsPerSample / 8;
190 int outsize = 0;
191 int i;
192
193 if ((resample_to_bitspersample == format->wBitsPerSample) &&
194 (resample_to_channels == format->nChannels) &&
195 (resample_to_srate == format->nSamplesPerSec))
196 return 0;
197
198#ifdef B_ENDIAN
199 if (!stream_be)
200 rdpsnd_dsp_swapbytes(in, size, format);
201#endif
202
203 if (resample_to_channels != format->nChannels)
204 {
205 int newsize = (size / format->nChannels) * resample_to_channels;
206 tmpdata = (unsigned char *) xmalloc(newsize);
207
208 for (i = 0; i < newsize / samplewidth; i++)
209 {
210 if (format->nChannels > resample_to_channels)
211 memcpy(tmpdata + (i * samplewidth),
212 in +
213 (((i * format->nChannels) / resample_to_channels) *
214 samplewidth), samplewidth);
215 else
216 memcpy(tmpdata + (i * samplewidth),
217 in +
218 (((i / resample_to_channels) * format->nChannels +
219 (i % format->nChannels)) * samplewidth), samplewidth);
220
221 }
222
223 in = tmpdata;
224 size = newsize;
225 }
226
227
228 /* Expand 8bit input-samples to 16bit */
229#ifndef HAVE_LIBSAMPLERATE /* libsamplerate needs 16bit samples */
230 if (format->wBitsPerSample != resample_to_bitspersample)
231#endif
232 {
233 /* source: 8 bit, dest: 16bit */
234 if (format->wBitsPerSample == 8)
235 {
236 tmp = tmpdata;
237 tmpdata = (unsigned char *) xmalloc(size * 2);
238 for (i = 0; i < (int) size; i++)
239 {
240 tmpdata[i * 2] = in[i];
241 tmpdata[(i * 2) + 1] = 0x00;
242 }
243 in = tmpdata;
244 samplewidth = 16 / 2;
245 size *= 2;
246
247 if (tmp != NULL)
248 xfree(tmp);
249 }
250 }
251
252 innum = size / samplewidth;
253
254 /* Do the resampling */
255#ifdef HAVE_LIBSAMPLERATE
256 if (src_converter == NULL)
257 {
258 warning("no samplerate converter available!\n");
259 return 0;
260 }
261
262 outnum = ((float) innum * ((float) resample_to_srate / (float) format->nSamplesPerSec)) + 1;
263
264 infloat = (float *) xmalloc(sizeof(float) * innum);
265 outfloat = (float *) xmalloc(sizeof(float) * outnum);
266
267 src_short_to_float_array((short *) in, infloat, innum);
268
269 bzero(&resample_data, sizeof(resample_data));
270 resample_data.data_in = infloat;
271 resample_data.data_out = outfloat;
272 resample_data.input_frames = innum / resample_to_channels;
273 resample_data.output_frames = outnum / resample_to_channels;
274 resample_data.src_ratio = (double) resample_to_srate / (double) format->nSamplesPerSec;
275 resample_data.end_of_input = 0;
276
277 if ((err = src_process(src_converter, &resample_data)) != 0)
278 error("src_process: %s", src_strerror(err));
279
280 xfree(infloat);
281
282 outsize = resample_data.output_frames_gen * resample_to_channels * samplewidth;
283 *out = (unsigned char *) xmalloc(outsize);
284 src_float_to_short_array(outfloat, (short *) *out,
285 resample_data.output_frames_gen * resample_to_channels);
286 xfree(outfloat);
287
288#else
289 /* Michaels simple linear resampler */
290 if (resample_to_srate < format->nSamplesPerSec)
291 {
292 warning("downsampling currently not supported!\n");
293 return 0;
294 }
295
296 outnum = (innum * ratio1k) / 1000;
297
298 outsize = outnum * samplewidth;
299 *out = (unsigned char *) xmalloc(outsize);
300 bzero(*out, outsize);
301
302 for (i = 0; i < outsize / (resample_to_channels * samplewidth); i++)
303 {
304 int source = (i * 1000) / ratio1k;
305#if 0 /* Partial for linear resampler */
306 int part = (i * 100000) / ratio1k - source * 100;
307#endif
308 int j;
309
310 if (source * resample_to_channels + samplewidth > (int) size)
311 break;
312
313#if 0 /* Linear resampling, TODO: soundquality fixes (LP filter) */
314 if (samplewidth == 1)
315 {
316 sint8 cval1, cval2;
317 for (j = 0; j < resample_to_channels; j++)
318 {
319 memcpy(&cval1,
320 in + (source * resample_to_channels * samplewidth) +
321 (samplewidth * j), samplewidth);
322 memcpy(&cval2,
323 in + ((source + 1) * resample_to_channels * samplewidth) +
324 (samplewidth * j), samplewidth);
325
326 cval1 += (sint8) (cval2 * part) / 100;
327
328 memcpy(*out + (i * resample_to_channels * samplewidth) +
329 (samplewidth * j), &cval1, samplewidth);
330 }
331 }
332 else
333 {
334 sint16 sval1, sval2;
335 for (j = 0; j < resample_to_channels; j++)
336 {
337 memcpy(&sval1,
338 in + (source * resample_to_channels * samplewidth) +
339 (samplewidth * j), samplewidth);
340 memcpy(&sval2,
341 in + ((source + 1) * resample_to_channels * samplewidth) +
342 (samplewidth * j), samplewidth);
343
344 sval1 += (sint16) (sval2 * part) / 100;
345
346 memcpy(*out + (i * resample_to_channels * samplewidth) +
347 (samplewidth * j), &sval1, samplewidth);
348 }
349 }
350#else /* Nearest neighbor search */
351 for (j = 0; j < resample_to_channels; j++)
352 {
353 memcpy(*out + (i * resample_to_channels * samplewidth) + (samplewidth * j),
354 in + (source * resample_to_channels * samplewidth) +
355 (samplewidth * j), samplewidth);
356 }
357#endif
358 }
359 outsize = i * resample_to_channels * samplewidth;
360#endif
361
362 if (tmpdata != NULL)
363 xfree(tmpdata);
364
365 /* Shrink 16bit output-samples to 8bit */
366#ifndef HAVE_LIBSAMPLERATE /* libsamplerate produces 16bit samples */
367 if (format->wBitsPerSample != resample_to_bitspersample)
368#endif
369 {
370 /* source: 16 bit, dest: 8 bit */
371 if (resample_to_bitspersample == 8)
372 {
373 for (i = 0; i < outsize; i++)
374 {
375 *out[i] = *out[i * 2];
376 }
377 outsize /= 2;
378 }
379 }
380
381#ifdef B_ENDIAN
382 if (!stream_be)
383 rdpsnd_dsp_swapbytes(*out, outsize, format);
384#endif
385 return outsize;
386}
387
388STREAM
389rdpsnd_dsp_process(unsigned char *data, unsigned int size, struct audio_driver * current_driver,
390 RD_WAVEFORMATEX * format)
391{
392 static struct stream out;
393 RD_BOOL stream_be = False;
394
395 /* softvol and byteswap do not change the amount of data they
396 return, so they can operate on the input-stream */
397 if (current_driver->wave_out_volume == rdpsnd_dsp_softvol_set)
398 rdpsnd_dsp_softvol(data, size, format);
399
400#ifdef B_ENDIAN
401 if (current_driver->need_byteswap_on_be)
402 {
403 rdpsnd_dsp_swapbytes(data, size, format);
404 stream_be = True;
405 }
406#endif
407
408 out.data = NULL;
409
410 if (current_driver->need_resampling)
411 out.size = rdpsnd_dsp_resample(&out.data, data, size, format, stream_be);
412
413 if (out.data == NULL)
414 {
415 out.data = (unsigned char *) xmalloc(size);
416 memcpy(out.data, data, size);
417 out.size = size;
418 }
419
420 out.p = out.data;
421 out.end = out.p + out.size;
422
423 return &out;
424}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette