static void stopBackground(bool bReleaseData)
{
    // The background music might have been already stopped
    // Stop request can come from
    //   - stopBackgroundMusic(..)
    //   - end(..)
    if (s_backgroundSource != AL_NONE)
        alSourceStop(s_backgroundSource);

    if (bReleaseData)
    {
        for (auto it = s_backgroundMusics.begin(); it != s_backgroundMusics.end(); ++it)
        {
            if (it->second->source == s_backgroundSource)
            {
                alDeleteSources(1, &it->second->source);
                checkALError("stopBackground:alDeleteSources");
                alDeleteBuffers(1, &it->second->buffer);
                checkALError("stopBackground:alDeleteBuffers");
                delete it->second;
                s_backgroundMusics.erase(it);
                break;
            }
        }
    }

    s_backgroundSource = AL_NONE;
}
void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
{
    // If there is already a background music source we stop it first
    if (s_backgroundSource != AL_NONE)
        stopBackgroundMusic(false);

    // Changing file path to full path
    std::string fullPath = FileUtils::getInstance()->fullPathForFilename(pszFilePath);

    BackgroundMusicsMap::const_iterator it = s_backgroundMusics.find(fullPath);
    if (it == s_backgroundMusics.end())
    {
        preloadBackgroundMusic(fullPath.c_str());
        it = s_backgroundMusics.find(fullPath);
    }

    if (it != s_backgroundMusics.end())
    {
        s_backgroundSource = it->second->source;
        alSourcei(s_backgroundSource, AL_LOOPING, bLoop ? AL_TRUE : AL_FALSE);
        setBackgroundVolume(s_volume);
        alSourcePlay(s_backgroundSource);
        checkALError("playBackgroundMusic:alSourcePlay");
    }
}
	void SimpleAudioEngine::end()
	{
		checkALError("end");

		// clear all the sounds
	    EffectsMap::const_iterator end = s_effects.end();
	    for (EffectsMap::iterator it = s_effects.begin(); it != end; it++)
	    {
	        alSourceStop(it->second->source);
	        checkALError("end");
			alDeleteBuffers(1, &it->second->buffer);
			checkALError("end");
			alDeleteSources(1, &it->second->source);
			checkALError("end");
			delete it->second;
	    }
	    s_effects.clear();

		// and the background too
		stopBackground(true);

		for (BackgroundMusicsMap::iterator it = s_backgroundMusics.begin(); it != s_backgroundMusics.end(); ++it)
		{
			alSourceStop(it->second->source);
			checkALError("end");
			alDeleteBuffers(1, &it->second->buffer);
			checkALError("end");
			alDeleteSources(1, &it->second->source);
			checkALError("end");
			delete it->second;
		}
		s_backgroundMusics.clear();
	}
void SimpleAudioEngine::end()
{
    checkALError("end:init");

    // clear all the sound effects
    EffectsMap::const_iterator end = s_effects.end();
    for (auto it = s_effects.begin(); it != end; ++it)
    {
        alSourceStop(it->second->source);
        checkALError("end:alSourceStop");

        alDeleteSources(1, &it->second->source);
        checkALError("end:alDeleteSources");

        alDeleteBuffers(1, &it->second->buffer);
        checkALError("end:alDeleteBuffers");

        delete it->second;
    }
    s_effects.clear();

    // and the background music too
    stopBackground(true);

    for (auto it = s_backgroundMusics.begin(); it != s_backgroundMusics.end(); ++it)
    {
        alSourceStop(it->second->source);
        checkALError("end:alSourceStop");

        alDeleteSources(1, &it->second->source);
        checkALError("end:alDeleteSources");

        alDeleteBuffers(1, &it->second->buffer);
        checkALError("end:alDeleteBuffers");

        delete it->second;
    }
    s_backgroundMusics.clear();

    CC_SAFE_DELETE(s_engine);
}
	void SimpleAudioEngine::end()
	{
		// clear all the sounds
	    EffectsMap::const_iterator end = s_effects.end();
	    for (EffectsMap::iterator it = s_effects.begin(); it != end; it++)
	    {
            Mix_FreeChunk(it->second->chunk);
			delete it->second;
	    }
	    s_effects.clear();

		// and the background too
		stopBackground(true);

		for (BackgroundMusicsMap::iterator it = s_backgroundMusics.begin(); it != s_backgroundMusics.end(); ++it)
		{
            Mix_FreeMusic(it->second->music);
			delete it->second;
		}
		s_backgroundMusics.clear();
	}
	//
	// background audio
	//
    void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath)
	{
		// Changing file path to full path
    	std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath);

    	BackgroundMusicsMap::const_iterator it = s_backgroundMusics.find(fullPath);
		if (it == s_backgroundMusics.end())
		{
			ALuint buffer = AL_NONE;
			if (isOGGFile(fullPath.data()))
			{
				buffer = createBufferFromOGG(fullPath.data());
			}
			else
			{
				buffer = alutCreateBufferFromFile(fullPath.data());
			}

			checkALError("preloadBackgroundMusic");

			if (buffer == AL_NONE)
			{
				fprintf(stderr, "Error loading file: '%s'\n", fullPath.data());
				alDeleteBuffers(1, &buffer);
				return;
			}

			ALuint source = AL_NONE;
			alGenSources(1, &source);
			checkALError("preloadBackgroundMusic");

			alSourcei(source, AL_BUFFER, buffer);
			checkALError("preloadBackgroundMusic");

			backgroundMusicData* data = new backgroundMusicData();
			data->buffer = buffer;
			data->source = source;
			s_backgroundMusics.insert(BackgroundMusicsMap::value_type(fullPath, data));
		}
	}
	void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
	{
		if (s_backgroundSource != AL_NONE)
			stopBackgroundMusic(false);

		// Changing file path to full path
    	std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath);

    	BackgroundMusicsMap::const_iterator it = s_backgroundMusics.find(fullPath);
		if (it == s_backgroundMusics.end())
		{
			preloadBackgroundMusic(fullPath.c_str());
			it = s_backgroundMusics.find(fullPath);
		}

		if (it != s_backgroundMusics.end())
		{
			s_backgroundSource = it->second->source;
			alSourcei(s_backgroundSource, AL_LOOPING, bLoop ? AL_TRUE : AL_FALSE);
			alSourcePlay(s_backgroundSource);
			checkALError("playBackgroundMusic");
		}
	}
    static void stopBackground(bool bReleaseData)
    {
		alSourceStop(s_backgroundSource);

		if (bReleaseData)
		{
			for (BackgroundMusicsMap::iterator it = s_backgroundMusics.begin(); it != s_backgroundMusics.end(); ++it)
			{
				if (it->second->source == s_backgroundSource)
				{
					alDeleteBuffers(1, &it->second->buffer);
					checkALError("stopBackground");
					alDeleteSources(1, &it->second->source);
					checkALError("stopBackground");
					delete it->second;
					s_backgroundMusics.erase(it);
					break;
				}
			}
		}

		s_backgroundSource = AL_NONE;
    }
