/[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 835 - (show annotations)
Tue Mar 8 04:25:12 2005 UTC (19 years, 2 months ago) by stargo
File MIME type: text/plain
File size: 4641 byte(s)
add initial support for multiple windows samplerates

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
31 int g_dsp_fd;
32 ao_device *o_device = NULL;
33 int default_driver;
34 int g_samplerate;
35 BOOL g_dsp_busy = False;
36 static short g_samplewidth;
37
38 static struct audio_packet
39 {
40 struct stream s;
41 uint16 tick;
42 uint8 index;
43 } packet_queue[MAX_QUEUE];
44 static unsigned int queue_hi, queue_lo;
45
46 BOOL
47 wave_out_open(void)
48 {
49 ao_sample_format format;
50
51 ao_initialize();
52 default_driver = ao_default_driver_id();
53
54 format.bits = 16;
55 format.channels = 2;
56 format.rate = 44100;
57 g_samplerate = 44100;
58 format.byte_format = AO_FMT_LITTLE;
59
60 o_device = ao_open_live(default_driver, &format, NULL);
61 if (o_device == NULL)
62 {
63 return False;
64 }
65
66 g_dsp_fd = 0;
67 queue_lo = queue_hi = 0;
68
69 return True;
70 }
71
72 void
73 wave_out_close(void)
74 {
75 /* Ack all remaining packets */
76 while (queue_lo != queue_hi)
77 {
78 rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index);
79 free(packet_queue[queue_lo].s.data);
80 queue_lo = (queue_lo + 1) % MAX_QUEUE;
81 }
82
83 if (o_device != NULL)
84 ao_close(o_device);
85 ao_shutdown();
86 }
87
88 BOOL
89 wave_out_format_supported(WAVEFORMATEX * pwfx)
90 {
91 if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
92 return False;
93 if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
94 return False;
95 if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
96 return False;
97 /* The only common denominator between libao output drivers is a sample-rate of
98 44100, we need to upsample 22050 to it */
99 if ((pwfx->nSamplesPerSec != 44100) && (pwfx->nSamplesPerSec != 22050))
100 return False;
101
102 return True;
103 }
104
105 BOOL
106 wave_out_set_format(WAVEFORMATEX * pwfx)
107 {
108 ao_sample_format format;
109
110 format.bits = pwfx->wBitsPerSample;
111 format.channels = pwfx->nChannels;
112 format.rate = 44100;
113 g_samplerate = pwfx->nSamplesPerSec;
114 format.byte_format = AO_FMT_LITTLE;
115
116 g_samplewidth = pwfx->wBitsPerSample / 8;
117
118 if(o_device != NULL)
119 ao_close(o_device);
120
121 o_device = ao_open_live(default_driver, &format, NULL);
122 if (o_device == NULL)
123 {
124 return False;
125 }
126
127
128 return True;
129 }
130
131 void
132 wave_out_volume(uint16 left, uint16 right)
133 {
134 }
135
136 void
137 wave_out_write(STREAM s, uint16 tick, uint8 index)
138 {
139 struct audio_packet *packet = &packet_queue[queue_hi];
140 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
141
142 if (next_hi == queue_lo)
143 {
144 error("No space to queue audio packet\n");
145 return;
146 }
147
148 queue_hi = next_hi;
149
150 packet->s = *s;
151 packet->tick = tick;
152 packet->index = index;
153 packet->s.p += 4;
154
155 /* we steal the data buffer from s, give it a new one */
156 s->data = malloc(s->size);
157
158 if (!g_dsp_busy)
159 wave_out_play();
160 }
161
162 void
163 wave_out_play(void)
164 {
165 struct audio_packet *packet;
166 STREAM out;
167 unsigned char expanded[16];
168 int offset,len,i;
169
170 if (queue_lo == queue_hi)
171 {
172 g_dsp_busy = 0;
173 return;
174 }
175
176 packet = &packet_queue[queue_lo];
177 out = &packet->s;
178
179 len = 0;
180
181 if (g_samplerate == 22050 )
182 {
183 /* Resample to 44100 */
184 for(i=0; (i<(2*(3-g_samplewidth))) && (out->p < out->end); i++)
185 {
186 offset=i*4*g_samplewidth;
187 memcpy(&expanded[0*g_samplewidth+offset],out->p,g_samplewidth);
188 memcpy(&expanded[2*g_samplewidth+offset],out->p,g_samplewidth);
189 out->p += 2;
190
191 memcpy(&expanded[1*g_samplewidth+offset],out->p,g_samplewidth);
192 memcpy(&expanded[3*g_samplewidth+offset],out->p,g_samplewidth);
193 out->p += 2;
194 len += 4*g_samplewidth;
195 }
196 }
197 else
198 {
199 len = (16 > (out->end - out->p)) ? (out->end - out->p) : 16;
200 memcpy(expanded,out->p,len);
201 out->p += len;
202 }
203
204 ao_play(o_device, expanded, len);
205
206 if (out->p == out->end)
207 {
208 rdpsnd_send_completion(packet->tick, packet->index);
209 free(out->data);
210 queue_lo = (queue_lo + 1) % MAX_QUEUE;
211 }
212
213 g_dsp_busy = 1;
214 return;
215 }

  ViewVC Help
Powered by ViewVC 1.1.26