/[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 1282 - (hide annotations)
Sun Oct 1 15:07:55 2006 UTC (17 years, 8 months ago) by stargo
File MIME type: text/plain
File size: 9082 byte(s)
fix conversion between arbitrary samplerates

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 1281 #ifndef HAVE_LIBSAMPLERATE
136 stargo 1276 if (device_srate != 44100 && device_srate != 22050)
137     return False;
138 stargo 1281 #endif
139 stargo 1263
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     BOOL
165     rdpsnd_dsp_resample_supported(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 stargo 1281 #ifndef HAVE_LIBSAMPLERATE
174 stargo 1276 if ((format->nSamplesPerSec != 44100) && (format->nSamplesPerSec != 22050))
175     return False;
176 stargo 1278 #endif
177 stargo 1276
178     return True;
179     }
180    
181     uint32
182     rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
183 stargo 1278 WAVEFORMATEX * format, BOOL stream_be)
184 stargo 1276 {
185 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
186     SRC_DATA resample_data;
187     float *infloat, *outfloat;
188     int innum, outnum;
189 stargo 1282 int err;
190 stargo 1278 #else
191     int offset;
192     #endif
193 stargo 1276 static BOOL warned = False;
194 stargo 1281 unsigned char *tmpdata = NULL;
195 stargo 1276 int samplewidth = format->wBitsPerSample / 8;
196 stargo 1278 int outsize = 0;
197 stargo 1281 int i;
198 stargo 1276
199 stargo 1277 if ((resample_to_bitspersample == format->wBitsPerSample) &&
200     (resample_to_channels == format->nChannels) &&
201     (resample_to_srate == format->nSamplesPerSec))
202     return 0;
203    
204 stargo 1278 #ifdef B_ENDIAN
205     if (!stream_be)
206 stargo 1281 rdpsnd_dsp_swapbytes(in, size, format);
207 stargo 1278 #endif
208 stargo 1281
209     /* Expand 8bit input-samples to 16bit */
210     #ifndef HAVE_LIBSAMPLERATE /* libsamplerate needs 16bit samples */
211     if (format->wBitsPerSample != resample_to_bitspersample)
212     #endif
213     {
214     /* source: 8 bit, dest: 16bit */
215     if (format->wBitsPerSample == 8)
216 stargo 1278 {
217 stargo 1281 tmpdata = xmalloc(size * 2);
218     for (i = 0; i < size; i++)
219     {
220     tmpdata[i * 2] = in[i];
221     tmpdata[(i * 2) + 1] = 0x00;
222     }
223     in = tmpdata;
224     samplewidth = 16 / 2;
225     size *= 2;
226 stargo 1278 }
227 stargo 1281 }
228 stargo 1278
229 stargo 1281 if (resample_to_channels != format->nChannels)
230     {
231     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);
232     warned = True;
233     }
234    
235     /* Do the resampling */
236 stargo 1278 #ifdef HAVE_LIBSAMPLERATE
237     if (src_converter == NULL)
238 stargo 1276 {
239 stargo 1278 warning("no samplerate converter available!!\n");
240     return 0;
241     }
242    
243     innum = size / samplewidth;
244 stargo 1282 outnum = ((float)innum * ((float)resample_to_srate / (float)format->nSamplesPerSec)) + 1;
245 stargo 1278
246     infloat = xmalloc(sizeof(float) * innum);
247     outfloat = xmalloc(sizeof(float) * outnum);
248    
249     src_short_to_float_array((short *) in, infloat, innum);
250    
251     bzero(&resample_data, sizeof(resample_data));
252     resample_data.data_in = infloat;
253     resample_data.data_out = outfloat;
254     resample_data.input_frames = innum / resample_to_channels;
255     resample_data.output_frames = outnum / resample_to_channels;
256     resample_data.src_ratio = (double) resample_to_srate / (double) format->nSamplesPerSec;
257     resample_data.end_of_input = 0;
258    
259 stargo 1282 if ((err = src_process(src_converter, &resample_data)) != 0)
260     error("src_process: %s", src_strerror(err));
261    
262 stargo 1278 xfree(infloat);
263    
264 stargo 1282 outsize = resample_data.output_frames_gen * resample_to_channels * samplewidth;
265 stargo 1278 *out = xmalloc(outsize);
266 stargo 1282 src_float_to_short_array(outfloat, (short *) *out, resample_data.output_frames_gen * resample_to_channels);
267 stargo 1278 xfree(outfloat);
268    
269     #else
270     if (format->nSamplesPerSec != 22050)
271     {
272 stargo 1276 if (!warned)
273     {
274 stargo 1278 warning("unsupported source samplerate (%u), not resampling!\n",
275     format->nSamplesPerSec);
276 stargo 1276 warned = True;
277     }
278     return 0;
279     }
280    
281 stargo 1277 outsize = size * 2;
282     *out = xmalloc(outsize);
283    
284     /* Resample from 22050 to 44100 */
285     for (i = 0; i < (size / samplewidth); i++)
286 stargo 1276 {
287 stargo 1277 /* On a stereo-channel we must make sure that left and right
288     does not get mixed up, so we need to expand the sample-
289     data with channels in mind: 1234 -> 12123434
290     If we have a mono-channel, we can expand the data by simply
291     doubling the sample-data: 1234 -> 11223344 */
292     if (resample_to_channels == 2)
293     offset = ((i * 2) - (i & 1)) * samplewidth;
294     else
295     offset = (i * 2) * samplewidth;
296 stargo 1276
297 stargo 1277 memcpy(*out + offset, in + (i * samplewidth), samplewidth);
298     memcpy(*out + (resample_to_channels * samplewidth + offset),
299     in + (i * samplewidth), samplewidth);
300 stargo 1276
301     }
302 stargo 1278 #endif
303 stargo 1276
304 stargo 1281 if (tmpdata != NULL)
305     xfree(tmpdata);
306    
307     /* Shrink 16bit output-samples to 8bit */
308     #ifndef HAVE_LIBSAMPLERATE /* libsamplerate produces 16bit samples */
309     if (format->wBitsPerSample != resample_to_bitspersample)
310     #endif
311     {
312     /* source: 16 bit, dest: 8 bit */
313     if (resample_to_bitspersample == 8)
314     {
315     for (i = 0; i < outsize; i++)
316     {
317     *out[i] = *out[i * 2];
318     }
319     outsize /= 2;
320     }
321     }
322    
323 stargo 1278 #ifdef B_ENDIAN
324     if (!stream_be)
325 stargo 1281 rdpsnd_dsp_swapbytes(*out, outsize, format);
326 stargo 1278 #endif
327 stargo 1281 return outsize;
328 stargo 1276 }
329    
330 stargo 1263 STREAM
331 stargo 1276 rdpsnd_dsp_process(STREAM s, struct audio_driver * current_driver, WAVEFORMATEX * format)
332 stargo 1258 {
333 stargo 1263 static struct stream out;
334 stargo 1278 BOOL stream_be = False;
335 stargo 1258
336 stargo 1263 /* softvol and byteswap do not change the amount of data they
337     return, so they can operate on the input-stream */
338 stargo 1258 if (current_driver->wave_out_volume == rdpsnd_dsp_softvol_set)
339 stargo 1263 rdpsnd_dsp_softvol(s->data, s->size, format);
340 stargo 1258
341 stargo 1260 #ifdef B_ENDIAN
342     if (current_driver->need_byteswap_on_be)
343 stargo 1278 {
344 stargo 1263 rdpsnd_dsp_swapbytes(s->data, s->size, format);
345 stargo 1278 stream_be = True;
346     }
347 stargo 1260 #endif
348    
349 stargo 1276 out.data = NULL;
350 stargo 1263
351 stargo 1279 if (current_driver->need_resampling)
352 stargo 1278 out.size = rdpsnd_dsp_resample(&out.data, s->data, s->size, format, stream_be);
353 stargo 1263
354 stargo 1276 if (out.data == NULL)
355     {
356     out.data = xmalloc(s->size);
357     memcpy(out.data, s->data, s->size);
358     out.size = s->size;
359     }
360    
361 stargo 1263 out.p = out.data;
362     out.end = out.p + out.size;
363    
364     return &out;
365 stargo 1258 }

  ViewVC Help
Powered by ViewVC 1.1.26