void * SoundManager::playSoundOnce(const char * soundId, const bool isMusic, const bool update)
{
    if (0 == strcmp(soundId, "")) return nullptr;
    
#ifdef FMOD_ACTIVE
    FMOD::Studio::ID sndID = {0};
    ERRCHECK(_system->lookupID(soundId, &sndID));
    FMOD::Studio::EventDescription* sndDescription = NULL;
    ERRCHECK(_system->getEventByID(&sndID, &sndDescription) );
    
    bool isOneShot;
    sndDescription->isOneshot(&isOneShot);
    if (!isOneShot)
    {
        CCLOG("ATTENZIONE: Il suono non è fire and forget");
    }
    
    FMOD::Studio::EventInstance* instance = NULL;
    ERRCHECK(sndDescription->createInstance(&instance));
    
    this->setVolumeForSound(instance, isMusic);
    
    ERRCHECK(instance->start());
    ERRCHECK(instance->release());
    if (update)
    {
        ERRCHECK(_system->update());
    }
    
    return instance;
#else
    return nullptr;
#endif
}
bool SoundManager::removeInstanceById(const std::string uniqueId)
{
#ifdef FMOD_ACTIVE
    FMOD::Studio::EventInstance * previousInstance = _instancesMap[uniqueId];
    if (previousInstance)
    {
        ERRCHECK(previousInstance->stop(FMOD_STUDIO_STOP_ALLOWFADEOUT));
        ERRCHECK(previousInstance->release());
        _instancesMap.erase(uniqueId);
        return true;
    }
#endif
    return false;
}
void SoundManager::stopPlaySound(void * soundHandle, const bool fadeOut)
{
#ifdef FMOD_ACTIVE
    FMOD::Studio::EventInstance * instance = static_cast<FMOD::Studio::EventInstance *>(soundHandle);
    if ( nullptr != instance && instance->isValid() )
    {
        ERRCHECK(instance->stop((fadeOut) ? FMOD_STUDIO_STOP_ALLOWFADEOUT : FMOD_STUDIO_STOP_IMMEDIATE));
        ERRCHECK(_system->update());
        
        _instancesFX.erase(std::remove(_instancesFX.begin(), _instancesFX.end(), instance), _instancesFX.end());
        _instancesMusic.erase(std::remove(_instancesMusic.begin(), _instancesMusic.end(), instance), _instancesMusic.end());
        for (auto iter = _instancesMap.begin(); iter != _instancesMap.end(); iter++ )
        {
            if (iter->second == soundHandle)
            {
                _instancesMap.erase(iter);
                break;
            }
        }
        ERRCHECK(instance->release());
    }
#endif
}
Exemple #4
0
int FMOD_Main()
{
    //void *extraDriverData = NULL;
    Common_Init(NULL);

    FMOD::Studio::System* system = NULL;
    ERRCHECK( FMOD::Studio::System::create(&system) );

    // The example Studio project is authored for 5.1 sound, so set up the system output mode to match
    //
    //ERRCHECK( lowLevelSystem->setSoftwareFormat(0, FMOD_SPEAKERMODE_5POINT1, 0) );

    ERRCHECK( system->initialize(32, FMOD_STUDIO_INIT_NORMAL, FMOD_INIT_NORMAL, NULL) );

	FMOD::System* lowLevelSystem = NULL;
    ERRCHECK( system->getLowLevelSystem(&lowLevelSystem) );

	FMOD_ADVANCEDSETTINGS set = {0};
	set.cbSize = sizeof(FMOD_ADVANCEDSETTINGS);
	
	lowLevelSystem->getAdvancedSettings(&set);

	srand(time(NULL));
	set.cbSize = sizeof(FMOD_ADVANCEDSETTINGS);
	set.randomSeed = rand();
	printf("%d\n",set.randomSeed);

	lowLevelSystem->setAdvancedSettings(&set);
    
    FMOD::Studio::Bank* masterBank = NULL;
    ERRCHECK( system->loadBankFile(Common_MediaPath("Master Bank.bank"), FMOD_STUDIO_LOAD_BANK_NORMAL, &masterBank) );
    
    FMOD::Studio::Bank* stringsBank = NULL;
    ERRCHECK( system->loadBankFile(Common_MediaPath("Master Bank.strings.bank"), FMOD_STUDIO_LOAD_BANK_NORMAL, &stringsBank) );
    
    FMOD::Studio::Bank* ambienceBank = NULL;
    ERRCHECK( system->loadBankFile(Common_MediaPath("Surround_Ambience.bank"), FMOD_STUDIO_LOAD_BANK_NORMAL, &ambienceBank) );
    
    FMOD::Studio::Bank* menuBank = NULL;
    ERRCHECK( system->loadBankFile(Common_MediaPath("UI_Menu.bank"), FMOD_STUDIO_LOAD_BANK_NORMAL, &menuBank) );
    
    FMOD::Studio::Bank* weaponsBank = NULL;
    ERRCHECK( system->loadBankFile(Common_MediaPath("Weapons.bank"), FMOD_STUDIO_LOAD_BANK_NORMAL, &weaponsBank) );

	
    FMOD::Studio::Bank* characterBank = NULL;
    ERRCHECK( system->loadBankFile(Common_MediaPath("Character.bank"), FMOD_STUDIO_LOAD_BANK_NORMAL, &characterBank) );

    // Get the Looping Ambience event
    FMOD::Studio::EventDescription* loopingAmbienceDescription = NULL;
    ERRCHECK( system->getEvent("event:/Ambience/Country", &loopingAmbienceDescription) );
    
    FMOD::Studio::EventInstance* loopingAmbienceInstance = NULL;
    ERRCHECK( loopingAmbienceDescription->createInstance(&loopingAmbienceInstance) );
    
    // Get the 4 Second Surge event
    FMOD::Studio::EventDescription* cancelDescription = NULL;
    ERRCHECK( system->getEvent("event:/Character/Hand Foley/Doorknob", &cancelDescription) );
    
    FMOD::Studio::EventInstance* cancelInstance = NULL;
    ERRCHECK( cancelDescription->createInstance(&cancelInstance) );
    
    // Get the Single Explosion event
    FMOD::Studio::EventDescription* explosionDescription = NULL;
    ERRCHECK( system->getEvent("event:/Explosions/Single Explosion", &explosionDescription) );

    // Start loading explosion sample data and keep it in memory
    ERRCHECK( explosionDescription->loadSampleData() );

    do
    {
        Common_Update();
        
        if (Common_BtnPress(BTN_ACTION1))
        {
            // One-shot event
            FMOD::Studio::EventInstance* eventInstance = NULL;
            ERRCHECK( explosionDescription->createInstance(&eventInstance) );

            ERRCHECK( eventInstance->start() );

            // Release will clean up the instance when it completes
            ERRCHECK( eventInstance->release() );
        }
    
        if (Common_BtnPress(BTN_ACTION2))
        {
            ERRCHECK( loopingAmbienceInstance->start() );
        }

        if (Common_BtnPress(BTN_ACTION3))
        {
            ERRCHECK( loopingAmbienceInstance->stop(FMOD_STUDIO_STOP_IMMEDIATE) );
        }

        if (Common_BtnPress(BTN_ACTION4))
        {
            // Calling start on an instance will cause it to restart if it's already playing
            ERRCHECK( cancelInstance->start() );
        }

        ERRCHECK( system->update() );

        Common_Draw("==================================================");
        Common_Draw("Simple Event Example.");
        Common_Draw("Copyright (c) Firelight Technologies 2014-2014.");
        Common_Draw("==================================================");
        Common_Draw("");
        Common_Draw("Press %s to fire and forget the explosion", Common_BtnStr(BTN_ACTION1));
        Common_Draw("Press %s to start the looping ambience", Common_BtnStr(BTN_ACTION2));
        Common_Draw("Press %s to stop the looping ambience", Common_BtnStr(BTN_ACTION3));
        Common_Draw("Press %s to start/restart the cancel sound", Common_BtnStr(BTN_ACTION4));
        Common_Draw("Press %s to quit", Common_BtnStr(BTN_QUIT));

        Common_Sleep(50);
    } while (!Common_BtnPress(BTN_QUIT));
    
    ERRCHECK( weaponsBank->unload() );
    ERRCHECK( menuBank->unload() );
    ERRCHECK( ambienceBank->unload() );
    ERRCHECK( stringsBank->unload() );
    ERRCHECK( masterBank->unload() );
	ERRCHECK( characterBank->unload() );

    ERRCHECK( system->release() );

    Common_Close();

    return 0;
}
void outputEventByID(FMOD::Studio::System* system, const char* ID)
{
	FMOD_RESULT result;

	FMOD::Studio::ID eventID = { 0 };
	ERRCHECK(system->lookupID(ID, &eventID));  //Lookup the ID string from the banks

											   //Use the ID to get the event
	FMOD::Studio::EventDescription* eventDescription = NULL;
	ERRCHECK(system->getEventByID(&eventID, &eventDescription));

	// Create an instance of the event
	FMOD::Studio::EventInstance* eventInstance = NULL;
	ERRCHECK(eventDescription->createInstance(&eventInstance));
	
	//Preload sample data - otherwise some sounds just dont play
	//eventDescription->loadSampleData(); Done need this -  docs say it starts loading sample as soon as eventinstance created
	FMOD_STUDIO_LOADING_STATE  loadingState = FMOD_STUDIO_LOADING_STATE_LOADING;
	system->update();
	ERRCHECK(eventDescription->getSampleLoadingState(&loadingState));
	while (loadingState != FMOD_STUDIO_LOADING_STATE_LOADED)
	{
		//if (eventDescription->getSampleLoadingState(&loadingState)  == FMOD_OK)
		//{
		//	system->update();
		//}
		//else
		//{}
		//Sleep(1);
		ERRCHECK(eventDescription->getSampleLoadingState(&loadingState));
		system->update();
	}

	//Try and stop looping :~ failed
	//FMOD::ChannelGroup* Channels = NULL;
	//eventInstance->getChannelGroup(&Channels);
	//Channels->setMode(FMOD_LOOP_OFF);


	cout << "Dumping " << ID << endl;

	//TODO - delete file if length is 0 - no point having empty files around
	int length = 0;
	result = eventDescription->getLength(&length);
	if (length == 0)
	{
		return;
	}
	float rate = 1024.0f / 48000.0f;
	float newlength = (float)length / 1000; //turn length into seconds
	float totalCalls = (newlength) / rate; // calculate how many calls of our loop we need till the sound has been played
	float totalTime = 0.0f;
	//bool played = false;
	//OutputDebugString(ID); OutputDebugString("\n");

	//Start playback
	ERRCHECK(eventInstance->start()); //starting here seems to work ok
	
	FMOD_STUDIO_PLAYBACK_STATE playbackState = FMOD_STUDIO_PLAYBACK_STOPPED;
	//system->update();
	eventInstance->getPlaybackState(&playbackState);
	while (playbackState != FMOD_STUDIO_PLAYBACK_PLAYING)
	{
		eventInstance->getPlaybackState(&playbackState);
		system->update();
	}

	int TimelinePos = 0;
	int LastPos = -1;
	//for (int i = 0; i < totalCalls; i++)
	while (TimelinePos < length)
	{
		// if(1000 <= totalTime && !played)
		// {
		//// play sound just once
		//  //ERRCHECK( eventInstance->start() );
		//played = true;
		// }


		eventInstance->getTimelinePosition(&TimelinePos);
		char buffer[255 + 1];
		sprintf(buffer, "Timeline Position is %d\n", TimelinePos);
		OutputDebugString(buffer);

		if (LastPos > TimelinePos) //Looping sounds repeat it seems eg mus_loop_tense never reaches timelinepos then starts again
		{
			break;
		}
		LastPos = TimelinePos;
		system->update();
		Sleep(1);
		//Sleep(1.5); //Crucial! Slows it down enough so that sounds start and end at correct time
					//Big hack but still cant fix it. Tried with callbacks and other methods - this
					//Is the only way that 'reliably' works
		//totalTime += (rate * 1000);
		//sprintf(buffer, "TotalTime Position is %f\n", totalTime);
		//OutputDebugString(buffer);
	}

	eventInstance->stop(FMOD_STUDIO_STOP_ALLOWFADEOUT); //FMOD_STUDIO_STOP_ALLOWFADEOUT 

	playbackState = FMOD_STUDIO_PLAYBACK_STOPPING;
	while (playbackState != FMOD_STUDIO_PLAYBACK_STOPPED)
	{
		eventInstance->getPlaybackState(&playbackState);
		system->update();
	}

	eventInstance->release(); //necessary?????
	eventDescription->unloadSampleData();

	system->update();
	loadingState = FMOD_STUDIO_LOADING_STATE_LOADED;
	while (loadingState != FMOD_STUDIO_LOADING_STATE_UNLOADED)
	{
		if (eventDescription->getSampleLoadingState(&loadingState) == FMOD_OK)
		{
			//system->update();
		}
		else
		{
		}
	}

	//eventDescription->releaseAllInstances;
}
bool outputEventByID(FMOD::Studio::System* system, const char* ID)
{
	FMOD_RESULT result;

	FMOD::Studio::ID eventID = { 0 };
	ERRCHECK(system->lookupID(ID, &eventID));  //Lookup the ID string from the banks

	//Use the ID to get the event
	FMOD::Studio::EventDescription* eventDescription = NULL;
	ERRCHECK(system->getEventByID(&eventID, &eventDescription));

	// Create an instance of the event
	FMOD::Studio::EventInstance* eventInstance = NULL;
	ERRCHECK(eventDescription->createInstance(&eventInstance));
	
	//Preload sample data - otherwise some sounds just dont play
	//eventDescription->loadSampleData(); Done need this -  docs say it starts loading sample as soon as eventinstance created
	FMOD_STUDIO_LOADING_STATE  loadingState = FMOD_STUDIO_LOADING_STATE_LOADING;
	system->update();
	ERRCHECK(eventDescription->getSampleLoadingState(&loadingState));
	while (loadingState != FMOD_STUDIO_LOADING_STATE_LOADED)
	{
		ERRCHECK(eventDescription->getSampleLoadingState(&loadingState));
		system->update();
	}

	
	int length = 0;
	result = eventDescription->getLength(&length);
	if (length == 0)
	{
		return false; 
	}


	cout << "Dumping " << ID << endl;

	int TimelinePos = 0;
	int LastPos = -1;
	bool played = false;

	while (TimelinePos < length)
	{
		if (!played)
		{
			ERRCHECK(eventInstance->start()); //Start playback
			played = true;
		}
		
		eventInstance->getTimelinePosition(&TimelinePos);
		//char buffer[255 + 1];
		//sprintf(buffer, "Timeline Position is %d\n", TimelinePos);
		//OutputDebugString(buffer);

		if (LastPos > TimelinePos) //Looping sounds repeat and have wrong getlength value eg mus_loop_tense never reaches timelinepos 
		{						   //Seems to report a longer length than reality. So if we dont manually stop it, the track loops forever
			break;
		}
		LastPos = TimelinePos;
		system->update();
		Sleep(1);   //Crucial! Slows it down enough so that sounds start and end at correct time
					//Big hack but still cant fix it. Tried with callbacks and other methods - this
					//Is the only way that 'reliably' works
	}

	eventInstance->stop(FMOD_STUDIO_STOP_IMMEDIATE); //FMOD_STUDIO_STOP_ALLOWFADEOUT 
	FMOD_STUDIO_PLAYBACK_STATE playbackState = FMOD_STUDIO_PLAYBACK_STOPPING;
	while (playbackState != FMOD_STUDIO_PLAYBACK_STOPPED)
	{
		eventInstance->getPlaybackState(&playbackState);
		system->update();
	}

	eventInstance->release(); //necessary?????
	eventDescription->unloadSampleData();

	system->update();
	loadingState = FMOD_STUDIO_LOADING_STATE_LOADED;
	while (loadingState != FMOD_STUDIO_LOADING_STATE_UNLOADED)
	{
		if (eventDescription->getSampleLoadingState(&loadingState) == FMOD_OK)
		{
			//system->update();
		}
		else
		{
		}
	}

	//eventDescription->releaseAllInstances;
	return true;
}