//
// background audio
//
void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath)
{
    // Changing file path to full path
    std::string fullPath = FileUtils::getInstance()->fullPathForFilename(pszFilePath);

    BackgroundMusicsMap::const_iterator it = s_backgroundMusics.find(fullPath);
    if (it == s_backgroundMusics.end())
    {
        ALuint buffer = AL_NONE;
        bool success = false;
        OpenALFile file;
        file.debugName = pszFilePath;
        file.file = fopen(fullPath.c_str(), "rb");
        if (!file.file) {
            fprintf(stderr, "Cannot read file: '%s'\n", fullPath.data());
            return;
        }

        const std::vector<OpenALDecoder *> &decoders = OpenALDecoder::getDecoders();
        for (size_t i = 0, n = decoders.size(); !success && i < n; ++i)
            success = decoders[i]->decode(file, buffer);
        file.clear();

        ALuint source = AL_NONE;
        alGenSources(1, &source);
        checkALError("preloadBackgroundMusic:alGenSources");

        alSourcei(source, AL_BUFFER, buffer);
        checkALError("preloadBackgroundMusic:alSourcei");

        backgroundMusicData* data = new backgroundMusicData();
        data->buffer = buffer;
        data->source = source;
        s_backgroundMusics.insert(BackgroundMusicsMap::value_type(fullPath, data));
    }
}
	void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
	{
        std::string key = std::string(pszFilePath);
        struct backgroundMusicData *musicData;
        if(!s_backgroundMusics.count(key))
        {
            musicData = new struct backgroundMusicData();
            musicData->music = Mix_LoadMUS(pszFilePath);
            s_backgroundMusics[key] = musicData;
        }
        else
        {
            musicData = s_backgroundMusics[key];
        }

        Mix_PlayMusic(musicData->music, bLoop ? -1 : 0);
	}
namespace CocosDenshion {

struct soundData {
    ALuint buffer;
    ALuint source;
    bool   isLooped;
    float pitch;
    float pan;
    float gain;
};

typedef map<string, soundData *> EffectsMap;
EffectsMap s_effects;

typedef enum {
    PLAYING,
    STOPPED,
    PAUSED,
} playStatus;

static float s_volume                  = 1.0f;
static float s_effectVolume            = 1.0f;

struct backgroundMusicData {
    ALuint buffer;
    ALuint source;
};

typedef map<string, backgroundMusicData *> BackgroundMusicsMap;
BackgroundMusicsMap s_backgroundMusics;

static ALuint s_backgroundSource = AL_NONE;

static SimpleAudioEngine  *s_engine = nullptr;

static int checkALError(const char *funcName)
{
    int err = alGetError();

    if (err != AL_NO_ERROR)
    {
        switch (err)
        {
            case AL_INVALID_NAME:
                fprintf(stderr, "AL_INVALID_NAME in %s\n", funcName);
                break;

            case AL_INVALID_ENUM:
                fprintf(stderr, "AL_INVALID_ENUM in %s\n", funcName);
                break;

            case AL_INVALID_VALUE:
                fprintf(stderr, "AL_INVALID_VALUE in %s\n", funcName);
                break;

            case AL_INVALID_OPERATION:
                fprintf(stderr, "AL_INVALID_OPERATION in %s\n", funcName);
                break;

            case AL_OUT_OF_MEMORY:
                fprintf(stderr, "AL_OUT_OF_MEMORY in %s\n", funcName);
                break;
        }
    }

    return err;
}

static void stopBackground(bool bReleaseData)
{
    // The background music might have been already stopped
    // Stop request can come from
    //   - stopBackgroundMusic(..)
    //   - end(..)
    if (s_backgroundSource != AL_NONE)
        alSourceStop(s_backgroundSource);

    if (bReleaseData)
    {
        for (auto it = s_backgroundMusics.begin(); it != s_backgroundMusics.end(); ++it)
        {
            if (it->second->source == s_backgroundSource)
            {
                alDeleteSources(1, &it->second->source);
                checkALError("stopBackground:alDeleteSources");
                alDeleteBuffers(1, &it->second->buffer);
                checkALError("stopBackground:alDeleteBuffers");
                delete it->second;
                s_backgroundMusics.erase(it);
                break;
            }
        }
    }

    s_backgroundSource = AL_NONE;
}

static void setBackgroundVolume(float volume)
{
    alSourcef(s_backgroundSource, AL_GAIN, volume);
}

SimpleAudioEngine::SimpleAudioEngine()
{
    alutInit(0, 0);
#ifdef ENABLE_MPG123
    mpg123_init();
#endif
    checkALError("SimpleAudioEngine:alutInit");
    OpenALDecoder::installDecoders();
}

SimpleAudioEngine::~SimpleAudioEngine()
{
#ifdef ENABLE_MPG123
    mpg123_exit();
#endif
    alutExit();
}

SimpleAudioEngine* SimpleAudioEngine::getInstance()
{
    if (!s_engine)
        s_engine = new SimpleAudioEngine();

    return s_engine;
}

void SimpleAudioEngine::end()
{
    checkALError("end:init");

    // clear all the sound effects
    EffectsMap::const_iterator end = s_effects.end();
    for (auto it = s_effects.begin(); it != end; ++it)
    {
        alSourceStop(it->second->source);
        checkALError("end:alSourceStop");

        alDeleteSources(1, &it->second->source);
        checkALError("end:alDeleteSources");

        alDeleteBuffers(1, &it->second->buffer);
        checkALError("end:alDeleteBuffers");

        delete it->second;
    }
    s_effects.clear();

    // and the background music too
    stopBackground(true);

    for (auto it = s_backgroundMusics.begin(); it != s_backgroundMusics.end(); ++it)
    {
        alSourceStop(it->second->source);
        checkALError("end:alSourceStop");

        alDeleteSources(1, &it->second->source);
        checkALError("end:alDeleteSources");

        alDeleteBuffers(1, &it->second->buffer);
        checkALError("end:alDeleteBuffers");

        delete it->second;
    }
    s_backgroundMusics.clear();

    CC_SAFE_DELETE(s_engine);
}

//
// background audio
//
void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath)
{
    // Changing file path to full path
    std::string fullPath = FileUtils::getInstance()->fullPathForFilename(pszFilePath);

    BackgroundMusicsMap::const_iterator it = s_backgroundMusics.find(fullPath);
    if (it == s_backgroundMusics.end())
    {
        ALuint buffer = AL_NONE;
        bool success = false;
        OpenALFile file;
        file.debugName = pszFilePath;
        file.file = fopen(fullPath.c_str(), "rb");
        if (!file.file) {
            fprintf(stderr, "Cannot read file: '%s'\n", fullPath.data());
            return;
        }

        const std::vector<OpenALDecoder *> &decoders = OpenALDecoder::getDecoders();
        for (size_t i = 0, n = decoders.size(); !success && i < n; ++i)
            success = decoders[i]->decode(file, buffer);
        file.clear();

        ALuint source = AL_NONE;
        alGenSources(1, &source);
        checkALError("preloadBackgroundMusic:alGenSources");

        alSourcei(source, AL_BUFFER, buffer);
        checkALError("preloadBackgroundMusic:alSourcei");

        backgroundMusicData* data = new backgroundMusicData();
        data->buffer = buffer;
        data->source = source;
        s_backgroundMusics.insert(BackgroundMusicsMap::value_type(fullPath, data));
    }
}

