From c5ac98dffbfedf8886c6ca9aa7ca9201f9c5798b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 19 Mar 2025 11:13:34 -0500 Subject: [PATCH] Minimal audio implementation This is good enough to play the system beep (which is at a multiple of the refresh rate, so every buffer contains an integer number of cycles of the tone) However, because the audio buffer filling is not synchronized with vertical retrace, it's probably not good enough for playing other kinds of audio. --- include/umac.h | 5 +++++ src/main.c | 3 +++ src/unix_main.c | 36 +++++++++++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/include/umac.h b/include/umac.h index 024a174..bb40fea 100644 --- a/include/umac.h +++ b/include/umac.h @@ -53,4 +53,9 @@ static inline unsigned int umac_get_fb_offset(void) return RAM_SIZE - ((DISP_WIDTH * DISP_HEIGHT / 8) + 0x380); } +#define umac_get_audio_offset() (RAM_SIZE - 768) +#define umac_get_audio_offset_end() (RAM_SIZE - 768 + 2 * 370) + +extern int umac_volume; + #endif diff --git a/src/main.c b/src/main.c index 1c68b26..1962bb9 100644 --- a/src/main.c +++ b/src/main.c @@ -40,6 +40,7 @@ #include #include +#include "umac.h" #include "machw.h" #include "m68k.h" #include "via.h" @@ -70,6 +71,7 @@ static unsigned int g_int_controller_highest_int = 0; /* Highest pending interr uint8_t *_ram_base; uint8_t *_rom_base; +int umac_volume = 0; int overlay = 1; static uint64_t global_time_us = 0; static int sim_done = 0; @@ -154,6 +156,7 @@ static void via_ra_changed(uint8_t val) MDBG("OVERLAY CHANGING\n"); update_overlay_layout(); } + umac_volume = val & 7; oldval = val; } diff --git a/src/unix_main.c b/src/unix_main.c index 588dba4..6ca2140 100644 --- a/src/unix_main.c +++ b/src/unix_main.c @@ -78,6 +78,19 @@ static void copy_fb(uint32_t *fb_out, uint8_t *fb_in) } } +static void audio_callback(void *userdata, Uint8 *stream_in, int len_bytes) { + int16_t *stream = (int16_t*) stream_in; + int len = len_bytes / 2; + uint16_t *audiodata = userdata; + int32_t scale = 65536 * umac_volume / 7; + int32_t offset = 128; + while (len--) { + int32_t a = (*audiodata++ & 0xff) - offset; + a = (a * scale) >> 8; + *stream++ = a; + } +} + /**********************************************************************/ /* The emulator core expects to be given ROM and RAM pointers, @@ -232,7 +245,7 @@ int main(int argc, char *argv[]) SDL_Renderer *renderer; SDL_Texture *texture; - SDL_Init(SDL_INIT_VIDEO); + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); SDL_Window *window = SDL_CreateWindow("umac", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, @@ -264,12 +277,33 @@ int main(int argc, char *argv[]) return 1; } + SDL_AudioSpec desired, obtained; + + SDL_zero(desired); + desired.freq = 22256; // wat + desired.channels = 1; + desired.samples = 370; + desired.userdata = (uint8_t*)ram_base + umac_get_audio_offset(); + desired.callback = audio_callback; + desired.format = AUDIO_S16; + + SDL_AudioDeviceID audio_device = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0); + if (!audio_device) { + char buf[500]; + SDL_GetErrorMsg(buf, sizeof(buf)); + printf("SDL audio_deviceSDL_GetError() -> %s\n", buf); + return 1; + } + //////////////////////////////////////////////////////////////////////// // Emulator init umac_init(ram_base, rom_base, discs); umac_opt_disassemble(opt_disassemble); + // Default state is paused, this unpauses it + SDL_PauseAudioDevice(audio_device, 0); + //////////////////////////////////////////////////////////////////////// // Main loop