ReactOS 0.4.16-dev-329-g9223134
rdpsnd_libao.c
Go to the documentation of this file.
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
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 along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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#include <sys/time.h>
29
30#define MAX_QUEUE 10
31#define WAVEOUTBUF 16
32
33int This->dsp_;
34ao_device *o_device = NULL;
37int This->channels;
38BOOL This->dsp_bu = False;
40static short g_samplewidth;
41
42static struct audio_packet
43{
44 struct stream s;
48static unsigned int queue_hi, queue_lo;
49
50BOOL
52{
53 ao_sample_format format;
54
55 ao_initialize();
56 default_driver = ao_default_driver_id();
57
58 format.bits = 16;
59 format.channels = 2;
60 This->channels = 2;
61 format.rate = 44100;
62 g_samplerate = 44100;
63 format.byte_format = AO_FMT_LITTLE;
64
65 o_device = ao_open_live(default_driver, &format, NULL);
66 if (o_device == NULL)
67 {
68 return False;
69 }
70
71 This->dsp_ = 0;
72 queue_lo = queue_hi = 0;
73
75
76 return True;
77}
78
79void
81{
82 /* Ack all remaining packets */
83 while (queue_lo != queue_hi)
84 {
87 queue_lo = (queue_lo + 1) % MAX_QUEUE;
88 }
89
90 if (o_device != NULL)
91 ao_close(o_device);
92
93 ao_shutdown();
94}
95
96BOOL
98{
99 if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
100 return False;
101 if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
102 return False;
103 if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
104 return False;
105 /* The only common denominator between libao output drivers is a sample-rate of
106 44100, we need to upsample 22050 to it */
107 if ((pwfx->nSamplesPerSec != 44100) && (pwfx->nSamplesPerSec != 22050))
108 return False;
109
110 return True;
111}
112
113BOOL
115{
116 ao_sample_format format;
117
118 format.bits = pwfx->wBitsPerSample;
119 format.channels = pwfx->nChannels;
120 This->channels = pwfx->nChannels;
121 format.rate = 44100;
123 format.byte_format = AO_FMT_LITTLE;
124
125 g_samplewidth = pwfx->wBitsPerSample / 8;
126
127 if (o_device != NULL)
128 ao_close(o_device);
129
130 o_device = ao_open_live(default_driver, &format, NULL);
131 if (o_device == NULL)
132 {
133 return False;
134 }
135
137
138 return True;
139}
140
141void
143{
144 warning("volume changes not supported with libao-output\n");
145}
146
147void
149{
151 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
152
153 if (next_hi == queue_lo)
154 {
155 error("No space to queue audio packet\n");
156 return;
157 }
158
159 queue_hi = next_hi;
160
161 packet->s = *s;
162 packet->tick = tick;
163 packet->index = index;
164 packet->s.p += 4;
165
166 /* we steal the data buffer from s, give it a new one */
167 s->data = malloc(s->size);
168
169 if (!This->dsp_bu)
171}
172
173void
175{
176 struct audio_packet *packet;
177 STREAM out;
178 char outbuf[WAVEOUTBUF];
179 int offset, len, i;
180 static long prev_s, prev_us;
181 unsigned int duration;
182 struct timeval tv;
183 int next_tick;
184
185 if (g_reopened)
186 {
188 gettimeofday(&tv, NULL);
189 prev_s = tv.tv_sec;
190 prev_us = tv.tv_usec;
191 }
192
193 if (queue_lo == queue_hi)
194 {
195 This->dsp_bu = 0;
196 return;
197 }
198
200 out = &packet->s;
201
202 if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
203 {
204 next_tick = packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
205 }
206 else
207 {
208 next_tick = (packet->tick + 65535) % 65536;
209 }
210
211 len = 0;
212
213 if (g_samplerate == 22050)
214 {
215 /* Resample to 44100 */
216 for (i = 0; (i < ((WAVEOUTBUF / 4) * (3 - g_samplewidth))) && (out->p < out->end);
217 i++)
218 {
219 /* On a stereo-channel we must make sure that left and right
220 does not get mixed up, so we need to expand the sample-
221 data with channels in mind: 1234 -> 12123434
222 If we have a mono-channel, we can expand the data by simply
223 doubling the sample-data: 1234 -> 11223344 */
224 if (This->channels == 2)
225 offset = ((i * 2) - (i & 1)) * g_samplewidth;
226 else
227 offset = (i * 2) * g_samplewidth;
228
229 memcpy(&outbuf[offset], out->p, g_samplewidth);
230 memcpy(&outbuf[This->channels * g_samplewidth + offset], out->p, g_samplewidth);
231
232 out->p += g_samplewidth;
233 len += 2 * g_samplewidth;
234 }
235 }
236 else
237 {
238 len = (WAVEOUTBUF > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTBUF;
239 memcpy(outbuf, out->p, len);
240 out->p += len;
241 }
242
243 ao_play(o_device, outbuf, len);
244
245 gettimeofday(&tv, NULL);
246
247 duration = ((tv.tv_sec - prev_s) * 1000000 + (tv.tv_usec - prev_us)) / 1000;
248
249 if (packet->tick > next_tick)
250 next_tick += 65536;
251
252 if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
253 {
254 prev_s = tv.tv_sec;
255 prev_us = tv.tv_usec;
256
257 if (abs((next_tick - packet->tick) - duration) > 20)
258 {
259 DEBUG(("duration: %d, calc: %d, ", duration, next_tick - packet->tick));
260 DEBUG(("last: %d, is: %d, should: %d\n", packet->tick,
261 (packet->tick + duration) % 65536, next_tick % 65536));
262 }
263
264 /* Until all drivers are using the windows sound-ticks, we need to
265 substract the 50 ticks added later by rdpsnd.c */
266 rdpsnd_send_completion(((packet->tick + duration) % 65536) - 50, packet->index);
267 free(out->data);
268 queue_lo = (queue_lo + 1) % MAX_QUEUE;
269 }
270
271 This->dsp_bu = 1;
272 return;
273}
#define gettimeofday(tv, tz)
Definition: adns_win32.h:159
#define WAVE_FORMAT_PCM
Definition: constants.h:425
#define DEBUG(args)
Definition: rdesktop.h:129
unsigned short uint16
Definition: types.h:30
#define False
Definition: types.h:25
#define True
Definition: types.h:24
unsigned char uint8
Definition: types.h:28
#define index(s, c)
Definition: various.h:29
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define abs(i)
Definition: fconv.c:206
unsigned int BOOL
Definition: ntddk_ex.h:94
GLdouble s
Definition: gl.h:2039
GLuint index
Definition: glext.h:6031
GLdouble GLdouble right
Definition: glext.h:10859
GLint left
Definition: glext.h:7726
GLenum GLsizei len
Definition: glext.h:6722
GLintptr offset
Definition: glext.h:5920
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
void rdpsnd_send_completion(RDPCLIENT *This, uint16 tick, uint8 packet_index)
Definition: rdpsnd.c:55
static unsigned int queue_lo
Definition: rdpsnd_libao.c:48
ao_device * o_device
Definition: rdpsnd_libao.c:34
BOOL wave_out_open(void)
Definition: rdpsnd_libao.c:51
static short g_samplewidth
Definition: rdpsnd_libao.c:40
BOOL wave_out_format_supported(WAVEFORMATEX *pwfx)
Definition: rdpsnd_libao.c:97
int g_samplerate
Definition: rdpsnd_libao.c:36
void wave_out_write(STREAM s, uint16 tick, uint8 index)
Definition: rdpsnd_libao.c:148
#define WAVEOUTBUF
Definition: rdpsnd_libao.c:31
static BOOL g_reopened
Definition: rdpsnd_libao.c:39
int default_driver
Definition: rdpsnd_libao.c:35
BOOL wave_out_set_format(WAVEFORMATEX *pwfx)
Definition: rdpsnd_libao.c:114
void wave_out_close(void)
Definition: rdpsnd_libao.c:80
void wave_out_volume(uint16 left, uint16 right)
Definition: rdpsnd_libao.c:142
void wave_out_play(void)
Definition: rdpsnd_libao.c:174
static unsigned int queue_hi
Definition: rdpsnd_libao.c:48
#define MAX_QUEUE
Definition: rdpsnd_libao.c:30
static struct audio_packet packet_queue[MAX_QUEUE]
static FILE * out
Definition: regtests2xml.c:44
#define warning(s)
Definition: debug.h:83
WORD wBitsPerSample
Definition: audioclient.idl:45
DWORD nSamplesPerSec
Definition: audioclient.idl:42
Definition: format.c:58
Definition: dhcpd.h:135
Definition: parse.h:23
unsigned long tv_sec
Definition: linux.h:1738
unsigned long tv_usec
Definition: linux.h:1739
static int tick
Definition: test_dhcp.c:143