void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
{
    // If there is already a background music source we stop it first
    if (s_backgroundSource != AL_NONE)
        stopBackgroundMusic(false);

    // Changing file path to full path
    std::string fullPath = FileUtils::getInstance()->fullPathForFilename(pszFilePath);

    BackgroundMusicsMap::const_iterator it = s_backgroundMusics.find(fullPath);
    if (it == s_backgroundMusics.end())
    {
        preloadBackgroundMusic(fullPath.c_str());
        it = s_backgroundMusics.find(fullPath);
    }

    if (it != s_backgroundMusics.end())
    {
        s_backgroundSource = it->second->source;
        alSourcei(s_backgroundSource, AL_LOOPING, bLoop ? AL_TRUE : AL_FALSE);
        setBackgroundVolume(s_volume);
        alSourcePlay(s_backgroundSource);
        checkALError("playBackgroundMusic:alSourcePlay");
    }
}

void SimpleAudioEngine::stopBackgroundMusic(bool bReleaseData)
{
    // If there is no source, then there is nothing that can be stopped
    if (s_backgroundSource == AL_NONE)
        return;

    ALint state;
    alGetSourcei(s_backgroundSource, AL_SOURCE_STATE, &state);
    if (state == AL_PLAYING)
        stopBackground(bReleaseData);
}

void SimpleAudioEngine::pauseBackgroundMusic()
{
    // If there is no source, then there is nothing that can be paused
    if (s_backgroundSource == AL_NONE)
        return;

    ALint state;
    alGetSourcei(s_backgroundSource, AL_SOURCE_STATE, &state);
    if (state == AL_PLAYING)
        alSourcePause(s_backgroundSource);

    checkALError("pauseBackgroundMusic:alSourcePause");
}

void SimpleAudioEngine::resumeBackgroundMusic()
{
    // If there is no source, then there is nothing that can be resumed
    if (s_backgroundSource == AL_NONE)
        return;

    ALint state;
    alGetSourcei(s_backgroundSource, AL_SOURCE_STATE, &state);
    if (state == AL_PAUSED)
        alSourcePlay(s_backgroundSource);

    checkALError("resumeBackgroundMusic:alSourcePlay");
}

void SimpleAudioEngine::rewindBackgroundMusic()
{
    // If there is no source, then there is nothing that can be rewinded
    if (s_backgroundSource == AL_NONE)
        return;

    // Rewind and prevent the last state the source had
    ALint state;
    alGetSourcei(s_backgroundSource, AL_SOURCE_STATE, &state);
    alSourceRewind(s_backgroundSource);

    if (state == AL_PLAYING)
    {
        alSourcePlay(s_backgroundSource);
    }
    else if (state == AL_PAUSED)
    {
        alSourcePlay(s_backgroundSource);
        alSourcePause(s_backgroundSource);
    }
    checkALError("rewindBackgroundMusic:alSourceRewind");
}

bool SimpleAudioEngine::willPlayBackgroundMusic()
{
    // We are able to play background music
    // if we have a valid background source
    if (s_backgroundSource == AL_NONE)
        return false;

    return (alIsSource(s_backgroundSource) == AL_TRUE ? true : false);
}

bool SimpleAudioEngine::isBackgroundMusicPlaying()
{
    // If there is no source, then there is nothing that is playing
    if (s_backgroundSource == AL_NONE)
        return false;

    ALint play_status;
    alGetSourcei(s_backgroundSource, AL_SOURCE_STATE, &play_status);
    checkALError("isBackgroundMusicPlaying:alGetSourcei");

    return (play_status == AL_PLAYING);
}

float SimpleAudioEngine::getBackgroundMusicVolume()
{
    return s_volume;
}

void SimpleAudioEngine::setBackgroundMusicVolume(float volume)
{
    if (s_volume != volume && volume >= -0.0001 && volume <= 1.0001)
    {
        s_volume = volume;

        // No source, no background music, no volume adjustment
        if (s_backgroundSource != AL_NONE)
        {
            setBackgroundVolume(volume);
        }
    }
}

//
// Effect audio (using OpenAL)
//
float SimpleAudioEngine::getEffectsVolume()
{
    return s_effectVolume;
}

void SimpleAudioEngine::setEffectsVolume(float volume)
{
    if (volume != s_effectVolume)
    {
        EffectsMap::const_iterator end = s_effects.end();
        for (EffectsMap::const_iterator it = s_effects.begin(); it != end; it++)
        {
            alSourcef(it->second->source, AL_GAIN, volume * it->second->gain);
        }

        s_effectVolume = volume;
    }
}

unsigned int SimpleAudioEngine::playEffect(const char* pszFilePath, bool bLoop,
                                           float pitch, float pan, float gain)
{
    std::string fullPath = FileUtils::getInstance()->fullPathForFilename(pszFilePath);

    EffectsMap::iterator iter = s_effects.find(fullPath);

    if (iter == s_effects.end())
    {
        preloadEffect(fullPath.c_str());

        // let's try again
        iter = s_effects.find(fullPath);
        if (iter == s_effects.end())
        {
            fprintf(stderr, "could not find play sound %s\n", fullPath.c_str());
            return -1;
        }
    }

    checkALError("playEffect:init");

    soundData &d = *iter->second;
    d.isLooped = bLoop;
    d.pitch = pitch;
    d.pan = pan;
    d.gain = gain;
    alSourcei(d.source, AL_LOOPING, d.isLooped ? AL_TRUE : AL_FALSE);
    alSourcef(d.source, AL_GAIN, s_effectVolume * d.gain);
    alSourcef(d.source, AL_PITCH, d.pitch);
    float sourcePosAL[] = {d.pan, 0.0f, 0.0f};//Set position - just using left and right panning
    alSourcefv(d.source, AL_POSITION, sourcePosAL);
    alSourcePlay(d.source);
    checkALError("playEffect:alSourcePlay");

    return d.source;
}

