blob: 96370458b391159a6ce431358bfc188acb6d0c91 [file] [log] [blame]
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -08001/*
2 * QEMU Audio subsystem header
3 *
4 * Copyright (c) 2005 Vassili Karpov (malc)
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
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
22 * THE SOFTWARE.
23 */
24
25#ifdef DAC
26#define NAME "playback"
27#define HWBUF hw->mix_buf
28#define TYPE out
29#define HW HWVoiceOut
30#define SW SWVoiceOut
31#else
32#define NAME "capture"
33#define TYPE in
34#define HW HWVoiceIn
35#define SW SWVoiceIn
36#define HWBUF hw->conv_buf
37#endif
38
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070039static void glue (audio_init_nb_voices_, TYPE) (struct audio_driver *drv)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080040{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070041 AudioState *s = &glob_audio_state;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080042 int max_voices = glue (drv->max_voices_, TYPE);
43 int voice_size = glue (drv->voice_size_, TYPE);
44
45 if (glue (s->nb_hw_voices_, TYPE) > max_voices) {
46 if (!max_voices) {
47#ifdef DAC
48 dolog ("Driver `%s' does not support " NAME "\n", drv->name);
49#endif
50 }
51 else {
52 dolog ("Driver `%s' does not support %d " NAME " voices, max %d\n",
53 drv->name,
54 glue (s->nb_hw_voices_, TYPE),
55 max_voices);
56 }
57 glue (s->nb_hw_voices_, TYPE) = max_voices;
58 }
59
60 if (audio_bug (AUDIO_FUNC, !voice_size && max_voices)) {
61 dolog ("drv=`%s' voice_size=0 max_voices=%d\n",
62 drv->name, max_voices);
63 glue (s->nb_hw_voices_, TYPE) = 0;
64 }
65
66 if (audio_bug (AUDIO_FUNC, voice_size && !max_voices)) {
67 dolog ("drv=`%s' voice_size=%d max_voices=0\n",
68 drv->name, voice_size);
69 }
70}
71
72static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)
73{
74 if (HWBUF) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +010075 g_free (HWBUF);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080076 }
77
78 HWBUF = NULL;
79}
80
81static int glue (audio_pcm_hw_alloc_resources_, TYPE) (HW *hw)
82{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070083 HWBUF = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (struct st_sample));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080084 if (!HWBUF) {
85 dolog ("Could not allocate " NAME " buffer (%d samples)\n",
86 hw->samples);
87 return -1;
88 }
89
90 return 0;
91}
92
93static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
94{
95 if (sw->buf) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +010096 g_free (sw->buf);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -080097 }
98
99 if (sw->rate) {
100 st_rate_stop (sw->rate);
101 }
102
103 sw->buf = NULL;
104 sw->rate = NULL;
105}
106
107static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
108{
109 int samples;
110
111#ifdef DAC
112 samples = sw->hw->samples;
113#else
114 samples = ((int64_t) sw->hw->samples << 32) / sw->ratio;
115#endif
116
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700117 sw->buf = audio_calloc (AUDIO_FUNC, samples, sizeof (struct st_sample));
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800118 if (!sw->buf) {
119 dolog ("Could not allocate buffer for `%s' (%d samples)\n",
120 SW_NAME (sw), samples);
121 return -1;
122 }
123
124#ifdef DAC
125 sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);
126#else
127 sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);
128#endif
129 if (!sw->rate) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100130 g_free (sw->buf);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800131 sw->buf = NULL;
132 return -1;
133 }
134 return 0;
135}
136
137static int glue (audio_pcm_sw_init_, TYPE) (
138 SW *sw,
139 HW *hw,
140 const char *name,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700141 struct audsettings *as
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800142 )
143{
144 int err;
145
146 audio_pcm_init_info (&sw->info, as);
147 sw->hw = hw;
148 sw->active = 0;
149#ifdef DAC
150 sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;
151 sw->total_hw_samples_mixed = 0;
152 sw->empty = 1;
153#else
154 sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
155#endif
156
157#ifdef DAC
158 sw->conv = mixeng_conv
159#else
160 sw->clip = mixeng_clip
161#endif
162 [sw->info.nchannels == 2]
163 [sw->info.sign]
164 [sw->info.swap_endianness]
165 [audio_bits_to_index (sw->info.bits)];
166
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100167 sw->name = g_strdup (name);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800168 err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
169 if (err) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100170 g_free (sw->name);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800171 sw->name = NULL;
172 }
173 return err;
174}
175
176static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw)
177{
178 glue (audio_pcm_sw_free_resources_, TYPE) (sw);
179 if (sw->name) {
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100180 g_free (sw->name);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800181 sw->name = NULL;
182 }
183}
184
185static void glue (audio_pcm_hw_add_sw_, TYPE) (HW *hw, SW *sw)
186{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700187 QLIST_INSERT_HEAD (&hw->sw_head, sw, entries);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800188}
189
190static void glue (audio_pcm_hw_del_sw_, TYPE) (SW *sw)
191{
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700192 QLIST_REMOVE (sw, entries);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800193}
194
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700195static void glue (audio_pcm_hw_gc_, TYPE) (HW **hwp)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800196{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700197 AudioState *s = &glob_audio_state;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800198 HW *hw = *hwp;
199
200 if (!hw->sw_head.lh_first) {
201#ifdef DAC
202 audio_detach_capture (hw);
203#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700204 QLIST_REMOVE (hw, entries);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800205 glue (s->nb_hw_voices_, TYPE) += 1;
206 glue (audio_pcm_hw_free_resources_ ,TYPE) (hw);
207 BEGIN_NOSIGALRM
208 glue (hw->pcm_ops->fini_, TYPE) (hw);
209 END_NOSIGALRM
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100210 g_free (hw);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800211 *hwp = NULL;
212 }
213}
214
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700215static HW *glue (audio_pcm_hw_find_any_, TYPE) (HW *hw)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800216{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700217 AudioState *s = &glob_audio_state;
218 return hw ? hw->entries.le_next : glue (s->hw_head_, TYPE).lh_first;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800219}
220
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700221static HW *glue (audio_pcm_hw_find_any_enabled_, TYPE) (HW *hw)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800222{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700223 while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800224 if (hw->enabled) {
225 return hw;
226 }
227 }
228 return NULL;
229}
230
231static HW *glue (audio_pcm_hw_find_specific_, TYPE) (
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800232 HW *hw,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700233 struct audsettings *as
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800234 )
235{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700236 while ((hw = glue (audio_pcm_hw_find_any_, TYPE) (hw))) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800237 if (audio_pcm_info_eq (&hw->info, as)) {
238 return hw;
239 }
240 }
241 return NULL;
242}
243
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700244static HW *glue (audio_pcm_hw_add_new_, TYPE) (struct audsettings *as)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800245{
246 HW *hw;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700247 AudioState *s = &glob_audio_state;
David 'Digit' Turner5d0e37b2011-01-02 12:58:51 +0100248 struct audio_driver *drv = s->drv;
249 int err;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800250
251 if (!glue (s->nb_hw_voices_, TYPE)) {
252 return NULL;
253 }
254
255 if (audio_bug (AUDIO_FUNC, !drv)) {
256 dolog ("No host audio driver\n");
257 return NULL;
258 }
259
260 if (audio_bug (AUDIO_FUNC, !drv->pcm_ops)) {
261 dolog ("Host audio driver without pcm_ops\n");
262 return NULL;
263 }
264
265 hw = audio_calloc (AUDIO_FUNC, 1, glue (drv->voice_size_, TYPE));
266 if (!hw) {
267 dolog ("Can not allocate voice `%s' size %d\n",
268 drv->name, glue (drv->voice_size_, TYPE));
269 return NULL;
270 }
271
272 hw->pcm_ops = drv->pcm_ops;
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700273 QLIST_INIT (&hw->sw_head);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800274#ifdef DAC
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700275 QLIST_INIT (&hw->cap_head);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800276#endif
277 BEGIN_NOSIGALRM
278 err = glue (hw->pcm_ops->init_, TYPE) (hw, as);
279 END_NOSIGALRM
280 if (err)
281 goto err0;
282
283 if (audio_bug (AUDIO_FUNC, hw->samples <= 0)) {
284 dolog ("hw->samples=%d\n", hw->samples);
285 goto err1;
286 }
287
288#ifdef DAC
289 hw->clip = mixeng_clip
290#else
291 hw->conv = mixeng_conv
292#endif
293 [hw->info.nchannels == 2]
294 [hw->info.sign]
295 [hw->info.swap_endianness]
296 [audio_bits_to_index (hw->info.bits)];
297
298 if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
299 goto err1;
300 }
301
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700302 QLIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800303 glue (s->nb_hw_voices_, TYPE) -= 1;
304#ifdef DAC
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700305 audio_attach_capture (hw);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800306#endif
307 return hw;
308
309 err1:
310 BEGIN_NOSIGALRM
311 glue (hw->pcm_ops->fini_, TYPE) (hw);
312 END_NOSIGALRM
313 err0:
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100314 g_free (hw);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800315 return NULL;
316}
317
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700318static HW *glue (audio_pcm_hw_add_, TYPE) (struct audsettings *as)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800319{
320 HW *hw;
321
322 if (glue (conf.fixed_, TYPE).enabled && glue (conf.fixed_, TYPE).greedy) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700323 hw = glue (audio_pcm_hw_add_new_, TYPE) (as);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800324 if (hw) {
325 return hw;
326 }
327 }
328
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700329 hw = glue (audio_pcm_hw_find_specific_, TYPE) (NULL, as);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800330 if (hw) {
331 return hw;
332 }
333
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700334 hw = glue (audio_pcm_hw_add_new_, TYPE) (as);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800335 if (hw) {
336 return hw;
337 }
338
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700339 return glue (audio_pcm_hw_find_any_, TYPE) (NULL);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800340}
341
342static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800343 const char *sw_name,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700344 struct audsettings *as
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800345 )
346{
347 SW *sw;
348 HW *hw;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700349 struct audsettings hw_as;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800350
351 if (glue (conf.fixed_, TYPE).enabled) {
352 hw_as = glue (conf.fixed_, TYPE).settings;
353 }
354 else {
355 hw_as = *as;
356 }
357
358 sw = audio_calloc (AUDIO_FUNC, 1, sizeof (*sw));
359 if (!sw) {
360 dolog ("Could not allocate soft voice `%s' (%zu bytes)\n",
361 sw_name ? sw_name : "unknown", sizeof (*sw));
362 goto err1;
363 }
364
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700365 hw = glue (audio_pcm_hw_add_, TYPE) (&hw_as);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800366 if (!hw) {
367 goto err2;
368 }
369
370 glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
371
372 if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
373 goto err3;
374 }
375
376 return sw;
377
378err3:
379 glue (audio_pcm_hw_del_sw_, TYPE) (sw);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700380 glue (audio_pcm_hw_gc_, TYPE) (&hw);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800381err2:
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100382 g_free (sw);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800383err1:
384 return NULL;
385}
386
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700387static void glue (audio_close_, TYPE) (SW *sw)
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800388{
389 glue (audio_pcm_sw_fini_, TYPE) (sw);
390 glue (audio_pcm_hw_del_sw_, TYPE) (sw);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700391 glue (audio_pcm_hw_gc_, TYPE) (&sw->hw);
David 'Digit' Turneraa8236d2014-01-10 17:02:29 +0100392 g_free (sw);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800393}
394
395void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
396{
397 if (sw) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700398 if (audio_bug (AUDIO_FUNC, !card)) {
399 dolog ("card=%p\n", card);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800400 return;
401 }
402
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700403 glue (audio_close_, TYPE) (sw);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800404 }
405}
406
407SW *glue (AUD_open_, TYPE) (
408 QEMUSoundCard *card,
409 SW *sw,
410 const char *name,
411 void *callback_opaque ,
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700412 audio_callback_fn callback_fn,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700413 struct audsettings *as
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800414 )
415{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700416 AudioState *s = &glob_audio_state;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800417#ifdef DAC
418 int live = 0;
419 SW *old_sw = NULL;
420#endif
421
422 ldebug ("open %s, freq %d, nchannels %d, fmt %d\n",
423 name, as->freq, as->nchannels, as->fmt);
424
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700425 if (audio_bug (AUDIO_FUNC, !card || !name || !callback_fn || !as)) {
426 dolog ("card=%p name=%p callback_fn=%p as=%p\n",
427 card, name, callback_fn, as);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800428 goto fail;
429 }
430
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800431 if (audio_bug (AUDIO_FUNC, audio_validate_settings (as))) {
432 audio_print_settings (as);
433 goto fail;
434 }
435
David 'Digit' Turner5d0e37b2011-01-02 12:58:51 +0100436 if (audio_bug (AUDIO_FUNC, !s->drv)) {
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800437 dolog ("Can not open `%s' (no host audio driver)\n", name);
438 goto fail;
439 }
440
441 if (sw && audio_pcm_info_eq (&sw->info, as)) {
442 return sw;
443 }
444
445#ifdef DAC
446 if (conf.plive && sw && (!sw->active && !sw->empty)) {
447 live = sw->total_hw_samples_mixed;
448
449#ifdef DEBUG_PLIVE
450 dolog ("Replacing voice %s with %d live samples\n", SW_NAME (sw), live);
451 dolog ("Old %s freq %d, bits %d, channels %d\n",
452 SW_NAME (sw), sw->info.freq, sw->info.bits, sw->info.nchannels);
453 dolog ("New %s freq %d, bits %d, channels %d\n",
454 name,
David 'Digit' Turner5d0e37b2011-01-02 12:58:51 +0100455 as->freq,
456 (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) ? 16 : 8,
457 as->nchannels);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800458#endif
459
460 if (live) {
461 old_sw = sw;
462 old_sw->callback.fn = NULL;
463 sw = NULL;
464 }
465 }
466#endif
467
468 if (!glue (conf.fixed_, TYPE).enabled && sw) {
469 glue (AUD_close_, TYPE) (card, sw);
470 sw = NULL;
471 }
472
473 if (sw) {
474 HW *hw = sw->hw;
475
476 if (!hw) {
477 dolog ("Internal logic error voice `%s' has no hardware store\n",
478 SW_NAME (sw));
479 goto fail;
480 }
481
482 glue (audio_pcm_sw_fini_, TYPE) (sw);
483 if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) {
484 goto fail;
485 }
486 }
487 else {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700488 sw = glue (audio_pcm_create_voice_pair_, TYPE) (name, as);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800489 if (!sw) {
490 dolog ("Failed to create voice `%s'\n", name);
491 return NULL;
492 }
493 }
494
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700495 sw->card = card;
496 sw->vol = nominal_volume;
497 sw->callback.fn = callback_fn;
498 sw->callback.opaque = callback_opaque;
David 'Digit' Turner5164d3c2010-12-22 16:55:41 +0100499#ifdef DAC
500 sw->empty = 1;
501#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800502
503#ifdef DAC
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700504 if (live) {
505 int mixed =
506 (live << old_sw->info.shift)
507 * old_sw->info.bytes_per_second
508 / sw->info.bytes_per_second;
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800509
510#ifdef DEBUG_PLIVE
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700511 dolog ("Silence will be mixed %d\n", mixed);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800512#endif
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700513 sw->total_hw_samples_mixed += mixed;
514 }
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800515#endif
516
517#ifdef DEBUG_AUDIO
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700518 dolog ("%s\n", name);
519 audio_pcm_print_info ("hw", &sw->hw->info);
520 audio_pcm_print_info ("sw", &sw->info);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800521#endif
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800522
523 return sw;
524
525 fail:
526 glue (AUD_close_, TYPE) (card, sw);
527 return NULL;
528}
529
530int glue (AUD_is_active_, TYPE) (SW *sw)
531{
532 return sw ? sw->active : 0;
533}
534
535void glue (AUD_init_time_stamp_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
536{
537 if (!sw) {
538 return;
539 }
540
541 ts->old_ts = sw->hw->ts_helper;
542}
543
544uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
545{
546 uint64_t delta, cur_ts, old_ts;
547
548 if (!sw) {
549 return 0;
550 }
551
552 cur_ts = sw->hw->ts_helper;
553 old_ts = ts->old_ts;
David 'Digit' Turner5d0e37b2011-01-02 12:58:51 +0100554 /* dolog ("cur %" PRId64 " old %" PRId64 "\n", cur_ts, old_ts); */
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800555
556 if (cur_ts >= old_ts) {
557 delta = cur_ts - old_ts;
558 }
559 else {
560 delta = UINT64_MAX - old_ts + cur_ts;
561 }
562
563 if (!delta) {
564 return 0;
565 }
566
David 'Digit' Turnera5d41202010-05-10 18:37:10 -0700567 return muldiv64 (delta, sw->hw->info.freq, 1000000);
The Android Open Source Project8b23a6c2009-03-03 19:30:32 -0800568}
569
570#undef TYPE
571#undef HW
572#undef SW
573#undef HWBUF
574#undef NAME