diff options
Diffstat (limited to 'audio/audio_template.h')
-rw-r--r-- | audio/audio_template.h | 262 |
1 files changed, 195 insertions, 67 deletions
diff --git a/audio/audio_template.h b/audio/audio_template.h index be32c68b3b..23d024201a 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -23,52 +23,159 @@ */ #ifdef DAC +#define NAME "playback" +#define HWBUF hw->mix_buf #define TYPE out -#define HW glue (HWVoice, Out) -#define SW glue (SWVoice, Out) +#define HW HWVoiceOut +#define SW SWVoiceOut #else +#define NAME "capture" #define TYPE in -#define HW glue (HWVoice, In) -#define SW glue (SWVoice, In) +#define HW HWVoiceIn +#define SW SWVoiceIn +#define HWBUF hw->conv_buf #endif -static int glue (audio_pcm_hw_init_, TYPE) ( - HW *hw, - audsettings_t *as +static void glue (audio_init_nb_voices_, TYPE) ( + AudioState *s, + struct audio_driver *drv ) { - glue (audio_pcm_hw_free_resources_, TYPE) (hw); + int max_voices = glue (drv->max_voices_, TYPE); + int voice_size = glue (drv->voice_size_, TYPE); - if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) { - return -1; + if (glue (s->nb_hw_voices_, TYPE) > max_voices) { + if (!max_voices) { +#ifdef DAC + dolog ("Driver `%s' does not support " NAME "\n", drv->name); +#endif + } + else { + dolog ("Driver `%s' does not support %d " NAME " voices, max %d\n", + drv->name, + glue (s->nb_hw_voices_, TYPE), + max_voices); + } + glue (s->nb_hw_voices_, TYPE) = max_voices; } - if (audio_bug (AUDIO_FUNC, hw->samples <= 0)) { - dolog ("hw->samples=%d\n", hw->samples); + if (audio_bug (AUDIO_FUNC, !voice_size && max_voices)) { + dolog ("drv=`%s' voice_size=0 max_voices=%d\n", + drv->name, max_voices); + glue (s->nb_hw_voices_, TYPE) = 0; + } + + if (audio_bug (AUDIO_FUNC, voice_size && !max_voices)) { + dolog ("drv=`%s' voice_size=%d max_voices=0\n", + drv->name, voice_size); + } +} + +static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw) +{ + if (HWBUF) { + qemu_free (HWBUF); + } + + HWBUF = NULL; +} + +static int glue (audio_pcm_hw_alloc_resources_, TYPE) (HW *hw) +{ + HWBUF = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (st_sample_t)); + if (!HWBUF) { + dolog ("Could not allocate " NAME " buffer (%d samples)\n", + hw->samples); return -1; } - LIST_INIT (&hw->sw_head); + return 0; +} + +static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw) +{ + if (sw->buf) { + qemu_free (sw->buf); + } + + if (sw->rate) { + st_rate_stop (sw->rate); + } + + sw->buf = NULL; + sw->rate = NULL; +} + +static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw) +{ + int samples; + #ifdef DAC - hw->clip = - mixeng_clip + samples = sw->hw->samples; #else - hw->conv = - mixeng_conv + samples = ((int64_t) sw->hw->samples << 32) / sw->ratio; #endif - [hw->info.nchannels == 2] - [hw->info.sign] - [hw->info.swap_endian] - [hw->info.bits == 16]; - if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) { - glue (hw->pcm_ops->fini_, TYPE) (hw); + sw->buf = audio_calloc (AUDIO_FUNC, samples, sizeof (st_sample_t)); + if (!sw->buf) { + dolog ("Could not allocate buffer for `%s' (%d samples)\n", + SW_NAME (sw), samples); return -1; } +#ifdef DAC + sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq); +#else + sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq); +#endif + if (!sw->rate) { + qemu_free (sw->buf); + sw->buf = NULL; + return -1; + } return 0; } +static int glue (audio_pcm_sw_init_, TYPE) ( + SW *sw, + HW *hw, + const char *name, + audsettings_t *as, + int endian + ) +{ + int err; + + audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (endian)); + sw->hw = hw; + sw->active = 0; +#ifdef DAC + sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq; + sw->total_hw_samples_mixed = 0; + sw->empty = 1; +#else + sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq; +#endif + +#ifdef DAC + sw->conv = mixeng_conv +#else + sw->clip = mixeng_clip +#endif + [sw->info.nchannels == 2] + [sw->info.sign] + [sw->info.swap_endian] + [sw->info.bits == 16]; + + sw->name = qemu_strdup (name); + err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw); + if (err) { + qemu_free (sw->name); + sw->name = NULL; + } + return err; +} + static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw) { glue (audio_pcm_sw_free_resources_, TYPE) (sw); @@ -117,31 +224,6 @@ static HW *glue (audio_pcm_hw_find_any_enabled_, TYPE) (AudioState *s, HW *hw) return NULL; } -static HW *glue (audio_pcm_hw_find_any_passive_, TYPE) (AudioState *s) -{ - if (glue (s->nb_hw_voices_, TYPE)) { - struct audio_driver *drv = s->drv; - - if (audio_bug (AUDIO_FUNC, !drv)) { - dolog ("No host audio driver\n"); - return NULL; - } - - HW *hw = audio_calloc (AUDIO_FUNC, 1, glue (drv->voice_size_, TYPE)); - if (!hw) { - dolog ("Can not allocate voice `%s' size %d\n", - drv->name, glue (drv->voice_size_, TYPE)); - return NULL; - } - - LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries); - glue (s->nb_hw_voices_, TYPE) -= 1; - return hw; - } - - return NULL; -} - static HW *glue (audio_pcm_hw_find_specific_, TYPE) ( AudioState *s, HW *hw, @@ -159,23 +241,63 @@ static HW *glue (audio_pcm_hw_find_specific_, TYPE) ( static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as) { HW *hw; + struct audio_driver *drv = s->drv; - hw = glue (audio_pcm_hw_find_any_passive_, TYPE) (s); - if (hw) { - hw->pcm_ops = s->drv->pcm_ops; - if (!hw->pcm_ops) { - return NULL; - } + if (!glue (s->nb_hw_voices_, TYPE)) { + return NULL; + } - if (glue (audio_pcm_hw_init_, TYPE) (hw, as)) { - glue (audio_pcm_hw_gc_, TYPE) (s, &hw); - return NULL; - } - else { - return hw; - } + if (audio_bug (AUDIO_FUNC, !drv)) { + dolog ("No host audio driver\n"); + return NULL; } + if (audio_bug (AUDIO_FUNC, !drv->pcm_ops)) { + dolog ("Host audio driver without pcm_ops\n"); + return NULL; + } + + hw = audio_calloc (AUDIO_FUNC, 1, glue (drv->voice_size_, TYPE)); + if (!hw) { + dolog ("Can not allocate voice `%s' size %d\n", + drv->name, glue (drv->voice_size_, TYPE)); + return NULL; + } + + hw->pcm_ops = drv->pcm_ops; + LIST_INIT (&hw->sw_head); + + if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) { + goto err0; + } + + if (audio_bug (AUDIO_FUNC, hw->samples <= 0)) { + dolog ("hw->samples=%d\n", hw->samples); + goto err1; + } + +#ifdef DAC + hw->clip = mixeng_clip +#else + hw->conv = mixeng_conv +#endif + [hw->info.nchannels == 2] + [hw->info.sign] + [hw->info.swap_endian] + [hw->info.bits == 16]; + + if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) { + goto err1; + } + + LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries); + glue (s->nb_hw_voices_, TYPE) -= 1; + return hw; + + err1: + glue (hw->pcm_ops->fini_, TYPE) (hw); + err0: + qemu_free (hw); return NULL; } @@ -206,7 +328,8 @@ static HW *glue (audio_pcm_hw_add_, TYPE) (AudioState *s, audsettings_t *as) static SW *glue (audio_pcm_create_voice_pair_, TYPE) ( AudioState *s, const char *sw_name, - audsettings_t *as + audsettings_t *as, + int sw_endian ) { SW *sw; @@ -234,7 +357,7 @@ static SW *glue (audio_pcm_create_voice_pair_, TYPE) ( glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw); - if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) { + if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as, sw_endian)) { goto err3; } @@ -256,6 +379,7 @@ static void glue (audio_close_, TYPE) (AudioState *s, SW *sw) glue (audio_pcm_hw_gc_, TYPE) (s, &sw->hw); qemu_free (sw); } + void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw) { if (sw) { @@ -275,7 +399,8 @@ SW *glue (AUD_open_, TYPE) ( const char *name, void *callback_opaque , audio_callback_fn_t callback_fn, - audsettings_t *as + audsettings_t *as, + int sw_endian ) { AudioState *s; @@ -347,15 +472,16 @@ SW *glue (AUD_open_, TYPE) ( goto fail; } - if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) { + glue (audio_pcm_sw_fini_, TYPE) (sw); + if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as, sw_endian)) { goto fail; } } else { - sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as); + sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as, sw_endian); if (!sw) { dolog ("Failed to create voice `%s'\n", name); - goto fail; + return NULL; } } @@ -435,3 +561,5 @@ uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts) #undef TYPE #undef HW #undef SW +#undef HWBUF +#undef NAME |