void SimpleAudioEngine::stopEffect(unsigned int nSoundId)
{
    alSourceStop(nSoundId);
    checkALError("stopEffect:alSourceStop");
}

void SimpleAudioEngine::preloadEffect(const char* pszFilePath)
{
    // Changing file path to full path
    std::string fullPath = FileUtils::getInstance()->fullPathForFilename(pszFilePath);

    EffectsMap::iterator iter = s_effects.find(fullPath);

    // check if we have this already
    if (iter == s_effects.end())
    {
        ALuint      buffer = AL_NONE;
        ALuint      source = AL_NONE;
        

        checkALError("preloadEffect:init");
        OpenALFile file;
        file.debugName = pszFilePath;
        file.file = fopen(fullPath.c_str(), "rb");
        if (!file.file) {
            fprintf(stderr, "Cannot read file: '%s'\n", fullPath.data());
            return;
        }
        
        bool success = false;
        const std::vector<OpenALDecoder *> &decoders = OpenALDecoder::getDecoders();
        for (size_t i = 0, n = decoders.size(); !success && i < n; ++i)
            success = decoders[i]->decode(file, buffer);
        file.clear();

        alGenSources(1, &source);

        if (checkALError("preloadEffect:alGenSources") != AL_NO_ERROR)
        {
            alDeleteBuffers(1, &buffer);
            return;
        }

        alSourcei(source, AL_BUFFER, buffer);
        checkALError("preloadEffect:alSourcei");
        
        soundData  *data = new soundData;
        data->isLooped = false;
        data->buffer = buffer;
        data->source = source;
        data->pitch = 1.0;
        data->pan = 0.0;
        data->gain = 1.0;

        s_effects.insert(EffectsMap::value_type(fullPath, data));
    }
}

void SimpleAudioEngine::unloadEffect(const char* pszFilePath)
{
    // Changing file path to full path
    std::string fullPath = FileUtils::getInstance()->fullPathForFilename(pszFilePath);

    EffectsMap::iterator iter = s_effects.find(fullPath);

    if (iter != s_effects.end())
    {
        checkALError("unloadEffect:init");

        alSourceStop(iter->second->source);
        checkALError("unloadEffect:alSourceStop");

        alDeleteSources(1, &iter->second->source);
        checkALError("unloadEffect:DeletSources");

        alDeleteBuffers(1, &iter->second->buffer);
        checkALError("unloadEffect:alDeleteBuffers");
        delete iter->second;

        s_effects.erase(iter);
    }
}

void SimpleAudioEngine::pauseEffect(unsigned int nSoundId)
{
    ALint state;
    alGetSourcei(nSoundId, AL_SOURCE_STATE, &state);
    if (state == AL_PLAYING)
        alSourcePause(nSoundId);
    checkALError("pauseEffect:alSourcePause");
}

void SimpleAudioEngine::pauseAllEffects()
{
    EffectsMap::iterator iter = s_effects.begin();
    ALint state;
    while (iter != s_effects.end())
    {
        alGetSourcei(iter->second->source, AL_SOURCE_STATE, &state);
        if (state == AL_PLAYING)
            alSourcePause(iter->second->source);
        checkALError("pauseAllEffects:alSourcePause");
        ++iter;
    }
}

void SimpleAudioEngine::resumeEffect(unsigned int nSoundId)
{
    ALint state;
    alGetSourcei(nSoundId, AL_SOURCE_STATE, &state);
    if (state == AL_PAUSED)
        alSourcePlay(nSoundId);
    checkALError("resumeEffect:alSourcePlay");
}

void SimpleAudioEngine::resumeAllEffects()
{
    EffectsMap::iterator iter = s_effects.begin();
    ALint state;
    while (iter != s_effects.end())
    {
        alGetSourcei(iter->second->source, AL_SOURCE_STATE, &state);
        if (state == AL_PAUSED)
            alSourcePlay(iter->second->source);
        checkALError("resumeAllEffects:alSourcePlay");
        ++iter;
    }
}

void SimpleAudioEngine::stopAllEffects()
{
    EffectsMap::iterator iter = s_effects.begin();

    if (iter != s_effects.end())
    {
        checkALError("stopAllEffects:init");
        alSourceStop(iter->second->source);
        checkALError("stopAllEffects:alSourceStop");
    }
}

} // namespace CocosDenshion {
namespace CocosDenshion
{
	struct soundData {
        Mix_Chunk *chunk;
		bool   isLooped;
	};

	typedef map<string, soundData *> EffectsMap;
	EffectsMap s_effects;
    float s_effectsVolume = 1.0;

	typedef enum {
		PLAYING,
		STOPPED,
		PAUSED,
	} playStatus;

	struct backgroundMusicData {
		Mix_Music *music;
	};
	typedef map<string, backgroundMusicData *> BackgroundMusicsMap;
	BackgroundMusicsMap s_backgroundMusics;
    float s_backgroundVolume = 1.0;

	static SimpleAudioEngine  *s_engine = 0;

    // Unfortunately this is just hard-coded in Emscripten's SDL
    // implementation.
    static const int NR_CHANNELS = 32;
    static void stopBackground(bool bReleaseData)
    {
        SimpleAudioEngine *engine = SimpleAudioEngine::getInstance();
        engine->stopBackgroundMusic();
    }

	SimpleAudioEngine::SimpleAudioEngine()
	{
	}

	SimpleAudioEngine::~SimpleAudioEngine()
	{
	}

	SimpleAudioEngine* SimpleAudioEngine::getInstance()
	{
		if (!s_engine)
			s_engine = new SimpleAudioEngine();
        
		return s_engine;
	}

	void SimpleAudioEngine::end()
	{
		// clear all the sounds
	    EffectsMap::const_iterator end = s_effects.end();
	    for (EffectsMap::iterator it = s_effects.begin(); it != end; it++)
	    {
            Mix_FreeChunk(it->second->chunk);
			delete it->second;
	    }
	    s_effects.clear();

		// and the background too
		stopBackground(true);

		for (BackgroundMusicsMap::iterator it = s_backgroundMusics.begin(); it != s_backgroundMusics.end(); ++it)
		{
            Mix_FreeMusic(it->second->music);
			delete it->second;
		}
		s_backgroundMusics.clear();
	}

