/[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

Contents of /sourceforge.net/trunk/rdesktop/rdpsnd_dsp.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1277 - (show annotations)
Sun Oct 1 12:26:01 2006 UTC (17 years, 8 months ago) by stargo
File MIME type: text/plain
File size: 6037 byte(s)
only resample when there is need

1 /*
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 #define MAX_VOLUME 65535
26
27 static uint16 softvol_left = MAX_VOLUME;
28 static uint16 softvol_right = MAX_VOLUME;
29 static uint32 resample_to_srate = 44100;
30 static uint16 resample_to_bitspersample = 16;
31 static uint16 resample_to_channels = 2;
32
33 void
34 rdpsnd_dsp_softvol_set(uint16 left, uint16 right)
35 {
36 softvol_left = left;
37 softvol_right = right;
38 DEBUG(("rdpsnd_dsp_softvol_set: left: %u, right: %u\n", left, right));
39 }
40
41 void
42 rdpsnd_dsp_softvol(unsigned char *buffer, unsigned int size, WAVEFORMATEX * format)
43 {
44 unsigned int factor_left, factor_right;
45 unsigned char *posin = buffer;
46 unsigned char *posout = buffer;
47
48 if ((softvol_left == MAX_VOLUME) && (softvol_right == MAX_VOLUME))
49 return;
50
51 factor_left = (softvol_left * 256) / MAX_VOLUME;
52 factor_right = (softvol_right * 256) / MAX_VOLUME;
53
54 if (format->nChannels == 1)
55 {
56 factor_left = factor_right = (factor_left + factor_right) / 2;
57 }
58
59 if (format->wBitsPerSample == 8)
60 {
61 sint8 val;
62
63 while (posout < buffer + size)
64 {
65 /* Left */
66 val = *posin++;
67 val = (val * factor_left) >> 8;
68 *posout++ = val;
69
70 /* Right */
71 val = *posin++;
72 val = (val * factor_right) >> 8;
73 *posout++ = val;
74 }
75 }
76 else
77 {
78 sint16 val;
79
80 while (posout < buffer + size)
81 {
82 /* Left */
83 val = *posin++;
84 val |= *posin++ << 8;
85 val = (val * factor_left) >> 8;
86 *posout++ = val & 0xff;
87 *posout++ = val >> 8;
88
89 /* Right */
90 val = *posin++;
91 val |= *posin++ << 8;
92 val = (val * factor_right) >> 8;
93 *posout++ = val & 0xff;
94 *posout++ = val >> 8;
95 }
96 }
97
98 DEBUG(("using softvol with factors left: %d, right: %d (%d/%d)\n", factor_left,
99 factor_right, format->wBitsPerSample, format->nChannels));
100 }
101
102 void
103 rdpsnd_dsp_swapbytes(unsigned char *buffer, unsigned int size, WAVEFORMATEX * format)
104 {
105 int i;
106 uint8 swap;
107
108 if (format->wBitsPerSample == 8)
109 return;
110
111 for (i = 0; i < size; i += 2)
112 {
113 swap = *(buffer + i);
114 *(buffer + i) = *(buffer + i + 1);
115 *(buffer + i + 1) = swap;
116 }
117 }
118
119 BOOL
120 rdpsnd_dsp_resample_set(uint32 device_srate, uint16 device_bitspersample, uint16 device_channels)
121 {
122 if (device_srate != 44100 && device_srate != 22050)
123 return False;
124
125 if (device_bitspersample != 16 && device_bitspersample != 8)
126 return False;
127
128 if (device_channels != 1 && device_channels != 2)
129 return False;
130
131 resample_to_srate = device_srate;
132 resample_to_bitspersample = device_bitspersample;
133 resample_to_channels = device_channels;
134
135 return True;
136 }
137
138 BOOL
139 rdpsnd_dsp_resample_supported(WAVEFORMATEX * format)
140 {
141 if (format->wFormatTag != WAVE_FORMAT_PCM)
142 return False;
143 if ((format->nChannels != 1) && (format->nChannels != 2))
144 return False;
145 if ((format->wBitsPerSample != 8) && (format->wBitsPerSample != 16))
146 return False;
147 if ((format->nSamplesPerSec != 44100) && (format->nSamplesPerSec != 22050))
148 return False;
149
150 return True;
151 }
152
153 uint32
154 rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
155 WAVEFORMATEX * format)
156 {
157 static BOOL warned = False;
158 int outsize, offset;
159 int samplewidth = format->wBitsPerSample / 8;
160 int i;
161
162 if ((resample_to_bitspersample == format->wBitsPerSample) &&
163 (resample_to_channels == format->nChannels) &&
164 (resample_to_srate == format->nSamplesPerSec))
165 return 0;
166
167 if ((resample_to_bitspersample != format->wBitsPerSample) ||
168 (resample_to_channels != format->nChannels) || (format->nSamplesPerSec != 22050))
169 {
170 if (!warned)
171 {
172 warning("unsupported resample-settings (%u/%u/%u), not resampling!\n",
173 format->nSamplesPerSec, format->wBitsPerSample, format->nChannels);
174 warned = True;
175 }
176 return 0;
177 }
178
179 outsize = size * 2;
180 *out = xmalloc(outsize);
181
182 /* Resample from 22050 to 44100 */
183 for (i = 0; i < (size / samplewidth); i++)
184 {
185 /* On a stereo-channel we must make sure that left and right
186 does not get mixed up, so we need to expand the sample-
187 data with channels in mind: 1234 -> 12123434
188 If we have a mono-channel, we can expand the data by simply
189 doubling the sample-data: 1234 -> 11223344 */
190 if (resample_to_channels == 2)
191 offset = ((i * 2) - (i & 1)) * samplewidth;
192 else
193 offset = (i * 2) * samplewidth;
194
195 memcpy(*out + offset, in + (i * samplewidth), samplewidth);
196 memcpy(*out + (resample_to_channels * samplewidth + offset),
197 in + (i * samplewidth), samplewidth);
198
199 }
200
201 return outsize;
202 }
203
204 STREAM
205 rdpsnd_dsp_process(STREAM s, struct audio_driver * current_driver, WAVEFORMATEX * format)
206 {
207 static struct stream out;
208
209 /* softvol and byteswap do not change the amount of data they
210 return, so they can operate on the input-stream */
211 if (current_driver->wave_out_volume == rdpsnd_dsp_softvol_set)
212 rdpsnd_dsp_softvol(s->data, s->size, format);
213
214 #ifdef B_ENDIAN
215 if (current_driver->need_byteswap_on_be)
216 rdpsnd_dsp_swapbytes(s->data, s->size, format);
217 #endif
218
219 out.data = NULL;
220
221 if (current_driver->wave_out_format_supported == rdpsnd_dsp_resample_supported)
222 out.size = rdpsnd_dsp_resample(&out.data, s->data, s->size, format);
223
224 if (out.data == NULL)
225 {
226 out.data = xmalloc(s->size);
227 memcpy(out.data, s->data, s->size);
228 out.size = s->size;
229 }
230
231 out.p = out.data;
232 out.end = out.p + out.size;
233
234 return &out;
235 }

  ViewVC Help
Powered by ViewVC 1.1.26