/[rdesktop]/jpeg/rdesktop/trunk/rdpsnd_dsp.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /jpeg/rdesktop/trunk/rdpsnd_dsp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1507 - (hide annotations)
Mon Jul 20 16:45:11 2009 UTC (14 years, 10 months ago) by dpavlin
File MIME type: text/plain
File size: 10639 byte(s)
branch for integration of Daniel Jarboe <daniel.jarboe(at)gmail.com>
patches for jpeg
1 stargo 1258 /*
2     rdesktop: A Remote Desktop Protocol client.
3     Sound DSP routines
4 jsorg71 1475 Copyright (C) Michael Gernoth 2006-2008
5 stargo 1258
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 stargo 1285 #include <strings.h>
22    
23 stargo 1258 #include "rdesktop.h"
24     #include "rdpsnd.h"
25     #include "rdpsnd_dsp.h"
26    
27 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
28     #include <samplerate.h>
29    
30     #define SRC_CONVERTER SRC_SINC_MEDIUM_QUALITY
31     #endif
32    
33 stargo 1258 #define MAX_VOLUME 65535
34    
35     static uint16 softvol_left = MAX_VOLUME;
36     static uint16 softvol_right = MAX_VOLUME;
37 stargo 1276 static uint32 resample_to_srate = 44100;
38     static uint16 resample_to_bitspersample = 16;
39     static uint16 resample_to_channels = 2;
40 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
41     static SRC_STATE *src_converter = NULL;
42     #endif
43 stargo 1258
44     void
45     rdpsnd_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    
52 stargo 1260 void
53 jsorg71 1364 rdpsnd_dsp_softvol(unsigned char *buffer, unsigned int size, RD_WAVEFORMATEX * format)
54 stargo 1258 {
55     unsigned int factor_left, factor_right;
56 stargo 1259 unsigned char *posin = buffer;
57     unsigned char *posout = buffer;
58 stargo 1258
59 stargo 1259 if ((softvol_left == MAX_VOLUME) && (softvol_right == MAX_VOLUME))
60     return;
61    
62 stargo 1270 factor_left = (softvol_left * 256) / MAX_VOLUME;
63     factor_right = (softvol_right * 256) / MAX_VOLUME;
64 stargo 1258
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 stargo 1262 sint8 val;
73 stargo 1258
74 stargo 1259 while (posout < buffer + size)
75 stargo 1258 {
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 stargo 1262 sint16 val;
90 stargo 1258
91 stargo 1259 while (posout < buffer + size)
92 stargo 1258 {
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 stargo 1263 DEBUG(("using softvol with factors left: %d, right: %d (%d/%d)\n", factor_left,
110     factor_right, format->wBitsPerSample, format->nChannels));
111 stargo 1258 }
112    
113 stargo 1260 void
114 jsorg71 1364 rdpsnd_dsp_swapbytes(unsigned char *buffer, unsigned int size, RD_WAVEFORMATEX * format)
115 stargo 1260 {
116     int i;
117     uint8 swap;
118    
119     if (format->wBitsPerSample == 8)
120     return;
121    
122 ossman_ 1431 if (size & 0x1)
123     warning("badly aligned sound data");
124    
125 jsorg71 1394 for (i = 0; i < (int) size; i += 2)
126 stargo 1260 {
127     swap = *(buffer + i);
128     *(buffer + i) = *(buffer + i + 1);
129     *(buffer + i + 1) = swap;
130     }
131     }
132    
133 jsorg71 1372 RD_BOOL
134 stargo 1276 rdpsnd_dsp_resample_set(uint32 device_srate, uint16 device_bitspersample, uint16 device_channels)
135     {
136 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
137     int err;
138     #endif
139    
140 stargo 1276 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 stargo 1278 #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 stargo 1276 return True;
162     }
163    
164 jsorg71 1372 RD_BOOL
165 jsorg71 1364 rdpsnd_dsp_resample_supported(RD_WAVEFORMATEX * format)
166 stargo 1276 {
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    
177     uint32
178     rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
179 jsorg71 1372 RD_WAVEFORMATEX * format, RD_BOOL stream_be)
180 stargo 1276 {
181 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
182     SRC_DATA resample_data;
183     float *infloat, *outfloat;
184 stargo 1282 int err;
185 stargo 1278 #else
186 stargo 1283 int ratio1k = (resample_to_srate * 1000) / format->nSamplesPerSec;
187 stargo 1278 #endif
188 stargo 1283 int innum, outnum;
189 stargo 1288 unsigned char *tmpdata = NULL, *tmp = NULL;
190 stargo 1276 int samplewidth = format->wBitsPerSample / 8;
191 stargo 1278 int outsize = 0;
192 stargo 1281 int i;
193 stargo 1276
194 stargo 1277 if ((resample_to_bitspersample == format->wBitsPerSample) &&
195     (resample_to_channels == format->nChannels) &&
196     (resample_to_srate == format->nSamplesPerSec))
197     return 0;
198    
199 stargo 1278 #ifdef B_ENDIAN
200     if (!stream_be)
201 stargo 1281 rdpsnd_dsp_swapbytes(in, size, format);
202 stargo 1278 #endif
203 stargo 1281
204 stargo 1288 if (resample_to_channels != format->nChannels)
205     {
206     int newsize = (size / format->nChannels) * resample_to_channels;
207 jsorg71 1394 tmpdata = (unsigned char *) xmalloc(newsize);
208 stargo 1288
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 stargo 1281 /* 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 stargo 1278 {
237 stargo 1288 tmp = tmpdata;
238 jsorg71 1394 tmpdata = (unsigned char *) xmalloc(size * 2);
239     for (i = 0; i < (int) size; i++)
240 stargo 1281 {
241     tmpdata[i * 2] = in[i];
242     tmpdata[(i * 2) + 1] = 0x00;
243     }
244     in = tmpdata;
245     samplewidth = 16 / 2;
246     size *= 2;
247 stargo 1288
248     if (tmp != NULL)
249     xfree(tmp);
250 stargo 1278 }
251 stargo 1281 }
252 stargo 1278
253 stargo 1283 innum = size / samplewidth;
254    
255 stargo 1281 /* Do the resampling */
256 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
257     if (src_converter == NULL)
258 stargo 1276 {
259 stargo 1278 warning("no samplerate converter available!!\n");
260     return 0;
261     }
262    
263 stargo 1283 outnum = ((float) innum * ((float) resample_to_srate / (float) format->nSamplesPerSec)) + 1;
264 stargo 1278
265 jsorg71 1394 infloat = (float *) xmalloc(sizeof(float) * innum);
266     outfloat = (float *) xmalloc(sizeof(float) * outnum);
267 stargo 1278
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 stargo 1282 if ((err = src_process(src_converter, &resample_data)) != 0)
279     error("src_process: %s", src_strerror(err));
280    
281 stargo 1278 xfree(infloat);
282    
283 stargo 1282 outsize = resample_data.output_frames_gen * resample_to_channels * samplewidth;
284 jsorg71 1394 *out = (unsigned char *) xmalloc(outsize);
285 stargo 1283 src_float_to_short_array(outfloat, (short *) *out,
286     resample_data.output_frames_gen * resample_to_channels);
287 stargo 1278 xfree(outfloat);
288    
289     #else
290 stargo 1283 /* Michaels simple linear resampler */
291     if (resample_to_srate < format->nSamplesPerSec)
292 stargo 1278 {
293 stargo 1283 warning("downsampling currently not supported!\n");
294 stargo 1276 return 0;
295     }
296    
297 stargo 1283 outnum = (innum * ratio1k) / 1000;
298    
299     outsize = outnum * samplewidth;
300 jsorg71 1394 *out = (unsigned char *) xmalloc(outsize);
301 stargo 1283 bzero(*out, outsize);
302 stargo 1277
303 stargo 1283 for (i = 0; i < outsize / (resample_to_channels * samplewidth); i++)
304 stargo 1276 {
305 stargo 1291 int source = (i * 1000) / ratio1k;
306 stargo 1292 #if 0 /* Partial for linear resampler */
307     int part = (i * 100000) / ratio1k - source * 100;
308     #endif
309 stargo 1287 int j;
310 stargo 1283
311 jsorg71 1394 if (source * resample_to_channels + samplewidth > (int) size)
312 stargo 1283 break;
313    
314 stargo 1303 #if 0 /* Linear resampling, TODO: soundquality fixes (LP filter) */
315 stargo 1292 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 astrand 1305 cval1 += (sint8) (cval2 * part) / 100;
328 stargo 1292
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 astrand 1305 sval1 += (sint16) (sval2 * part) / 100;
346 stargo 1292
347     memcpy(*out + (i * resample_to_channels * samplewidth) +
348     (samplewidth * j), &sval1, samplewidth);
349     }
350     }
351     #else /* Nearest neighbor search */
352 stargo 1287 for (j = 0; j < resample_to_channels; j++)
353 stargo 1283 {
354 stargo 1287 memcpy(*out + (i * resample_to_channels * samplewidth) + (samplewidth * j),
355 stargo 1288 in + (source * resample_to_channels * samplewidth) +
356     (samplewidth * j), samplewidth);
357 stargo 1283 }
358 stargo 1292 #endif
359 stargo 1276 }
360 stargo 1283 outsize = i * resample_to_channels * samplewidth;
361 stargo 1278 #endif
362 stargo 1276
363 stargo 1281 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 stargo 1278 #ifdef B_ENDIAN
383     if (!stream_be)
384 stargo 1281 rdpsnd_dsp_swapbytes(*out, outsize, format);
385 stargo 1278 #endif
386 stargo 1281 return outsize;
387 stargo 1276 }
388    
389 stargo 1263 STREAM
390 ossman_ 1342 rdpsnd_dsp_process(unsigned char *data, unsigned int size, struct audio_driver * current_driver,
391 jsorg71 1364 RD_WAVEFORMATEX * format)
392 stargo 1258 {
393 stargo 1263 static struct stream out;
394 jsorg71 1372 RD_BOOL stream_be = False;
395 stargo 1258
396 stargo 1263 /* softvol and byteswap do not change the amount of data they
397     return, so they can operate on the input-stream */
398 stargo 1258 if (current_driver->wave_out_volume == rdpsnd_dsp_softvol_set)
399 ossman_ 1342 rdpsnd_dsp_softvol(data, size, format);
400 stargo 1258
401 stargo 1260 #ifdef B_ENDIAN
402     if (current_driver->need_byteswap_on_be)
403 stargo 1278 {
404 ossman_ 1342 rdpsnd_dsp_swapbytes(data, size, format);
405 stargo 1278 stream_be = True;
406     }
407 stargo 1260 #endif
408    
409 stargo 1276 out.data = NULL;
410 stargo 1263
411 stargo 1279 if (current_driver->need_resampling)
412 ossman_ 1342 out.size = rdpsnd_dsp_resample(&out.data, data, size, format, stream_be);
413 stargo 1263
414 stargo 1276 if (out.data == NULL)
415     {
416 jsorg71 1394 out.data = (unsigned char *) xmalloc(size);
417 ossman_ 1342 memcpy(out.data, data, size);
418     out.size = size;
419 stargo 1276 }
420    
421 stargo 1263 out.p = out.data;
422     out.end = out.p + out.size;
423    
424     return &out;
425 stargo 1258 }

  ViewVC Help
Powered by ViewVC 1.1.26