VirtualBox

source: vbox/trunk/src/VBox/RDP/client/rdpsnd_dsp.c@ 10076

Last change on this file since 10076 was 9902, checked in by vboxsync, 16 years ago

Added rdesktop 1.6.0.

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