#include "AudioBackend.h" #include #include "../../audio/AudioPlayer.h" AudioBackend audioBackend; AudioBackend::AudioBackend() { } AudioBackend::~AudioBackend() { terminate(); } void AudioBackend::init() { SDL_AudioSpec desired; desired.freq = 44100; desired.format = AUDIO_S16LSB; desired.channels = 2; desired.samples = 1024; desired.padding = 0; desired.userdata = this; desired.callback = [] (void *userdata, Uint8 *stream, int len) { static_cast(userdata)->generate(stream, len); }; _audioDevice = SDL_OpenAudioDevice(nullptr, 0, &desired, &_audioSpec, 0); if (!_audioDevice) { std::cerr << "Failed to open audio device: " << SDL_GetError() << std::endl; abort(); } _audioStream = SDL_NewAudioStream(AUDIO_S8, 1, 8000, AUDIO_S16LSB, _audioSpec.channels, _audioSpec.freq); SDL_PauseAudioDevice(_audioDevice, 0); } void AudioBackend::terminate() { if (_audioDevice) { SDL_PauseAudioDevice(_audioDevice, 1); SDL_FreeAudioStream(_audioStream); SDL_CloseAudioDevice(_audioDevice); } } void AudioBackend::generate(Uint8 *stream, int len) { auto s = reinterpret_cast(stream); // Convert sample rate (8000->44100) for SDL output int8_t mixerSample = 0; while (SDL_AudioStreamAvailable(_audioStream) < len) { audioPlayer.generateSamples(&mixerSample, 1); SDL_AudioStreamPut(_audioStream, &mixerSample, 1); } for (int i = 0; i < len/4; i++) { int16_t convertedMixerSample[2]{}; SDL_AudioStreamGet(_audioStream, &convertedMixerSample, sizeof convertedMixerSample); int16_t l = 0, r = 0; Opl::generateSample(&l, &r); *s++ = l + convertedMixerSample[0]; *s++ = r + convertedMixerSample[1]; } }