From 2425cecf7b6eeefe535fb32a9f93ca2d444402a8 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Thu, 5 Feb 2026 00:47:06 -0700 Subject: [PATCH] apu: Move monitor management out to monitor.c --- hw/xbox/mcpx/apu/apu.c | 50 +++----------------------- hw/xbox/mcpx/apu/apu_int.h | 4 +++ hw/xbox/mcpx/apu/meson.build | 1 + hw/xbox/mcpx/apu/monitor.c | 69 ++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 46 deletions(-) create mode 100644 hw/xbox/mcpx/apu/monitor.c diff --git a/hw/xbox/mcpx/apu/apu.c b/hw/xbox/mcpx/apu/apu.c index 59c1569f35..09ca3a5b55 100644 --- a/hw/xbox/mcpx/apu/apu.c +++ b/hw/xbox/mcpx/apu/apu.c @@ -174,16 +174,7 @@ static void se_frame(MCPXAPUState *d) mcpx_apu_vp_frame(d, mixbins); mcpx_apu_dsp_frame(d, mixbins); - - if ((d->ep_frame_div + 1) % 8 == 0) { - if (d->monitor.stream) { - float vu = pow(fmax(0.0, fmin(g_config.audio.volume_limit, 1.0)), M_E); - SDL_SetAudioStreamGain(d->monitor.stream, vu); - SDL_PutAudioStreamData(d->monitor.stream, d->monitor.frame_buf, - sizeof(d->monitor.frame_buf)); - } - memset(d->monitor.frame_buf, 0, sizeof(d->monitor.frame_buf)); - } + mcpx_apu_monitor_frame(d); d->ep_frame_div++; @@ -238,39 +229,6 @@ static void *mcpx_apu_frame_thread(void *arg) return NULL; } -static void monitor_init(MCPXAPUState *d, Error **errp) -{ - SDL_AudioSpec spec = { - .freq = 48000, - .format = SDL_AUDIO_S16LE, - .channels = 2, - }; - - d->monitor.stream = NULL; - - if (!SDL_Init(SDL_INIT_AUDIO)) { - error_setg(errp, "SDL_Init failed: %s", SDL_GetError()); - return; - } - - d->monitor.stream = SDL_OpenAudioDeviceStream( - SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL, NULL); - if (d->monitor.stream == NULL) { - error_setg(errp, "SDL_OpenAudioDeviceStream failed: %s", - SDL_GetError()); - return; - } - - SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(d->monitor.stream)); -} - -static void monitor_finalize(MCPXAPUState *d) -{ - if (d->monitor.stream) { - SDL_DestroyAudioStream(d->monitor.stream); - } -} - static void mcpx_apu_wait_for_idle(MCPXAPUState *d) { d->pause_requested = true; @@ -378,9 +336,9 @@ static void mcpx_apu_realize(PCIDevice *dev, Error **errp) mcpx_apu_dsp_init(d); Error *local_err = NULL; - monitor_init(d, &local_err); + mcpx_apu_monitor_init(d, &local_err); if (local_err) { - warn_reportf_err(local_err, "monitor_init failed: "); + warn_reportf_err(local_err, "mcpx_apu_monitor_init failed: "); } qemu_add_vm_change_state_handler(mcpx_apu_vm_state_change, d); @@ -404,7 +362,7 @@ static void mcpx_apu_exitfn(PCIDevice *dev) qemu_thread_join(&d->apu_thread); mcpx_apu_vp_finalize(d); - monitor_finalize(d); + mcpx_apu_monitor_finalize(d); } const VMStateDescription vmstate_vp_dsp_dma_state = { diff --git a/hw/xbox/mcpx/apu/apu_int.h b/hw/xbox/mcpx/apu/apu_int.h index a8751c3e14..a86b5684c8 100644 --- a/hw/xbox/mcpx/apu/apu_int.h +++ b/hw/xbox/mcpx/apu/apu_int.h @@ -116,4 +116,8 @@ extern uint64_t g_dbg_muted_voices[4]; void mcpx_debug_begin_frame(void); void mcpx_debug_end_frame(void); +void mcpx_apu_monitor_init(MCPXAPUState *d, Error **errp); +void mcpx_apu_monitor_finalize(MCPXAPUState *d); +void mcpx_apu_monitor_frame(MCPXAPUState *d); + #endif diff --git a/hw/xbox/mcpx/apu/meson.build b/hw/xbox/mcpx/apu/meson.build index ba64434642..9b161a900b 100644 --- a/hw/xbox/mcpx/apu/meson.build +++ b/hw/xbox/mcpx/apu/meson.build @@ -1,6 +1,7 @@ mcpx_ss.add(sdl, files( 'apu.c', 'debug.c', + 'monitor.c', )) subdir('vp') diff --git a/hw/xbox/mcpx/apu/monitor.c b/hw/xbox/mcpx/apu/monitor.c new file mode 100644 index 0000000000..562665c6c4 --- /dev/null +++ b/hw/xbox/mcpx/apu/monitor.c @@ -0,0 +1,69 @@ +/* + * QEMU MCPX Audio Processing Unit implementation + * + * Copyright (c) 2019-2025 Matt Borgerson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "apu_int.h" + +void mcpx_apu_monitor_init(MCPXAPUState *d, Error **errp) +{ + SDL_AudioSpec spec = { + .freq = 48000, + .format = SDL_AUDIO_S16LE, + .channels = 2, + }; + + d->monitor.stream = NULL; + + if (!SDL_Init(SDL_INIT_AUDIO)) { + error_setg(errp, "SDL_Init failed: %s", SDL_GetError()); + return; + } + + d->monitor.stream = SDL_OpenAudioDeviceStream( + SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec, NULL, NULL); + if (d->monitor.stream == NULL) { + error_setg(errp, "SDL_OpenAudioDeviceStream failed: %s", + SDL_GetError()); + return; + } + + SDL_ResumeAudioDevice(SDL_GetAudioStreamDevice(d->monitor.stream)); +} + +void mcpx_apu_monitor_finalize(MCPXAPUState *d) +{ + if (d->monitor.stream) { + SDL_DestroyAudioStream(d->monitor.stream); + } +} + +void mcpx_apu_monitor_frame(MCPXAPUState *d) +{ + if ((d->ep_frame_div + 1) % 8) { + return; + } + + if (d->monitor.stream) { + float vu = pow(fmax(0.0, fmin(g_config.audio.volume_limit, 1.0)), M_E); + SDL_SetAudioStreamGain(d->monitor.stream, vu); + SDL_PutAudioStreamData(d->monitor.stream, d->monitor.frame_buf, + sizeof(d->monitor.frame_buf)); + } + + memset(d->monitor.frame_buf, 0, sizeof(d->monitor.frame_buf)); +}