]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
sound: track QEMU output voices separately
authorStefan Reinauer <stefan.reinauer@coreboot.org>
Sun, 31 May 2026 07:18:38 +0000 (00:18 -0700)
committerStefan Reinauer <stefan.reinauer@coreboot.org>
Sun, 31 May 2026 07:19:02 +0000 (00:19 -0700)
Keep every QEMU output voice on a small linked list instead of
replacing a single global pointer. Pass the voice through the audio
callback so each active stream reads its own buffer.

Update all active QEMU voice volumes, only run QEMU board audio when a
voice is active, clamp writes to the sample buffer, and return no input
data until the capture path has a real backend.

qemuvga/qemuaudio.h
sndboard.cpp

index 0551096fb4ef9c8fbe1d7507d9b341aea55ce196..c39c591224cd083acff39fb5768c6438e1a7bfc7 100644 (file)
@@ -32,6 +32,7 @@ struct SWVoiceOut
        audfmt_e fmt;
        int left_volume, right_volume;
        int streamid;
+       struct SWVoiceOut *next;
 };
 struct SWVoiceIn
 {
index 3d17fa6ef3a73bd0a48ff16729279fba2fdcc4d7..68ba37066f72ddcabdf18b02492705495aefc003 100644 (file)
@@ -2831,7 +2831,7 @@ static SWVoiceOut *qemu_voice_out;
 
 static bool audio_state_sndboard_qemu(int streamid, void *params)
 {
-       SWVoiceOut *out = qemu_voice_out;
+       SWVoiceOut *out = (SWVoiceOut*)params;
 
        if (!out || !out->active)
                return false;
@@ -2876,39 +2876,60 @@ static bool audio_state_sndboard_qemu(int streamid, void *params)
        return true;
 }
 
-static void calculate_volume_qemu(void)
+static void calculate_volume_qemu(SWVoiceOut *out)
 {
-       SWVoiceOut *out = qemu_voice_out;
        if (!out)
                return;
        out->left_volume = (100 - currprefs.sound_volume_board) * 32768 / 100;
        out->right_volume = (100 - currprefs.sound_volume_board) * 32768 / 100;
 }
 
+static void calculate_volume_qemu_all(void)
+{
+       for (SWVoiceOut *out = qemu_voice_out; out; out = out->next) {
+               calculate_volume_qemu(out);
+       }
+}
+
+static bool qemu_voice_out_active(void)
+{
+       for (SWVoiceOut *out = qemu_voice_out; out; out = out->next) {
+               if (out->active)
+                       return true;
+       }
+       return false;
+}
+
 void AUD_close_in(QEMUSoundCard *card, SWVoiceIn *sw)
 {
 }
 int AUD_read(SWVoiceIn *sw, void *pcm_buf, int size)
 {
-       return size;
+       return 0;
 }
 int AUD_write(SWVoiceOut *sw, void *pcm_buf, int size)
 {
+       if (!sw || !pcm_buf || size <= 0)
+               return 0;
+       if (size > (int)sizeof(sw->samplebuf))
+               size = sizeof(sw->samplebuf);
        memcpy(sw->samplebuf, pcm_buf, size);
        sw->samplebuf_total = size;
        return sw->samplebuf_total;
 }
 void AUD_set_active_out(SWVoiceOut *sw, int on)
 {
+       if (!sw)
+               return;
        sw->active = on != 0;
        sw->event_time = (int)(base_event_clock * CYCLE_UNIT / sw->freq);
        sw->samplebuf_index = 0;
        sw->samplebuf_total = 0;
-       calculate_volume_qemu();
+       calculate_volume_qemu(sw);
        audio_enable_stream(false, sw->streamid, 2, NULL, NULL);
        sw->streamid = 0;
        if (on) {
-               sw->streamid = audio_enable_stream(true, -1, 2, audio_state_sndboard_qemu, NULL);
+               sw->streamid = audio_enable_stream(true, -1, 2, audio_state_sndboard_qemu, sw);
        }
 }
 void AUD_set_active_in(SWVoiceIn *sw, int on)
@@ -2920,8 +2941,15 @@ int  AUD_is_active_in(SWVoiceIn *sw)
 }
 void AUD_close_out(QEMUSoundCard *card, SWVoiceOut *sw)
 {
-       qemu_voice_out = NULL;
        if (sw) {
+               SWVoiceOut **outp = &qemu_voice_out;
+               while (*outp) {
+                       if (*outp == sw) {
+                               *outp = sw->next;
+                               break;
+                       }
+                       outp = &(*outp)->next;
+               }
                audio_enable_stream(false, sw->streamid, 0, NULL, NULL);
                sw->streamid = 0;
                xfree(sw);
@@ -2946,8 +2974,11 @@ SWVoiceOut *AUD_open_out(
        struct audsettings *settings)
 {
        SWVoiceOut *out = sw;
-       if (!sw)
+       if (!sw) {
                out = xcalloc(SWVoiceOut, 1);
+               out->next = qemu_voice_out;
+               qemu_voice_out = out;
+       }
        int bits = 8;
 
        if (settings->fmt >= AUD_FMT_U16)
@@ -2967,8 +2998,6 @@ SWVoiceOut *AUD_open_out(
        write_log(_T("QEMU AUDIO: freq=%d ch=%d bits=%d (fmt=%d) '%s'\n"), out->freq, out->ch, bits, settings->fmt, name2);
        xfree(name2);
 
-       qemu_voice_out = out;
-
        return out;
 }
 
@@ -2983,7 +3012,7 @@ static void sndboard_vsync(void)
                sndboard_vsync_toccata(&snddev[0]);
        if (fm801_active)
                sndboard_vsync_fm801();
-       if (qemu_voice_out && qemu_voice_out->active)
+       if (qemu_voice_out_active())
                sndboard_vsync_qemu();
 }
 
@@ -2993,8 +3022,7 @@ void sndboard_ext_volume(void)
                calculate_volume_toccata(&snddev[0]);
        if (fm801_active)
                calculate_volume_fm801();
-       if (qemu_voice_out && qemu_voice_out->active)
-               calculate_volume_qemu();
+       calculate_volume_qemu_all();
 }
 
 static void snd_init(void)