dosgame1/system/sdl/AudioBackend.cpp

67 lines
1.8 KiB
C++

#include "AudioBackend.h"
#include <iostream>
#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<AudioBackend*>(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<int16_t *>(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];
}
}