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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 841 - (show annotations)
Tue Mar 8 17:23:26 2005 UTC (19 years, 2 months ago) by stargo
File MIME type: text/plain
File size: 5091 byte(s)
bugfix: correctly increment the out->p pointer

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 Sound Channel Process Functions - libao-driver
4 Copyright (C) Matthew Chapman 2003
5 Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6 Copyright (C) Michael Gernoth mike@zerfleddert.de 2005
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "rdesktop.h"
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <errno.h>
27 #include <ao/ao.h>
28
29 #define MAX_QUEUE 10
30 #define WAVEOUTBUF 64
31
32 int g_dsp_fd;
33 ao_device *o_device = NULL;
34 int default_driver;
35 int g_samplerate;
36 int g_channels;
37 BOOL g_dsp_busy = False;
38 static short g_samplewidth;
39
40 static struct audio_packet
41 {
42 struct stream s;
43 uint16 tick;
44 uint8 index;
45 } packet_queue[MAX_QUEUE];
46 static unsigned int queue_hi, queue_lo;
47
48 BOOL
49 wave_out_open(void)
50 {
51 ao_sample_format format;
52
53 ao_initialize();
54 default_driver = ao_default_driver_id();
55
56 format.bits = 16;
57 format.channels = 2;
58 g_channels = 2;
59 format.rate = 44100;
60 g_samplerate = 44100;
61 format.byte_format = AO_FMT_LITTLE;
62
63 o_device = ao_open_live(default_driver, &format, NULL);
64 if (o_device == NULL)
65 {
66 return False;
67 }
68
69 g_dsp_fd = 0;
70 queue_lo = queue_hi = 0;
71
72 return True;
73 }
74
75 void
76 wave_out_close(void)
77 {
78 /* Ack all remaining packets */
79 while (queue_lo != queue_hi)
80 {
81 rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index);
82 free(packet_queue[queue_lo].s.data);
83 queue_lo = (queue_lo + 1) % MAX_QUEUE;
84 }
85
86 if (o_device != NULL)
87 ao_close(o_device);
88
89 ao_shutdown();
90 }
91
92 BOOL
93 wave_out_format_supported(WAVEFORMATEX * pwfx)
94 {
95 if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
96 return False;
97 if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
98 return False;
99 if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
100 return False;
101 /* The only common denominator between libao output drivers is a sample-rate of
102 44100, we need to upsample 22050 to it */
103 if ((pwfx->nSamplesPerSec != 44100) && (pwfx->nSamplesPerSec != 22050))
104 return False;
105
106 return True;
107 }
108
109 BOOL
110 wave_out_set_format(WAVEFORMATEX * pwfx)
111 {
112 ao_sample_format format;
113
114 format.bits = pwfx->wBitsPerSample;
115 format.channels = pwfx->nChannels;
116 g_channels = pwfx->nChannels;
117 format.rate = 44100;
118 g_samplerate = pwfx->nSamplesPerSec;
119 format.byte_format = AO_FMT_LITTLE;
120
121 g_samplewidth = pwfx->wBitsPerSample / 8;
122
123 if (o_device != NULL)
124 ao_close(o_device);
125
126 o_device = ao_open_live(default_driver, &format, NULL);
127 if (o_device == NULL)
128 {
129 return False;
130 }
131
132
133 return True;
134 }
135
136 void
137 wave_out_volume(uint16 left, uint16 right)
138 {
139 warning("volume changes not supported with libao-output\n");
140 }
141
142 void
143 wave_out_write(STREAM s, uint16 tick, uint8 index)
144 {
145 struct audio_packet *packet = &packet_queue[queue_hi];
146 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
147
148 if (next_hi == queue_lo)
149 {
150 error("No space to queue audio packet\n");
151 return;
152 }
153
154 queue_hi = next_hi;
155
156 packet->s = *s;
157 packet->tick = tick;
158 packet->index = index;
159 packet->s.p += 4;
160
161 /* we steal the data buffer from s, give it a new one */
162 s->data = malloc(s->size);
163
164 if (!g_dsp_busy)
165 wave_out_play();
166 }
167
168 void
169 wave_out_play(void)
170 {
171 struct audio_packet *packet;
172 STREAM out;
173 unsigned char outbuf[WAVEOUTBUF];
174 int offset, len, i;
175
176 if (queue_lo == queue_hi)
177 {
178 g_dsp_busy = 0;
179 return;
180 }
181
182 packet = &packet_queue[queue_lo];
183 out = &packet->s;
184
185 len = 0;
186
187 if (g_samplerate == 22050)
188 {
189 /* Resample to 44100 */
190 for (i = 0; (i < ((WAVEOUTBUF / 4) * (3 - g_samplewidth))) && (out->p < out->end);
191 i++)
192 {
193 /* On a stereo-channel we must make sure that left and right
194 does not get mixed up, so we need to expand the sample-
195 data with channels in mind: 1234 -> 12123434
196 If we have a mono-channel, we can expand the data by simply
197 doubling the sample-data: 1234 -> 11223344 */
198 if (g_channels == 2)
199 offset = ((i * 2) - (i & 1)) * g_samplewidth;
200 else
201 offset = (i * 2) * g_samplewidth;
202
203 memcpy(&outbuf[offset], out->p, g_samplewidth);
204 memcpy(&outbuf[g_channels * g_samplewidth + offset], out->p, g_samplewidth);
205
206 out->p += g_samplewidth;
207 len += 2 * g_samplewidth;
208 }
209 }
210 else
211 {
212 len = (WAVEOUTBUF > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTBUF;
213 memcpy(outbuf, out->p, len);
214 out->p += len;
215 }
216
217 ao_play(o_device, outbuf, len);
218
219 if (out->p == out->end)
220 {
221 rdpsnd_send_completion(packet->tick, packet->index);
222 free(out->data);
223 queue_lo = (queue_lo + 1) % MAX_QUEUE;
224 }
225
226 g_dsp_busy = 1;
227 return;
228 }

  ViewVC Help
Powered by ViewVC 1.1.26