#include "AudioManager.h" #include #include "Log.h" std::vector> AudioManager::sSoundVector; SDL_AudioSpec AudioManager::sAudioFormat; std::shared_ptr AudioManager::sInstance; void AudioManager::mixAudio(void *unused, Uint8 *stream, int len) { bool stillPlaying = false; //initialize the buffer to "silence" SDL_memset(stream, 0, len); //iterate through all our samples std::vector>::const_iterator soundIt = sSoundVector.cbegin(); while (soundIt != sSoundVector.cend()) { std::shared_ptr sound = *soundIt; if(sound->isPlaying()) { //calculate rest length of current sample Uint32 restLength = (sound->getLength() - sound->getPosition()); if (restLength > (Uint32)len) { //if stream length is smaller than smaple lenght, clip it restLength = len; } //mix sample into stream SDL_MixAudio(stream, &(sound->getData()[sound->getPosition()]), restLength, SDL_MIX_MAXVOLUME); if (sound->getPosition() + restLength < sound->getLength()) { //sample hasn't ended yet stillPlaying = true; } //set new sound position. if this is at or beyond the end of the sample, it will stop automatically sound->setPosition(sound->getPosition() + restLength); } //advance to next sound ++soundIt; } //we have processed all samples. check if some will still be playing if (!stillPlaying) { //no. pause audio till a Sound::play() wakes us up SDL_PauseAudio(1); } } AudioManager::AudioManager() { init(); } AudioManager::~AudioManager() { deinit(); } std::shared_ptr & AudioManager::getInstance() { //check if an AudioManager instance is already created, if not create one if (sInstance == nullptr) { sInstance = std::shared_ptr(new AudioManager); } return sInstance; } void AudioManager::init() { if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) { LOG(LogError) << "Error initializing SDL audio!\n" << SDL_GetError(); return; } //stop playing all Sounds for(unsigned int i = 0; i < sSoundVector.size(); i++) { if(sSoundVector.at(i)->isPlaying()) { sSoundVector[i]->stop(); } } //Set up format and callback. Play 16-bit stereo audio at 44.1Khz sAudioFormat.freq = 44100; sAudioFormat.format = AUDIO_S16; sAudioFormat.channels = 2; sAudioFormat.samples = 1024; sAudioFormat.callback = mixAudio; sAudioFormat.userdata = NULL; //Open the audio device and pause if (SDL_OpenAudio(&sAudioFormat, NULL) < 0) { LOG(LogError) << "AudioManager Error - Unable to open SDL audio: " << SDL_GetError() << std::endl; } } void AudioManager::deinit() { //stop all playback stop(); //completely tear down SDL audio. else SDL hogs audio resources and emulators might fail to start... SDL_CloseAudio(); SDL_QuitSubSystem(SDL_INIT_AUDIO); } void AudioManager::registerSound(std::shared_ptr & sound) { getInstance(); sSoundVector.push_back(sound); } void AudioManager::unregisterSound(std::shared_ptr & sound) { getInstance(); for(unsigned int i = 0; i < sSoundVector.size(); i++) { if(sSoundVector.at(i) == sound) { sSoundVector[i]->stop(); sSoundVector.erase(sSoundVector.begin() + i); return; } } LOG(LogError) << "AudioManager Error - tried to unregister a sound that wasn't registered!"; } void AudioManager::play() { getInstance(); //unpause audio, the mixer will figure out if samples need to be played... SDL_PauseAudio(0); } void AudioManager::stop() { //stop playing all Sounds for(unsigned int i = 0; i < sSoundVector.size(); i++) { if(sSoundVector.at(i)->isPlaying()) { sSoundVector[i]->stop(); } } //pause audio SDL_PauseAudio(1); }