/[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 1281 - (hide annotations)
Sun Oct 1 14:31:09 2006 UTC (17 years, 8 months ago) by stargo
File MIME type: text/plain
File size: 8884 byte(s)
make it possible to resample 8bit<->16bit soundstreams

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

  ViewVC Help
Powered by ViewVC 1.1.26