diff --git a/audio/audio.c b/audio/audio.c index d6e91901aa..1ace47f510 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -29,6 +29,7 @@ #include "sysemu/sysemu.h" #include "qemu/cutils.h" #include "sysemu/replay.h" +#include "trace.h" #define AUDIO_CAP "audio" #include "audio_int.h" @@ -1129,6 +1130,10 @@ static void audio_pcm_print_info (const char *cap, struct audio_pcm_info *info) /* * Timer */ + +static bool audio_timer_running; +static uint64_t audio_timer_last; + static int audio_is_timer_needed (void) { HWVoiceIn *hwi = NULL; @@ -1148,14 +1153,31 @@ static void audio_reset_timer (AudioState *s) if (audio_is_timer_needed ()) { timer_mod_anticipate_ns(s->ts, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + conf.period.ticks); - } - else { - timer_del (s->ts); + if (!audio_timer_running) { + audio_timer_running = true; + audio_timer_last = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + trace_audio_timer_start(conf.period.ticks / SCALE_MS); + } + } else { + timer_del(s->ts); + if (audio_timer_running) { + audio_timer_running = false; + trace_audio_timer_stop(); + } } } static void audio_timer (void *opaque) { + int64_t now, diff; + + now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + diff = now - audio_timer_last; + if (diff > conf.period.ticks * 3 / 2) { + trace_audio_timer_delayed(diff / SCALE_MS); + } + audio_timer_last = now; + audio_run ("timer"); audio_reset_timer (opaque); } diff --git a/audio/trace-events b/audio/trace-events index d37639e611..c986469319 100644 --- a/audio/trace-events +++ b/audio/trace-events @@ -15,3 +15,8 @@ alsa_no_frames(int state) "No frames available and ALSA state is %d" # audio/ossaudio.c oss_version(int version) "OSS version = 0x%x" oss_invalid_available_size(int size, int bufsize) "Invalid available size, size=%d bufsize=%d" + +# audio/audio.c +audio_timer_start(int interval) "interval %d ms" +audio_timer_stop(void) "" +audio_timer_delayed(int interval) "interval %d ms" diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c index 31c66d4255..2b58c3505b 100644 --- a/hw/audio/hda-codec.c +++ b/hw/audio/hda-codec.c @@ -189,7 +189,7 @@ struct HDAAudioState { static inline int64_t hda_bytes_per_second(HDAAudioStream *st) { - return 2 * st->as.nchannels * st->as.freq; + return 2LL * st->as.nchannels * st->as.freq; } static inline void hda_timer_sync_adjust(HDAAudioStream *st, int64_t target_pos) @@ -203,6 +203,9 @@ static inline void hda_timer_sync_adjust(HDAAudioStream *st, int64_t target_pos) if (target_pos < -limit) { corr = -HDA_TIMER_TICKS; } + if (target_pos < -(2 * limit)) { + corr = -(4 * HDA_TIMER_TICKS); + } if (corr == 0) { return; }