2012-10-13 18:29:53 +00:00
|
|
|
#include "Sound.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
|
2012-10-13 18:29:53 +00:00
|
|
|
#include "AudioManager.h"
|
2013-01-04 23:31:51 +00:00
|
|
|
#include "Log.h"
|
2013-08-07 05:41:55 +00:00
|
|
|
#include "Settings.h"
|
2014-01-03 16:40:36 +00:00
|
|
|
#include "ThemeData.h"
|
|
|
|
|
|
|
|
std::map< std::string, std::shared_ptr<Sound> > Sound::sMap;
|
|
|
|
|
|
|
|
std::shared_ptr<Sound> Sound::get(const std::string& path)
|
|
|
|
{
|
|
|
|
auto it = sMap.find(path);
|
2017-11-11 14:56:22 +00:00
|
|
|
if(it != sMap.cend())
|
2014-01-03 16:40:36 +00:00
|
|
|
return it->second;
|
|
|
|
|
|
|
|
std::shared_ptr<Sound> sound = std::shared_ptr<Sound>(new Sound(path));
|
|
|
|
AudioManager::getInstance()->registerSound(sound);
|
|
|
|
sMap[path] = sound;
|
|
|
|
return sound;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<Sound> Sound::getFromTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element)
|
|
|
|
{
|
2020-05-15 16:08:26 +00:00
|
|
|
LOG(LogInfo) << "Sound::getFromTheme() looking for [" << view << "." << element << "]";
|
2014-01-03 16:40:36 +00:00
|
|
|
|
|
|
|
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "sound");
|
|
|
|
if(!elem || !elem->has("path"))
|
|
|
|
{
|
2020-05-15 16:08:26 +00:00
|
|
|
LOG(LogInfo) << "[" << element << "] not found, can't play sound file";
|
2014-01-03 16:40:36 +00:00
|
|
|
return get("");
|
|
|
|
}
|
2020-05-15 16:08:26 +00:00
|
|
|
|
|
|
|
LOG(LogInfo) << "[" << element << "] found, ready to play sound file";
|
2014-01-03 16:40:36 +00:00
|
|
|
return get(elem->get<std::string>("path"));
|
|
|
|
}
|
2012-10-13 18:29:53 +00:00
|
|
|
|
2020-05-15 16:21:24 +00:00
|
|
|
void NavigationSounds::loadThemeNavigationSounds(const std::shared_ptr<ThemeData>& theme)
|
|
|
|
{
|
|
|
|
systembrowseSound = Sound::getFromTheme(theme, "all", "systembrowseSound");
|
|
|
|
quicksysselectSound = Sound::getFromTheme(theme, "all", "quicksysselectSound");
|
|
|
|
selectSound = Sound::getFromTheme(theme, "all", "selectSound");
|
|
|
|
backSound = Sound::getFromTheme(theme, "all", "backSound");
|
|
|
|
scrollSound = Sound::getFromTheme(theme, "all", "scrollSound");
|
|
|
|
favoriteSound = Sound::getFromTheme(theme, "all", "favoriteSound");
|
|
|
|
launchSound = Sound::getFromTheme(theme, "all", "launchSound");
|
|
|
|
}
|
|
|
|
|
|
|
|
void NavigationSounds::playThemeNavigationSound(NavigationSoundsID soundID)
|
|
|
|
{
|
|
|
|
|
|
|
|
switch(soundID)
|
|
|
|
{
|
2020-05-15 16:41:53 +00:00
|
|
|
case SYSTEMBROWSESOUND:
|
2020-05-15 16:21:24 +00:00
|
|
|
navigationsounds.systembrowseSound->play();
|
|
|
|
break;
|
2020-05-15 16:41:53 +00:00
|
|
|
case QUICKSYSSELECTSOUND:
|
2020-05-15 16:21:24 +00:00
|
|
|
navigationsounds.quicksysselectSound->play();
|
|
|
|
break;
|
|
|
|
case SELECTSOUND:
|
|
|
|
navigationsounds.selectSound->play();
|
|
|
|
break;
|
|
|
|
case BACKSOUND:
|
|
|
|
navigationsounds.backSound->play();
|
|
|
|
break;
|
|
|
|
case SCROLLSOUND:
|
|
|
|
navigationsounds.scrollSound->play();
|
|
|
|
break;
|
|
|
|
case FAVORITESOUND:
|
|
|
|
navigationsounds.favoriteSound->play();
|
|
|
|
break;
|
|
|
|
case LAUNCHSOUND:
|
|
|
|
navigationsounds.launchSound->play();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool NavigationSounds::isPlayingThemeNavigationSound(NavigationSoundsID soundID)
|
|
|
|
{
|
|
|
|
switch(soundID)
|
|
|
|
{
|
2020-05-15 16:41:53 +00:00
|
|
|
case SYSTEMBROWSESOUND:
|
2020-05-15 16:21:24 +00:00
|
|
|
return navigationsounds.systembrowseSound->isPlaying();
|
|
|
|
break;
|
2020-05-15 16:41:53 +00:00
|
|
|
case QUICKSYSSELECTSOUND:
|
2020-05-15 16:21:24 +00:00
|
|
|
return navigationsounds.quicksysselectSound->isPlaying();
|
|
|
|
break;
|
|
|
|
case SELECTSOUND:
|
|
|
|
return navigationsounds.selectSound->isPlaying();
|
|
|
|
break;
|
|
|
|
case BACKSOUND:
|
|
|
|
return navigationsounds.backSound->isPlaying();
|
|
|
|
break;
|
|
|
|
case SCROLLSOUND:
|
|
|
|
return navigationsounds.scrollSound->isPlaying();
|
|
|
|
break;
|
|
|
|
case FAVORITESOUND:
|
|
|
|
return navigationsounds.favoriteSound->isPlaying();
|
|
|
|
break;
|
|
|
|
case LAUNCHSOUND:
|
|
|
|
return navigationsounds.launchSound->isPlaying();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
Sound::Sound(const std::string & path) : mSampleData(NULL), mSamplePos(0), mSampleLength(0), playing(false)
|
|
|
|
{
|
2012-10-13 18:29:53 +00:00
|
|
|
loadFile(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
Sound::~Sound()
|
|
|
|
{
|
|
|
|
deinit();
|
|
|
|
}
|
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
void Sound::loadFile(const std::string & path)
|
2012-10-13 18:29:53 +00:00
|
|
|
{
|
|
|
|
mPath = path;
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sound::init()
|
|
|
|
{
|
2013-05-14 19:31:39 +00:00
|
|
|
if(mSampleData != NULL)
|
2012-10-13 18:29:53 +00:00
|
|
|
deinit();
|
|
|
|
|
|
|
|
if(mPath.empty())
|
|
|
|
return;
|
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
//load wav file via SDL
|
|
|
|
SDL_AudioSpec wave;
|
|
|
|
Uint8 * data = NULL;
|
|
|
|
Uint32 dlen = 0;
|
|
|
|
if (SDL_LoadWAV(mPath.c_str(), &wave, &data, &dlen) == NULL) {
|
|
|
|
LOG(LogError) << "Error loading sound \"" << mPath << "\"!\n" << " " << SDL_GetError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//build conversion buffer
|
|
|
|
SDL_AudioCVT cvt;
|
|
|
|
SDL_BuildAudioCVT(&cvt, wave.format, wave.channels, wave.freq, AUDIO_S16, 2, 44100);
|
|
|
|
//copy data to conversion buffer
|
|
|
|
cvt.len = dlen;
|
|
|
|
cvt.buf = new Uint8[cvt.len * cvt.len_mult];
|
|
|
|
memcpy(cvt.buf, data, dlen);
|
|
|
|
//convert buffer to stereo, 16bit, 44.1kHz
|
|
|
|
if (SDL_ConvertAudio(&cvt) < 0) {
|
|
|
|
LOG(LogError) << "Error converting sound \"" << mPath << "\" to 44.1kHz, 16bit, stereo format!\n" << " " << SDL_GetError();
|
|
|
|
delete[] cvt.buf;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
//worked. set up member data
|
|
|
|
SDL_LockAudio();
|
|
|
|
mSampleData = cvt.buf;
|
|
|
|
mSampleLength = cvt.len_cvt;
|
|
|
|
mSamplePos = 0;
|
|
|
|
mSampleFormat.channels = 2;
|
|
|
|
mSampleFormat.freq = 44100;
|
|
|
|
mSampleFormat.format = AUDIO_S16;
|
|
|
|
SDL_UnlockAudio();
|
2012-10-13 18:29:53 +00:00
|
|
|
}
|
2013-05-14 19:31:39 +00:00
|
|
|
//free wav data now
|
|
|
|
SDL_FreeWAV(data);
|
2012-10-13 18:29:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Sound::deinit()
|
|
|
|
{
|
2013-05-14 19:31:39 +00:00
|
|
|
playing = false;
|
|
|
|
|
|
|
|
if(mSampleData != NULL)
|
2012-10-13 18:29:53 +00:00
|
|
|
{
|
2013-05-14 19:31:39 +00:00
|
|
|
SDL_LockAudio();
|
|
|
|
delete[] mSampleData;
|
|
|
|
mSampleData = NULL;
|
|
|
|
mSampleLength = 0;
|
|
|
|
mSamplePos = 0;
|
|
|
|
SDL_UnlockAudio();
|
2012-10-13 18:29:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sound::play()
|
|
|
|
{
|
2013-05-14 19:31:39 +00:00
|
|
|
if(mSampleData == NULL)
|
2012-10-13 18:29:53 +00:00
|
|
|
return;
|
|
|
|
|
2014-11-12 01:13:57 +00:00
|
|
|
if(!Settings::getInstance()->getBool("EnableSounds"))
|
2013-08-07 05:41:55 +00:00
|
|
|
return;
|
|
|
|
|
2017-09-14 01:26:33 +00:00
|
|
|
AudioManager::getInstance();
|
|
|
|
|
2013-06-12 09:48:53 +00:00
|
|
|
SDL_LockAudio();
|
2013-05-15 08:12:51 +00:00
|
|
|
if (playing)
|
|
|
|
{
|
|
|
|
//replay from start. rewind the sample to the beginning
|
|
|
|
mSamplePos = 0;
|
2019-08-25 15:23:02 +00:00
|
|
|
|
2013-05-15 08:12:51 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//flag our sample as playing
|
|
|
|
playing = true;
|
|
|
|
}
|
2013-06-12 09:48:53 +00:00
|
|
|
SDL_UnlockAudio();
|
2013-05-14 19:31:39 +00:00
|
|
|
//tell the AudioManager to start playing samples
|
2013-05-22 17:11:10 +00:00
|
|
|
AudioManager::getInstance()->play();
|
2013-05-14 19:31:39 +00:00
|
|
|
}
|
2012-10-13 18:29:53 +00:00
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
bool Sound::isPlaying() const
|
|
|
|
{
|
|
|
|
return playing;
|
2012-10-13 18:29:53 +00:00
|
|
|
}
|
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
void Sound::stop()
|
2012-10-13 18:29:53 +00:00
|
|
|
{
|
2013-05-14 19:31:39 +00:00
|
|
|
//flag our sample as playing and rewind its position
|
2013-05-15 08:12:51 +00:00
|
|
|
SDL_LockAudio();
|
2013-05-14 19:31:39 +00:00
|
|
|
playing = false;
|
|
|
|
mSamplePos = 0;
|
2013-05-15 08:12:51 +00:00
|
|
|
SDL_UnlockAudio();
|
2012-10-13 18:29:53 +00:00
|
|
|
}
|
|
|
|
|
2013-05-14 19:31:39 +00:00
|
|
|
const Uint8 * Sound::getData() const
|
|
|
|
{
|
|
|
|
return mSampleData;
|
|
|
|
}
|
|
|
|
|
|
|
|
Uint32 Sound::getPosition() const
|
|
|
|
{
|
|
|
|
return mSamplePos;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Sound::setPosition(Uint32 newPosition)
|
|
|
|
{
|
|
|
|
mSamplePos = newPosition;
|
|
|
|
if (mSamplePos >= mSampleLength) {
|
2013-06-12 09:48:53 +00:00
|
|
|
//got to or beyond the end of the sample. stop playing
|
|
|
|
playing = false;
|
2013-05-14 19:31:39 +00:00
|
|
|
mSamplePos = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Uint32 Sound::getLength() const
|
|
|
|
{
|
|
|
|
return mSampleLength;
|
2013-08-06 13:15:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Uint32 Sound::getLengthMS() const
|
|
|
|
{
|
|
|
|
//44100 samples per second, 2 channels (stereo)
|
|
|
|
//I have no idea why the *0.75 is necessary, but otherwise it's inaccurate
|
|
|
|
return (Uint32)((mSampleLength / 44100.0f / 2.0f * 0.75f) * 1000);
|
|
|
|
}
|