//---------------------------------------------------------------------------
#include "stdafx.h"
#include "sound.h"
#include "utils.h"
#include "game.h"
#include "gamestate.h"
//---------------------------------------------------------------------------
bool error_occurred = false;
bool have_sound = false;
bool errorSound() {
bool rtn = error_occurred;
return rtn;
}
void resetErrorSound() {
error_occurred = false;
}
Sample::~Sample() {
if( music != NULL )
Mix_FreeMusic(music);
if( chunk != NULL )
Mix_FreeChunk(chunk);
}
bool initSound() {
// important to reinitialise for Android, where globals aren't reinitialised when native app is restarted
error_occurred = false;
have_sound = false;
if( SDL_InitSubSystem(SDL_INIT_AUDIO) != 0 ) {
LOG("failed to init SDL audio subsystem");
return false;
}
if( Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024) == -1 ) {
LOG("Mix_OpenAudio failed: %s\n", Mix_GetError());
SDL_QuitSubSystem(SDL_INIT_AUDIO);
return false;
}
#ifdef _WIN32
// not yet available on Linux!
Mix_Init(0);
#endif
have_sound = true;
return true;
}
void updateSound() {
}
void freeSound() {
if( have_sound ) {
Mix_CloseAudio();
#ifdef _WIN32
// not yet available on Linux!
Mix_Quit();
#endif
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
}
Sample *Sample::loadSample(const char *filename, bool iff) {
//LOG("loadSample %s\n", filename); // disabled logging to improve performance on startup
Mix_Chunk *chunk = NULL;
if( have_sound ) {
chunk = Mix_LoadWAV(filename);
if( chunk == NULL ) {
LOG("Mix_LoadWAV failed: %s\n", Mix_GetError());
error_occurred = true;
}
}
// we still create the structure even if no sample is loaded, as we also use for displaying the associated text; also means we don't have to check for NULL pointers every time we want to play a sample
Sample *sample = new Sample(false, NULL, chunk);
return sample;
}
Sample *Sample::loadSample(string filename, bool iff) {
return loadSample(filename.c_str(), iff);
}
Sample *Sample::loadMusic(const char *filename) {
LOG("loadMusic %s\n", filename);
Mix_Music *music = NULL;
if( have_sound ) {
// Mix_LoadMUS doesn't support RWops, so won't work on Android (but only available in SDL 2)
#if SDL_MAJOR_VERSION == 1
music = Mix_LoadMUS(filename);
#else
music = Mix_LoadMUSType_RW(SDL_RWFromFile(filename, "rb"), MUS_OGG, 1);
#endif
if( music == NULL ) {
LOG("Mix_LoadMUS failed: %s\n", Mix_GetError());
error_occurred = true;
}
}
// we still create the structure even if no sample is loaded, as means we don't have to check for NULL pointers every time we want to play a sample
Sample *sample = new Sample(true, music, NULL);
return sample;
}
Sample *Sample::loadMusic(string filename) {
return loadMusic(filename.c_str());
}
void Sample::play(int ch, int loops) {
if( have_sound ) {
if( is_music && game_g->isPrefMusicOn() ) {
if( Mix_PlayMusic(music, loops) == -1 ) {
//if( Mix_FadeInMusic(music, -1, 2000) == -1 ) {
LOG("Mix_PlayMusic failed: %s\n", Mix_GetError());
}
Mix_VolumeMusic(MIX_MAX_VOLUME);
}
else if( !is_music && game_g->isPrefSoundOn() ) {
if( chunk != NULL ) {
bool done = false;
if( channel != -1 ) {
if( Mix_Paused(channel) ) {
// sound was paused, so let's just resume
Mix_Resume(channel);
done = true;
}
// otherwise, let's stop the currently playing sound
Mix_HaltChannel(channel);
}
if( !done ) {
channel = Mix_PlayChannel(ch, chunk, loops);
if( channel == -1 ) {
LOG("Failed to play sound: %s\n", Mix_GetError());
}
else {
Mix_Volume(channel, MIX_MAX_VOLUME);
}
}
}
}
}
if( this->text.length() > 0 ) {
//const int ypos = 216;
const int ypos = 224;
TextEffect *effect = new TextEffect(this->text, 160, ypos, 2000);
game_g->addTextEffect(effect);
}
}
/*bool Sample::isPlaying() const {
// also returns true if the channel is paused - this is about whether the sample has finished (or not yet started)
if( channel != -1 ) {
// still need to check in case sample ended
if( Mix_Playing(channel) != 0 ) {
return true;
}
}
return false;
}*/
void Sample::pauseMusic() {
if( have_sound ) {
Mix_PauseMusic();
}
}
void Sample::unpauseMusic() {
if( have_sound ) {
Mix_ResumeMusic();
}
}
void Sample::pauseChannel(int ch) {
if( have_sound ) {
Mix_Pause(ch);
}
}
void Sample::unpauseChannel(int ch) {
if( have_sound ) {
Mix_Resume(ch);
}
}
void Sample::fadeOut(int duration_ms) {
if( have_sound ) {
if( is_music && music != NULL ) {
Mix_FadeOutMusic(duration_ms);
}
else if( channel != -1 ) {
Mix_FadeOutChannel(channel, duration_ms);
}
}
}
void Sample::setVolume(float volume) {
if( have_sound ) {
if( is_music ) {
Mix_VolumeMusic((int)(MIX_MAX_VOLUME*volume));
}
else if( channel != -1 ) {
Mix_Volume(channel, (int)(MIX_MAX_VOLUME*volume));
}
}
}
bool isPlaying(int ch) {
bool is_playing = false;
if( have_sound ) {
if( Mix_Playing(ch) != 0 ) {
is_playing = true;
}
}
return is_playing;
}