	//
	// background audio
	//
    void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath)
	{
	}

	void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
	{
        std::string key = std::string(pszFilePath);
        struct backgroundMusicData *musicData;
        if(!s_backgroundMusics.count(key))
        {
            musicData = new struct backgroundMusicData();
            musicData->music = Mix_LoadMUS(pszFilePath);
            s_backgroundMusics[key] = musicData;
        }
        else
        {
            musicData = s_backgroundMusics[key];
        }

        Mix_PlayMusic(musicData->music, bLoop ? -1 : 0);
	}

	void SimpleAudioEngine::stopBackgroundMusic(bool bReleaseData)
	{
        Mix_HaltMusic();
	}

	void SimpleAudioEngine::pauseBackgroundMusic()
	{
        Mix_PauseMusic();
	}

	void SimpleAudioEngine::resumeBackgroundMusic()
	{
        Mix_ResumeMusic();
	} 

	void SimpleAudioEngine::rewindBackgroundMusic()
	{
        CCLOGWARN("Cannot rewind background in Emscripten");
	}

	bool SimpleAudioEngine::willPlayBackgroundMusic()
	{
		return true;
	}

	bool SimpleAudioEngine::isBackgroundMusicPlaying()
	{
        return Mix_PlayingMusic();
	}

	float SimpleAudioEngine::getBackgroundMusicVolume()
	{
        return s_backgroundVolume;
	}

	void SimpleAudioEngine::setBackgroundMusicVolume(float volume)
	{
        // Ensure volume is between 0.0 and 1.0.
        volume = volume > 1.0 ? 1.0 : volume;
        volume = volume < 0.0 ? 0.0 : volume;

        Mix_VolumeMusic(volume * MIX_MAX_VOLUME);
        s_backgroundVolume = volume;
	}

	float SimpleAudioEngine::getEffectsVolume()
	{
		return s_effectsVolume;
	}

	void SimpleAudioEngine::setEffectsVolume(float volume)
	{
        volume = volume > 1.0 ? 1.0 : volume;
        volume = volume < 0.0 ? 0.0 : volume;

        // Need to set volume on every channel. SDL will then read this volume
        // level and apply it back to the individual sample.
        for(int i = 0; i < NR_CHANNELS; i++)
        {
            Mix_Volume(i, volume * MIX_MAX_VOLUME);
        }

        s_effectsVolume = volume;
	}

	unsigned int SimpleAudioEngine::playEffect(const char* pszFilePath, bool bLoop,
                                               float pitch, float pan, float gain)
	{
        std::string key = std::string(pszFilePath);
        struct soundData *sound;
        if(!s_effects.count(key))
        {
            sound = new struct soundData();
            sound->chunk = Mix_LoadWAV(pszFilePath);
            sound->isLooped = bLoop;
            s_effects[key] = sound;
        }
        else
        {
            sound = s_effects[key];
        }
        // This is safe here since Emscripten is just passing back an
        // incrementing integer each time you use the Mix_LoadWAV method.
        unsigned int result = (unsigned int) sound->chunk;

        // XXX: This is a bit of a hack, but... Choose a channel based on the
        // modulo of the # of channels. This allows us to set the volume
        // without passing around both chunk address and channel.
        Mix_PlayChannel(result % NR_CHANNELS, sound->chunk, bLoop ? -1 : 0);

        return result;
	}

	void SimpleAudioEngine::stopEffect(unsigned int nSoundId)
	{
        Mix_HaltChannel(nSoundId % NR_CHANNELS);
	}

	void SimpleAudioEngine::preloadEffect(const char* pszFilePath)
	{
	}

	void SimpleAudioEngine::unloadEffect(const char* pszFilePath)
	{
        std::string key = std::string(pszFilePath);
        if(!s_effects.count(key))
        {
            return;
        }

        struct soundData *sound = s_effects[key];

        Mix_FreeChunk(sound->chunk);
        delete sound;
        s_effects.erase(key);
	}

	void SimpleAudioEngine::pauseEffect(unsigned int nSoundId)
	{
        Mix_Pause(nSoundId % NR_CHANNELS);
	}

	void SimpleAudioEngine::pauseAllEffects()
	{
        for(int i = 0; i < NR_CHANNELS; i++)
        {
            Mix_Pause(i);
        }
	}

	void SimpleAudioEngine::resumeEffect(unsigned int nSoundId)
	{
        Mix_Resume(nSoundId % NR_CHANNELS);
	}

	void SimpleAudioEngine::resumeAllEffects()
	{
        for(int i = 0; i < NR_CHANNELS; i++)
        {
            Mix_Resume(i);
        }
	}

    void SimpleAudioEngine::stopAllEffects()
    {
        for(int i = 0; i < NR_CHANNELS; i++)
        {
            Mix_HaltChannel(i);
        }
    }

}
namespace CocosDenshion
{
	struct soundData {
		ALuint buffer;
		ALuint source;
		bool   isLooped;
	};

	typedef map<string, soundData *> EffectsMap;
	EffectsMap s_effects;

	typedef enum {
		PLAYING,
		STOPPED,
		PAUSED,
	} playStatus;

	static float s_volume 				   = 1.0f;
	static float s_effectVolume			   = 1.0f;

	struct backgroundMusicData {
		ALuint buffer;
		ALuint source;
	};
	typedef map<string, backgroundMusicData *> BackgroundMusicsMap;
	BackgroundMusicsMap s_backgroundMusics;

	static ALuint s_backgroundSource = AL_NONE;

	static SimpleAudioEngine  *s_engine = 0;

	static int checkALError(const char *funcName)
	{
		int err = alGetError();

		if (err != AL_NO_ERROR)
		{
			switch (err)
			{
				case AL_INVALID_NAME:
					fprintf(stderr, "AL_INVALID_NAME in %s\n", funcName);
					break;

				case AL_INVALID_ENUM:
					fprintf(stderr, "AL_INVALID_ENUM in %s\n", funcName);
					break;

				case AL_INVALID_VALUE:
					fprintf(stderr, "AL_INVALID_VALUE in %s\n", funcName);
					break;

				case AL_INVALID_OPERATION:
					fprintf(stderr, "AL_INVALID_OPERATION in %s\n", funcName);
					break;

				case AL_OUT_OF_MEMORY:
					fprintf(stderr, "AL_OUT_OF_MEMORY in %s\n", funcName);
					break;
			}
		}

		return err;
	}

    static void stopBackground(bool bReleaseData)
    {
		s_backgroundSource = AL_NONE;
    }

    static void setBackgroundVolume(float volume)
    {
    }

	SimpleAudioEngine::SimpleAudioEngine()
	{
	}

	SimpleAudioEngine::~SimpleAudioEngine()
	{
	}

	SimpleAudioEngine* SimpleAudioEngine::sharedEngine()
	{
		if (!s_engine)
			s_engine = new SimpleAudioEngine();
        
		return s_engine;
	}

