2 * QEMU OSS Audio output driver
4 * Copyright (c) 2003 Vassili Karpov (malc)
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37 #include <sys/types.h>
38 #include <sys/ioctl.h>
39 #include <sys/soundcard.h>
42 /* http://www.df.lth.se/~john_e/gems/gem002d.html */
43 /* http://www.multi-platforms.com/Tips/PopCount.htm */
44 static inline uint32_t popcount (uint32_t u
)
46 u
= ((u
&0x55555555) + ((u
>>1)&0x55555555));
47 u
= ((u
&0x33333333) + ((u
>>2)&0x33333333));
48 u
= ((u
&0x0f0f0f0f) + ((u
>>4)&0x0f0f0f0f));
49 u
= ((u
&0x00ff00ff) + ((u
>>8)&0x00ff00ff));
50 u
= ( u
&0x0000ffff) + (u
>>16);
54 static inline uint32_t lsbindex (uint32_t u
)
56 return popcount ((u
&-u
)-1);
59 #define MIN(a, b) ((a)>(b)?(b):(a))
60 #define MAX(a, b) ((a)<(b)?(b):(a))
62 #define DEREF(x) (void)x
63 #define log(...) fprintf (stderr, "oss: " __VA_ARGS__)
64 #define ERRFail(...) do { \
66 fprintf (stderr, "oss: " __VA_ARGS__); \
67 fprintf (stderr, "system error: %s\n", strerror (_errno)); \
70 #define Fail(...) do { \
71 fprintf (stderr, "oss: " __VA_ARGS__); \
72 fprintf (stderr, "\n"); \
77 #define lwarn(...) fprintf (stderr, "oss: " __VA_ARGS__)
78 #define linfo(...) fprintf (stderr, "oss: " __VA_ARGS__)
79 #define ldebug(...) fprintf (stderr, "oss: " __VA_ARGS__)
87 #define IOCTL(args) do { \
88 int ret = ioctl args; \
92 ldebug ("ioctl " #args " = %d\n", ret); \
104 int bytes_per_second
;
113 void (*copy_fn
)(void *, void *, int);
114 } oss
= { .fd
= -1 };
126 static enum {DONT
, DSP
, TID
} est
= DONT
;
128 static void copy_no_conversion (void *dst
, void *src
, int size
)
130 memcpy (dst
, src
, size
);
133 static void copy_u16_to_s16 (void *dst
, void *src
, int size
)
141 for (i
= 0; i
< size
/ 2; i
++) {
142 out
[i
] = in
[i
] + 0x8000;
146 static void pab (struct audio_buf_info
*abinfo
)
150 ldebug ("fragments %d, fragstotal %d, fragsize %d, bytes %d\n"
151 "rpos %d, wpos %d, live %d\n",
159 static void do_open ()
162 audio_buf_info abinfo
;
163 int fmt
, freq
, nchannels
;
166 if (-1 == munmap (oss
.buf
, oss
.bufsize
)) {
167 ERRFail ("failed to unmap audio buffer %p %d",
168 oss
.buf
, oss
.bufsize
);
176 oss
.fd
= open ("/dev/dsp", O_RDWR
| O_NONBLOCK
);
178 ERRFail ("can not open /dev/dsp");
183 nchannels
= oss
.nchannels
;
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
));
191 mmmmssss
= (conf
.nfrags
<< 16) | conf
.fragsize
;
192 IOCTL ((oss
.fd
, SNDCTL_DSP_SETFRAGMENT
, &mmmmssss
));
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",
203 oss
.nchannels
, nchannels
,
207 IOCTL ((oss
.fd
, SNDCTL_DSP_GETOSPACE
, &abinfo
));
209 oss
.nfrags
= abinfo
.fragstotal
;
210 oss
.fragsize
= abinfo
.fragsize
;
211 oss
.bufsize
= oss
.nfrags
* oss
.fragsize
;
214 oss
.bytes_per_second
= (freq
<< (nchannels
>> 1)) << oss
.bits16
;
216 linfo ("bytes per second %d\n", oss
.bytes_per_second
);
218 linfo ("fragments %d, fragstotal %d, fragsize %d, bytes %d, bufsize %d\n",
225 oss
.buf
= MAP_FAILED
;
229 oss
.buf
= mmap (NULL
, oss
.bufsize
, PROT_WRITE
, MAP_SHARED
, oss
.fd
, 0);
230 if (MAP_FAILED
== oss
.buf
) {
234 log ("failed to mmap audio, size %d, fd %d\n"
236 oss
.bufsize
, oss
.fd
, strerror (err
));
244 if (MAP_FAILED
== oss
.buf
) {
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
);
261 IOCTL ((oss
.fd
, SNDCTL_DSP_SETTRIGGER
, &trig
));
262 trig
= PCM_ENABLE_OUTPUT
;
263 IOCTL ((oss
.fd
, SNDCTL_DSP_SETTRIGGER
, &trig
));
267 static void maybe_open (int req_freq
, int req_nchannels
,
268 audfmt_e req_fmt
, int force_open
)
276 oss
.copy_fn
= copy_no_conversion
;
280 Fail ("can not play 8bit signed");
284 oss_fmt
= AFMT_S16_LE
;
285 oss
.copy_fn
= copy_no_conversion
;
290 oss_fmt
= AFMT_S16_LE
;
291 oss
.copy_fn
= copy_u16_to_s16
;
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
;
312 void AUD_reset (int req_freq
, int req_nchannels
, audfmt_e req_fmt
)
314 maybe_open (req_freq
, req_nchannels
, req_fmt
, 0);
317 void AUD_open (int req_freq
, int req_nchannels
, audfmt_e req_fmt
)
319 maybe_open (req_freq
, req_nchannels
, req_fmt
, 1);
322 int AUD_write (void *in_buf
, int size
)
327 to_copy
= MIN (oss
.bufsize
- oss
.live
, size
);
337 copy
= MIN (temp
, oss
.bufsize
- oss
.wpos
);
338 oss
.copy_fn (out
+ oss
.wpos
, in
, copy
);
341 if (oss
.wpos
== oss
.bufsize
) {
357 struct audio_buf_info abinfo
;
365 res
= ioctl (oss
.fd
, SNDCTL_DSP_GETOPTR
, &info
);
370 lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err
));
374 if (info
.ptr
> oss
.old_optr
) {
375 bytes
= info
.ptr
- oss
.old_optr
;
378 bytes
= oss
.bufsize
+ info
.ptr
- oss
.old_optr
;
381 oss
.old_optr
= info
.ptr
;
386 res
= ioctl (oss
.fd
, SNDCTL_DSP_GETOSPACE
, &abinfo
);
392 lwarn ("SNDCTL_DSP_GETOSPACE failed with %s\n", strerror (err
));
395 bytes
= abinfo
.bytes
;
396 bytes
= MIN (oss
.live
, bytes
);
398 bytes
= (bytes
/ fragsize
) * fragsize
;
402 int left
, play
, written
;
404 left
= oss
.bufsize
- oss
.rpos
;
405 play
= MIN (left
, bytes
);
406 written
= write (oss
.fd
, (void *) ((uint32_t) oss
.buf
+ oss
.rpos
), play
);
409 if (EAGAIN
== errno
|| EINTR
== errno
) {
413 ERRFail ("write audio");
422 if (oss
.rpos
== oss
.bufsize
) {
428 static int get_dsp_bytes (void)
431 struct count_info info
;
433 res
= ioctl (oss
.fd
, SNDCTL_DSP_GETOPTR
, &info
);
438 lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err
));
442 ldebug ("bytes %d\n", info
.bytes
);
447 void AUD_adjust_estimate (int leftover
)
449 oss
.leftover
= leftover
;
452 int AUD_get_free (void)
456 free
= oss
.bufsize
- oss
.live
;
468 static int old_bytes
;
471 bytes
= get_dsp_bytes ();
475 elapsed
= bytes
- old_bytes
;
477 ldebug ("dsp elapsed %d bytes\n", elapsed
);
483 uint64_t ticks
, delta
;
487 ticks
= qemu_get_clock(rt_clock
);
488 delta
= ticks
- oss
.old_ticks
;
489 oss
.old_ticks
= ticks
;
491 ua_elapsed
= (delta
* oss
.bytes_per_second
) / 1000;
492 al_elapsed
= ua_elapsed
& ~3ULL;
494 ldebug ("tid elapsed %llu bytes\n", ua_elapsed
);
496 if (al_elapsed
> (uint64_t) INT_MAX
)
499 elapsed
= al_elapsed
;
501 elapsed
+= oss
.leftover
;
505 if (elapsed
> free
) {
506 lwarn ("audio can not keep up elapsed %d free %d\n", elapsed
, free
);
514 int AUD_get_live (void)
519 int AUD_get_buffer_size (void)
524 #define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE"
525 #define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS"
526 #define QC_OSS_MMAP "QEMU_OSS_MMAP"
528 static int get_conf_val (const char *key
, int defval
)
533 strval
= getenv (key
);
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
);
552 if (0 != (fsp
& (fsp
- 1))) {
553 Fail ("fragment size %d is not power of 2", fsp
);
556 conf
.fragsize
= lsbindex (fsp
);
565 int AUD_write (void *in_buf
, int size
)
570 void AUD_reset (int rfreq
, int rnchannels
, audfmt_e rfmt
)
574 void AUD_adjust_estimate (int _leftover
)
578 int AUD_get_free (void)
583 int AUD_get_live (void)
588 int AUD_get_buffer_size (void)