Revision d329a6fb oss.c
b/oss.c | ||
---|---|---|
24 | 24 |
#include "vl.h" |
25 | 25 |
|
26 | 26 |
#ifndef _WIN32 |
27 |
#include <ctype.h> |
|
27 | 28 |
#include <fcntl.h> |
28 | 29 |
#include <errno.h> |
29 | 30 |
#include <stdio.h> |
... | ... | |
32 | 33 |
#include <stdlib.h> |
33 | 34 |
#include <limits.h> |
34 | 35 |
#include <inttypes.h> |
36 |
#include <sys/mman.h> |
|
35 | 37 |
#include <sys/types.h> |
36 | 38 |
#include <sys/ioctl.h> |
37 | 39 |
#include <sys/soundcard.h> |
... | ... | |
90 | 92 |
ldebug ("ioctl " #args " = %d\n", ret); \ |
91 | 93 |
} while (0) |
92 | 94 |
|
93 |
static int audio_fd = -1; |
|
94 |
static int freq; |
|
95 |
static int conf_nfrags = 4; |
|
96 |
static int conf_fragsize; |
|
97 |
static int nfrags; |
|
98 |
static int fragsize; |
|
99 |
static int bufsize; |
|
100 |
static int nchannels; |
|
101 |
static int fmt; |
|
102 |
static int rpos; |
|
103 |
static int wpos; |
|
104 |
static int atom; |
|
105 |
static int live; |
|
106 |
static int leftover; |
|
107 |
static int bytes_per_second; |
|
108 |
static void *buf; |
|
109 |
static enum {DONT, DSP, TID} estimate = TID; |
|
110 |
|
|
111 |
static void (*copy_fn)(void *, void *, int); |
|
95 |
static struct { |
|
96 |
int fd; |
|
97 |
int freq; |
|
98 |
int bits16; |
|
99 |
int nchannels; |
|
100 |
int rpos; |
|
101 |
int wpos; |
|
102 |
int live; |
|
103 |
int oss_fmt; |
|
104 |
int bytes_per_second; |
|
105 |
int is_mapped; |
|
106 |
void *buf; |
|
107 |
int bufsize; |
|
108 |
int nfrags; |
|
109 |
int fragsize; |
|
110 |
int old_optr; |
|
111 |
int leftover; |
|
112 |
uint64_t old_ticks; |
|
113 |
void (*copy_fn)(void *, void *, int); |
|
114 |
} oss = { .fd = -1 }; |
|
115 |
|
|
116 |
static struct { |
|
117 |
int try_mmap; |
|
118 |
int nfrags; |
|
119 |
int fragsize; |
|
120 |
} conf = { |
|
121 |
.try_mmap = 0, |
|
122 |
.nfrags = 4, |
|
123 |
.fragsize = 4096 |
|
124 |
}; |
|
125 |
|
|
126 |
static enum {DONT, DSP, TID} est = DONT; |
|
112 | 127 |
|
113 | 128 |
static void copy_no_conversion (void *dst, void *src, int size) |
114 | 129 |
{ |
... | ... | |
141 | 156 |
rpos, wpos, live); |
142 | 157 |
} |
143 | 158 |
|
144 |
void AUD_reset (int rfreq, int rnchannels, audfmt_e rfmt)
|
|
159 |
static void do_open ()
|
|
145 | 160 |
{ |
146 |
int fmt_; |
|
147 |
int bits16; |
|
161 |
int mmmmssss; |
|
162 |
audio_buf_info abinfo; |
|
163 |
int fmt, freq, nchannels; |
|
148 | 164 |
|
149 |
if (-1 == audio_fd) { |
|
150 |
AUD_open (rfreq, rnchannels, rfmt); |
|
151 |
return; |
|
165 |
if (oss.buf) { |
|
166 |
if (-1 == munmap (oss.buf, oss.bufsize)) { |
|
167 |
ERRFail ("failed to unmap audio buffer %p %d", |
|
168 |
oss.buf, oss.bufsize); |
|
169 |
} |
|
170 |
oss.buf = NULL; |
|
152 | 171 |
} |
153 | 172 |
|
154 |
switch (rfmt) { |
|
155 |
case AUD_FMT_U8: |
|
156 |
bits16 = 0; |
|
157 |
fmt_ = AFMT_U8; |
|
158 |
copy_fn = copy_no_conversion; |
|
159 |
atom = 1; |
|
160 |
break; |
|
173 |
if (-1 != oss.fd) |
|
174 |
close (oss.fd); |
|
161 | 175 |
|
162 |
case AUD_FMT_S8: |
|
163 |
Fail ("can not play 8bit signed"); |
|
176 |
oss.fd = open ("/dev/dsp", O_RDWR | O_NONBLOCK); |
|
177 |
if (-1 == oss.fd) { |
|
178 |
ERRFail ("can not open /dev/dsp"); |
|
179 |
} |
|
164 | 180 |
|
165 |
case AUD_FMT_S16: |
|
166 |
bits16 = 1; |
|
167 |
fmt_ = AFMT_S16_LE; |
|
168 |
copy_fn = copy_no_conversion; |
|
169 |
atom = 2; |
|
170 |
break; |
|
181 |
fmt = oss.oss_fmt; |
|
182 |
freq = oss.freq; |
|
183 |
nchannels = oss.nchannels; |
|
184 |
|
|
185 |
IOCTL ((oss.fd, SNDCTL_DSP_RESET, 1)); |
|
186 |
IOCTL ((oss.fd, SNDCTL_DSP_SAMPLESIZE, &fmt)); |
|
187 |
IOCTL ((oss.fd, SNDCTL_DSP_CHANNELS, &nchannels)); |
|
188 |
IOCTL ((oss.fd, SNDCTL_DSP_SPEED, &freq)); |
|
189 |
IOCTL ((oss.fd, SNDCTL_DSP_NONBLOCK)); |
|
190 |
|
|
191 |
mmmmssss = (conf.nfrags << 16) | conf.fragsize; |
|
192 |
IOCTL ((oss.fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)); |
|
193 |
|
|
194 |
if ((oss.oss_fmt != fmt) |
|
195 |
|| (oss.nchannels != nchannels) |
|
196 |
|| (oss.freq != freq)) { |
|
197 |
Fail ("failed to set audio parameters\n" |
|
198 |
"parameter | requested value | obtained value\n" |
|
199 |
"format | %10d | %10d\n" |
|
200 |
"channels | %10d | %10d\n" |
|
201 |
"frequency | %10d | %10d\n", |
|
202 |
oss.oss_fmt, fmt, |
|
203 |
oss.nchannels, nchannels, |
|
204 |
oss.freq, freq); |
|
205 |
} |
|
171 | 206 |
|
172 |
case AUD_FMT_U16: |
|
173 |
bits16 = 1; |
|
174 |
fmt_ = AFMT_S16_LE; |
|
175 |
copy_fn = copy_u16_to_s16; |
|
176 |
atom = 2; |
|
177 |
break; |
|
207 |
IOCTL ((oss.fd, SNDCTL_DSP_GETOSPACE, &abinfo)); |
|
178 | 208 |
|
179 |
default: |
|
180 |
abort (); |
|
181 |
} |
|
209 |
oss.nfrags = abinfo.fragstotal; |
|
210 |
oss.fragsize = abinfo.fragsize; |
|
211 |
oss.bufsize = oss.nfrags * oss.fragsize; |
|
212 |
oss.old_optr = 0; |
|
182 | 213 |
|
183 |
if ((fmt_ == fmt) && (bits16 + 1 == nchannels) && (rfreq == freq)) |
|
184 |
return; |
|
214 |
oss.bytes_per_second = (freq << (nchannels >> 1)) << oss.bits16; |
|
215 |
|
|
216 |
linfo ("bytes per second %d\n", oss.bytes_per_second); |
|
217 |
|
|
218 |
linfo ("fragments %d, fragstotal %d, fragsize %d, bytes %d, bufsize %d\n", |
|
219 |
abinfo.fragments, |
|
220 |
abinfo.fragstotal, |
|
221 |
abinfo.fragsize, |
|
222 |
abinfo.bytes, |
|
223 |
oss.bufsize); |
|
224 |
|
|
225 |
oss.buf = MAP_FAILED; |
|
226 |
oss.is_mapped = 0; |
|
227 |
|
|
228 |
if (conf.try_mmap) { |
|
229 |
oss.buf = mmap (NULL, oss.bufsize, PROT_WRITE, MAP_SHARED, oss.fd, 0); |
|
230 |
if (MAP_FAILED == oss.buf) { |
|
231 |
int err; |
|
232 |
|
|
233 |
err = errno; |
|
234 |
log ("failed to mmap audio, size %d, fd %d\n" |
|
235 |
"syserr: %s\n", |
|
236 |
oss.bufsize, oss.fd, strerror (err)); |
|
237 |
} |
|
185 | 238 |
else { |
186 |
AUD_open (rfreq, rnchannels, rfmt); |
|
239 |
est = TID; |
|
240 |
oss.is_mapped = 1; |
|
241 |
} |
|
242 |
} |
|
243 |
|
|
244 |
if (MAP_FAILED == oss.buf) { |
|
245 |
est = TID; |
|
246 |
oss.buf = mmap (NULL, oss.bufsize, PROT_READ | PROT_WRITE, |
|
247 |
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); |
|
248 |
if (MAP_FAILED == oss.buf) { |
|
249 |
ERRFail ("mmap audio buf, size %d", oss.bufsize); |
|
250 |
} |
|
251 |
} |
|
252 |
|
|
253 |
oss.rpos = 0; |
|
254 |
oss.wpos = 0; |
|
255 |
oss.live = 0; |
|
256 |
|
|
257 |
if (oss.is_mapped) { |
|
258 |
int trig; |
|
259 |
|
|
260 |
trig = 0; |
|
261 |
IOCTL ((oss.fd, SNDCTL_DSP_SETTRIGGER, &trig)); |
|
262 |
trig = PCM_ENABLE_OUTPUT; |
|
263 |
IOCTL ((oss.fd, SNDCTL_DSP_SETTRIGGER, &trig)); |
|
187 | 264 |
} |
188 | 265 |
} |
189 | 266 |
|
190 |
void AUD_open (int rfreq, int rnchannels, audfmt_e rfmt) |
|
267 |
static void maybe_open (int req_freq, int req_nchannels, |
|
268 |
audfmt_e req_fmt, int force_open) |
|
191 | 269 |
{ |
192 |
int fmt_; |
|
193 |
int mmmmssss; |
|
194 |
struct audio_buf_info abinfo; |
|
195 |
int _fmt; |
|
196 |
int _freq; |
|
197 |
int _nchannels; |
|
198 |
int bits16; |
|
270 |
int oss_fmt, bits16; |
|
199 | 271 |
|
200 |
bits16 = 0; |
|
201 |
|
|
202 |
switch (rfmt) { |
|
272 |
switch (req_fmt) { |
|
203 | 273 |
case AUD_FMT_U8: |
204 | 274 |
bits16 = 0; |
205 |
fmt_ = AFMT_U8; |
|
206 |
copy_fn = copy_no_conversion; |
|
207 |
atom = 1; |
|
275 |
oss_fmt = AFMT_U8; |
|
276 |
oss.copy_fn = copy_no_conversion; |
|
208 | 277 |
break; |
209 | 278 |
|
210 | 279 |
case AUD_FMT_S8: |
... | ... | |
212 | 281 |
|
213 | 282 |
case AUD_FMT_S16: |
214 | 283 |
bits16 = 1; |
215 |
fmt_ = AFMT_S16_LE; |
|
216 |
copy_fn = copy_no_conversion; |
|
217 |
atom = 2; |
|
284 |
oss_fmt = AFMT_S16_LE; |
|
285 |
oss.copy_fn = copy_no_conversion; |
|
218 | 286 |
break; |
219 | 287 |
|
220 | 288 |
case AUD_FMT_U16: |
221 | 289 |
bits16 = 1; |
222 |
fmt_ = AFMT_S16_LE; |
|
223 |
copy_fn = copy_u16_to_s16; |
|
224 |
atom = 2; |
|
290 |
oss_fmt = AFMT_S16_LE; |
|
291 |
oss.copy_fn = copy_u16_to_s16; |
|
225 | 292 |
break; |
226 | 293 |
|
227 | 294 |
default: |
228 | 295 |
abort (); |
229 | 296 |
} |
230 | 297 |
|
231 |
if (buf) { |
|
232 |
free (buf); |
|
233 |
buf = 0; |
|
234 |
} |
|
235 |
|
|
236 |
if (-1 != audio_fd) |
|
237 |
close (audio_fd); |
|
238 |
|
|
239 |
audio_fd = open ("/dev/dsp", O_WRONLY | O_NONBLOCK); |
|
240 |
if (-1 == audio_fd) { |
|
241 |
ERRFail ("can not open /dev/dsp"); |
|
242 |
} |
|
243 |
|
|
244 |
_fmt = fmt_; |
|
245 |
_freq = rfreq; |
|
246 |
_nchannels = rnchannels; |
|
247 |
|
|
248 |
IOCTL ((audio_fd, SNDCTL_DSP_RESET, 1)); |
|
249 |
IOCTL ((audio_fd, SNDCTL_DSP_SAMPLESIZE, &_fmt)); |
|
250 |
IOCTL ((audio_fd, SNDCTL_DSP_CHANNELS, &_nchannels)); |
|
251 |
IOCTL ((audio_fd, SNDCTL_DSP_SPEED, &_freq)); |
|
252 |
IOCTL ((audio_fd, SNDCTL_DSP_NONBLOCK)); |
|
253 |
|
|
254 |
/* from oss.pdf: |
|
255 |
|
|
256 |
The argument to this call is an integer encoded as 0xMMMMSSSS (in |
|
257 |
hex). The 16 least significant bits determine the fragment |
|
258 |
size. The size is 2^SSSS. For examp le SSSS=0008 gives fragment |
|
259 |
size of 256 bytes (2^8). The minimum is 16 bytes (SSSS=4) and the |
|
260 |
maximum is total_buffer_size/2. Some devices or processor |
|
261 |
architectures may require larger fragments - in this case the |
|
262 |
requested fragment size is automatically increased. |
|
263 |
|
|
264 |
So ahem... 4096 = 2^12, and grand total 0x0004000c |
|
265 |
*/ |
|
266 |
|
|
267 |
mmmmssss = (conf_nfrags << 16) | conf_fragsize; |
|
268 |
IOCTL ((audio_fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss)); |
|
269 |
|
|
270 |
linfo ("_fmt = %d, fmt = %d\n" |
|
271 |
"_channels = %d, rnchannels = %d\n" |
|
272 |
"_freq = %d, freq = %d\n", |
|
273 |
_fmt, fmt_, |
|
274 |
_nchannels, rnchannels, |
|
275 |
_freq, rfreq); |
|
276 |
|
|
277 |
if (_fmt != fmt_) { |
|
278 |
Fail ("format %d != %d", _fmt, fmt_); |
|
279 |
} |
|
280 |
|
|
281 |
if (_nchannels != rnchannels) { |
|
282 |
Fail ("channels %d != %d", _nchannels, rnchannels); |
|
298 |
if (force_open |
|
299 |
|| (-1 == oss.fd) |
|
300 |
|| (oss_fmt != oss.oss_fmt) |
|
301 |
|| (req_nchannels != oss.nchannels) |
|
302 |
|| (req_freq != oss.freq) |
|
303 |
|| (bits16 != oss.bits16)) { |
|
304 |
oss.oss_fmt = oss_fmt; |
|
305 |
oss.nchannels = req_nchannels; |
|
306 |
oss.freq = req_freq; |
|
307 |
oss.bits16 = bits16; |
|
308 |
do_open (); |
|
283 | 309 |
} |
310 |
} |
|
284 | 311 |
|
285 |
if (_freq != rfreq) { |
|
286 |
Fail ("freq %d != %d", _freq, rfreq); |
|
287 |
} |
|
288 |
|
|
289 |
IOCTL ((audio_fd, SNDCTL_DSP_GETOSPACE, &abinfo)); |
|
290 |
|
|
291 |
nfrags = abinfo.fragstotal; |
|
292 |
fragsize = abinfo.fragsize; |
|
293 |
freq = _freq; |
|
294 |
fmt = _fmt; |
|
295 |
nchannels = rnchannels; |
|
296 |
atom <<= nchannels >> 1; |
|
297 |
bufsize = nfrags * fragsize; |
|
298 |
|
|
299 |
bytes_per_second = (freq << (nchannels >> 1)) << bits16; |
|
300 |
|
|
301 |
linfo ("bytes per second %d\n", bytes_per_second); |
|
302 |
|
|
303 |
linfo ("fragments %d, fragstotal %d, fragsize %d, bytes %d, bufsize %d\n", |
|
304 |
abinfo.fragments, |
|
305 |
abinfo.fragstotal, |
|
306 |
abinfo.fragsize, |
|
307 |
abinfo.bytes, |
|
308 |
bufsize); |
|
309 |
|
|
310 |
if (NULL == buf) { |
|
311 |
buf = malloc (bufsize); |
|
312 |
if (NULL == buf) { |
|
313 |
abort (); |
|
314 |
} |
|
315 |
} |
|
312 |
void AUD_reset (int req_freq, int req_nchannels, audfmt_e req_fmt) |
|
313 |
{ |
|
314 |
maybe_open (req_freq, req_nchannels, req_fmt, 0); |
|
315 |
} |
|
316 | 316 |
|
317 |
rpos = 0;
|
|
318 |
wpos = 0;
|
|
319 |
live = 0;
|
|
317 |
void AUD_open (int req_freq, int req_nchannels, audfmt_e req_fmt)
|
|
318 |
{
|
|
319 |
maybe_open (req_freq, req_nchannels, req_fmt, 1);
|
|
320 | 320 |
} |
321 | 321 |
|
322 | 322 |
int AUD_write (void *in_buf, int size) |
... | ... | |
324 | 324 |
int to_copy, temp; |
325 | 325 |
uint8_t *in, *out; |
326 | 326 |
|
327 |
to_copy = MIN (bufsize - live, size);
|
|
327 |
to_copy = MIN (oss.bufsize - oss.live, size);
|
|
328 | 328 |
|
329 | 329 |
temp = to_copy; |
330 | 330 |
|
331 | 331 |
in = in_buf; |
332 |
out = buf; |
|
332 |
out = oss.buf;
|
|
333 | 333 |
|
334 | 334 |
while (temp) { |
335 | 335 |
int copy; |
336 | 336 |
|
337 |
copy = MIN (temp, bufsize - wpos);
|
|
338 |
copy_fn (out + wpos, in, copy);
|
|
337 |
copy = MIN (temp, oss.bufsize - oss.wpos);
|
|
338 |
oss.copy_fn (out + oss.wpos, in, copy);
|
|
339 | 339 |
|
340 |
wpos += copy; |
|
341 |
if (wpos == bufsize) {
|
|
342 |
wpos = 0; |
|
340 |
oss.wpos += copy;
|
|
341 |
if (oss.wpos == oss.bufsize) {
|
|
342 |
oss.wpos = 0;
|
|
343 | 343 |
} |
344 | 344 |
|
345 | 345 |
temp -= copy; |
346 | 346 |
in += copy; |
347 |
live += copy; |
|
347 |
oss.live += copy;
|
|
348 | 348 |
} |
349 | 349 |
|
350 | 350 |
return to_copy; |
... | ... | |
356 | 356 |
int bytes; |
357 | 357 |
struct audio_buf_info abinfo; |
358 | 358 |
|
359 |
if (0 == live) |
|
359 |
if (0 == oss.live)
|
|
360 | 360 |
return; |
361 | 361 |
|
362 |
res = ioctl (audio_fd, SNDCTL_DSP_GETOSPACE, &abinfo); |
|
362 |
if (oss.is_mapped) { |
|
363 |
count_info info; |
|
364 |
|
|
365 |
res = ioctl (oss.fd, SNDCTL_DSP_GETOPTR, &info); |
|
366 |
if (-1 == res) { |
|
367 |
int err; |
|
368 |
|
|
369 |
err = errno; |
|
370 |
lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err)); |
|
371 |
return; |
|
372 |
} |
|
373 |
|
|
374 |
if (info.ptr > oss.old_optr) { |
|
375 |
bytes = info.ptr - oss.old_optr; |
|
376 |
} |
|
377 |
else { |
|
378 |
bytes = oss.bufsize + info.ptr - oss.old_optr; |
|
379 |
} |
|
380 |
|
|
381 |
oss.old_optr = info.ptr; |
|
382 |
oss.live -= bytes; |
|
383 |
return; |
|
384 |
} |
|
385 |
|
|
386 |
res = ioctl (oss.fd, SNDCTL_DSP_GETOSPACE, &abinfo); |
|
363 | 387 |
|
364 | 388 |
if (-1 == res) { |
365 | 389 |
int err; |
... | ... | |
369 | 393 |
} |
370 | 394 |
|
371 | 395 |
bytes = abinfo.bytes; |
372 |
bytes = MIN (live, bytes); |
|
396 |
bytes = MIN (oss.live, bytes);
|
|
373 | 397 |
#if 0 |
374 | 398 |
bytes = (bytes / fragsize) * fragsize; |
375 | 399 |
#endif |
... | ... | |
377 | 401 |
while (bytes) { |
378 | 402 |
int left, play, written; |
379 | 403 |
|
380 |
left = bufsize - rpos;
|
|
404 |
left = oss.bufsize - oss.rpos;
|
|
381 | 405 |
play = MIN (left, bytes); |
382 |
written = write (audio_fd, (void *) ((uint32_t) buf + rpos), play);
|
|
406 |
written = write (oss.fd, (void *) ((uint32_t) oss.buf + oss.rpos), play);
|
|
383 | 407 |
|
384 | 408 |
if (-1 == written) { |
385 | 409 |
if (EAGAIN == errno || EINTR == errno) { |
... | ... | |
391 | 415 |
} |
392 | 416 |
|
393 | 417 |
play = written; |
394 |
live -= play; |
|
395 |
rpos += play; |
|
418 |
oss.live -= play;
|
|
419 |
oss.rpos += play;
|
|
396 | 420 |
bytes -= play; |
397 | 421 |
|
398 |
if (rpos == bufsize) {
|
|
399 |
rpos = 0; |
|
422 |
if (oss.rpos == oss.bufsize) {
|
|
423 |
oss.rpos = 0;
|
|
400 | 424 |
} |
401 | 425 |
} |
402 | 426 |
} |
... | ... | |
406 | 430 |
int res; |
407 | 431 |
struct count_info info; |
408 | 432 |
|
409 |
res = ioctl (audio_fd, SNDCTL_DSP_GETOPTR, &info);
|
|
433 |
res = ioctl (oss.fd, SNDCTL_DSP_GETOPTR, &info);
|
|
410 | 434 |
if (-1 == res) { |
411 | 435 |
int err; |
412 | 436 |
|
... | ... | |
420 | 444 |
} |
421 | 445 |
} |
422 | 446 |
|
423 |
void AUD_adjust_estimate (int _leftover)
|
|
447 |
void AUD_adjust_estimate (int leftover) |
|
424 | 448 |
{ |
425 |
leftover = _leftover;
|
|
449 |
oss.leftover = leftover;
|
|
426 | 450 |
} |
427 | 451 |
|
428 | 452 |
int AUD_get_free (void) |
429 | 453 |
{ |
430 | 454 |
int free, elapsed; |
431 | 455 |
|
432 |
free = bufsize - live;
|
|
456 |
free = oss.bufsize - oss.live;
|
|
433 | 457 |
|
434 | 458 |
if (0 == free) |
435 | 459 |
return 0; |
436 | 460 |
|
437 | 461 |
elapsed = free; |
438 |
switch (estimate) {
|
|
462 |
switch (est) { |
|
439 | 463 |
case DONT: |
440 | 464 |
break; |
441 | 465 |
|
... | ... | |
456 | 480 |
|
457 | 481 |
case TID: |
458 | 482 |
{ |
459 |
static uint64_t old_ticks; |
|
460 | 483 |
uint64_t ticks, delta; |
461 | 484 |
uint64_t ua_elapsed; |
462 | 485 |
uint64_t al_elapsed; |
463 | 486 |
|
464 | 487 |
ticks = qemu_get_clock(rt_clock); |
465 |
delta = ticks - old_ticks; |
|
466 |
old_ticks = ticks; |
|
488 |
delta = ticks - oss.old_ticks;
|
|
489 |
oss.old_ticks = ticks;
|
|
467 | 490 |
|
468 |
ua_elapsed = (delta * bytes_per_second) / 1000; |
|
491 |
ua_elapsed = (delta * oss.bytes_per_second) / 1000;
|
|
469 | 492 |
al_elapsed = ua_elapsed & ~3ULL; |
470 | 493 |
|
471 | 494 |
ldebug ("tid elapsed %llu bytes\n", ua_elapsed); |
... | ... | |
475 | 498 |
else |
476 | 499 |
elapsed = al_elapsed; |
477 | 500 |
|
478 |
elapsed += leftover; |
|
501 |
elapsed += oss.leftover;
|
|
479 | 502 |
} |
480 | 503 |
} |
481 | 504 |
|
... | ... | |
490 | 513 |
|
491 | 514 |
int AUD_get_live (void) |
492 | 515 |
{ |
493 |
return live; |
|
516 |
return oss.live;
|
|
494 | 517 |
} |
495 | 518 |
|
496 | 519 |
int AUD_get_buffer_size (void) |
497 | 520 |
{ |
498 |
return bufsize; |
|
521 |
return oss.bufsize; |
|
522 |
} |
|
523 |
|
|
524 |
#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE" |
|
525 |
#define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS" |
|
526 |
#define QC_OSS_MMAP "QEMU_OSS_MMAP" |
|
527 |
|
|
528 |
static int get_conf_val (const char *key, int defval) |
|
529 |
{ |
|
530 |
int val = defval; |
|
531 |
char *strval; |
|
532 |
|
|
533 |
strval = getenv (key); |
|
534 |
if (strval) { |
|
535 |
val = atoi (strval); |
|
536 |
} |
|
537 |
|
|
538 |
return val; |
|
499 | 539 |
} |
500 | 540 |
|
501 | 541 |
void AUD_init (void) |
502 | 542 |
{ |
503 | 543 |
int fsp; |
504 |
int _fragsize = 4096; |
|
505 | 544 |
|
506 | 545 |
DEREF (pab); |
507 | 546 |
|
508 |
fsp = _fragsize; |
|
547 |
conf.fragsize = get_conf_val (QC_OSS_FRAGSIZE, conf.fragsize); |
|
548 |
conf.nfrags = get_conf_val (QC_OSS_NFRAGS, conf.nfrags); |
|
549 |
conf.try_mmap = get_conf_val (QC_OSS_MMAP, conf.try_mmap); |
|
550 |
|
|
551 |
fsp = conf.fragsize; |
|
509 | 552 |
if (0 != (fsp & (fsp - 1))) { |
510 | 553 |
Fail ("fragment size %d is not power of 2", fsp); |
511 | 554 |
} |
512 | 555 |
|
513 |
conf_fragsize = lsbindex (fsp);
|
|
556 |
conf.fragsize = lsbindex (fsp);
|
|
514 | 557 |
} |
515 | 558 |
|
516 | 559 |
#else |
Also available in: Unified diff