void SimpleAudioEngine::preloadEffect(const char* pszFilePath)
	{
		EffectsMap::iterator iter = s_effects.find(pszFilePath);

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

			string path = pszFilePath;

			buffer = alutCreateBufferFromFile(path.data());

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

			alGenSources(1, &source);
			alSourcei(source, AL_BUFFER, buffer);

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

			s_effects.insert(EffectsMap::value_type(pszFilePath, data));
		}
	}
	unsigned int SimpleAudioEngine::playEffect(const char* pszFilePath, bool bLoop)
	{
		EffectsMap::iterator iter = s_effects.find(pszFilePath);

		if (iter == s_effects.end())
		{
			preloadEffect(pszFilePath);

			// let's try again
			iter = s_effects.find(pszFilePath);
			if (iter == s_effects.end())
			{
				fprintf(stderr, "could not find play sound %s\n", pszFilePath);
				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;
	}
Example #3
0
	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::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::pauseAllEffects()
	{
		EffectsMap::iterator iter = s_effects.begin();

		if (iter != s_effects.end())
	    {
			alSourcePause(iter->second->source);
			checkALError("pauseAllEffects");
	    }
	}
	void SimpleAudioEngine::resumeAllEffects()
	{
		EffectsMap::iterator iter = s_effects.begin();

		if (iter != s_effects.end())
	    {
			checkALError("resumeAllEffects");
			alSourcePlay(iter->second->source);
			checkALError("resumeAllEffects");
	    }
	}
void SimpleAudioEngine::stopAllEffects()
{
    EffectsMap::iterator iter = s_effects.begin();

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

		if (iter != s_effects.end())
	    {
	        alSourceStop(iter->second->source);
			int err = alGetError();
			if (err != AL_NO_ERROR)
				printALError(err);
	    }
    }
Example #9
0
	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::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;
    }
}
Example #11
0
	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::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;
    }
}
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)
	{
        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);
	}
	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::unloadEffect(const char* pszFilePath)
	{
		EffectsMap::iterator iter = s_effects.find(pszFilePath);

		if (iter != s_effects.end())
	    {
	        alSourceStop(iter->second->source);
			alDeleteSources(1, &iter->second->source);
			alDeleteBuffers(1, &iter->second->buffer);
			delete iter->second;

			int err = alGetError();
			if (err != AL_NO_ERROR)
				printALError(err);

			s_effects.erase(iter);
	    }
	}
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::unloadEffect(const char* pszFilePath)
	{
		EffectsMap::iterator iter = s_effects.find(pszFilePath);

		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::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();
	}
	void SimpleAudioEngine::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);

			alDeleteBuffers(1, &it->second->buffer);
			alDeleteSources(1, &it->second->source);
			delete it->second;
	    }
	    s_effects.clear();

		if (s_isBackgroundInitialized)
		{
			s_isBackgroundInitialized = false;
		}

		// and the background too
		stopBackground(true);
	}
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::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 System<EffectsComp>::update(double elapsed)
{

    std::map<ObjectId,EffectsComp>::iterator iCom = components_.begin();

    while(iCom!=components_.end())
    {
        EffectsComp* effectsComp = &iCom->second;
        EffectsMap* effectsMap = effectsComp->getEffects();
//        std::cout << "Address of effectsMap: "<< effectsMap << std::endl;
//        std::cout << "copy of effects map size : "<< effectsMap->size() << std::endl;
//        std::cout << "orig effects map size : " << effectsComp->getEffects()->size() << std::endl;
        //update each effect in component as necessary
        EffectsMap::iterator iEffect = effectsMap->begin();
        while(iEffect!=effectsMap->end())
        {
             //update timer if necessary
            if(iEffect->second->hasDuration())
            {
                iEffect->second->updateDuration(elapsed);
                //check if timer has expired
                if (iEffect->second->hasExpired())
                {
                    //do on end messages
                    std::vector<Parameters> endParams = iEffect->second->getOnEnd();
                    std::vector<Parameters>::iterator iParams = endParams.begin();
                    while(iParams!= endParams.end())
                    {
                        if(iParams->size()>0)
                        {
                            Message msg(effectsComp->getId(), effectsComp->getId(), *iParams);
                            Telegram tel(effectsComp->getId(), effectsComp->getId(), 0.0, msg);
                            core_->getMessageCentre()->addTelegram(tel);
                        }
                        ++iParams;
                    }

                    //delete params
                    effectsMap->erase(iEffect++);
                    continue;
                }

            }

            //carry out onUpdate messages
            std::vector<Parameters> updateParams = iEffect->second->getOnUpdate();
            std::vector<Parameters>::iterator iParams = updateParams.begin();
            while(iParams!= updateParams.end())
            {
                if(iParams->size()>0)
                {
                    Message msg(effectsComp->getId(), effectsComp->getId(), *iParams);
                    Telegram tel(effectsComp->getId(), effectsComp->getId(), 0.0, msg);
                    core_->getMessageCentre()->addTelegram(tel);
                }
                ++iParams;
            }

            ++iEffect;

        }

        ++iCom;
    }


}
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 int	 s_audioOid;

	static float s_volume 				  = 1.0f;
	static float s_effectVolume			  = 1.0f;
	static bool s_isBackgroundInitialized = false;
	static bool s_hasMMRError			  = false;
	static playStatus s_playStatus	  	  = STOPPED;

	static string 		   s_currentBackgroundStr;
	static mmr_connection_t   *s_mmrConnection 	  = 0;
	static mmr_context_t 	  *s_mmrContext 	  = 0;
	static strm_dict_t 		  *s_repeatDictionary = 0;
	static strm_dict_t 		  *s_volumeDictionary = 0;

	static SimpleAudioEngine  *s_engine = 0;

	static void printALError(int err)
	{
		switch (err)
		{
			case AL_NO_ERROR:
				fprintf(stderr, "AL_NO_ERROR");
				break;

			case AL_INVALID_NAME:
				fprintf(stderr, "AL_INVALID_NAME");
				break;

			case AL_INVALID_ENUM:
				fprintf(stderr, "AL_INVALID_ENUM");
				break;

			case AL_INVALID_VALUE:
				fprintf(stderr, "AL_INVALID_VALUE");
				break;

			case AL_INVALID_OPERATION:
				fprintf(stderr, "AL_INVALID_OPERATION");
				break;

			case AL_OUT_OF_MEMORY:
				fprintf(stderr, "AL_OUT_OF_MEMORY");
				break;
		};
	}

    static void mmrerror(mmr_context_t *ctxt, const char *msg)
    {
    	const mmr_error_info_t  *err = mmr_error_info( ctxt );
    	unsigned 				 errcode = (err) ? err->error_code : -1;
    	const char 				*name;

    	fprintf(stderr, "%s: error %d \n", msg, errcode);
    	s_hasMMRError = true;
    }

    static void stopBackground(bool bReleaseData)
    {
    	s_playStatus = STOPPED;

		if (s_mmrContext)
			mmr_stop(s_mmrContext);

		if (bReleaseData)
		{
			if (s_mmrContext)
			{
				mmr_input_detach(s_mmrContext);
				mmr_context_destroy(s_mmrContext);
			}

			if (s_mmrConnection)
				mmr_disconnect(s_mmrConnection);

			if (s_repeatDictionary)
				strm_dict_destroy(s_repeatDictionary);

			if (s_volumeDictionary)
				strm_dict_destroy(s_volumeDictionary);

			s_mmrContext = 0;
			s_mmrConnection = 0;
			s_repeatDictionary = 0;
			s_volumeDictionary = 0;
			s_hasMMRError = false;
			s_currentBackgroundStr = "";
			s_isBackgroundInitialized = false;
		}
    }

    static void setBackgroundVolume(float volume)
    {
    	if (!s_isBackgroundInitialized)
    	{
    		return;
    	}
		char volume_str[128];

		// set it up the background volume
		strm_dict_t *dictionary = strm_dict_new();

		sprintf(volume_str, "%d", (int)(volume * 100) );
		s_volumeDictionary = strm_dict_set(dictionary, "volume", volume_str);

		if (mmr_output_parameters(s_mmrContext, s_audioOid, s_volumeDictionary) != 0)
		{
			mmrerror(s_mmrContext, "output parameters");
			return;
		}
    }

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

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

	SimpleAudioEngine* SimpleAudioEngine::sharedEngine()
	{
		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++)
	    {
	        alSourceStop(it->second->source);

			alDeleteBuffers(1, &it->second->buffer);
			alDeleteSources(1, &it->second->source);
			delete it->second;
	    }
	    s_effects.clear();

		if (s_isBackgroundInitialized)
		{
			s_isBackgroundInitialized = false;
		}

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

	void SimpleAudioEngine::setResource(const char* pszZipFileName)
	{
	}

	//
	// background audio (using mmrenderer)
	//
    void SimpleAudioEngine::preloadBackgroundMusic(const char* pszFilePath)
	{
    	if (!s_isBackgroundInitialized)
    	{
    		const char 		*mmrname = NULL;
    		const char 		*ctxtname = "mmrplayer";
    		char 			 cwd[PATH_MAX];
    		mode_t 			 mode = S_IRUSR | S_IXUSR;

    		getcwd(cwd, PATH_MAX);
    		string path = "file://";
    		path += cwd;
    		path += "/";
    		path += pszFilePath;

    		s_mmrConnection = mmr_connect(mmrname);
    		if (!s_mmrConnection)
    		{
    			perror("mmr_connect");
    			s_hasMMRError = true;
    			return;
    		}

    		s_mmrContext = mmr_context_create(s_mmrConnection, ctxtname, 0, mode);
    		if (!s_mmrContext)
    		{
    			perror(ctxtname);
    			s_hasMMRError = true;
    			return;
    		}

    		if ((s_audioOid = mmr_output_attach(s_mmrContext, "audio:default", "audio")) < 0)
    		{
    			mmrerror(s_mmrContext, "audio:default");
    			return;
    		}

    		if (mmr_input_attach(s_mmrContext, path.data(), "autolist") < 0)
    		{
    			fprintf(stderr, "unable to load %s\n", path.data());
    			mmrerror(s_mmrContext, path.data());
    			return;
    		}

    		s_currentBackgroundStr 	  = pszFilePath;
			s_isBackgroundInitialized = true;
			setBackgroundVolume(s_volume);
    	}
	}

	void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
	{
		if (0 != strcmp(s_currentBackgroundStr.c_str(), pszFilePath))
		{
			stopBackgroundMusic(true);
		}
		else
		{
			if (s_playStatus == PAUSED)
				resumeBackgroundMusic();
			else
				rewindBackgroundMusic();
		}

		if (!s_isBackgroundInitialized)
			preloadBackgroundMusic(pszFilePath);

		if (bLoop)
		{
			// set it up to loop
			strm_dict_t *dictionary = strm_dict_new();
			s_repeatDictionary = strm_dict_set(dictionary, "repeat", "all");

    		if (mmr_input_parameters(s_mmrContext, s_repeatDictionary) != 0)
    		{
    			mmrerror(s_mmrContext, "input parameters (loop)");
    			return;
    		}
		}

		if (s_hasMMRError || !s_mmrContext)
			return;

		if (mmr_play(s_mmrContext) < 0)
		{
			mmrerror(s_mmrContext, "mmr_play");
			s_hasMMRError = true;
		}

		if (!s_hasMMRError)
			s_playStatus = PLAYING;
	}

	void SimpleAudioEngine::stopBackgroundMusic(bool bReleaseData)
	{
    	// if we were paused then we need to resume first so that we can play
		if (s_playStatus == PAUSED)
			resumeBackgroundMusic();

		stopBackground(bReleaseData);
	}

	void SimpleAudioEngine::pauseBackgroundMusic()
	{
		if (s_mmrContext && mmr_speed_set(s_mmrContext, 0) < 0)
		{
			mmrerror(s_mmrContext, "pause");
		}
		s_playStatus = PAUSED;
	}

	void SimpleAudioEngine::resumeBackgroundMusic()
	{
		if (s_mmrContext && mmr_speed_set(s_mmrContext, 1000) < 0)
		{
			mmrerror(s_mmrContext, "resume");
		}
		s_playStatus = PLAYING;
	} 

	void SimpleAudioEngine::rewindBackgroundMusic()
	{
		if (s_mmrContext && mmr_seek(s_mmrContext, "1:0") < 0)
		{
			mmrerror(s_mmrContext, "rewind");
		}
	}

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

	bool SimpleAudioEngine::isBackgroundMusicPlaying()
	{
		return (s_playStatus == PLAYING) && s_isBackgroundInitialized;
	}

	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)
	{
		EffectsMap::iterator iter = s_effects.find(pszFilePath);

		if (iter == s_effects.end())
		{
			preloadEffect(pszFilePath);

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

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

		return iter->second->source;
	}

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

	void SimpleAudioEngine::preloadEffect(const char* pszFilePath)
	{
		EffectsMap::iterator iter = s_effects.find(pszFilePath);

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

			string path = pszFilePath;

			buffer = alutCreateBufferFromFile(path.data());

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

			alGenSources(1, &source);
			alSourcei(source, AL_BUFFER, buffer);

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

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

	void SimpleAudioEngine::unloadEffect(const char* pszFilePath)
	{
		EffectsMap::iterator iter = s_effects.find(pszFilePath);

		if (iter != s_effects.end())
	    {
	        alSourceStop(iter->second->source);
			alDeleteSources(1, &iter->second->source);
			alDeleteBuffers(1, &iter->second->buffer);
			delete iter->second;

			int err = alGetError();
			if (err != AL_NO_ERROR)
				printALError(err);

			s_effects.erase(iter);
	    }
	}

	void SimpleAudioEngine::pauseEffect(unsigned int nSoundId)
	{
		alSourcePause(nSoundId);
	}

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

		if (iter != s_effects.end())
	    {
			alSourcePause(iter->second->source);
			int err = alGetError();
			if (err != AL_NO_ERROR)
				printALError(err);
	    }
	}

	void SimpleAudioEngine::resumeEffect(unsigned int nSoundId)
	{
		alSourcePlay(nSoundId);
	}

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

		if (iter != s_effects.end())
	    {
			alSourcePlay(iter->second->source);
			int err = alGetError();
			if (err != AL_NO_ERROR)
				printALError(err);
	    }
	}

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

		if (iter != s_effects.end())
	    {
	        alSourceStop(iter->second->source);
			int err = alGetError();
			if (err != AL_NO_ERROR)
				printALError(err);
	    }
    }

}
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;
	static bool  s_isBackgroundInitialized = false;
	static std::string s_currentBackgroundStr;

	ALuint s_backgroundBuffer;
	ALuint s_backgroundSource;

	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)
		{
			s_currentBackgroundStr = "";
			s_isBackgroundInitialized = false;

			alDeleteBuffers(1, &s_backgroundBuffer);
			checkALError("stopBackground");
			alDeleteSources(1, &s_backgroundSource);
			checkALError("stopBackground");
		}
    }

    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);
	}

	void SimpleAudioEngine::setResource(const char* pszZipFileName)
	{
	}

	//
	// 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;
		int				err;
		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)
	{
		if (!s_isBackgroundInitialized || s_currentBackgroundStr != pszFilePath)
		{
			string path = pszFilePath;

			if (isOGGFile(path.data()))
			{
				s_backgroundBuffer = createBufferFromOGG(path.data());
			}
			else
			{
				s_backgroundBuffer = alutCreateBufferFromFile(path.data());
			}

			checkALError("preloadBackgroundMusic");

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

			alGenSources(1, &s_backgroundSource);
			checkALError("preloadBackgroundMusic");

			alSourcei(s_backgroundSource, AL_BUFFER, s_backgroundBuffer);
			checkALError("preloadBackgroundMusic");

			s_currentBackgroundStr = pszFilePath;
		}

		s_currentBackgroundStr 	  = pszFilePath;
		s_isBackgroundInitialized = true;
	}

	void SimpleAudioEngine::playBackgroundMusic(const char* pszFilePath, bool bLoop)
	{
		if (!s_isBackgroundInitialized)
			preloadBackgroundMusic(pszFilePath);

		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()
	{
		alSourcePause(s_backgroundSource);
		checkALError("pauseBackgroundMusic");
	}

	void SimpleAudioEngine::resumeBackgroundMusic()
	{
		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)
	{
		EffectsMap::iterator iter = s_effects.find(pszFilePath);

		if (iter == s_effects.end())
		{
			preloadEffect(pszFilePath);

			// let's try again
			iter = s_effects.find(pszFilePath);
			if (iter == s_effects.end())
			{
				fprintf(stderr, "could not find play sound %s\n", pszFilePath);
				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)
	{
		EffectsMap::iterator iter = s_effects.find(pszFilePath);

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

			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(pszFilePath, data));
		}
	}

	void SimpleAudioEngine::unloadEffect(const char* pszFilePath)
	{
		EffectsMap::iterator iter = s_effects.find(pszFilePath);

		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)
	{
		alSourcePause(nSoundId);
		checkALError("pauseEffect");
	}

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

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

	void SimpleAudioEngine::resumeEffect(unsigned int nSoundId)
	{
		alSourcePlay(nSoundId);
		checkALError("resumeEffect");
	}

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

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

    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;
    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");
	    }
    }

}