/[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 1254 - (show annotations)
Sun Sep 17 10:32:18 2006 UTC (17 years, 8 months ago) by stargo
File MIME type: text/plain
File size: 5260 byte(s)
unify queue-handling in rdpsnd.c (remove private copies from all
drivers)

1 /* -*- c-basic-offset: 8 -*-
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-2006
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 "rdpsnd.h"
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 #include <ao/ao.h>
29 #include <sys/time.h>
30
31 #define WAVEOUTBUF 16
32
33 static ao_device *o_device = NULL;
34 static int default_driver;
35 static int samplerate;
36 static int audiochannels;
37 static BOOL reopened;
38 static short samplewidth;
39
40 BOOL
41 wave_out_open(void)
42 {
43 ao_sample_format format;
44
45 ao_initialize();
46 default_driver = ao_default_driver_id();
47
48 format.bits = 16;
49 format.channels = 2;
50 audiochannels = 2;
51 format.rate = 44100;
52 samplerate = 44100;
53 format.byte_format = AO_FMT_LITTLE;
54
55 o_device = ao_open_live(default_driver, &format, NULL);
56 if (o_device == NULL)
57 {
58 return False;
59 }
60
61 g_dsp_fd = 0;
62 rdpsnd_queue_init();
63
64 reopened = True;
65
66 return True;
67 }
68
69 void
70 wave_out_close(void)
71 {
72 /* Ack all remaining packets */
73 while (!rdpsnd_queue_empty())
74 {
75 rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick,
76 rdpsnd_queue_current_packet()->index);
77 rdpsnd_queue_next();
78 }
79
80 if (o_device != NULL)
81 ao_close(o_device);
82
83 ao_shutdown();
84 }
85
86 BOOL
87 wave_out_format_supported(WAVEFORMATEX * pwfx)
88 {
89 if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
90 return False;
91 if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
92 return False;
93 if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
94 return False;
95 /* The only common denominator between libao output drivers is a sample-rate of
96 44100, we need to upsample 22050 to it */
97 if ((pwfx->nSamplesPerSec != 44100) && (pwfx->nSamplesPerSec != 22050))
98 return False;
99
100 return True;
101 }
102
103 BOOL
104 wave_out_set_format(WAVEFORMATEX * pwfx)
105 {
106 ao_sample_format format;
107
108 format.bits = pwfx->wBitsPerSample;
109 format.channels = pwfx->nChannels;
110 audiochannels = pwfx->nChannels;
111 format.rate = 44100;
112 samplerate = pwfx->nSamplesPerSec;
113 format.byte_format = AO_FMT_LITTLE;
114
115 samplewidth = pwfx->wBitsPerSample / 8;
116
117 if (o_device != NULL)
118 ao_close(o_device);
119
120 o_device = ao_open_live(default_driver, &format, NULL);
121 if (o_device == NULL)
122 {
123 return False;
124 }
125
126 reopened = True;
127
128 return True;
129 }
130
131 void
132 wave_out_volume(uint16 left, uint16 right)
133 {
134 warning("volume changes not supported with libao-output\n");
135 }
136
137 void
138 wave_out_play(void)
139 {
140 struct audio_packet *packet;
141 STREAM out;
142 char outbuf[WAVEOUTBUF];
143 int offset, len, i;
144 static long prev_s, prev_us;
145 unsigned int duration;
146 struct timeval tv;
147 int next_tick;
148
149 if (reopened)
150 {
151 reopened = False;
152 gettimeofday(&tv, NULL);
153 prev_s = tv.tv_sec;
154 prev_us = tv.tv_usec;
155 }
156
157 if (rdpsnd_queue_empty())
158 {
159 g_dsp_busy = 0;
160 return;
161 }
162
163 packet = rdpsnd_queue_current_packet();
164 out = &packet->s;
165
166 next_tick = rdpsnd_queue_next_tick();
167
168 len = 0;
169
170 if (samplerate == 22050)
171 {
172 /* Resample to 44100 */
173 for (i = 0; (i < ((WAVEOUTBUF / 4) * (3 - samplewidth))) && (out->p < out->end);
174 i++)
175 {
176 /* On a stereo-channel we must make sure that left and right
177 does not get mixed up, so we need to expand the sample-
178 data with channels in mind: 1234 -> 12123434
179 If we have a mono-channel, we can expand the data by simply
180 doubling the sample-data: 1234 -> 11223344 */
181 if (audiochannels == 2)
182 offset = ((i * 2) - (i & 1)) * samplewidth;
183 else
184 offset = (i * 2) * samplewidth;
185
186 memcpy(&outbuf[offset], out->p, samplewidth);
187 memcpy(&outbuf[audiochannels * samplewidth + offset], out->p, samplewidth);
188
189 out->p += samplewidth;
190 len += 2 * samplewidth;
191 }
192 }
193 else
194 {
195 len = (WAVEOUTBUF > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTBUF;
196 memcpy(outbuf, out->p, len);
197 out->p += len;
198 }
199
200 ao_play(o_device, outbuf, len);
201
202 gettimeofday(&tv, NULL);
203
204 duration = ((tv.tv_sec - prev_s) * 1000000 + (tv.tv_usec - prev_us)) / 1000;
205
206 if (packet->tick > next_tick)
207 next_tick += 65536;
208
209 if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
210 {
211 prev_s = tv.tv_sec;
212 prev_us = tv.tv_usec;
213
214 if (abs((next_tick - packet->tick) - duration) > 20)
215 {
216 DEBUG(("duration: %d, calc: %d, ", duration, next_tick - packet->tick));
217 DEBUG(("last: %d, is: %d, should: %d\n", packet->tick,
218 (packet->tick + duration) % 65536, next_tick % 65536));
219 }
220
221 rdpsnd_send_completion(((packet->tick + duration) % 65536), packet->index);
222 rdpsnd_queue_next();
223 }
224
225 g_dsp_busy = 1;
226 return;
227 }

  ViewVC Help
Powered by ViewVC 1.1.26