	void SimpleAudioEngine::end()
	{
		checkALError("end");

		// clear all the sounds
	    EffectsMap::const_iterator end = s_effects.end();
	    for (EffectsMap::iterator it = s_effects.begin(); it != end; it++)
	    {
	        alSourceStop(it->second->source);
	        checkALError("end");
			alDeleteBuffers(1, &it->second->buffer);
			checkALError("end");
			alDeleteSources(1, &it->second->source);
			checkALError("end");
			delete it->second;
	    }
	    s_effects.clear();

		// and the background too
		stopBackground(true);

		for (BackgroundMusicsMap::iterator it = s_backgroundMusics.begin(); it != s_backgroundMusics.end(); ++it)
		{
			alSourceStop(it->second->source);
			checkALError("end");
			alDeleteBuffers(1, &it->second->buffer);
			checkALError("end");
			alDeleteSources(1, &it->second->source);
			checkALError("end");
			delete it->second;
		}
		s_backgroundMusics.clear();
	}

	//
	// OGG support
	//
	static bool isOGGFile(const char *pszFilePath)
	{
        return true;
	}

	static ALuint createBufferFromOGG(const char *pszFilePath)
	{
	}


	//
	// background audio
	//
    void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath)
	{
	}

	void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
	{
	}

	void SimpleAudioEngine::stopBackgroundMusic(bool bReleaseData)
	{
	}

	void SimpleAudioEngine::pauseBackgroundMusic()
	{
	}

	void SimpleAudioEngine::resumeBackgroundMusic()
	{
	} 

	void SimpleAudioEngine::rewindBackgroundMusic()
	{
	}

	bool SimpleAudioEngine::willPlayBackgroundMusic()
	{
		return false;
	}

	bool SimpleAudioEngine::isBackgroundMusicPlaying()
	{
        return false;
	}

	float SimpleAudioEngine::getBackgroundMusicVolume()
	{
		return s_volume;
	}

	void SimpleAudioEngine::setBackgroundMusicVolume(float volume)
	{
	}

	//
	// Effect audio (using OpenAL)
	//
	float SimpleAudioEngine::getEffectsVolume()
	{
		return s_effectVolume;
	}

	void SimpleAudioEngine::setEffectsVolume(float volume)
	{
	}

	unsigned int SimpleAudioEngine::playEffect(const char* pszFilePath, bool bLoop)
	{
		// Changing file path to full path
    	std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath);

		EffectsMap::iterator iter = s_effects.find(fullPath);

		if (iter == s_effects.end())
		{
			preloadEffect(fullPath.c_str());

			// let's try again
			iter = s_effects.find(fullPath);
			if (iter == s_effects.end())
			{
				fprintf(stderr, "could not find play sound %s\n", fullPath.c_str());
				return -1;
			}
		}

		checkALError("playEffect");
		iter->second->isLooped = bLoop;
		alSourcei(iter->second->source, AL_LOOPING, iter->second->isLooped ? AL_TRUE : AL_FALSE);
		alSourcePlay(iter->second->source);
		checkALError("playEffect");

		return iter->second->source;
	}

	void SimpleAudioEngine::stopEffect(unsigned int nSoundId)
	{
		alSourceStop(nSoundId);
		checkALError("stopEffect");
	}

	void SimpleAudioEngine::preloadEffect(const char* pszFilePath)
	{
	}

	void SimpleAudioEngine::unloadEffect(const char* pszFilePath)
	{
		// Changing file path to full path
    	std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath);
    	
		EffectsMap::iterator iter = s_effects.find(fullPath);

		if (iter != s_effects.end())
	    {
			checkALError("unloadEffect");

	        alSourceStop(iter->second->source);
	        checkALError("unloadEffect");

			alDeleteSources(1, &iter->second->source);
			checkALError("unloadEffect");

			alDeleteBuffers(1, &iter->second->buffer);
			checkALError("unloadEffect");
			delete iter->second;

			s_effects.erase(iter);
	    }
	}

	void SimpleAudioEngine::pauseEffect(unsigned int nSoundId)
	{
		ALint state;
		alGetSourcei(nSoundId, AL_SOURCE_STATE, &state);
		if (state == AL_PLAYING)
			alSourcePause(nSoundId);
		checkALError("pauseEffect");
	}

	void SimpleAudioEngine::pauseAllEffects()
	{
		EffectsMap::iterator iter = s_effects.begin();
		ALint state;
		while (iter != s_effects.end())
	    {
			alGetSourcei(iter->second->source, AL_SOURCE_STATE, &state);
			if (state == AL_PLAYING)
				alSourcePause(iter->second->source);
			checkALError("pauseAllEffects");
			++iter;
	    }
	}

	void SimpleAudioEngine::resumeEffect(unsigned int nSoundId)
	{
		ALint state;
		alGetSourcei(nSoundId, AL_SOURCE_STATE, &state);
		if (state == AL_PAUSED)
			alSourcePlay(nSoundId);
		checkALError("resumeEffect");
	}

	void SimpleAudioEngine::resumeAllEffects()
	{
		EffectsMap::iterator iter = s_effects.begin();
		ALint state;
		while (iter != s_effects.end())
	    {
			alGetSourcei(iter->second->source, AL_SOURCE_STATE, &state);
			if (state == AL_PAUSED)
				alSourcePlay(iter->second->source);
			checkALError("resumeAllEffects");
			++iter;
	    }
	}

    void SimpleAudioEngine::stopAllEffects()
    {
		EffectsMap::iterator iter = s_effects.begin();

		if (iter != s_effects.end())
	    {
			checkALError("stopAllEffects");
	        alSourceStop(iter->second->source);
			checkALError("stopAllEffects");
	    }
    }

}
namespace CocosDenshion
{
	struct soundData {
		ALuint buffer;
		ALuint source;
		bool   isLooped;
	};

	typedef map<string, soundData *> EffectsMap;
	EffectsMap s_effects;

	typedef enum {
		PLAYING,
		STOPPED,
		PAUSED,
	} playStatus;

	static float s_volume 				   = 1.0f;
	static float s_effectVolume			   = 1.0f;

	struct backgroundMusicData {
		ALuint buffer;
		ALuint source;
	};
	typedef map<string, backgroundMusicData *> BackgroundMusicsMap;
	BackgroundMusicsMap s_backgroundMusics;

	static ALuint s_backgroundSource = AL_NONE;

	static SimpleAudioEngine  *s_engine = 0;

	static int checkALError(const char *funcName)
	{
		int err = alGetError();

		if (err != AL_NO_ERROR)
		{
			switch (err)
			{
				case AL_INVALID_NAME:
					fprintf(stderr, "AL_INVALID_NAME in %s\n", funcName);
					break;

				case AL_INVALID_ENUM:
					fprintf(stderr, "AL_INVALID_ENUM in %s\n", funcName);
					break;

				case AL_INVALID_VALUE:
					fprintf(stderr, "AL_INVALID_VALUE in %s\n", funcName);
					break;

				case AL_INVALID_OPERATION:
					fprintf(stderr, "AL_INVALID_OPERATION in %s\n", funcName);
					break;

				case AL_OUT_OF_MEMORY:
					fprintf(stderr, "AL_OUT_OF_MEMORY in %s\n", funcName);
					break;
			}
		}

		return err;
	}

