[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 08/21] asc: generate silence if FIFO empty but engine still runni
From: |
Mark Cave-Ayland |
Subject: |
[PATCH 08/21] asc: generate silence if FIFO empty but engine still running |
Date: |
Sun, 2 Jul 2023 16:48:25 +0100 |
MacOS (un)helpfully leaves the FIFO engine running even when all the samples
have
been written to the hardware, and expects the FIFO status flags and IRQ to be
updated continuously.
Since not all audio backends guarantee an all-zero output when no data is
provided, explicitly generate at least one full output buffer of all-zero output
when the FIFO is disabled and continuously if the FIFO is empty. Otherwise some
audio backends such as Windows re-use their internal buffers causing the last
played sound to loop indefinitely.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
---
hw/audio/asc.c | 43 ++++++++++++++++++++++++++++++++----------
include/hw/audio/asc.h | 1 +
2 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/hw/audio/asc.c b/hw/audio/asc.c
index ebcb8a97a6..f9bfae5168 100644
--- a/hw/audio/asc.c
+++ b/hw/audio/asc.c
@@ -148,6 +148,20 @@ static uint8_t asc_fifo_get(ASCFIFOState *fs)
return val;
}
+static int generate_silence(ASCState *s, int maxsamples)
+{
+ uint8_t *buf = s->mixbuf;
+
+ if (s->flush_zero_samples) {
+ memset(buf, 0x80, maxsamples << s->shift);
+ s->flush_zero_samples -= MIN(maxsamples, s->flush_zero_samples);
+
+ return maxsamples;
+ }
+
+ return 0;
+}
+
static int generate_fifo(ASCState *s, int maxsamples)
{
uint8_t *buf = s->mixbuf;
@@ -156,18 +170,26 @@ static int generate_fifo(ASCState *s, int maxsamples)
limit = MIN(MAX(s->fifos[0].cnt, s->fifos[1].cnt), maxsamples);
/*
- * If starting a new run with no FIFO data present, update the IRQ and
- * continue
+ * MacOS (un)helpfully leaves the FIFO engine running even when it has
+ * finished writing out samples. Since not all audio backends guarantee an
+ * all-zero output when no data is provided, zero out the sample buffer
+ * and then update the FIFO flags and IRQ as normal and continue
*/
- if (limit == 0 && s->fifos[0].int_status == 0 &&
- s->fifos[1].int_status == 0) {
- s->fifos[0].int_status |= ASC_FIFO_STATUS_HALF_FULL |
- ASC_FIFO_STATUS_FULL_EMPTY;
- s->fifos[1].int_status |= ASC_FIFO_STATUS_HALF_FULL |
- ASC_FIFO_STATUS_FULL_EMPTY;
+ if (limit == 0) {
+ if (s->fifos[0].int_status == 0 && s->fifos[1].int_status == 0) {
+ s->fifos[0].int_status |= ASC_FIFO_STATUS_HALF_FULL |
+ ASC_FIFO_STATUS_FULL_EMPTY;
+ s->fifos[1].int_status |= ASC_FIFO_STATUS_HALF_FULL |
+ ASC_FIFO_STATUS_FULL_EMPTY;
+ }
+
+ if (s->flush_zero_samples == 0) {
+ s->flush_zero_samples = s->samples;
+ }
+ generate_silence(s, maxsamples);
asc_raise_irq(s);
- return 0;
+ return maxsamples;
}
while (count < limit) {
@@ -309,7 +331,7 @@ static void asc_out_cb(void *opaque, int free_b)
switch (s->regs[ASC_MODE] & 3) {
default:
/* Off */
- samples = 0;
+ samples = generate_silence(s, samples);
break;
case 1:
/* FIFO mode */
@@ -437,6 +459,7 @@ static void asc_write(void *opaque, hwaddr addr, uint64_t
value,
asc_lower_irq(s);
if (value != 0) {
AUD_set_active_out(s->voice, 1);
+ s->flush_zero_samples = 0;
} else {
AUD_set_active_out(s->voice, 0);
}
diff --git a/include/hw/audio/asc.h b/include/hw/audio/asc.h
index 41c6cba8fa..918f6ac582 100644
--- a/include/hw/audio/asc.h
+++ b/include/hw/audio/asc.h
@@ -65,6 +65,7 @@ struct ASCState {
uint8_t *mixbuf;
int samples;
int shift;
+ uint32_t flush_zero_samples;
qemu_irq irq;
--
2.30.2
- Re: [PATCH 03/21] q800: add machine id register, (continued)
- [PATCH 04/21] q800: implement additional machine id bits on VIA1 port A, Mark Cave-Ayland, 2023/07/02
- [PATCH 05/21] q800: add IOSB subsystem, Mark Cave-Ayland, 2023/07/02
- [PATCH 06/21] q800: allow accesses to RAM area even if less memory is available, Mark Cave-Ayland, 2023/07/02
- [PATCH 07/21] audio: add Apple Sound Chip (ASC) emulation, Mark Cave-Ayland, 2023/07/02
- [PATCH 08/21] asc: generate silence if FIFO empty but engine still running,
Mark Cave-Ayland <=
- [PATCH 09/21] q800: add Apple Sound Chip (ASC) audio to machine, Mark Cave-Ayland, 2023/07/02
- [PATCH 10/21] q800: add easc bool machine class property to switch between ASC and EASC, Mark Cave-Ayland, 2023/07/02
- [PATCH 11/21] swim: add trace events for IWM and ISM registers, Mark Cave-Ayland, 2023/07/02
- [PATCH 12/21] swim: split into separate IWM and ISM register blocks, Mark Cave-Ayland, 2023/07/02