2012-10-13 18:29:53 +00:00
|
|
|
#include "AudioManager.h"
|
|
|
|
|
2013-06-20 14:14:10 +00:00
|
|
|
#include <SDL.h>
|
2013-01-04 23:31:51 +00:00
|
|
|
#include "Log.h"
|
2012-10-13 18:29:53 +00:00
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
std::vector<std::shared_ptr<Sound>> AudioManager::sSoundVector;
|
|
|
|
SDL_AudioSpec AudioManager::sAudioFormat;
|
2013-05-22 17:11:10 +00:00
|
|
|
std::shared_ptr<AudioManager> AudioManager::sInstance;
|
2012-10-13 18:29:53 +00:00
|
|
|
|
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
void AudioManager::mixAudio(void *unused, Uint8 *stream, int len)
|
|
|
|
{
|
|
|
|
bool stillPlaying = false;
|
2012-10-13 18:29:53 +00:00
|
|
|
|
2013-08-18 17:17:24 +00:00
|
|
|
//initialize the buffer to "silence"
|
|
|
|
SDL_memset(stream, 0, len);
|
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
//iterate through all our samples
|
|
|
|
std::vector<std::shared_ptr<Sound>>::const_iterator soundIt = sSoundVector.cbegin();
|
|
|
|
while (soundIt != sSoundVector.cend())
|
2012-10-13 18:29:53 +00:00
|
|
|
{
|
2013-05-14 19:31:39 +00:00
|
|
|
std::shared_ptr<Sound> sound = *soundIt;
|
|
|
|
if(sound->isPlaying())
|
2012-10-13 18:29:53 +00:00
|
|
|
{
|
2013-05-14 19:31:39 +00:00
|
|
|
//calculate rest length of current sample
|
|
|
|
Uint32 restLength = (sound->getLength() - sound->getPosition());
|
2013-05-27 17:13:38 +00:00
|
|
|
if (restLength > (Uint32)len) {
|
2013-05-14 19:31:39 +00:00
|
|
|
//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);
|
2013-06-12 09:48:53 +00:00
|
|
|
if (sound->getPosition() + restLength < sound->getLength())
|
2013-05-14 19:31:39 +00:00
|
|
|
{
|
|
|
|
//sample hasn't ended yet
|
|
|
|
stillPlaying = true;
|
2012-10-13 18:29:53 +00:00
|
|
|
}
|
2013-06-12 09:48:53 +00:00
|
|
|
//set new sound position. if this is at or beyond the end of the sample, it will stop automatically
|
|
|
|
sound->setPosition(sound->getPosition() + restLength);
|
2012-10-13 18:29:53 +00:00
|
|
|
}
|
2013-05-14 19:31:39 +00:00
|
|
|
//advance to next sound
|
|
|
|
++soundIt;
|
|
|
|
}
|
2013-08-18 17:17:24 +00:00
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
//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);
|
2012-10-13 18:29:53 +00:00
|
|
|
}
|
2013-05-14 19:31:39 +00:00
|
|
|
}
|
2012-10-13 18:29:53 +00:00
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
AudioManager::AudioManager()
|
|
|
|
{
|
2013-05-21 08:40:01 +00:00
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
AudioManager::~AudioManager()
|
|
|
|
{
|
|
|
|
deinit();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<AudioManager> & AudioManager::getInstance()
|
|
|
|
{
|
|
|
|
//check if an AudioManager instance is already created, if not create one
|
|
|
|
if (sInstance == nullptr) {
|
|
|
|
sInstance = std::shared_ptr<AudioManager>(new AudioManager);
|
|
|
|
}
|
|
|
|
return sInstance;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioManager::init()
|
|
|
|
{
|
2013-06-20 14:14:10 +00:00
|
|
|
if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0)
|
|
|
|
{
|
|
|
|
LOG(LogError) << "Error initializing SDL audio!\n" << SDL_GetError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-05-21 08:40:01 +00:00
|
|
|
//stop playing all Sounds
|
|
|
|
for(unsigned int i = 0; i < sSoundVector.size(); i++)
|
|
|
|
{
|
|
|
|
if(sSoundVector.at(i)->isPlaying())
|
|
|
|
{
|
|
|
|
sSoundVector[i]->stop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
//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;
|
2012-10-13 18:29:53 +00:00
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
//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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-21 08:40:01 +00:00
|
|
|
void AudioManager::deinit()
|
2013-05-14 19:31:39 +00:00
|
|
|
{
|
2013-05-22 17:11:10 +00:00
|
|
|
//stop all playback
|
|
|
|
stop();
|
2013-06-20 14:14:10 +00:00
|
|
|
//completely tear down SDL audio. else SDL hogs audio resources and emulators might fail to start...
|
2013-05-14 19:31:39 +00:00
|
|
|
SDL_CloseAudio();
|
2013-06-20 14:14:10 +00:00
|
|
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
2013-05-14 19:31:39 +00:00
|
|
|
}
|
2012-10-13 18:29:53 +00:00
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
void AudioManager::registerSound(std::shared_ptr<Sound> & sound)
|
|
|
|
{
|
2013-05-21 08:40:01 +00:00
|
|
|
getInstance();
|
2013-05-14 19:31:39 +00:00
|
|
|
sSoundVector.push_back(sound);
|
|
|
|
}
|
2012-10-13 18:29:53 +00:00
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
void AudioManager::unregisterSound(std::shared_ptr<Sound> & sound)
|
|
|
|
{
|
2013-05-21 08:40:01 +00:00
|
|
|
getInstance();
|
2013-05-14 19:31:39 +00:00
|
|
|
for(unsigned int i = 0; i < sSoundVector.size(); i++)
|
2012-10-13 18:29:53 +00:00
|
|
|
{
|
2013-05-14 19:31:39 +00:00
|
|
|
if(sSoundVector.at(i) == sound)
|
|
|
|
{
|
2013-05-21 08:40:01 +00:00
|
|
|
sSoundVector[i]->stop();
|
2013-05-14 19:31:39 +00:00
|
|
|
sSoundVector.erase(sSoundVector.begin() + i);
|
|
|
|
return;
|
|
|
|
}
|
2012-10-13 18:29:53 +00:00
|
|
|
}
|
2013-05-14 19:31:39 +00:00
|
|
|
LOG(LogError) << "AudioManager Error - tried to unregister a sound that wasn't registered!";
|
2012-10-13 18:29:53 +00:00
|
|
|
}
|
2013-05-14 19:31:39 +00:00
|
|
|
|
|
|
|
void AudioManager::play()
|
|
|
|
{
|
2013-05-21 08:40:01 +00:00
|
|
|
getInstance();
|
2013-05-22 17:11:10 +00:00
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
//unpause audio, the mixer will figure out if samples need to be played...
|
|
|
|
SDL_PauseAudio(0);
|
2013-05-22 17:11:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|