audio.c revision b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * QEMU Audio subsystem
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Copyright (c) 2003-2005 Vassili Karpov (malc)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Permission is hereby granted, free of charge, to any person obtaining a copy
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync * of this software and associated documentation files (the "Software"), to deal
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * in the Software without restriction, including without limitation the rights
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * copies of the Software, and to permit persons to whom the Software is
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * furnished to do so, subject to the following conditions:
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * The above copyright notice and this permission notice shall be included in
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * all copies or substantial portions of the Software.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * THE SOFTWARE.
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#include "../../vl_vbox.h"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/* #define DEBUG_PLIVE */
efff36b306e370346025647a158689021df2e1d1vboxsync/* #define DEBUG_LIVE */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/* #define DEBUG_OUT */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync/* #define DEBUG_CAPTURE */
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync#define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsynctypedef struct DRVAUDIO
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** The audio interface. */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /** Pointer to the driver instance. */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncconst char *audio_get_stream_name(void)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic struct {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync { /* DAC fixed settings */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync { /* ADC fixed settings */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync 0, /* plive */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/* http://www.df.lth.se/~john_e/gems/gem002d.html */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync/* http://www.multi-platforms.com/Tips/PopCount.htm */
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync return s->pDrvIns->pDrvHlp->pfnTMGetVirtualTime (s->pDrvIns);
16a9adc14900ca18e6909679a579f6833425e030vboxsync return s->pDrvIns->pDrvHlp->pfnTMGetVirtualFreq (s->pDrvIns);
16a9adc14900ca18e6909679a579f6833425e030vboxsync AUD_log (NULL, "A bug was just triggered in %s\n", funcname);
16a9adc14900ca18e6909679a579f6833425e030vboxsync AUD_log (NULL, "Save all your work and restart without audio\n");
16a9adc14900ca18e6909679a579f6833425e030vboxsync AUD_log (NULL, "Please send a bug, see www.virtualbox.org\n");
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncvoid *audio_calloc (const char *funcname, int nmemb, size_t size)
9496f2d398b49813176939d7a339ae513d5175efvboxsync AUD_log (NULL, "%s passed invalid arguments to audio_calloc\n",
9496f2d398b49813176939d7a339ae513d5175efvboxsync AUD_log (NULL, "nmemb=%d size=%" FMTZ "u (len=%" FMTZ "u)\n",
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic const char *audio_audfmt_to_string (audfmt_e fmt)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return "U8";
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync return "U16";
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync return "U32";
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsync return "S8";
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync return "S16";
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync return "S32";
bbede9c189def47a9880f0ffb03c0c230c774185vboxsync return "S16";
5d0d754550d06b7d59a935e59caaf814462d53ccvboxsyncstatic audfmt_e audio_string_to_audfmt (const char *s, audfmt_e defval,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic audfmt_e audio_get_conf_fmt (const char *envname,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync return audio_string_to_audfmt (var, defval, defaultp);
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic int audio_get_conf_int (const char *key, int defval, int *defaultp)
9496f2d398b49813176939d7a339ae513d5175efvboxsyncstatic const char *audio_get_conf_str (const char *key,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync const char *defval,
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncvoid AUD_vlog (const char *cap, const char *fmt, va_list va)
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync va_copy (va2, va); /* Have to make a copy here or GCC will break. */
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsyncvoid AUD_log (const char *cap, const char *fmt, ...)
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsyncstatic void audio_process_options (const char *prefix,
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync dolog ("Option value pointer for `%s' is not set\n",
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /* len of opt->name + len of prefix + size of vbox_prefix
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * (includes trailing zero) + zero + underscore (on behalf of
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync * sizeof) */
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync optname = qemu_malloc (len + preflen + sizeof (vbox_prefix) + 1);
9496f2d398b49813176939d7a339ae513d5175efvboxsync dolog ("Could not allocate memory for option name `%s'\n",
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync /* copy while upcasing, including trailing zero */
ce03ea57fdcf3d48523b1de5b894feb75e1b34davboxsync for (i = 0; i <= preflen; ++i) {
5341459ca931b65de60b5af2a4cba6836b6b45cavboxsync optname[i + sizeof (vbox_prefix) - 1] = toupper (prefix[i]);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsyncstatic void audio_print_settings (audsettings_t *as)
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync dolog ("frequency=%d nchannels=%d fmt=", as->freq, as->nchannels);
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic int audio_validate_settings (audsettings_t *as)
16a9adc14900ca18e6909679a579f6833425e030vboxsync invalid = as->nchannels != 1 && as->nchannels != 2;
16a9adc14900ca18e6909679a579f6833425e030vboxsync invalid |= as->endianness != 0 && as->endianness != 1;
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsync && info->swap_endianness == (as->endianness != AUDIO_HOST_ENDIANNESS);
efff36b306e370346025647a158689021df2e1d1vboxsyncvoid audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync info->bytes_per_second = info->freq << info->shift;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncvoid audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync AUD_log (NULL, "audio_pcm_info_clear_buf: invalid bits %d\n",
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic void noop_conv (st_sample_t *dst, const void *src,
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic CaptureVoiceOut *audio_pcm_capture_find_specific (
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic void audio_notify_capture (CaptureVoiceOut *cap, audcnotification_e cmd)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic void audio_capture_maybe_changed (CaptureVoiceOut *cap, int enabled)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync cmd = enabled ? AUD_CNOTIFY_ENABLE : AUD_CNOTIFY_DISABLE;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsyncstatic void audio_recalc_and_notify_capture (CaptureVoiceOut *cap)
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync /* We have removed soft voice from the capture:
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync this might have changed the overall status of the capture
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync since this might have been the only active voice */
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsyncstatic int audio_attach_capture (AudioState *s, HWVoiceOut *hw)
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync dolog ("Could not allocate soft capture voice (%u bytes)\n",
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync sizeof (*sc));
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync sw->ratio = ((int64_t) hw_cap->info.freq << 32) / sw->info.freq;
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync sw->rate = st_rate_start (sw->info.freq, hw_cap->info.freq);
d571b6e3237f0ce89ea27f6fa4635d41c5ee3d88vboxsync dolog ("Could not start rate conversion for `%s'\n", SW_NAME (sw));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync hw, sw->info.freq, sw->info.bits, sw->info.nchannels);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync dolog ("Added %s active = %d\n", sw->name, sw->active);
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync * Hard voice (capture)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync int live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);
fe813b3594039ba864493438e78ee0e7132bc445vboxsync if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync dolog ("live=%d hw->samples=%d\n", live, hw->samples);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync * Soft voice (capture)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int live = hw->total_samples_captured - sw->total_hw_samples_acquired;
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
16a9adc14900ca18e6909679a579f6833425e030vboxsync dolog ("live=%d hw->samples=%d\n", live, hw->samples);
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (rpos >= 0) {
16a9adc14900ca18e6909679a579f6833425e030vboxsyncint audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size)
16a9adc14900ca18e6909679a579f6833425e030vboxsync int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
16a9adc14900ca18e6909679a579f6833425e030vboxsync rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples;
16a9adc14900ca18e6909679a579f6833425e030vboxsync live = hw->total_samples_captured - sw->total_hw_samples_acquired;
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
16a9adc14900ca18e6909679a579f6833425e030vboxsync dolog ("live_in=%d hw->samples=%d\n", live, hw->samples);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* XXX: <= ? */
fe813b3594039ba864493438e78ee0e7132bc445vboxsync * Hard voice (playback)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncint audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live)
fe813b3594039ba864493438e78ee0e7132bc445vboxsync if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync dolog ("live=%d hw->samples=%d\n", live, hw->samples);
e04eeee1b306d610b0441cee9bf1c750100254d5vboxsync if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
fe813b3594039ba864493438e78ee0e7132bc445vboxsync dolog ("live=%d hw->samples=%d\n", live, hw->samples);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Soft voice (playback)
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncint audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync if (audio_bug (AUDIO_FUNC, live < 0 || live > hwsamples)){
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync dolog ("live=%d hw->samples=%d\n", live, hwsamples);
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync "%s: write size %d ret %d total sw %d\n",
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsyncstatic void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info)
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync dolog ("%s: bits %d, sign %d, freq %d, nchan %d\n",
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync cap, info->bits, info->sign, info->freq, info->nchannels);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* XXX: Consider options */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync dolog ("Writing to disabled voice %s\n", SW_NAME (sw));
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync /* XXX: Consider options */
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync dolog ("Reading from disabled voice %s\n", SW_NAME (sw));
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
16a9adc14900ca18e6909679a579f6833425e030vboxsync sw->total_hw_samples_acquired = hw->total_samples_captured;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync live = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) {
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync "%s: get_avail live %d ret %lld\n",
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync return (((int64_t) live << 32) / sw->ratio) << sw->info.shift;
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) {
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples);
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift);
9496f2d398b49813176939d7a339ae513d5175efvboxsync return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift;
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsyncstatic void audio_capture_mix_and_clear (HWVoiceOut *hw, int rpos, int samples)
9496f2d398b49813176939d7a339ae513d5175efvboxsync for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
548ca31b6b47c36bacce49bed3339cb8075b9681vboxsync while (n) {
9496f2d398b49813176939d7a339ae513d5175efvboxsync "buffer, mixed %d\n",
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync mixeng_sniff_and_clear (hw, hw->mix_buf + rpos, n);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync mixeng_sniff_and_clear (hw, hw->mix_buf, samples - n);
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync while ((hw = audio_pcm_hw_find_any_enabled_out (s, hw))) {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int live, free, nb_live, cleanup_required, prev_rpos;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync dolog ("live=%d hw->samples=%d\n", live, hw->samples);
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync for (sc = hw->cap_head.lh_first; sc; sc = sc->entries.le_next) {
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsync if (audio_bug (AUDIO_FUNC, hw->rpos >= hw->samples)) {
0ccdfa1953b2f57311fb9ec01a2baf5e1e366f5avboxsync audio_capture_mix_and_clear (hw, prev_rpos, played);
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (audio_bug (AUDIO_FUNC, played > sw->total_hw_samples_mixed)) {
16a9adc14900ca18e6909679a579f6833425e030vboxsync dolog ("played=%d sw->total_hw_samples_mixed=%d\n",
16a9adc14900ca18e6909679a579f6833425e030vboxsync cleanup_required |= !sw->active && !sw->callback.fn;
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync while ((hw = audio_pcm_hw_find_any_enabled_in (s, hw))) {
51fe8789a74f6c118894aaa12eb69ec155386dbdvboxsync for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync for (cap = s->cap_head.lh_first; cap; cap = cap->entries.le_next) {
27b178e99b06a68ef52353b15bc647674d2006bcvboxsync for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
16a9adc14900ca18e6909679a579f6833425e030vboxsync for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
16a9adc14900ca18e6909679a579f6833425e030vboxsync if (audio_bug (AUDIO_FUNC, captured > sw->total_hw_samples_mixed)) {
16a9adc14900ca18e6909679a579f6833425e030vboxsync dolog ("captured=%d sw->total_hw_samples_mixed=%d\n",
89929f1c5e76283fd07c1886aa7c861d12df3a67vboxsync TMTimerSet (s->ts, TMTimerGet (s->ts) + conf.period.ticks);
c7551981eb6d97331da479f68f14a9c56247e4f7vboxsync {"DAC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_out.enabled,
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync {"DAC_FIXED_FREQ", AUD_OPT_INT, &conf.fixed_out.settings.freq,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync {"DAC_FIXED_FMT", AUD_OPT_FMT, &conf.fixed_out.settings.fmt,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync {"DAC_FIXED_CHANNELS", AUD_OPT_INT, &conf.fixed_out.settings.nchannels,
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync "Number of channels for fixed DAC (1 - mono, 2 - stereo)", NULL, 0},
d80c85a1bc7317da7d0cd1254fae6a20db039c8cvboxsync {"DAC_VOICES", AUD_OPT_INT, &conf.fixed_out.nb_voices,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {"ADC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_in.enabled,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {"ADC_FIXED_FREQ", AUD_OPT_INT, &conf.fixed_in.settings.freq,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {"ADC_FIXED_FMT", AUD_OPT_FMT, &conf.fixed_in.settings.fmt,
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync {"ADC_FIXED_CHANNELS", AUD_OPT_INT, &conf.fixed_in.settings.nchannels,
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync "Number of channels for fixed ADC (1 - mono, 2 - stereo)", NULL, 0},
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync {"ADC_VOICES", AUD_OPT_INT, &conf.fixed_in.nb_voices,
16a9adc14900ca18e6909679a579f6833425e030vboxsync "Timer period in HZ (0 - use lowest possible)", NULL, 0},
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic int audio_driver_init (AudioState *s, struct audio_driver *drv)
16a9adc14900ca18e6909679a579f6833425e030vboxsync dolog ("Could not init `%s' audio driver\n", drv->name);
16a9adc14900ca18e6909679a579f6833425e030vboxsyncstatic void audio_vm_change_state_handler (void *opaque, int running)
16a9adc14900ca18e6909679a579f6833425e030vboxsync while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {
16a9adc14900ca18e6909679a579f6833425e030vboxsync while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {
9c149a2789022f5011e88fb62f02a1cc8068e88fvboxsyncstatic void audio_atexit (void)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* VBox change: audio_pcm_hw_find_any_enabled_out => audio_pcm_hw_find_any_out */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync while ((hwo = audio_pcm_hw_find_any_out (s, hwo))) {
9496f2d398b49813176939d7a339ae513d5175efvboxsync for (sc = hwo->cap_head.lh_first; sc; sc = sc->entries.le_next) {
9496f2d398b49813176939d7a339ae513d5175efvboxsync for (cb = cap->cb_head.lh_first; cb; cb = cb->entries.le_next) {
b7a5b3f9f9ecce32ddacf8404c625ce0451bbdc1vboxsync /* VBox change: audio_pcm_hw_find_any_enabled_in => audio_pcm_hw_find_any_in */
6b223679d40f5e57e55e867e806a9f194e2cde12vboxsync while ((hwi = audio_pcm_hw_find_any_in (s, hwi))) {
f35c44bfc9e1036d0cb376fb144cdae416c7ef3avboxsyncvoid AUD_register_card (const char *name, QEMUSoundCard *card)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync memset (&card->entries, 0, sizeof (card->entries));
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsyncstatic void audio_timer_helper (PPDMDRVINS pDrvIns, PTMTIMER pTimer)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncstatic int AUD_init (PPDMDRVINS pDrvIns, const char *drvname)
16a9adc14900ca18e6909679a579f6833425e030vboxsync rc = pDrvIns->pDrvHlp->pfnTMTimerCreate (pDrvIns, TMCLOCK_VIRTUAL,
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync if (s->nb_hw_voices_out <= 0) {
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync dolog ("Bogus number of playback voices %d, setting to 1\n",
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync if (s->nb_hw_voices_in <= 0) {
d9d5fbda1b8f7a6f7fae555db60d0e636fd03af8vboxsync dolog ("Bogus number of capture voices %d, setting to 0\n",
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogRel(("Audio: Initialization of driver '%s' failed, trying '%s'.\n",
1bf495e3eec00dd79cecb6b36ef2a97f422c3737vboxsync LogRel(("Audio: Initialization of driver '%s' failed, using NULL driver.\n", drvname));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync dolog ("warning: Using timer based audio emulation\n");
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync "treating as zero\n",
cba6719bd64ec749967bbe931230452664109857vboxsync conf.period.ticks = pDrvIns->pDrvHlp->pfnTMGetVirtualFreq (pDrvIns)
return rc;
return VINF_SUCCESS;
int AUD_init_null(void)
#ifdef VBOX
if (s->drv)
AudioState *s,
void *cb_opaque
s = &glob_audio_state;
goto err0;
if (!cb) {
sizeof (*cb));
goto err0;
if (cap) {
return cap;
if (!cap) {
sizeof (*cap));
goto err1;
sizeof (st_sample_t));
goto err2;
goto err3;
return cap;
err3:
err2:
err1:
err0:
return NULL;
while (sw) {
#ifdef DEBUG_CAPTURE
if (sw)
const char *name;
switch (mt)
case AUD_MIXER_VOLUME:
case AUD_MIXER_PCM:
case AUD_MIXER_LINE_IN:
if (vol)
if (u32VolumeLeft)
if (u32VolumeRight)
switch (enmInterface)
case PDMINTERFACE_BASE:
return NULL;
audio_vm_change_state_handler (s, 0);
audio_atexit ();
int rc;
char *drvname;
return rc;
return rc;
return VINF_SUCCESS;
audio_vm_change_state_handler (s, 0);
sizeof(DRVAUDIO),
NULL,
NULL,
NULL,
NULL,