67 lines
1.8 KiB
C++
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];
|
|
}
|
|
}
|