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.
This commit is contained in:
Jeff Epler 2025-03-19 11:13:34 -05:00
parent 606f7f75fe
commit c5ac98dffb
3 changed files with 43 additions and 1 deletions

View file

@ -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

View file

@ -40,6 +40,7 @@
#include <errno.h>
#include <setjmp.h>
#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;
}

View file

@ -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