//Sets a parameter a of effect e to value v. For parameters of different effects, see fmod_dsp_effects.h GMexport double FMODGMS_Effect_Set_Parameter(double e, double p, double v) { int effectIndex = (int)round(e); if ((effectIndex < 0) || (effectIndex >= (int)effectList.size())) { errorMessage = "Invalid effect index"; return GMS_error; } FMOD::DSP* effect = effectList[effectIndex]; int param = (int)round(p); int value = (int)round(v); FMOD_DSP_PARAMETER_DESC* desc = NULL; if (effect->getParameterInfo(param, &desc) != FMOD_OK) { errorMessage = "Could not get effect parameter info, probably invalid param index"; return GMS_error; } if (desc->type == FMOD_DSP_PARAMETER_TYPE_FLOAT) { if (effect->setParameterFloat(param, (float)value) == FMOD_OK) return FMODGMS_Util_ErrorChecker(); } else if (desc->type == FMOD_DSP_PARAMETER_TYPE_INT) { if (effect->setParameterInt(param, (int)round(value)) == FMOD_OK) return FMODGMS_Util_ErrorChecker(); } else if (desc->type == FMOD_DSP_PARAMETER_TYPE_BOOL) { if (effect->setParameterBool(param, (bool)(value > 0.5)) == FMOD_OK) return FMODGMS_Util_ErrorChecker(); } else { errorMessage = "Unsupported effect parameter type"; return GMS_error; } errorMessage = "Could not set effect parameter"; return GMS_error; }
int FMOD_Main() { FMOD::System *system; FMOD::Channel *channel = 0; FMOD::DSP *dsp; FMOD_RESULT result; unsigned int version; void *extradriverdata = 0; Common_Init(&extradriverdata); /* Create a System object and initialize. */ result = FMOD::System_Create(&system); ERRCHECK(result); result = system->getVersion(&version); ERRCHECK(result); if (version < FMOD_VERSION) { Common_Fatal("FMOD lib version %08x doesn't match header version %08x", version, FMOD_VERSION); } result = system->init(32, FMOD_INIT_NORMAL, extradriverdata); ERRCHECK(result); /* Create an oscillator DSP units for the tone. */ result = system->createDSPByType(FMOD_DSP_TYPE_OSCILLATOR, &dsp); ERRCHECK(result); result = dsp->setParameterFloat(FMOD_DSP_OSCILLATOR_RATE, 440.0f); /* Musical note 'A' */ ERRCHECK(result); /* Main loop */ do { Common_Update(); if (Common_BtnPress(BTN_ACTION1)) { if (channel) { result = channel->stop(); ERRCHECK(result); } result = system->playDSP(dsp, 0, true, &channel); ERRCHECK(result); result = channel->setVolume(0.5f); ERRCHECK(result); result = dsp->setParameterInt(FMOD_DSP_OSCILLATOR_TYPE, 0); ERRCHECK(result); result = channel->setPaused(false); ERRCHECK(result); } if (Common_BtnPress(BTN_ACTION2)) { if (channel) { result = channel->stop(); ERRCHECK(result); } result = system->playDSP(dsp, 0, true, &channel); ERRCHECK(result); result = channel->setVolume(0.125f); ERRCHECK(result); result = dsp->setParameterInt(FMOD_DSP_OSCILLATOR_TYPE, 1); ERRCHECK(result); result = channel->setPaused(false); ERRCHECK(result); } if (Common_BtnPress(BTN_ACTION3)) { if (channel) { result = channel->stop(); ERRCHECK(result); } result = system->playDSP(dsp, 0, true, &channel); ERRCHECK(result); result = channel->setVolume(0.125f); ERRCHECK(result); result = dsp->setParameterInt(FMOD_DSP_OSCILLATOR_TYPE, 2); ERRCHECK(result); result = channel->setPaused(false); ERRCHECK(result); } if (Common_BtnPress(BTN_ACTION4)) { if (channel) { result = channel->stop(); ERRCHECK(result); } result = system->playDSP(dsp, 0, true, &channel); ERRCHECK(result); result = channel->setVolume(0.5f); ERRCHECK(result); result = dsp->setParameterInt(FMOD_DSP_OSCILLATOR_TYPE, 4); ERRCHECK(result); result = channel->setPaused(false); ERRCHECK(result); } if (Common_BtnPress(BTN_MORE)) { if (channel) { result = channel->stop(); ERRCHECK(result); channel = 0; } } if (channel) { if (Common_BtnDown(BTN_UP) || Common_BtnDown(BTN_DOWN)) { float volume; result = channel->getVolume(&volume); ERRCHECK(result); volume += (Common_BtnDown(BTN_UP) ? +0.1f : -0.1f); volume = (volume > 1.0f) ? 1.0f : volume; volume = (volume < 0.0f) ? 0.0f : volume; result = channel->setVolume(volume); ERRCHECK(result); } if (Common_BtnDown(BTN_LEFT) || Common_BtnDown(BTN_RIGHT)) { float frequency; result = channel->getFrequency(&frequency); ERRCHECK(result); frequency += (Common_BtnDown(BTN_RIGHT) ? +500.0f : -500.0f); result = channel->setFrequency(frequency); ERRCHECK(result); } } result = system->update(); ERRCHECK(result); { float frequency = 0.0f, volume = 0.0f; bool playing = false; if (channel) { result = channel->getFrequency(&frequency); ERRCHECK(result); result = channel->getVolume(&volume); ERRCHECK(result); result = channel->isPlaying(&playing); ERRCHECK(result); } Common_Draw("=================================================="); Common_Draw("Generate Tone Example."); Common_Draw("Copyright (c) Firelight Technologies 2004-2015."); Common_Draw("=================================================="); Common_Draw(""); Common_Draw("Press %s to play a sine wave", Common_BtnStr(BTN_ACTION1)); Common_Draw("Press %s to play a square wave", Common_BtnStr(BTN_ACTION2)); Common_Draw("Press %s to play a saw wave", Common_BtnStr(BTN_ACTION3)); Common_Draw("Press %s to play a triangle wave", Common_BtnStr(BTN_ACTION4)); Common_Draw("Press %s to stop the channel", Common_BtnStr(BTN_MORE)); Common_Draw("Press %s and %s to change volume", Common_BtnStr(BTN_UP), Common_BtnStr(BTN_DOWN)); Common_Draw("Press %s and %s to change frequency", Common_BtnStr(BTN_LEFT), Common_BtnStr(BTN_RIGHT)); Common_Draw("Press %s to quit", Common_BtnStr(BTN_QUIT)); Common_Draw(""); Common_Draw("Channel is %s", playing ? "playing" : "stopped"); Common_Draw("Volume %0.2f", volume); Common_Draw("Frequency %0.2f", frequency); } Common_Sleep(50); } while (!Common_BtnPress(BTN_QUIT)); /* Shut down */ result = dsp->release(); ERRCHECK(result); result = system->close(); ERRCHECK(result); result = system->release(); ERRCHECK(result); Common_Close(); return 0; }
void InitFmod(){ cfmod(FMOD::System_Create(&fmodSystem)); u32 version = 0; cfmod(fmodSystem->getVersion(&version)); if(version < FMOD_VERSION){ std::cerr << "FMOD version of at least " << FMOD_VERSION << " required. Version used " << version << std::endl; throw "FMOD Error"; } cfmod(fmodSystem->init(100, FMOD_INIT_NORMAL, nullptr)); FMOD::DSP* dsp; FMOD::DSP* compressor; { FMOD_DSP_DESCRIPTION desc; memset(&desc, 0, sizeof(desc)); // strncpy(desc.name, "Fuckyou", sizeof(desc.name)); desc.numinputbuffers = 0; desc.numoutputbuffers = 1; desc.read = DSPCallback; desc.userdata = new DSPUserdata{/*sched, */0.0}; cfmod(fmodSystem->createDSP(&desc, &dsp)); cfmod(dsp->setChannelFormat(FMOD_CHANNELMASK_STEREO,2,FMOD_SPEAKERMODE_STEREO)); } cfmod(fmodSystem->createDSPByType(FMOD_DSP_TYPE_COMPRESSOR, &compressor)); cfmod(compressor->setParameterFloat(FMOD_DSP_COMPRESSOR_THRESHOLD, -13)); cfmod(compressor->setParameterFloat(FMOD_DSP_COMPRESSOR_ATTACK, 1)); cfmod(compressor->setBypass(false)); cfmod(dsp->setBypass(false)); FMOD::ChannelGroup* mastergroup; cfmod(fmodSystem->getMasterChannelGroup(&mastergroup)); cfmod(mastergroup->addDSP(0, compressor)); cfmod(fmodSystem->playDSP(dsp, mastergroup, false, &channel)); cfmod(channel->setMode(FMOD_2D)); cfmod(channel->setVolume(0.7f)); FMOD::Reverb3D* reverb; cfmod(fmodSystem->createReverb3D(&reverb)); // http://www.fmod.org/docs/content/generated/FMOD_REVERB_PROPERTIES.html FMOD_REVERB_PROPERTIES rprops = { .DecayTime = 8000.0, //1500.0, /* Reverberation decay time in ms */ .EarlyDelay = 7.0, //7.0, /* Initial reflection delay time */ .LateDelay = 11.0, //11.0, /* Late reverberation delay time relative to initial reflection */ .HFReference = 5000.0, /* Reference high frequency (hz) */ .HFDecayRatio = 50.0, /* High-frequency to mid-frequency decay time ratio */ .Diffusion = 60.0, /* Value that controls the echo density in the late reverberation decay. */ .Density = 100.0, //100.0, /* Value that controls the modal density in the late reverberation decay */ .LowShelfFrequency = 250.0, /* Reference low frequency (hz) */ .LowShelfGain = 0.0, /* Relative room effect level at low frequencies */ .HighCut = 10000.0, /* Relative room effect level at high frequencies */ .EarlyLateMix = 50.0, /* Early reflections level relative to room effect */ .WetLevel = -12.0, //-6.0, /* Room effect level (at mid frequencies) */ }; cfmod(reverb->setProperties(&rprops)); }
int FMOD_Main() { void *extradriverdata = 0; Common_Init(&extradriverdata); /* Create a System object and initialize */ FMOD_RESULT result; FMOD::System* system; result = FMOD::System_Create(&system); ERRCHECK(result); unsigned int version; result = system->getVersion(&version); ERRCHECK(result); if (version < FMOD_VERSION) { Common_Fatal("FMOD lib version %08x doesn't match header version %08x", version, FMOD_VERSION); } result = system->init(32, FMOD_INIT_NORMAL, extradriverdata); ERRCHECK(result); /* Create a new channel group to hold the convolution DSP unit */ FMOD::ChannelGroup* reverbGroup; result = system->createChannelGroup("reverb", &reverbGroup); ERRCHECK(result); /* Create a new channel group to hold all the channels and process the dry path */ FMOD::ChannelGroup* mainGroup; result = system->createChannelGroup("main", &mainGroup); ERRCHECK(result); /* Create the convultion DSP unit and set it as the tail of the channel group */ FMOD::DSP* reverbUnit; result = system->createDSPByType(FMOD_DSP_TYPE_CONVOLUTIONREVERB, &reverbUnit); ERRCHECK(result); result = reverbGroup->addDSP(FMOD_CHANNELCONTROL_DSP_TAIL, reverbUnit); ERRCHECK(result); /* Open the impulse response wav file, but use FMOD_OPENONLY as we want to read the data into a seperate buffer */ FMOD::Sound* irSound; result = system->createSound(Common_MediaPath("standrews.wav"), FMOD_DEFAULT | FMOD_OPENONLY, NULL, &irSound); ERRCHECK(result); /* Retrieve the sound information for the Impulse Response input file */ FMOD_SOUND_FORMAT irSoundFormat; FMOD_SOUND_TYPE irSoundType; int irSoundBits, irSoundChannels; result = irSound->getFormat(&irSoundType, &irSoundFormat, &irSoundChannels, &irSoundBits); ERRCHECK(result); unsigned int irSoundLength; result = irSound->getLength(&irSoundLength, FMOD_TIMEUNIT_PCM); ERRCHECK(result); if (irSoundFormat != FMOD_SOUND_FORMAT_PCM16) { /* For simplicity of the example, if the impulse response is the wrong format just display an error */ Common_Fatal("Impulse Response file is the wrong audio format"); } /* The reverb unit expects a block of data containing a single 16 bit int containing the number of channels in the impulse response, followed by PCM 16 data */ unsigned int irDataLength = sizeof(short) * (irSoundLength * irSoundChannels + 1); short* irData = (short*)malloc(irDataLength); irData[0] = irSoundChannels; unsigned int irDataRead; result = irSound->readData(&irData[1], irDataLength - sizeof(short), &irDataRead); ERRCHECK(result); result = reverbUnit->setParameterData(FMOD_DSP_CONVOLUTION_REVERB_PARAM_IR, irData, irDataLength); ERRCHECK(result); /* Don't pass any dry signal from the reverb unit, instead take the dry part of the mix from the main signal path */ result = reverbUnit->setParameterFloat(FMOD_DSP_CONVOLUTION_REVERB_PARAM_DRY, -80.0f); ERRCHECK(result); /* We can now free our copy of the IR data and release the sound object, the reverb unit has created it's internal data */ free(irData); result = irSound->release(); ERRCHECK(result); /* Load up and play a sample clip recorded in an anechoic chamber */ FMOD::Sound* sound; system->createSound(Common_MediaPath("singing.wav"), FMOD_3D | FMOD_LOOP_NORMAL, NULL, &sound); ERRCHECK(result); FMOD::Channel* channel; system->playSound(sound, mainGroup, true, &channel); ERRCHECK(result); /* Create a send connection between the channel head and the reverb unit */ FMOD::DSP* channelHead; channel->getDSP(FMOD_CHANNELCONTROL_DSP_HEAD, &channelHead); ERRCHECK(result); FMOD::DSPConnection* reverbConnection; result = reverbUnit->addInput(channelHead, &reverbConnection, FMOD_DSPCONNECTION_TYPE_SEND); ERRCHECK(result); result = channel->setPaused(false); ERRCHECK(result); float wetVolume = 1.0; float dryVolume = 1.0; /* Main loop */ do { Common_Update(); if (Common_BtnPress(BTN_LEFT)) { wetVolume = (wetVolume <= 0.0f) ? wetVolume : wetVolume - 0.05; } if (Common_BtnPress(BTN_RIGHT)) { wetVolume = (wetVolume >= 1.0f) ? wetVolume : wetVolume + 0.05f; } if (Common_BtnPress(BTN_DOWN)) { dryVolume = (dryVolume <= 0.0f) ? dryVolume : dryVolume - 0.05f; } if (Common_BtnPress(BTN_UP)) { dryVolume = (dryVolume >= 1.0f) ? dryVolume : dryVolume + 0.05f; } result = system->update(); ERRCHECK(result); result = reverbConnection->setMix(wetVolume); ERRCHECK(result); result = mainGroup->setVolume(dryVolume); ERRCHECK(result); Common_Draw("=================================================="); Common_Draw("Convolution Example."); Common_Draw("Copyright (c) Firelight Technologies 2004-2015."); Common_Draw("=================================================="); Common_Draw("Press %s and %s to change dry mix", Common_BtnStr(BTN_UP), Common_BtnStr(BTN_DOWN)); Common_Draw("Press %s and %s to change wet mix", Common_BtnStr(BTN_LEFT), Common_BtnStr(BTN_RIGHT)); Common_Draw("wet mix [%.2f] dry mix [%.2f]", wetVolume, dryVolume); Common_Draw("Press %s to quit", Common_BtnStr(BTN_QUIT)); Common_Draw(""); Common_Sleep(50); } while (!Common_BtnPress(BTN_QUIT)); /* Shut down */ result = sound->release(); ERRCHECK(result); result = mainGroup->release(); ERRCHECK(result); result = reverbGroup->removeDSP(reverbUnit); ERRCHECK(result); result = reverbUnit->disconnectAll(true, true); ERRCHECK(result); result = reverbUnit->release(); ERRCHECK(result); result = reverbGroup->release(); ERRCHECK(result); result = system->close(); ERRCHECK(result); result = system->release(); ERRCHECK(result); Common_Close(); return 0; }
// Taken mostly from ActiveSound.cpp void UFMODAudioComponent::UpdateInteriorVolumes() { // Result of the ambient calculations to apply to the instance float AmbientVolumeMultiplier = 1.0f; float AmbientHighFrequencyGain = 1.0f; FInteriorSettings Ambient; const FVector& Location = GetOwner()->GetTransform().GetTranslation(); AAudioVolume* AudioVolume = GetWorld()->GetAudioSettings(Location, NULL, &Ambient); const FFMODListener& Listener = IFMODStudioModule::Get().GetNearestListener(Location); if( InteriorLastUpdateTime < Listener.InteriorStartTime ) { SourceInteriorVolume = CurrentInteriorVolume; SourceInteriorLPF = CurrentInteriorLPF; InteriorLastUpdateTime = FApp::GetCurrentTime(); } bool bAllowSpatialization = true; if( Listener.Volume == AudioVolume || !bAllowSpatialization ) { // Ambient and listener in same ambient zone CurrentInteriorVolume = ( SourceInteriorVolume * ( 1.0f - Listener.InteriorVolumeInterp ) ) + Listener.InteriorVolumeInterp; AmbientVolumeMultiplier *= CurrentInteriorVolume; CurrentInteriorLPF = ( SourceInteriorLPF * ( 1.0f - Listener.InteriorLPFInterp ) ) + Listener.InteriorLPFInterp; AmbientHighFrequencyGain *= CurrentInteriorLPF; //UE_LOG(LogFMOD, Verbose, TEXT( "Ambient in same volume. Volume *= %g LPF *= %g" ), CurrentInteriorVolume, CurrentInteriorLPF); } else { // Ambient and listener in different ambient zone if( Ambient.bIsWorldSettings ) { // The ambient sound is 'outside' - use the listener's exterior volume CurrentInteriorVolume = ( SourceInteriorVolume * ( 1.0f - Listener.ExteriorVolumeInterp ) ) + ( Listener.InteriorSettings.ExteriorVolume * Listener.ExteriorVolumeInterp ); AmbientVolumeMultiplier *= CurrentInteriorVolume; CurrentInteriorLPF = ( SourceInteriorLPF * ( 1.0f - Listener.ExteriorLPFInterp ) ) + ( Listener.InteriorSettings.ExteriorLPF * Listener.ExteriorLPFInterp ); AmbientHighFrequencyGain *= CurrentInteriorLPF; //UE_LOG(LogFMOD, Verbose, TEXT( "Ambient in diff volume, ambient outside. Volume *= %g LPF *= %g" ), CurrentInteriorVolume, CurrentInteriorLPF); } else { // The ambient sound is 'inside' - use the ambient sound's interior volume multiplied with the listeners exterior volume CurrentInteriorVolume = (( SourceInteriorVolume * ( 1.0f - Listener.InteriorVolumeInterp ) ) + ( Ambient.InteriorVolume * Listener.InteriorVolumeInterp )) * (( SourceInteriorVolume * ( 1.0f - Listener.ExteriorVolumeInterp ) ) + ( Listener.InteriorSettings.ExteriorVolume * Listener.ExteriorVolumeInterp )); AmbientVolumeMultiplier *= CurrentInteriorVolume; CurrentInteriorLPF = (( SourceInteriorLPF * ( 1.0f - Listener.InteriorLPFInterp ) ) + ( Ambient.InteriorLPF * Listener.InteriorLPFInterp )) * (( SourceInteriorLPF * ( 1.0f - Listener.ExteriorLPFInterp ) ) + ( Listener.InteriorSettings.ExteriorLPF * Listener.ExteriorLPFInterp )); AmbientHighFrequencyGain *= CurrentInteriorLPF; //UE_LOG(LogFMOD, Verbose, TEXT( "Ambient in diff volume, ambient inside. Volume *= %g LPF *= %g" ), CurrentInteriorVolume, CurrentInteriorLPF); } } StudioInstance->setVolume(AmbientVolumeMultiplier); FMOD::ChannelGroup* ChanGroup = nullptr; StudioInstance->getChannelGroup(&ChanGroup); if (ChanGroup) { int NumDSP = 0; ChanGroup->getNumDSPs(&NumDSP); for (int Index=0; Index<NumDSP; ++Index) { FMOD::DSP* ChanDSP = nullptr; ChanGroup->getDSP(Index, &ChanDSP); if (ChanDSP) { FMOD_DSP_TYPE DSPType = FMOD_DSP_TYPE_UNKNOWN; ChanDSP->getType(&DSPType); if (DSPType == FMOD_DSP_TYPE_LOWPASS || DSPType == FMOD_DSP_TYPE_LOWPASS_SIMPLE) { static float MAX_FREQUENCY = 8000.0f; float Frequency = MAX_FREQUENCY * AmbientHighFrequencyGain; ChanDSP->setParameterFloat(FMOD_DSP_LOWPASS_CUTOFF, MAX_FREQUENCY * AmbientHighFrequencyGain); break; } } } } }