    static void stopBackground(bool bReleaseData)
    {
		alSourceStop(s_backgroundSource);

		if (bReleaseData)
		{
			for (BackgroundMusicsMap::iterator it = s_backgroundMusics.begin(); it != s_backgroundMusics.end(); ++it)
			{
				if (it->second->source == s_backgroundSource)
				{
					alDeleteBuffers(1, &it->second->buffer);
					checkALError("stopBackground");
					alDeleteSources(1, &it->second->source);
					checkALError("stopBackground");
					delete it->second;
					s_backgroundMusics.erase(it);
					break;
				}
			}
		}

		s_backgroundSource = AL_NONE;
    }

    static void setBackgroundVolume(float volume)
    {
    	alSourcef(s_backgroundSource, AL_GAIN, volume);
    }

	SimpleAudioEngine::SimpleAudioEngine()
	{
		alutInit(0, 0);
	}

	SimpleAudioEngine::~SimpleAudioEngine()
	{
		alutExit();
	}

	SimpleAudioEngine* SimpleAudioEngine::sharedEngine()
	{
		if (!s_engine)
			s_engine = new SimpleAudioEngine();
        
		return s_engine;
	}

	void SimpleAudioEngine::end()
	{
		checkALError("end");

		// clear all the sounds
	    EffectsMap::const_iterator end = s_effects.end();
	    for (EffectsMap::iterator it = s_effects.begin(); it != end; it++)
	    {
	        alSourceStop(it->second->source);
	        checkALError("end");
			alDeleteBuffers(1, &it->second->buffer);
			checkALError("end");
			alDeleteSources(1, &it->second->source);
			checkALError("end");
			delete it->second;
	    }
	    s_effects.clear();

		// and the background too
		stopBackground(true);

		for (BackgroundMusicsMap::iterator it = s_backgroundMusics.begin(); it != s_backgroundMusics.end(); ++it)
		{
			alSourceStop(it->second->source);
			checkALError("end");
			alDeleteBuffers(1, &it->second->buffer);
			checkALError("end");
			alDeleteSources(1, &it->second->source);
			checkALError("end");
			delete it->second;
		}
		s_backgroundMusics.clear();
	}

	//
	// OGG support
	//
	static bool isOGGFile(const char *pszFilePath)
	{
		FILE			*file;
		OggVorbis_File   ogg_file;
		int				 result;

		file = fopen(pszFilePath, "rb");
		result = ov_test(file, &ogg_file, 0, 0);
		ov_clear(&ogg_file);

		return (result == 0);
	}

	static ALuint createBufferFromOGG(const char *pszFilePath)
	{
		ALuint 			buffer;
		OggVorbis_File  ogg_file;
		vorbis_info*    info;
		ALenum 			format;
		int 			result;
		int 			section;
		unsigned int 	size = 0;

		if (ov_fopen(pszFilePath, &ogg_file) < 0)
		{
			ov_clear(&ogg_file);
			fprintf(stderr, "Could not open OGG file %s\n", pszFilePath);
			return -1;
		}

		info = ov_info(&ogg_file, -1);

		if (info->channels == 1)
			format = AL_FORMAT_MONO16;
		else
			format = AL_FORMAT_STEREO16;

		// size = #samples * #channels * 2 (for 16 bit)
		unsigned int data_size = ov_pcm_total(&ogg_file, -1) * info->channels * 2;
		char* data = new char[data_size];

		while (size < data_size)
		{
			result = ov_read(&ogg_file, data + size, data_size - size, 0, 2, 1, &section);
			if (result > 0)
			{
				size += result;
			}
			else if (result < 0)
			{
				delete [] data;
				fprintf(stderr, "OGG file problem %s\n", pszFilePath);
				return -1;
			}
			else
			{
				break;
			}
		}

		if (size == 0)
		{
			delete [] data;
			fprintf(stderr, "Unable to read OGG data\n");
			return -1;
		}

		// clear al errors
		checkALError("createBufferFromOGG");

	    // Load audio data into a buffer.
	    alGenBuffers(1, &buffer);

	    if (checkALError("createBufferFromOGG") != AL_NO_ERROR)
	    {
	        fprintf(stderr, "Couldn't generate a buffer for OGG file\n");
	        delete [] data;
	        return buffer;
	    }

		alBufferData(buffer, format, data, data_size, info->rate);
		checkALError("createBufferFromOGG");

		delete [] data;
		ov_clear(&ogg_file);

		return buffer;
	}


