diff --git a/Makefile.target b/Makefile.target index 5982f08377..c764538503 100644 --- a/Makefile.target +++ b/Makefile.target @@ -274,7 +274,7 @@ VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o SOUND_HW = sb16.o -AUDIODRV = audio.o wavaudio.o +AUDIODRV = audio.o noaudio.o wavaudio.o ifdef CONFIG_SDL AUDIODRV += sdlaudio.o endif diff --git a/audio/audio.c b/audio/audio.c index ec77c259e2..80170b96d4 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -183,7 +183,6 @@ int pcm_hw_alloc_resources (HWVoice *hw) return 0; } - void pcm_hw_fini (HWVoice *hw) { if (hw->active) { @@ -786,6 +785,7 @@ static struct audio_output_driver *drvtab[] = { #ifdef CONFIG_SDL &sdl_output_driver, #endif + &no_output_driver, #ifdef USE_WAV_AUDIO &wav_output_driver, #endif @@ -906,6 +906,6 @@ void AUD_init (void) register_savevm ("audio", 0, 1, audio_save, audio_load, NULL); if (!done) { dolog ("Can not initialize audio subsystem\n"); - return; + voice_init (&no_output_driver); } } diff --git a/audio/audio_int.h b/audio/audio_int.h index 599d3b0614..db7fd1a7d3 100644 --- a/audio/audio_int.h +++ b/audio/audio_int.h @@ -55,6 +55,9 @@ typedef struct HWVoice { struct pcm_ops *pcm_ops; } HWVoice; +extern struct pcm_ops no_pcm_ops; +extern struct audio_output_driver no_output_driver; + extern struct pcm_ops oss_pcm_ops; extern struct audio_output_driver oss_output_driver; diff --git a/audio/fmodaudio.c b/audio/fmodaudio.c index 8245f93fde..7b79026a82 100644 --- a/audio/fmodaudio.c +++ b/audio/fmodaudio.c @@ -34,7 +34,6 @@ typedef struct FMODVoice { int channel; } FMODVoice; - #define dolog(...) AUD_log ("fmod", __VA_ARGS__) #ifdef DEBUG #define ldebug(...) dolog (__VA_ARGS__) diff --git a/audio/noaudio.c b/audio/noaudio.c new file mode 100644 index 0000000000..819de1e538 --- /dev/null +++ b/audio/noaudio.c @@ -0,0 +1,130 @@ +/* + * QEMU NULL audio output driver + * + * Copyright (c) 2004 Vassili Karpov (malc) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +#include "audio/audio_int.h" + +typedef struct NoVoice { + HWVoice hw; + int64_t old_ticks; +} NoVoice; + +#define dolog(...) AUD_log ("noaudio", __VA_ARGS__) +#ifdef DEBUG +#define ldebug(...) dolog (__VA_ARGS__) +#else +#define ldebug(...) +#endif + +static void no_hw_run (HWVoice *hw) +{ + NoVoice *no = (NoVoice *) hw; + int rpos, live, decr, samples; + uint8_t *dst; + st_sample_t *src; + int64_t now = qemu_get_clock (vm_clock); + int64_t ticks = now - no->old_ticks; + int64_t bytes = (ticks * hw->bytes_per_second) / ticks_per_sec; + + if (bytes > INT_MAX) + samples = INT_MAX >> hw->shift; + else + samples = bytes >> hw->shift; + + live = pcm_hw_get_live (hw); + if (live <= 0) + return; + + no->old_ticks = now; + decr = audio_MIN (live, samples); + samples = decr; + rpos = hw->rpos; + while (samples) { + int left_till_end_samples = hw->samples - rpos; + int convert_samples = audio_MIN (samples, left_till_end_samples); + + src = advance (hw->mix_buf, rpos * sizeof (st_sample_t)); + memset (src, 0, convert_samples * sizeof (st_sample_t)); + + rpos = (rpos + convert_samples) % hw->samples; + samples -= convert_samples; + } + + pcm_hw_dec_live (hw, decr); + hw->rpos = rpos; +} + +static int no_hw_write (SWVoice *sw, void *buf, int len) +{ + return pcm_hw_write (sw, buf, len); +} + +static int no_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt) +{ + NoVoice *no = (NoVoice *) hw; + hw->freq = freq; + hw->nchannels = nchannels; + hw->fmt = fmt; + hw->bufsize = 4096; + return 0; +} + +static void no_hw_fini (HWVoice *hw) +{ + (void) hw; +} + +static int no_hw_ctl (HWVoice *hw, int cmd, ...) +{ + (void) hw; + (void) cmd; + return 0; +} + +static void *no_audio_init (void) +{ + return &no_audio_init; +} + +static void no_audio_fini (void *opaque) +{ +} + +struct pcm_ops no_pcm_ops = { + no_hw_init, + no_hw_fini, + no_hw_run, + no_hw_write, + no_hw_ctl +}; + +struct audio_output_driver no_output_driver = { + "none", + no_audio_init, + no_audio_fini, + &no_pcm_ops, + 1, + 1, + sizeof (NoVoice) +}; diff --git a/audio/ossaudio.c b/audio/ossaudio.c index 6bf8cc40c2..79b1e8a5b3 100644 --- a/audio/ossaudio.c +++ b/audio/ossaudio.c @@ -40,7 +40,6 @@ typedef struct OSSVoice { int old_optr; } OSSVoice; - #define dolog(...) AUD_log ("oss", __VA_ARGS__) #ifdef DEBUG #define ldebug(...) dolog (__VA_ARGS__) @@ -371,9 +370,7 @@ static int oss_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt) if (oss->pcm_buf == MAP_FAILED) { dolog ("Failed to mmap OSS device\nReason: %s\n", errstr ()); - } - - for (;;) { + } else for (;;) { int err; int trig = 0; if (ioctl (oss->fd, SNDCTL_DSP_SETTRIGGER, &trig) < 0) { diff --git a/audio/wavaudio.c b/audio/wavaudio.c index f8d6acb4a2..5680161c72 100644 --- a/audio/wavaudio.c +++ b/audio/wavaudio.c @@ -55,7 +55,6 @@ static void wav_hw_run (HWVoice *hw) int64_t now = qemu_get_clock (vm_clock); int64_t ticks = now - wav->old_ticks; int64_t bytes = (ticks * hw->bytes_per_second) / ticks_per_sec; - wav->old_ticks = now; if (bytes > INT_MAX) samples = INT_MAX >> hw->shift; @@ -66,6 +65,7 @@ static void wav_hw_run (HWVoice *hw) if (live <= 0) return; + wav->old_ticks = now; decr = audio_MIN (live, samples); samples = decr; rpos = hw->rpos; @@ -94,7 +94,6 @@ static int wav_hw_write (SWVoice *sw, void *buf, int len) return pcm_hw_write (sw, buf, len); } - /* VICE code: Store number as little endian. */ static void le_store (uint8_t *buf, uint32_t val, int len) { @@ -145,6 +144,8 @@ static int wav_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt) if (!wav->f) { dolog ("failed to open wave file `%s'\nReason: %s\n", conf.wav_path, strerror (errno)); + qemu_free (wav->pcm_buf); + wav->pcm_buf = NULL; return -1; } @@ -175,6 +176,9 @@ static void wav_hw_fini (HWVoice *hw) fclose (wav->f); wav->f = NULL; + + qemu_free (wav->pcm_buf); + wav->pcm_buf = NULL; } static int wav_hw_ctl (HWVoice *hw, int cmd, ...) diff --git a/hw/sb16.c b/hw/sb16.c index a94e6899e9..8973c5ef25 100644 --- a/hw/sb16.c +++ b/hw/sb16.c @@ -640,8 +640,8 @@ static void complete (SB16State *s) s->freq = 11025; samples = dsp_get_lohi (s); bytes = samples << s->fmt_stereo << (s->fmt_bits == 16); - ticks = ticks_per_sec / (s->freq / bytes); - if (ticks < ticks_per_sec / 1024) + ticks = bytes ? (ticks_per_sec / (s->freq / bytes)) : 0; + if (!bytes || ticks < ticks_per_sec / 1024) pic_set_irq (s->irq, 1); else qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks);