#include "zx_speaker.h" #include #include "z80.h" #include namespace speaker { uint16_t sampling_freq = 44100; uint16_t audio_buffer_size = 2048; SDL_AudioDeviceID sdlAudioDevice = 0; uint8_t *sound_buffer = nullptr; uint16_t sound_pos=0; uint16_t t_sound=0; std::vector sources; float cycles_per_sample; void init(const uint16_t freq, const uint16_t buffer_size) { if (sound_buffer || sdlAudioDevice) quit(); sampling_freq = freq; audio_buffer_size = buffer_size; SDL_AudioSpec audioSpec{sampling_freq, AUDIO_U8, 1, 0, (uint16_t)(audio_buffer_size>>2), 0, 0, NULL, NULL}; sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0); cycles_per_sample = z80::getClock() / sampling_freq; sound_buffer = (uint8_t*)malloc(audio_buffer_size); enable(); } void quit() { disable(); sources.clear(); if (sound_buffer) { free(sound_buffer); sound_buffer = nullptr; } if (sdlAudioDevice) { SDL_CloseAudioDevice(sdlAudioDevice); sdlAudioDevice = 0; } } void enable() { SDL_PauseAudioDevice(sdlAudioDevice, 0); } void disable() { SDL_PauseAudioDevice(sdlAudioDevice, 1); } void register_source(uint8_t(*callback)()) { sources.push_back(callback); } void update(const uint32_t dt) { t_sound += dt; if (t_sound>=cycles_per_sample) { t_sound-=cycles_per_sample; uint32_t sample = 0; for (auto callback : sources) sample += callback(); sample /= sources.size(); sound_buffer[(sound_pos++)&(audio_buffer_size-1)] = sample; } if (sound_pos>=1000) { SDL_QueueAudio(sdlAudioDevice, sound_buffer, sound_pos); sound_pos = 0; while (SDL_GetQueuedAudioSize(sdlAudioDevice) > (audio_buffer_size<<1) ) {} } } }