	//
	// background audio
	//
    void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath)
	{
		// Changing file path to full path
    	std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath);

    	BackgroundMusicsMap::const_iterator it = s_backgroundMusics.find(fullPath);
		if (it == s_backgroundMusics.end())
		{
			ALuint buffer = AL_NONE;
			if (isOGGFile(fullPath.data()))
			{
				buffer = createBufferFromOGG(fullPath.data());
			}
			else
			{
				buffer = alutCreateBufferFromFile(fullPath.data());
			}

			checkALError("preloadBackgroundMusic");

			if (buffer == AL_NONE)
			{
				fprintf(stderr, "Error loading file: '%s'\n", fullPath.data());
				alDeleteBuffers(1, &buffer);
				return;
			}

			ALuint source = AL_NONE;
			alGenSources(1, &source);
			checkALError("preloadBackgroundMusic");

			alSourcei(source, AL_BUFFER, buffer);
			checkALError("preloadBackgroundMusic");

			backgroundMusicData* data = new backgroundMusicData();
			data->buffer = buffer;
			data->source = source;
			s_backgroundMusics.insert(BackgroundMusicsMap::value_type(fullPath, data));
		}
	}

	void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
	{
		if (s_backgroundSource != AL_NONE)
			stopBackgroundMusic(false);

		// Changing file path to full path
    	std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath);

    	BackgroundMusicsMap::const_iterator it = s_backgroundMusics.find(fullPath);
		if (it == s_backgroundMusics.end())
		{
			preloadBackgroundMusic(fullPath.c_str());
			it = s_backgroundMusics.find(fullPath);
		}

		if (it != s_backgroundMusics.end())
		{
			s_backgroundSource = it->second->source;
			alSourcei(s_backgroundSource, AL_LOOPING, bLoop ? AL_TRUE : AL_FALSE);
			alSourcePlay(s_backgroundSource);
			checkALError("playBackgroundMusic");
		}
	}

	void SimpleAudioEngine::stopBackgroundMusic(bool bReleaseData)
	{
		stopBackground(bReleaseData);
	}

	void SimpleAudioEngine::pauseBackgroundMusic()
	{
		ALint state;
		alGetSourcei(s_backgroundSource, AL_SOURCE_STATE, &state);
		if (state == AL_PLAYING)
			alSourcePause(s_backgroundSource);
		checkALError("pauseBackgroundMusic");
	}

	void SimpleAudioEngine::resumeBackgroundMusic()
	{
		ALint state;
		alGetSourcei(s_backgroundSource, AL_SOURCE_STATE, &state);
		if (state == AL_PAUSED)
			alSourcePlay(s_backgroundSource);
		checkALError("resumeBackgroundMusic");
	} 

	void SimpleAudioEngine::rewindBackgroundMusic()
	{
		alSourceRewind(s_backgroundSource);
		checkALError("rewindBackgroundMusic");
	}

	bool SimpleAudioEngine::willPlayBackgroundMusic()
	{
		return true;
	}

	bool SimpleAudioEngine::isBackgroundMusicPlaying()
	{
	    ALint play_status;
	    alGetSourcei(s_backgroundSource, AL_SOURCE_STATE, &play_status);

		return (play_status == AL_PLAYING);
	}

	float SimpleAudioEngine::getBackgroundMusicVolume()
	{
		return s_volume;
	}

	void SimpleAudioEngine::setBackgroundMusicVolume(float volume)
	{
		if (s_volume != volume && volume >= -0.0001 && volume <= 1.0001)
		{
    		s_volume = volume;

			setBackgroundVolume(volume);
		}
	}

	//
	// Effect audio (using OpenAL)
	//
	float SimpleAudioEngine::getEffectsVolume()
	{
		return s_effectVolume;
	}

	void SimpleAudioEngine::setEffectsVolume(float volume)
	{
		if (volume != s_effectVolume)
		{
			EffectsMap::const_iterator end = s_effects.end();
			for (EffectsMap::const_iterator it = s_effects.begin(); it != end; it++)
			{
				alSourcef(it->second->source, AL_GAIN, volume);
			}

			s_effectVolume = volume;
		}
	}

	unsigned int SimpleAudioEngine::playEffect(const char* pszFilePath, bool bLoop)
	{
		// Changing file path to full path
    	std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath);

		EffectsMap::iterator iter = s_effects.find(fullPath);

		if (iter == s_effects.end())
		{
			preloadEffect(fullPath.c_str());

			// let's try again
			iter = s_effects.find(fullPath);
			if (iter == s_effects.end())
			{
				fprintf(stderr, "could not find play sound %s\n", fullPath.c_str());
				return -1;
			}
		}

		checkALError("playEffect");
		iter->second->isLooped = bLoop;
		alSourcei(iter->second->source, AL_LOOPING, iter->second->isLooped ? AL_TRUE : AL_FALSE);
		alSourcePlay(iter->second->source);
		checkALError("playEffect");

		return iter->second->source;
	}

	void SimpleAudioEngine::stopEffect(unsigned int nSoundId)
	{
		alSourceStop(nSoundId);
		checkALError("stopEffect");
	}

	void SimpleAudioEngine::preloadEffect(const char* pszFilePath)
	{
		// Changing file path to full path
    	std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath);

		EffectsMap::iterator iter = s_effects.find(fullPath);

		// check if we have this already
		if (iter == s_effects.end())
		{
			ALuint 		buffer;
			ALuint 		source;
			soundData  *data = new soundData;
			string 	    path = fullPath;

			checkALError("preloadEffect");

			if (isOGGFile(path.data()))
			{
				buffer = createBufferFromOGG(path.data());
			}
			else
			{
				buffer = alutCreateBufferFromFile(path.data());
				checkALError("preloadEffect");
			}

			if (buffer == AL_NONE)
			{
				fprintf(stderr, "Error loading file: '%s'\n", path.data());
				alDeleteBuffers(1, &buffer);
				return;
			}

			alGenSources(1, &source);

			if (checkALError("preloadEffect") != AL_NO_ERROR)
			{
				alDeleteBuffers(1, &buffer);
				return;
			}

			alSourcei(source, AL_BUFFER, buffer);
			checkALError("preloadEffect");

			data->isLooped = false;
			data->buffer = buffer;
			data->source = source;

			s_effects.insert(EffectsMap::value_type(fullPath, data));
		}
	}

	void SimpleAudioEngine::unloadEffect(const char* pszFilePath)
	{
		// Changing file path to full path
    	std::string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(pszFilePath);
    	
		EffectsMap::iterator iter = s_effects.find(fullPath);

		if (iter != s_effects.end())
	    {
			checkALError("unloadEffect");

	        alSourceStop(iter->second->source);
	        checkALError("unloadEffect");

			alDeleteSources(1, &iter->second->source);
			checkALError("unloadEffect");

			alDeleteBuffers(1, &iter->second->buffer);
			checkALError("unloadEffect");
			delete iter->second;

			s_effects.erase(iter);
	    }
	}

	void SimpleAudioEngine::pauseEffect(unsigned int nSoundId)
	{
		ALint state;
		alGetSourcei(nSoundId, AL_SOURCE_STATE, &state);
		if (state == AL_PLAYING)
			alSourcePause(nSoundId);
		checkALError("pauseEffect");
	}

	void SimpleAudioEngine::pauseAllEffects()
	{
		EffectsMap::iterator iter = s_effects.begin();
		ALint state;
		while (iter != s_effects.end())
	    {
			alGetSourcei(iter->second->source, AL_SOURCE_STATE, &state);
			if (state == AL_PLAYING)
				alSourcePause(iter->second->source);
			checkALError("pauseAllEffects");
			++iter;
	    }
	}

	void SimpleAudioEngine::resumeEffect(unsigned int nSoundId)
	{
		ALint state;
		alGetSourcei(nSoundId, AL_SOURCE_STATE, &state);
		if (state == AL_PAUSED)
			alSourcePlay(nSoundId);
		checkALError("resumeEffect");
	}

	void SimpleAudioEngine::resumeAllEffects()
	{
		EffectsMap::iterator iter = s_effects.begin();
		ALint state;
		while (iter != s_effects.end())
	    {
			alGetSourcei(iter->second->source, AL_SOURCE_STATE, &state);
			if (state == AL_PAUSED)
				alSourcePlay(iter->second->source);
			checkALError("resumeAllEffects");
			++iter;
	    }
	}

    void SimpleAudioEngine::stopAllEffects()
    {
		EffectsMap::iterator iter = s_effects.begin();

		if (iter != s_effects.end())
	    {
			checkALError("stopAllEffects");
	        alSourceStop(iter->second->source);
			checkALError("stopAllEffects");
	    }
    }

}