/[rdesktop]/sourceforge.net/trunk/rdesktop/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 /sourceforge.net/trunk/rdesktop/rdpsnd_dsp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1284 - (hide annotations)
Sun Oct 1 17:51:51 2006 UTC (17 years, 9 months ago) by stargo
File MIME type: text/plain
File size: 8984 byte(s)
sound quality fixes for resampling

1 stargo 1258 /*
2     rdesktop: A Remote Desktop Protocol client.
3     Sound DSP routines
4     Copyright (C) Michael Gernoth 2006
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 "rdesktop.h"
22     #include "rdpsnd.h"
23     #include "rdpsnd_dsp.h"
24    
25 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
26     #include <samplerate.h>
27    
28     #define SRC_CONVERTER SRC_SINC_MEDIUM_QUALITY
29     #endif
30    
31 stargo 1258 #define MAX_VOLUME 65535
32    
33     static uint16 softvol_left = MAX_VOLUME;
34     static uint16 softvol_right = MAX_VOLUME;
35 stargo 1276 static uint32 resample_to_srate = 44100;
36     static uint16 resample_to_bitspersample = 16;
37     static uint16 resample_to_channels = 2;
38 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
39     static SRC_STATE *src_converter = NULL;
40     #endif
41 stargo 1258
42     void
43     rdpsnd_dsp_softvol_set(uint16 left, uint16 right)
44     {
45     softvol_left = left;
46     softvol_right = right;
47     DEBUG(("rdpsnd_dsp_softvol_set: left: %u, right: %u\n", left, right));
48     }
49    
50 stargo 1260 void
51 stargo 1259 rdpsnd_dsp_softvol(unsigned char *buffer, unsigned int size, WAVEFORMATEX * format)
52 stargo 1258 {
53     unsigned int factor_left, factor_right;
54 stargo 1259 unsigned char *posin = buffer;
55     unsigned char *posout = buffer;
56 stargo 1258
57 stargo 1259 if ((softvol_left == MAX_VOLUME) && (softvol_right == MAX_VOLUME))
58     return;
59    
60 stargo 1270 factor_left = (softvol_left * 256) / MAX_VOLUME;
61     factor_right = (softvol_right * 256) / MAX_VOLUME;
62 stargo 1258
63     if (format->nChannels == 1)
64     {
65     factor_left = factor_right = (factor_left + factor_right) / 2;
66     }
67    
68     if (format->wBitsPerSample == 8)
69     {
70 stargo 1262 sint8 val;
71 stargo 1258
72 stargo 1259 while (posout < buffer + size)
73 stargo 1258 {
74     /* Left */
75     val = *posin++;
76     val = (val * factor_left) >> 8;
77     *posout++ = val;
78    
79     /* Right */
80     val = *posin++;
81     val = (val * factor_right) >> 8;
82     *posout++ = val;
83     }
84     }
85     else
86     {
87 stargo 1262 sint16 val;
88 stargo 1258
89 stargo 1259 while (posout < buffer + size)
90 stargo 1258 {
91     /* Left */
92     val = *posin++;
93     val |= *posin++ << 8;
94     val = (val * factor_left) >> 8;
95     *posout++ = val & 0xff;
96     *posout++ = val >> 8;
97    
98     /* Right */
99     val = *posin++;
100     val |= *posin++ << 8;
101     val = (val * factor_right) >> 8;
102     *posout++ = val & 0xff;
103     *posout++ = val >> 8;
104     }
105     }
106    
107 stargo 1263 DEBUG(("using softvol with factors left: %d, right: %d (%d/%d)\n", factor_left,
108     factor_right, format->wBitsPerSample, format->nChannels));
109 stargo 1258 }
110    
111 stargo 1260 void
112     rdpsnd_dsp_swapbytes(unsigned char *buffer, unsigned int size, WAVEFORMATEX * format)
113     {
114     int i;
115     uint8 swap;
116    
117     if (format->wBitsPerSample == 8)
118     return;
119    
120     for (i = 0; i < size; i += 2)
121     {
122     swap = *(buffer + i);
123     *(buffer + i) = *(buffer + i + 1);
124     *(buffer + i + 1) = swap;
125     }
126     }
127    
128 stargo 1276 BOOL
129     rdpsnd_dsp_resample_set(uint32 device_srate, uint16 device_bitspersample, uint16 device_channels)
130     {
131 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
132     int err;
133     #endif
134    
135 stargo 1276 if (device_bitspersample != 16 && device_bitspersample != 8)
136     return False;
137    
138     if (device_channels != 1 && device_channels != 2)
139     return False;
140    
141     resample_to_srate = device_srate;
142     resample_to_bitspersample = device_bitspersample;
143     resample_to_channels = device_channels;
144    
145 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
146     if (src_converter != NULL)
147     src_converter = src_delete(src_converter);
148    
149     if ((src_converter = src_new(SRC_CONVERTER, device_channels, &err)) == NULL)
150     {
151     warning("src_new failed: %d!\n", err);
152     return False;
153     }
154     #endif
155    
156 stargo 1276 return True;
157     }
158    
159     BOOL
160     rdpsnd_dsp_resample_supported(WAVEFORMATEX * format)
161     {
162     if (format->wFormatTag != WAVE_FORMAT_PCM)
163     return False;
164     if ((format->nChannels != 1) && (format->nChannels != 2))
165     return False;
166     if ((format->wBitsPerSample != 8) && (format->wBitsPerSample != 16))
167     return False;
168    
169     return True;
170     }
171    
172     uint32
173     rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
174 stargo 1278 WAVEFORMATEX * format, BOOL stream_be)
175 stargo 1276 {
176 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
177     SRC_DATA resample_data;
178     float *infloat, *outfloat;
179 stargo 1282 int err;
180 stargo 1278 #else
181 stargo 1283 int ratio1k = (resample_to_srate * 1000) / format->nSamplesPerSec;
182 stargo 1278 #endif
183 stargo 1283 int innum, outnum;
184 stargo 1276 static BOOL warned = False;
185 stargo 1281 unsigned char *tmpdata = NULL;
186 stargo 1276 int samplewidth = format->wBitsPerSample / 8;
187 stargo 1278 int outsize = 0;
188 stargo 1281 int i;
189 stargo 1276
190 stargo 1277 if ((resample_to_bitspersample == format->wBitsPerSample) &&
191     (resample_to_channels == format->nChannels) &&
192     (resample_to_srate == format->nSamplesPerSec))
193     return 0;
194    
195 stargo 1278 #ifdef B_ENDIAN
196     if (!stream_be)
197 stargo 1281 rdpsnd_dsp_swapbytes(in, size, format);
198 stargo 1278 #endif
199 stargo 1281
200     /* Expand 8bit input-samples to 16bit */
201     #ifndef HAVE_LIBSAMPLERATE /* libsamplerate needs 16bit samples */
202     if (format->wBitsPerSample != resample_to_bitspersample)
203     #endif
204     {
205     /* source: 8 bit, dest: 16bit */
206     if (format->wBitsPerSample == 8)
207 stargo 1278 {
208 stargo 1281 tmpdata = xmalloc(size * 2);
209     for (i = 0; i < size; i++)
210     {
211     tmpdata[i * 2] = in[i];
212     tmpdata[(i * 2) + 1] = 0x00;
213     }
214     in = tmpdata;
215     samplewidth = 16 / 2;
216     size *= 2;
217 stargo 1278 }
218 stargo 1281 }
219 stargo 1278
220 stargo 1281 if (resample_to_channels != format->nChannels)
221     {
222     warning("unsupported resample-settings (%u -> %u/%u -> %u/%u -> %u), not resampling!\n", format->nSamplesPerSec, resample_to_srate, format->wBitsPerSample, resample_to_bitspersample, format->nChannels, resample_to_channels);
223     warned = True;
224     }
225    
226 stargo 1283 innum = size / samplewidth;
227    
228 stargo 1281 /* Do the resampling */
229 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
230     if (src_converter == NULL)
231 stargo 1276 {
232 stargo 1278 warning("no samplerate converter available!!\n");
233     return 0;
234     }
235    
236 stargo 1283 outnum = ((float) innum * ((float) resample_to_srate / (float) format->nSamplesPerSec)) + 1;
237 stargo 1278
238     infloat = xmalloc(sizeof(float) * innum);
239     outfloat = xmalloc(sizeof(float) * outnum);
240    
241     src_short_to_float_array((short *) in, infloat, innum);
242    
243     bzero(&resample_data, sizeof(resample_data));
244     resample_data.data_in = infloat;
245     resample_data.data_out = outfloat;
246     resample_data.input_frames = innum / resample_to_channels;
247     resample_data.output_frames = outnum / resample_to_channels;
248     resample_data.src_ratio = (double) resample_to_srate / (double) format->nSamplesPerSec;
249     resample_data.end_of_input = 0;
250    
251 stargo 1282 if ((err = src_process(src_converter, &resample_data)) != 0)
252     error("src_process: %s", src_strerror(err));
253    
254 stargo 1278 xfree(infloat);
255    
256 stargo 1282 outsize = resample_data.output_frames_gen * resample_to_channels * samplewidth;
257 stargo 1278 *out = xmalloc(outsize);
258 stargo 1283 src_float_to_short_array(outfloat, (short *) *out,
259     resample_data.output_frames_gen * resample_to_channels);
260 stargo 1278 xfree(outfloat);
261    
262     #else
263 stargo 1283 /* Michaels simple linear resampler */
264     if (resample_to_srate < format->nSamplesPerSec)
265 stargo 1278 {
266 stargo 1283 warning("downsampling currently not supported!\n");
267 stargo 1276 return 0;
268     }
269    
270 stargo 1283 outnum = (innum * ratio1k) / 1000;
271    
272     outsize = outnum * samplewidth;
273 stargo 1277 *out = xmalloc(outsize);
274 stargo 1283 bzero(*out, outsize);
275 stargo 1277
276 stargo 1283 for (i = 0; i < outsize / (resample_to_channels * samplewidth); i++)
277 stargo 1276 {
278 stargo 1284 int source = ((i * 1000) + ratio1k - 1000) / (ratio1k + 1);
279 stargo 1283
280     if (source * resample_to_channels + samplewidth > size)
281     break;
282    
283 stargo 1277 if (resample_to_channels == 2)
284 stargo 1283 {
285     memcpy(*out + (i * resample_to_channels * samplewidth),
286     in + (source * resample_to_channels * samplewidth), samplewidth);
287     memcpy(*out + (i * resample_to_channels * samplewidth) + samplewidth,
288     in + (source * resample_to_channels * samplewidth) + samplewidth,
289     samplewidth);
290     }
291 stargo 1277 else
292 stargo 1283 {
293     memcpy(*out + (i * samplewidth), in + (source * samplewidth), samplewidth);
294     }
295 stargo 1276 }
296 stargo 1283 outsize = i * resample_to_channels * samplewidth;
297 stargo 1278 #endif
298 stargo 1276
299 stargo 1281 if (tmpdata != NULL)
300     xfree(tmpdata);
301    
302     /* Shrink 16bit output-samples to 8bit */
303     #ifndef HAVE_LIBSAMPLERATE /* libsamplerate produces 16bit samples */
304     if (format->wBitsPerSample != resample_to_bitspersample)
305     #endif
306     {
307     /* source: 16 bit, dest: 8 bit */
308     if (resample_to_bitspersample == 8)
309     {
310     for (i = 0; i < outsize; i++)
311     {
312     *out[i] = *out[i * 2];
313     }
314     outsize /= 2;
315     }
316     }
317    
318 stargo 1278 #ifdef B_ENDIAN
319     if (!stream_be)
320 stargo 1281 rdpsnd_dsp_swapbytes(*out, outsize, format);
321 stargo 1278 #endif
322 stargo 1281 return outsize;
323 stargo 1276 }
324    
325 stargo 1263 STREAM
326 stargo 1276 rdpsnd_dsp_process(STREAM s, struct audio_driver * current_driver, WAVEFORMATEX * format)
327 stargo 1258 {
328 stargo 1263 static struct stream out;
329 stargo 1278 BOOL stream_be = False;
330 stargo 1258
331 stargo 1263 /* softvol and byteswap do not change the amount of data they
332     return, so they can operate on the input-stream */
333 stargo 1258 if (current_driver->wave_out_volume == rdpsnd_dsp_softvol_set)
334 stargo 1263 rdpsnd_dsp_softvol(s->data, s->size, format);
335 stargo 1258
336 stargo 1260 #ifdef B_ENDIAN
337     if (current_driver->need_byteswap_on_be)
338 stargo 1278 {
339 stargo 1263 rdpsnd_dsp_swapbytes(s->data, s->size, format);
340 stargo 1278 stream_be = True;
341     }
342 stargo 1260 #endif
343    
344 stargo 1276 out.data = NULL;
345 stargo 1263
346 stargo 1279 if (current_driver->need_resampling)
347 stargo 1278 out.size = rdpsnd_dsp_resample(&out.data, s->data, s->size, format, stream_be);
348 stargo 1263
349 stargo 1276 if (out.data == NULL)
350     {
351     out.data = xmalloc(s->size);
352     memcpy(out.data, s->data, s->size);
353     out.size = s->size;
354     }
355    
356 stargo 1263 out.p = out.data;
357     out.end = out.p + out.size;
358    
359     return &out;
360 stargo 1258 }

  ViewVC Help
Powered by ViewVC 1.1.26