diff --git a/Config/DefaultEditor.ini b/Config/DefaultEditor.ini new file mode 100644 index 0000000..e69de29 diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini new file mode 100644 index 0000000..9e1e4d7 --- /dev/null +++ b/Config/DefaultEngine.ini @@ -0,0 +1,16 @@ + + +[/Script/HardwareTargeting.HardwareTargetingSettings] +TargetedHardwareClass=Desktop +AppliedTargetedHardwareClass=Desktop +DefaultGraphicsPerformance=Maximum +AppliedDefaultGraphicsPerformance=Maximum + +[/Script/EngineSettings.GameMapsSettings] +EditorStartupMap=/Game/StarterContent/Maps/Minimal_Default +GameDefaultMap=/Game/StarterContent/Maps/Minimal_Default + +[/Script/Engine.Engine] ++ActiveGameNameRedirects=(OldGameName="TP_BlankBP",NewGameName="/Script/JamTeacher") ++ActiveGameNameRedirects=(OldGameName="/Script/TP_BlankBP",NewGameName="/Script/JamTeacher") + diff --git a/Config/DefaultGame.ini b/Config/DefaultGame.ini new file mode 100644 index 0000000..13edda8 --- /dev/null +++ b/Config/DefaultGame.ini @@ -0,0 +1,73 @@ + + +[/Script/EngineSettings.GeneralProjectSettings] +ProjectID=2E83EBB84D5FB79959796494171847D7 + +[StartupActions] +bAddPacks=True +InsertPack=(PackSource="StarterContent.upack",PackName="StarterContent") + +[/Script/UnrealEd.ProjectPackagingSettings] +Build=IfProjectHasCode +BuildConfiguration=PPBC_Development +BuildTarget= +StagingDirectory=(Path="") +FullRebuild=False +ForDistribution=False +IncludeDebugFiles=False +BlueprintNativizationMethod=Disabled +bIncludeNativizedAssetsInProjectGeneration=False +bExcludeMonolithicEngineHeadersInNativizedCode=False +UsePakFile=True +bUseIoStore=False +bGenerateChunks=False +bGenerateNoChunks=False +bChunkHardReferencesOnly=False +bForceOneChunkPerFile=False +MaxChunkSize=0 +bBuildHttpChunkInstallData=False +HttpChunkInstallDataDirectory=(Path="") +PakFileCompressionFormats= +PakFileAdditionalCompressionOptions= +HttpChunkInstallDataVersion= +IncludePrerequisites=True +IncludeAppLocalPrerequisites=False +bShareMaterialShaderCode=True +bSharedMaterialNativeLibraries=True +ApplocalPrerequisitesDirectory=(Path="") +IncludeCrashReporter=False +InternationalizationPreset=English +-CulturesToStage=en ++CulturesToStage=en +LocalizationTargetCatchAllChunkId=0 +bCookAll=False +bCookMapsOnly=False +bCompressed=False +bSkipEditorContent=False +bSkipMovies=False +-IniKeyBlacklist=KeyStorePassword +-IniKeyBlacklist=KeyPassword +-IniKeyBlacklist=rsa.privateexp +-IniKeyBlacklist=rsa.modulus +-IniKeyBlacklist=rsa.publicexp +-IniKeyBlacklist=aes.key +-IniKeyBlacklist=SigningPublicExponent +-IniKeyBlacklist=SigningModulus +-IniKeyBlacklist=SigningPrivateExponent +-IniKeyBlacklist=EncryptionKey +-IniKeyBlacklist=IniKeyBlacklist +-IniKeyBlacklist=IniSectionBlacklist ++IniKeyBlacklist=KeyStorePassword ++IniKeyBlacklist=KeyPassword ++IniKeyBlacklist=rsa.privateexp ++IniKeyBlacklist=rsa.modulus ++IniKeyBlacklist=rsa.publicexp ++IniKeyBlacklist=aes.key ++IniKeyBlacklist=SigningPublicExponent ++IniKeyBlacklist=SigningModulus ++IniKeyBlacklist=SigningPrivateExponent ++IniKeyBlacklist=EncryptionKey ++IniKeyBlacklist=IniKeyBlacklist ++IniKeyBlacklist=IniSectionBlacklist ++DirectoriesToAlwaysStageAsNonUFS=(Path="FMOD") + diff --git a/JamTeacher.uproject b/JamTeacher.uproject new file mode 100644 index 0000000..589a456 --- /dev/null +++ b/JamTeacher.uproject @@ -0,0 +1,22 @@ +{ + "FileVersion": 3, + "EngineAssociation": "4.25", + "Category": "", + "Description": "", + "Modules": [ + { + "Name": "JamTeacher", + "Type": "Runtime", + "LoadingPhase": "Default", + "AdditionalDependencies": [ + "Engine" + ] + } + ], + "Plugins": [ + { + "Name": "FMODStudio", + "Enabled": true + } + ] +} \ No newline at end of file diff --git a/Plugins/FMODStudio/Content/AnimNotify_FMODPlayEvent.uasset b/Plugins/FMODStudio/Content/AnimNotify_FMODPlayEvent.uasset new file mode 100644 index 0000000..4aa99a4 Binary files /dev/null and b/Plugins/FMODStudio/Content/AnimNotify_FMODPlayEvent.uasset differ diff --git a/Plugins/FMODStudio/Docs/api-reference-afmodambientsound.html b/Plugins/FMODStudio/Docs/api-reference-afmodambientsound.html new file mode 100644 index 0000000..06ddf94 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-afmodambientsound.html @@ -0,0 +1,50 @@ + + +API Reference | AFMODAmbientSound + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | AFMODAmbientSound

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from AActor

+

Properties:

+ +

AFMODAmbientSound::AudioComponent

+

FMODAudioComponent used to play the ambient Event.

+

+

+
C++
+
+

+
UFMODAudioComponent *AudioComponent;
+
+ + +

See Also: UFMODAudioComponent

+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ffmodassettable.html b/Plugins/FMODStudio/Docs/api-reference-ffmodassettable.html new file mode 100644 index 0000000..729183d --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ffmodassettable.html @@ -0,0 +1,55 @@ + + +API Reference | FFmodAssetTable + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | FFmodAssetTable

+
+

This documentation is preliminary and is subject to change.

+
+

Properties:

+ +

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ffmodbankupdatenotifier.html b/Plugins/FMODStudio/Docs/api-reference-ffmodbankupdatenotifier.html new file mode 100644 index 0000000..c776360 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ffmodbankupdatenotifier.html @@ -0,0 +1,56 @@ + + +API Reference | FFMODBankUpdateNotifier + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | FFMODBankUpdateNotifier

+
+

This documentation is preliminary and is subject to change.

+
+

Properties:

+

Public:

+ +

Private:

+ +

Methods:

+

Public:

+ +

Private:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ffmodeventcontrolsectiontemplate.html b/Plugins/FMODStudio/Docs/api-reference-ffmodeventcontrolsectiontemplate.html new file mode 100644 index 0000000..5d722e7 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ffmodeventcontrolsectiontemplate.html @@ -0,0 +1,45 @@ + + +API Reference | FFMODEventControlSectionTemplate + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | FFMODEventControlSectionTemplate

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from FMovieSceneEvalTemplate.

+

Properties:

+

Public:

+ +

Methods:

+

Private:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ffmodeventparametersectiontemplate.html b/Plugins/FMODStudio/Docs/api-reference-ffmodeventparametersectiontemplate.html new file mode 100644 index 0000000..71e7a79 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ffmodeventparametersectiontemplate.html @@ -0,0 +1,40 @@ + + +API Reference | FFMODEventParameterSectionTemplate + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | FFMODEventParameterSectionTemplate

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from FMovieSceneParameterSectionTemplate.

+

Methods:

+

Private:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ffmodfilecallbacks.html b/Plugins/FMODStudio/Docs/api-reference-ffmodfilecallbacks.html new file mode 100644 index 0000000..7550a1c --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ffmodfilecallbacks.html @@ -0,0 +1,43 @@ + + +API Reference | FFMODFileCallbacks + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | FFMODFileCallbacks

+
+

This documentation is preliminary and is subject to change.

+
+

Defines:

+ +

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ffmodlistener.html b/Plugins/FMODStudio/Docs/api-reference-ffmodlistener.html new file mode 100644 index 0000000..76dfb91 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ffmodlistener.html @@ -0,0 +1,62 @@ + + +API Reference | FFMODListener + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | FFMODListener

+
+

This documentation is preliminary and is subject to change.

+
+

Defines:

+ +

Properties:

+ +

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ffmodstudiomodule.html b/Plugins/FMODStudio/Docs/api-reference-ffmodstudiomodule.html new file mode 100644 index 0000000..15468f3 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ffmodstudiomodule.html @@ -0,0 +1,130 @@ + + +API Reference | FFMODStudioModule + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | FFMODStudioModule

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from IFMODStudioModule.

+

Defines:

+ +

Properties:

+ +

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-fmodplatformloaddll_generic.html b/Plugins/FMODStudio/Docs/api-reference-fmodplatformloaddll_generic.html new file mode 100644 index 0000000..3df5aa7 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-fmodplatformloaddll_generic.html @@ -0,0 +1,38 @@ + + +API Reference | FMODPlatformLoadDll_Generic + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | FMODPlatformLoadDll_Generic

+
+

This documentation is preliminary and is subject to change.

+
+

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-fmodutils.html b/Plugins/FMODStudio/Docs/api-reference-fmodutils.html new file mode 100644 index 0000000..fdbea7a --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-fmodutils.html @@ -0,0 +1,52 @@ + + +API Reference | FMODUtils + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | FMODUtils

+
+

This documentation is preliminary and is subject to change.

+
+

Defines:

+ +

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ifmodstudiomodule.html b/Plugins/FMODStudio/Docs/api-reference-ifmodstudiomodule.html new file mode 100644 index 0000000..58181c8 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ifmodstudiomodule.html @@ -0,0 +1,65 @@ + + +API Reference | IFMODStudioModule + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | IFMODStudioModule

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from IModuleInterface.

+

Defines:

+ +

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodanimnotifyplay.html b/Plugins/FMODStudio/Docs/api-reference-ufmodanimnotifyplay.html new file mode 100644 index 0000000..9fa08e9 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodanimnotifyplay.html @@ -0,0 +1,98 @@ + + +API Reference | UFMODAnimNotifyPlay + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODAnimNotifyPlay

+
+

This documentation is preliminary and is subject to change.

+
+

Used for triggering Events in Animation timelines.

+

This class inherits from UAnimNotify

+

Properties:

+ +

Methods:

+ +

UFMODAnimNotifyPlay::AttachName

+

Socket or bone name to attach sound to.

+

+

+
C++
+
+

+
FString AttachName;
+
+ + +

UFMODAnimNotifyPlay::bFollow

+

Should this sound follow its owner.

+

+

+
C++
+
+

+
unit32 bFollow : 1;
+
+ + +

UFMODAnimNotifyPlay::Event

+

FMODEvent reference to play.

+

+

+
C++
+
+

+
TAssetPtr<class UFMODEvent> Event;
+
+ + +

See Also: UFMODEvent

+

UFMODAnimNotifyPlay::Notify

+

Event triggered when the timeline crosses the notify marker.

+

+

+
C++
+
+

+
virtual void Notify(USkeletalMeshComponent *MeshComp, UAnimSequenceBase *AnimSeq) override
+
+ + +
+
MeshComp
+
USceneComponent used for the position of the Event.
+
AnimSeq
+
Reference to the current animation.
+
+

If UFMODAnimNotifyPlay::bFollow is true UFMODBlueprintStatics::PlayEventAttached is called using the current UFMODAnimNotifyPlay::AttachName.
+Otherwise UFMODBlueprintStatics::PlayEventAtLocation is called using the MeshComp for the positional information.

+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodasset.html b/Plugins/FMODStudio/Docs/api-reference-ufmodasset.html new file mode 100644 index 0000000..b373fad --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodasset.html @@ -0,0 +1,106 @@ + + +API Reference | UFMODAsset + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODAsset

+
+

This documentation is preliminary and is subject to change.

+
+

Base asset used for creating FMOD object assets in UE4.

+

This class inherits from UObject

+

Properties:

+ +

Methods:

+ +

UFMODAsset::AssetGuid

+

The unique Guid, which matches the one exported from FMOD Studio.

+

+

+
C++
+
+

+
FGuid AssetGuid;
+
+ + +

UFMODAsset::bShowAsAsset

+

Whether to show in the content window.

+

+

+
C++
+
+

+
bool bShowAsAsset;
+
+ + +

UFMODAsset::FileName

+

In memory asset name, created at load time.

+

+

+
C++
+
+

+
FString FileName;
+
+ + +

UFMODAsset::GetAssetRegistryTags

+

Get tags to show in content view.

+

+

+
C++
+
+

+
virtual void GetAssetRegistryTags(TArray<FAssetRegistryTag> &OutTags) const override
+
+ + +
+
OutTags
+
+
+

UFMODAsset::IsAsset

+

Event triggered when the timeline crosses the notify marker.

+

+

+
C++
+
+

+
virtual bool IsAsset() const override
+
+ + +

Returns UFMODAsset::bShowAsAsset.

+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodaudiocomponent.html b/Plugins/FMODStudio/Docs/api-reference-ufmodaudiocomponent.html new file mode 100644 index 0000000..9268955 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodaudiocomponent.html @@ -0,0 +1,1126 @@ + + +API Reference | UFMODAudioComponent + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODAudioComponent

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from USceneComponent

+

Defines:

+ +

Properties:

+

Public:

+ +

Private:

+ +

Methods:

+

Public:

+ +

Private:

+ +

UFMODAudioComponent::Activate

+

Activates the component.

+

+

+
C++
+
+

+
virtual void Activate(
+  bool bReset = false
+);
+
+ + +
+
bReset
+
Whether the activation should happen even if ShouldActivate returns false.
+
+

UFMODAudioComponent::AmbientLPF

+

Calculated Ambient LPF level for that frame.

+

+

+
C++
+
+

+
float AmbientLPF;
+
+ + +

Used for automating volume and/or LPF with Ambient Zones.

+

See Also: Ambient Zones

+

UFMODAudioComponent::AmbientLPFID

+

Stored ID of the LPF parameter of the Event (if applicable).

+

+

+
C++
+
+

+
FMOD_STUDIO_PARAMETER_ID AmbientLPFID;
+
+ + +

See Also: Ambient Zones, FMOD_STUDIO_PARAMETER_ID

+

UFMODAudioComponent::AmbientVolume

+

Calculated Ambient volume level for that frame.

+

+

+
C++
+
+

+
float AmbientVolume;
+
+ + +

Used for automating volume and/or LPF with Ambient Zones.

+

See Also: Ambient Zones

+

UFMODAudioComponent::AmbientVolumeID

+

Stored ID of the Volume parameter of the Event (if applicable).

+

+

+
C++
+
+

+
FMOD_STUDIO_PARAMETER_ID AmbientVolumeID;
+
+ + +

See Also: Ambient Zones, FMOD_STUDIO_PARAMETER_ID

+

UFMODAudioComponent::ApplyVolumeLPF

+

Apply Volume and LPF to Event.

+

+

+
C++
+
+

+
void ApplyVolumeLPF();
+
+ + +

UFMODAudioComponent::AttenuationDetails

+

FMOD Custom Attenuation Details.

+

+

+
C++
+
+

+
struct FFMODAttenuationDetails AttenuationDetails;
+
+ + +

See Also: FFMODAttenuationDetails

+

UFMODAudioComponent::bApplyAmbientVolumes

+

Whether we apply gain and low-pass based on audio zones.

+

+

+
C++
+
+

+
uint32 bApplyAmbientVolumes : 1;
+
+ + +

UFMODAudioComponent::bApplyOcclusionParameter

+

Whether we apply gain and low-pass based on occlusion onto a parameter.

+

+

+
C++
+
+

+
uint32 bApplyOcclusionParameter : 1;
+
+ + +

UFMODAudioComponent::bAutoDestroy

+

Auto destroy this component on completion.

+

+

+
C++
+
+

+
uint32 bAutoDestroy : 1;
+
+ + +

UFMODAudioComponent::bDefaultParameterValuesCached

+

Have the Event parameters default values been cached.

+

+

+
C++
+
+

+
bool bDefaultParameterValuesCached;
+
+ + +

UFMODAudioComponent::bEnableTimelineCallbacks

+

Enable timeline callbacks for this sound, so that OnTimelineMarker and OnTimelineBeat can be used.

+

+

+
C++
+
+

+
uint32 bEnableTimelineCallbacks : 1;
+
+ + +

See Also: UFMODAudioComponent::OnTimelineMarker, UFMODAudioComponent::OnTimelineBeat

+

UFMODAudioComponent::bStopWhenOwnerDestroyed

+

Stop sound when owner is destroyed.

+

+

+
C++
+
+

+
uint32 bStopWhenOwnerDestroyed : 1;
+
+ + +

UFMODAudioComponent::CacheDefaultParameterValues

+

Cache default event parameter values

+

+

+
C++
+
+

+
void CacheDefaultParameterValues()
+
+ + +

UFMODAudioComponent::CallbackBeatQueue

+

Stores the Timeline Beats as they are triggered.

+

+

+
C++
+
+

+
TArray<FTimelineBeatProperties> CallbackBeatQueue;
+
+ + +

See Also: UFMODAudioComponent::EventCallbackAddBeat

+

UFMODAudioComponent::CallbackLock

+

A scope lock used specifically for callbacks.

+

+

+
C++
+
+

+
FCriticalSection CallbackLock;
+
+ + +

UFMODAudioComponent::CallbackMarkerQueue

+

Stores the Timeline Markers as they are triggered.

+

+

+
C++
+
+

+
TArray<FTimelineMarkerProperties> CallbackMarkerQueue;
+
+ + +

See Also: UFMODAudioComponent::EventCallbackAddMarker

+

UFMODAudioComponent::CurrentInteriorLPF

+

Previous interior LPF value.

+

+

+
C++
+
+

+
float CurrentInteriorLPF;
+
+ + +

Used for automating volume and/or LPF with Ambient Zones.

+

See Also: Ambient Zones

+

UFMODAudioComponent::CurrentInteriorVolume

+

Current interior volume value.

+

+

+
C++
+
+

+
float CurrentInteriorVolume;
+
+ + +

Used for automating volume and/or LPF with Ambient Zones.

+

See Also: Ambient Zones

+

UFMODAudioComponent::Deactivate

+

Deactivates the SceneComponent.

+

+

+
C++
+
+

+
virtual void Deactivate();
+
+ + +

UFMODAudioComponent::EndPlay

+

Overridable function called whenever this actor is being removed from a level.

+

+

+
C++
+
+

+
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
+
+ + +
+
EndPlayReason
+
Why an actor is being deleted/removed from a level.
+
+

UFMODAudioComponent::Event

+

The event asset to use for this sound.

+

+

+
C++
+
+

+
TAssetPtr<class UFMODEvent> Event;
+
+ + +

See Also: UFMODEvent

+

UFMODAudioComponent_EventCallback

+

Generic callback used for the Studio Instance.

+

+

+
C++
+
+

+
FMOD_RESULT F_CALLBACK UFMODAudioComponent_EventCallback(
+  FMOD_STUDIO_EVENT_CALLBACK_TYPE type,
+  FMOD_STUDIO_EVENTINSTANCE *event, void *parameters
+);
+
+ + +
+
type
+
The type of callback being triggered.
+
event
+
Reference to the Studio Instance.
+
parameters
+
Info about the callback.
+
+

This is on set on the UFMODAudioComponent::StudioInstance if UFMODAudioComponent::bEnableTimelineCallbacks is true or UFMODAudioComponent::ProgrammerSoundName is not empty.

+

See Also: FMOD_STUDIO_EVENT_CALLBACK_TYPE, UFMODAudioComponent::EventCallbackAddMarker, UFMODAudioComponent::EventCallbackAddBeat, UFMODAudioComponent::EventCallbackCreateProgrammerSound, UFMODAudioComponent::EventCallbackDestroyProgrammerSound

+

UFMODAudioComponent::EventCallbackAddBeat

+

Timeline Beat callback.

+

+

+
C++
+
+

+
void EventCallbackAddBeat(
+  struct FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES *props
+);
+
+ + +
+
props
+
Callback properties.
+
+

See Also: UFMODAudioComponent_EventCallback, FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES

+

UFMODAudioComponent::EventCallbackAddMarker

+

Timeline Marker callback.

+

+

+
C++
+
+

+
void EventCallbackAddMarker(
+  struct FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES *props
+);
+
+ + +
+
props
+
Callback properties.
+
+

See Also: UFMODAudioComponent_EventCallback, FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES

+

UFMODAudioComponent::EventCallbackCreateProgrammerSound

+

Programmer Sound Create callback.

+

+

+
C++
+
+

+
void EventCallbackCreateProgrammerSound(
+  struct FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES *props
+);
+
+ + +
+
props
+
Callback properties.
+
+

See Also: UFMODAudioComponent_EventCallback, FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES

+

UFMODAudioComponent::EventCallbackDestroyProgrammerSound

+

Programmer Sound Destroy callback.

+

+

+
C++
+
+

+
void EventCallbackDestroyProgrammerSound(
+  struct FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES *props
+);
+
+ + +
+
props
+
Callback properties.
+
+

See Also: UFMODAudioComponent_EventCallback, FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES

+

UFMODAudioComponent::EventLength

+

The length of the current Event in milliseconds.

+

+

+
C++
+
+

+
int32 EventLength;
+
+ + +

UFMODAudioComponent::GetLength

+

Get the event length in milliseconds.

+

+

+
C++
+
+

+
int32 GetLength() const;
+
+ + +

UFMODAudioComponent::GetParameter

+

Get parameter value from the Event.

+

+

+
C++
+
+

+
float GetParameter(
+  FName Name
+);
+
+ + +
+
Name
+
Name of the parameter.
+
+

UFMODAudioComponent::GetProperty

+

Get a property of the Event.

+

+

+
C++
+
+

+
float GetProperty(
+  EFMODEventProperty::Type Property
+);
+
+ + +
+
Property
+
Enum to describe built-in event properties.
+
+

See Also: EFMODEventProperty

+

UFMODAudioComponent::GetStudioModule

+

Return a cached reference to the current IFMODStudioModule.

+

+

+
C++
+
+

+
IFMODStudioModule& GetStudioModule();
+
+ + +

See Also: IFMODStudioModule

+

UFMODAudioComponent::GetTimelinePosition

+

Get the timeline position in milliseconds.

+

+

+
C++
+
+

+
int32 GetTimelinePosition();
+
+ + +

UFMODAudioComponent::InteriorLastUpdateTime

+

Timer used for volumes fading in and out.

+

+

+
C++
+
+

+
double InteriorLastUpdateTime;
+
+ + +

UFMODAudioComponent::IsPlaying

+

Return true if this component is currently playing an event.

+

+

+
C++
+
+

+
bool IsPlaying();
+
+ + +

UFMODAudioComponent::LastLPF

+

Previously set LPF value.

+

+

+
C++
+
+

+
float LastLPF;
+
+ + +

Used for automating volume and/or LPF with Ambient Zones.

+

See Also: Ambient Zones

+

UFMODAudioComponent::LastVolume

+

Previously set Volume value.

+

+

+
C++
+
+

+
float LastVolume;
+
+ + +

Used for automating volume and/or LPF with Ambient Zones.

+

See Also: Ambient Zones

+

UFMODAudioComponent::Module

+

Stored reference to the current IFMODStudioModule.

+

+

+
C++
+
+

+
IFMODStudioModule* Module;
+
+ + +

See Also: IFMODStudioModule

+

UFMODAudioComponent::OcclusionDetails

+

FMOD Custom Occlusion Details.

+

+

+
C++
+
+

+
struct FFMODOcclusionDetails OcclusionDetails;
+
+ + +

See Also: FFMODOcclusionDetails

+

UFMODAudioComponent::OcclusionID

+

Stored ID of the Occlusion parameter of the Event (if applicable).

+

+

+
C++
+
+

+
FMOD_STUDIO_PARAMETER_ID OcclusionID;
+
+ + +

See Also: Occlusion, FMOD_STUDIO_PARAMETER_ID

+

UFMODAudioComponent::OnEventStopped

+

Called when an event stops, either because it played to completion or because a Stop() call turned it off early.

+

+

+
C++
+
+

+
FOnEventStopped OnEventStopped;
+
+ + +

UFMODAudioComponent::OnPlaybackCompleted

+

Called when the event has finished stopping.

+

+

+
C++
+
+

+
void OnPlaybackCompleted();
+
+ + +

UFMODAudioComponent::OnRegister

+

Called when a component is registered, after Scene is set, but before CreateRenderState_Concurrent or OnCreatePhysicsState are called.

+

+

+
C++
+
+

+
virtual void OnRegister();
+
+ + +

UFMODAudioComponent::OnTimelineBeat

+

Called when we reach a beat of a tempo (if bEnableTimelineCallbacks is true).

+

+

+
C++
+
+

+
FOnTimelineMarker OnTimelineBeat;
+
+ + +

See Also: UFMODAudioComponent::bEnableTimelineCallbacks

+

UFMODAudioComponent::OnTimelineMarker

+

Called when we reach a named marker (if bEnableTimelineCallbacks is true).

+

+

+
C++
+
+

+
FOnTimelineMarker OnTimelineMarker;
+
+ + +

See Also: UFMODAudioComponent::bEnableTimelineCallbacks

+

UFMODAudioComponent::OnUnregister

+

Called when a component is unregistered. Called after DestroyRenderState_Concurrent and OnDestroyPhysicsState are called.

+

+

+
C++
+
+

+
virtual void OnUnregister();
+
+ + +

UFMODAudioComponent::OnUpdateTransform

+

Native callback when this component is moved.

+

+

+
C++
+
+

+
virtual void OnUpdateTransform(
+  EUpdateTransformFlags UpdateTransformFlags,
+  ETeleportType Teleport = ETeleportType::None
+);
+
+ + +

Used to update the 3D positional information of the Event.

+

UFMODAudioComponent::ParameterCache

+

Cache of the current Events parameters.

+

+

+
C++
+
+

+
TMap<FName, float> ParameterCache;
+
+ + +

UFMODAudioComponent::Play

+

Start a sound playing on an audio component.

+

+

+
C++
+
+

+
void Play();
+
+ + +

UFMODAudioComponent::PlayInternal

+

Internal play function which can play Events in the editor.

+

+

+
C++
+
+

+
void PlayInternal(
+  EFMODSystemContext::Type Context
+);
+
+ + +
+
Context
+
Which FMOD Studio system to use.
+
+

See Also: EFMODSystemContext

+

UFMODAudioComponent::ProgrammerSound

+

Direct assignment of programmer sound from other C++ code.

+

+

+
C++
+
+

+
FMOD::Sound *ProgrammerSound;
+
+ + +

See Also: FMOD::Sound

+

UFMODAudioComponent::ProgrammerSoundName

+

Sound name used for programmer sound.

+

+

+
C++
+
+

+
FString ProgrammerSoundName;
+
+ + +

The integration will look up the name in any loaded audio table.

+

UFMODAudioComponent::Release

+

Release the current Studio Instance.

+

+

+
C++
+
+

+
void Release();
+
+ + +

See Also: UFMODAudioComponent::StudioInstance

+

UFMODAudioComponent::ReleaseEventCache

+

Release any cached parameters then the Studio Instance.

+

+

+
C++
+
+

+
void ReleaseEventCache();
+
+ + +

See Also: UFMODAudioComponent::StudioInstance

+

UFMODAudioComponent::ReleaseEventInstance

+

Release the Studio Instance.

+

+

+
C++
+
+

+
void ReleaseEventInstance();
+
+ + +

See Also: UFMODAudioComponent::StudioInstance

+

UFMODAudioComponent::SetEvent

+

New Event to be used by the FMODAudioComponent.

+

+

+
C++
+
+

+
void SetEvent(
+  UFMODEvent *NewEvent
+);
+
+ + +
+
NewEvent
+
New Event Asset reference to use.
+
+

If an Event is currently playing, it will be stopped and the new Event passed in will be started.

+

See Also: UFMODEvent

+

UFMODAudioComponent::SetParameter

+

Set a parameter of the Event.

+

+

+
C++
+
+

+
void SetParameter(
+  FName Name,
+  float Value
+);
+
+ + +
+
Name
+
Name of the parameter.
+
Value
+
Value to apply to the parameter.
+
+

UFMODAudioComponent::SetPaused

+

Pause/Unpause an audio component.

+

+

+
C++
+
+

+
void SetPaused(
+  bool paused
+);
+
+ + +
+
paused
+
The paused state to apply.
+
+

UFMODAudioComponent::SetPitch

+

Set pitch on an audio component.

+

+

+
C++
+
+

+
void SetPitch(
+  float pitch
+);
+
+ + +
+
pitch
+
New pitch multiplier to apply.
+
+

The pitch multiplier is used to modulate the event instance's pitch. It can be set to any value greater than or equal to zero but the final combined pitch is clamped to the range [0, 100] before being applied.

+

UFMODAudioComponent::SetProgrammerSound

+

Set a programmer sound to use for this audio component. Lifetime of sound must exceed that of the audio component.

+

+

+
C++
+
+

+
void SetProgrammerSound(
+  FMOD::Sound *Sound
+);
+
+ + +
+
Sound
+
User created sound to use.
+
+

See Als: FMOD::Sound

+

UFMODAudioComponent::SetProgrammerSoundName

+

Set the sound name to use for programmer sound.

+

+

+
C++
+
+

+
void SetProgrammerSoundName(
+  FString Value
+);
+
+ + +
+
Value
+
Name of sound or file to use.
+
+

The integration will look up the name in any loaded audio table.

+

UFMODAudioComponent::SetProperty

+

Set a property of the Event.

+

+

+
C++
+
+

+
void SetProperty(
+  EFMODEventProperty::Type Property,
+  float Value
+);
+
+ + +
+
Property
+
Enum to describe built-in event properties.
+
Value
+
Value to apply to the property.
+
+

See Also: EFMODEventProperty

+

UFMODAudioComponent::SetTimelinePosition

+

Set the timeline position in milliseconds

+

+

+
C++
+
+

+
void SetTimelinePosition(
+  int32 Time
+);
+
+ + +
+
Time
+
Time in milliseconds.
+
+

UFMODAudioComponent::SetVolume

+

Set volume on an audio component.

+

+

+
C++
+
+

+
void SetVolume(
+  float volume
+);
+
+ + +
+
volume
+
New volume level to apply.
+
+

This volume is applied as a scaling factor for the event volume. It does not override the volume level set in FMOD Studio, nor any internal volume automation or modulation.

+

UFMODAudioComponent::SourceInteriorLPF

+

Previous interior LPF value.

+

+

+
C++
+
+

+
float SourceInteriorLPF;
+
+ + +

Used for automating volume and/or LPF with Ambient Zones.

+

See Also: Ambient Zones

+

UFMODAudioComponent::SourceInteriorVolume

+

Previous interior volume value.

+

+

+
C++
+
+

+
float SourceInteriorVolume;
+
+ + +

Used for automating volume and/or LPF with Ambient Zones.

+

See Also: Ambient Zones

+

UFMODAudioComponent::Stop

+

Stop an audio component playing.

+

+

+
C++
+
+

+
void Stop();
+
+ + +

UFMODAudioComponent::StoredProperties

+

Stored properties to apply next time we create an instance.

+

+

+
C++
+
+

+
float StoredProperties[EFMODEventProperty::Count];
+
+ + +

See Also: EFMODEventProperty

+

UFMODAudioComponent::StudioInstance

+

Actual Studio instance handle.

+

+

+
C++
+
+

+
FMOD::Studio::EventInstance *StudioInstance;
+
+ + +

UFMODAudioComponent::TickComponent

+

Function called every frame on this ActorComponent.

+

+

+
C++
+
+

+
virtual void TickComponent(
+  float DeltaTime,
+  enum ELevelTick TickType,
+  FActorComponentTickFunction *ThisTickFunction
+);
+
+ + +

Only executes if the component is registered, and also PrimaryComponentTick.bCanEverTick must be set to true.

+

UFMODAudioComponent::TriggerCue

+

Trigger a cue in an event.

+

+

+
C++
+
+

+
void TriggerCue();
+
+ + +

UFMODAudioComponent::UpdateAttenuation

+

Update attenuation if we have it set.

+

+

+
C++
+
+

+
void UpdateAttenuation();
+
+ + +

UFMODAudioComponent::UpdateInteriorVolumes

+

Update gain and low-pass based on interior volumes.

+

+

+
C++
+
+

+
void UpdateInteriorVolumes();
+
+ + +

UFMODAudioComponent::wasOccluded

+

Was the object occluded in the previous frame.

+

+

+
C++
+
+

+
bool wasOccluded;
+
+ + +

See Also: Occlusion

+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodbank.html b/Plugins/FMODStudio/Docs/api-reference-ufmodbank.html new file mode 100644 index 0000000..405a672 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodbank.html @@ -0,0 +1,39 @@ + + +API Reference | UFMODBank + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODBank

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from UFMODAsset

+

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodblueprintstatics.html b/Plugins/FMODStudio/Docs/api-reference-ufmodblueprintstatics.html new file mode 100644 index 0000000..80dda58 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodblueprintstatics.html @@ -0,0 +1,844 @@ + + +API Reference | UFMODBlueprintStatics + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODBlueprintStatics

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from UBlueprintFunctionLibrary

+

Defines:

+ +

Methods:

+ +

UFMODBlueprintStatics::BusSetMute

+

Mute/Unmute the bus.

+

+

+
C++
+
+

+
static void BusSetMute(
+  class UFMODBus *Bus,
+  bool bMute
+);
+
+ + +
+
Bus
+
UFMODBus to use.
+
bMute
+
Mute value.
+
+

UFMODBlueprintStatics::BusSetPaused

+

Pause/Unpause all events going through the bus.

+

+

+
C++
+
+

+
static void BusSetPaused(
+  class UFMODBus *Bus,
+  bool bPaused
+);
+
+ + +
+
Bus
+
UFMODBus to use.
+
bPaused
+
Pause value.
+
+

UFMODBlueprintStatics::BusSetVolume

+

Set volume on a bus.

+

+

+
C++
+
+

+
static void BusSetVolume(
+  class UFMODBus *Bus,
+  float Volume
+);
+
+ + +
+
Bus
+
UFMODBus to use.
+
Volume
+
+

Volume value.

+
    +
  • Units: Linear
  • +
  • Range: [0, 1]
  • +
+
+
+

UFMODBlueprintStatics::BusStopAllEvents

+

Stop all EventInstances routed into the bus.

+

+

+
C++
+
+

+
static void BusStopAllEvents(
+  class UFMODBus *Bus,
+  EFMOD_STUDIO_STOP_MODE stopMode
+);
+
+ + +
+
Bus
+
UFMODBus to use.
+
stopMode
+
Desired stop mode.
+
+

See Also: FMOD_STUDIO_STOP_MODE

+

EFMOD_STUDIO_STOP_MODE

+

Studio stop mode enum for use in blueprints.

+

+

+
C++
+
+

+
enum EFMOD_STUDIO_STOP_MODE{
+  ALLOWFADEOUT,
+  IMMEDIATE
+} EFMOD_STUDIO_STOP_MODE;
+
+ + +
+
ALLOWFADEOUT
+
Allow AHDSR modulators to complete their release, and DSP effect tails to play out.
+
IMMEDIATE
+
Stop the event instance immediately.
+
+

See Also: FMOD_STUDIO_STOP_MODE

+

UFMODBlueprintStatics::EventInstanceGetParameter

+

Get a parameter on an FMOD Event Instance.

+

+

+
C++
+
+

+
static float EventInstanceGetParameter(
+  FFMODEventInstance EventInstance,
+  FName Name
+);
+
+ + +
+
EventInstance
+
FFMODEventInstance to use.
+
Name
+
Name of parameter.
+
+

UFMODBlueprintStatics::EventInstanceIsValid

+

Return whether this FMOD Event Instance is valid.

+

+

+
C++
+
+

+
static bool EventInstanceIsValid(
+  FFMODEventInstance EventInstance
+);
+
+ + +
+
EventInstance
+
FFMODEventInstance to use.
+
+

The instance will be invalidated when the sound stops.

+

UFMODBlueprintStatics::EventInstancePlay

+

Play an FMOD Event Instance.

+

+

+
C++
+
+

+
static void EventInstancePlay(
+  FFMODEventInstance EventInstance
+);
+
+ + +
+
EventInstance
+
FFMODEventInstance to use.
+
+

UFMODBlueprintStatics::EventInstanceSetParameter

+

Set a parameter on an FMOD Event Instance.

+

+

+
C++
+
+

+
static void EventInstanceSetParameter(
+  FFMODEventInstance EventInstance,
+  FName Name,
+  float Value
+);
+
+ + +
+
EventInstance
+
FFMODEventInstance to use.
+
Name
+
Name of the parameter.
+
Value
+
Value to set the parameter to.
+
+

UFMODBlueprintStatics::EventInstanceSetPaused

+

Pause/Unpause an FMOD Event Instance.

+

+

+
C++
+
+

+
static void EventInstanceSetPaused(
+  FFMODEventInstance EventInstance,
+  bool Paused
+);
+
+ + +
+
EventInstance
+
FFMODEventInstance to use.
+
Paused
+
Paused value.
+
+

UFMODBlueprintStatics::EventInstanceSetPitch

+

Set pitch on an FMOD Event Instance.

+

+

+
C++
+
+

+
static void EventInstanceSetPitch(
+  FFMODEventInstance EventInstance,
+  float Pitch
+);
+
+ + +
+
EventInstance
+
FFMODEventInstance to use.
+
Pitch
+
Pitch value.
+
+

UFMODBlueprintStatics::EventInstanceSetProperty

+

Set an FMOD event property on an FMOD Event Instance.

+

+

+
C++
+
+

+
static void EventInstanceSetProperty(
+  FFMODEventInstance EventInstance,
+  EFMODEventProperty::Type Property,
+  float Value
+);
+
+ + +
+
EventInstance
+
FFMODEventInstance to use.
+
Property
+
FMOD_STUDIO_EVENT_PROPERTY to set.
+
Value
+
Value of property.
+
+

UFMODBlueprintStatics::EventInstanceSetTransform

+

Set 3D attributes on an FMOD Event Instance.

+

+

+
C++
+
+

+
static void EventInstanceSetTransform(
+  FFMODEventInstance EventInstance,
+  const FTransform &Location
+);
+
+ + +
+
EventInstance
+
FFMODEventInstance to use.
+
Location
+
Location to place event.
+
+

UFMODBlueprintStatics::EventInstanceSetVolume

+

Set volume on an FMOD Event Instance.

+

+

+
C++
+
+

+
static void EventInstanceSetVolume(
+  FFMODEventInstance EventInstance,
+  float Volume
+);
+
+ + +
+
EventInstance
+
Event Instance to use.
+
Volume
+
Volume value to set.
+
+

See Also: FMOD::Studio::EventInstance

+

UFMODBlueprintStatics::EventInstanceStop

+

Mute/Unmute the bus.

+

+

+
C++
+
+

+
static void EventInstanceStop(
+  FFMODEventInstance EventInstance
+);
+
+ + +
+
EventInstance
+
+
+

UFMODBlueprintStatics::EventInstanceTriggerCue

+

Trigger a cue on an FMOD Event Instance.

+

+

+
C++
+
+

+
static void EventInstanceTriggerCue(
+  FFMODEventInstance EventInstance
+);
+
+ + +
+
EventInstance
+
FFMODEventInstance to use.
+
+

See Also: Sustain Points and Key Off

+

FFMODEventInstance

+

Wrapped FMOD::Studio::EventInstance for use in blueprints.

+

+

+
C++
+
+

+
struct FFMODEventInstance{
+  FMOD::Studio::EventInstance *Instance;
+} FFMODEventInstance;
+
+ + +
+
Instance
+
FMOD::Studio::EventInstance to use.
+
+

UFMODBlueprintStatics::FindAssetByName

+

Find an asset by name.

+

+

+
C++
+
+

+
static UFMODAsset *FindAssetByName(
+  const FString &Name
+);
+
+ + +
+
Name
+
The asset name.
+
+

See Also: UFMODAsset

+

UFMODBlueprintStatics::FindEventByName

+

Find an Event by name.

+

+

+
C++
+
+

+
static UFMODEvent *FindEventByName(
+  const FString &Name
+);
+
+ + +
+
Name
+
The event name.
+
+

See Also: UFMODEvent

+

UFMODBlueprintStatics::FindEventInstances

+

Return a list of all event instances that are playing for this event.

+

+

+
C++
+
+

+
static TArray<FFMODEventInstance> FindEventInstances(
+  UObject *WorldContextObject,
+  UFMODEvent *Event
+);
+
+ + +
+
WorldContextObject
+
Object from current world context.
+
Event
+
UFMODEvent to find instances of.
+
+

Be careful using this function because it is possible to find and alter any playing sound, even ones owned by other audio components.

+

See Also: FFMODEventInstance

+

UFMODBlueprintStatics::GetGlobalParameterByName

+

Get a global parameter value from the System.

+

+

+
C++
+
+

+
static float GetGlobalParameterByName(
+  FName Name
+);
+
+ + +
+
Name
+
Name of the parameter.
+
+

See Also: UFMODBlueprintStatics::SetGlobalParameterByName

+

UFMODBlueprintStatics::GetOutputDrivers

+

List all output device names.

+

+

+
C++
+
+

+
static TArray<FString> GetOutputDrivers();
+
+ + +

See Also: UFMODBlueprintStatics::SetOutputDriverByIndex, UFMODBlueprintStatics::SetOutputDriverByName

+

UFMODBlueprintStatics::IsBankLoaded

+

Return true if a bank is loaded.

+

+

+
C++
+
+

+
static bool IsBankLoaded(
+  UFMODBank *Bank
+);
+
+ + +
+
Bank
+
UFMODBank to query.
+
+

See Also: UFMODBlueprintStatics::LoadBank

+

UFMODBlueprintStatics::LoadBank

+

Load a bank.

+

+

+
C++
+
+

+
static void LoadBank(
+  UFMODBank *Bank,
+  bool bBlocking,
+  bool bLoadSampleData
+);
+
+ + +
+
Bank
+
UFMODBank to use.
+
bBlocking
+
Whether the bank will load synchronously.
+
bLoadSampleData
+
Whether sample data will be preloaded immediately.
+
+

UFMODBlueprintStatics::LoadBankSampleData

+

Load bank sample data.

+

+

+
C++
+
+

+
static void LoadBankSampleData(
+  UFMODBank *Bank
+);
+
+ + +
+
Bank
+
UFMODBank to use.
+
+

UFMODBlueprintStatics::LoadEventSampleData

+

Load event sample data.

+

+

+
C++
+
+

+
static void LoadEventSampleData(
+  UObject *WorldContextObject,
+  UFMODEvent *Event
+);
+
+ + +
+
WorldContextObject
+
Object from current world context.
+
Event
+
UFMODEvent to use.
+
+

This can be done ahead of time to avoid loading stalls.

+

UFMODBlueprintStatics::MixerResume

+

Resume the FMOD mixer.

+

+

+
C++
+
+

+
static void MixerResume();
+
+ + +

Used when resuming the application.

+

UFMODBlueprintStatics::MixerSuspend

+

Suspend the FMOD mixer.

+

+

+
C++
+
+

+
static void MixerSuspend();
+
+ + +

Used when suspending the application.

+

UFMODBlueprintStatics::PlayEvent2D

+

Play an event without a specified location.

+

+

+
C++
+
+

+
static FFMODEventInstance PlayEvent2D(
+  UObject *WorldContextObject,
+  UFMODEvent *Event,
+  bool bAutoPlay
+);
+
+ + +
+
WorldContextObject
+
Object from current world context.
+
Event
+
UFMODEvent to use.
+
bAutoPlay
+
Start the event automatically.
+
+

This returns an FFMODEventInstance.
+The sound does not travel with any actor.

+

UFMODBlueprintStatics::PlayEventAtLocation

+

Plays an event at the given location.

+

+

+
C++
+
+

+
static FFMODEventInstance PlayEventAtLocation(
+  UObject *WorldContextObject,
+  UFMODEvent *Event,
+  const FTransform &Location,
+  bool bAutoPlay
+);
+
+ + +
+
WorldContextObject
+
Object from current world context.
+
Event
+
UFMODEvent to use.
+
Location
+
World position to play event at.
+
bAutoPlay
+
Start the event automatically.
+
+

This returns an FMOD Event Instance.
+The sound does not travel with any actor.

+

UFMODBlueprintStatics::PlayEventAttached

+

Play an event attached to and following the specified component.

+

+

+
C++
+
+

+
static class UFMODAudioComponent *PlayEventAttached(
+  UFMODEvent *Event,
+  USceneComponent *AttachToComponent,
+  FName AttachPointName,
+  FVector Location,
+  EAttachLocation::Type LocationType,
+  bool bStopWhenAttachedToDestroyed,
+  bool bAutoPlay,
+  bool bAutoDestroy
+);
+
+ + +
+
Event
+
UFMODEvent to use.
+
AttachToComponent
+
Component to attach to.
+
AttachPointName Opt
+
Named point within the AttachComponent to play the sound at.
+
Location
+
Depending on the value of Location Type this is either a relative offset from the attach component/point or an absolute world position that will be translated to a relative offset.
+
LocationType
+
Location is a relative offset or an absolute world position.
+
bStopWhenAttachedToDestroyed
+
The sound should stop playing when the owner of the attach to component is destroyed.
+
bAutoPlay
+
Start the event automatically.
+
bAutoDestroy
+
Automatically destroy the audio component when the sound is stopped.
+
+

UFMODBlueprintStatics::SetGlobalParameterByName

+

Set a global parameter from the System.

+

+

+
C++
+
+

+
static void SetGlobalParameterByName(
+  FName Name,
+  float Value
+);
+
+ + +
+
Name
+
Name of parameter.
+
Value
+
Value to apply to the parameter.
+
+

UFMODBlueprintStatics::SetOutputDriverByIndex

+

Set current output device by its index from GetOutputDrivers.

+

+

+
C++
+
+

+
static void SetOutputDriverByIndex(
+  int NewDriverIndex
+);
+
+ + +
+
NewDriverIndex
+
Index of driver to use.
+
+

See Also: UFMODBlueprintStatics::GetOutputDrivers

+

UFMODBlueprintStatics::SetOutputDriverByName

+

Set current output device by name or part of the name.

+

+

+
C++
+
+

+
static void SetOutputDriverByName(
+  FString NewDriverName
+);
+
+ + +
+
NewDriverName
+
Name of new driver to use.
+
+

See Also: UFMODBlueprintStatics::GetOutputDrivers

+

UFMODBlueprintStatics::UnloadBank

+

Unload a bank.

+

+

+
C++
+
+

+
static void UnloadBank(
+  UFMODBank *Bank
+);
+
+ + +
+
Bank
+
UFMODBank to use.
+
+

UFMODBlueprintStatics::UnloadBankSampleData

+

Unload bank sample data.

+

+

+
C++
+
+

+
static void UnloadBankSampleData(
+  UFMODBank *Bank
+);
+
+ + +
+
Bank
+
UFMODBank to use.
+
+

UFMODBlueprintStatics::UnloadEventSampleData

+

Unload event sample data.

+

+

+
C++
+
+

+
static void UnloadEventSampleData(
+  UObject *WorldContextObject,
+  UFMODEvent *Event
+);
+
+ + +
+
WorldContextObject
+
Object from current world context.
+
Event
+
UFMODEvent to use.
+
+

UFMODBlueprintStatics::VCASetVolume

+

Set volume on a VCA.

+

+

+
C++
+
+

+
static void VCASetVolume(
+  UFMODVCA *Vca,
+  float Volume
+);
+
+ + +
+
Vca
+
UFMODVCA to use.
+
Volume
+
Volume value.
+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodbus.html b/Plugins/FMODStudio/Docs/api-reference-ufmodbus.html new file mode 100644 index 0000000..328111d --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodbus.html @@ -0,0 +1,39 @@ + + +API Reference | UFMODBus + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODBus

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from UFMODAsset

+

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodevent.html b/Plugins/FMODStudio/Docs/api-reference-ufmodevent.html new file mode 100644 index 0000000..f30df28 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodevent.html @@ -0,0 +1,40 @@ + + +API Reference | UFMODEvent + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODEvent

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from UFMODAsset

+

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodeventcontrolsection.html b/Plugins/FMODStudio/Docs/api-reference-ufmodeventcontrolsection.html new file mode 100644 index 0000000..cd3277a --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodeventcontrolsection.html @@ -0,0 +1,49 @@ + + +API Reference | UFMODEventControlSection + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODEventControlSection

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from UMovieSceneSection.

+

Defines:

+ +

Properties:

+ +

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodeventcontroltrack.html b/Plugins/FMODStudio/Docs/api-reference-ufmodeventcontroltrack.html new file mode 100644 index 0000000..15a85ae --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodeventcontroltrack.html @@ -0,0 +1,53 @@ + + +API Reference | UFMODEventControlTrack + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODEventControlTrack

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from UMovieSceneNameableTrack.

+

Properties:

+

Private:

+ +

Methods:

+

Public:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodeventparametertrack.html b/Plugins/FMODStudio/Docs/api-reference-ufmodeventparametertrack.html new file mode 100644 index 0000000..f56f281 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodeventparametertrack.html @@ -0,0 +1,53 @@ + + +API Reference | UFMODEventParameterTrack + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODEventParameterTrack

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from UMovieSceneNameableTrack.

+

Properties:

+

Private:

+ +

Methods:

+

Public:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodsettings.html b/Plugins/FMODStudio/Docs/api-reference-ufmodsettings.html new file mode 100644 index 0000000..b26724b --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodsettings.html @@ -0,0 +1,84 @@ + + +API Reference | UFMODSettings + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODSettings

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from UObject.

+

Defines:

+ +

Properties:

+ +

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodsnapshot.html b/Plugins/FMODStudio/Docs/api-reference-ufmodsnapshot.html new file mode 100644 index 0000000..3213d18 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodsnapshot.html @@ -0,0 +1,38 @@ + + +API Reference | UFMODSnapshot + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODSnapshot

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from UFMODEvent.

+

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodsnapshotreverb.html b/Plugins/FMODStudio/Docs/api-reference-ufmodsnapshotreverb.html new file mode 100644 index 0000000..fbc4966 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodsnapshotreverb.html @@ -0,0 +1,44 @@ + + +API Reference | UFMODSnapshotReverb + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODSnapshotReverb

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from UReverbEffect.

+

Properties:

+ +

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference-ufmodvca.html b/Plugins/FMODStudio/Docs/api-reference-ufmodvca.html new file mode 100644 index 0000000..7b4db47 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference-ufmodvca.html @@ -0,0 +1,39 @@ + + +API Reference | UFMODVCA + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference | UFMODVCA

+
+

This documentation is preliminary and is subject to change.

+
+

This class inherits from UFMODAsset.

+

Methods:

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/api-reference.html b/Plugins/FMODStudio/Docs/api-reference.html new file mode 100644 index 0000000..3988002 --- /dev/null +++ b/Plugins/FMODStudio/Docs/api-reference.html @@ -0,0 +1,56 @@ + + +API Reference + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

5. API Reference

+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/blueprint-reference.html b/Plugins/FMODStudio/Docs/blueprint-reference.html new file mode 100644 index 0000000..5c1b1cc --- /dev/null +++ b/Plugins/FMODStudio/Docs/blueprint-reference.html @@ -0,0 +1,34 @@ + + +Blueprint Reference + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

6. Blueprint Reference

+

6.0.1 Coming soon...

+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/glossary.html b/Plugins/FMODStudio/Docs/glossary.html new file mode 100644 index 0000000..80299e4 --- /dev/null +++ b/Plugins/FMODStudio/Docs/glossary.html @@ -0,0 +1,74 @@ + + +Glossary + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

9. Glossary

+

This page includes definitions for various common FMOD Studio terms, along with references to related terms and documentation.

+

9.1 Documentation Conventions

+

9.1.1 Parameter Tokens

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TokenMeaning
OutThe API function will fill in information in this parameter.
OptThis parameter is optional, specify null or zero to ignore.
R/OThis token applies to members of various structures which FMOD passes to user callbacks. User callbacks must not modify the values of these members. Modifying the values of these members will cause undefined behavior.
C#This is only available in C#.
JSThis is only available in Javascript.
+

9.2 Version

+

The version number of FMOD Studio. Version numbers are split into three parts, in the format: productVersion.majorVersion.minorVersion. For example, the version 1.23.45 would indicate product version 1, major version 23, and minor version 45 of that major version.

+

Major versions contain significant changes, add new features, and may affect bank compatibility. Updating to a new major version usually requires project migration. New major versions may change playback behavior in some cases.

+

Minor versions, also known as patch versions, contain bug fixes and smaller workflow improvements.

+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/images/add-actor-button.png b/Plugins/FMODStudio/Docs/images/add-actor-button.png new file mode 100644 index 0000000..87f1702 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/add-actor-button.png differ diff --git a/Plugins/FMODStudio/Docs/images/add-parameter-button.png b/Plugins/FMODStudio/Docs/images/add-parameter-button.png new file mode 100644 index 0000000..fd35d99 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/add-parameter-button.png differ diff --git a/Plugins/FMODStudio/Docs/images/add-track-button.png b/Plugins/FMODStudio/Docs/images/add-track-button.png new file mode 100644 index 0000000..642d457 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/add-track-button.png differ diff --git a/Plugins/FMODStudio/Docs/images/ambient-setting.png b/Plugins/FMODStudio/Docs/images/ambient-setting.png new file mode 100644 index 0000000..d8c05bc Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/ambient-setting.png differ diff --git a/Plugins/FMODStudio/Docs/images/assign-to-bank.png b/Plugins/FMODStudio/Docs/images/assign-to-bank.png new file mode 100644 index 0000000..06f3161 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/assign-to-bank.png differ diff --git a/Plugins/FMODStudio/Docs/images/audio-table.png b/Plugins/FMODStudio/Docs/images/audio-table.png new file mode 100644 index 0000000..fa5fb67 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/audio-table.png differ diff --git a/Plugins/FMODStudio/Docs/images/banks-blueprint.png b/Plugins/FMODStudio/Docs/images/banks-blueprint.png new file mode 100644 index 0000000..11350ff Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/banks-blueprint.png differ diff --git a/Plugins/FMODStudio/Docs/images/blueprint-play-simple.png b/Plugins/FMODStudio/Docs/images/blueprint-play-simple.png new file mode 100644 index 0000000..91aaac0 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/blueprint-play-simple.png differ diff --git a/Plugins/FMODStudio/Docs/images/blueprint-sample.png b/Plugins/FMODStudio/Docs/images/blueprint-sample.png new file mode 100644 index 0000000..3ced876 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/blueprint-sample.png differ diff --git a/Plugins/FMODStudio/Docs/images/build-menu.png b/Plugins/FMODStudio/Docs/images/build-menu.png new file mode 100644 index 0000000..267281d Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/build-menu.png differ diff --git a/Plugins/FMODStudio/Docs/images/callback-bp.png b/Plugins/FMODStudio/Docs/images/callback-bp.png new file mode 100644 index 0000000..ea18e09 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/callback-bp.png differ diff --git a/Plugins/FMODStudio/Docs/images/callback-enable.png b/Plugins/FMODStudio/Docs/images/callback-enable.png new file mode 100644 index 0000000..dff915e Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/callback-enable.png differ diff --git a/Plugins/FMODStudio/Docs/images/callback-example.png b/Plugins/FMODStudio/Docs/images/callback-example.png new file mode 100644 index 0000000..0974a7e Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/callback-example.png differ diff --git a/Plugins/FMODStudio/Docs/images/content-view.png b/Plugins/FMODStudio/Docs/images/content-view.png new file mode 100644 index 0000000..0e8cd3b Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/content-view.png differ diff --git a/Plugins/FMODStudio/Docs/images/control-track.png b/Plugins/FMODStudio/Docs/images/control-track.png new file mode 100644 index 0000000..63b0c7e Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/control-track.png differ diff --git a/Plugins/FMODStudio/Docs/images/docs-menu.png b/Plugins/FMODStudio/Docs/images/docs-menu.png new file mode 100644 index 0000000..f81db26 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/docs-menu.png differ diff --git a/Plugins/FMODStudio/Docs/images/drag-ambient.png b/Plugins/FMODStudio/Docs/images/drag-ambient.png new file mode 100644 index 0000000..6fbef0e Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/drag-ambient.png differ diff --git a/Plugins/FMODStudio/Docs/images/engine-mac.png b/Plugins/FMODStudio/Docs/images/engine-mac.png new file mode 100644 index 0000000..b0c217d Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/engine-mac.png differ diff --git a/Plugins/FMODStudio/Docs/images/engine-tree.png b/Plugins/FMODStudio/Docs/images/engine-tree.png new file mode 100644 index 0000000..f43ce2e Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/engine-tree.png differ diff --git a/Plugins/FMODStudio/Docs/images/event-tracks.png b/Plugins/FMODStudio/Docs/images/event-tracks.png new file mode 100644 index 0000000..6083626 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/event-tracks.png differ diff --git a/Plugins/FMODStudio/Docs/images/fmod-content.png b/Plugins/FMODStudio/Docs/images/fmod-content.png new file mode 100644 index 0000000..c93c612 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/fmod-content.png differ diff --git a/Plugins/FMODStudio/Docs/images/getglobalparameter.png b/Plugins/FMODStudio/Docs/images/getglobalparameter.png new file mode 100644 index 0000000..a91b490 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/getglobalparameter.png differ diff --git a/Plugins/FMODStudio/Docs/images/load-locale-bank.png b/Plugins/FMODStudio/Docs/images/load-locale-bank.png new file mode 100644 index 0000000..b0e1897 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/load-locale-bank.png differ diff --git a/Plugins/FMODStudio/Docs/images/master-bank-name.png b/Plugins/FMODStudio/Docs/images/master-bank-name.png new file mode 100644 index 0000000..9a730b3 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/master-bank-name.png differ diff --git a/Plugins/FMODStudio/Docs/images/occlusion-props.png b/Plugins/FMODStudio/Docs/images/occlusion-props.png new file mode 100644 index 0000000..2d88955 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/occlusion-props.png differ diff --git a/Plugins/FMODStudio/Docs/images/occlusion-props2.png b/Plugins/FMODStudio/Docs/images/occlusion-props2.png new file mode 100644 index 0000000..0ea1d72 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/occlusion-props2.png differ diff --git a/Plugins/FMODStudio/Docs/images/occlusion-setting.png b/Plugins/FMODStudio/Docs/images/occlusion-setting.png new file mode 100644 index 0000000..132f5b8 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/occlusion-setting.png differ diff --git a/Plugins/FMODStudio/Docs/images/occlusion.png b/Plugins/FMODStudio/Docs/images/occlusion.png new file mode 100644 index 0000000..63fe60c Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/occlusion.png differ diff --git a/Plugins/FMODStudio/Docs/images/parameter-keyframe-curve.png b/Plugins/FMODStudio/Docs/images/parameter-keyframe-curve.png new file mode 100644 index 0000000..8683192 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/parameter-keyframe-curve.png differ diff --git a/Plugins/FMODStudio/Docs/images/parameter-track.png b/Plugins/FMODStudio/Docs/images/parameter-track.png new file mode 100644 index 0000000..3301916 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/parameter-track.png differ diff --git a/Plugins/FMODStudio/Docs/images/plugins.png b/Plugins/FMODStudio/Docs/images/plugins.png new file mode 100644 index 0000000..3a2dd16 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/plugins.png differ diff --git a/Plugins/FMODStudio/Docs/images/possess-actor.png b/Plugins/FMODStudio/Docs/images/possess-actor.png new file mode 100644 index 0000000..125cb78 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/possess-actor.png differ diff --git a/Plugins/FMODStudio/Docs/images/programmer-asset-name.png b/Plugins/FMODStudio/Docs/images/programmer-asset-name.png new file mode 100644 index 0000000..9a493bc Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/programmer-asset-name.png differ diff --git a/Plugins/FMODStudio/Docs/images/programmer-bp.png b/Plugins/FMODStudio/Docs/images/programmer-bp.png new file mode 100644 index 0000000..dde4420 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/programmer-bp.png differ diff --git a/Plugins/FMODStudio/Docs/images/programmer-file-path.png b/Plugins/FMODStudio/Docs/images/programmer-file-path.png new file mode 100644 index 0000000..acc1061 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/programmer-file-path.png differ diff --git a/Plugins/FMODStudio/Docs/images/project-deploy.png b/Plugins/FMODStudio/Docs/images/project-deploy.png new file mode 100644 index 0000000..af2df3a Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/project-deploy.png differ diff --git a/Plugins/FMODStudio/Docs/images/project-settings.png b/Plugins/FMODStudio/Docs/images/project-settings.png new file mode 100644 index 0000000..4ae2875 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/project-settings.png differ diff --git a/Plugins/FMODStudio/Docs/images/reverb-ambient.png b/Plugins/FMODStudio/Docs/images/reverb-ambient.png new file mode 100644 index 0000000..e48f1d1 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/reverb-ambient.png differ diff --git a/Plugins/FMODStudio/Docs/images/reverb-assets.png b/Plugins/FMODStudio/Docs/images/reverb-assets.png new file mode 100644 index 0000000..50b2e9b Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/reverb-assets.png differ diff --git a/Plugins/FMODStudio/Docs/images/reverb-settings.png b/Plugins/FMODStudio/Docs/images/reverb-settings.png new file mode 100644 index 0000000..44b4b98 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/reverb-settings.png differ diff --git a/Plugins/FMODStudio/Docs/images/reverb-snapshot-intensity.png b/Plugins/FMODStudio/Docs/images/reverb-snapshot-intensity.png new file mode 100644 index 0000000..ec8a665 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/reverb-snapshot-intensity.png differ diff --git a/Plugins/FMODStudio/Docs/images/reverb-user-property.png b/Plugins/FMODStudio/Docs/images/reverb-user-property.png new file mode 100644 index 0000000..1d5c981 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/reverb-user-property.png differ diff --git a/Plugins/FMODStudio/Docs/images/save-as-studio.png b/Plugins/FMODStudio/Docs/images/save-as-studio.png new file mode 100644 index 0000000..c2b2b75 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/save-as-studio.png differ diff --git a/Plugins/FMODStudio/Docs/images/set-audio-listener-override.png b/Plugins/FMODStudio/Docs/images/set-audio-listener-override.png new file mode 100644 index 0000000..d95480a Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/set-audio-listener-override.png differ diff --git a/Plugins/FMODStudio/Docs/images/set-locale.png b/Plugins/FMODStudio/Docs/images/set-locale.png new file mode 100644 index 0000000..6090321 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/set-locale.png differ diff --git a/Plugins/FMODStudio/Docs/images/setglobalparameter.png b/Plugins/FMODStudio/Docs/images/setglobalparameter.png new file mode 100644 index 0000000..659ef5c Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/setglobalparameter.png differ diff --git a/Plugins/FMODStudio/Docs/images/settings-advanced.png b/Plugins/FMODStudio/Docs/images/settings-advanced.png new file mode 100644 index 0000000..eae3461 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/settings-advanced.png differ diff --git a/Plugins/FMODStudio/Docs/images/settings-basic.png b/Plugins/FMODStudio/Docs/images/settings-basic.png new file mode 100644 index 0000000..4658e57 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/settings-basic.png differ diff --git a/Plugins/FMODStudio/Docs/images/settings-encryption.png b/Plugins/FMODStudio/Docs/images/settings-encryption.png new file mode 100644 index 0000000..186ce44 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/settings-encryption.png differ diff --git a/Plugins/FMODStudio/Docs/images/settings-init.png b/Plugins/FMODStudio/Docs/images/settings-init.png new file mode 100644 index 0000000..25c6611 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/settings-init.png differ diff --git a/Plugins/FMODStudio/Docs/images/settings-locale.png b/Plugins/FMODStudio/Docs/images/settings-locale.png new file mode 100644 index 0000000..8805ecf Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/settings-locale.png differ diff --git a/Plugins/FMODStudio/Docs/images/studio-bank-layout.png b/Plugins/FMODStudio/Docs/images/studio-bank-layout.png new file mode 100644 index 0000000..609bed9 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/studio-bank-layout.png differ diff --git a/Plugins/FMODStudio/Docs/images/studio-export-path.png b/Plugins/FMODStudio/Docs/images/studio-export-path.png new file mode 100644 index 0000000..726d6b6 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/studio-export-path.png differ diff --git a/Plugins/FMODStudio/Docs/images/studio-programmer.png b/Plugins/FMODStudio/Docs/images/studio-programmer.png new file mode 100644 index 0000000..d472810 Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/studio-programmer.png differ diff --git a/Plugins/FMODStudio/Docs/images/unload-setlocale-load.png b/Plugins/FMODStudio/Docs/images/unload-setlocale-load.png new file mode 100644 index 0000000..244058f Binary files /dev/null and b/Plugins/FMODStudio/Docs/images/unload-setlocale-load.png differ diff --git a/Plugins/FMODStudio/Docs/platform-specifics.html b/Plugins/FMODStudio/Docs/platform-specifics.html new file mode 100644 index 0000000..97a2aa4 --- /dev/null +++ b/Plugins/FMODStudio/Docs/platform-specifics.html @@ -0,0 +1,160 @@ + + +Platform Specifics + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

7. Platform Specifics

+

Some platforms require some extra steps to run properly.

+

7.1 Android

+

To deploy on Android, make sure FMODStudio is in your game's directory, not in the Engine plugins directory. When FMODStudio is in your game's plugin directory, the engine will rebuild the plugin for Android and deploy all the files properly.

+

7.1.1 Deployment of Android plugins

+

FMOD supports DSP plugins, which will be stand-alone .so files that will need to be packaged into the build. Add the .so file into the FMODStudio/Binaries/Android/{Architecture} directory. Unreal will also need an APL file so it knows to package the .so file. To do this, you will need to write an APL file and drop it into the FMODStudio/Binaries/Android directory. The FMODStudio.build.cs file looks for any file ending with __APL.xml_ and will pass that along to the unreal build tool for packaging.

+

The APL is a custom xml file format which is documented in the engine file AndroidPluginLanguage.cs. Here is a sample APL file for libovrfmod.so:

+
<?xml version="1.0" encoding="utf-8"?>
+<!--Plugin additions-->
+<root xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- init section is always evaluated once per architecture -->
+    <init>
+        <log text="ovrfmod APL init"/>
+    </init>
+
+    <!-- optional files or directories to copy to Intermediate/Android/APK -->
+    <resourceCopies>
+        <log text="ovrfmod APL copying files for $S(Architecture)/"/>
+        <copyFile src="$S(PluginDir)/$S(Architecture)/libovrfmod.so"
+                    dst="$S(BuildDir)/libs/$S(Architecture)/libovrfmod.so" />
+    </resourceCopies>
+
+    <!-- optional libraries to load in GameActivity.java before libUE4.so -->
+    <soLoadLibrary>
+        <log text="ovrfmod APL adding loadLibrary references"/>
+        <loadLibrary name="ovrfmod" failmsg="ovrfmod not loaded and required!" />
+    </soLoadLibrary>
+</root>
+
+ + +

You only need to write this if you want to load a DSP plugin on Android.

+

7.2 TVOS

+

To build for TVOS, make sure FMODStudio is in your game's directory and not in the Engine plugins directory.

+

7.3 Linux

+

To deploy on linux, you will need to rebuild the engine from source via github. For compiling linux from windows, see this page for instructions how to get up and running with UE4. Then, add in both the fmodstudio linux .zip and windows .zip on top of each other into the engine plugins directory.

+

The last thing you will need to do is to get the FMOD .so libraries into a directory that the executable can read them. The easiest way is to copy them from

+
<DeployedDir>\Engine\Plugins\FMODStudio\Binaries\Linux\x86_64
+
+ + +

to

+
<DeployedDir>\<GameName>\Binaries\Linux
+
+ + +

To see what directories the .so files can be located, look at LinuxToolChain.cs. Currently there are only a set of hard coded directories that are supported.

+

7.4 Xbox One

+

7.4.1 Enabling XboxOne Microphone Input

+

To enable FMOD Studio the use of any microphone input, including Kinect, on the Xbox One. The Engine ini file specific for the platform, located in '/Config/XboxOne/XboxOneEngine.ini', needs to have the following lines added:

+
[AppxManifest]
+Package.Capabilities.mx:Capability[0].Name=kinectAudio
+Package.Capabilities.mx:Capability[1].Name=kinectGamechat
+
+ + +

7.4.2 Copying dll's to build

+

Add the following to GetFilesToDeployOrStage in XboxOnePlatform.Automation.cs, before the end of the function:

+
// FMOD code start
+DirectoryReference FMODDLLPath = null;
+if (Directory.Exists(Path.Combine(SC.ProjectRoot.ToString(), "Plugins/FMODStudio")))
+{
+    FMODDLLPath = DirectoryReference.Combine(SC.ProjectRoot, "Plugins/FMODStudio/Binaries/XBoxOne/");
+}
+else if (Directory.Exists(Path.Combine(SC.LocalRoot.ToString(), "Engine/Plugins/FMODStudio")))
+{
+    FMODDLLPath = DirectoryReference.Combine(SC.LocalRoot, "Engine/Plugins/FMODStudio/Binaries/XBoxOne/");
+}
+else
+{
+    LogError("Failed to find FMODStudio plugin in game or engine directory");
+}
+if (FMODDLLPath != null)
+{
+    Log.TraceInformation("Copying FMOD dlls to loose directory: " + RelativeBinPath);
+    StagedDirectoryReference RelativeBinPathRef = new StagedDirectoryReference(RelativeBinPath);
+    StageFileIfExists(StagedFileType.NonUFS, FileReference.Combine(FMODDLLPath, "fmod.dll"), RelativeBinPathRef, SC);
+    StageFileIfExists(StagedFileType.NonUFS, FileReference.Combine(FMODDLLPath, "fmodL.dll"), RelativeBinPathRef, SC);
+    StageFileIfExists(StagedFileType.NonUFS, FileReference.Combine(FMODDLLPath, "fmodstudio.dll"), RelativeBinPathRef, SC);
+    StageFileIfExists(StagedFileType.NonUFS, FileReference.Combine(FMODDLLPath, "fmodstudioL.dll"), RelativeBinPathRef, SC);
+}
+// FMOD code end
+
+ + +

Add the following to PrepTargetForDeployment in XboxOneDeploy.cs, in the same scope as 'DestDir':

+
// FMOD code start
+string FMODDLLPath = null;
+if (Directory.Exists(Path.Combine(ProjectDirectory.FullName, "Plugins/FMODStudio")))
+{
+    FMODDLLPath = Path.Combine(ProjectDirectory.FullName, "Plugins/FMODStudio/Binaries/XBoxOne/");
+}
+else if (Directory.Exists(Path.Combine(RelativeEnginePath, "Plugins/FMODStudio")))
+{
+    FMODDLLPath = Path.Combine(RelativeEnginePath, "Plugins/FMODStudio/Binaries/XBoxOne/");
+}
+else
+{
+    Log.TraceWarning("Failed to find FMODStudio plugin in game or engine directory");
+}
+if (FMODDLLPath != null)
+{
+    Log.TraceInformation("...copying the FMOD dlls...");
+    string FMODDLLName = "fmod.dll";
+    Log.TraceInformation("\tcopying " + FMODDLLPath + FMODDLLName + " to " + DestDir + "/" + FMODDLLName);
+    CopyFile(FMODDLLPath + FMODDLLName, DestDir + "/" + FMODDLLName, true);
+    FMODDLLName = "fmodL.dll";
+    Log.TraceInformation("\tcopying " + FMODDLLPath + FMODDLLName + " to " + DestDir + "/" + FMODDLLName);
+    CopyFile(FMODDLLPath + FMODDLLName, DestDir + "/" + FMODDLLName, true);
+    FMODDLLName = "fmodstudio.dll";
+    Log.TraceInformation("\tcopying " + FMODDLLPath + FMODDLLName + " to " + DestDir + "/" + FMODDLLName);
+    CopyFile(FMODDLLPath + FMODDLLName, DestDir + "/" + FMODDLLName, true);
+    FMODDLLName = "fmodstudioL.dll";
+    Log.TraceInformation("\tcopying " + FMODDLLPath + FMODDLLName + " to " + DestDir + "/" + FMODDLLName);
+    CopyFile(FMODDLLPath + FMODDLLName, DestDir + "/" + FMODDLLName, true);
+}
+// FMOD code end
+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/plugins.html b/Plugins/FMODStudio/Docs/plugins.html new file mode 100644 index 0000000..9856588 --- /dev/null +++ b/Plugins/FMODStudio/Docs/plugins.html @@ -0,0 +1,53 @@ + + +Plugins + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

4. Plugins

+

FMOD Studio projects can be set up to use third party plugins. These can include custom DSP effects that are created in-house or commercial products that can be used with FMOD Studio.

+

4.1 Adding plugins to the project

+

The plugins must be loaded at runtime so that they are there when loading the banks that need them. Plugins are set up in the project settings Advanced section.

+

Plugins

+

Each entry should be the filename of the plugin, without any extension. Any plugin files required should be added to the FMODStudio/Binaries/Platform/ directory.

+

For example, to use fmod_gain.dll on Win64 builds, you should add the file here:

+
FMODStudio/Binaries/Win64/fmod_gain.dll
+
+ + +

4.2 Deploying FMOD plugins

+

You will need to make sure the plugins are deployed as well. Unreal deployment doesn't have access to the settings information so you will need to create an extra file that lists the plugins you want to deploy.

+

Create a file "plugins.txt" in the FMODStudio/Binaries/Platform/ directory. The text file should contain the plugin names (just the name without file extension).

+

For example, to deploy fmod_gain.dll on Win64 builds, create a file FMODStudio/Binaries/Win64/plugins.txt with the following contents:

+
fmod_gain
+
+ + +

Check the Platform Specifics for information relating to plugins on specific platforms.

+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/scripts/language-selector.js b/Plugins/FMODStudio/Docs/scripts/language-selector.js new file mode 100644 index 0000000..fe9bdc9 --- /dev/null +++ b/Plugins/FMODStudio/Docs/scripts/language-selector.js @@ -0,0 +1,94 @@ +var languageTabs = null; +var languageSpecificElements = null; +var availableLanguages = null; + +// Helper function to iterate over an HTMLCollection or NodeList (https://stackoverflow.com/questions/3871547/js-iterating-over-result-of-getelementsbyclassname-using-array-foreach) +function forEachElement(collection, func) { + Array.prototype.forEach.call(collection, func); +} + +function matchLanguage(el, lang) { + if (lang == "language-all" || el.classList.contains("language-all")) { + return true; + } else if ((lang === "language-c" || lang === "language-cpp") && el.classList.contains("language-c-cpp")) { + return true; + } else { + return el.classList.contains(lang); + } +} + +function setLanguage(lang) { + if (languageSpecificElements == null) { + return; + } + + window.localStorage.setItem("FMOD.Documents.selected-language", lang); + + if (availableLanguages.length > 0 && !availableLanguages.includes(lang)) { + lang = availableLanguages[0]; + } + + forEachElement(languageTabs, function(el) { + var ellang = el.attributes['data-language'].value; + + if (ellang === lang) { + el.classList.add("selected"); + } else { + el.classList.remove("selected"); + } + }); + + forEachElement(languageSpecificElements, function(el) { + if (matchLanguage(el, lang)) { + el.style.display = 'block'; + } else { + el.style.display = 'none'; + } + }); + + window.localStorage.setItem("FMOD.Documents.selected-language", lang); +} + +function init() { + var docsBody = document.querySelector("div.manual-content.api"); + + if (docsBody) { + // API docs + + // Setup language tabs + languageTabs = docsBody.getElementsByClassName("language-tab"); + + forEachElement(languageTabs, function(el) { + el.onclick = function() { setLanguage(this.attributes['data-language'].value); } + }); + + // Cache language specific elements on the page + languageSpecificElements = docsBody.querySelectorAll(".language-c, .language-cpp, .language-c-cpp, .language-csharp, .language-javascript"); + + // Determine languages used on the page + availableLanguages = []; + ["language-c", "language-cpp", "language-c-cpp", "language-csharp", "language-javascript"].forEach(function(lang) { + if (docsBody.querySelector("." + lang) != null) { + availableLanguages.push(lang); + } + }); + + // Set initial language + var lang = window.localStorage.getItem("FMOD.Documents.selected-language"); + + if (lang == null) { + lang = "language-cpp"; + } + + setLanguage(lang); + } +} + +if (typeof module !== 'undefined') { + module.exports = { initLanguageSelector: init }; +} else { + // Call our init function when the document is loaded. (https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/) + if (document.readyState != 'loading') init(); + else if (document.addEventListener) document.addEventListener('DOMContentLoaded', init); + else document.attachEvent('onreadystatechange', function() { if (document.readyState == 'complete') init(); }); +} diff --git a/Plugins/FMODStudio/Docs/settings.html b/Plugins/FMODStudio/Docs/settings.html new file mode 100644 index 0000000..55b69f1 --- /dev/null +++ b/Plugins/FMODStudio/Docs/settings.html @@ -0,0 +1,110 @@ + + +Settings + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

3. Settings

+

The FMOD UE4 Integration settings can be found in the UE4 Editor, under "Project Settings > Plugins > FMOD Studio".
+Settings

+

3.1 Basic

+

3.1.1 Load All Banks

+

3.1.2 Load All Sample Data

+

3.1.3 Enable Live Update

+

3.1.4 Enable Editor Live Update

+

3.1.5 Bank Output Directory

+

3.1.6 Output Format

+

3.2 Init

+

3.2.1 Vol 0 Virtual

+

3.2.2 Vol 0 Virtual Level

+

3.2.3 Sample Rate

+

3.2.4 Match Hardware Sample Rate

+

3.2.5 Real Channel Count

+

3.2.6 Total Channel Count

+

3.2.7 DSP Buffer Length

+

3.2.8 DSP Buffer Count

+

3.2.9 File Buffer Size

+

3.2.10 Studio Update Period

+

3.2.11 Initial Output Driver Name

+

3.2.12 Lock All Buses

+

3.2.13 Memory Pool Sizes

+

3.3 Advanced

+

3.3.1 Live Update Port

+

3.3.2 Editor Live Update Port

+

3.3.3 Plugin Files

+

3.3.4 Content Browser Prefix

+

3.3.5 Force Platform Name

+

3.3.6 Master Bank Name

+

3.3.7 Skip Load Bank Name

+

3.3.8 Encryption Key

+

3.3.9 Wav Writer Path

+

3.3.10 Logging Level

+

3.3.11 Occlusion Parameter

+

3.3.12 Ambient Volume Parameter

+

3.3.13 Ambient LPF Parameter

+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/style/DINWeb-Medium.woff b/Plugins/FMODStudio/Docs/style/DINWeb-Medium.woff new file mode 100644 index 0000000..5c098af Binary files /dev/null and b/Plugins/FMODStudio/Docs/style/DINWeb-Medium.woff differ diff --git a/Plugins/FMODStudio/Docs/style/DINWeb.woff b/Plugins/FMODStudio/Docs/style/DINWeb.woff new file mode 100644 index 0000000..5aaa4b8 Binary files /dev/null and b/Plugins/FMODStudio/Docs/style/DINWeb.woff differ diff --git a/Plugins/FMODStudio/Docs/style/code_highlight.css b/Plugins/FMODStudio/Docs/style/code_highlight.css new file mode 100644 index 0000000..631bc92 --- /dev/null +++ b/Plugins/FMODStudio/Docs/style/code_highlight.css @@ -0,0 +1,69 @@ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #408080; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #008000; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #BC7A00 } /* Comment.Preproc */ +.highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #008000 } /* Keyword.Pseudo */ +.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #B00040 } /* Keyword.Type */ +.highlight .m { color: #666666 } /* Literal.Number */ +.highlight .s { color: #BA2121 } /* Literal.String */ +.highlight .na { color: #7D9029 } /* Name.Attribute */ +.highlight .nb { color: #008000 } /* Name.Builtin */ +.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.highlight .no { color: #880000 } /* Name.Constant */ +.highlight .nd { color: #AA22FF } /* Name.Decorator */ +.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #0000FF } /* Name.Function */ +.highlight .nl { color: #A0A000 } /* Name.Label */ +.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #19177C } /* Name.Variable */ +.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mb { color: #666666 } /* Literal.Number.Bin */ +.highlight .mf { color: #666666 } /* Literal.Number.Float */ +.highlight .mh { color: #666666 } /* Literal.Number.Hex */ +.highlight .mi { color: #666666 } /* Literal.Number.Integer */ +.highlight .mo { color: #666666 } /* Literal.Number.Oct */ +.highlight .sa { color: #BA2121 } /* Literal.String.Affix */ +.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ +.highlight .sc { color: #BA2121 } /* Literal.String.Char */ +.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */ +.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ +.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.highlight .sx { color: #008000 } /* Literal.String.Other */ +.highlight .sr { color: #BB6688 } /* Literal.String.Regex */ +.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ +.highlight .ss { color: #19177C } /* Literal.String.Symbol */ +.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #0000FF } /* Name.Function.Magic */ +.highlight .vc { color: #19177C } /* Name.Variable.Class */ +.highlight .vg { color: #19177C } /* Name.Variable.Global */ +.highlight .vi { color: #19177C } /* Name.Variable.Instance */ +.highlight .vm { color: #19177C } /* Name.Variable.Magic */ +.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/Plugins/FMODStudio/Docs/style/docs.css b/Plugins/FMODStudio/Docs/style/docs.css new file mode 100644 index 0000000..eaf47bc --- /dev/null +++ b/Plugins/FMODStudio/Docs/style/docs.css @@ -0,0 +1,265 @@ +@font-face { + font-family:'DINWeb-Medium'; + src:url('DINWeb-Medium.woff'); +} + +@font-face { + font-family:'DINWeb'; + src:url('DINWeb.woff'); +} + +body { + background-color: black; +} + +.docs-body { + font-family: DINWeb-Medium, -apple-system, sans-serif; + background-color: black; + padding: 24px; +} + +.docs-body a { + color: #020eab; + text-decoration: none; + font-weight: bold; +} + +.manual-content h1 a, +.manual-content h2 a, +.manual-content h3 a, +.manual-content h4 a, +.manual-content h5 a, +.manual-content h6 a { + color: black; +} + +.docs-body img { + max-width: 100%; + box-shadow: 0px 4px 30px #333333; + margin: 20px; +} + +.admonition { + border: 1px solid #b3b3b3; + border-top: 4px solid black; + background-color: #f1f1f1; + padding: 3px; +} + +.admonition.warning { + border-top: 4px solid #cc0000; +} + +.highlight { + border: 1px solid #b3b3b3; + background-color: #f1f1f1; + overflow: auto; + padding: 6px; +} + +.highlight pre { + margin: 0; +} + +code { + background-color: #eeeeee; +} + +.manual-toc { + float: right; + display: inline-block; + width: 20%; + min-width: 300px; + margin: 0; + margin-left: 20px; + margin-bottom: 20px; + color: black; + background-color: #d6dceb; + font-weight: bold; +} + +.manual-toc p { + color: black; + font-size: larger; + text-align: center; +} + +.manual-toc > ul { + padding: 0px; +} + +.manual-toc > ul > li { + padding: 12px; + list-style-position: inside; +} + +.manual-toc ul { list-style-type: none; } +.manual-toc ul { counter-reset: toc-level-1; } +.manual-toc li { counter-increment: toc-level-1; } +.manual-toc li > a:before { content: counter(toc-level-1)". "; } +.manual-toc li ul { counter-reset: toc-level-2; } +.manual-toc li li { counter-increment: toc-level-2; } +.manual-toc li li a:before { content: counter(toc-level-1)"."counter(toc-level-2)" "; } +.manual-toc li li ul { counter-reset: toc-level-3; } +.manual-toc li li li { counter-increment: toc-level-3; } +.manual-toc li li li a:before { content: counter(toc-level-1)"."counter(toc-level-2)"."counter(toc-level-3)" "; } +.manual-inactive-chapter li ul { display: none; } + +.manual-current-chapter { + background-color: white; +} + +.manual-current-chapter ul { + padding-left: 20px; +} + +.manual-active-chapter > a { + color: black; +} + +.manual-current-chapter > ul { margin-top: 14px; } +.manual-current-chapter li { padding-top: 18px; font-size: 14px; } +.manual-current-chapter > ul > li:first-child { padding-top: 0px; } + +.manual-current-chapter li > ul > li > ul { + display: none; +} + +ul.subchapters { border-left: 2px dotted #b3b3b3; } +ul.subchapters li > a:before { content: ""; } +ul.subchapters .manual-active-chapter > a { border-bottom: 2px solid black; } + +.manual-content { + background-color: white; + overflow: hidden; + padding: 20px 50px 40px; + min-width: 300px; +} + +.manual-content li { + margin: 1em 0; +} + +.manual-content h2 { + margin: 1.5em 0 1em 0; +} + +.manual-content table { + margin-bottom: 1.5em; + width: 100%; + border-collapse: collapse; + display: block; + overflow-x: auto; +} + +.manual-content th { + background-color: #d6dceb; +} + +.manual-content th, .manual-content td { + border: 1px solid #b3b3b3; + padding: 12px; + text-align: left; +} + +.manual-content.api dt { + font-style:italic; + margin-bottom: 1em; +} + +/* Exclude token links (e.g. "Optional", "Output") - TODO: these need proper styling */ +.manual-content.api dt a.token { + font-style:initial; +} + +.manual-content.api dd { + margin-bottom: 2em; +} + +.manual-content.api dd ul { + margin: 0; + padding: 0.75em 0 0.5em 1em; + font-family: DINWeb; + border: 1px solid #b3b3b3; + width:max-content; +} + +.manual-content.api dd ul li { + margin: 0; + margin-right: 1em; + display: inline; +} + +.manual-content.api dd ul li .label { + font-weight: bold; +} + +.manual-content.api dd p { + margin: 0.25em; +} + +.manual-footer { + color: white; + padding: 20px; + font-size: smaller; +} + +div.language-selector { + display: -webkit-flex; + display: flex; + text-align: center; +} + +div.language-tab { + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + border: 1px solid #bbbbbb; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + box-sizing: content-box; + max-width: 30px; + padding: 2px 10px; + margin-right: -1px; + margin-bottom: -1px; + cursor: pointer; +} + +.language-tab:hover { + background-color: #d6dceb; +} + +.language-tab.selected { + background-color: #f1f1f1; + border-bottom-width: 0; +} + +.language-tab.selected:after { + content: ''; + width: 100%; + height: 3px; + bottom: -1px; + left: 0; + background: inherit; +} + +div.language-selector + p { + display: none; +} + +a.token, .token { + padding: 6px; + margin-left: 8px; + color: black; + font-size: small; + font-weight: normal; + border: 1px solid #bbbbbb; + border-radius: 6px; +} + +a.token:hover { + background-color: #d6dceb; +} + +[id]:target { animation:highlighter 3s } +@keyframes highlighter { 25% { background-color: gold; } 75% { background-color: gold; } } diff --git a/Plugins/FMODStudio/Docs/troubleshooting.html b/Plugins/FMODStudio/Docs/troubleshooting.html new file mode 100644 index 0000000..bdda187 --- /dev/null +++ b/Plugins/FMODStudio/Docs/troubleshooting.html @@ -0,0 +1,63 @@ + + +Troubleshooting + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

8. Troubleshooting

+

If you are experiencing an issue with the integration and none of the topics below help, visit to our Q&A Forum.

+

8.1 Check the plugin is installed

+

You should see a shortcut to the manual is available under the help menu, that means the plugin is in the right place and has been enabled.

+

UE4 Help Menu

+

If you see the FMOD Help in the manual, then the plugin installed correctly. If you don't see FMOD help, it isn't installed.

+

8.2 Project Output Format

+

If you have modified the project output format in your FMOD Studio project, you will need to update your Unreal project settings to match.
+This can be found under "Edit > Project Settings > FMOD Studio > Output Format". Keep in mind that this must match the Studio project settings in order for the mix to behave correctly.

+

8.3 Content Changes

+

The editor does not mark FMOD assets as read-only, so there is nothing stopping the user from trying to rearrange the folder structure.
+However any such changes aren't going to change the underlying Studio project, so the changes will be lost next time Unreal is restarted.

+

8.3.1 Asset Paths

+

The inbuilt Unreal asset serialization stores asset by full path, not by GUID. This means that if you rename events or folders in the Studio Tool, then any references in Unreal levels will be lost. For now the only workaround is to avoid renaming events or folders once you have started using them in levels.

+

8.4 Deployment Issues

+

See the Deployment page for information about issues with deployment.

+

If you Launch your game and there is no sound playing or there is error loading the FMODStudio module, it an issue with Deployment.

+

8.5 Live Update

+

If Live Update is enabled and the FMOD Studio will error when it fails to open the required network port. If this is a problem, then Live Update can be disabled in the Project Settings window.

+

8.6 Additional Logging

+

To help track down problems, verbose logging can be turned on for the FMOD UE4 integration. Add the following command line to the UE4 editor:

+
-LogCmds="LogFMOD verbose"
+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/user-guide.html b/Plugins/FMODStudio/Docs/user-guide.html new file mode 100644 index 0000000..b4b42c0 --- /dev/null +++ b/Plugins/FMODStudio/Docs/user-guide.html @@ -0,0 +1,516 @@ + + +User Guide + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

2. User Guide

+

The FMOD UE4 Integration is a plugin that allows you to use the FMOD APIs and projects from the FMOD Studio authoring tool in your UE4 game.

+

Normally you will just need one copy of the integration. If you develop for multiple platforms at once, you can copy multiple integrations over the top of each other.

+
+

2.1 Installing the integration

+

The integration consists of a single FMODStudio folder which can be placed in either the Engine/Plugins directory or your UE4 game's Plugin directory {ProjectName}/Plugins. The next steps show how to install it into your Engine directory, so it will be available for all projects using UE4.

+

2.1.1 Windows

+

Browse to your UE4 Engine folder and unzip FMODStudio into the plugins directory.

+

UE4 Engine Tree

+

2.1.2 Mac

+

Use Finder to browse to your /Users/Shared/UnrealEngine/4.X/Engine directory and drop FMODStudio into the plugins directory.

+

UE4 Engine Tree OSX

+

If you have trouble getting the plugin working on a certain platform, then try putting FMODStudio in your game's Plugins directory instead of the engine.

+

Otherwise see the TroubleShooting section.

+
+

2.2 Updating/Upgrading the Integration

+

Start by replacing the old FMODStudio folder with the new version:

+ +

If you are updating to a newer minor version of FMOD no additional steps are required unless specified in the revision history.

+

Upgrading to a newer major version of FMOD is usually only recommend for projects at or near the beginning of development, because new major versions may introduce behavioral and breaking changes. If you are upgrading to a new major version, you will need to read over:

+ +

These will describe specific changes that might need to be made to your project.

+

2.3 Setting up your project

+

There are settings in both UE4 and FMOD Studio that need to be configured to link the two together.

+

If you have any trouble setting up your project, use the automatic method. These settings can always be changed later.

+

2.3.1 Automatically

+

You can run the "Help > FMOD Validate" option in the UE4 Help menu. It finds and fixes common issues, and can automatically set up your FMOD Studio project for you!

+

It will check the following:

+ +

2.3.2 Manually

+

From your FMOD Studio Project, select "Edit > Preferences..." ("FMOD Studio > Preferences..." on Mac) and select the build tab. Set your built banks output directory to a directory called "FMOD" under your game's content path.

+

Studio export path

+

Now select "File > Build". This will build bank files for events that have been assigned to banks. You should do this whenever project data has been modified.

+

2.3.3 Confirm the Banks are Built and Loaded

+

Now, open UE4 and look at the content browser. The plug-in defaults to looking in Content/FMOD directory for banks, so if you have exported banks there, assets should appear in the content window automatically. These represent items in your Studio project which update automatically when banks are built.

+

Content browser

+

For more information about banks, see the Banks page.

+
+

2.4 Compiling the plugin (Optional)

+

If you want to recompile the plugin, you can drop the plugin into a code project under your game's Plugins/FMODStudio directory, then re-generate the project. This might be useful if you want to use the plugin with a different version of the engine, such as a new pre-release of UE4. You can also do this if you want to get the plugin from github.

+

To recompile the plugin after downloading it from FMOD, do the following:

+ +

To compile the plugin after downloading the source from github, do the following

+ +

When rebuilding the plugin inside a code project, make sure you haven't also left it in the engine directory as well!

+
+

2.5 Programming Support

+

You are able to interface with the FMOD UE4 Integration and/or the FMOD C++ APIs.

+

2.5.1 Programming with the FMOD UE4 Integration

+

To reference FMOD Studio, the programmer will need to add the following to their .Build.cs file:

+ +

To add some FMOD Events to a class, do the following:

+ +

To play the event at a location, do the following:

+ +

You can also call UFMODBlueprintStatics::PlayEventAttached to create a new audio component attached to an actor, which will update the location automatically as the actor moves around the world.

+

2.5.2 Programming with the FMOD Studio C++ API

+

Programmers can interface with FMOD Studio directly by including "fmod_studio.hpp".

+

The Studio system can be obtained by GetStudioSystem. The function takes an enum because there may be a separate Studio system for auditioning in-editor and the proper system for play-in-editor. Normally, you will want to obtain the system with EFMODSystemContext.Runtime since that is the real system used in game.

+
if (IFMODStudioModule::IsAvailable())
+{
+    FMOD::Studio::System* StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime);
+    if (StudioSystem)
+    {
+        // Use it here
+    }
+}
+
+ + +

You can use a mixture of FMOD Studio wrapper and FMOD Studio API functions. For example:

+
// Call wrapper helper function to create and start an event instance
+FFMODEventInstance InstanceWrapper = UFMODBlueprintStatics::PlayEventAtLocation(ThisActor, MyEvent, FTransform(MyLocation), true);
+FMOD::Studio::EventInstance* Instance = InstanceWrapper.Instance;
+// Call into FMOD API directly
+Instance->setVolume(0.5f);
+// The instance handle will be cleaned up automatically when the sound finishes
+
+ + +

2.5.3 Further Programming Documentation

+

For further documentation, see:
+- Integration API Reference
+- FMOD API Reference.

+
+

2.6 Making sounds

+

The FMOD UE4 integration provides multiple ways in which Studio events can be played.

+

2.6.1 Ambient Sounds

+

The simplest way to play a looping ambience, is to drag and drop an event from the content browser into a scene viewport.

+

Drag sample

+

For example, try dragging the Game/FMOD/Events/Ambience/Forest event into a level. This will create an FMODAmbientSound. Hit Play to begin playing in editor, and you should immediately hear the Forest ambience.

+

Make sure you drag an event into the main viewport. Dragging a bank into main viewport won't do anything.

+

2.6.2 Playing Sounds From Blueprint

+

Another easy way to trigger a sound is via blueprint. You can use the play event at location function to quickly trigger any given event.

+

Blueprint Sample

+

In the example shown below, the Single_Explosion event is triggered at the location of the camera, every time the spacebar is pressed.

+

Blueprint simple playback

+

2.6.3 Other avenues

+

Keep in mind that more advanced control is also available from blueprints. There are graph functions for playing and stopping events, setting parameters, and loading or unloading banks. You can also add FMODAudioComponents to blueprints, allowing you attach audio directly to an object.

+
+

2.7 Listener

+

FMOD can support up to 8 listeners in game. The FMODListeners will follow the UE4 listeners which by default is attached to the camera, but we can move them by moving the UE4 listeners.

+

This is particularly useful for Third-Person and Top-Down style games.

+

2.7.1 Example

+

Using SetAudioListenerOverride allows you either attach the listener to a component or set the transform and rotation manually.

+

Listener Override

+
+

2.8 Working with Banks

+

Content created in FMOD Studio is exported into bank files. These bank files can then be loaded within Unreal using the FMOD UE4 integration. Banks can contain multiple events, which will implicitly pull in any audio assets they depend on.

+

Studio bank layout

+

Loading a bank will load all metadata, which contains information about all the events, parameters, and other data needed for all events assigned to that bank.

+

2.8.1 Studio Bank Output Directory

+

It is highly recommended that banks are exported to the Content directory of your project (see Deployment for more information). This can set via the built banks output directory setting in the FMOD Studio, which can be found in "Edit > Preferences..." on Windows (or "FMOD Studio > Preferences..." on Mac), under the Build tab.

+

Studio export path

+

When using the UE4 editor, as long as you match the FMOD Studio built banks output directory to the bank output directory specified in the Unreal project settings ("Edit > Project Settings > FMOD Studio"), the integration will find and load all bank content automatically.

+

Project Settings

+

2.8.2 Assigning Events to Banks

+

Before a new FMOD Studio event can be used in Unreal, it must first be assigned and built to a bank which can be loaded by Unreal. This can be done within FMOD Studio via the context menu of an event, or by dragging and dropping an event onto a bank.

+

Assign events to banks

+

Events are typically assigned to the same bank when they should be loaded and unloaded at the same time. For example, you might put all the events for the Goblin enemy within the Goblin bank.

+

Once you have assigned your events to a bank, you should rebuild your banks. This is done via the "File > Build..." menu item.

+

Build menu

+

2.8.3 Loading Banks within Unreal

+

The banks built in FMOD Studio are loaded in editor by the plugin, so that you can browse Events, Buses, Snapshots, etc. from the Studio Project. You are able to customize the way the banks are loaded in game, to suit your requirement, otherwise by default all the banks will be loaded at initialization.

+

In Editor

+

Within the Unreal editor, banks are loaded automatically as soon they are built. When correctly configured, any data within banks (e.g. events, mixer strips) should appear within the content browser under Game/FMOD by default.

+

Content view

+

In Game

+

The FMOD UE4 integration will load all banks by default. If you would like to manually control bank loading, this behavior can be disabled via the load all banks checkbox withing the FMOD Studio settings dialog ("Edit > Project Settings > FMOD Studio").

+

If using split banks, make sure to load the assets bank first and using load sample data on the metadata bank.

+

Banks can then manually be loaded and unloaded using the Load Bank and Unload Bank blueprint functions.

+

Banks blueprint

+
+

The Master Bank does not need to be loaded manually. It is automatically loaded at startup.

+
+
+

2.9 Sequencer Integration

+

FMOD is integrated into Unreal Engine 4's Sequencer.

+

2.9.1 Adding FMOD Events to a Level Sequence

+

Events can be added in one of two ways:

+
    +
  1. +

    Ambient sounds already placed in the level may be possessed by the level sequence. Add ambient sound actors to the sequence by clicking the Add actor button button in the Sequencer editor and choosing the ambient sound actor to add. Alternatively the actor can be dragged from the World Outliner into the Sequencer editor.
    +Possess actor
    +Possessed events will retain any state set by the level sequence when playback is complete. The level sequence's Restore State setting can be enabled to restore the state of possessed events (and any other actors possessed by the level sequence).

    +
  2. +
  3. +

    New events may be spawned from Sequencer. Sequencer can spawn FMOD events during playback. To create a spawned event drag an FMOD event from the Content Browser into the Sequencer editor.
    +Audio Table
    +Spawned events will not automatically play when spawned.

    +
  4. +
+

2.9.2 Adding Event Sub-Tracks

+

Once added to a sequence additional sub-tracks are required to do anything interesting. Sub-tracks can be added by clicking the Add track button button in the object's track. FMOD adds two new sub-track types for events in addition to the standard Sequencer sub-tracks.

+
    +
  1. Event control tracks allow events to be played and stopped.
  2. +
  3. Parameter tracks allow event parameters to be animated using Sequencer's keyframe animation tools.
  4. +
+

Event tracks

+

2.9.3 Event Control Sub-Track

+

Keyframes on the event control sub-track can be used to Play or Stop the event.

+

Control track

+

2.9.4 Parameter Track

+

An FMOD Event Parameter Track allows additional sub-tracks to be added for each parameter in the targeted FMOD event. Additional sub-tracks can be added by clicking the Add parameter button button in the FMOD Event Parameter Track.

+

Parameter track

+

Keyframes may be added to the parameter sub-tracks to control the value of the event parameter during playback of the level sequence. The Unreal Engine 4 curve editor may be used to create rich curves for FMOD event parameters.

+

Parameter keyframe track

+

The FMOD UE4 integration is unable to validate the range of parameter values set by Sequencer. The FMOD Engine will clamp any parameter value outside the range specified in FMOD Studio.

+
+

2.10 Occlusion

+

The FMOD UE4 integration supports the use of ray casts, to drive a specified parameter, for per instance occlusion of sounds.

+

2.10.1 Occlusion Settings

+

To enable occlusion ray casts for FMOD in your UE4 project, set the name of the parameter that will be used for occlusion in Studio.

+

Occlusion Settings

+

If an Event contains this parameter, the integration will set the parameter value any time the occlusion value changes.
+You can disable occlusion, per instance, and adjust the Trace Channel in the Component Details window.

+

Occlusion Settings

+
+

2.11 Reverb Zones

+

The FMOD UE4 integration supports the use of the standard UE4 audio volumes to trigger Studio's advanced snapshot system.

+

2.11.1 Snapshot Reverb Effects

+

The workflow to use reverb zones is to set up snapshots in FMOD Studio. Snapshots can modify global reverb effects, change any bus volume, and modify any DSP value. To help trigger snapshots for reverb effects, the integration exports all snapshots as reverb effects in the FMOD/Reverbs folder.

+

Reverb assets

+

These reverb effects can be dragged into audio volume Reverb Settings panel to be triggered when the audio listener enters the audio zone. It uses the same logic as the inbuilt UE4 audio system to determine which audio volume should be enabled, based on the priority of the volume.

+

Reverb settings

+

By default, snapshots apply instantly. To have a snapshot fade in, one of two things can be done. The first is by adding a AHDSR modulation to the intensity dial. The second way is to expose the intensity as a parameter, which allows it to be driven from the integration.

+

Reverb snapshot intensity

+

If the snapshot has its intensity exposed as a parameter, then the integration will ramp in the intensity over time based on the audio volume's Volume and Fade Time settings. If the snapshot does not expose its intensity as a parameter, then these values will not do anything.

+

2.11.2 Ambient Zone Settings

+

Another feature of the UE4 audio system is the ability to have an ambient effect applied to selected instances, based on both the listener position and the emitter position. Unlike the global reverb effects, this is something which is applied per instance.

+

Reverb ambient

+

Only some sounds should be affected by the ambient settings. To enable the ambient effect your Events will need two parameters, one for volume and one for LPF.
+You will need to add these parameter names to the integration settings.

+

Reverb user property

+

If an Event contains these parameters, the integration will set the parameter value any time the ambient values change.

+
+

Only FMOD audio components are affected by ambient zones. The simpler PlayEventAtLocation blueprint function to spawn one-shots does not apply ambient effects.

+
+
+

2.12 Callbacks

+

You can hook up event callbacks using blueprints. FMOD Audio component callbacks are only triggered if the enable callback option is ticked. This is because each component that triggers callbacks can incur a small CPU overhead, so it has to be turned on explicitly for the components you want to use.

+

Callback enable

+

Once enabled, then tempo beat callbacks and timeline callbacks can be added in blueprints. One way is via the Assign On Timeline Beat and Assign On Timeline Marker blueprint actions. For FMOD audio components used in blueprint actors, you can add events from the details window instead.

+

Callback blueprints

+

You can trigger various actions to occur on the beat or when a timeline hits a named marker. The event contains the same fields as FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES and FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES.

+

Callback example

+
+

2.13 Localization

+

Localized audio tables are a special kind of audio table with features that facilitate localization. We recommend using localized audio tables if your game supports multiple spoken languages, or if you intend to add support for additional languages in a future patch.

+

2.13.1 Setting up Audio Tables

+

Audio Tables are lists of audio files stored outside your FMOD Studio project's asset folder. You can use audio tables to control localized sounds. See the Dialogue and Localization section of the FMOD Studio Docs on how to set up an audio table in your project.

+

Audio Table

+

2.13.2 Loading Localized Banks

+

Audio tables are assigned to an associated bank, this means that in order to change the currently loaded audio table you will need to change the bank. Only one localized bank should be loaded at a time, otherwise just the first one to be loaded will be used.

+

You will need to define the different locale names and codes in the Localization Settings.

+

Localization Settings

+

Only the locale that is selected as default will have it's bank loaded at startup, if Load All Banks has been enabled in the settings.

+

To change the locale, you will need to:

+ +

Load locale bank

+
+

2.14 Programmer Sounds

+

FMOD Studio events can include programmer sound modules that are controlled at runtime. There are a few different ways of hooking them up.

+

2.14.1 Programmer Sounds via Audio Tables

+

With this approach, you don't need to do any programming at all!

+

Choosing the audio entry to play

+

Create an event with a programmer sound module on it. If the module has a name, then if nothing else is assigned then that sound will be used. For example, if the sound designer sets the module name as "Welcome", then the audio table entry "Welcome" will be used by default.

+

Studio programmer sound

+

To select at runtime what audio entry to use, set the programmer sound name field in the FMODAudioComponent.

+

Programmer asset name

+

Or you can assign the name via blueprint.

+

Programmer blueprint

+

The name has to be one of the audio asset entries of a loaded audio table, or it won't find the sound to play.

+

Be careful to set the name before you play the audio component. If the name is assigned after the event has started, it may not play the right sound.

+

2.14.2 Programmer Sounds by Path

+

With this approach, you can easily play any media file for your event.

+

You can set up a programmer sound to point directly to a file. To do this, set the FMOD audio component's programmer sound name to the path to the .wav or .ogg file that you want to load. If this path is relative, it will be looked up relative to the content directory.

+

Programmer file path

+

If you do this, you'll need to make sure that directory with the media files is added to directories to package in the packaging settings, otherwise it will work in the editor, but not when packaged into the final game.

+

2.14.3 Programmer Sounds via API

+

With this approach, you have the most flexibility for programmers.

+

If you are writing code, you can programmatically set the FMOD Sound to use by calling the FMOD audio component function SetProgrammerSound. Here is an example of setting the sound from code:

+
void AExampleGameMode::InitAudio(UFMODAudioComponent* AudioComponent)
+{
+    if (AudioComponent)
+    {
+        FMOD::Studio::System* System = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime);
+        FMOD::System* CoreSystem = nullptr;
+        System->getCoreSystem(&CoreSystem);
+
+        // Create sound in memory
+        static const int EXAMPLE_SOUND_LEN = 4096;
+        float ExampleData[EXAMPLE_SOUND_LEN];
+        for (int i=0; i<EXAMPLE_SOUND_LEN; ++i)
+        {
+            ExampleData[i] = FMath::Sin((float)i);
+        }
+
+        FMOD_CREATESOUNDEXINFO SoundInfo = {0};
+        SoundInfo.cbsize = sizeof(SoundInfo);
+        SoundInfo.format = FMOD_SOUND_FORMAT_PCMFLOAT;
+        SoundInfo.defaultfrequency = 12000;
+        SoundInfo.numchannels = 1;
+        SoundInfo.length = sizeof(float) * EXAMPLE_SOUND_LEN;
+
+        FMOD::Sound* Sound = nullptr;
+        if (CoreSystem->createSound(reinterpret_cast<const char*>(ExampleData), FMOD_OPENMEMORY | FMOD_OPENRAW | FMOD_LOOP_OFF, &SoundInfo, &Sound) == FMOD_OK)
+        {
+            AudioComponent->SetProgrammerSound(Sound);
+            // Note: Need to remember to release the sound *after* the audio component has finished using it.
+        }
+    }
+}
+
+ + +

2.14.4 Troubleshooting

+

Also, when setting the name to an audio table entry, you will need to make sure the audio table bank is already loaded before the event starts.

+

The FMOD audio component only supports a single programmer sound per event. If you want to have an event that has multiple programmer sounds, each one playing a different sound, then you'll need to create the event directly via the FMOD API and provide your own callback. You can look at how the FMOD audio component programmer sound callback works and use that as a base for your own class.

+
+

2.15 Deployment

+

These steps describe how to prepare your project for deployment. This is relevant to both the Launch option as well as the "File > Package Project" menu item.
+If any platforms require specific steps, they can be found in Platform Specifics.

+

2.15.1 Packaging banks

+

Banks need to be packaged and included in the game data. This can be done by selecting the "Edit > Project Settings..." menu item. Navigating to the Packaging section from the left hand pane, under the game heading, presents you with options for specifying directories that include extra assets. There are two ways of doing this:

+ +

We recommend using Directories to Package so that bank files are bundled into the package file automatically.

+

Project deployment

+

Each platform will look for its own type of banks in its own directory. Make sure you have added the platform to FMOD Studio project. The platforms are:

+ +

If you only have the Desktop banks and want to run on another platform, you can set force platform name to Desktop in the FMOD advanced settings.

+

2.15.2 Bank Files Inside Content Directory

+

The above directory name is relative to your Content directory. It is highly recommended that banks be placed within the content directory, as paths outside this directory will not deploy correctly to all platforms. For example:

+ +

This doesn't mean you need to put your whole Studio project inside the content directory. You can customize Studio by editing the Preferences and choosing a directory to export banks to, as described in the Working with Banks page.

+

The integration will load the platform bank files automatically. On PC it will load from FMOD/Desktop but on Android and IOS it will look for banks under FMOD/Mobile.

+

If you use FMOD as the directory to deploy and have multiple platform banks exported, then they will all be packaged up. To slim down your final package size, you may need to tweak the additional directories setting on a per platform basis. That way you only package FMOD/Mobile for Android, FMOD/Desktop for PC, FMOD/PS4 for PS4, etc.

+

2.15.3 Deploying FMOD audio plugins

+

You will need to make sure the plugins are deployed as well. Unreal deployment doesn't access to the settings information so you will need to create an extra file that lists the plugins you want to deploy.

+

Create a file "plugins.txt" in the FMODStudio/Binaries/Platform/ directory. The text file should contain the plugin names (just the name without file extension).

+

For example, to deploy fmod_gain.dll on Win64 builds, create a file FMODStudio/Binaries/Win64/plugins.txt with the following contents:

+
fmod_gain
+
+ + +

2.15.4 Loading blueprints before plugin load

+

One issue to be aware of is where blueprints are serialized from disk too early, before any plugins are loaded. This can occur from the following code, which is included by default in example C++ projects constructor:

+
static ConstructorHelpers::FClassFinder<APawn> PlayerPawnClassFinder(TEXT("/Game/FirstPersonCPP/Blueprints/FirstPersonCharacter"));
+
+ + +

The finder will serialize the first person character blueprint, but any FMOD references will fail to load since the FMOD plugin has not been created yet. To make sure that the FMOD plugin is loaded first, add the line of code above the class finder.

+
IFMODStudioModule::Get();
+
+ + +

2.15.5 Disabling Unreal Audio Device

+

By default FMOD Studio works side-by-side with the inbuilt Unreal audio device on the following platforms:

+ +

Any of the platforms listed below will not work with the inbuilt Unreal audio:

+ +

To disable the Unreal audio while leaving the FMOD Studio audio, the standard Unreal ini file setting can be used.

+

For each required platform, add a new file /Config/{Platform}/{Platform}Engine.ini with this section:

+
[Audio]
+AudioDeviceModuleName=
+AudioMixerModuleName=
+
+ + +

The audio device can be disabled for every platform that you want to ship with.

+

2.15.6 Enabling Live Update

+

The default permissions won't allow FMOD to set up a socket properly for live update. Uncheck the enable live update option in FMOD settings to avoid errors.

+

If you get a deployment error "resource.resw is in use by other process", go to the YourGame/Config/DefaultGame.ini and remove the following:

+
-CulturesToStage=en
++CulturesToStage=en
+
+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/welcome-whats-new-200.html b/Plugins/FMODStudio/Docs/welcome-whats-new-200.html new file mode 100644 index 0000000..f33c32b --- /dev/null +++ b/Plugins/FMODStudio/Docs/welcome-whats-new-200.html @@ -0,0 +1,70 @@ + + +Welcome to the FMOD UE4 Integration | New in FMOD UE4 Integration 2.00 + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

1. Welcome to the FMOD UE4 Integration | New in FMOD UE4 Integration 2.00

+ +

What's new in 2.00?

+

This section describes the major features introduced in the 2.00 release. See the Detailed Revision History for information regarding each patch release.

+

LowLevel API Renamed to Core API

+

The LowLevel API has been renamed to Core API:

+ +

Global Parameters

+

The Studio API now supports global parameters. These parameters are controlled via the System parameter API and have a single value that is shared between all instances. See the Global Parameters chapter of the FMOD API User Manual for more information.

+

New blueprint nodes can be found for getting and setting Global Parameters:

+

GetGlobalParameterByName SetGlobalParameterByName

+

New Parameter API

+

The Studio parameter API has been updated to support global parameters and provide a more robust fast path for setting parameter values frequently. There are a number of new, removed and renamed APIs, see the FMOD API User Manual for more information.

+

Sample Data Encryption

+

Bank sample data can now be encrypted using FMOD Studio. This implementation is an extension of the Core API FSB encryption feature.

+

See the Sample Data Encryption chapter of the FMOD API User Manual for more information.

+

To allow bank loading when used with the Studio API, set the key via FMOD_STUDIO_ADVANCEDSETTINGS::encryptionkey. Then if some banks are unencrypted you can use the FMOD_STUDIO_LOAD_BANK_UNENCRYPTED load flag to ignore the given key.

+

The FMOD UE4 Integration settings now have an added field for bank loading, Bank Encryption Key, which will set the FMOD_STUDIO_ADVANCEDSETTINGS::encryptionkey for you.

+

Encryption Key

+

Occlusion & Ambient Changes

+

The integration uses Parameters to pass Occlusion & Ambient information to Studio. The Parameters can be specified in the FMOD UE4 Integration settings:
+- Occlusion Parameter
+- Ambient Volume Parameter
+- Ambient LPF Parameter

+

Master Bank Default Name Changed

+

The default Master Bank name has changed from "Master Bank.bank" to "Master.bank". If you are upgrading from an older version or you are using a different name, this will need to be updated in the Master Bank Name field of the FMOD UE4 Settings so that the Integration can find it.

+

Master Bank Name

+ + + + + +
diff --git a/Plugins/FMODStudio/Docs/welcome.html b/Plugins/FMODStudio/Docs/welcome.html new file mode 100644 index 0000000..c4efdd8 --- /dev/null +++ b/Plugins/FMODStudio/Docs/welcome.html @@ -0,0 +1,53 @@ + + +Welcome to the FMOD UE4 Integration + + + + +
+
+

UE4 Integration 2.00

+ +
+
+

1. Welcome to the FMOD UE4 Integration

+

The FMOD UE4 Integration is a plugin that allows you to use the FMOD APIs and projects from FMOD Studio in your UE4 game.

+

1.1 Supported UE4 Versions

+

The integration is compatible with public release versions UE4.20 and newer.

+

1.2 Supported platforms

+

The integration supports:

+ +

1.3 Licensing

+

The integration itself is free, but you must have the appropriate FMOD License to release a title using FMOD Studio with UE4. For more information about licensing see the FMOD sales page.

+

1.4 What's New?

+

This section describes the major changes introduced in each new release. See the Detailed Revision History for information regarding each patch release.

+ + + + + +
diff --git a/Plugins/FMODStudio/FMODStudio.uplugin b/Plugins/FMODStudio/FMODStudio.uplugin new file mode 100644 index 0000000..f608f52 --- /dev/null +++ b/Plugins/FMODStudio/FMODStudio.uplugin @@ -0,0 +1,33 @@ +{ + "FileVersion" : 3, + + "FriendlyName" : "FMOD Studio Integration", + "Version" : 20011, + "VersionName" : "2.00.11", + "CreatedBy" : "Firelight Technologies", + "CreatedByURL" : "http://fmod.com", + "Description" : "FMOD Studio Integration.", + "Category" : "Audio", + "EnabledByDefault" : true, + + "Modules" : + [ + { + "Name": "FMODStudio", + "Type": "CookedOnly", + "LoadingPhase": "PreLoadingScreen" + }, + { + "Name": "FMODStudio", + "Type": "Runtime", + "LoadingPhase": "PreDefault" + }, + { + "Name" : "FMODStudioEditor", + "Type" : "Editor" + } + ], + + "CanContainContent" : true, + "Installed" : true +} \ No newline at end of file diff --git a/Plugins/FMODStudio/Resources/Icon128.png b/Plugins/FMODStudio/Resources/Icon128.png new file mode 100644 index 0000000..fcec53d Binary files /dev/null and b/Plugins/FMODStudio/Resources/Icon128.png differ diff --git a/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODAmbientSound.h b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODAmbientSound.h new file mode 100644 index 0000000..03a1b67 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODAmbientSound.h @@ -0,0 +1,25 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "FMODAudioComponent.h" +#include "FMODAmbientSound.generated.h" + +/** FMOD Ambient Sound. +*/ +UCLASS(AutoExpandCategories = Audio, ClassGroup = Sounds, hidecategories(Collision, Input)) +class FMODSTUDIO_API AFMODAmbientSound : public AActor +{ + GENERATED_UCLASS_BODY() +public: + /** The Audio component for this actor */ + UPROPERTY(Category = Sound, VisibleAnywhere, BlueprintReadOnly, meta = (ExposeFunctionCategories = "Sound")) + UFMODAudioComponent *AudioComponent; + +// Begin AActor interface. +#if WITH_EDITOR + virtual void CheckForErrors() override; + virtual bool GetReferencedContentObjects(TArray &Objects) const override; +#endif + // End AActor interface. +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODAnimNotifyPlay.h b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODAnimNotifyPlay.h new file mode 100644 index 0000000..b4a9d16 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODAnimNotifyPlay.h @@ -0,0 +1,31 @@ +#pragma once + +#include "Animation/AnimNotifies/AnimNotify.h" +#include "FMODEvent.h" +#include "FMODAnimNotifyPlay.generated.h" + +UCLASS(const, hidecategories = Object, collapsecategories, meta = (DisplayName = "Play FMOD Event")) +class FMODSTUDIO_API UFMODAnimNotifyPlay : public UAnimNotify +{ + GENERATED_BODY() + +public: + UFMODAnimNotifyPlay(); + + // Being UAnimNotify interface + virtual void Notify(USkeletalMeshComponent *MeshComp, UAnimSequenceBase *AnimSeq) override; + virtual FString GetNotifyName_Implementation() const override; + // End UAnimNotify interface + + // If this sound should follow its owner + UPROPERTY(EditAnywhere, Category = "FMOD Anim Notify") + uint32 bFollow : 1; + + // Socket or bone name to attach sound to + UPROPERTY(EditAnywhere, Category = "FMOD Anim Notify", meta = (EditCondition = "bFollow")) + FString AttachName; + + // Sound to Play + UPROPERTY(EditAnywhere, Category = "FMOD Anim Notify", BlueprintReadWrite) + TAssetPtr Event; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODAsset.h b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODAsset.h new file mode 100644 index 0000000..67f645f --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODAsset.h @@ -0,0 +1,32 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "Misc/Guid.h" +#include "CoreMinimal.h" +#include "FMODAsset.generated.h" + +/** + * FMOD Asset. + */ +UCLASS(BlueprintType) +class FMODSTUDIO_API UFMODAsset : public UObject +{ + GENERATED_UCLASS_BODY() + + /** The unique Guid, which matches the one exported from FMOD Studio */ + UPROPERTY() + FGuid AssetGuid; + + /** Whether to show in the content window */ + UPROPERTY() + bool bShowAsAsset; + + FString FileName; + + /** Force this to be an asset */ + virtual bool IsAsset() const override { return bShowAsAsset; } + + /** Get tags to show in content view */ + virtual void GetAssetRegistryTags(TArray &OutTags) const override; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODAudioComponent.h b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODAudioComponent.h new file mode 100644 index 0000000..57c3d1b --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODAudioComponent.h @@ -0,0 +1,372 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "Containers/Map.h" +#include "Runtime/Launch/Resources/Version.h" +#include "Sound/SoundAttenuation.h" +#include "AudioDevice.h" +#include "FMODStudioModule.h" +#include "FMODUtils.h" +#include "FMODAudioComponent.generated.h" + +// Event property +UENUM() +namespace EFMODEventProperty +{ +enum Type +{ + /* Priority to set on low-level channels created by this event instance (-1 to 256). */ + ChannelPriority, + /** Schedule delay to synchronized playback for multiple tracks in DSP clocks, or -1 for default. */ + ScheduleDelay, + /** Schedule look-ahead on the timeline in DSP clocks, or -1 for default. */ + ScheduleLookahead, + /** Override the event's 3D minimum distance, or -1 for default. */ + MinimumDistance, + /** Override the event's 3D maximum distance, or -1 for default. */ + MaximumDistance, + /** Number of options */ + Count +}; +} + + +/** Used to store callback info from FMOD thread to our event */ +struct FTimelineMarkerProperties +{ + FString Name; + int32 Position; +}; + +/** Used to store callback info from FMOD thread to our event */ +struct FTimelineBeatProperties +{ + int32 Bar; + int32 Beat; + int32 Position; + float Tempo; + int32 TimeSignatureUpper; + int32 TimeSignatureLower; +}; + +USTRUCT(BlueprintType) +struct FFMODAttenuationDetails +{ + GENERATED_USTRUCT_BODY() + + /** Should we use Attenuation set in Studio or be able to modify in Editor. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "FMOD|Attenuation") + uint32 bOverrideAttenuation : 1; + + /** Override the event's 3D minimum distance. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "FMOD|Attenuation", + meta = (ClampMin = "0.0", UIMin = "0.0", EditCondition = "bOverrideAttenuation")) + float MinimumDistance; + + /** Override the event's 3D maximum distance. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "FMOD|Attenuation", + meta = (ClampMin = "0.0", UIMin = "0.0", EditCondition = "bOverrideAttenuation")) + float MaximumDistance; + + FFMODAttenuationDetails() + : bOverrideAttenuation(false) + , MinimumDistance(1.0f) + , MaximumDistance(10.0f) + {} +}; + +USTRUCT(BlueprintType) +struct FFMODOcclusionDetails +{ + GENERATED_USTRUCT_BODY() + + /** Enable Occlusion Settings. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "FMOD|Occlusion") + bool bEnableOcclusion; + + /* Which trace channel to use for audio occlusion checks. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "FMOD|Occlusion", meta = (EditCondition = "bEnableOcclusion")) + TEnumAsByte OcclusionTraceChannel; + + /** Whether or not to enable complex geometry occlusion checks. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="FMOD|Occlusion", meta=(EditCondition = "bEnableOcclusion")) + bool bUseComplexCollisionForOcclusion; + + FFMODOcclusionDetails() + : bEnableOcclusion(false) + , OcclusionTraceChannel(ECC_Visibility) + , bUseComplexCollisionForOcclusion(false) + {} +}; + +/** called when an event stops, either because it played to completion or because a Stop() call turned it off early */ +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnEventStopped); +/** called when we reach a named marker on the timeline */ +DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnTimelineMarker, FString, Name, int32, Position); +/** called when we reach a beat on the timeline */ +DECLARE_DYNAMIC_MULTICAST_DELEGATE_SixParams( + FOnTimelineBeat, int32, Bar, int32, Beat, int32, Position, float, Tempo, int32, TimeSignatureUpper, int32, TimeSignatureLower); + +namespace FMOD +{ +class DSP; +class Sound; + +namespace Studio +{ +class EventDescription; +class EventInstance; +} +} + +struct FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES; +struct FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES; + +/** + * Plays FMOD Studio events. + */ +UCLASS(Blueprintable, ClassGroup = (Audio, Common), hidecategories = (Object, ActorComponent, Physics, Rendering, Mobility, LOD), + ShowCategories = Trigger, meta = (BlueprintSpawnableComponent)) +class FMODSTUDIO_API UFMODAudioComponent : public USceneComponent +{ + GENERATED_UCLASS_BODY() +public: + + /** The event asset to use for this sound. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = FMODAudio) + TAssetPtr Event; + + /** Event parameter cache. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, SimpleDisplay, Category = FMODAudio) + TMap ParameterCache; + bool bDefaultParameterValuesCached; + + /** Sound name used for programmer sound. Will look up the name in any loaded audio table. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = FMODAudio) + FString ProgrammerSoundName; + + /** Enable timeline callbacks for this sound, so that OnTimelineMarker and OnTimelineBeat can be used. */ + UPROPERTY(EditAnywhere, Category = FMODAudio) + uint32 bEnableTimelineCallbacks : 1; + + /** Stored properties to apply next time we create an instance. */ + float StoredProperties[EFMODEventProperty::Count]; + + /** Auto destroy this component on completion. */ + UPROPERTY() + uint32 bAutoDestroy : 1; + + /** Stop sound when owner is destroyed. */ + UPROPERTY() + uint32 bStopWhenOwnerDestroyed : 1; + + /** Whether we apply gain and low-pass based on audio zones. */ + uint32 bApplyAmbientVolumes : 1; + + /** Whether we apply gain and low-pass based on occlusion onto a parameter. */ + uint32 bApplyOcclusionParameter:1; + + /** Called when an event stops, either because it played to completion or because a Stop() call turned it off early. */ + UPROPERTY(BlueprintAssignable) + FOnEventStopped OnEventStopped; + + /** Called when we reach a named marker (if bEnableTimelineCallbacks is true). */ + UPROPERTY(BlueprintAssignable) + FOnTimelineMarker OnTimelineMarker; + + /** Called when we reach a beat of a tempo (if bEnableTimelineCallbacks is true). */ + UPROPERTY(BlueprintAssignable) + FOnTimelineBeat OnTimelineBeat; + + /** New Event to be used by the FMODAudioComponent. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void SetEvent(UFMODEvent *NewEvent); + + /** Start a sound playing on an audio component. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void Play(); + + /** Stop an audio component playing its sound cue, issue any delegates if needed. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void Stop(); + + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void Release(); + + /** Trigger a cue in an event. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void TriggerCue(); + + /** Return true if this component is currently playing an event. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + bool IsPlaying(); + + /** Sets the volume level. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void SetVolume(float volume); + + /** Sets the pitch multiplier. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void SetPitch(float pitch); + + /** Pause/Unpause an audio component. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void SetPaused(bool paused); + + /** Set a parameter of the Event. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void SetParameter(FName Name, float Value); + + /** Will be deprecated in FMOD 2.01, use `GetParameterValue(FName, float, float)` instead. + * Get parameter value from the Event. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + float GetParameter(FName Name); + + /** Get parameter value from the Event. + * @param Name - Name of parameter + * @param UserValue - Parameter value as set from the public API. + * @param FinalValue - Final combined parameter value. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void GetParameterValue(FName Name, float &UserValue, float &FinalValue); + + /** Set a property of the Event. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void SetProperty(EFMODEventProperty::Type Property, float Value); + + /** Get a property of the Event. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + float GetProperty(EFMODEventProperty::Type Property); + + /** Get the event length in milliseconds. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + int32 GetLength() const; + + /** Set the timeline position in milliseconds. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void SetTimelinePosition(int32 Time); + + /** Get the timeline position in milliseconds. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + int32 GetTimelinePosition(); + + /** Called when the event has finished stopping. */ + void OnPlaybackCompleted(); + + /** Update gain and low-pass based on interior volumes. */ + void UpdateInteriorVolumes(); + + /** Set the sound name to use for programmer sound. Will look up the name in any loaded audio table. */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Components") + void SetProgrammerSoundName(FString Value); + + /** Set a programmer sound to use for this audio component. Lifetime of sound must exceed that of the audio component. */ + void SetProgrammerSound(FMOD::Sound *Sound); + + /** FMOD Custom Attenuation Details. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = FMODAudio) + struct FFMODAttenuationDetails AttenuationDetails; + + /** FMOD Custom Occlusion Details. */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = FMODAudio) + struct FFMODOcclusionDetails OcclusionDetails; + + /** Update attenuation if we have it set. */ + void UpdateAttenuation(); + + /** Apply Volume and LPF into event. */ + void ApplyVolumeLPF(); + + /** Cache default event parameter values. */ + void CacheDefaultParameterValues(); + +public: + /** Internal play function which can play events in the editor. */ + void PlayInternal(EFMODSystemContext::Type Context); + + /** Actual Studio instance handle. */ + FMOD::Studio::EventInstance *StudioInstance; + + /** Timeline Marker callback. */ + void EventCallbackAddMarker(struct FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES *props); + + /** Timeline Beat callback. */ + void EventCallbackAddBeat(struct FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES *props); + + /** Programmer Sound Create callback. */ + void EventCallbackCreateProgrammerSound(struct FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES *props); + + /** Programmer Sound Destroy callback. */ + void EventCallbackDestroyProgrammerSound(struct FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES *props); + +// Begin UObject interface. +#if WITH_EDITOR + virtual void PostEditChangeProperty(FPropertyChangedEvent &e) override; +#endif // WITH_EDITOR + virtual void PostLoad() override; + virtual FString GetDetailedInfoInternal() const override; + // End UObject interface. + // Begin USceneComponent Interface + virtual void Activate(bool bReset = false) override; + virtual void Deactivate() override; + virtual void OnUpdateTransform(EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport = ETeleportType::None) override; + // End USceneComponent Interface + +private: +// Begin ActorComponent interface. +#if WITH_EDITORONLY_DATA + virtual void OnRegister() override; +#endif + virtual void OnUnregister() override; + virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; + virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override; +// End ActorComponent interface. + +#if WITH_EDITORONLY_DATA + void UpdateSpriteTexture(); +#endif + + /** Release any cached parameters then the Studio Instance. */ + void ReleaseEventCache(); + + /** Release the Studio Instance. */ + void ReleaseEventInstance(); + + /** Return a cached reference to the current IFMODStudioModule.*/ + IFMODStudioModule& GetStudioModule() + { + if (Module == nullptr) + { + Module = &IFMODStudioModule::Get(); + } + return *Module; + } + IFMODStudioModule* Module; + + // Settings for ambient volume effects. + double InteriorLastUpdateTime; + float SourceInteriorVolume; + float SourceInteriorLPF; + float CurrentInteriorVolume; + float CurrentInteriorLPF; + float AmbientVolume; + float AmbientLPF; + float LastVolume; + float LastLPF; + bool wasOccluded; + FMOD_STUDIO_PARAMETER_ID OcclusionID; + FMOD_STUDIO_PARAMETER_ID AmbientVolumeID; + FMOD_STUDIO_PARAMETER_ID AmbientLPFID; + + // Tempo and marker callbacks. + FCriticalSection CallbackLock; + TArray CallbackMarkerQueue; + TArray CallbackBeatQueue; + + // Direct assignment of programmer sound from other C++ code. + FMOD::Sound *ProgrammerSound; + bool NeedDestroyProgrammerSoundCallback; + int32 EventLength; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODBank.h b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODBank.h new file mode 100644 index 0000000..72f8fc6 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODBank.h @@ -0,0 +1,21 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "FMODAsset.h" +#include "FMODBank.generated.h" + +/** + * FMOD Bank Asset. + */ +UCLASS() +class FMODSTUDIO_API UFMODBank : public UFMODAsset +{ + GENERATED_UCLASS_BODY() + + /** Get tags to show in content view */ + virtual void GetAssetRegistryTags(TArray &OutTags) const override; + + /** Descriptive name */ + virtual FString GetDesc() override; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODBlueprintStatics.h b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODBlueprintStatics.h new file mode 100644 index 0000000..c59415f --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODBlueprintStatics.h @@ -0,0 +1,323 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "FMODAudioComponent.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Containers/UnrealString.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "FMODBlueprintStatics.generated.h" + +class UFMODAudioComponent; + +namespace FMOD +{ +namespace Studio +{ +class EventDescription; +class EventInstance; +} +} + +class UFMODAsset; +class UFMODEvent; +class USceneComponent; + +USTRUCT(BlueprintType) +struct FFMODEventInstance +{ + GENERATED_USTRUCT_BODY() + + FMOD::Studio::EventInstance *Instance; +}; + +UENUM(BlueprintType) +enum EFMOD_STUDIO_STOP_MODE +{ + ALLOWFADEOUT, + IMMEDIATE +}; + +UCLASS() +class FMODSTUDIO_API UFMODBlueprintStatics : public UBlueprintFunctionLibrary +{ + GENERATED_UCLASS_BODY() + + /** Plays an event. This returns an FMOD Event Instance. The sound does not travel with any actor. + * @param Event - event to play + * @param bAutoPlay - Start the event automatically. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", + meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", AdvancedDisplay = "2", bAutoPlay = "true", + UnsafeDuringActorConstruction = "true")) + static FFMODEventInstance PlayEvent2D(UObject *WorldContextObject, UFMODEvent *Event, bool bAutoPlay); + + /** Plays an event at the given location. This returns an FMOD Event Instance. The sound does not travel with any actor. + * @param Event - event to play + * @param Location - World position to play event at + * @param bAutoPlay - Start the event automatically. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", + meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", AdvancedDisplay = "2", bAutoPlay = "true", + UnsafeDuringActorConstruction = "true")) + static FFMODEventInstance PlayEventAtLocation(UObject *WorldContextObject, UFMODEvent *Event, const FTransform &Location, bool bAutoPlay); + + /** Plays an event attached to and following the specified component. + * @param Event - event to play + * @param AttachComponent - Component to attach to. + * @param AttachPointName - Optional named point within the AttachComponent to play the sound at + * @param Location - Depending on the value of Location Type this is either a relative offset from the attach component/point or an absolute world position that will be translated to a relative offset + * @param LocationType - Specifies whether Location is a relative offset or an absolute world position + * @param bStopWhenAttachedToDestroyed - Specifies whether the sound should stop playing when the owner of the attach to component is destroyed. + * @param bAutoPlay - Start the event automatically. + * @param bAutoDestroy - Automatically destroy the audio component when the sound is stopped. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", + meta = (AdvancedDisplay = "2", UnsafeDuringActorConstruction = "true", bAutoPlay = "true", bAutoDestroy = "true")) + static class UFMODAudioComponent *PlayEventAttached(UFMODEvent *Event, USceneComponent *AttachToComponent, FName AttachPointName, + FVector Location, EAttachLocation::Type LocationType, bool bStopWhenAttachedToDestroyed, bool bAutoPlay, bool bAutoDestroy); + + /** Find an asset by name. + * @param EventName - The asset name + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD") + static UFMODAsset *FindAssetByName(const FString &Name); + + /** Find an event by name. + * @param EventName - The event name + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD") + static UFMODEvent *FindEventByName(const FString &Name); + + /** Loads a bank. + * @param Bank - bank to load + * @param bBlocking - determines whether the bank will load synchronously + * @param bLoadSampleData - determines whether sample data will be preloaded immediately + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", meta = (UnsafeDuringActorConstruction = "true")) + static void LoadBank(class UFMODBank *Bank, bool bBlocking, bool bLoadSampleData); + + /** Unloads a bank. + * @param Bank - bank to unload + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", meta = (UnsafeDuringActorConstruction = "true")) + static void UnloadBank(class UFMODBank *Bank); + + /** Returns true if a bank is loaded. + * @param Bank - bank to query + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", meta = (UnsafeDuringActorConstruction = "true")) + static bool IsBankLoaded(class UFMODBank *Bank); + + /** Load bank sample data. + * @param Bank - bank to load sample data from + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", meta = (UnsafeDuringActorConstruction = "true")) + static void LoadBankSampleData(class UFMODBank *Bank); + + /** Unload bank sample data. + * @param Bank - bank to unload sample data from + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", meta = (UnsafeDuringActorConstruction = "true")) + static void UnloadBankSampleData(class UFMODBank *Bank); + + /** Load event sample data. This can be done ahead of time to avoid loading stalls. + * @param Event - event to load sample data from. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", + meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", UnsafeDuringActorConstruction = "true")) + static void LoadEventSampleData(UObject *WorldContextObject, UFMODEvent *Event); + + /** Unload event sample data. + * @param Event - event to load sample data from. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", + meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", UnsafeDuringActorConstruction = "true")) + static void UnloadEventSampleData(UObject *WorldContextObject, UFMODEvent *Event); + + /** Return a list of all event instances that are playing for this event. + Be careful using this function because it is possible to find and alter any playing sound, even ones owned by other audio components. + * @param Event - event to find instances from. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", + meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", UnsafeDuringActorConstruction = "true")) + static TArray FindEventInstances(UObject *WorldContextObject, UFMODEvent *Event); + + /** Set volume on a bus + * @param Bus - bus to use + * @param Volume - volume + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Bus", meta = (UnsafeDuringActorConstruction = "true")) + static void BusSetVolume(class UFMODBus *Bus, float Volume); + + /** Pause/Unpause all events going through this bus + * @param Bus - bus to use + * @param bPaused - paused + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Bus", meta = (UnsafeDuringActorConstruction = "true")) + static void BusSetPaused(class UFMODBus *Bus, bool bPaused); + + /** Mute/Unmute this bus + * @param Bus - bus to use + * @param bMute - mute + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Bus", meta = (UnsafeDuringActorConstruction = "true")) + static void BusSetMute(class UFMODBus *Bus, bool bMute); + + /** Stops all EventInstances routed into the bus + * @param Bus - bus to use + * @param stopMode - desired stop mode + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|Bus", meta = (UnsafeDuringActorConstruction = "true")) + static void BusStopAllEvents(class UFMODBus *Bus, EFMOD_STUDIO_STOP_MODE stopMode); + + /** Set volume on a VCA + * @param Vca - VCA to use + * @param Volume - volume + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|VCA", meta = (UnsafeDuringActorConstruction = "true")) + static void VCASetVolume(class UFMODVCA *Vca, float Volume); + + /** Set a global parameter from the System. + * @param Name - Name of parameter + * @param Value - Value of parameter + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", meta = (UnsafeDuringActorConstruction = "true")) + static void SetGlobalParameterByName(FName Name, float Value); + + /** Will be deprecated in FMOD 2.01, use `GetGlobalParameterValueByName(FName, float, float)` instead. + * Get a global parameter from the System. + * @param Name - Name of parameter + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", meta = (UnsafeDuringActorConstruction = "true")) + static float GetGlobalParameterByName(FName Name); + + /** Get a global parameter from the System. + * @param Name - Name of parameter + * @param UserValue - Parameter value as set from the public API. + * @param FinalValue - Final combined parameter value. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD", meta = (UnsafeDuringActorConstruction = "true")) + static void GetGlobalParameterValueByName(FName Name, float &UserValue, float &FinalValue); + + /** Returns whether this FMOD Event Instance is valid. The instance will be invalidated when the sound stops. + * @param EventInstance - Event instance + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static bool EventInstanceIsValid(FFMODEventInstance EventInstance); + + /** Set volume on an FMOD Event Instance. + * @param EventInstance - Event instance + * @param Value - Volume to set + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static void EventInstanceSetVolume(FFMODEventInstance EventInstance, float Volume); + + /** Set pitch on an FMOD Event Instance. + * @param EventInstance - Event instance + * @param Value - Volume to set + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static void EventInstanceSetPitch(FFMODEventInstance EventInstance, float Pitch); + + /** Pause/Unpause an FMOD Event Instance. + * @param EventInstance - Event instance + * @param Paused - Whether to pause or unpause + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static void EventInstanceSetPaused(FFMODEventInstance EventInstance, bool Paused); + + /** Set a parameter on an FMOD Event Instance. + * @param EventInstance - Event instance + * @param Name - Name of parameter + * @param Value - Value of parameter + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static void EventInstanceSetParameter(FFMODEventInstance EventInstance, FName Name, float Value); + + /** Will be deprecated in FMOD 2.01, use `EventInstanceGetParameterValue(FFMODEventInstance, FName, float, float)` instead. + * Get a parameter on an FMOD Event Instance. + * @param EventInstance - Event instance + * @param Name - Name of parameter + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static float EventInstanceGetParameter(FFMODEventInstance EventInstance, FName Name); + + /** Get a parameter on an FMOD Event Instance. + * @param EventInstance - Event instance + * @param Name - Name of parameter + * @param UserValue - Parameter value as set from the public API. + * @param FinalValue - Final combined parameter value. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static void EventInstanceGetParameterValue(FFMODEventInstance EventInstance, FName Name, float &UserValue, float &FinalValue); + /** Set an FMOD event property on an FMOD Event Instance. + * @param EventInstance - Event instance + * @param Property - Property to set + * @param Value - Value to set + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static void EventInstanceSetProperty(FFMODEventInstance EventInstance, EFMODEventProperty::Type Property, float Value); + + /** Plays an FMOD Event Instance. + * @param EventInstance - Event instance + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static void EventInstancePlay(FFMODEventInstance EventInstance); + + /** Stop an FMOD Event Instance. + * @param EventInstance - Event instance + * @param Release - Whether to release the Event Instance + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static void EventInstanceStop(FFMODEventInstance EventInstance, bool Release = false); + + /** Release an FMOD Event Instance. + * @param EventInstance - Event instance + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static void EventInstanceRelease(FFMODEventInstance EventInstance); + + /** Trigger a cue on an FMOD Event Instance. + * @param EventInstance - Event instance + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static void EventInstanceTriggerCue(FFMODEventInstance EventInstance); + + /** Set 3D attributes on a FMOD Event Instance. + * @param EventInstance - Event instance + * @param Location - Location to place event + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD|EventInstance", meta = (UnsafeDuringActorConstruction = "true")) + static void EventInstanceSetTransform(FFMODEventInstance EventInstance, const FTransform &Location); + + /** List all output device names. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD") + static TArray GetOutputDrivers(); + + /** Set current output device by name or part of the name. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD") + static void SetOutputDriverByName(FString NewDriverName); + + /** Set current output device by its index from GetOutputDrivers. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD") + static void SetOutputDriverByIndex(int NewDriverIndex); + + /** Suspend the FMOD mixer. Used when suspending the application. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD") + static void MixerSuspend(); + + /** Resume the FMOD mixer. Used when resuming the application. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD") + static void MixerResume(); + + /** Set the active locale for subsequent bank loads. + */ + UFUNCTION(BlueprintCallable, Category = "Audio|FMOD") + static void SetLocale(const FString& Locale); +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODBus.h b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODBus.h new file mode 100644 index 0000000..29ba4aa --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODBus.h @@ -0,0 +1,21 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "FMODAsset.h" +#include "FMODBus.generated.h" + +/** + * FMOD Bus Asset. + */ +UCLASS() +class FMODSTUDIO_API UFMODBus : public UFMODAsset +{ + GENERATED_UCLASS_BODY() + + /** Get tags to show in content view */ + virtual void GetAssetRegistryTags(TArray &OutTags) const override; + + /** Descriptive name */ + virtual FString GetDesc() override; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODEvent.h b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODEvent.h new file mode 100644 index 0000000..4216fca --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODEvent.h @@ -0,0 +1,26 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "FMODAsset.h" +#include "FMODEvent.generated.h" + +struct FMOD_STUDIO_PARAMETER_DESCRIPTION; + +/** + * FMOD Event Asset. + */ +UCLASS() +class FMODSTUDIO_API UFMODEvent : public UFMODAsset +{ + GENERATED_UCLASS_BODY() + + /** Get tags to show in content view */ + virtual void GetAssetRegistryTags(TArray &OutTags) const override; + + /** Descriptive name */ + virtual FString GetDesc() override; + + /** Get parameter descriptions for this event */ + void GetParameterDescriptions(TArray &Parameters) const; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODSettings.h b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODSettings.h new file mode 100644 index 0000000..1974b3c --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODSettings.h @@ -0,0 +1,329 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "UObject/Class.h" +#include "Engine/EngineTypes.h" +#include "GenericPlatform/GenericPlatform.h" +#include "FMODSettings.generated.h" + +class Paths; + +UENUM() +enum EFMODLogging +{ + LEVEL_NONE = 0, + LEVEL_ERROR = 1, + LEVEL_WARNING = 2, + LEVEL_LOG = 4, + TYPE_MEMORY = 100, + TYPE_FILE = 200, + TYPE_CODEC = 400, + TYPE_TRACE = 800, + DISPLAY_TIMESTAMPS = 10000, + DISPLAY_LINENUMBERS = 20000, + DISPLAY_THREAD = 40000 +}; + +UENUM() +namespace EFMODSpeakerMode +{ +enum Type +{ + // The speakers are stereo + Stereo, + // 5.1 speaker setup + Surround_5_1, + // 7.1 speaker setup + Surround_7_1 +}; +} + +USTRUCT() +struct FCustomPoolSizes +{ + GENERATED_USTRUCT_BODY() + + /** Default = 0 (Disabled) units in bytes*/ + UPROPERTY(config, EditAnywhere, Category = InitSettings, meta = (ClampMin = "0")) + int32 Desktop; + /** Default = 0 (Disabled) units in bytes*/ + UPROPERTY(config, EditAnywhere, Category = InitSettings, meta = (ClampMin = "0")) + int32 Mobile; + /** Default = 0 (Disabled) units in bytes*/ + UPROPERTY(config, EditAnywhere, Category = InitSettings, meta = (ClampMin = "0")) + int32 PS4; + /** Default = 0 (Disabled) units in bytes*/ + UPROPERTY(config, EditAnywhere, Category = InitSettings, meta = (ClampMin = "0")) + int32 Switch; + /** Default = 0 (Disabled) units in bytes*/ + UPROPERTY(config, EditAnywhere, Category = InitSettings, meta = (ClampMin = "0")) + int32 XboxOne; + + FCustomPoolSizes() + : Desktop(0) + , Mobile(0) + , PS4(0) + , Switch(0) + , XboxOne(0) + { + } +}; + +USTRUCT() +struct FFMODProjectLocale +{ + GENERATED_USTRUCT_BODY() + + /** + * Human readable locale name, displayed in Blueprints. + */ + UPROPERTY(config, EditAnywhere, Category = Localization) + FString LocaleName; + + /** + * Locale code. Must correspond to project locale codes in FMOD Studio project. + */ + UPROPERTY(config, EditAnywhere, Category = Localization) + FString LocaleCode; + + /** + * Default locale at startup. Only one locale should be marked as default. + */ + UPROPERTY(config, EditAnywhere, Category = Localization) + bool bDefault; +}; + +UCLASS(config = Engine, defaultconfig) +class FMODSTUDIO_API UFMODSettings : public UObject +{ + GENERATED_UCLASS_BODY() + +public: + /** + * Whether to load all banks at startup. + */ + UPROPERTY(config, EditAnywhere, Category = Basic) + bool bLoadAllBanks; + + /** + * Whether to load all bank sample data into memory at startup. + */ + UPROPERTY(config, EditAnywhere, Category = Basic) + bool bLoadAllSampleData; + + /** + * Enable live update in non-final builds. + */ + UPROPERTY(config, EditAnywhere, Category = Basic) + bool bEnableLiveUpdate; + + /** + * Enable live update in Editor for Auditioning. *Requires Restart* + */ + UPROPERTY(Config, EditAnywhere, Category = Basic) + bool bEnableEditorLiveUpdate; + + /** + * Path to find your studio bank output directory, relative to Content directory. + */ + UPROPERTY(config, EditAnywhere, Category = Basic, meta = (RelativeToGameContentDir)) + FDirectoryPath BankOutputDirectory; + + /** Project Output Format, should match the mode set up for the Studio project. */ + UPROPERTY(config, EditAnywhere, Category = Basic) + TEnumAsByte OutputFormat; + + /** + * Locales for localized banks. These should match the project locales configured in the FMOD Studio project. + */ + UPROPERTY(config, EditAnywhere, Category = Localization) + TArray Locales; + + /** + * Whether to enable vol0virtual, which means voices with low volume will automatically go virtual to save CPU. + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + bool bVol0Virtual; + + /** + * If vol0virtual is enabled, the signal level at which to make channels virtual. + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + float Vol0VirtualLevel; + + /** + * Sample rate to use, or 0 to match system rate. + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + int32 SampleRate; + + /** + * Whether to match hardware sample rate where reasonable (44.1kHz to 48kHz). + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + bool bMatchHardwareSampleRate; + + /** + * Number of actual software voices that can be used at once. + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + int32 RealChannelCount; + + /** + * Total number of voices available that can be either real or virtual. + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + int32 TotalChannelCount; + + /** + * DSP mixer buffer length (eg. 512, 1024) or 0 for system default. + * When changing the Buffer Length, Buffer Count also needs to be set. + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + int32 DSPBufferLength; + + /** + * DSP mixer buffer count (eg. 2, 4) or 0 for system default. + * When changing the Buffer Count, Buffer Length also needs to be set. + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + int32 DSPBufferCount; + + /** + * File buffer size in bytes (2048 by default). + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + int32 FileBufferSize; + + /** + * Studio update period in milliseconds, or 0 for default (which means 20ms). + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + int32 StudioUpdatePeriod; + + /** + * Output device to choose at system start up, or empty for default. + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + FString InitialOutputDriverName; + + /** + * Lock all mixer buses at startup, making sure they are created up front. + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + bool bLockAllBuses; + + /** + * Use specified memory pool size for platform, units in bytes. Disabled by default. + * FMOD may become unstable if the limit is exceeded! + */ + UPROPERTY(config, EditAnywhere, Category = InitSettings) + FCustomPoolSizes MemoryPoolSizes; + + /** + * Live update port to use, or 0 for default. + */ + UPROPERTY(config, EditAnywhere, Category = Advanced, meta = (EditCondition = "bEnableLiveUpdate")) + int32 LiveUpdatePort; + + /** + * Live update port to use while in editor for auditioning. *Requires Restart* + */ + UPROPERTY(config, EditAnywhere, Category = Advanced, meta = (EditCondition = "bEnableEditorLiveUpdate")) + int32 EditorLiveUpdatePort; + + /** + * Extra plugin files to load. + * The plugin files should sit alongside the FMOD dynamic libraries in the ThirdParty directory. + */ + UPROPERTY(config, EditAnywhere, Category = Advanced) + TArray PluginFiles; + + /** + * Directory for content to appear in content window. Be careful changing this! + */ + UPROPERTY(config, EditAnywhere, Category = Advanced) + FString ContentBrowserPrefix; + + /** + * Force platform directory name, or leave empty for automatic (Desktop/Mobile/PS4/XBoxOne) + */ + UPROPERTY(config, EditAnywhere, Category = Advanced) + FString ForcePlatformName; + + /** + * Name of master bank. The default in Studio is "Master Bank". + */ + UPROPERTY(config, EditAnywhere, Category = Advanced) + FString MasterBankName; + + /** + * Skip bank files of the given name. + * Can be used to load all banks except for a certain set, such as localization banks. + */ + UPROPERTY(config, EditAnywhere, Category = Advanced) + FString SkipLoadBankName; + + /* + * Specify the key for loading sounds from encrypted banks. + */ + UPROPERTY(config, EditAnywhere, Category = Advanced, meta = (DisplayName = "Encryption Key")) + FString StudioBankKey; + + /** + * Force wav writer output, for debugging only. Setting this will prevent normal sound output! + */ + UPROPERTY(config, EditAnywhere, Category = Advanced) + FString WavWriterPath; + + UPROPERTY(config, EditAnywhere, Category = Advanced) + TEnumAsByte LoggingLevel; + + /** + * Name of the parameter used in Studio to control Occlusion effects. + */ + UPROPERTY(config, EditAnywhere, Category = Advanced) + FString OcclusionParameter; + + /** + * Name of the parameter used in Studio to control Ambient volume. + */ + UPROPERTY(config, EditAnywhere, Category = Advanced) + FString AmbientVolumeParameter; + + /** + * Name of the parameter used in Studio to control Ambient LPF effects. + */ + UPROPERTY(config, EditAnywhere, Category = Advanced) + FString AmbientLPFParameter; + + /** Is the bank path set up . */ + bool IsBankPathSet() const { return !BankOutputDirectory.Path.IsEmpty(); } + + /** Get the full bank path. Uses the game's content directory as a base. */ + FString GetFullBankPath() const; + + /** Get the master bank filename. */ + FString GetMasterBankFilename() const; + + /** Get the master assets bank filename. */ + FString GetMasterAssetsBankFilename() const; + + /** Get the master strings bank filename. */ + FString GetMasterStringsBankFilename() const; + +#if WITH_EDITOR + /** Check the settings for any configuration issues. */ + enum EProblem + { + Okay, + BankPathNotSet, + AddedToUFS, + NotPackaged, + AddedToBoth + }; + + EProblem Check() const; +#endif // WITH_EDITOR +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODSnapshot.h b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODSnapshot.h new file mode 100644 index 0000000..5549a2b --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODSnapshot.h @@ -0,0 +1,18 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "FMODEvent.h" +#include "FMODSnapshot.generated.h" + +/** + * FMOD Snapshot Asset. + */ +UCLASS() +class FMODSTUDIO_API UFMODSnapshot : public UFMODEvent +{ + GENERATED_UCLASS_BODY() + + /** Descriptive name */ + virtual FString GetDesc() override; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODSnapshotReverb.h b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODSnapshotReverb.h new file mode 100644 index 0000000..b9ea392 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODSnapshotReverb.h @@ -0,0 +1,31 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "FMODAsset.h" +#include "Sound/ReverbEffect.h" +#include "FMODSnapshotReverb.generated.h" + +/** + * FMOD Event Asset. + */ +UCLASS() +class FMODSTUDIO_API UFMODSnapshotReverb : public UReverbEffect +{ + GENERATED_UCLASS_BODY() + + /** The unique Guid, which matches the one exported from FMOD Studio */ + UPROPERTY() + FGuid AssetGuid; + + /** Whether to show in the content window */ + UPROPERTY() + bool bShowAsAsset; + + /** Force this to be an asset */ + virtual bool IsAsset() const override { return bShowAsAsset; } + +#if WITH_EDITORONLY_DATA + virtual void PostEditChangeProperty(FPropertyChangedEvent &PropertyChangedEvent) override; +#endif // EDITORONLY_DATA +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODVCA.h b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODVCA.h new file mode 100644 index 0000000..1c858ab --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Classes/FMODVCA.h @@ -0,0 +1,21 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "FMODAsset.h" +#include "FMODVCA.generated.h" + +/** + * FMOD VCA Asset. + */ +UCLASS() +class FMODSTUDIO_API UFMODVCA : public UFMODAsset +{ + GENERATED_UCLASS_BODY() + + /** Get tags to show in content view */ + virtual void GetAssetRegistryTags(TArray &OutTags) const override; + + /** Descriptive name */ + virtual FString GetDesc() override; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/FMODStudio.Build.cs b/Plugins/FMODStudio/Source/FMODStudio/FMODStudio.Build.cs new file mode 100644 index 0000000..b807d8c --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/FMODStudio.Build.cs @@ -0,0 +1,295 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. +using UnrealBuildTool; +using System; +using System.IO; +using System.Collections.Generic; + +namespace UnrealBuildTool.Rules +{ + public class FMODStudio : ModuleRules + { + string LibRootDirectory { get { return Path.Combine(ModuleDirectory, @"..\..\Binaries\"); } } + protected virtual string FMODLibDir { get { return null; } } + + protected virtual string ConsoleLinkExt { get { return null; } } + protected virtual string ConsoleDllExt { get { return null; } } + protected virtual string ConsoleLibPrefix { get { return null; } } + + protected virtual bool ConsoleRuntimeDependencies { get { return true; } } + protected virtual bool ConsoleDelayLoad { get { return false; } } + + protected virtual string CopyThirdPartyPath { get { return null; } } + + public FMODStudio(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + PrivatePCHHeaderFile = "Private/FMODStudioPrivatePCH.h"; + + bUseUnity = false; + + PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Public/FMOD")); + PrivateIncludePaths.Add(Path.Combine(ModuleDirectory, "Classes")); + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "CoreUObject", + "Engine", + "Media", + "Projects" + } + ); + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "MovieScene", + "MovieSceneTracks" + } + ); + + if (Target.bBuildEditor == true) + { + PrivateDependencyModuleNames.Add("AssetRegistry"); + PrivateDependencyModuleNames.Add("UnrealEd"); + PrivateDependencyModuleNames.Add("Settings"); + } + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + } + ); + + string configName = ""; + + if (Target.Configuration != UnrealTargetConfiguration.Shipping) + { + configName = "L"; + PublicDefinitions.Add("FMODSTUDIO_LINK_LOGGING=1"); + } + else + { + configName = ""; + PublicDefinitions.Add("FMODSTUDIO_LINK_RELEASE=1"); + } + + string linkExtension = ""; + string dllExtension = ""; + string libPrefix = ""; + string libPath = FMODLibDir; + + bool bAddRuntimeDependencies = true; + bool bAddDelayLoad = false; + + if (libPath == null) + { + string platformName = Target.Platform.ToString(); + + libPath = System.IO.Path.Combine(LibRootDirectory, platformName); + + // Minimum UE version for Switch 4.15 + System.Console.WriteLine("Target Platform -- " + Target.Platform.ToString()); + if (Target.Platform == UnrealTargetPlatform.Switch) + { + linkExtension = ".a"; + dllExtension = ".a"; + libPrefix = "lib"; + bAddRuntimeDependencies = false; + } + else if (Target.Platform.ToString() == "UWP64") + { + linkExtension = ".lib"; + dllExtension = ".dll"; + bAddDelayLoad = true; + } + else if (Target.IsInPlatformGroup(UnrealPlatformGroup.Windows)) + { + linkExtension = "_vc.lib"; + dllExtension = ".dll"; + bAddDelayLoad = true; + } + else if (Target.Platform == UnrealTargetPlatform.Mac) + { + linkExtension = dllExtension = ".dylib"; + libPrefix = "lib"; + + libPath = System.IO.Path.Combine(ModuleDirectory, "../../Libs/Mac/"); + } + else if (Target.Platform == UnrealTargetPlatform.XboxOne) + { + linkExtension = "_vc.lib"; + dllExtension = ".dll"; + } + else if (Target.Platform == UnrealTargetPlatform.PS4) + { + linkExtension = "_stub.a"; + dllExtension = ".prx"; + libPrefix = "lib"; + bAddDelayLoad = true; + } + else if (Target.Platform == UnrealTargetPlatform.Android) + { + bAddRuntimeDependencies = false; // Don't use this system + linkExtension = dllExtension = ".so"; + libPrefix = "lib"; + } + else if (Target.Platform == UnrealTargetPlatform.IOS) + { + linkExtension = "_iphoneos.a"; + libPrefix = "lib"; + bAddRuntimeDependencies = false; + } + else if (Target.Platform == UnrealTargetPlatform.TVOS) + { + linkExtension = "_appletvos.a"; + libPrefix = "lib"; + bAddRuntimeDependencies = false; + } + else if (Target.Platform == UnrealTargetPlatform.Linux) + { + libPath = System.IO.Path.Combine(libPath, "x86_64"); + linkExtension = ".so"; + dllExtension = ".so"; + libPrefix = "lib"; + } + } + else + { + linkExtension = ConsoleLinkExt; + dllExtension = ConsoleDllExt; + libPrefix = ConsoleLibPrefix; + + bAddRuntimeDependencies = ConsoleRuntimeDependencies; + bAddDelayLoad = ConsoleDelayLoad; + } + + // Collapse the directory path, otherwise MacOS has issues with plugin paths. + libPath = Utils.CleanDirectorySeparators(libPath); + + string fmodLibName = System.String.Format("{0}fmod{1}{2}", libPrefix, configName, linkExtension); + string fmodStudioLibName = System.String.Format("{0}fmodstudio{1}{2}", libPrefix, configName, linkExtension); + + string fmodDllName = System.String.Format("{0}fmod{1}{2}", libPrefix, configName, dllExtension); + string fmodStudioDllName = System.String.Format("{0}fmodstudio{1}{2}", libPrefix, configName, dllExtension); + + string fmodLibPath = System.IO.Path.Combine(libPath, fmodLibName); + string fmodStudioLibPath = System.IO.Path.Combine(libPath, fmodStudioLibName); + + string fmodDllPath = System.IO.Path.Combine(libPath, fmodDllName); + string fmodStudioDllPath = System.IO.Path.Combine(libPath, fmodStudioDllName); + + System.Collections.Generic.List plugins = GetPlugins(libPath); + + if (Target.IsInPlatformGroup(UnrealPlatformGroup.Android)) + { + string[] archs = new string[] { "armeabi-v7a", "arm64-v8a", "x86_64" }; + foreach (string arch in archs) + { + string LibPath = System.IO.Path.Combine(libPath, arch); + PublicAdditionalLibraries.Add(System.String.Format("{0}/{1}", LibPath, fmodLibName)); + PublicAdditionalLibraries.Add(System.String.Format("{0}/{1}", LibPath, fmodStudioLibName)); + } + } + else + { + PublicAdditionalLibraries.Add(fmodLibPath); + PublicAdditionalLibraries.Add(fmodStudioLibPath); + } + + if (bAddRuntimeDependencies) + { + RuntimeDependencies.Add(fmodDllPath); + RuntimeDependencies.Add(fmodStudioDllPath); + foreach (string plugin in plugins) + { + string pluginPath = System.IO.Path.Combine(libPath, plugin + dllExtension); + System.Console.WriteLine("Adding reference to FMOD plugin: " + pluginPath); + RuntimeDependencies.Add(pluginPath); + } + } + + if (CopyThirdPartyPath != null) + { + string destPath = System.IO.Path.Combine(Target.UEThirdPartyBinariesDirectory, CopyThirdPartyPath); + System.IO.Directory.CreateDirectory(destPath); + + string fmodDllDest = System.IO.Path.Combine(destPath, fmodDllName); + string fmodStudioDllDest = System.IO.Path.Combine(destPath, fmodStudioDllName); + + CopyFile(fmodDllPath, fmodDllDest); + CopyFile(fmodStudioDllPath, fmodStudioDllDest); + } + + if (bAddDelayLoad) + { + PublicDelayLoadDLLs.AddRange( + new string[] { + fmodDllName, + fmodStudioDllName + } + ); + } + + if (Target.Platform == UnrealTargetPlatform.Android) + { + string APLName = System.String.Format("FMODStudio{0}_APL.xml", configName); + string RelAPLPath = Utils.MakePathRelativeTo(System.IO.Path.Combine(ModuleDirectory, APLName), Target.RelativeEnginePath); + System.Console.WriteLine("Adding {0}", RelAPLPath); + AdditionalPropertiesForReceipt.Add("AndroidPlugin", RelAPLPath); + foreach (string PluginName in System.IO.Directory.GetFiles(libPath)) + { + if (PluginName.EndsWith("_APL.xml", System.StringComparison.OrdinalIgnoreCase)) + { + string RelPluginPath = Utils.MakePathRelativeTo(PluginName, Target.RelativeEnginePath); + System.Console.WriteLine("Adding {0}", RelPluginPath); + AdditionalPropertiesForReceipt.Add("AndroidPlugin", RelPluginPath); + } + } + } + } + + private void CopyFile(string source, string dest) + { + //System.Console.WriteLine("Copying {0} to {1}", source, dest); + if (System.IO.File.Exists(dest)) + { + System.IO.File.SetAttributes(dest, System.IO.File.GetAttributes(dest) & ~System.IO.FileAttributes.ReadOnly); + } + try + { + System.IO.File.Copy(source, dest, true); + } + catch (System.Exception ex) + { + System.Console.WriteLine("Failed to copy file: {0}", ex.Message); + } + } + + private System.Collections.Generic.List GetPlugins(string BasePath) + { + System.Collections.Generic.List AllPlugins = new System.Collections.Generic.List(); + string PluginListName = System.IO.Path.Combine(BasePath, "plugins.txt"); + if (System.IO.File.Exists(PluginListName)) + { + try + { + foreach (string FullEntry in System.IO.File.ReadAllLines(PluginListName)) + { + string Entry = FullEntry.Trim(); + if (Entry.Length > 0) + { + AllPlugins.Add(Entry); + } + } + } + catch (System.Exception ex) + { + System.Console.WriteLine("Failed to read plugin list file: {0}", ex.Message); + } + } + return AllPlugins; + } + } +} \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudio/FMODStudioL_APL.xml b/Plugins/FMODStudio/Source/FMODStudio/FMODStudioL_APL.xml new file mode 100644 index 0000000..64a8a4a --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/FMODStudioL_APL.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + -keep class org.fmod.** { + *; + } + -dontwarn org.fmod.** + + + + + + + + + + + + + + + // Initialize FMOD Studio jar file + org.fmod.FMOD.init(this); + + + + + + + // Shutdown FMOD Studio jar file + org.fmod.FMOD.close(); + + + + + + + + + + diff --git a/Plugins/FMODStudio/Source/FMODStudio/FMODStudio_APL.xml b/Plugins/FMODStudio/Source/FMODStudio/FMODStudio_APL.xml new file mode 100644 index 0000000..3a01d4d --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/FMODStudio_APL.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + -keep class org.fmod.** { + *; + } + -dontwarn org.fmod.** + + + + + + + + + + + + + + + // Initialize FMOD Studio jar file + org.fmod.FMOD.init(this); + + + + + + + // Shutdown FMOD Studio jar file + org.fmod.FMOD.close(); + + + + + + + + + + diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAmbientSound.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAmbientSound.cpp new file mode 100644 index 0000000..5320d5d --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAmbientSound.cpp @@ -0,0 +1,69 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODAmbientSound.h" +#include "FMODEvent.h" +#include "Logging/MessageLog.h" +#include "Misc/UObjectToken.h" +#include "Misc/MapErrors.h" + +#define LOCTEXT_NAMESPACE "FMODAmbientSound" + +AFMODAmbientSound::AFMODAmbientSound(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ + AudioComponent = ObjectInitializer.CreateDefaultSubobject(this, TEXT("FMODAudioComponent0")); + + AudioComponent->bAutoActivate = true; + AudioComponent->bStopWhenOwnerDestroyed = true; + AudioComponent->Mobility = EComponentMobility::Movable; + + RootComponent = AudioComponent; + + SetReplicates(false); + SetHidden(true); + SetCanBeDamaged(true); +} + +#if WITH_EDITOR + +void AFMODAmbientSound::CheckForErrors(void) +{ + Super::CheckForErrors(); + + if (!AudioComponent) + { + FFormatNamedArguments Arguments; + Arguments.Add(TEXT("ActorName"), FText::FromString(GetName())); + FMessageLog("MapCheck") + .Warning() + ->AddToken(FUObjectToken::Create(this)) + ->AddToken(FTextToken::Create(FText::Format( + LOCTEXT("MapCheck_Message_AudioComponentNull", "{ActorName} : Ambient sound actor has NULL AudioComponent property - please delete"), + Arguments))) + ->AddToken(FMapErrorToken::Create(FMapErrors::AudioComponentNull)); + } + else if (AudioComponent->Event == NULL) + { + FFormatNamedArguments Arguments; + Arguments.Add(TEXT("ActorName"), FText::FromString(GetName())); + FMessageLog("MapCheck") + .Warning() + ->AddToken(FUObjectToken::Create(this)) + ->AddToken(FTextToken::Create( + FText::Format(LOCTEXT("MapCheck_Message_EventNull", "{ActorName} : Ambient sound actor has NULL Event property"), Arguments))) + ->AddToken(FMapErrorToken::Create(FMapErrors::SoundCueNull)); + } +} + +bool AFMODAmbientSound::GetReferencedContentObjects(TArray &Objects) const +{ + if (IsValid(AudioComponent) && AudioComponent->Event) + { + Objects.Add(AudioComponent->Event.Get()); + } + return true; +} + +#endif + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAnimNotifyPlay.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAnimNotifyPlay.cpp new file mode 100644 index 0000000..e066ed7 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAnimNotifyPlay.cpp @@ -0,0 +1,44 @@ + +#include "FMODAnimNotifyPlay.h" +#include "FMODBlueprintStatics.h" +#include "Components/SkeletalMeshComponent.h" +#include "Kismet/KismetSystemLibrary.h" + +UFMODAnimNotifyPlay::UFMODAnimNotifyPlay() + : Super() +{ + +#if WITH_EDITORONLY_DATA + NotifyColor = FColor(196, 142, 255, 255); +#endif // WITH_EDITORONLY_DATA +} + +void UFMODAnimNotifyPlay::Notify(USkeletalMeshComponent *MeshComp, UAnimSequenceBase *AnimSeq) +{ + if (Event.IsValid()) + { + if (bFollow) + { + // Play event attached + UFMODBlueprintStatics::PlayEventAttached( + Event.Get(), MeshComp, *AttachName, FVector(0, 0, 0), EAttachLocation::KeepRelativeOffset, false, true, true); + } + else + { + // Play event at location + UFMODBlueprintStatics::PlayEventAtLocation(MeshComp, Event.Get(), MeshComp->GetComponentTransform(), true); + } + } +} + +FString UFMODAnimNotifyPlay::GetNotifyName_Implementation() const +{ + if (Event.IsValid()) + { + return (Event.Get())->GetName(); + } + else + { + return Super::GetNotifyName_Implementation(); + } +} \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAsset.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAsset.cpp new file mode 100644 index 0000000..5cc5df2 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAsset.cpp @@ -0,0 +1,19 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODAsset.h" +#include "FMODStudioModule.h" + +static const TCHAR *FMODAssetTypeStrings[] = { TEXT("Bank"), TEXT("Event"), TEXT("VCA"), TEXT("Bus"), TEXT("Invalid") }; + +UFMODAsset::UFMODAsset(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +/** Get tags to show in content view */ +void UFMODAsset::GetAssetRegistryTags(TArray &OutTags) const +{ + Super::GetAssetRegistryTags(OutTags); + OutTags.Add( + UObject::FAssetRegistryTag("Guid", AssetGuid.ToString(EGuidFormats::DigitsWithHyphensInBraces), UObject::FAssetRegistryTag::TT_Alphabetical)); +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAssetTable.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAssetTable.cpp new file mode 100644 index 0000000..79e8c81 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAssetTable.cpp @@ -0,0 +1,480 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODAssetTable.h" +#include "FMODEvent.h" +#include "FMODSnapshot.h" +#include "FMODSnapshotReverb.h" +#include "FMODBank.h" +#include "FMODBus.h" +#include "FMODVCA.h" +#include "FMODUtils.h" +#include "FMODSettings.h" +#include "FMODFileCallbacks.h" +#include "FMODStudioPrivatePCH.h" +#include "fmod_studio.hpp" +#include "HAL/FileManager.h" +#include "Misc/Paths.h" +#include "UObject/Package.h" + +#if WITH_EDITOR +#include "AssetRegistryModule.h" +#endif + +FFMODAssetTable::FFMODAssetTable() + : StudioSystem(nullptr) +{ +} + +FFMODAssetTable::~FFMODAssetTable() +{ + Destroy(); +} + +void FFMODAssetTable::Create() +{ + Destroy(); + + // Create a sandbox system purely for loading and considering banks + verifyfmod(FMOD::Studio::System::create(&StudioSystem)); + FMOD::System *lowLevelSystem = nullptr; + verifyfmod(StudioSystem->getCoreSystem(&lowLevelSystem)); + verifyfmod(lowLevelSystem->setOutput(FMOD_OUTPUTTYPE_NOSOUND)); + AttachFMODFileSystem(lowLevelSystem, 2048); + verifyfmod( + StudioSystem->initialize(1, FMOD_STUDIO_INIT_ALLOW_MISSING_PLUGINS | FMOD_STUDIO_INIT_SYNCHRONOUS_UPDATE, FMOD_INIT_MIX_FROM_UPDATE, 0)); +} + +void FFMODAssetTable::Destroy() +{ + if (StudioSystem != nullptr) + { + verifyfmod(StudioSystem->release()); + } + StudioSystem = nullptr; +} + +UFMODAsset *FFMODAssetTable::FindByName(const FString &Name) const +{ + const TWeakObjectPtr *FoundAsset = FullNameLookup.Find(Name); + if (FoundAsset) + { + return FoundAsset->Get(); + } + return nullptr; +} + +void FFMODAssetTable::Refresh() +{ + if (StudioSystem == nullptr) + { + return; + } + + BuildBankPathLookup(); + + if (!MasterStringsBankPath.IsEmpty()) + { + const UFMODSettings &Settings = *GetDefault(); + FString StringPath = Settings.GetFullBankPath() / MasterStringsBankPath; + + UE_LOG(LogFMOD, Log, TEXT("Loading strings bank: %s"), *StringPath); + + FMOD::Studio::Bank *StudioStringBank; + FMOD_RESULT StringResult = StudioSystem->loadBankFile(TCHAR_TO_UTF8(*StringPath), FMOD_STUDIO_LOAD_BANK_NORMAL, &StudioStringBank); + if (StringResult == FMOD_OK) + { + TArray RawBuffer; + RawBuffer.SetNum(256); // Initial capacity + + int Count = 0; + verifyfmod(StudioStringBank->getStringCount(&Count)); + for (int StringIdx = 0; StringIdx < Count; ++StringIdx) + { + FMOD_RESULT Result; + FMOD::Studio::ID Guid = { 0 }; + while (true) + { + int ActualSize = 0; + Result = StudioStringBank->getStringInfo(StringIdx, &Guid, RawBuffer.GetData(), RawBuffer.Num(), &ActualSize); + if (Result == FMOD_ERR_TRUNCATED) + { + RawBuffer.SetNum(ActualSize); + } + else + { + break; + } + } + verifyfmod(Result); + FString AssetName(UTF8_TO_TCHAR(RawBuffer.GetData())); + FGuid AssetGuid = FMODUtils::ConvertGuid(Guid); + if (!AssetName.IsEmpty()) + { + AddAsset(AssetGuid, AssetName); + } + } + verifyfmod(StudioStringBank->unload()); + verifyfmod(StudioSystem->update()); + } + else + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to load strings bank: %s"), *StringPath); + } + } +} + +void FFMODAssetTable::AddAsset(const FGuid &AssetGuid, const FString &AssetFullName) +{ + FString AssetPath = AssetFullName; + FString AssetType = ""; + FString AssetFileName = "asset"; + + int DelimIndex; + if (AssetPath.FindChar(':', DelimIndex)) + { + AssetType = AssetPath.Left(DelimIndex); + AssetPath = AssetPath.Right(AssetPath.Len() - DelimIndex - 1); + } + + FString FormattedAssetType = ""; + UClass *AssetClass = UFMODAsset::StaticClass(); + if (AssetType.Equals(TEXT("event"))) + { + FormattedAssetType = TEXT("Events"); + AssetClass = UFMODEvent::StaticClass(); + } + else if (AssetType.Equals(TEXT("snapshot"))) + { + FormattedAssetType = TEXT("Snapshots"); + AssetClass = UFMODSnapshot::StaticClass(); + } + else if (AssetType.Equals(TEXT("bank"))) + { + FormattedAssetType = TEXT("Banks"); + AssetClass = UFMODBank::StaticClass(); + } + else if (AssetType.Equals(TEXT("bus"))) + { + FormattedAssetType = TEXT("Buses"); + AssetClass = UFMODBus::StaticClass(); + } + else if (AssetType.Equals(TEXT("vca"))) + { + FormattedAssetType = TEXT("VCAs"); + AssetClass = UFMODVCA::StaticClass(); + } + else if (AssetType.Equals(TEXT("parameter"))) + { + return; + } + else + { + UE_LOG(LogFMOD, Warning, TEXT("Unknown asset type: %s"), *AssetType); + } + + if (AssetPath.FindLastChar('/', DelimIndex)) + { + AssetFileName = AssetPath.Right(AssetPath.Len() - DelimIndex - 1); + AssetPath = AssetPath.Left(AssetPath.Len() - AssetFileName.Len() - 1); + } + else + { + // No path part, all name + AssetFileName = AssetPath; + AssetPath = TEXT(""); + } + + if (AssetFileName.IsEmpty() || AssetFileName.Contains(TEXT(".strings"))) + { + UE_LOG(LogFMOD, Log, TEXT("Skipping asset: %s"), *AssetFullName); + return; + } + + AssetPath = AssetPath.Replace(TEXT(" "), TEXT("_")); + FString AssetShortName = AssetFileName.Replace(TEXT(" "), TEXT("_")); + AssetShortName = AssetShortName.Replace(TEXT("."), TEXT("_")); + + const UFMODSettings &Settings = *GetDefault(); + + FString FolderPath = Settings.ContentBrowserPrefix; + FolderPath += FormattedAssetType; + FolderPath += AssetPath; + + FString AssetPackagePath = FolderPath + TEXT("/") + AssetShortName; + + FName AssetPackagePathName(*AssetPackagePath); + + TWeakObjectPtr &ExistingNameAsset = NameMap.FindOrAdd(AssetPackagePathName); + TWeakObjectPtr &ExistingGuidAsset = GuidMap.FindOrAdd(AssetGuid); + TWeakObjectPtr &ExistingFullNameLookupAsset = FullNameLookup.FindOrAdd(AssetFullName); + + UFMODAsset *AssetNameObject = ExistingNameAsset.Get(); + if (AssetNameObject == nullptr) + { + UE_LOG(LogFMOD, Log, TEXT("Constructing asset: %s"), *AssetPackagePath); + + EObjectFlags NewObjectFlags = RF_Standalone | RF_Public /* | RF_Transient */; + if (IsRunningDedicatedServer()) + { + NewObjectFlags |= RF_MarkAsRootSet; + } + + UPackage *NewPackage = CreatePackage(nullptr, *AssetPackagePath); + if (IsValid(NewPackage)) + { + if (!GEventDrivenLoaderEnabled) + { + NewPackage->SetPackageFlags(PKG_CompiledIn); + } + + AssetNameObject = NewObject(NewPackage, AssetClass, FName(*AssetShortName), NewObjectFlags); + AssetNameObject->AssetGuid = AssetGuid; + AssetNameObject->bShowAsAsset = true; + AssetNameObject->FileName = AssetFileName; + +#if WITH_EDITOR + FAssetRegistryModule &AssetRegistryModule = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry")); + AssetRegistryModule.Get().AddPath(*FolderPath); + FAssetRegistryModule::AssetCreated(AssetNameObject); +#endif + } + else + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to construct package for asset %s"), *AssetPackagePath); + } + + if (AssetClass == UFMODSnapshot::StaticClass()) + { + FString ReverbFolderPath = Settings.ContentBrowserPrefix; + ReverbFolderPath += TEXT("Reverbs"); + ReverbFolderPath += AssetPath; + + FString ReverbAssetPackagePath = ReverbFolderPath + TEXT("/") + AssetShortName; + + UPackage *ReverbPackage = CreatePackage(nullptr, *ReverbAssetPackagePath); + if (ReverbPackage) + { + if (!GEventDrivenLoaderEnabled) + { + ReverbPackage->SetPackageFlags(PKG_CompiledIn); + } + UFMODSnapshotReverb *AssetReverb = NewObject( + ReverbPackage, UFMODSnapshotReverb::StaticClass(), FName(*AssetShortName), NewObjectFlags); + AssetReverb->AssetGuid = AssetGuid; + AssetReverb->bShowAsAsset = true; + +#if WITH_EDITOR + FAssetRegistryModule &AssetRegistryModule = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry")); + AssetRegistryModule.Get().AddPath(*ReverbFolderPath); + FAssetRegistryModule::AssetCreated(AssetReverb); +#endif + } + } + } + + UFMODAsset *AssetGuidObject = ExistingGuidAsset.Get(); + if (IsValid(AssetGuidObject) && AssetGuidObject != AssetNameObject) + { + FString OldPath = AssetGuidObject->GetPathName(); + UE_LOG(LogFMOD, Log, TEXT("Hiding old asset '%s'"), *OldPath); + + // We had an asset with the same guid but it must have been renamed + // We just hide the old asset from the asset table + AssetGuidObject->bShowAsAsset = false; + +#if WITH_EDITOR + FAssetRegistryModule::AssetRenamed(AssetNameObject, OldPath); +#endif + } + + ExistingNameAsset = AssetNameObject; + ExistingGuidAsset = AssetNameObject; + ExistingFullNameLookupAsset = AssetNameObject; +} + +FString FFMODAssetTable::GetBankPathByGuid(const FGuid& Guid) const +{ + FString BankPath = ""; + const FString* File = nullptr; + const BankLocalizations* localizations = BankPathLookup.Find(Guid); + + if (localizations) + { + const FString* DefaultFile = nullptr; + + for (int i = 0; i < localizations->Num(); ++i) + { + if ((*localizations)[i].Locale.IsEmpty()) + { + DefaultFile = &(*localizations)[i].Path; + } + else if ((*localizations)[i].Locale == ActiveLocale) + { + File = &(*localizations)[i].Path; + break; + } + } + + if (!File) + { + File = DefaultFile; + } + } + + if (File) + { + BankPath = *File; + } + + return BankPath; +} + +FString FFMODAssetTable::GetBankPath(const UFMODBank &Bank) const +{ + FString BankPath = GetBankPathByGuid(Bank.AssetGuid); + + if (BankPath.IsEmpty()) + { + UE_LOG(LogFMOD, Warning, TEXT("Could not find disk file for bank %s"), *Bank.FileName); + } + + return BankPath; +} + +FString FFMODAssetTable::GetMasterBankPath() const +{ + return MasterBankPath; +} + +FString FFMODAssetTable::GetMasterStringsBankPath() const +{ + return MasterStringsBankPath; +} + +FString FFMODAssetTable::GetMasterAssetsBankPath() const +{ + return MasterAssetsBankPath; +} + +void FFMODAssetTable::SetLocale(const FString &LocaleCode) +{ + ActiveLocale = LocaleCode; +} + +void FFMODAssetTable::GetAllBankPaths(TArray &Paths, bool IncludeMasterBank) const +{ + const UFMODSettings &Settings = *GetDefault(); + + for (const TMap::ElementType& Localizations : BankPathLookup) + { + FString BankPath = GetBankPathByGuid(Localizations.Key); + bool Skip = false; + + if (BankPath.IsEmpty()) + { + // Never expect to be in here, but should skip empty paths + continue; + } + + if (!IncludeMasterBank) + { + Skip = (BankPath == Settings.GetMasterBankFilename() || BankPath == Settings.GetMasterAssetsBankFilename() || BankPath == Settings.GetMasterStringsBankFilename()); + } + + if (!Skip) + { + Paths.Push(Settings.GetFullBankPath() / BankPath); + } + } +} + + +void FFMODAssetTable::GetAllBankPathsFromDisk(const FString &BankDir, TArray &Paths) +{ + FString SearchDir = BankDir; + + TArray AllFiles; + IFileManager::Get().FindFilesRecursive(AllFiles, *SearchDir, TEXT("*.bank"), true, false, false); + + for (FString &CurFile : AllFiles) + { + Paths.Push(CurFile); + } +} + +void FFMODAssetTable::BuildBankPathLookup() +{ + const UFMODSettings &Settings = *GetDefault(); + + TArray BankPaths; + GetAllBankPathsFromDisk(Settings.GetFullBankPath(), BankPaths); + + BankPathLookup.Empty(BankPaths.Num()); + MasterBankPath.Empty(); + MasterStringsBankPath.Empty(); + MasterAssetsBankPath.Empty(); + + if (BankPaths.Num() == 0) + { + return; + } + + for (FString BankPath : BankPaths) + { + FMOD::Studio::Bank *Bank; + FMOD_RESULT result = StudioSystem->loadBankFile(TCHAR_TO_UTF8(*BankPath), FMOD_STUDIO_LOAD_BANK_NORMAL, &Bank); + FMOD_GUID GUID; + + if (result == FMOD_OK) + { + result = Bank->getID(&GUID); + Bank->unload(); + } + + if (result == FMOD_OK) + { + FString CurFilename = FPaths::GetCleanFilename(BankPath); + FString PathPart; + FString FilenamePart; + FString ExtensionPart; + FPaths::Split(BankPath, PathPart, FilenamePart, ExtensionPart); + BankPath = BankPath.RightChop(Settings.GetFullBankPath().Len() + 1); + + BankLocalization localization; + localization.Path = BankPath; + localization.Locale = ""; + + for (const FFMODProjectLocale& Locale : Settings.Locales) + { + if (FilenamePart.EndsWith(FString("_") + Locale.LocaleCode)) + { + localization.Locale = Locale.LocaleCode; + break; + } + } + + BankLocalizations& localizations = BankPathLookup.FindOrAdd(FMODUtils::ConvertGuid(GUID)); + localizations.Add(localization); + + if (MasterBankPath.IsEmpty() && CurFilename == Settings.GetMasterBankFilename()) + { + MasterBankPath = BankPath; + } + else if (MasterStringsBankPath.IsEmpty() && CurFilename == Settings.GetMasterStringsBankFilename()) + { + MasterStringsBankPath = BankPath; + } + else if (MasterAssetsBankPath.IsEmpty() && CurFilename == Settings.GetMasterAssetsBankFilename()) + { + MasterAssetsBankPath = BankPath; + } + } + + if (result != FMOD_OK) + { + UE_LOG(LogFMOD, Error, TEXT("Failed to register disk file for bank: %s"), *BankPath); + } + } + + StudioSystem->flushCommands(); +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAssetTable.h b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAssetTable.h new file mode 100644 index 0000000..2baa0f5 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAssetTable.h @@ -0,0 +1,62 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "FMODAsset.h" + +namespace FMOD +{ +namespace Studio +{ +class System; +} +} + +class UFMODBank; +struct FFMODBankDiskFileMap; + +class FFMODAssetTable +{ +public: + FFMODAssetTable(); + ~FFMODAssetTable(); + + void Create(); + void Destroy(); + + void Refresh(); + + UFMODAsset *FindByName(const FString &Name) const; + FString GetBankPath(const UFMODBank &Bank) const; + FString GetMasterBankPath() const; + FString GetMasterStringsBankPath() const; + FString GetMasterAssetsBankPath() const; + void SetLocale(const FString &LocaleCode); + void GetAllBankPaths(TArray &BankPaths, bool IncludeMasterBank) const; + +private: + void AddAsset(const FGuid &AssetGuid, const FString &AssetFullName); + void GetAllBankPathsFromDisk(const FString &BankDir, TArray &Paths); + void BuildBankPathLookup(); + FString GetBankPathByGuid(const FGuid& Guid) const; + +private: + FMOD::Studio::System *StudioSystem; + TMap> GuidMap; + TMap> NameMap; + TMap> FullNameLookup; + FString MasterBankPath; + FString MasterStringsBankPath; + FString MasterAssetsBankPath; + + struct BankLocalization + { + FString Locale; + FString Path; + }; + + typedef TArray BankLocalizations; + + TMap BankPathLookup; + FString ActiveLocale; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAudioComponent.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAudioComponent.cpp new file mode 100644 index 0000000..6092893 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODAudioComponent.cpp @@ -0,0 +1,909 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODAudioComponent.h" +#include "FMODStudioModule.h" +#include "FMODUtils.h" +#include "FMODEvent.h" +#include "FMODListener.h" +#include "FMODSettings.h" +#include "fmod_studio.hpp" +#include "Misc/App.h" +#include "Misc/Paths.h" +#include "Misc/ScopeLock.h" +#include "FMODStudioPrivatePCH.h" +#include "Components/BillboardComponent.h" +#if WITH_EDITORONLY_DATA +#include "Engine/Texture2D.h" +#endif + +UFMODAudioComponent::UFMODAudioComponent(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ + bAutoDestroy = false; + bAutoActivate = true; + bEnableTimelineCallbacks = false; // Default OFF for efficiency + bStopWhenOwnerDestroyed = true; + bNeverNeedsRenderUpdate = true; + bWantsOnUpdateTransform = true; +#if WITH_EDITORONLY_DATA + bVisualizeComponent = true; +#endif + bApplyOcclusionParameter = false; + bDefaultParameterValuesCached = false; + + PrimaryComponentTick.bCanEverTick = true; + PrimaryComponentTick.TickGroup = TG_PrePhysics; + PrimaryComponentTick.bStartWithTickEnabled = false; + + StudioInstance = nullptr; + ProgrammerSound = nullptr; + + LastLPF = MAX_FILTER_FREQUENCY; + LastVolume = 1.0f; + Module = nullptr; + wasOccluded = false; + + for (int i = 0; i < EFMODEventProperty::Count; ++i) + { + StoredProperties[i] = -1.0f; + } + + NeedDestroyProgrammerSoundCallback = false; +} + +FString UFMODAudioComponent::GetDetailedInfoInternal(void) const +{ + FString Result; + + if (Event) + { + Result = Event->GetPathName(NULL); + } + else + { + Result = TEXT("No_Event"); + } + + return Result; +} + +#if WITH_EDITORONLY_DATA +void UFMODAudioComponent::OnRegister() +{ + Super::OnRegister(); + + if (!bDefaultParameterValuesCached) + CacheDefaultParameterValues(); + + UpdateSpriteTexture(); +} + +void UFMODAudioComponent::UpdateSpriteTexture() +{ + if (SpriteComponent) + { + if (bAutoActivate) + { + SpriteComponent->SetSprite( + LoadObject(NULL, TEXT("/Engine/EditorResources/AudioIcons/S_AudioComponent_AutoActivate.S_AudioComponent_AutoActivate"))); + } + else + { + SpriteComponent->SetSprite(LoadObject(NULL, TEXT("/Engine/EditorResources/AudioIcons/S_AudioComponent.S_AudioComponent"))); + } + } +} +#endif + +#if WITH_EDITOR +void UFMODAudioComponent::PostEditChangeProperty(FPropertyChangedEvent &e) +{ + if (IsPlaying()) + { + Stop(); + Play(); + } + + FName PropertyName = (e.Property != NULL) ? e.Property->GetFName() : NAME_None; + if (PropertyName == GET_MEMBER_NAME_CHECKED(UFMODAudioComponent, Event) || + (PropertyName == GET_MEMBER_NAME_CHECKED(UFMODAudioComponent, ParameterCache) && ParameterCache.Num() == 0)) + { + ParameterCache.Empty(); + bDefaultParameterValuesCached = false; + } + +#if WITH_EDITORONLY_DATA + UpdateSpriteTexture(); +#endif + + Super::PostEditChangeProperty(e); +} +#endif // WITH_EDITOR + +void UFMODAudioComponent::OnUpdateTransform(EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport) +{ + Super::OnUpdateTransform(UpdateTransformFlags, Teleport); + if (StudioInstance) + { + FMOD_3D_ATTRIBUTES attr = { { 0 } }; + attr.position = FMODUtils::ConvertWorldVector(GetComponentTransform().GetLocation()); + attr.up = FMODUtils::ConvertUnitVector(GetComponentTransform().GetUnitAxis(EAxis::Z)); + attr.forward = FMODUtils::ConvertUnitVector(GetComponentTransform().GetUnitAxis(EAxis::X)); + attr.velocity = FMODUtils::ConvertWorldVector(GetOwner()->GetVelocity()); + + StudioInstance->set3DAttributes(&attr); + + UpdateInteriorVolumes(); + UpdateAttenuation(); + ApplyVolumeLPF(); + } +} + +// Taken mostly from ActiveSound.cpp +void UFMODAudioComponent::UpdateInteriorVolumes() +{ + if (!GetOwner()) + return; // May not have owner when previewing animations + + if (!bApplyAmbientVolumes) + return; + + // Result of the ambient calculations to apply to the instance + float NewAmbientVolumeMultiplier = 1.0f; + float NewAmbientHighFrequencyGain = 1.0f; + + FInteriorSettings *Ambient = + (FInteriorSettings *)alloca(sizeof(FInteriorSettings)); // FinteriorSetting::FInteriorSettings() isn't exposed (possible UE4 bug???) + const FVector &Location = GetOwner()->GetTransform().GetTranslation(); + AAudioVolume *AudioVolume = GetWorld()->GetAudioSettings(Location, NULL, Ambient); + + const FFMODListener &Listener = GetStudioModule().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 = FMath::Lerp(SourceInteriorVolume, 1.0f, Listener.InteriorVolumeInterp); + NewAmbientVolumeMultiplier = CurrentInteriorVolume; + + CurrentInteriorLPF = FMath::Lerp(SourceInteriorLPF, MAX_FILTER_FREQUENCY, Listener.InteriorLPFInterp); + NewAmbientHighFrequencyGain = 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 = FMath::Lerp(SourceInteriorVolume, Listener.InteriorSettings.ExteriorVolume, Listener.ExteriorVolumeInterp); + NewAmbientVolumeMultiplier = CurrentInteriorVolume; + + CurrentInteriorLPF = FMath::Lerp(SourceInteriorLPF, Listener.InteriorSettings.ExteriorLPF, Listener.ExteriorLPFInterp); + NewAmbientHighFrequencyGain = 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 = FMath::Lerp(SourceInteriorVolume, Ambient->InteriorVolume, Listener.InteriorVolumeInterp); + CurrentInteriorVolume *= FMath::Lerp(SourceInteriorVolume, Listener.InteriorSettings.ExteriorVolume, Listener.ExteriorVolumeInterp); + NewAmbientVolumeMultiplier = CurrentInteriorVolume; + + + float AmbientLPFValue = FMath::Lerp(SourceInteriorLPF, Ambient->InteriorLPF, Listener.InteriorLPFInterp); + float ListenerLPFValue = FMath::Lerp(SourceInteriorLPF, Listener.InteriorSettings.ExteriorLPF, Listener.ExteriorLPFInterp); + + // The current interior LPF value is the less of the LPF due to ambient zone and LPF due to listener settings + if (AmbientLPFValue < ListenerLPFValue) + { + CurrentInteriorLPF = AmbientLPFValue; + NewAmbientHighFrequencyGain = AmbientLPFValue; + } + else + { + CurrentInteriorLPF = ListenerLPFValue; + NewAmbientHighFrequencyGain = ListenerLPFValue; + } + + //UE_LOG(LogFMOD, Verbose, TEXT( "Ambient in diff volume, ambient inside. Volume *= %g LPF *= %g" ), CurrentInteriorVolume, CurrentInteriorLPF); + } + } + + AmbientVolume = NewAmbientVolumeMultiplier; + AmbientLPF = NewAmbientHighFrequencyGain; +} + +void UFMODAudioComponent::UpdateAttenuation() +{ + if (!GetOwner()) + return; // May not have owner when previewing animations + + if (!AttenuationDetails.bOverrideAttenuation && !OcclusionDetails.bEnableOcclusion) + { + return; + } + + if (AttenuationDetails.bOverrideAttenuation) + { + SetProperty(EFMODEventProperty::MinimumDistance, AttenuationDetails.MinimumDistance); + SetProperty(EFMODEventProperty::MaximumDistance, AttenuationDetails.MaximumDistance); + } + + // Use occlusion part of settings + if (OcclusionDetails.bEnableOcclusion && bApplyOcclusionParameter) + { + static FName NAME_SoundOcclusion = FName(TEXT("SoundOcclusion")); + FCollisionQueryParams Params(NAME_SoundOcclusion, OcclusionDetails.bUseComplexCollisionForOcclusion, GetOwner()); + + const FVector &Location = GetOwner()->GetTransform().GetTranslation(); + const FFMODListener &Listener = GetStudioModule().GetNearestListener(Location); + + bool bIsOccluded = GWorld->LineTraceTestByChannel(Location, Listener.Transform.GetLocation(), OcclusionDetails.OcclusionTraceChannel, Params); + + if (bIsOccluded != wasOccluded) + { + StudioInstance->setParameterByID(OcclusionID, bIsOccluded ? 1.0f : 0.0f); + wasOccluded = bIsOccluded; + } + } + else + { + wasOccluded = false; + } +} + +void UFMODAudioComponent::ApplyVolumeLPF() +{ + if (bApplyAmbientVolumes) + { + float CurVolume = AmbientVolume; + if (CurVolume != LastVolume) + { + StudioInstance->setParameterByID(AmbientVolumeID, CurVolume); + LastVolume = CurVolume; + } + + float CurLPF = AmbientLPF; + if (CurLPF != LastLPF) + { + StudioInstance->setParameterByID(AmbientLPFID, CurLPF); + LastLPF = CurLPF; + } + } + else + { + LastLPF = MAX_FILTER_FREQUENCY; + LastVolume = 1.0f; + } +} + +void UFMODAudioComponent::CacheDefaultParameterValues() +{ + if (Event) + { + const UFMODSettings &Settings = *GetDefault(); + TArray ParameterDescriptions; + Event->GetParameterDescriptions(ParameterDescriptions); + for (const FMOD_STUDIO_PARAMETER_DESCRIPTION &ParameterDescription : ParameterDescriptions) + { + if (!ParameterCache.Find(ParameterDescription.name) && + (ParameterDescription.type == FMOD_STUDIO_PARAMETER_GAME_CONTROLLED) && + ParameterDescription.name != Settings.OcclusionParameter && + ParameterDescription.name != Settings.AmbientVolumeParameter && + ParameterDescription.name != Settings.AmbientLPFParameter) + { + ParameterCache.Add(ParameterDescription.name, ParameterDescription.defaultvalue); + } + } + } + bDefaultParameterValuesCached = true; +} + +void UFMODAudioComponent::OnUnregister() +{ + // Route OnUnregister event. + Super::OnUnregister(); +} + +void UFMODAudioComponent::EndPlay(const EEndPlayReason::Type EndPlayReason) +{ + bool shouldStop = false; + + switch (EndPlayReason) + { + case EEndPlayReason::Destroyed: + case EEndPlayReason::RemovedFromWorld: + { + AActor *Owner = GetOwner(); + if (!Owner || bStopWhenOwnerDestroyed) + shouldStop = true; + break; + } + case EEndPlayReason::EndPlayInEditor: + case EEndPlayReason::LevelTransition: + case EEndPlayReason::Quit: + { + shouldStop = true; + break; + } + } + + if (shouldStop) + { + Stop(); + OnEventStopped.Broadcast(); + } + Release(); +} + +void UFMODAudioComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + if (IsActive()) + { + if (GetStudioModule().HasListenerMoved()) + { + UpdateInteriorVolumes(); + UpdateAttenuation(); + ApplyVolumeLPF(); + } + + if (bEnableTimelineCallbacks) + { + TArray LocalMarkerQueue; + TArray LocalBeatQueue; + { + FScopeLock Lock(&CallbackLock); + Swap(LocalMarkerQueue, CallbackMarkerQueue); + Swap(LocalBeatQueue, CallbackBeatQueue); + } + + for (const FTimelineMarkerProperties &EachProps : LocalMarkerQueue) + { + OnTimelineMarker.Broadcast(EachProps.Name, EachProps.Position); + } + for (const FTimelineBeatProperties &EachProps : LocalBeatQueue) + { + OnTimelineBeat.Broadcast( + EachProps.Bar, EachProps.Beat, EachProps.Position, EachProps.Tempo, EachProps.TimeSignatureUpper, EachProps.TimeSignatureLower); + } + } + + FMOD_STUDIO_PLAYBACK_STATE state = FMOD_STUDIO_PLAYBACK_STOPPED; + StudioInstance->getPlaybackState(&state); + if (state == FMOD_STUDIO_PLAYBACK_STOPPED) + { + OnPlaybackCompleted(); + } + } +} + +void UFMODAudioComponent::SetEvent(UFMODEvent *NewEvent) +{ + const bool bPlay = IsPlaying(); + + Stop(); + + if (Event != NewEvent) + { + ReleaseEventCache(); + Event = NewEvent; + } + + if (bPlay) + { + Play(); + } +} + +void UFMODAudioComponent::PostLoad() +{ + Super::PostLoad(); +} + +void UFMODAudioComponent::Activate(bool bReset) +{ + Super::Activate(bReset); + if (bReset || ShouldActivate() == true) + { + Play(); + } +} + +void UFMODAudioComponent::Deactivate() +{ + if (ShouldActivate() == false) + { + Stop(); + } + Super::Deactivate(); +} + +FMOD_RESULT F_CALLBACK UFMODAudioComponent_EventCallback(FMOD_STUDIO_EVENT_CALLBACK_TYPE type, FMOD_STUDIO_EVENTINSTANCE *event, void *parameters) +{ + UFMODAudioComponent *Component = nullptr; + FMOD::Studio::EventInstance *Instance = (FMOD::Studio::EventInstance *)event; + if (Instance->getUserData((void **)&Component) == FMOD_OK && IsValid(Component)) + { + if (type == FMOD_STUDIO_EVENT_CALLBACK_TIMELINE_MARKER && Component->bEnableTimelineCallbacks) + { + Component->EventCallbackAddMarker((FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES *)parameters); + } + else if (type == FMOD_STUDIO_EVENT_CALLBACK_TIMELINE_BEAT && Component->bEnableTimelineCallbacks) + { + Component->EventCallbackAddBeat((FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES *)parameters); + } + else if (type == FMOD_STUDIO_EVENT_CALLBACK_CREATE_PROGRAMMER_SOUND) + { + Component->EventCallbackCreateProgrammerSound((FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES *)parameters); + } + else if (type == FMOD_STUDIO_EVENT_CALLBACK_DESTROY_PROGRAMMER_SOUND) + { + Component->EventCallbackDestroyProgrammerSound((FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES *)parameters); + } + } + return FMOD_OK; +} + +void UFMODAudioComponent_ReleaseProgrammerSound(FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES *props) +{ + if (props->sound) + { + UE_LOG(LogFMOD, Verbose, TEXT("Destroying programmer sound")); + FMOD_RESULT Result = ((FMOD::Sound *)props->sound)->release(); + verifyfmod(Result); + } +} + +FMOD_RESULT F_CALLBACK UFMODAudioComponent_EventCallbackDestroyProgrammerSound(FMOD_STUDIO_EVENT_CALLBACK_TYPE type, FMOD_STUDIO_EVENTINSTANCE *event, void *parameters) +{ + UFMODAudioComponent_ReleaseProgrammerSound((FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES *)parameters); + return FMOD_OK; +} + +void UFMODAudioComponent::EventCallbackAddMarker(FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES *props) +{ + FScopeLock Lock(&CallbackLock); + FTimelineMarkerProperties info; + info.Name = props->name; + info.Position = props->position; + CallbackMarkerQueue.Push(info); +} + +void UFMODAudioComponent::EventCallbackAddBeat(FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES *props) +{ + FScopeLock Lock(&CallbackLock); + FTimelineBeatProperties info; + info.Bar = props->bar; + info.Beat = props->beat; + info.Position = props->position; + info.Tempo = props->tempo; + info.TimeSignatureUpper = props->timesignatureupper; + info.TimeSignatureLower = props->timesignaturelower; + CallbackBeatQueue.Push(info); +} + +void UFMODAudioComponent::EventCallbackCreateProgrammerSound(FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES *props) +{ + // Make sure name isn't being changed as we are reading it + FString ProgrammerSoundNameCopy; + { + FScopeLock Lock(&CallbackLock); + ProgrammerSoundNameCopy = ProgrammerSoundName; + } + + if (ProgrammerSound) + { + props->sound = (FMOD_SOUND *)ProgrammerSound; + props->subsoundIndex = -1; + } + else if (ProgrammerSoundNameCopy.Len() || strlen(props->name) != 0) + { + FMOD::Studio::System *System = GetStudioModule().GetStudioSystem(EFMODSystemContext::Max); + FMOD::System *LowLevelSystem = nullptr; + System->getCoreSystem(&LowLevelSystem); + FString SoundName = ProgrammerSoundNameCopy.Len() ? ProgrammerSoundNameCopy : UTF8_TO_TCHAR(props->name); + FMOD_MODE SoundMode = FMOD_LOOP_NORMAL | FMOD_CREATECOMPRESSEDSAMPLE | FMOD_NONBLOCKING; + + if (SoundName.Contains(TEXT("."))) + { + // Load via file + FString SoundPath = SoundName; + if (FPaths::IsRelative(SoundPath)) + { + SoundPath = FPaths::ProjectContentDir() / SoundPath; + } + + FMOD::Sound *Sound = nullptr; + if (LowLevelSystem->createSound(TCHAR_TO_UTF8(*SoundPath), SoundMode, nullptr, &Sound) == FMOD_OK) + { + UE_LOG(LogFMOD, Verbose, TEXT("Creating programmer sound from file '%s'"), *SoundPath); + props->sound = (FMOD_SOUND *)Sound; + props->subsoundIndex = -1; + NeedDestroyProgrammerSoundCallback = true; + } + else + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to load programmer sound file '%s'"), *SoundPath); + } + } + else + { + // Load via FMOD Studio asset table + FMOD_STUDIO_SOUND_INFO SoundInfo = { 0 }; + FMOD_RESULT Result = System->getSoundInfo(TCHAR_TO_UTF8(*SoundName), &SoundInfo); + if (Result == FMOD_OK) + { + FMOD::Sound *Sound = nullptr; + Result = LowLevelSystem->createSound(SoundInfo.name_or_data, SoundMode | SoundInfo.mode, &SoundInfo.exinfo, &Sound); + if (Result == FMOD_OK) + { + UE_LOG(LogFMOD, Verbose, TEXT("Creating programmer sound using audio entry '%s'"), *SoundName); + + props->sound = (FMOD_SOUND *)Sound; + props->subsoundIndex = SoundInfo.subsoundindex; + NeedDestroyProgrammerSoundCallback = true; + } + else + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to load FMOD audio entry '%s'"), *SoundName); + } + } + else + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to find FMOD audio entry '%s'"), *SoundName); + } + } + } +} + +void UFMODAudioComponent::EventCallbackDestroyProgrammerSound(FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES *props) +{ + if (NeedDestroyProgrammerSoundCallback) + { + UFMODAudioComponent_ReleaseProgrammerSound(props); + NeedDestroyProgrammerSoundCallback = false; + } +} + +void UFMODAudioComponent::SetProgrammerSoundName(FString Value) +{ + FScopeLock Lock(&CallbackLock); + ProgrammerSoundName = Value; +} + +void UFMODAudioComponent::SetProgrammerSound(FMOD::Sound *Sound) +{ + FScopeLock Lock(&CallbackLock); + ProgrammerSound = Sound; +} + +void UFMODAudioComponent::Play() +{ + PlayInternal(EFMODSystemContext::Max); +} + +void UFMODAudioComponent::PlayInternal(EFMODSystemContext::Type Context) +{ + Stop(); + + if (!FMODUtils::IsWorldAudible(GetWorld(), Context == EFMODSystemContext::Editor)) + { + return; + } + + UE_LOG(LogFMOD, Verbose, TEXT("UFMODAudioComponent %p Play"), this); + + // Only play events in PIE/game, not when placing them in the editor + FMOD::Studio::EventDescription *EventDesc = GetStudioModule().GetEventDescription(Event.Get(), Context); + if (EventDesc != nullptr) + { + EventDesc->getLength(&EventLength); + if (!StudioInstance || !StudioInstance->isValid()) + { + FMOD_RESULT result = EventDesc->createInstance(&StudioInstance); + if (result != FMOD_OK) + return; + } + + const UFMODSettings &Settings = *GetDefault(); + FMOD_STUDIO_PARAMETER_DESCRIPTION paramDesc = {}; + FString param = Settings.OcclusionParameter; + if (!param.IsEmpty()) + { + if (EventDesc->getParameterDescriptionByName(TCHAR_TO_UTF8(*Settings.OcclusionParameter), ¶mDesc) == FMOD_OK) + { + OcclusionID = paramDesc.id; + bApplyOcclusionParameter = true; + } + } + + paramDesc = {}; + param = Settings.AmbientVolumeParameter; + if (!param.IsEmpty()) + { + if (EventDesc->getParameterDescriptionByName(TCHAR_TO_UTF8(*param), ¶mDesc) == FMOD_OK) + { + AmbientVolumeID = paramDesc.id; + bApplyAmbientVolumes = true; + } + } + + paramDesc = {}; + param = Settings.AmbientLPFParameter; + if (!param.IsEmpty()) + { + if (EventDesc->getParameterDescriptionByName(TCHAR_TO_UTF8(*Settings.AmbientLPFParameter), ¶mDesc) == FMOD_OK) + { + AmbientLPFID = paramDesc.id; + bApplyAmbientVolumes = true; + } + } + + OnUpdateTransform(EUpdateTransformFlags::SkipPhysicsUpdate); + // Set initial parameters + for (auto Kvp : ParameterCache) + { + FMOD_RESULT Result = StudioInstance->setParameterByName(TCHAR_TO_UTF8(*Kvp.Key.ToString()), Kvp.Value); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set initial parameter %s"), *Kvp.Key.ToString()); + } + } + for (int i = 0; i < EFMODEventProperty::Count; ++i) + { + if (StoredProperties[i] != -1.0f) + { + FMOD_RESULT Result = StudioInstance->setProperty((FMOD_STUDIO_EVENT_PROPERTY)i, StoredProperties[i]); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set initial property %d"), i); + } + } + } + + if (bEnableTimelineCallbacks || !ProgrammerSoundName.IsEmpty()) + { + verifyfmod(StudioInstance->setCallback(UFMODAudioComponent_EventCallback)); + } + verifyfmod(StudioInstance->setUserData(this)); + verifyfmod(StudioInstance->start()); + UE_LOG(LogFMOD, Verbose, TEXT("Playing component %p"), this); + SetActiveFlag(true); + SetComponentTickEnabled(true); + } +} + +void UFMODAudioComponent::Stop() +{ + UE_LOG(LogFMOD, Verbose, TEXT("UFMODAudioComponent %p Stop"), this); + if (StudioInstance) + { + StudioInstance->stop(FMOD_STUDIO_STOP_ALLOWFADEOUT); + } + + wasOccluded = false; +} + +void UFMODAudioComponent::Release() +{ + ReleaseEventInstance(); +} + +void UFMODAudioComponent::ReleaseEventCache() +{ + ParameterCache.Empty(); + bDefaultParameterValuesCached = false; + ReleaseEventInstance(); +} + +void UFMODAudioComponent::ReleaseEventInstance() +{ + if (StudioInstance) + { + if (NeedDestroyProgrammerSoundCallback) + { + // We need a callback to destroy a programmer sound + StudioInstance->setCallback(UFMODAudioComponent_EventCallbackDestroyProgrammerSound, FMOD_STUDIO_EVENT_CALLBACK_DESTROY_PROGRAMMER_SOUND); + } + else + { + // We don't want any more callbacks + StudioInstance->setCallback(nullptr); + } + + StudioInstance->release(); + StudioInstance = nullptr; + } +} + +void UFMODAudioComponent::TriggerCue() +{ + UE_LOG(LogFMOD, Verbose, TEXT("UFMODAudioComponent %p TriggerCue"), this); + if (StudioInstance) + { + StudioInstance->triggerCue(); + } +} + +void UFMODAudioComponent::OnPlaybackCompleted() +{ + // Mark inactive before calling destroy to avoid recursion + UE_LOG(LogFMOD, Verbose, TEXT("UFMODAudioComponent %p PlaybackCompleted"), this); + SetActive(false); + SetComponentTickEnabled(false); + + Release(); + + // Fire callback after we have cleaned up our instance + OnEventStopped.Broadcast(); + + // Auto destruction is handled via marking object for deletion. + if (bAutoDestroy) + { + DestroyComponent(); + } +} + +bool UFMODAudioComponent::IsPlaying(void) +{ + return IsActive(); +} + +void UFMODAudioComponent::SetVolume(float Volume) +{ + if (StudioInstance) + { + FMOD_RESULT Result = StudioInstance->setVolume(Volume); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set volume")); + } + } +} + +void UFMODAudioComponent::SetPitch(float Pitch) +{ + if (StudioInstance) + { + FMOD_RESULT Result = StudioInstance->setPitch(Pitch); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set pitch")); + } + } +} + +void UFMODAudioComponent::SetPaused(bool Paused) +{ + if (StudioInstance) + { + FMOD_RESULT Result = StudioInstance->setPaused(Paused); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to pause")); + } + } +} + +void UFMODAudioComponent::SetParameter(FName Name, float Value) +{ + if (StudioInstance) + { + FMOD_RESULT Result = StudioInstance->setParameterByName(TCHAR_TO_UTF8(*Name.ToString()), Value); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set parameter %s"), *Name.ToString()); + } + } + ParameterCache.FindOrAdd(Name) = Value; +} + +void UFMODAudioComponent::SetProperty(EFMODEventProperty::Type Property, float Value) +{ + verify(Property < EFMODEventProperty::Count); + if (StudioInstance) + { + FMOD_RESULT Result = StudioInstance->setProperty((FMOD_STUDIO_EVENT_PROPERTY)Property, Value); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set property %d"), (int)Property); + } + } + StoredProperties[Property] = Value; +} + +float UFMODAudioComponent::GetProperty(EFMODEventProperty::Type Property) +{ + verify(Property < EFMODEventProperty::Count); + float outValue = 0; + if (Event) + { + FMOD_RESULT Result = StudioInstance->getProperty((FMOD_STUDIO_EVENT_PROPERTY)Property, &outValue); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to get property %d"), (int)Property); + } + } + return StoredProperties[Property] = outValue; +} + +int32 UFMODAudioComponent::GetLength() const +{ + return EventLength; +} + +void UFMODAudioComponent::SetTimelinePosition(int32 Time) +{ + if (StudioInstance) + { + FMOD_RESULT Result = StudioInstance->setTimelinePosition(Time); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set timeline position")); + } + } +} + +int32 UFMODAudioComponent::GetTimelinePosition() +{ + int Time = 0; + if (StudioInstance) + { + FMOD_RESULT Result = StudioInstance->getTimelinePosition(&Time); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to get timeline position")); + } + } + return Time; +} + +float UFMODAudioComponent::GetParameter(FName Name) +{ + if (!bDefaultParameterValuesCached) + { + CacheDefaultParameterValues(); + } + + float *CachedValue = ParameterCache.Find(Name); + float Value = CachedValue ? *CachedValue : 0.0; + if (StudioInstance) + { + FMOD_RESULT Result = StudioInstance->getParameterByName(TCHAR_TO_UTF8(*Name.ToString()), &Value); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to get parameter %s"), *Name.ToString()); + } + } + return Value; +} + +void UFMODAudioComponent::GetParameterValue(FName Name, float &UserValue, float &FinalValue) +{ + if (!bDefaultParameterValuesCached) + { + CacheDefaultParameterValues(); + } + + float *CachedValue = ParameterCache.Find(Name); + if (StudioInstance) + { + FMOD_RESULT Result = StudioInstance->getParameterByName(TCHAR_TO_UTF8(*Name.ToString()), &UserValue, &FinalValue); + if (Result != FMOD_OK) + { + UserValue = FinalValue = 0; + UE_LOG(LogFMOD, Warning, TEXT("Failed to get parameter %s"), *Name.ToString()); + } + } +} \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBank.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBank.cpp new file mode 100644 index 0000000..2f0cc19 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBank.cpp @@ -0,0 +1,20 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODBank.h" +#include "FMODStudioModule.h" + +UFMODBank::UFMODBank(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +/** Get tags to show in content view */ +void UFMODBank::GetAssetRegistryTags(TArray &OutTags) const +{ + Super::GetAssetRegistryTags(OutTags); +} + +FString UFMODBank::GetDesc() +{ + return FString::Printf(TEXT("Bank %s"), *AssetGuid.ToString(EGuidFormats::DigitsWithHyphensInBraces)); +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBankUpdateNotifier.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBankUpdateNotifier.cpp new file mode 100644 index 0000000..1b81009 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBankUpdateNotifier.cpp @@ -0,0 +1,59 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODBankUpdateNotifier.h" +#include "FMODSettings.h" +#include "HAL/FileManager.h" + +#include "FMODStudioPrivatePCH.h" + +FFMODBankUpdateNotifier::FFMODBankUpdateNotifier() + : bUpdateEnabled(true) + , NextRefreshTime(FDateTime::MinValue()) +{ +} + +void FFMODBankUpdateNotifier::SetFilePath(const FString &InPath) +{ + FilePath = InPath; + NextRefreshTime = FDateTime::MinValue(); + FileTime = FDateTime::MinValue(); +} + +void FFMODBankUpdateNotifier::Update() +{ + if (bUpdateEnabled) + { + FDateTime CurTime = FDateTime::UtcNow(); + if (CurTime >= NextRefreshTime) + { + NextRefreshTime = CurTime + FTimespan(0, 0, 1); + Refresh(); + } + } +} + +void FFMODBankUpdateNotifier::EnableUpdate(bool bEnable) +{ + bUpdateEnabled = bEnable; + + if (bEnable) + { + // Refreshing right after update is enabled is not desirable + NextRefreshTime = FDateTime::UtcNow() + FTimespan(0, 0, 1); + } +} + +void FFMODBankUpdateNotifier::Refresh() +{ + if (!FilePath.IsEmpty()) + { + const FDateTime NewFileTime = IFileManager::Get().GetTimeStamp(*FilePath); + if (NewFileTime != FileTime) + { + FileTime = NewFileTime; + UE_LOG(LogFMOD, Log, TEXT("File has changed: %s"), *FilePath); + + BanksUpdatedEvent.Broadcast(); + } + } +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBankUpdateNotifier.h b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBankUpdateNotifier.h new file mode 100644 index 0000000..6aac044 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBankUpdateNotifier.h @@ -0,0 +1,28 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "Containers/UnrealString.h" +#include "Misc/DateTime.h" +#include "Delegates/Delegate.h" + +class FFMODBankUpdateNotifier +{ +public: + FFMODBankUpdateNotifier(); + + void SetFilePath(const FString &InPath); + void Update(); + + void EnableUpdate(bool bEnable); + + FSimpleMulticastDelegate BanksUpdatedEvent; + +private: + void Refresh(); + + bool bUpdateEnabled; + FString FilePath; + FDateTime NextRefreshTime; + FDateTime FileTime; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBlueprintStatics.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBlueprintStatics.cpp new file mode 100644 index 0000000..4346575 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBlueprintStatics.cpp @@ -0,0 +1,668 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODBlueprintStatics.h" +#include "FMODAudioComponent.h" +#include "FMODSettings.h" +#include "FMODStudioModule.h" +#include "FMODUtils.h" +#include "FMODBank.h" +#include "FMODEvent.h" +#include "FMODBus.h" +#include "FMODVCA.h" +#include "fmod_studio.hpp" +#include "fmod_errors.h" +#include "FMODStudioPrivatePCH.h" + +///////////////////////////////////////////////////// +// UFMODBlueprintStatics + +UFMODBlueprintStatics::UFMODBlueprintStatics(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +FFMODEventInstance UFMODBlueprintStatics::PlayEvent2D(UObject *WorldContextObject, class UFMODEvent *Event, bool bAutoPlay) +{ + return PlayEventAtLocation(WorldContextObject, Event, FTransform(), bAutoPlay); +} + +FFMODEventInstance UFMODBlueprintStatics::PlayEventAtLocation( + UObject *WorldContextObject, class UFMODEvent *Event, const FTransform &Location, bool bAutoPlay) +{ + FFMODEventInstance Instance; + Instance.Instance = nullptr; + + UWorld *ThisWorld = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::ReturnNull); + if (FMODUtils::IsWorldAudible(ThisWorld, false) && IsValid(Event)) + { + FMOD::Studio::EventDescription *EventDesc = IFMODStudioModule::Get().GetEventDescription(Event); + if (EventDesc != nullptr) + { + FMOD::Studio::EventInstance *EventInst = nullptr; + EventDesc->createInstance(&EventInst); + if (EventInst != nullptr) + { + FMOD_3D_ATTRIBUTES EventAttr = { { 0 } }; + FMODUtils::Assign(EventAttr, Location); + EventInst->set3DAttributes(&EventAttr); + + if (bAutoPlay) + { + EventInst->start(); + EventInst->release(); + } + Instance.Instance = EventInst; + } + } + } + return Instance; +} + +class UFMODAudioComponent *UFMODBlueprintStatics::PlayEventAttached(class UFMODEvent *Event, class USceneComponent *AttachToComponent, + FName AttachPointName, FVector Location, EAttachLocation::Type LocationType, bool bStopWhenAttachedToDestroyed, bool bAutoPlay, bool bAutoDestroy) +{ + if (Event == nullptr) + { + return nullptr; + } + if (AttachToComponent == nullptr) + { + UE_LOG(LogFMOD, Warning, TEXT("UFMODBlueprintStatics::PlayEventAttached: NULL AttachComponent specified!")); + return nullptr; + } + + AActor *Actor = AttachToComponent->GetOwner(); + + // Avoid creating component if we're trying to play a sound on an already destroyed actor. + if (Actor && Actor->IsPendingKill()) + { + return nullptr; + } + + UFMODAudioComponent *AudioComponent; + if (Actor) + { + // Use actor as outer if we have one. + AudioComponent = NewObject(Actor); + } + else + { + // Let engine pick the outer (transient package). + AudioComponent = NewObject(); + } + check(AudioComponent); + AudioComponent->Event = Event; + AudioComponent->bAutoActivate = false; + AudioComponent->bAutoDestroy = bAutoDestroy; + AudioComponent->bStopWhenOwnerDestroyed = bStopWhenAttachedToDestroyed; +#if WITH_EDITORONLY_DATA + AudioComponent->bVisualizeComponent = false; +#endif + AudioComponent->RegisterComponentWithWorld(AttachToComponent->GetWorld()); + + AudioComponent->AttachToComponent(AttachToComponent, FAttachmentTransformRules::KeepRelativeTransform, AttachPointName); + if (LocationType == EAttachLocation::KeepWorldPosition) + { + AudioComponent->SetWorldLocation(Location); + } + else + { + AudioComponent->SetRelativeLocation(Location); + } + + if (bAutoPlay) + { + AudioComponent->Play(); + } + return AudioComponent; +} + +UFMODAsset *UFMODBlueprintStatics::FindAssetByName(const FString &Name) +{ + return IFMODStudioModule::Get().FindAssetByName(Name); +} + +UFMODEvent *UFMODBlueprintStatics::FindEventByName(const FString &Name) +{ + return IFMODStudioModule::Get().FindEventByName(Name); +} + +void UFMODBlueprintStatics::LoadBank(class UFMODBank *Bank, bool bBlocking, bool bLoadSampleData) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr && IsValid(Bank)) + { + UE_LOG(LogFMOD, Log, TEXT("LoadBank %s"), *Bank->FileName); + + FString BankPath = IFMODStudioModule::Get().GetBankPath(*Bank); + FMOD::Studio::Bank *bank = nullptr; + FMOD_STUDIO_LOAD_BANK_FLAGS flags = (bBlocking || bLoadSampleData) ? FMOD_STUDIO_LOAD_BANK_NORMAL : FMOD_STUDIO_LOAD_BANK_NONBLOCKING; + FMOD_RESULT result = StudioSystem->loadBankFile(TCHAR_TO_UTF8(*BankPath), flags, &bank); + + if (result != FMOD_OK) + { + UE_LOG(LogFMOD, Error, TEXT("Failed to load bank %s: %s"), *Bank->FileName, UTF8_TO_TCHAR(FMOD_ErrorString(result))); + } + + if (result == FMOD_OK) + { + bank->loadSampleData(); + } + } +} + +void UFMODBlueprintStatics::UnloadBank(class UFMODBank *Bank) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr && IsValid(Bank)) + { + UE_LOG(LogFMOD, Log, TEXT("UnloadBank %s"), *Bank->FileName); + + FMOD::Studio::ID guid = FMODUtils::ConvertGuid(Bank->AssetGuid); + FMOD::Studio::Bank *bank = nullptr; + FMOD_RESULT result = StudioSystem->getBankByID(&guid, &bank); + if (result == FMOD_OK && bank != nullptr) + { + bank->unload(); + } + } +} + +bool UFMODBlueprintStatics::IsBankLoaded(class UFMODBank *Bank) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr && IsValid(Bank)) + { + FMOD::Studio::ID guid = FMODUtils::ConvertGuid(Bank->AssetGuid); + FMOD::Studio::Bank *bank = nullptr; + FMOD_RESULT result = StudioSystem->getBankByID(&guid, &bank); + if (result == FMOD_OK && bank != nullptr) + { + FMOD_STUDIO_LOADING_STATE loadingState; + if (bank->getLoadingState(&loadingState) == FMOD_OK) + { + return (loadingState == FMOD_STUDIO_LOADING_STATE_LOADED); + } + } + } + return false; +} + +void UFMODBlueprintStatics::LoadBankSampleData(class UFMODBank *Bank) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr && IsValid(Bank)) + { + FMOD::Studio::ID guid = FMODUtils::ConvertGuid(Bank->AssetGuid); + FMOD::Studio::Bank *bank = nullptr; + FMOD_RESULT result = StudioSystem->getBankByID(&guid, &bank); + if (result == FMOD_OK && bank != nullptr) + { + bank->loadSampleData(); + } + } +} + +void UFMODBlueprintStatics::UnloadBankSampleData(class UFMODBank *Bank) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr && IsValid(Bank)) + { + FMOD::Studio::ID guid = FMODUtils::ConvertGuid(Bank->AssetGuid); + FMOD::Studio::Bank *bank = nullptr; + FMOD_RESULT result = StudioSystem->getBankByID(&guid, &bank); + if (result == FMOD_OK && bank != nullptr) + { + bank->unloadSampleData(); + } + } +} + +void UFMODBlueprintStatics::LoadEventSampleData(UObject *WorldContextObject, class UFMODEvent *Event) +{ + if (IsValid(Event)) + { + FMOD::Studio::EventDescription *EventDesc = IFMODStudioModule::Get().GetEventDescription(Event); + if (EventDesc != nullptr) + { + EventDesc->loadSampleData(); + } + } +} + +void UFMODBlueprintStatics::UnloadEventSampleData(UObject *WorldContextObject, class UFMODEvent *Event) +{ + if (IsValid(Event)) + { + FMOD::Studio::EventDescription *EventDesc = IFMODStudioModule::Get().GetEventDescription(Event); + if (EventDesc != nullptr) + { + EventDesc->unloadSampleData(); + } + } +} + +TArray UFMODBlueprintStatics::FindEventInstances(UObject *WorldContextObject, UFMODEvent *Event) +{ + TArray Instances; + if (IsValid(Event)) + { + FMOD::Studio::EventDescription *EventDesc = IFMODStudioModule::Get().GetEventDescription(Event); + if (EventDesc != nullptr) + { + int Capacity = 0; + EventDesc->getInstanceCount(&Capacity); + if (Capacity > 0) + { + TArray InstancePointers; + InstancePointers.SetNum(Capacity, true); + int Count = 0; + EventDesc->getInstanceList(InstancePointers.GetData(), Capacity, &Count); + Instances.SetNum(Count, true); + for (int i = 0; i < Count; ++i) + { + Instances[i].Instance = InstancePointers[i]; + } + } + } + } + return Instances; +} + +void UFMODBlueprintStatics::BusSetVolume(class UFMODBus *Bus, float Volume) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr && IsValid(Bus)) + { + FMOD::Studio::ID guid = FMODUtils::ConvertGuid(Bus->AssetGuid); + FMOD::Studio::Bus *bus = nullptr; + FMOD_RESULT result = StudioSystem->getBusByID(&guid, &bus); + if (result == FMOD_OK && bus != nullptr) + { + bus->setVolume(Volume); + } + } +} + +void UFMODBlueprintStatics::BusSetPaused(class UFMODBus *Bus, bool bPaused) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr && IsValid(Bus)) + { + FMOD::Studio::ID guid = FMODUtils::ConvertGuid(Bus->AssetGuid); + FMOD::Studio::Bus *bus = nullptr; + FMOD_RESULT result = StudioSystem->getBusByID(&guid, &bus); + if (result == FMOD_OK && bus != nullptr) + { + bus->setPaused(bPaused); + } + } +} + +void UFMODBlueprintStatics::BusSetMute(class UFMODBus *Bus, bool bMute) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr && IsValid(Bus)) + { + FMOD::Studio::ID guid = FMODUtils::ConvertGuid(Bus->AssetGuid); + FMOD::Studio::Bus *bus = nullptr; + FMOD_RESULT result = StudioSystem->getBusByID(&guid, &bus); + if (result == FMOD_OK && bus != nullptr) + { + bus->setMute(bMute); + } + } +} + +void UFMODBlueprintStatics::BusStopAllEvents(UFMODBus *Bus, EFMOD_STUDIO_STOP_MODE stopMode) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr && IsValid(Bus)) + { + FMOD::Studio::ID guid = FMODUtils::ConvertGuid(Bus->AssetGuid); + FMOD::Studio::Bus *bus = nullptr; + FMOD_RESULT result = StudioSystem->getBusByID(&guid, &bus); + if (result == FMOD_OK && bus != nullptr) + { + bus->stopAllEvents((FMOD_STUDIO_STOP_MODE)stopMode); + } + } +} + +void UFMODBlueprintStatics::VCASetVolume(class UFMODVCA *Vca, float Volume) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr && IsValid(Vca)) + { + FMOD::Studio::ID guid = FMODUtils::ConvertGuid(Vca->AssetGuid); + FMOD::Studio::VCA *vca = nullptr; + FMOD_RESULT result = StudioSystem->getVCAByID(&guid, &vca); + if (result == FMOD_OK && vca != nullptr) + { + vca->setVolume(Volume); + } + } +} + +void UFMODBlueprintStatics::SetGlobalParameterByName(FName Name, float Value) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr) + { + FMOD_RESULT Result = StudioSystem->setParameterByName(TCHAR_TO_UTF8(*Name.ToString()), Value); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set parameter %s"), *Name.ToString()); + } + } +} + +float UFMODBlueprintStatics::GetGlobalParameterByName(FName Name) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + float Value = 0.0f; + if (StudioSystem != nullptr) + { + FMOD_RESULT Result = StudioSystem->getParameterByName(TCHAR_TO_UTF8(*Name.ToString()), &Value); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to get event instance parameter %s"), *Name.ToString()); + } + } + return Value; +} + +void UFMODBlueprintStatics::GetGlobalParameterValueByName(FName Name, float &UserValue, float &FinalValue) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr) + { + FMOD_RESULT Result = StudioSystem->getParameterByName(TCHAR_TO_UTF8(*Name.ToString()), &UserValue, &FinalValue); + if (Result != FMOD_OK) + { + UserValue = FinalValue = 0.0f; + UE_LOG(LogFMOD, Warning, TEXT("Failed to get event instance parameter %s"), *Name.ToString()); + } + } +} + +bool UFMODBlueprintStatics::EventInstanceIsValid(FFMODEventInstance EventInstance) +{ + if (EventInstance.Instance) + { + return EventInstance.Instance->isValid(); + } + return false; +} + +void UFMODBlueprintStatics::EventInstanceSetVolume(FFMODEventInstance EventInstance, float Volume) +{ + if (EventInstance.Instance) + { + FMOD_RESULT Result = EventInstance.Instance->setVolume(Volume); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set event instance volume")); + } + } +} + +void UFMODBlueprintStatics::EventInstanceSetPitch(FFMODEventInstance EventInstance, float Pitch) +{ + if (EventInstance.Instance) + { + FMOD_RESULT Result = EventInstance.Instance->setPitch(Pitch); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set event instance pitch")); + } + } +} + +void UFMODBlueprintStatics::EventInstanceSetPaused(FFMODEventInstance EventInstance, bool Paused) +{ + if (EventInstance.Instance) + { + FMOD_RESULT Result = EventInstance.Instance->setPaused(Paused); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to pause event instance")); + } + } +} + +void UFMODBlueprintStatics::EventInstanceSetParameter(FFMODEventInstance EventInstance, FName Name, float Value) +{ + if (EventInstance.Instance) + { + FMOD_RESULT Result = EventInstance.Instance->setParameterByName(TCHAR_TO_UTF8(*Name.ToString()), Value); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set event instance parameter %s"), *Name.ToString()); + } + } +} + +float UFMODBlueprintStatics::EventInstanceGetParameter(FFMODEventInstance EventInstance, FName Name) +{ + float Value = 0.0f; + if (EventInstance.Instance) + { + FMOD_RESULT Result = EventInstance.Instance->getParameterByName(TCHAR_TO_UTF8(*Name.ToString()), &Value); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to get event instance parameter %s"), *Name.ToString()); + } + } + return Value; +} + +void UFMODBlueprintStatics::EventInstanceGetParameterValue(FFMODEventInstance EventInstance, FName Name, float &UserValue, float &FinalValue) +{ + if (EventInstance.Instance) + { + FMOD_RESULT Result = EventInstance.Instance->getParameterByName(TCHAR_TO_UTF8(*Name.ToString()), &UserValue, &FinalValue); + if (Result != FMOD_OK) + { + UserValue = FinalValue = 0.0f; + UE_LOG(LogFMOD, Warning, TEXT("Failed to get event instance parameter %s"), *Name.ToString()); + } + } +} + +void UFMODBlueprintStatics::EventInstanceSetProperty(FFMODEventInstance EventInstance, EFMODEventProperty::Type Property, float Value) +{ + if (EventInstance.Instance) + { + FMOD_RESULT Result = EventInstance.Instance->setProperty((FMOD_STUDIO_EVENT_PROPERTY)Property, Value); + + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set event instance property type %d to value %f (%s)"), (int)Property, Value, + FMOD_ErrorString(Result)); + } + } +} + +void UFMODBlueprintStatics::EventInstancePlay(FFMODEventInstance EventInstance) +{ + if (EventInstance.Instance) + { + FMOD_RESULT Result = EventInstance.Instance->start(); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to play event instance")); + } + // Once we start playing, allow instance to be cleaned up when it finishes + EventInstance.Instance->release(); + } +} + +void UFMODBlueprintStatics::EventInstanceStop(FFMODEventInstance EventInstance, bool Release) +{ + if (EventInstance.Instance) + { + FMOD_RESULT Result = EventInstance.Instance->stop(FMOD_STUDIO_STOP_ALLOWFADEOUT); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to stop event instance")); + } + else + { + if (Release) + { + EventInstanceRelease(EventInstance); + //EventInstance.Instance->release(); + } + } + } +} + +void UFMODBlueprintStatics::EventInstanceRelease(FFMODEventInstance EventInstance) +{ + if (EventInstance.Instance) + { + FMOD_RESULT Result = EventInstance.Instance->release(); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to release event instance")); + } + } +} + +void UFMODBlueprintStatics::EventInstanceTriggerCue(FFMODEventInstance EventInstance) +{ + if (EventInstance.Instance) + { + EventInstance.Instance->triggerCue(); + } +} + +void UFMODBlueprintStatics::EventInstanceSetTransform(FFMODEventInstance EventInstance, const FTransform &Location) +{ + if (EventInstance.Instance) + { + FMOD_3D_ATTRIBUTES attr = { { 0 } }; + FMODUtils::Assign(attr, Location); + FMOD_RESULT Result = EventInstance.Instance->set3DAttributes(&attr); + if (Result != FMOD_OK) + { + UE_LOG(LogFMOD, Warning, TEXT("Failed to set transform on event instance")); + } + } +} + +TArray UFMODBlueprintStatics::GetOutputDrivers() +{ + TArray AllNames; + + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr) + { + FMOD::System *LowLevelSystem = nullptr; + verifyfmod(StudioSystem->getCoreSystem(&LowLevelSystem)); + + int DriverCount = 0; + verifyfmod(LowLevelSystem->getNumDrivers(&DriverCount)); + + for (int id = 0; id < DriverCount; ++id) + { + char DriverNameUTF8[256] = {}; + verifyfmod(LowLevelSystem->getDriverInfo(id, DriverNameUTF8, sizeof(DriverNameUTF8), 0, 0, 0, 0)); + FString DriverName(UTF8_TO_TCHAR(DriverNameUTF8)); + AllNames.Add(DriverName); + } + } + + return AllNames; +} + +void UFMODBlueprintStatics::SetOutputDriverByName(FString NewDriverName) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr) + { + FMOD::System *LowLevelSystem = nullptr; + verifyfmod(StudioSystem->getCoreSystem(&LowLevelSystem)); + + int DriverIndex = -1; + int DriverCount = 0; + verifyfmod(LowLevelSystem->getNumDrivers(&DriverCount)); + + for (int id = 0; id < DriverCount; ++id) + { + char DriverNameUTF8[256] = {}; + verifyfmod(LowLevelSystem->getDriverInfo(id, DriverNameUTF8, sizeof(DriverNameUTF8), 0, 0, 0, 0)); + FString DriverName(UTF8_TO_TCHAR(DriverNameUTF8)); + UE_LOG(LogFMOD, Log, TEXT("Driver %d: %s"), id, *DriverName); + if (DriverName.Contains(NewDriverName)) + { + DriverIndex = id; + } + } + + if (DriverIndex >= 0) + { + UE_LOG(LogFMOD, Log, TEXT("Selected driver %d"), DriverIndex); + verifyfmod(LowLevelSystem->setDriver(DriverIndex)); + } + else + { + UE_LOG(LogFMOD, Warning, TEXT("Did not find driver of name '%s'"), *NewDriverName); + } + } +} + +void UFMODBlueprintStatics::SetOutputDriverByIndex(int NewDriverIndex) +{ + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr) + { + FMOD::System *LowLevelSystem = nullptr; + verifyfmod(StudioSystem->getCoreSystem(&LowLevelSystem)); + + int DriverCount = 0; + verifyfmod(LowLevelSystem->getNumDrivers(&DriverCount)); + + if (NewDriverIndex >= 0 && NewDriverIndex < DriverCount) + { + UE_LOG(LogFMOD, Log, TEXT("Selected driver %d"), NewDriverIndex); + verifyfmod(LowLevelSystem->setDriver(NewDriverIndex)); + } + else + { + UE_LOG(LogFMOD, Warning, TEXT("Driver %d out of range"), NewDriverIndex); + } + } +} + +void UFMODBlueprintStatics::MixerSuspend() +{ + UE_LOG(LogFMOD, Log, TEXT("MixerSuspend called")); + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr) + { + FMOD::System *LowLevelSystem = nullptr; + verifyfmod(StudioSystem->getCoreSystem(&LowLevelSystem)); + + verifyfmod(LowLevelSystem->mixerSuspend()); + } +} + +void UFMODBlueprintStatics::MixerResume() +{ + UE_LOG(LogFMOD, Log, TEXT("MixerResume called")); + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (StudioSystem != nullptr) + { + FMOD::System *LowLevelSystem = nullptr; + verifyfmod(StudioSystem->getCoreSystem(&LowLevelSystem)); + + verifyfmod(LowLevelSystem->mixerResume()); + } +} + +void UFMODBlueprintStatics::SetLocale(const FString& Locale) +{ + IFMODStudioModule::Get().SetLocale(Locale); +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBus.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBus.cpp new file mode 100644 index 0000000..4a9388a --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODBus.cpp @@ -0,0 +1,20 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODBus.h" +#include "FMODStudioModule.h" + +UFMODBus::UFMODBus(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +/** Get tags to show in content view */ +void UFMODBus::GetAssetRegistryTags(TArray &OutTags) const +{ + Super::GetAssetRegistryTags(OutTags); +} + +FString UFMODBus::GetDesc() +{ + return FString::Printf(TEXT("Bus %s"), *AssetGuid.ToString(EGuidFormats::DigitsWithHyphensInBraces)); +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODEvent.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODEvent.cpp new file mode 100644 index 0000000..c1cab59 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODEvent.cpp @@ -0,0 +1,58 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODEvent.h" +#include "FMODStudioModule.h" +#include "fmod_studio.hpp" + +UFMODEvent::UFMODEvent(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +/** Get tags to show in content view */ +void UFMODEvent::GetAssetRegistryTags(TArray &OutTags) const +{ + Super::GetAssetRegistryTags(OutTags); + if (IFMODStudioModule::Get().AreBanksLoaded()) + { + FMOD::Studio::EventDescription *EventDesc = IFMODStudioModule::Get().GetEventDescription(this, EFMODSystemContext::Max); + + bool bOneshot = false; + bool bStream = false; + bool b3D = false; + if (EventDesc) + { + EventDesc->isOneshot(&bOneshot); + EventDesc->isStream(&bStream); + EventDesc->is3D(&b3D); + } + + OutTags.Add(UObject::FAssetRegistryTag("Oneshot", bOneshot ? TEXT("True") : TEXT("False"), UObject::FAssetRegistryTag::TT_Alphabetical)); + OutTags.Add(UObject::FAssetRegistryTag("Streaming", bStream ? TEXT("True") : TEXT("False"), UObject::FAssetRegistryTag::TT_Alphabetical)); + OutTags.Add(UObject::FAssetRegistryTag("3D", b3D ? TEXT("True") : TEXT("False"), UObject::FAssetRegistryTag::TT_Alphabetical)); + } +} + +FString UFMODEvent::GetDesc() +{ + return FString::Printf(TEXT("Event %s"), *AssetGuid.ToString(EGuidFormats::DigitsWithHyphensInBraces)); +} + +void UFMODEvent::GetParameterDescriptions(TArray &Parameters) const +{ + if (IFMODStudioModule::Get().AreBanksLoaded()) + { + FMOD::Studio::EventDescription *EventDesc = IFMODStudioModule::Get().GetEventDescription(this, EFMODSystemContext::Auditioning); + + if (EventDesc) + { + int ParameterCount; + EventDesc->getParameterDescriptionCount(&ParameterCount); + Parameters.SetNumUninitialized(ParameterCount); + for (int ParameterIndex = 0; ParameterIndex < ParameterCount; ++ParameterIndex) + { + EventDesc->getParameterDescriptionByIndex(ParameterIndex, &Parameters[ParameterIndex]); + } + } + } +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODFileCallbacks.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODFileCallbacks.cpp new file mode 100644 index 0000000..9579a2b --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODFileCallbacks.cpp @@ -0,0 +1,329 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2015. + +#include "FMODFileCallbacks.h" +#include "FMODUtils.h" +#include "HAL/FileManager.h" +#include "GenericPlatform/GenericPlatformProcess.h" +#include "HAL/Runnable.h" +#include "HAL/RunnableThread.h" +#include "Misc/ScopeLock.h" +#include "FMODStudioPrivatePCH.h" + +FMOD_RESULT F_CALLBACK FMODLogCallback(FMOD_DEBUG_FLAGS flags, const char *file, int line, const char *func, const char *message) +{ + if (flags & FMOD_DEBUG_LEVEL_ERROR) + { + UE_LOG(LogFMOD, Error, TEXT("%s(%d) - %s"), UTF8_TO_TCHAR(file), line, UTF8_TO_TCHAR(message)); + } + else if (flags & FMOD_DEBUG_LEVEL_WARNING) + { + FString Message = UTF8_TO_TCHAR(message); + UE_LOG(LogFMOD, Warning, TEXT("%s(%d) - %s"), UTF8_TO_TCHAR(file), line, *Message); + if (GIsEditor) + { + int32 StartIndex = Message.Find(TEXT("Missing DSP plugin '")); + if (StartIndex != INDEX_NONE) + { + int32 Len = FString(TEXT("Missing DSP plugin '")).Len(); + int32 EndIndex; + if (Message.FindLastChar('\'', EndIndex) && EndIndex != INDEX_NONE && StartIndex + Len < EndIndex) + { + FString PluginName = Message.Mid(StartIndex + Len, EndIndex - StartIndex - Len); + + FModuleManager::GetModuleChecked("FMODStudio").AddRequiredPlugin(PluginName); + } + } + } + } + else if (flags & FMOD_DEBUG_LEVEL_LOG) + { + UE_LOG(LogFMOD, Log, TEXT("%s(%d) - %s"), UTF8_TO_TCHAR(file), line, UTF8_TO_TCHAR(message)); + } + return FMOD_OK; +} + +class FFMODFileSystem : public FRunnable +{ +public: + FFMODFileSystem() + : mHandleIn(nullptr) + , mName(nullptr) + , mFileSize(nullptr) + , mHandleOut(nullptr) + , mBuffer(nullptr) + , mSizeBytes(0) + , mBytesRead(nullptr) + , mSeekPosition(0) + , mCommand(COMMAND_MAX) + , mResult(FMOD_OK) + , mReferenceCount(0) + , mThread(nullptr) + , mCommandReadyEvent(nullptr) + , mCommandCompleteEvent(nullptr) + { + } + + static FMOD_RESULT F_CALLBACK OpenCallback(const char *name, unsigned int *filesize, void **handle, void * /*userdata*/); + static FMOD_RESULT F_CALLBACK CloseCallback(void *handle, void * /*userdata*/); + static FMOD_RESULT F_CALLBACK ReadCallback(void *handle, void *buffer, unsigned int sizebytes, unsigned int *bytesread, void * /*userdata*/); + static FMOD_RESULT F_CALLBACK SeekCallback(void *handle, unsigned int pos, void * /*userdata*/); + + static FMOD_RESULT OpenInternal(const char *name, unsigned int *filesize, void **handle); + static FMOD_RESULT CloseInternal(void *handle); + static FMOD_RESULT ReadInternal(void *handle, void *buffer, unsigned int sizebytes, unsigned int *bytesread); + static FMOD_RESULT SeekInternal(void *handle, unsigned int pos); + + void IncrementReferenceCount() + { + FScopeLock lock(&mCrit); + + ++mReferenceCount; + + if (mReferenceCount == 1) + { + check(!mThread); + + mCommandReadyEvent = FGenericPlatformProcess::GetSynchEventFromPool(); + mCommandCompleteEvent = FGenericPlatformProcess::GetSynchEventFromPool(); + mThread = FRunnableThread::Create(this, TEXT("FMOD File Access Coordinator")); + } + } + + void DecrementReferenceCount() + { + FScopeLock lock(&mCrit); + + check(mReferenceCount > 0); + check(mThread); + + --mReferenceCount; + + if (mReferenceCount == 0) + { + verifyfmod(RunCommand(COMMAND_STOP)); + mThread->WaitForCompletion(); + + FGenericPlatformProcess::ReturnSynchEventToPool(mCommandReadyEvent); + mCommandReadyEvent = nullptr; + FGenericPlatformProcess::ReturnSynchEventToPool(mCommandCompleteEvent); + mCommandCompleteEvent = nullptr; + delete mThread; + mThread = nullptr; + } + } + + void Attach(FMOD::System *system, int32 fileBufferSize) + { + check(mThread); + + verifyfmod(system->setFileSystem(OpenCallback, CloseCallback, ReadCallback, SeekCallback, 0, 0, fileBufferSize)); + } + + uint32 Run() override + { + bool stopRequested = false; + + while (!stopRequested) + { + mCommandReadyEvent->Wait(); + + switch (mCommand) + { + case COMMAND_OPEN: + mResult = OpenInternal(mName, mFileSize, mHandleOut); + break; + case COMMAND_CLOSE: + mResult = CloseInternal(mHandleIn); + break; + case COMMAND_READ: + mResult = ReadInternal(mHandleIn, mBuffer, mSizeBytes, mBytesRead); + break; + case COMMAND_SEEK: + mResult = SeekInternal(mHandleIn, mSeekPosition); + break; + case COMMAND_STOP: + stopRequested = true; + mResult = FMOD_OK; + break; + } + + mCommandCompleteEvent->Trigger(); + } + + return 0; + } + +private: + enum Command + { + COMMAND_OPEN, + COMMAND_CLOSE, + COMMAND_READ, + COMMAND_SEEK, + COMMAND_STOP, + COMMAND_MAX, + }; + + FMOD_RESULT RunCommand(Command command) + { + check(mThread); + + mCommand = command; + mCommandReadyEvent->Trigger(); + mCommandCompleteEvent->Wait(); + + return mResult; + } + + // Parameter for Close, Seek and Read + void *mHandleIn; + + // Parameters for Open + const char *mName; + unsigned int *mFileSize; + void **mHandleOut; + + // Parameters for Read + void *mBuffer; + unsigned int mSizeBytes; + unsigned int *mBytesRead; + + // Parameter for Seek + unsigned int mSeekPosition; + + Command mCommand; + FMOD_RESULT mResult; + + int mReferenceCount; + FRunnableThread *mThread; + FEvent *mCommandReadyEvent; + FEvent *mCommandCompleteEvent; + + FCriticalSection mCrit; +}; + +static FFMODFileSystem gFileSystem; + +FMOD_RESULT F_CALLBACK FFMODFileSystem::OpenCallback(const char *name, unsigned int *filesize, void **handle, void * /*userdata*/) +{ + FScopeLock lock(&gFileSystem.mCrit); + gFileSystem.mName = name; + gFileSystem.mFileSize = filesize; + gFileSystem.mHandleOut = handle; + + return gFileSystem.RunCommand(COMMAND_OPEN); +} + +FMOD_RESULT FFMODFileSystem::OpenInternal(const char *name, unsigned int *filesize, void **handle) +{ + if (name) + { + FArchive *Archive = IFileManager::Get().CreateFileReader(UTF8_TO_TCHAR(name)); + UE_LOG(LogFMOD, Verbose, TEXT("FFMODFileSystem::OpenInternal opening '%s' returned archive %p"), UTF8_TO_TCHAR(name), Archive); + if (!Archive) + { + return FMOD_ERR_FILE_NOTFOUND; + } + *filesize = Archive->TotalSize(); + *handle = Archive; + UE_LOG(LogFMOD, Verbose, TEXT(" TotalSize = %d"), *filesize); + } + + return FMOD_OK; +} + +FMOD_RESULT F_CALLBACK FFMODFileSystem::CloseCallback(void *handle, void * /*userdata*/) +{ + FScopeLock lock(&gFileSystem.mCrit); + gFileSystem.mHandleIn = handle; + + return gFileSystem.RunCommand(COMMAND_CLOSE); +} + +FMOD_RESULT FFMODFileSystem::CloseInternal(void *handle) +{ + if (!handle) + { + return FMOD_ERR_INVALID_PARAM; + } + + FArchive *Archive = (FArchive *)handle; + UE_LOG(LogFMOD, Verbose, TEXT("FFMODFileSystem::CloseCallback closing archive %p"), Archive); + delete Archive; + + return FMOD_OK; +} + +FMOD_RESULT F_CALLBACK FFMODFileSystem::ReadCallback(void *handle, void *buffer, unsigned int sizebytes, unsigned int *bytesread, void * /*userdata*/) +{ + FScopeLock lock(&gFileSystem.mCrit); + gFileSystem.mHandleIn = handle; + gFileSystem.mBuffer = buffer; + gFileSystem.mSizeBytes = sizebytes; + gFileSystem.mBytesRead = bytesread; + + return gFileSystem.RunCommand(COMMAND_READ); +} + +FMOD_RESULT FFMODFileSystem::ReadInternal(void *handle, void *buffer, unsigned int sizebytes, unsigned int *bytesread) +{ + if (!handle) + { + return FMOD_ERR_INVALID_PARAM; + } + + if (bytesread) + { + FArchive *Archive = (FArchive *)handle; + + int64 BytesLeft = Archive->TotalSize() - Archive->Tell(); + int64 ReadAmount = FMath::Min((int64)sizebytes, BytesLeft); + + Archive->Serialize(buffer, ReadAmount); + *bytesread = (unsigned int)ReadAmount; + if (ReadAmount < (int64)sizebytes) + { + UE_LOG(LogFMOD, Verbose, TEXT(" -> EOF ")); + return FMOD_ERR_FILE_EOF; + } + } + + return FMOD_OK; +} + +FMOD_RESULT F_CALLBACK FFMODFileSystem::SeekCallback(void *handle, unsigned int pos, void * /*userdata*/) +{ + FScopeLock lock(&gFileSystem.mCrit); + gFileSystem.mHandleIn = handle; + gFileSystem.mSeekPosition = pos; + + return gFileSystem.RunCommand(COMMAND_SEEK); +} + +FMOD_RESULT FFMODFileSystem::SeekInternal(void *handle, unsigned int pos) +{ + if (!handle) + { + return FMOD_ERR_INVALID_PARAM; + } + + FArchive *Archive = (FArchive *)handle; + Archive->Seek(pos); + + return FMOD_OK; +} + +void AcquireFMODFileSystem() +{ + gFileSystem.IncrementReferenceCount(); +} + +void ReleaseFMODFileSystem() +{ + gFileSystem.DecrementReferenceCount(); +} + +void AttachFMODFileSystem(FMOD::System *system, int32 fileBufferSize) +{ + gFileSystem.Attach(system, fileBufferSize); +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODFileCallbacks.h b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODFileCallbacks.h new file mode 100644 index 0000000..9f9b8e9 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODFileCallbacks.h @@ -0,0 +1,12 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "fmod.hpp" +#include "GenericPlatform/GenericPlatform.h" + +FMOD_RESULT F_CALLBACK FMODLogCallback(FMOD_DEBUG_FLAGS flags, const char *file, int line, const char *func, const char *message); + +void AcquireFMODFileSystem(); +void ReleaseFMODFileSystem(); +void AttachFMODFileSystem(FMOD::System *system, FGenericPlatformTypes::int32 fileBufferSize); diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODListener.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODListener.cpp new file mode 100644 index 0000000..951319f --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODListener.cpp @@ -0,0 +1,86 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODListener.h" +#include "Misc/App.h" +#include "AudioDefines.h" +#include "Sound/AudioVolume.h" + +float FFMODListener::Interpolate(const double EndTime) +{ + if (FApp::GetCurrentTime() < InteriorStartTime) + { + return (0.0f); + } + + if (FApp::GetCurrentTime() >= EndTime) + { + return (1.0f); + } + + float InterpValue = (float)((FApp::GetCurrentTime() - InteriorStartTime) / (EndTime - InteriorStartTime)); + return (InterpValue); +} + +void FFMODListener::UpdateCurrentInteriorSettings() +{ + // Store the interpolation value, not the actual value + InteriorVolumeInterp = Interpolate(InteriorEndTime); + ExteriorVolumeInterp = Interpolate(ExteriorEndTime); + InteriorLPFInterp = Interpolate(InteriorLPFEndTime); + ExteriorLPFInterp = Interpolate(ExteriorLPFEndTime); +} + +void FFMODListener::ApplyInteriorSettings(class AAudioVolume *InVolume, const FInteriorSettings &Settings) +{ + if (InteriorSettings != Settings) + { + // Use previous/ current interpolation time if we're transitioning to the default worldsettings zone. + InteriorStartTime = FApp::GetCurrentTime(); + InteriorEndTime = InteriorStartTime + (Settings.bIsWorldSettings ? InteriorSettings.InteriorTime : Settings.InteriorTime); + ExteriorEndTime = InteriorStartTime + (Settings.bIsWorldSettings ? InteriorSettings.ExteriorTime : Settings.ExteriorTime); + InteriorLPFEndTime = InteriorStartTime + (Settings.bIsWorldSettings ? InteriorSettings.InteriorLPFTime : Settings.InteriorLPFTime); + ExteriorLPFEndTime = InteriorStartTime + (Settings.bIsWorldSettings ? InteriorSettings.ExteriorLPFTime : Settings.ExteriorLPFTime); + + InteriorSettings = Settings; + } + Volume = InVolume; +} + +FFMODInteriorSettings::FFMODInteriorSettings() + : bIsWorldSettings(false) + , ExteriorVolume(1.0f) + , ExteriorTime(0.5f) + , ExteriorLPF(MAX_FILTER_FREQUENCY) + , ExteriorLPFTime(0.5f) + , InteriorVolume(1.0f) + , InteriorTime(0.5f) + , InteriorLPF(MAX_FILTER_FREQUENCY) + , InteriorLPFTime(0.5f) +{ +} + +bool FFMODInteriorSettings::operator==(const FInteriorSettings &Other) const +{ + return (this->bIsWorldSettings == Other.bIsWorldSettings) && (this->ExteriorVolume == Other.ExteriorVolume) && + (this->ExteriorTime == Other.ExteriorTime) && (this->ExteriorLPF == Other.ExteriorLPF) && + (this->ExteriorLPFTime == Other.ExteriorLPFTime) && (this->InteriorVolume == Other.InteriorVolume) && + (this->InteriorTime == Other.InteriorTime) && (this->InteriorLPF == Other.InteriorLPF) && (this->InteriorLPFTime == Other.InteriorLPFTime); +} +bool FFMODInteriorSettings::operator!=(const FInteriorSettings &Other) const +{ + return !(*this == Other); +} + +FFMODInteriorSettings &FFMODInteriorSettings::operator=(FInteriorSettings Other) +{ + bIsWorldSettings = Other.bIsWorldSettings; + ExteriorVolume = Other.ExteriorVolume; + ExteriorTime = Other.ExteriorTime; + ExteriorLPF = Other.ExteriorLPF; + ExteriorLPFTime = Other.ExteriorLPFTime; + InteriorVolume = Other.InteriorVolume; + InteriorTime = Other.InteriorTime; + InteriorLPF = Other.InteriorLPF; + InteriorLPFTime = Other.InteriorLPFTime; + return *this; +} \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODListener.h b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODListener.h new file mode 100644 index 0000000..e0cc1c9 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODListener.h @@ -0,0 +1,85 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "GenericPlatform/GenericPlatform.h" +#include "UObject/Object.h" +#include "Math/Vector.h" + +struct FInteriorSettings; + +/** Struct encapsulating settings for interior areas. */ +struct FFMODInteriorSettings +{ + uint32 bIsWorldSettings : 1; + float ExteriorVolume; + float ExteriorTime; + float ExteriorLPF; + float ExteriorLPFTime; + float InteriorVolume; + float InteriorTime; + float InteriorLPF; + float InteriorLPFTime; + + FFMODInteriorSettings(); + bool operator==(const FInteriorSettings &Other) const; + bool operator!=(const FInteriorSettings &Other) const; + FFMODInteriorSettings &operator=(FInteriorSettings Other); +}; + +/** A direct copy of FListener (which doesn't have external linkage, unfortunately) **/ +struct FFMODListener +{ + FTransform Transform; + FVector Velocity; + + struct FFMODInteriorSettings InteriorSettings; + /** The volume the listener resides in */ + class AAudioVolume *Volume; + + /** The times of interior volumes fading in and out */ + double InteriorStartTime; + double InteriorEndTime; + double ExteriorEndTime; + double InteriorLPFEndTime; + double ExteriorLPFEndTime; + float InteriorVolumeInterp; + float InteriorLPFInterp; + float ExteriorVolumeInterp; + float ExteriorLPFInterp; + + FVector GetUp() const { return Transform.GetUnitAxis(EAxis::Z); } + FVector GetFront() const { return Transform.GetUnitAxis(EAxis::Y); } + FVector GetRight() const { return Transform.GetUnitAxis(EAxis::X); } + + /** + * Works out the interp value between source and end + */ + float Interpolate(const double EndTime); + + /** + * Gets the current state of the interior settings for the listener + */ + void UpdateCurrentInteriorSettings(); + + /** + * Apply the interior settings to ambient sounds + */ + void ApplyInteriorSettings(class AAudioVolume *Volume, const FInteriorSettings &Settings); + + FFMODListener() + : Transform(FTransform::Identity) + , Velocity(ForceInit) + , Volume(NULL) + , InteriorStartTime(0.0) + , InteriorEndTime(0.0) + , ExteriorEndTime(0.0) + , InteriorLPFEndTime(0.0) + , ExteriorLPFEndTime(0.0) + , InteriorVolumeInterp(0.f) + , InteriorLPFInterp(0.f) + , ExteriorVolumeInterp(0.f) + , ExteriorLPFInterp(0.f) + { + } +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODPlatform.h b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODPlatform.h new file mode 100644 index 0000000..b20fd77 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODPlatform.h @@ -0,0 +1,18 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. +#pragma once + +#include "Containers/UnrealString.h" +#include "fmod_common.h" +#include "FMODSettings.h" + +FString FMODPlatform_GetDllPath(const TCHAR *ShortName, bool bExplicitPath, bool bUseLibPrefix); + +FString FMODPlatform_PlatformName(); + +void FMODPlatform_SetRealChannelCount(FMOD_ADVANCEDSETTINGS* advSettings); + +int FMODPlatform_MemoryPoolSize(); + +void* FMODPlatformLoadDll(const TCHAR* LibToLoad); + +FMOD_RESULT FMODPlatformSystemSetup(); \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODPlatformLoadDll_Generic.h b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODPlatformLoadDll_Generic.h new file mode 100644 index 0000000..20c89e7 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODPlatformLoadDll_Generic.h @@ -0,0 +1,12 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. +#pragma once + +void *FMODPlatformLoadDll(const TCHAR *LibToLoad) +{ + return FPlatformProcess::GetDllHandle(LibToLoad); +} + +FMOD_RESULT FMODPlatformSystemSetup() +{ + return FMOD_OK; +} \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODSettings.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODSettings.cpp new file mode 100644 index 0000000..941a979 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODSettings.cpp @@ -0,0 +1,139 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODSettings.h" +#include "Misc/Paths.h" + +#if WITH_EDITOR +#include "Settings/ProjectPackagingSettings.h" +#endif + +#ifdef FMOD_PLATFORM_HEADER +#include "FMODPlatform.h" +#endif + +////////////////////////////////////////////////////////////////////////// +// UPaperRuntimeSettings + +UFMODSettings::UFMODSettings(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ + MasterBankName = TEXT("Master"); + BankOutputDirectory.Path = TEXT("FMOD"); + OutputFormat = EFMODSpeakerMode::Surround_5_1; + ContentBrowserPrefix = TEXT("/Game/FMOD/"); + bLoadAllBanks = true; + bLoadAllSampleData = false; + bEnableLiveUpdate = true; + bVol0Virtual = true; + Vol0VirtualLevel = 0.0001f; + RealChannelCount = 64; + TotalChannelCount = 512; + DSPBufferLength = 0; + DSPBufferCount = 0; + FileBufferSize = 2048; + StudioUpdatePeriod = 0; + LiveUpdatePort = 9264; + EditorLiveUpdatePort = 9265; + bMatchHardwareSampleRate = true; + bLockAllBuses = false; +} + +FString UFMODSettings::GetFullBankPath() const +{ + FString FullPath = BankOutputDirectory.Path; + if (FPaths::IsRelative(FullPath)) + { + FullPath = FPaths::ProjectContentDir() / FullPath; + } + + if (ForcePlatformName == TEXT(".")) + { + // Leave path without subdirectory + } + else if (!ForcePlatformName.IsEmpty()) + { + FullPath = FullPath / ForcePlatformName; + } + else + { +#ifdef FMOD_PLATFORM_HEADER + FString PlatformName = FMODPlatform_PlatformName(); +#elif PLATFORM_IOS || PLATFORM_TVOS || PLATFORM_ANDROID + FString PlatformName = "Mobile"; +#elif PLATFORM_PS4 + FString PlatformName = "PS4"; +#elif PLATFORM_XBOXONE + FString PlatformName = "XboxOne"; +#elif PLATFORM_SWITCH + FString PlatformName = "Switch"; +#else + FString PlatformName = "Desktop"; +#endif + FullPath = FullPath / PlatformName; + } + return FullPath; +} + +FString UFMODSettings::GetMasterBankFilename() const +{ + return MasterBankName + TEXT(".bank"); +} + +FString UFMODSettings::GetMasterAssetsBankFilename() const +{ + return MasterBankName + TEXT(".assets.bank"); +} + +FString UFMODSettings::GetMasterStringsBankFilename() const +{ + return MasterBankName + TEXT(".strings.bank"); +} + +#if WITH_EDITOR +UFMODSettings::EProblem UFMODSettings::Check() const +{ + if (!IsBankPathSet()) + { + return BankPathNotSet; + } + + UProjectPackagingSettings* PackagingSettings = Cast(UProjectPackagingSettings::StaticClass()->GetDefaultObject()); + bool bAddedToNonUFS = false; + bool bAddedToUFS = false; + + for (int i = 0; i < PackagingSettings->DirectoriesToAlwaysStageAsNonUFS.Num(); ++i) + { + if (PackagingSettings->DirectoriesToAlwaysStageAsNonUFS[i].Path.StartsWith(BankOutputDirectory.Path)) + { + bAddedToNonUFS = true; + break; + } + } + + for (int i = 0; i < PackagingSettings->DirectoriesToAlwaysStageAsUFS.Num(); ++i) + { + if (PackagingSettings->DirectoriesToAlwaysStageAsUFS[i].Path.StartsWith(BankOutputDirectory.Path)) + { + bAddedToUFS = true; + break; + } + } + + if (bAddedToUFS && bAddedToNonUFS) + { + return AddedToBoth; + } + + if (bAddedToUFS) + { + return AddedToUFS; + } + + if (!bAddedToNonUFS) + { + return NotPackaged; + } + + return Okay; +} +#endif // WITH_EDITOR diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODSnapshot.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODSnapshot.cpp new file mode 100644 index 0000000..36a2109 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODSnapshot.cpp @@ -0,0 +1,14 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODSnapshot.h" +#include "FMODStudioModule.h" + +UFMODSnapshot::UFMODSnapshot(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +FString UFMODSnapshot::GetDesc() +{ + return FString::Printf(TEXT("Snapshot %s"), *AssetGuid.ToString(EGuidFormats::DigitsWithHyphensInBraces)); +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODSnapshotReverb.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODSnapshotReverb.cpp new file mode 100644 index 0000000..2bf2016 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODSnapshotReverb.cpp @@ -0,0 +1,14 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODSnapshotReverb.h" + +UFMODSnapshotReverb::UFMODSnapshotReverb(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +#if WITH_EDITORONLY_DATA +void UFMODSnapshotReverb::PostEditChangeProperty(FPropertyChangedEvent &PropertyChangedEvent) +{ +} +#endif // EDITORONLY_DATA \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODStudioModule.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODStudioModule.cpp new file mode 100644 index 0000000..7fa8501 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODStudioModule.cpp @@ -0,0 +1,1495 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODStudioModule.h" +#include "FMODSettings.h" +#include "FMODAudioComponent.h" +#include "FMODBlueprintStatics.h" +#include "FMODAssetTable.h" +#include "FMODFileCallbacks.h" +#include "FMODBankUpdateNotifier.h" +#include "FMODUtils.h" +#include "FMODEvent.h" +#include "FMODListener.h" +#include "FMODSnapshotReverb.h" + +#include "Async/Async.h" +#include "Interfaces/IPluginManager.h" +#include "Misc/App.h" +#include "Misc/CommandLine.h" +#include "Misc/CoreDelegates.h" +#include "Engine/GameViewportClient.h" +#include "GameFramework/PlayerController.h" +#include "Containers/Ticker.h" +#include "Misc/Paths.h" +#include "Runtime/Media/Public/IMediaClock.h" +#include "Runtime/Media/Public/IMediaClockSink.h" +#include "Runtime/Media/Public/IMediaModule.h" +#include "TimerManager.h" + +#include "fmod_studio.hpp" +#include "fmod_errors.h" +#include "FMODStudioPrivatePCH.h" + +#ifdef FMOD_PLATFORM_HEADER +#include "FMODPlatform.h" +#elif PLATFORM_PS4 +#include "FMODPlatformLoadDll_PS4.h" +#elif PLATFORM_XBOXONE +#include "FMODPlatformLoadDll_XBoxOne.h" +#elif PLATFORM_SWITCH +#include "FMODPlatformLoadDll_Switch.h" +#else +#include "FMODPlatformLoadDll_Generic.h" +#endif + +#define LOCTEXT_NAMESPACE "FMODStudio" + +DEFINE_LOG_CATEGORY(LogFMOD); + +DECLARE_STATS_GROUP(TEXT("FMOD"), STATGROUP_FMOD, STATCAT_Advanced); +DECLARE_FLOAT_COUNTER_STAT(TEXT("FMOD CPU - Mixer"), STAT_FMOD_CPUMixer, STATGROUP_FMOD); +DECLARE_FLOAT_COUNTER_STAT(TEXT("FMOD CPU - Studio"), STAT_FMOD_CPUStudio, STATGROUP_FMOD); +DECLARE_MEMORY_STAT(TEXT("FMOD Memory - Current"), STAT_FMOD_Current_Memory, STATGROUP_FMOD); +DECLARE_MEMORY_STAT(TEXT("FMOD Memory - Max"), STAT_FMOD_Max_Memory, STATGROUP_FMOD); +DECLARE_DWORD_COUNTER_STAT(TEXT("FMOD Channels - Total"), STAT_FMOD_Total_Channels, STATGROUP_FMOD); +DECLARE_DWORD_COUNTER_STAT(TEXT("FMOD Channels - Real"), STAT_FMOD_Real_Channels, STATGROUP_FMOD); + +const TCHAR *FMODSystemContextNames[EFMODSystemContext::Max] = { + TEXT("Auditioning"), TEXT("Runtime"), TEXT("Editor"), +}; + +void *F_CALLBACK FMODMemoryAlloc(unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) +{ + return FMemory::Malloc(size); +} +void *F_CALLBACK FMODMemoryRealloc(void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr) +{ + return FMemory::Realloc(ptr, size); +} +void F_CALLBACK FMODMemoryFree(void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr) +{ + FMemory::Free(ptr); +} + +struct FFMODSnapshotEntry +{ + FFMODSnapshotEntry(UFMODSnapshotReverb *InSnapshot = nullptr, FMOD::Studio::EventInstance *InInstance = nullptr) + : Snapshot(InSnapshot) + , Instance(InInstance) + , StartTime(0.0) + , FadeDuration(0.0f) + , FadeIntensityStart(0.0f) + , FadeIntensityEnd(0.0f) + { + } + + float CurrentIntensity() const + { + double CurrentTime = FApp::GetCurrentTime(); + if (StartTime + FadeDuration <= CurrentTime) + { + return FadeIntensityEnd; + } + else + { + float Factor = (CurrentTime - StartTime) / FadeDuration; + return FMath::Lerp(FadeIntensityStart, FadeIntensityEnd, Factor); + } + } + + void FadeTo(float Target, float Duration) + { + float StartIntensity = CurrentIntensity(); + + StartTime = FApp::GetCurrentTime(); + FadeDuration = Duration; + FadeIntensityStart = StartIntensity; + FadeIntensityEnd = Target; + } + + UFMODSnapshotReverb *Snapshot; + FMOD::Studio::EventInstance *Instance; + double StartTime; + float FadeDuration; + float FadeIntensityStart; + float FadeIntensityEnd; +}; + +class FFMODStudioSystemClockSink : public IMediaClockSink +{ +public: + DECLARE_DELEGATE_RetVal(void, FUpdateListenerPosition); + + FFMODStudioSystemClockSink(FMOD::Studio::System *SystemIn) + : System(SystemIn) + , LastResult(FMOD_OK) + { + } + + virtual void TickRender(FTimespan DeltaTime, FTimespan Timecode) override + { + if (System) + { + if (UpdateListenerPosition.IsBound()) + { + UpdateListenerPosition.Execute(); + } + + LastResult = System->update(); + } + } + + void SetUpdateListenerPositionDelegate(FUpdateListenerPosition UpdateListenerPositionIn) { UpdateListenerPosition = UpdateListenerPositionIn; } + + void OnDestroyStudioSystem() { System = nullptr; } + + FMOD::Studio::System *System; + FMOD_RESULT LastResult; + FUpdateListenerPosition UpdateListenerPosition; +}; + +class FFMODStudioModule : public IFMODStudioModule +{ +public: + /** IModuleInterface implementation */ + FFMODStudioModule() + : AuditioningInstance(nullptr) + , ListenerCount(1) + , bSimulating(false) + , bIsInPIE(false) + , bUseSound(true) + , bListenerMoved(true) + , bAllowLiveUpdate(true) + , bBanksLoaded(false) + , LowLevelLibHandle(nullptr) + , StudioLibHandle(nullptr) + , bMixerPaused(false) + , MemPool(nullptr) + { + for (int i = 0; i < EFMODSystemContext::Max; ++i) + { + StudioSystem[i] = nullptr; + } + } + + void HandleApplicationWillDeactivate() + { + AsyncTask(ENamedThreads::GameThread, [&]() { SetSystemPaused(true); }); + } + void HandleApplicationHasReactivated() + { + AsyncTask(ENamedThreads::GameThread, [&]() { SetSystemPaused(false); }); + } + + virtual void StartupModule() override; + virtual void PostLoadCallback() override; + virtual void ShutdownModule() override; + + FString GetDllPath(const TCHAR *ShortName, bool bExplicitPath, bool bUseLibPrefix); + void *LoadDll(const TCHAR *ShortName); + + bool LoadLibraries(); + + void LoadBanks(EFMODSystemContext::Type Type); + + /** Called when a newer version of the bank files was detected */ + void HandleBanksUpdated(); + + void CreateStudioSystem(EFMODSystemContext::Type Type); + void DestroyStudioSystem(EFMODSystemContext::Type Type); + + bool Tick(float DeltaTime); + + void UpdateViewportPosition(); + + virtual FMOD::Studio::System *GetStudioSystem(EFMODSystemContext::Type Context) override; + virtual FMOD::Studio::EventDescription *GetEventDescription(const UFMODEvent *Event, EFMODSystemContext::Type Type) override; + virtual FMOD::Studio::EventInstance *CreateAuditioningInstance(const UFMODEvent *Event) override; + virtual void StopAuditioningInstance() override; + + virtual void SetListenerPosition(int ListenerIndex, UWorld *World, const FTransform &ListenerTransform, float DeltaSeconds) override; + virtual void FinishSetListenerPosition(int ListenerCount, float DeltaSeconds) override; + + virtual const FFMODListener &GetNearestListener(const FVector &Location) override; + + virtual bool HasListenerMoved() override; + + virtual void RefreshSettings(); + + virtual void SetSystemPaused(bool paused) override; + + virtual void SetInPIE(bool bInPIE, bool simulating) override; + + virtual UFMODAsset *FindAssetByName(const FString &Name) override; + virtual UFMODEvent *FindEventByName(const FString &Name) override; + virtual FString GetBankPath(const UFMODBank &Bank) override; + virtual void GetAllBankPaths(TArray &Paths, bool IncludeMasterBank) const override; + + FSimpleMulticastDelegate BanksReloadedDelegate; + virtual FSimpleMulticastDelegate &BanksReloadedEvent() override { return BanksReloadedDelegate; } + + virtual TArray GetFailedBankLoads(EFMODSystemContext::Type Context) override { return FailedBankLoads[Context]; } + + virtual TArray GetRequiredPlugins() override { return RequiredPlugins; } + + virtual void AddRequiredPlugin(const FString &Plugin) + { + if (!RequiredPlugins.Contains(Plugin)) + { + RequiredPlugins.Add(Plugin); + } + } + + virtual bool UseSound() override { return bUseSound; } + + virtual bool LoadPlugin(EFMODSystemContext::Type Context, const TCHAR *ShortName) override; + + virtual void LogError(int result, const char *function) override; + + virtual bool AreBanksLoaded() override; + + virtual bool SetLocale(const FString& Locale) override; + + void ResetInterpolation(); + + /** The studio system handle. */ + FMOD::Studio::System *StudioSystem[EFMODSystemContext::Max]; + FMOD::Studio::EventInstance *AuditioningInstance; + + /** The delegate to be invoked when this profiler manager ticks. */ + FTickerDelegate OnTick; + + /** IMediaClockSink wrappers for Studio Systems */ + TSharedPtr ClockSinks[EFMODSystemContext::Max]; + + /** Handle for registered TickDelegate. */ + FDelegateHandle TickDelegateHandle; + + /** Table of assets with name and guid */ + FFMODAssetTable AssetTable; + + /** Periodically checks for updates of the strings.bank file */ + FFMODBankUpdateNotifier BankUpdateNotifier; + + /** List of failed bank files */ + TArray FailedBankLoads[EFMODSystemContext::Max]; + + /** List of required plugins we found when loading banks. */ + TArray RequiredPlugins; + +/** Listener information */ +#if FMOD_VERSION >= 0x00010600 + static const int MAX_LISTENERS = FMOD_MAX_LISTENERS; +#else + static const int MAX_LISTENERS = 1; +#endif + FFMODListener Listeners[MAX_LISTENERS]; + int ListenerCount; + + /** Current snapshot applied via reverb zones*/ + TArray ReverbSnapshots; + + /** True if simulating */ + bool bSimulating; + + /** True if in PIE */ + bool bIsInPIE; + + /** True if we want sound enabled */ + bool bUseSound; + + /** True if we the listener has moved and may have changed audio settings*/ + bool bListenerMoved; + + /** True if we allow live update */ + bool bAllowLiveUpdate; + + bool bBanksLoaded; + + /** Dynamic library */ + FString BaseLibPath; + void *LowLevelLibHandle; + void *StudioLibHandle; + + /** True if the mixer has been paused by application deactivation */ + bool bMixerPaused; + + /** You can also supply a pool of memory for FMOD to work with and it will do so with no extra calls to malloc or free. */ + void *MemPool; + + bool bLoadAllSampleData; +}; + +IMPLEMENT_MODULE(FFMODStudioModule, FMODStudio) + +void FFMODStudioModule::LogError(int result, const char *function) +{ + FString ErrorStr(ANSI_TO_TCHAR(FMOD_ErrorString((FMOD_RESULT)result))); + FString FunctionStr(ANSI_TO_TCHAR(function)); + UE_LOG(LogFMOD, Error, TEXT("'%s' returned '%s'"), *FunctionStr, *ErrorStr); +} + +bool FFMODStudioModule::LoadPlugin(EFMODSystemContext::Type Context, const TCHAR *ShortName) +{ + UE_LOG(LogFMOD, Log, TEXT("Loading plugin '%s'"), ShortName); + + static const int ATTEMPT_COUNT = 2; + static const TCHAR *AttemptPrefixes[ATTEMPT_COUNT] = { + TEXT(""), +#if PLATFORM_64BITS + TEXT("64") +#else + TEXT("32") +#endif + }; + + FMOD::System *LowLevelSystem = nullptr; + verifyfmod(StudioSystem[Context]->getCoreSystem(&LowLevelSystem)); + + FMOD_RESULT PluginLoadResult; + + for (int useLib = 0; useLib < 2; ++useLib) + { + for (int attempt = 0; attempt < 2; ++attempt) + { + // Try to load combinations of 64/32 suffix and lib prefix for relevant platforms + FString AttemptName = FString(ShortName) + AttemptPrefixes[attempt]; + FString PluginPath = GetDllPath(*AttemptName, true, useLib != 0); + + UE_LOG(LogFMOD, Log, TEXT("Trying to load plugin file at location: %s"), *PluginPath); + +#if defined(PLATFORM_UWP) && PLATFORM_UWP + FPaths::MakePathRelativeTo(PluginPath, *(FPaths::RootDir() + TEXT("/"))); +#endif + + unsigned int Handle = 0; + PluginLoadResult = LowLevelSystem->loadPlugin(TCHAR_TO_UTF8(*PluginPath), &Handle, 0); + if (PluginLoadResult == FMOD_OK) + { + UE_LOG(LogFMOD, Log, TEXT("Loaded plugin %s"), ShortName); + return true; + } + } + } + UE_LOG(LogFMOD, Error, TEXT("Failed to load plugin '%s', sounds may not play"), ShortName); + return false; +} + +void *FFMODStudioModule::LoadDll(const TCHAR *ShortName) +{ + FString LibPath = GetDllPath(ShortName, false, true); + + void *Handle = nullptr; + UE_LOG(LogFMOD, Log, TEXT("FFMODStudioModule::LoadDll: Loading %s"), *LibPath); + // Unfortunately Unreal's platform loading code hasn't been implemented on all platforms so we wrap it + Handle = FMODPlatformLoadDll(*LibPath); +#if WITH_EDITOR + if (!Handle && !FApp::IsUnattended()) + { + FString Message = TEXT("Couldn't load FMOD DLL ") + LibPath; + FPlatformMisc::MessageBoxExt(EAppMsgType::Ok, *Message, TEXT("Error")); + } +#endif + if (!Handle) + { + UE_LOG(LogFMOD, Error, TEXT("Failed to load FMOD DLL '%s', FMOD sounds will not play!"), *LibPath); + } + return Handle; +} + +FString FFMODStudioModule::GetDllPath(const TCHAR *ShortName, bool bExplicitPath, bool bUseLibPrefix) +{ + const TCHAR *LibPrefixName = (bUseLibPrefix ? TEXT("lib") : TEXT("")); +#ifdef FMOD_PLATFORM_HEADER + return FMODPlatform_GetDllPath(ShortName, bExplicitPath, bUseLibPrefix); +#elif PLATFORM_MAC + return FString::Printf(TEXT("%s/Mac/%s%s.dylib"), *BaseLibPath, LibPrefixName, ShortName); +#elif PLATFORM_PS4 + const TCHAR *DirPrefix = (bExplicitPath ? TEXT("/app0/prx/") : TEXT("")); + return FString::Printf(TEXT("%s%s%s.prx"), DirPrefix, LibPrefixName, ShortName); +#elif PLATFORM_XBOXONE + return FString::Printf(TEXT("%s/XBoxOne/%s.dll"), *BaseLibPath, ShortName); +#elif PLATFORM_ANDROID + return FString::Printf(TEXT("%s%s.so"), LibPrefixName, ShortName); +#elif PLATFORM_LINUX + return FString::Printf(TEXT("%s%s.so"), LibPrefixName, ShortName); +#elif PLATFORM_WINDOWS +#if PLATFORM_64BITS + return FString::Printf(TEXT("%s/Win64/%s.dll"), *BaseLibPath, ShortName); +#else + return FString::Printf(TEXT("%s/Win32/%s.dll"), *BaseLibPath, ShortName); +#endif +#elif defined(PLATFORM_UWP) && PLATFORM_UWP + return FString::Printf(TEXT("%s/UWP64/%s.dll"), *BaseLibPath, ShortName); +#else + UE_LOG(LogFMOD, Error, TEXT("Unsupported platform for dynamic libs")); + return ""; +#endif +} + +bool FFMODStudioModule::LoadLibraries() +{ +#if PLATFORM_IOS || PLATFORM_TVOS || PLATFORM_ANDROID || PLATFORM_LINUX || PLATFORM_MAC || PLATFORM_SWITCH || defined(FMOD_DONT_LOAD_LIBRARIES) + return true; // Nothing to do on those platforms +#else + UE_LOG(LogFMOD, Verbose, TEXT("FFMODStudioModule::LoadLibraries")); + +#if defined(FMODSTUDIO_LINK_DEBUG) + FString ConfigName = TEXT("D"); +#elif defined(FMODSTUDIO_LINK_LOGGING) + FString ConfigName = TEXT("L"); +#elif defined(FMODSTUDIO_LINK_RELEASE) + FString ConfigName = TEXT(""); +#else +#error FMODSTUDIO_LINK not defined +#endif + + FString LowLevelName = FString(TEXT("fmod")) + ConfigName; + FString StudioName = FString(TEXT("fmodstudio")) + ConfigName; + LowLevelLibHandle = LoadDll(*LowLevelName); + StudioLibHandle = LoadDll(*StudioName); + return (LowLevelLibHandle != nullptr && StudioLibHandle != nullptr); +#endif +} + +void FFMODStudioModule::StartupModule() +{ + UE_LOG(LogFMOD, Log, TEXT("FFMODStudioModule startup")); + BaseLibPath = IPluginManager::Get().FindPlugin(TEXT("FMODStudio"))->GetBaseDir() + TEXT("/Binaries"); + UE_LOG(LogFMOD, Log, TEXT(" Lib path = '%s'"), *BaseLibPath); + + if (FParse::Param(FCommandLine::Get(), TEXT("nosound")) || FApp::IsBenchmarking() || IsRunningDedicatedServer() || IsRunningCommandlet()) + { + bUseSound = false; + } + + if (FParse::Param(FCommandLine::Get(), TEXT("noliveupdate"))) + { + bAllowLiveUpdate = false; + } + + if (LoadLibraries()) + { + verifyfmod(FMOD::Debug_Initialize(FMOD_DEBUG_LEVEL_WARNING, FMOD_DEBUG_MODE_CALLBACK, FMODLogCallback)); + + const UFMODSettings &Settings = *GetDefault(); + +//#ifdef FMOD_PLATFORM_HEADER +// int size = FMODPlatform_MemoryPoolSize(); +#if PLATFORM_IOS || PLATFORM_TVOS || PLATFORM_ANDROID + int size = Settings.MemoryPoolSizes.Mobile; +#elif PLATFORM_PS4 + int size = Settings.MemoryPoolSizes.PS4; +#elif PLATFORM_XBOXONE + int size = Settings.MemoryPoolSizes.XboxOne; +#elif PLATFORM_SWITCH + int size = Settings.MemoryPoolSizes.Switch; +#else + int size = Settings.MemoryPoolSizes.Desktop; +#endif + if (!GIsEditor && size > 0) + { + MemPool = FMemory::Malloc(size); + verifyfmod(FMOD::Memory_Initialize(MemPool, size, nullptr, nullptr, nullptr)); + } + else + { + verifyfmod(FMOD::Memory_Initialize(0, 0, FMODMemoryAlloc, FMODMemoryRealloc, FMODMemoryFree)); + } + + verifyfmod(FMODPlatformSystemSetup()); + + AcquireFMODFileSystem(); + + // Create sandbox system just for asset loading + AssetTable.Create(); + RefreshSettings(); + + if (GIsEditor) + { + CreateStudioSystem(EFMODSystemContext::Auditioning); + CreateStudioSystem(EFMODSystemContext::Editor); + } + else + { + AssetTable.Destroy(); // Don't need this copy around since we don't hot reload + + SetInPIE(true, false); + } + } + + OnTick = FTickerDelegate::CreateRaw(this, &FFMODStudioModule::Tick); + TickDelegateHandle = FTicker::GetCoreTicker().AddTicker(OnTick); + + if (GIsEditor) + { + BankUpdateNotifier.BanksUpdatedEvent.AddRaw(this, &FFMODStudioModule::HandleBanksUpdated); + } +} + +inline FMOD_SPEAKERMODE ConvertSpeakerMode(EFMODSpeakerMode::Type Mode) +{ + switch (Mode) + { + case EFMODSpeakerMode::Stereo: + return FMOD_SPEAKERMODE_STEREO; + case EFMODSpeakerMode::Surround_5_1: + return FMOD_SPEAKERMODE_5POINT1; + case EFMODSpeakerMode::Surround_7_1: + return FMOD_SPEAKERMODE_7POINT1; + default: + check(0); + return FMOD_SPEAKERMODE_DEFAULT; + }; +} + +void FFMODStudioModule::CreateStudioSystem(EFMODSystemContext::Type Type) +{ + DestroyStudioSystem(Type); + if (!bUseSound) + { + return; + } + + UE_LOG(LogFMOD, Verbose, TEXT("CreateStudioSystem for context %s"), FMODSystemContextNames[Type]); + + const UFMODSettings &Settings = *GetDefault(); + bLoadAllSampleData = Settings.bLoadAllSampleData; + + FMOD_SPEAKERMODE OutputMode = ConvertSpeakerMode(Settings.OutputFormat); + FMOD_STUDIO_INITFLAGS StudioInitFlags = FMOD_STUDIO_INIT_NORMAL; + FMOD_INITFLAGS InitFlags = FMOD_INIT_NORMAL; + +#if (defined(FMODSTUDIO_LINK_DEBUG) || defined(FMODSTUDIO_LINK_LOGGING)) + bool liveUpdateEnabledForType = ((Type == EFMODSystemContext::Auditioning) && Settings.bEnableEditorLiveUpdate) || + ((Type == EFMODSystemContext::Runtime) && Settings.bEnableLiveUpdate); + if (liveUpdateEnabledForType && bAllowLiveUpdate) + { + UE_LOG(LogFMOD, Verbose, TEXT("Enabling live update")); + StudioInitFlags |= FMOD_STUDIO_INIT_LIVEUPDATE; + } +#endif + if (Type == EFMODSystemContext::Auditioning || Type == EFMODSystemContext::Editor) + { + StudioInitFlags |= FMOD_STUDIO_INIT_ALLOW_MISSING_PLUGINS; + } + + verifyfmod(FMOD::Studio::System::create(&StudioSystem[Type])); + FMOD::System *lowLevelSystem = nullptr; + verifyfmod(StudioSystem[Type]->getCoreSystem(&lowLevelSystem)); + + int DriverIndex = 0; + if (!Settings.InitialOutputDriverName.IsEmpty()) + { + int DriverCount = 0; + verifyfmod(lowLevelSystem->getNumDrivers(&DriverCount)); + for (int id = 0; id < DriverCount; ++id) + { + char DriverNameUTF8[256] = {}; + verifyfmod(lowLevelSystem->getDriverInfo(id, DriverNameUTF8, sizeof(DriverNameUTF8), 0, 0, 0, 0)); + FString DriverName(UTF8_TO_TCHAR(DriverNameUTF8)); + UE_LOG(LogFMOD, Log, TEXT("Driver %d: %s"), id, *DriverName); + if (DriverName.Contains(Settings.InitialOutputDriverName)) + { + UE_LOG(LogFMOD, Log, TEXT("Selected driver %d"), id); + DriverIndex = id; + } + } + verifyfmod(lowLevelSystem->setDriver(DriverIndex)); + } + + FTCHARToUTF8 WavWriterDestUTF8(*Settings.WavWriterPath); + void *InitData = nullptr; + if (Type == EFMODSystemContext::Runtime && Settings.WavWriterPath.Len() > 0) + { + UE_LOG(LogFMOD, Log, TEXT("Running with Wav Writer: %s"), *Settings.WavWriterPath); + verifyfmod(lowLevelSystem->setOutput(FMOD_OUTPUTTYPE_WAVWRITER)); + InitData = (void *)WavWriterDestUTF8.Get(); + } + + int SampleRate = Settings.SampleRate; + if (Settings.bMatchHardwareSampleRate) + { + int DefaultSampleRate = 0; + verifyfmod(lowLevelSystem->getSoftwareFormat(&DefaultSampleRate, 0, 0)); + int SystemSampleRate = 0; + verifyfmod(lowLevelSystem->getDriverInfo(DriverIndex, nullptr, 0, nullptr, &SystemSampleRate, nullptr, nullptr)); + UE_LOG(LogFMOD, Log, TEXT("Default sample rate = %d"), DefaultSampleRate); + UE_LOG(LogFMOD, Log, TEXT("System sample rate = %d"), SystemSampleRate); + if (DefaultSampleRate >= 44100 && DefaultSampleRate <= 48000 && SystemSampleRate >= 44100 && SystemSampleRate <= 48000) + { + UE_LOG(LogFMOD, Log, TEXT("Matching system sample rate %d"), SystemSampleRate); + SampleRate = SystemSampleRate; + } + } + + verifyfmod(lowLevelSystem->setSoftwareFormat(SampleRate, OutputMode, 0)); + verifyfmod(lowLevelSystem->setSoftwareChannels(Settings.RealChannelCount)); + AttachFMODFileSystem(lowLevelSystem, Settings.FileBufferSize); + + if (Settings.DSPBufferLength > 0 && Settings.DSPBufferCount > 0) + { + verifyfmod(lowLevelSystem->setDSPBufferSize(Settings.DSPBufferLength, Settings.DSPBufferCount)); + } + + FMOD_ADVANCEDSETTINGS advSettings = { 0 }; + advSettings.cbSize = sizeof(FMOD_ADVANCEDSETTINGS); + if (Settings.bVol0Virtual) + { + advSettings.vol0virtualvol = Settings.Vol0VirtualLevel; + InitFlags |= FMOD_INIT_VOL0_BECOMES_VIRTUAL; + } +#ifdef FMOD_PLATFORM_HEADER + FMODPlatform_SetRealChannelCount(&advSettings); +#elif PLATFORM_IOS || PLATFORM_TVOS || PLATFORM_ANDROID || PLATFORM_SWITCH + advSettings.maxFADPCMCodecs = Settings.RealChannelCount; +#elif PLATFORM_PS4 + advSettings.maxAT9Codecs = Settings.RealChannelCount; +#elif PLATFORM_XBOXONE + advSettings.maxXMACodecs = Settings.RealChannelCount; +#else + advSettings.maxVorbisCodecs = Settings.RealChannelCount; +#endif + if (Type == EFMODSystemContext::Runtime) + { + advSettings.profilePort = Settings.LiveUpdatePort; + } + else if (Type == EFMODSystemContext::Auditioning) + { + advSettings.profilePort = Settings.EditorLiveUpdatePort; + } + advSettings.randomSeed = FMath::Rand(); + verifyfmod(lowLevelSystem->setAdvancedSettings(&advSettings)); + + FMOD_STUDIO_ADVANCEDSETTINGS advStudioSettings = { 0 }; + advStudioSettings.cbsize = sizeof(advStudioSettings); + advStudioSettings.studioupdateperiod = Settings.StudioUpdatePeriod; + + if (!Settings.StudioBankKey.IsEmpty()) + { + advStudioSettings.encryptionkey = TCHAR_TO_UTF8(*Settings.StudioBankKey); + } + + verifyfmod(StudioSystem[Type]->setAdvancedSettings(&advStudioSettings)); + + verifyfmod(StudioSystem[Type]->initialize(Settings.TotalChannelCount, StudioInitFlags, InitFlags, InitData)); + + for (FString PluginName : Settings.PluginFiles) + { + if (!PluginName.IsEmpty()) + LoadPlugin(Type, *PluginName); + } + + if (Type == EFMODSystemContext::Runtime) + { + // Add interrupt callbacks for Mobile + FCoreDelegates::ApplicationWillDeactivateDelegate.AddRaw(this, &FFMODStudioModule::HandleApplicationWillDeactivate); + FCoreDelegates::ApplicationHasReactivatedDelegate.AddRaw(this, &FFMODStudioModule::HandleApplicationHasReactivated); + } + + IMediaModule *MediaModule = FModuleManager::LoadModulePtr("Media"); + + if (MediaModule != nullptr) + { + ClockSinks[Type] = MakeShared(StudioSystem[Type]); + + if (Type == EFMODSystemContext::Runtime) + { + ClockSinks[Type]->SetUpdateListenerPositionDelegate(FTimerDelegate::CreateRaw(this, &FFMODStudioModule::UpdateViewportPosition)); + } + + MediaModule->GetClock().AddSink(ClockSinks[Type].ToSharedRef()); + } +} + +void FFMODStudioModule::DestroyStudioSystem(EFMODSystemContext::Type Type) +{ + UE_LOG(LogFMOD, Verbose, TEXT("DestroyStudioSystem for context %s"), FMODSystemContextNames[Type]); + + if (ClockSinks[Type].IsValid()) + { + // Calling through the shared ptr enforces thread safety with the media clock + ClockSinks[Type]->OnDestroyStudioSystem(); + + IMediaModule *MediaModule = FModuleManager::LoadModulePtr("Media"); + + if (MediaModule != nullptr) + { + MediaModule->GetClock().RemoveSink(ClockSinks[Type].ToSharedRef()); + } + + ClockSinks[Type].Reset(); + } + + // Unload all events and banks to remove warning spam when using split banks + if (StudioSystem[Type] && bLoadAllSampleData) + { + int bankCount; + verifyfmod(StudioSystem[Type]->getBankCount(&bankCount)); + if (bankCount > 0) + { + TArray bankArray; + TArray eventArray; + TArray instanceArray; + + bankArray.SetNumUninitialized(bankCount, false); + verifyfmod(StudioSystem[Type]->getBankList(bankArray.GetData(), bankCount, &bankCount)); + for (int i = 0; i < bankCount; i++) + { + int eventCount; + verifyfmod(bankArray[i]->getEventCount(&eventCount)); + if (eventCount > 0) + { + eventArray.SetNumUninitialized(eventCount, false); + verifyfmod(bankArray[i]->getEventList(eventArray.GetData(), eventCount, &eventCount)); + for (int j = 0; j < eventCount; j++) + { + int instanceCount; + verifyfmod(eventArray[j]->getInstanceCount(&instanceCount)); + if (instanceCount > 0) + { + instanceArray.SetNumUninitialized(instanceCount, false); + verifyfmod(eventArray[j]->getInstanceList(instanceArray.GetData(), instanceCount, &instanceCount)); + for (int k = 0; k < instanceCount; k++) + { + verifyfmod(instanceArray[k]->stop(FMOD_STUDIO_STOP_IMMEDIATE)); + verifyfmod(instanceArray[k]->release()); + } + } + } + } + } + + for (int i = 0; i < bankCount; i++) + { + FMOD_STUDIO_LOADING_STATE state; + bankArray[i]->getSampleLoadingState(&state); + if (state == FMOD_STUDIO_LOADING_STATE_LOADED) + { + verifyfmod(bankArray[i]->unloadSampleData()); + } + } + } + } + + if (StudioSystem[Type]) + { + verifyfmod(StudioSystem[Type]->release()); + StudioSystem[Type] = nullptr; + } +} + +bool FFMODStudioModule::Tick(float DeltaTime) +{ + if (GIsEditor) + { + BankUpdateNotifier.Update(); + } + + if (ClockSinks[EFMODSystemContext::Auditioning].IsValid()) + { + verifyfmod(ClockSinks[EFMODSystemContext::Auditioning]->LastResult); + } + if (ClockSinks[EFMODSystemContext::Runtime].IsValid()) + { + FMOD_STUDIO_CPU_USAGE Usage = {}; + StudioSystem[EFMODSystemContext::Runtime]->getCPUUsage(&Usage); + SET_FLOAT_STAT(STAT_FMOD_CPUMixer, Usage.dspusage); + SET_FLOAT_STAT(STAT_FMOD_CPUStudio, Usage.studiousage); + + int currentAlloc, maxAlloc; + FMOD::Memory_GetStats(¤tAlloc, &maxAlloc, false); + SET_MEMORY_STAT(STAT_FMOD_Current_Memory, currentAlloc); + SET_MEMORY_STAT(STAT_FMOD_Max_Memory, maxAlloc); + + int channels, realChannels; + FMOD::System *lowlevel; + StudioSystem[EFMODSystemContext::Runtime]->getCoreSystem(&lowlevel); + lowlevel->getChannelsPlaying(&channels, &realChannels); + SET_DWORD_STAT(STAT_FMOD_Real_Channels, realChannels); + SET_DWORD_STAT(STAT_FMOD_Total_Channels, channels); + + verifyfmod(ClockSinks[EFMODSystemContext::Runtime]->LastResult); + } + if (ClockSinks[EFMODSystemContext::Editor].IsValid()) + { + verifyfmod(ClockSinks[EFMODSystemContext::Editor]->LastResult); + } + return true; +} + +void FFMODStudioModule::UpdateViewportPosition() +{ + if (bSimulating) + { + return; + } + int ListenerIndex = 0; + + UWorld *ViewportWorld = nullptr; + if (GEngine && GEngine->GameViewport) + { + ViewportWorld = GEngine->GameViewport->GetWorld(); + } + + bool bCameraCut = false; // Not sure how to get View->bCameraCut from here + float DeltaSeconds = ((bCameraCut || !ViewportWorld) ? 0.f : ViewportWorld->GetDeltaSeconds()); + + bListenerMoved = false; + + if (IsValid(ViewportWorld)) + { + for (FConstPlayerControllerIterator Iterator = ViewportWorld->GetPlayerControllerIterator(); Iterator; ++Iterator) + { + APlayerController *PlayerController = Iterator->Get(); + if (PlayerController) + { + ULocalPlayer *LocalPlayer = PlayerController->GetLocalPlayer(); + if (LocalPlayer) + { + FVector Location; + FVector ProjFront; + FVector ProjRight; + PlayerController->GetAudioListenerPosition(/*out*/ Location, /*out*/ ProjFront, /*out*/ ProjRight); + FVector ProjUp = FVector::CrossProduct(ProjFront, ProjRight); + + FTransform ListenerTransform(FRotationMatrix::MakeFromXY(ProjFront, ProjRight)); + ListenerTransform.SetTranslation(Location); + ListenerTransform.NormalizeRotation(); + + SetListenerPosition(ListenerIndex, ViewportWorld, ListenerTransform, DeltaSeconds); + + ListenerIndex++; + } + } + } + FinishSetListenerPosition(ListenerIndex, DeltaSeconds); + } +} + +bool FFMODStudioModule::HasListenerMoved() +{ + return bListenerMoved; +} + +void FFMODStudioModule::ResetInterpolation() +{ + for (FFMODListener &Listener : Listeners) + { + Listener = FFMODListener(); + } +} + +const FFMODListener &FFMODStudioModule::GetNearestListener(const FVector &Location) +{ + float BestDistSq = FLT_MAX; + int BestListener = 0; + for (int i = 0; i < ListenerCount; ++i) + { + const float DistSq = FVector::DistSquared(Location, Listeners[i].Transform.GetTranslation()); + if (DistSq < BestDistSq) + { + BestListener = i; + BestDistSq = DistSq; + } + } + return Listeners[BestListener]; +} + +// Partially copied from FAudioDevice::SetListener +void FFMODStudioModule::SetListenerPosition(int ListenerIndex, UWorld *World, const FTransform &ListenerTransform, float DeltaSeconds) +{ + FMOD::Studio::System *System = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (System && ListenerIndex < MAX_LISTENERS) + { + FVector ListenerPos = ListenerTransform.GetTranslation(); + + FInteriorSettings *InteriorSettings = + (FInteriorSettings *)alloca(sizeof(FInteriorSettings)); // FinteriorSetting::FInteriorSettings() isn't exposed (possible UE4 bug???) + AAudioVolume *Volume = World->GetAudioSettings(ListenerPos, NULL, InteriorSettings); + + Listeners[ListenerIndex].Velocity = + DeltaSeconds > 0.f ? (ListenerTransform.GetTranslation() - Listeners[ListenerIndex].Transform.GetTranslation()) / DeltaSeconds : + FVector::ZeroVector; + + Listeners[ListenerIndex].Transform = ListenerTransform; + + Listeners[ListenerIndex].ApplyInteriorSettings(Volume, *InteriorSettings); + + // We are using a direct copy of the inbuilt transforms but the directions come out wrong. + // Several of the audio functions use GetFront() for right, so we do the same here. + const FVector Up = Listeners[ListenerIndex].GetUp(); + const FVector Right = Listeners[ListenerIndex].GetFront(); + const FVector Forward = Right ^ Up; + + FMOD_3D_ATTRIBUTES Attributes = { { 0 } }; + Attributes.position = FMODUtils::ConvertWorldVector(ListenerPos); + Attributes.forward = FMODUtils::ConvertUnitVector(Forward); + Attributes.up = FMODUtils::ConvertUnitVector(Up); + Attributes.velocity = FMODUtils::ConvertWorldVector(Listeners[ListenerIndex].Velocity); + + // Expand number of listeners dynamically + if (ListenerIndex >= ListenerCount) + { + Listeners[ListenerIndex] = FFMODListener(); + ListenerCount = ListenerIndex + 1; + verifyfmod(System->setNumListeners(ListenerCount)); + } + verifyfmod(System->setListenerAttributes(ListenerIndex, &Attributes)); + + bListenerMoved = true; + } +} + +void FFMODStudioModule::FinishSetListenerPosition(int NumListeners, float DeltaSeconds) +{ + FMOD::Studio::System *System = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Runtime); + if (!System || NumListeners < 1) + { + return; + } + + if (System && NumListeners < ListenerCount) + { + ListenerCount = NumListeners; + verifyfmod(System->setNumListeners(ListenerCount)); + } + + for (int i = 0; i < ListenerCount; ++i) + { + Listeners[i].UpdateCurrentInteriorSettings(); + } + + // Apply a reverb snapshot from the listener position(s) + AAudioVolume *BestVolume = nullptr; + for (int i = 0; i < ListenerCount; ++i) + { + AAudioVolume *CandidateVolume = Listeners[i].Volume; + + if (BestVolume == nullptr || (IsValid(CandidateVolume) && IsValid(BestVolume) && CandidateVolume->GetPriority() > BestVolume->GetPriority())) + { + BestVolume = CandidateVolume; + } + } + UFMODSnapshotReverb *NewSnapshot = nullptr; + + if (IsValid(BestVolume) && BestVolume->GetReverbSettings().bApplyReverb) + { + NewSnapshot = Cast(BestVolume->GetReverbSettings().ReverbEffect); + } + + if (NewSnapshot != nullptr) + { + FString NewSnapshotName = FMODUtils::LookupNameFromGuid(System, NewSnapshot->AssetGuid); + UE_LOG(LogFMOD, Verbose, TEXT("Starting new snapshot '%s'"), *NewSnapshotName); + + // Try to steal old entry + FFMODSnapshotEntry SnapshotEntry; + int SnapshotEntryIndex = -1; + for (int i = 0; i < ReverbSnapshots.Num(); ++i) + { + if (ReverbSnapshots[i].Snapshot == NewSnapshot) + { + UE_LOG(LogFMOD, Verbose, TEXT("Re-using old entry with intensity %f"), ReverbSnapshots[i].CurrentIntensity()); + SnapshotEntryIndex = i; + break; + } + } + // Create new instance + if (SnapshotEntryIndex == -1) + { + UE_LOG(LogFMOD, Verbose, TEXT("Creating new instance")); + + FMOD::Studio::ID Guid = FMODUtils::ConvertGuid(NewSnapshot->AssetGuid); + FMOD::Studio::EventInstance *NewInstance = nullptr; + FMOD::Studio::EventDescription *EventDesc = nullptr; + System->getEventByID(&Guid, &EventDesc); + if (EventDesc) + { + EventDesc->createInstance(&NewInstance); + if (NewInstance) + { + NewInstance->setParameterByName("Intensity", 0.0f); + NewInstance->start(); + } + } + + SnapshotEntryIndex = ReverbSnapshots.Num(); + ReverbSnapshots.Push(FFMODSnapshotEntry(NewSnapshot, NewInstance)); + } + // Fade up + if (ReverbSnapshots[SnapshotEntryIndex].FadeIntensityEnd == 0.0f) + { + ReverbSnapshots[SnapshotEntryIndex].FadeTo(BestVolume->GetReverbSettings().Volume, BestVolume->GetReverbSettings().FadeTime); + } + } + // Fade out all other entries + for (int i = 0; i < ReverbSnapshots.Num(); ++i) + { + UE_LOG(LogFMOD, Verbose, TEXT("Ramping intensity (%f,%f) -> %f"), ReverbSnapshots[i].FadeIntensityStart, ReverbSnapshots[i].FadeIntensityEnd, + ReverbSnapshots[i].CurrentIntensity()); + ReverbSnapshots[i].Instance->setParameterByName("Intensity", 100.0f * ReverbSnapshots[i].CurrentIntensity()); + + if (ReverbSnapshots[i].Snapshot != NewSnapshot) + { + // Start fading out if needed + if (ReverbSnapshots[i].FadeIntensityEnd != 0.0f) + { + ReverbSnapshots[i].FadeTo(0.0f, ReverbSnapshots[i].FadeDuration); + } + // Finish fading out and remove + else if (ReverbSnapshots[i].CurrentIntensity() == 0.0f) + { + UE_LOG(LogFMOD, Verbose, TEXT("Removing snapshot")); + + ReverbSnapshots[i].Instance->stop(FMOD_STUDIO_STOP_ALLOWFADEOUT); + ReverbSnapshots[i].Instance->release(); + ReverbSnapshots.RemoveAt(i); + --i; // removed entry, redo current index for next one + } + } + } +} + +void FFMODStudioModule::RefreshSettings() +{ + AssetTable.Refresh(); + if (GIsEditor) + { + const UFMODSettings &Settings = *GetDefault(); + BankUpdateNotifier.SetFilePath(Settings.GetFullBankPath() / AssetTable.GetMasterStringsBankPath()); + + // Initialize ActiveLocale based on settings + FString LocaleCode = ""; + + if (Settings.Locales.Num() > 0) + { + LocaleCode = Settings.Locales[0].LocaleCode; + + for (int32 i = 0; i < Settings.Locales.Num(); ++i) + { + if (Settings.Locales[i].bDefault) + { + LocaleCode = Settings.Locales[i].LocaleCode; + break; + } + } + } + + AssetTable.SetLocale(LocaleCode); + } +} + +void FFMODStudioModule::SetInPIE(bool bInPIE, bool simulating) +{ + bIsInPIE = bInPIE; + bSimulating = simulating; + bListenerMoved = true; + ResetInterpolation(); + + if (GIsEditor) + { + BankUpdateNotifier.EnableUpdate(!bInPIE); + } + + FMOD_DEBUG_FLAGS flags; + + if (bInPIE) + { + if (StudioSystem[EFMODSystemContext::Auditioning]) + { + // We currently don't tear down auditioning system but we do stop the playing event. + if (AuditioningInstance) + { + AuditioningInstance->stop(FMOD_STUDIO_STOP_IMMEDIATE); + AuditioningInstance = nullptr; + } + // Also make sure banks are finishing loading so they aren't grabbing file handles. + StudioSystem[EFMODSystemContext::Auditioning]->flushCommands(); + } + + // TODO: Stop sounds for the Editor system? What should happen if the user previews a sequence with transport + // controls then starts a PIE session? What does happen? + + UE_LOG(LogFMOD, Log, TEXT("Creating runtime Studio System")); + ListenerCount = 1; + CreateStudioSystem(EFMODSystemContext::Runtime); + + UE_LOG(LogFMOD, Log, TEXT("Loading Banks")); + LoadBanks(EFMODSystemContext::Runtime); + + const UFMODSettings &Settings = *GetDefault(); + flags = Settings.LoggingLevel; + } + else + { + ReverbSnapshots.Reset(); + DestroyStudioSystem(EFMODSystemContext::Runtime); + flags = FMOD_DEBUG_LEVEL_WARNING; + } + + verifyfmod(FMOD::Debug_Initialize(flags, FMOD_DEBUG_MODE_CALLBACK, FMODLogCallback)); + +} + +UFMODAsset *FFMODStudioModule::FindAssetByName(const FString &Name) +{ + return AssetTable.FindByName(Name); +} + +UFMODEvent *FFMODStudioModule::FindEventByName(const FString &Name) +{ + UFMODAsset *Asset = AssetTable.FindByName(Name); + return Cast(Asset); +} + +FString FFMODStudioModule::GetBankPath(const UFMODBank &Bank) +{ + FString BankPath = AssetTable.GetBankPath(Bank); + + if (!BankPath.IsEmpty()) + { + const UFMODSettings &Settings = *GetDefault(); + BankPath = Settings.GetFullBankPath() / BankPath; + } + + return BankPath; +} + +void FFMODStudioModule::GetAllBankPaths(TArray &Paths, bool IncludeMasterBank) const +{ + AssetTable.GetAllBankPaths(Paths, IncludeMasterBank); +} + +void FFMODStudioModule::SetSystemPaused(bool paused) +{ + if (StudioSystem[EFMODSystemContext::Runtime]) + { + if (bMixerPaused != paused) + { + FMOD::System *LowLevelSystem = nullptr; + verifyfmod(StudioSystem[EFMODSystemContext::Runtime]->getCoreSystem(&LowLevelSystem)); + + // Resume mixer before making calls for Android in particular + if (!paused) + { + LowLevelSystem->mixerResume(); + } + + FMOD::ChannelGroup *MasterChannelGroup = nullptr; + verifyfmod(LowLevelSystem->getMasterChannelGroup(&MasterChannelGroup)); + verifyfmod(MasterChannelGroup->setPaused(paused)); + + if (paused) + { + LowLevelSystem->mixerSuspend(); + } + } + + bMixerPaused = paused; + } +} + +void FFMODStudioModule::PostLoadCallback() +{ +} + +void FFMODStudioModule::ShutdownModule() +{ + UE_LOG(LogFMOD, Verbose, TEXT("FFMODStudioModule shutdown")); + + DestroyStudioSystem(EFMODSystemContext::Auditioning); + DestroyStudioSystem(EFMODSystemContext::Runtime); + DestroyStudioSystem(EFMODSystemContext::Editor); + + if (StudioLibHandle && LowLevelLibHandle) + { + ReleaseFMODFileSystem(); + } + + if (MemPool) + FMemory::Free(MemPool); + + if (GIsEditor) + { + BankUpdateNotifier.BanksUpdatedEvent.RemoveAll(this); + } + + if (UObjectInitialized()) + { + // Unregister tick function. + FTicker::GetCoreTicker().RemoveTicker(TickDelegateHandle); + } + + UE_LOG(LogFMOD, Verbose, TEXT("FFMODStudioModule unloading dynamic libraries")); + if (StudioLibHandle) + { + FPlatformProcess::FreeDllHandle(StudioLibHandle); + StudioLibHandle = nullptr; + } + if (LowLevelLibHandle) + { + FPlatformProcess::FreeDllHandle(LowLevelLibHandle); + LowLevelLibHandle = nullptr; + } + UE_LOG(LogFMOD, Verbose, TEXT("FFMODStudioModule finished unloading")); +} + +struct NamedBankEntry +{ + NamedBankEntry() + : Bank(nullptr) + { + } + NamedBankEntry(const FString &InName, FMOD::Studio::Bank *InBank, FMOD_RESULT InResult) + : Name(InName) + , Bank(InBank) + , Result(InResult) + { + } + + FString Name; + FMOD::Studio::Bank *Bank; + FMOD_RESULT Result; +}; + +bool FFMODStudioModule::AreBanksLoaded() +{ + return bBanksLoaded; +} + +bool FFMODStudioModule::SetLocale(const FString& LocaleName) +{ + const UFMODSettings &Settings = *GetDefault(); + + for (const FFMODProjectLocale& Locale : Settings.Locales) + { + if (Locale.LocaleName == LocaleName) + { + AssetTable.SetLocale(Locale.LocaleCode); + return true; + } + } + + UE_LOG(LogFMOD, Error, TEXT("No project locale named '%s' has been defined."), *LocaleName); + return false; +} + +void FFMODStudioModule::LoadBanks(EFMODSystemContext::Type Type) +{ + const UFMODSettings &Settings = *GetDefault(); + + FailedBankLoads[Type].Reset(); + if (Type == EFMODSystemContext::Auditioning || Type == EFMODSystemContext::Editor) + { + RequiredPlugins.Reset(); + } + + if (StudioSystem[Type] != nullptr && Settings.IsBankPathSet()) + { + UE_LOG(LogFMOD, Verbose, TEXT("LoadBanks for context %s"), FMODSystemContextNames[Type]); + + /* + Queue up all banks to load asynchronously then wait at the end. + */ + bool bLoadAllBanks = ((Type == EFMODSystemContext::Auditioning) || (Type == EFMODSystemContext::Editor) || Settings.bLoadAllBanks); + bool bLoadSampleData = ((Type == EFMODSystemContext::Runtime) && Settings.bLoadAllSampleData); + bool bLockAllBuses = ((Type == EFMODSystemContext::Runtime) && Settings.bLockAllBuses); + FMOD_STUDIO_LOAD_BANK_FLAGS BankFlags = (bLockAllBuses ? FMOD_STUDIO_LOAD_BANK_NORMAL : FMOD_STUDIO_LOAD_BANK_NONBLOCKING); + FMOD_RESULT Result = FMOD_OK; + TArray BankEntries; + + // Always load the master bank at startup + FMOD::Studio::Bank *MasterBank = nullptr; + + if (AssetTable.GetMasterBankPath().IsEmpty()) + { + FString MasterBankFilename = Settings.GetMasterBankFilename(); + UE_LOG(LogFMOD, Warning, TEXT("Master bank (%s) not found."), *MasterBankFilename); + FailedBankLoads[Type].Add(FString::Printf(TEXT("Could not find master bank (%s). Check project settings."), *MasterBankFilename)); + } + else + { + FString MasterBankPath = Settings.GetFullBankPath() / AssetTable.GetMasterBankPath(); + UE_LOG(LogFMOD, Verbose, TEXT("Loading master bank: %s"), *MasterBankPath); + Result = StudioSystem[Type]->loadBankFile(TCHAR_TO_UTF8(*MasterBankPath), BankFlags, &MasterBank); + BankEntries.Add(NamedBankEntry(MasterBankPath, MasterBank, Result)); + } + + if (Result == FMOD_OK) + { + FMOD::Studio::Bank *MasterAssetsBank = nullptr; + FString MasterAssetsBankPath = Settings.GetFullBankPath() / AssetTable.GetMasterAssetsBankPath(); + if (FPaths::FileExists(MasterAssetsBankPath)) + { + Result = StudioSystem[Type]->loadBankFile(TCHAR_TO_UTF8(*MasterAssetsBankPath), BankFlags, &MasterAssetsBank); + BankEntries.Add(NamedBankEntry(MasterAssetsBankPath, MasterAssetsBank, Result)); + } + } + + if (Result == FMOD_OK) + { + // Auditioning needs string bank to get back full paths from events + // Runtime could do without it, but if we load it we can look up guids to names which is helpful + if (MasterBank) + { + FString StringsBankPath = Settings.GetFullBankPath() / AssetTable.GetMasterStringsBankPath(); + UE_LOG(LogFMOD, Verbose, TEXT("Loading strings bank: %s"), *StringsBankPath); + FMOD::Studio::Bank *StringsBank = nullptr; + Result = StudioSystem[Type]->loadBankFile(TCHAR_TO_UTF8(*StringsBankPath), BankFlags, &StringsBank); + BankEntries.Add(NamedBankEntry(StringsBankPath, StringsBank, Result)); + } + + // Optionally load all banks in the directory + if (bLoadAllBanks) + { + UE_LOG(LogFMOD, Verbose, TEXT("Loading all banks")); + TArray BankFiles; + AssetTable.GetAllBankPaths(BankFiles, false); + for (const FString &OtherFile : BankFiles) + { + if (Settings.SkipLoadBankName.Len() && OtherFile.Contains(Settings.SkipLoadBankName)) + { + UE_LOG(LogFMOD, Log, TEXT("Skipping bank: %s"), *OtherFile); + continue; + } + UE_LOG(LogFMOD, Log, TEXT("Loading bank: %s"), *OtherFile); + + FMOD::Studio::Bank *OtherBank; + Result = StudioSystem[Type]->loadBankFile(TCHAR_TO_UTF8(*OtherFile), BankFlags, &OtherBank); + BankEntries.Add(NamedBankEntry(OtherFile, OtherBank, Result)); + } + } + + // Optionally lock all buses to make sure they are created + if (MasterBank && Settings.bLockAllBuses) + { + UE_LOG(LogFMOD, Verbose, TEXT("Locking all buses")); + int BusCount = 0; + verifyfmod(MasterBank->getBusCount(&BusCount)); + if (BusCount != 0) + { + TArray BusList; + BusList.AddZeroed(BusCount); + verifyfmod(MasterBank->getBusList(BusList.GetData(), BusCount, &BusCount)); + BusList.SetNum(BusCount); + for (int BusIdx = 0; BusIdx < BusCount; ++BusIdx) + { + verifyfmod(BusList[BusIdx]->lockChannelGroup()); + } + } + } + } + + // Wait for all banks to load. + StudioSystem[Type]->flushCommands(); + + for (NamedBankEntry &Entry : BankEntries) + { + if (Entry.Result == FMOD_OK) + { + FMOD_STUDIO_LOADING_STATE BankLoadingState = FMOD_STUDIO_LOADING_STATE_ERROR; + Entry.Result = Entry.Bank->getLoadingState(&BankLoadingState); + if (BankLoadingState == FMOD_STUDIO_LOADING_STATE_ERROR) + { + Entry.Bank->unload(); + Entry.Bank = nullptr; + } + else if (bLoadSampleData) + { + verifyfmod(Entry.Bank->loadSampleData()); + } + } + if (Entry.Bank == nullptr || Entry.Result != FMOD_OK) + { + FString ErrorMessage; + if (!FPaths::FileExists(Entry.Name)) + { + ErrorMessage = "File does not exist"; + } + else + { + ErrorMessage = UTF8_TO_TCHAR(FMOD_ErrorString(Entry.Result)); + } + UE_LOG(LogFMOD, Warning, TEXT("Failed to load bank: %s (%s)"), *Entry.Name, *ErrorMessage); + FailedBankLoads[Type].Add(FString::Printf(TEXT("%s (%s)"), *FPaths::GetBaseFilename(Entry.Name), *ErrorMessage)); + } + } + } + + bBanksLoaded = true; +} + +void FFMODStudioModule::HandleBanksUpdated() +{ + UE_LOG(LogFMOD, Verbose, TEXT("Refreshing auditioning system")); + + DestroyStudioSystem(EFMODSystemContext::Auditioning); + + AssetTable.Refresh(); + + CreateStudioSystem(EFMODSystemContext::Auditioning); + LoadBanks(EFMODSystemContext::Auditioning); + + DestroyStudioSystem(EFMODSystemContext::Editor); + CreateStudioSystem(EFMODSystemContext::Editor); + LoadBanks(EFMODSystemContext::Editor); + + BanksReloadedDelegate.Broadcast(); +} + +FMOD::Studio::System *FFMODStudioModule::GetStudioSystem(EFMODSystemContext::Type Context) +{ + if (Context == EFMODSystemContext::Max) + { + Context = (bIsInPIE ? EFMODSystemContext::Runtime : EFMODSystemContext::Auditioning); + } + return StudioSystem[Context]; +} + +FMOD::Studio::EventDescription *FFMODStudioModule::GetEventDescription(const UFMODEvent *Event, EFMODSystemContext::Type Context) +{ + if (Context == EFMODSystemContext::Max) + { + Context = (bIsInPIE ? EFMODSystemContext::Runtime : EFMODSystemContext::Auditioning); + } + if (StudioSystem[Context] != nullptr && IsValid(Event) && Event->AssetGuid.IsValid()) + { + FMOD::Studio::ID Guid = FMODUtils::ConvertGuid(Event->AssetGuid); + FMOD::Studio::EventDescription *EventDesc = nullptr; + StudioSystem[Context]->getEventByID(&Guid, &EventDesc); + return EventDesc; + } + return nullptr; +} + +FMOD::Studio::EventInstance *FFMODStudioModule::CreateAuditioningInstance(const UFMODEvent *Event) +{ + StopAuditioningInstance(); + if (IsValid(Event)) + { + FMOD::Studio::EventDescription *EventDesc = GetEventDescription(Event, EFMODSystemContext::Auditioning); + if (EventDesc) + { + FMOD_RESULT Result = EventDesc->createInstance(&AuditioningInstance); + if (Result == FMOD_OK) + { + return AuditioningInstance; + } + } + } + return nullptr; +} + +void FFMODStudioModule::StopAuditioningInstance() +{ + if (AuditioningInstance) + { + // Don't bother checking for errors just in case auditioning is already shutting down + AuditioningInstance->stop(FMOD_STUDIO_STOP_ALLOWFADEOUT); + AuditioningInstance->release(); + AuditioningInstance = nullptr; + } +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODStudioPrivatePCH.h b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODStudioPrivatePCH.h new file mode 100644 index 0000000..ef6c266 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODStudioPrivatePCH.h @@ -0,0 +1,9 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "Components/SceneComponent.h" +#include "Runtime/Launch/Resources/Version.h" + +DECLARE_LOG_CATEGORY_EXTERN(LogFMOD, Log, All); \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/FMODVCA.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODVCA.cpp new file mode 100644 index 0000000..27ae3da --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/FMODVCA.cpp @@ -0,0 +1,20 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODVCA.h" +#include "FMODStudioModule.h" + +UFMODVCA::UFMODVCA(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ +} + +/** Get tags to show in content view */ +void UFMODVCA::GetAssetRegistryTags(TArray &OutTags) const +{ + Super::GetAssetRegistryTags(OutTags); +} + +FString UFMODVCA::GetDesc() +{ + return FString::Printf(TEXT("VCA %s"), *AssetGuid.ToString(EGuidFormats::DigitsWithHyphensInBraces)); +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlSection.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlSection.cpp new file mode 100644 index 0000000..b1602b2 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlSection.cpp @@ -0,0 +1,49 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODEventControlSection.h" +#include "FMODEventControlSectionTemplate.h" +#include "Channels/MovieSceneChannelProxy.h" +#include "UObject/SequencerObjectVersion.h" +#include "UObject/Package.h" + +FFMODEventControlChannel::FFMODEventControlChannel() +{ + SetEnum(FindObject(ANY_PACKAGE, TEXT("EFMODEventControlKey"))); +} + +UFMODEventControlSection::UFMODEventControlSection(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ + SetRange(TRange::All()); + + int32 LinkerCustomVersion = GetLinkerCustomVersion(FSequencerObjectVersion::GUID); + EMovieSceneCompletionMode CompletionMode; + + if (LinkerCustomVersion < FSequencerObjectVersion::WhenFinishedDefaultsToRestoreState) + { + CompletionMode = EMovieSceneCompletionMode::KeepState; + } + else if (LinkerCustomVersion < FSequencerObjectVersion::WhenFinishedDefaultsToProjectDefault) + { + CompletionMode = EMovieSceneCompletionMode::RestoreState; + } + else + { + CompletionMode = EMovieSceneCompletionMode::ProjectDefault; + } + +#if WITH_EDITOR + + ChannelProxy = MakeShared(ControlKeys, FMovieSceneChannelMetaData(), TMovieSceneExternalValue()); + +#else + + ChannelProxy = MakeShared(ControlKeys); + +#endif +} + +FMovieSceneEvalTemplatePtr UFMODEventControlSection::GenerateTemplate() const +{ + return FFMODEventControlSectionTemplate(*this); +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlSection.h b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlSection.h new file mode 100644 index 0000000..dc8f282 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlSection.h @@ -0,0 +1,90 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Curves/KeyHandle.h" +#include "MovieSceneClipboard.h" +#include "MovieSceneSection.h" +#include "Channels/MovieSceneByteChannel.h" +#include "FMODEventControlSection.generated.h" + +/** Defines the types of FMOD event control keys. */ +UENUM() +enum class EFMODEventControlKey : uint8 +{ + Stop = 0, + Play = 1 +}; + +USTRUCT() +struct FFMODEventControlChannel : public FMovieSceneByteChannel +{ + GENERATED_BODY() + + FFMODEventControlChannel(); +}; + +template <> +struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 +{ + enum + { + WithStructuredSerializeFromMismatchedTag = true + }; +}; + +template <> +struct TMovieSceneChannelTraits : TMovieSceneChannelTraitsBase +{ + enum + { + SupportsDefaults = false + }; + +#if WITH_EDITOR + + /** Byte channels can have external values (ie, they can get their values from external objects for UI purposes) */ + typedef TMovieSceneExternalValue ExtendedEditorDataType; + +#endif +}; + +/** FMOD Event control section */ +UCLASS(MinimalAPI) +class UFMODEventControlSection : public UMovieSceneSection +{ + GENERATED_UCLASS_BODY() + +public: + /** Channel containing the event control keys */ + UPROPERTY() + FFMODEventControlChannel ControlKeys; + +protected: + //~ UMovieSceneSection interface + virtual FMovieSceneEvalTemplatePtr GenerateTemplate() const override; +}; + +inline void AssignValue(FFMODEventControlChannel *InChannel, FKeyHandle InKeyHandle, EFMODEventControlKey InValue) +{ + TMovieSceneChannelData ChannelData = InChannel->GetData(); + int32 ValueIndex = ChannelData.GetIndex(InKeyHandle); + + if (ValueIndex != INDEX_NONE) + { + ChannelData.GetValues()[ValueIndex] = (uint8)InValue; + } +} + +inline bool EvaluateChannel(const FFMODEventControlChannel *InChannel, FFrameTime InTime, EFMODEventControlKey &OutValue) +{ + uint8 RawValue = 0; + if (InChannel->Evaluate(InTime, RawValue)) + { + OutValue = (EFMODEventControlKey)RawValue; + return true; + } + return false; +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlSectionTemplate.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlSectionTemplate.cpp new file mode 100644 index 0000000..ec23d53 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlSectionTemplate.cpp @@ -0,0 +1,139 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODEventControlSectionTemplate.h" +#include "FMODAmbientSound.h" +#include "FMODAudioComponent.h" +#include "Evaluation/MovieSceneEvaluation.h" +#include "IMovieScenePlayer.h" + +struct FPlayingToken : IMovieScenePreAnimatedToken +{ + FPlayingToken(UObject &InObject) + { + bPlaying = false; + + if (UFMODAudioComponent *AudioComponent = Cast(&InObject)) + { + if (IsValid(AudioComponent)) + { + bPlaying = AudioComponent->IsPlaying(); + } + } + } + + virtual void RestoreState(UObject &Object, IMovieScenePlayer &Player) override + { + UFMODAudioComponent *AudioComponent = CastChecked(&Object); + + if (AudioComponent) + { + if (bPlaying) + { + AudioComponent->Play(); + } + else + { + AudioComponent->Stop(); + } + } + } + +private: + bool bPlaying; +}; + +struct FPlayingTokenProducer : IMovieScenePreAnimatedTokenProducer +{ + static FMovieSceneAnimTypeID GetAnimTypeID() { return TMovieSceneAnimTypeID(); } + +private: + virtual IMovieScenePreAnimatedTokenPtr CacheExistingState(UObject &Object) const override { return FPlayingToken(Object); } +}; + +struct FFMODEventKeyState : IPersistentEvaluationData +{ + FKeyHandle LastKeyHandle; + FKeyHandle InvalidKeyHandle; +}; + +struct FFMODEventControlExecutionToken : IMovieSceneExecutionToken +{ + FFMODEventControlExecutionToken(EFMODEventControlKey InEventControlKey, FFrameTime InKeyTime) + : EventControlKey(InEventControlKey) + , KeyTime(InKeyTime) + { + } + + /** Execute this token, operating on all objects referenced by 'Operand' */ + virtual void Execute(const FMovieSceneContext &Context, const FMovieSceneEvaluationOperand &Operand, FPersistentEvaluationData &PersistentData, + IMovieScenePlayer &Player) + { + for (TWeakObjectPtr<> &WeakObject : Player.FindBoundObjects(Operand)) + { + UFMODAudioComponent *AudioComponent = Cast(WeakObject.Get()); + + if (!AudioComponent) + { + AFMODAmbientSound *AmbientSound = Cast(WeakObject.Get()); + AudioComponent = AmbientSound ? AmbientSound->AudioComponent : nullptr; + } + + if (IsValid(AudioComponent)) + { + Player.SavePreAnimatedState(*AudioComponent, FPlayingTokenProducer::GetAnimTypeID(), FPlayingTokenProducer()); + + if (EventControlKey == EFMODEventControlKey::Play) + { + if (AudioComponent->IsPlaying()) + { + AudioComponent->Stop(); + } + + EFMODSystemContext::Type SystemContext = + (GWorld && GWorld->WorldType == EWorldType::Editor) ? EFMODSystemContext::Editor : EFMODSystemContext::Runtime; + AudioComponent->PlayInternal(SystemContext); + } + else if (EventControlKey == EFMODEventControlKey::Stop) + { + AudioComponent->Stop(); + } + } + } + } + + EFMODEventControlKey EventControlKey; + FFrameTime KeyTime; +}; + +FFMODEventControlSectionTemplate::FFMODEventControlSectionTemplate(const UFMODEventControlSection &Section) + : ControlKeys(Section.ControlKeys) +{ +} + +void FFMODEventControlSectionTemplate::Evaluate(const FMovieSceneEvaluationOperand &Operand, const FMovieSceneContext &Context, + const FPersistentEvaluationData &PersistentData, FMovieSceneExecutionTokens &ExecutionTokens) const +{ + const bool bPlaying = Context.IsSilent() == false && Context.GetDirection() == EPlayDirection::Forwards && + Context.GetRange().Size() >= FFrameTime(0) && Context.GetStatus() == EMovieScenePlayerStatus::Playing; + + if (!bPlaying) + { + ExecutionTokens.Add(FFMODEventControlExecutionToken(EFMODEventControlKey::Stop, FFrameTime(0))); + } + else + { + TRange PlaybackRange = Context.GetFrameNumberRange(); + TMovieSceneChannelData ChannelData = ControlKeys.GetData(); + + // Find the index of the key handle that exists before this time + TArrayView Times = ChannelData.GetTimes(); + TArrayView Values = ChannelData.GetValues(); + + const int32 LastKeyIndex = Algo::UpperBound(Times, PlaybackRange.GetUpperBoundValue()) - 1; + if (LastKeyIndex >= 0 && PlaybackRange.Contains(Times[LastKeyIndex])) + { + FFMODEventControlExecutionToken NewToken((EFMODEventControlKey)Values[LastKeyIndex], Times[LastKeyIndex]); + ExecutionTokens.Add(MoveTemp(NewToken)); + } + } +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlSectionTemplate.h b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlSectionTemplate.h new file mode 100644 index 0000000..b0a1e03 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlSectionTemplate.h @@ -0,0 +1,26 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Evaluation/MovieSceneEvalTemplate.h" +#include "FMODEventControlSection.h" +#include "FMODEventControlSectionTemplate.generated.h" + +USTRUCT() +struct FFMODEventControlSectionTemplate : public FMovieSceneEvalTemplate +{ + GENERATED_BODY() + + FFMODEventControlSectionTemplate() {} + FFMODEventControlSectionTemplate(const UFMODEventControlSection &Section); + + UPROPERTY() + FFMODEventControlChannel ControlKeys; + +private: + virtual UScriptStruct &GetScriptStructImpl() const override { return *StaticStruct(); } + virtual void Evaluate(const FMovieSceneEvaluationOperand &Operand, const FMovieSceneContext &Context, + const FPersistentEvaluationData &PersistentData, FMovieSceneExecutionTokens &ExecutionTokens) const override; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlTrack.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlTrack.cpp new file mode 100644 index 0000000..1c34bb8 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlTrack.cpp @@ -0,0 +1,70 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODEventControlTrack.h" +#include "FMODEventControlSection.h" +#include "IMovieScenePlayer.h" +#include "FMODEventControlSectionTemplate.h" +#include "MovieSceneCommonHelpers.h" + +#define LOCTEXT_NAMESPACE "FMODEventControlTrack" + +UFMODEventControlTrack::UFMODEventControlTrack(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ +#if WITH_EDITORONLY_DATA + TrackTint = FColor(255, 255, 255, 160); +#endif +} + +const TArray &UFMODEventControlTrack::GetAllSections() const +{ + return ControlSections; +} + +void UFMODEventControlTrack::RemoveAllAnimationData() +{ + // do nothing +} + +bool UFMODEventControlTrack::HasSection(const UMovieSceneSection &Section) const +{ + return ControlSections.Contains(&Section); +} + +void UFMODEventControlTrack::AddSection(UMovieSceneSection &Section) +{ + ControlSections.Add(&Section); +} + +void UFMODEventControlTrack::RemoveSection(UMovieSceneSection &Section) +{ + ControlSections.Remove(&Section); +} + +bool UFMODEventControlTrack::IsEmpty() const +{ + return ControlSections.Num() == 0; +} + +void UFMODEventControlTrack::AddNewSection(FFrameNumber SectionTime) +{ + if (MovieSceneHelpers::FindSectionAtTime(ControlSections, SectionTime) == nullptr) + { + UFMODEventControlSection *NewSection = Cast(CreateNewSection()); + ControlSections.Add(NewSection); + } +} + +UMovieSceneSection *UFMODEventControlTrack::CreateNewSection() +{ + return NewObject(this); +} + +#if WITH_EDITORONLY_DATA +FText UFMODEventControlTrack::GetDefaultDisplayName() const +{ + return LOCTEXT("DisplayName", "FMOD Event"); +} +#endif + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlTrack.h b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlTrack.h new file mode 100644 index 0000000..86a19b5 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventControlTrack.h @@ -0,0 +1,39 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "MovieSceneNameableTrack.h" +#include "FMODEventControlTrack.generated.h" + +/** Handles control of an FMOD Event */ +UCLASS(MinimalAPI) +class UFMODEventControlTrack : public UMovieSceneNameableTrack +{ + GENERATED_UCLASS_BODY() + +public: + virtual TArray GetAllControlSections() const { return ControlSections; } + +public: + // Begin UMovieSceneTrack interface + virtual void RemoveAllAnimationData() override; + virtual bool HasSection(const UMovieSceneSection &Section) const override; + virtual void AddSection(UMovieSceneSection &Section) override; + virtual void RemoveSection(UMovieSceneSection &Section) override; + virtual bool IsEmpty() const override; + virtual const TArray &GetAllSections() const override; + virtual void AddNewSection(FFrameNumber SectionTime); + virtual UMovieSceneSection *CreateNewSection() override; +// End UMovieSceneTrack interface + +#if WITH_EDITORONLY_DATA + virtual FText GetDefaultDisplayName() const override; +#endif + +private: + /** List of all event control sections. */ + UPROPERTY() + TArray ControlSections; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventParameterSectionTemplate.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventParameterSectionTemplate.cpp new file mode 100644 index 0000000..9131dc7 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventParameterSectionTemplate.cpp @@ -0,0 +1,109 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2017. + +#include "FMODEventParameterSectionTemplate.h" +#include "FMODAmbientSound.h" +#include "FMODEvent.h" +#include "FMODEventParameterTrack.h" +#include "IMovieScenePlayer.h" +#include "fmod_studio.hpp" + +struct FFMODEventParameterPreAnimatedToken : IMovieScenePreAnimatedToken +{ + FFMODEventParameterPreAnimatedToken() {} + + FFMODEventParameterPreAnimatedToken(FFMODEventParameterPreAnimatedToken &&) = default; + FFMODEventParameterPreAnimatedToken &operator=(FFMODEventParameterPreAnimatedToken &&) = default; + + virtual void RestoreState(UObject &Object, IMovieScenePlayer &Player) override + { + UFMODAudioComponent *AudioComponent = CastChecked(&Object); + + if (IsValid(AudioComponent)) + { + for (FScalarParameterNameAndValue &Value : Values) + { + AudioComponent->SetParameter(Value.ParameterName, Value.Value); + } + } + } + + TArray Values; +}; + +struct FFMODEventParameterPreAnimatedTokenProducer : IMovieScenePreAnimatedTokenProducer +{ + virtual IMovieScenePreAnimatedTokenPtr CacheExistingState(UObject &Object) const override + { + UFMODAudioComponent *AudioComponent = CastChecked(&Object); + + FFMODEventParameterPreAnimatedToken Token; + + if (IsValid(AudioComponent) && AudioComponent->Event) + { + TArray ParameterDescriptions; + AudioComponent->Event->GetParameterDescriptions(ParameterDescriptions); + + for (const FMOD_STUDIO_PARAMETER_DESCRIPTION &ParameterDescription : ParameterDescriptions) + { + float Value = AudioComponent->GetParameter(ParameterDescription.name); + Token.Values.Add(FScalarParameterNameAndValue(ParameterDescription.name, Value)); + } + } + + return MoveTemp(Token); + } +}; + +struct FFMODEventParameterExecutionToken : IMovieSceneExecutionToken +{ + FFMODEventParameterExecutionToken() = default; + + FFMODEventParameterExecutionToken(FFMODEventParameterExecutionToken &&) = default; + FFMODEventParameterExecutionToken &operator=(FFMODEventParameterExecutionToken &&) = default; + + // Non-copyable + FFMODEventParameterExecutionToken(const FFMODEventParameterExecutionToken &) = delete; + FFMODEventParameterExecutionToken &operator=(const FFMODEventParameterExecutionToken &) = delete; + + virtual void Execute(const FMovieSceneContext &Context, const FMovieSceneEvaluationOperand &Operand, FPersistentEvaluationData &PersistentData, + IMovieScenePlayer &Player) + { + for (TWeakObjectPtr<> &WeakObject : Player.FindBoundObjects(Operand)) + { + UFMODAudioComponent *AudioComponent = Cast(WeakObject.Get()); + + if (!AudioComponent) + { + AFMODAmbientSound *AmbientSound = Cast(WeakObject.Get()); + AudioComponent = AmbientSound ? AmbientSound->AudioComponent : nullptr; + } + + if (IsValid(AudioComponent)) + { + Player.SavePreAnimatedState( + *AudioComponent, TMovieSceneAnimTypeID(), FFMODEventParameterPreAnimatedTokenProducer()); + + for (const FScalarParameterNameAndValue &NameAndValue : Values.ScalarValues) + { + AudioComponent->SetParameter(NameAndValue.ParameterName, NameAndValue.Value); + } + } + } + } + + FEvaluatedParameterSectionValues Values; +}; + +FFMODEventParameterSectionTemplate::FFMODEventParameterSectionTemplate( + const UMovieSceneParameterSection &Section, const UFMODEventParameterTrack &Track) + : FMovieSceneParameterSectionTemplate(Section) +{ +} + +void FFMODEventParameterSectionTemplate::Evaluate(const FMovieSceneEvaluationOperand &Operand, const FMovieSceneContext &Context, + const FPersistentEvaluationData &PersistentData, FMovieSceneExecutionTokens &ExecutionTokens) const +{ + FFMODEventParameterExecutionToken ExecutionToken; + EvaluateCurves(Context, ExecutionToken.Values); + ExecutionTokens.Add(MoveTemp(ExecutionToken)); +} diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventParameterSectionTemplate.h b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventParameterSectionTemplate.h new file mode 100644 index 0000000..16da4ca --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventParameterSectionTemplate.h @@ -0,0 +1,24 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Evaluation/MovieSceneParameterTemplate.h" +#include "FMODEventParameterSectionTemplate.generated.h" + +class UFMODEventParameterTrack; + +USTRUCT() +struct FFMODEventParameterSectionTemplate : public FMovieSceneParameterSectionTemplate +{ + GENERATED_BODY() + + FFMODEventParameterSectionTemplate() {} + FFMODEventParameterSectionTemplate(const UMovieSceneParameterSection &Section, const UFMODEventParameterTrack &Track); + +private: + virtual UScriptStruct &GetScriptStructImpl() const override { return *StaticStruct(); } + virtual void Evaluate(const FMovieSceneEvaluationOperand &Operand, const FMovieSceneContext &Context, + const FPersistentEvaluationData &PersistentData, FMovieSceneExecutionTokens &ExecutionTokens) const override; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventParameterTrack.cpp b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventParameterTrack.cpp new file mode 100644 index 0000000..011c884 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventParameterTrack.cpp @@ -0,0 +1,77 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODEventParameterTrack.h" +#include "FMODEventParameterSectionTemplate.h" +#include "IMovieScenePlayer.h" +#include "MovieSceneCommonHelpers.h" + +#define LOCTEXT_NAMESPACE "FMODEventParameterTrack" + +UFMODEventParameterTrack::UFMODEventParameterTrack(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ +#if WITH_EDITORONLY_DATA + TrackTint = FColor(0, 170, 255, 65); +#endif +} + +FMovieSceneEvalTemplatePtr UFMODEventParameterTrack::CreateTemplateForSection(const UMovieSceneSection &InSection) const +{ + return FFMODEventParameterSectionTemplate(*CastChecked(&InSection), *this); +} + +UMovieSceneSection *UFMODEventParameterTrack::CreateNewSection() +{ + return NewObject(this, UMovieSceneParameterSection::StaticClass(), NAME_None, RF_Transactional); +} + +void UFMODEventParameterTrack::RemoveAllAnimationData() +{ + Sections.Empty(); +} + +bool UFMODEventParameterTrack::HasSection(const UMovieSceneSection &Section) const +{ + return Sections.Contains(&Section); +} + +void UFMODEventParameterTrack::AddSection(UMovieSceneSection &Section) +{ + Sections.Add(&Section); +} + +void UFMODEventParameterTrack::RemoveSection(UMovieSceneSection &Section) +{ + Sections.Remove(&Section); +} + +bool UFMODEventParameterTrack::IsEmpty() const +{ + return Sections.Num() == 0; +} + +const TArray &UFMODEventParameterTrack::GetAllSections() const +{ + return Sections; +} + +#if WITH_EDITORONLY_DATA +FText UFMODEventParameterTrack::GetDefaultDisplayName() const +{ + return LOCTEXT("DisplayName", "FMOD Event Parameter"); +} +#endif + +void UFMODEventParameterTrack::AddParameterKey(FName ParameterName, FFrameNumber Time, float Value) +{ + UMovieSceneParameterSection *NearestSection = Cast(MovieSceneHelpers::FindNearestSectionAtTime(Sections, Time)); + if (NearestSection == nullptr) + { + NearestSection = Cast(CreateNewSection()); + NearestSection->SetRange(TRange::Inclusive(Time, Time)); + Sections.Add(NearestSection); + } + NearestSection->AddScalarParameterKey(ParameterName, Time, Value); +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventParameterTrack.h b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventParameterTrack.h new file mode 100644 index 0000000..076e036 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Private/Sequencer/FMODEventParameterTrack.h @@ -0,0 +1,41 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/ObjectMacros.h" +#include "Sections/MovieSceneParameterSection.h" +#include "MovieSceneNameableTrack.h" +#include "FMODEventParameterTrack.generated.h" + +/** Handles manipulation of event parameters in a movie scene. */ +UCLASS(MinimalAPI) +class UFMODEventParameterTrack : public UMovieSceneNameableTrack +{ + GENERATED_UCLASS_BODY() + +public: + // Begin UMovieSceneTrack interface + virtual FMovieSceneEvalTemplatePtr CreateTemplateForSection(const UMovieSceneSection &InSection) const override; + virtual UMovieSceneSection *CreateNewSection() override; + virtual void RemoveAllAnimationData() override; + virtual bool HasSection(const UMovieSceneSection &Section) const override; + virtual void AddSection(UMovieSceneSection &Section) override; + virtual void RemoveSection(UMovieSceneSection &Section) override; + virtual bool IsEmpty() const override; + virtual const TArray &GetAllSections() const override; +// End UMovieSceneTrack interface + +#if WITH_EDITORONLY_DATA + virtual FText GetDefaultDisplayName() const override; +#endif + +public: + /** Adds a (scalar) event parameter key to the track. */ + void FMODSTUDIO_API AddParameterKey(FName ParameterName, FFrameNumber Time, float Value); + +private: + /** The sections owned by this track. */ + UPROPERTY() + TArray Sections; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod.h b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod.h new file mode 100644 index 0000000..c12bc9e --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod.h @@ -0,0 +1,665 @@ +/* ======================================================================================== */ +/* FMOD Core API - C header file. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* */ +/* Use this header in conjunction with fmod_common.h (which contains all the constants / */ +/* callbacks) to develop using the C interface */ +/* */ +/* For more detail visit: */ +/* https://fmod.com/resources/documentation-api?version=2.0&page=core-api.html */ +/* ======================================================================================== */ + +#ifndef _FMOD_H +#define _FMOD_H + +#include "fmod_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + FMOD global system functions (optional). +*/ +FMOD_RESULT F_API FMOD_Memory_Initialize (void *poolmem, int poollen, FMOD_MEMORY_ALLOC_CALLBACK useralloc, FMOD_MEMORY_REALLOC_CALLBACK userrealloc, FMOD_MEMORY_FREE_CALLBACK userfree, FMOD_MEMORY_TYPE memtypeflags); +FMOD_RESULT F_API FMOD_Memory_GetStats (int *currentalloced, int *maxalloced, FMOD_BOOL blocking); +FMOD_RESULT F_API FMOD_Debug_Initialize (FMOD_DEBUG_FLAGS flags, FMOD_DEBUG_MODE mode, FMOD_DEBUG_CALLBACK callback, const char *filename); +FMOD_RESULT F_API FMOD_File_SetDiskBusy (int busy); +FMOD_RESULT F_API FMOD_File_GetDiskBusy (int *busy); + +/* + FMOD System factory functions. Use this to create an FMOD System Instance. below you will see FMOD_System_Init/Close to get started. +*/ +FMOD_RESULT F_API FMOD_System_Create (FMOD_SYSTEM **system); +FMOD_RESULT F_API FMOD_System_Release (FMOD_SYSTEM *system); + +/* + 'System' API +*/ + +/* Setup functions. */ +FMOD_RESULT F_API FMOD_System_SetOutput (FMOD_SYSTEM *system, FMOD_OUTPUTTYPE output); +FMOD_RESULT F_API FMOD_System_GetOutput (FMOD_SYSTEM *system, FMOD_OUTPUTTYPE *output); +FMOD_RESULT F_API FMOD_System_GetNumDrivers (FMOD_SYSTEM *system, int *numdrivers); +FMOD_RESULT F_API FMOD_System_GetDriverInfo (FMOD_SYSTEM *system, int id, char *name, int namelen, FMOD_GUID *guid, int *systemrate, FMOD_SPEAKERMODE *speakermode, int *speakermodechannels); +FMOD_RESULT F_API FMOD_System_SetDriver (FMOD_SYSTEM *system, int driver); +FMOD_RESULT F_API FMOD_System_GetDriver (FMOD_SYSTEM *system, int *driver); +FMOD_RESULT F_API FMOD_System_SetSoftwareChannels (FMOD_SYSTEM *system, int numsoftwarechannels); +FMOD_RESULT F_API FMOD_System_GetSoftwareChannels (FMOD_SYSTEM *system, int *numsoftwarechannels); +FMOD_RESULT F_API FMOD_System_SetSoftwareFormat (FMOD_SYSTEM *system, int samplerate, FMOD_SPEAKERMODE speakermode, int numrawspeakers); +FMOD_RESULT F_API FMOD_System_GetSoftwareFormat (FMOD_SYSTEM *system, int *samplerate, FMOD_SPEAKERMODE *speakermode, int *numrawspeakers); +FMOD_RESULT F_API FMOD_System_SetDSPBufferSize (FMOD_SYSTEM *system, unsigned int bufferlength, int numbuffers); +FMOD_RESULT F_API FMOD_System_GetDSPBufferSize (FMOD_SYSTEM *system, unsigned int *bufferlength, int *numbuffers); +FMOD_RESULT F_API FMOD_System_SetFileSystem (FMOD_SYSTEM *system, FMOD_FILE_OPEN_CALLBACK useropen, FMOD_FILE_CLOSE_CALLBACK userclose, FMOD_FILE_READ_CALLBACK userread, FMOD_FILE_SEEK_CALLBACK userseek, FMOD_FILE_ASYNCREAD_CALLBACK userasyncread, FMOD_FILE_ASYNCCANCEL_CALLBACK userasynccancel, int blockalign); +FMOD_RESULT F_API FMOD_System_AttachFileSystem (FMOD_SYSTEM *system, FMOD_FILE_OPEN_CALLBACK useropen, FMOD_FILE_CLOSE_CALLBACK userclose, FMOD_FILE_READ_CALLBACK userread, FMOD_FILE_SEEK_CALLBACK userseek); +FMOD_RESULT F_API FMOD_System_SetAdvancedSettings (FMOD_SYSTEM *system, FMOD_ADVANCEDSETTINGS *settings); +FMOD_RESULT F_API FMOD_System_GetAdvancedSettings (FMOD_SYSTEM *system, FMOD_ADVANCEDSETTINGS *settings); +FMOD_RESULT F_API FMOD_System_SetCallback (FMOD_SYSTEM *system, FMOD_SYSTEM_CALLBACK callback, FMOD_SYSTEM_CALLBACK_TYPE callbackmask); + +/* Plug-in support. */ +FMOD_RESULT F_API FMOD_System_SetPluginPath (FMOD_SYSTEM *system, const char *path); +FMOD_RESULT F_API FMOD_System_LoadPlugin (FMOD_SYSTEM *system, const char *filename, unsigned int *handle, unsigned int priority); +FMOD_RESULT F_API FMOD_System_UnloadPlugin (FMOD_SYSTEM *system, unsigned int handle); +FMOD_RESULT F_API FMOD_System_GetNumNestedPlugins (FMOD_SYSTEM *system, unsigned int handle, int *count); +FMOD_RESULT F_API FMOD_System_GetNestedPlugin (FMOD_SYSTEM *system, unsigned int handle, int index, unsigned int *nestedhandle); +FMOD_RESULT F_API FMOD_System_GetNumPlugins (FMOD_SYSTEM *system, FMOD_PLUGINTYPE plugintype, int *numplugins); +FMOD_RESULT F_API FMOD_System_GetPluginHandle (FMOD_SYSTEM *system, FMOD_PLUGINTYPE plugintype, int index, unsigned int *handle); +FMOD_RESULT F_API FMOD_System_GetPluginInfo (FMOD_SYSTEM *system, unsigned int handle, FMOD_PLUGINTYPE *plugintype, char *name, int namelen, unsigned int *version); +FMOD_RESULT F_API FMOD_System_SetOutputByPlugin (FMOD_SYSTEM *system, unsigned int handle); +FMOD_RESULT F_API FMOD_System_GetOutputByPlugin (FMOD_SYSTEM *system, unsigned int *handle); +FMOD_RESULT F_API FMOD_System_CreateDSPByPlugin (FMOD_SYSTEM *system, unsigned int handle, FMOD_DSP **dsp); +FMOD_RESULT F_API FMOD_System_GetDSPInfoByPlugin (FMOD_SYSTEM *system, unsigned int handle, const FMOD_DSP_DESCRIPTION **description); +FMOD_RESULT F_API FMOD_System_RegisterCodec (FMOD_SYSTEM *system, FMOD_CODEC_DESCRIPTION *description, unsigned int *handle, unsigned int priority); +FMOD_RESULT F_API FMOD_System_RegisterDSP (FMOD_SYSTEM *system, const FMOD_DSP_DESCRIPTION *description, unsigned int *handle); +FMOD_RESULT F_API FMOD_System_RegisterOutput (FMOD_SYSTEM *system, const FMOD_OUTPUT_DESCRIPTION *description, unsigned int *handle); + +/* Init/Close. */ +FMOD_RESULT F_API FMOD_System_Init (FMOD_SYSTEM *system, int maxchannels, FMOD_INITFLAGS flags, void *extradriverdata); +FMOD_RESULT F_API FMOD_System_Close (FMOD_SYSTEM *system); + +/* General post-init system functions. */ +FMOD_RESULT F_API FMOD_System_Update (FMOD_SYSTEM *system); +FMOD_RESULT F_API FMOD_System_SetSpeakerPosition (FMOD_SYSTEM *system, FMOD_SPEAKER speaker, float x, float y, FMOD_BOOL active); +FMOD_RESULT F_API FMOD_System_GetSpeakerPosition (FMOD_SYSTEM *system, FMOD_SPEAKER speaker, float *x, float *y, FMOD_BOOL *active); +FMOD_RESULT F_API FMOD_System_SetStreamBufferSize (FMOD_SYSTEM *system, unsigned int filebuffersize, FMOD_TIMEUNIT filebuffersizetype); +FMOD_RESULT F_API FMOD_System_GetStreamBufferSize (FMOD_SYSTEM *system, unsigned int *filebuffersize, FMOD_TIMEUNIT *filebuffersizetype); +FMOD_RESULT F_API FMOD_System_Set3DSettings (FMOD_SYSTEM *system, float dopplerscale, float distancefactor, float rolloffscale); +FMOD_RESULT F_API FMOD_System_Get3DSettings (FMOD_SYSTEM *system, float *dopplerscale, float *distancefactor, float *rolloffscale); +FMOD_RESULT F_API FMOD_System_Set3DNumListeners (FMOD_SYSTEM *system, int numlisteners); +FMOD_RESULT F_API FMOD_System_Get3DNumListeners (FMOD_SYSTEM *system, int *numlisteners); +FMOD_RESULT F_API FMOD_System_Set3DListenerAttributes (FMOD_SYSTEM *system, int listener, const FMOD_VECTOR *pos, const FMOD_VECTOR *vel, const FMOD_VECTOR *forward, const FMOD_VECTOR *up); +FMOD_RESULT F_API FMOD_System_Get3DListenerAttributes (FMOD_SYSTEM *system, int listener, FMOD_VECTOR *pos, FMOD_VECTOR *vel, FMOD_VECTOR *forward, FMOD_VECTOR *up); +FMOD_RESULT F_API FMOD_System_Set3DRolloffCallback (FMOD_SYSTEM *system, FMOD_3D_ROLLOFF_CALLBACK callback); +FMOD_RESULT F_API FMOD_System_MixerSuspend (FMOD_SYSTEM *system); +FMOD_RESULT F_API FMOD_System_MixerResume (FMOD_SYSTEM *system); +FMOD_RESULT F_API FMOD_System_GetDefaultMixMatrix (FMOD_SYSTEM *system, FMOD_SPEAKERMODE sourcespeakermode, FMOD_SPEAKERMODE targetspeakermode, float *matrix, int matrixhop); +FMOD_RESULT F_API FMOD_System_GetSpeakerModeChannels (FMOD_SYSTEM *system, FMOD_SPEAKERMODE mode, int *channels); + +/* System information functions. */ +FMOD_RESULT F_API FMOD_System_GetVersion (FMOD_SYSTEM *system, unsigned int *version); +FMOD_RESULT F_API FMOD_System_GetOutputHandle (FMOD_SYSTEM *system, void **handle); +FMOD_RESULT F_API FMOD_System_GetChannelsPlaying (FMOD_SYSTEM *system, int *channels, int *realchannels); +FMOD_RESULT F_API FMOD_System_GetCPUUsage (FMOD_SYSTEM *system, float *dsp, float *stream, float *geometry, float *update, float *total); +FMOD_RESULT F_API FMOD_System_GetFileUsage (FMOD_SYSTEM *system, long long *sampleBytesRead, long long *streamBytesRead, long long *otherBytesRead); + +/* Sound/DSP/Channel/FX creation and retrieval. */ +FMOD_RESULT F_API FMOD_System_CreateSound (FMOD_SYSTEM *system, const char *name_or_data, FMOD_MODE mode, FMOD_CREATESOUNDEXINFO *exinfo, FMOD_SOUND **sound); +FMOD_RESULT F_API FMOD_System_CreateStream (FMOD_SYSTEM *system, const char *name_or_data, FMOD_MODE mode, FMOD_CREATESOUNDEXINFO *exinfo, FMOD_SOUND **sound); +FMOD_RESULT F_API FMOD_System_CreateDSP (FMOD_SYSTEM *system, const FMOD_DSP_DESCRIPTION *description, FMOD_DSP **dsp); +FMOD_RESULT F_API FMOD_System_CreateDSPByType (FMOD_SYSTEM *system, FMOD_DSP_TYPE type, FMOD_DSP **dsp); +FMOD_RESULT F_API FMOD_System_CreateChannelGroup (FMOD_SYSTEM *system, const char *name, FMOD_CHANNELGROUP **channelgroup); +FMOD_RESULT F_API FMOD_System_CreateSoundGroup (FMOD_SYSTEM *system, const char *name, FMOD_SOUNDGROUP **soundgroup); +FMOD_RESULT F_API FMOD_System_CreateReverb3D (FMOD_SYSTEM *system, FMOD_REVERB3D **reverb); +FMOD_RESULT F_API FMOD_System_PlaySound (FMOD_SYSTEM *system, FMOD_SOUND *sound, FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL paused, FMOD_CHANNEL **channel); +FMOD_RESULT F_API FMOD_System_PlayDSP (FMOD_SYSTEM *system, FMOD_DSP *dsp, FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL paused, FMOD_CHANNEL **channel); +FMOD_RESULT F_API FMOD_System_GetChannel (FMOD_SYSTEM *system, int channelid, FMOD_CHANNEL **channel); +FMOD_RESULT F_API FMOD_System_GetMasterChannelGroup (FMOD_SYSTEM *system, FMOD_CHANNELGROUP **channelgroup); +FMOD_RESULT F_API FMOD_System_GetMasterSoundGroup (FMOD_SYSTEM *system, FMOD_SOUNDGROUP **soundgroup); + +/* Routing to ports. */ +FMOD_RESULT F_API FMOD_System_AttachChannelGroupToPort (FMOD_SYSTEM *system, FMOD_PORT_TYPE portType, FMOD_PORT_INDEX portIndex, FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL passThru); +FMOD_RESULT F_API FMOD_System_DetachChannelGroupFromPort(FMOD_SYSTEM *system, FMOD_CHANNELGROUP *channelgroup); + +/* Reverb API. */ +FMOD_RESULT F_API FMOD_System_SetReverbProperties (FMOD_SYSTEM *system, int instance, const FMOD_REVERB_PROPERTIES *prop); +FMOD_RESULT F_API FMOD_System_GetReverbProperties (FMOD_SYSTEM *system, int instance, FMOD_REVERB_PROPERTIES *prop); + +/* System level DSP functionality. */ +FMOD_RESULT F_API FMOD_System_LockDSP (FMOD_SYSTEM *system); +FMOD_RESULT F_API FMOD_System_UnlockDSP (FMOD_SYSTEM *system); + +/* Recording API. */ +FMOD_RESULT F_API FMOD_System_GetRecordNumDrivers (FMOD_SYSTEM *system, int *numdrivers, int *numconnected); +FMOD_RESULT F_API FMOD_System_GetRecordDriverInfo (FMOD_SYSTEM *system, int id, char *name, int namelen, FMOD_GUID *guid, int *systemrate, FMOD_SPEAKERMODE *speakermode, int *speakermodechannels, FMOD_DRIVER_STATE *state); +FMOD_RESULT F_API FMOD_System_GetRecordPosition (FMOD_SYSTEM *system, int id, unsigned int *position); +FMOD_RESULT F_API FMOD_System_RecordStart (FMOD_SYSTEM *system, int id, FMOD_SOUND *sound, FMOD_BOOL loop); +FMOD_RESULT F_API FMOD_System_RecordStop (FMOD_SYSTEM *system, int id); +FMOD_RESULT F_API FMOD_System_IsRecording (FMOD_SYSTEM *system, int id, FMOD_BOOL *recording); + +/* Geometry API. */ +FMOD_RESULT F_API FMOD_System_CreateGeometry (FMOD_SYSTEM *system, int maxpolygons, int maxvertices, FMOD_GEOMETRY **geometry); +FMOD_RESULT F_API FMOD_System_SetGeometrySettings (FMOD_SYSTEM *system, float maxworldsize); +FMOD_RESULT F_API FMOD_System_GetGeometrySettings (FMOD_SYSTEM *system, float *maxworldsize); +FMOD_RESULT F_API FMOD_System_LoadGeometry (FMOD_SYSTEM *system, const void *data, int datasize, FMOD_GEOMETRY **geometry); +FMOD_RESULT F_API FMOD_System_GetGeometryOcclusion (FMOD_SYSTEM *system, const FMOD_VECTOR *listener, const FMOD_VECTOR *source, float *direct, float *reverb); + +/* Network functions. */ +FMOD_RESULT F_API FMOD_System_SetNetworkProxy (FMOD_SYSTEM *system, const char *proxy); +FMOD_RESULT F_API FMOD_System_GetNetworkProxy (FMOD_SYSTEM *system, char *proxy, int proxylen); +FMOD_RESULT F_API FMOD_System_SetNetworkTimeout (FMOD_SYSTEM *system, int timeout); +FMOD_RESULT F_API FMOD_System_GetNetworkTimeout (FMOD_SYSTEM *system, int *timeout); + +/* Userdata set/get. */ +FMOD_RESULT F_API FMOD_System_SetUserData (FMOD_SYSTEM *system, void *userdata); +FMOD_RESULT F_API FMOD_System_GetUserData (FMOD_SYSTEM *system, void **userdata); + +/* Sound API +*/ + +FMOD_RESULT F_API FMOD_Sound_Release (FMOD_SOUND *sound); +FMOD_RESULT F_API FMOD_Sound_GetSystemObject (FMOD_SOUND *sound, FMOD_SYSTEM **system); + +/* + Standard sound manipulation functions. +*/ + +FMOD_RESULT F_API FMOD_Sound_Lock (FMOD_SOUND *sound, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2); +FMOD_RESULT F_API FMOD_Sound_Unlock (FMOD_SOUND *sound, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2); +FMOD_RESULT F_API FMOD_Sound_SetDefaults (FMOD_SOUND *sound, float frequency, int priority); +FMOD_RESULT F_API FMOD_Sound_GetDefaults (FMOD_SOUND *sound, float *frequency, int *priority); +FMOD_RESULT F_API FMOD_Sound_Set3DMinMaxDistance (FMOD_SOUND *sound, float min, float max); +FMOD_RESULT F_API FMOD_Sound_Get3DMinMaxDistance (FMOD_SOUND *sound, float *min, float *max); +FMOD_RESULT F_API FMOD_Sound_Set3DConeSettings (FMOD_SOUND *sound, float insideconeangle, float outsideconeangle, float outsidevolume); +FMOD_RESULT F_API FMOD_Sound_Get3DConeSettings (FMOD_SOUND *sound, float *insideconeangle, float *outsideconeangle, float *outsidevolume); +FMOD_RESULT F_API FMOD_Sound_Set3DCustomRolloff (FMOD_SOUND *sound, FMOD_VECTOR *points, int numpoints); +FMOD_RESULT F_API FMOD_Sound_Get3DCustomRolloff (FMOD_SOUND *sound, FMOD_VECTOR **points, int *numpoints); +FMOD_RESULT F_API FMOD_Sound_GetSubSound (FMOD_SOUND *sound, int index, FMOD_SOUND **subsound); +FMOD_RESULT F_API FMOD_Sound_GetSubSoundParent (FMOD_SOUND *sound, FMOD_SOUND **parentsound); +FMOD_RESULT F_API FMOD_Sound_GetName (FMOD_SOUND *sound, char *name, int namelen); +FMOD_RESULT F_API FMOD_Sound_GetLength (FMOD_SOUND *sound, unsigned int *length, FMOD_TIMEUNIT lengthtype); +FMOD_RESULT F_API FMOD_Sound_GetFormat (FMOD_SOUND *sound, FMOD_SOUND_TYPE *type, FMOD_SOUND_FORMAT *format, int *channels, int *bits); +FMOD_RESULT F_API FMOD_Sound_GetNumSubSounds (FMOD_SOUND *sound, int *numsubsounds); +FMOD_RESULT F_API FMOD_Sound_GetNumTags (FMOD_SOUND *sound, int *numtags, int *numtagsupdated); +FMOD_RESULT F_API FMOD_Sound_GetTag (FMOD_SOUND *sound, const char *name, int index, FMOD_TAG *tag); +FMOD_RESULT F_API FMOD_Sound_GetOpenState (FMOD_SOUND *sound, FMOD_OPENSTATE *openstate, unsigned int *percentbuffered, FMOD_BOOL *starving, FMOD_BOOL *diskbusy); +FMOD_RESULT F_API FMOD_Sound_ReadData (FMOD_SOUND *sound, void *buffer, unsigned int length, unsigned int *read); +FMOD_RESULT F_API FMOD_Sound_SeekData (FMOD_SOUND *sound, unsigned int pcm); + +FMOD_RESULT F_API FMOD_Sound_SetSoundGroup (FMOD_SOUND *sound, FMOD_SOUNDGROUP *soundgroup); +FMOD_RESULT F_API FMOD_Sound_GetSoundGroup (FMOD_SOUND *sound, FMOD_SOUNDGROUP **soundgroup); + +/* + Synchronization point API. These points can come from markers embedded in wav files, and can also generate channel callbacks. +*/ + +FMOD_RESULT F_API FMOD_Sound_GetNumSyncPoints (FMOD_SOUND *sound, int *numsyncpoints); +FMOD_RESULT F_API FMOD_Sound_GetSyncPoint (FMOD_SOUND *sound, int index, FMOD_SYNCPOINT **point); +FMOD_RESULT F_API FMOD_Sound_GetSyncPointInfo (FMOD_SOUND *sound, FMOD_SYNCPOINT *point, char *name, int namelen, unsigned int *offset, FMOD_TIMEUNIT offsettype); +FMOD_RESULT F_API FMOD_Sound_AddSyncPoint (FMOD_SOUND *sound, unsigned int offset, FMOD_TIMEUNIT offsettype, const char *name, FMOD_SYNCPOINT **point); +FMOD_RESULT F_API FMOD_Sound_DeleteSyncPoint (FMOD_SOUND *sound, FMOD_SYNCPOINT *point); + +/* + Functions also in Channel class but here they are the 'default' to save having to change it in Channel all the time. +*/ + +FMOD_RESULT F_API FMOD_Sound_SetMode (FMOD_SOUND *sound, FMOD_MODE mode); +FMOD_RESULT F_API FMOD_Sound_GetMode (FMOD_SOUND *sound, FMOD_MODE *mode); +FMOD_RESULT F_API FMOD_Sound_SetLoopCount (FMOD_SOUND *sound, int loopcount); +FMOD_RESULT F_API FMOD_Sound_GetLoopCount (FMOD_SOUND *sound, int *loopcount); +FMOD_RESULT F_API FMOD_Sound_SetLoopPoints (FMOD_SOUND *sound, unsigned int loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int loopend, FMOD_TIMEUNIT loopendtype); +FMOD_RESULT F_API FMOD_Sound_GetLoopPoints (FMOD_SOUND *sound, unsigned int *loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int *loopend, FMOD_TIMEUNIT loopendtype); + +/* + For MOD/S3M/XM/IT/MID sequenced formats only. +*/ + +FMOD_RESULT F_API FMOD_Sound_GetMusicNumChannels (FMOD_SOUND *sound, int *numchannels); +FMOD_RESULT F_API FMOD_Sound_SetMusicChannelVolume (FMOD_SOUND *sound, int channel, float volume); +FMOD_RESULT F_API FMOD_Sound_GetMusicChannelVolume (FMOD_SOUND *sound, int channel, float *volume); +FMOD_RESULT F_API FMOD_Sound_SetMusicSpeed (FMOD_SOUND *sound, float speed); +FMOD_RESULT F_API FMOD_Sound_GetMusicSpeed (FMOD_SOUND *sound, float *speed); + +/* + Userdata set/get. +*/ + +FMOD_RESULT F_API FMOD_Sound_SetUserData (FMOD_SOUND *sound, void *userdata); +FMOD_RESULT F_API FMOD_Sound_GetUserData (FMOD_SOUND *sound, void **userdata); + +/* + 'Channel' API +*/ + +FMOD_RESULT F_API FMOD_Channel_GetSystemObject (FMOD_CHANNEL *channel, FMOD_SYSTEM **system); + +/* + General control functionality for Channels and ChannelGroups. +*/ + +FMOD_RESULT F_API FMOD_Channel_Stop (FMOD_CHANNEL *channel); +FMOD_RESULT F_API FMOD_Channel_SetPaused (FMOD_CHANNEL *channel, FMOD_BOOL paused); +FMOD_RESULT F_API FMOD_Channel_GetPaused (FMOD_CHANNEL *channel, FMOD_BOOL *paused); +FMOD_RESULT F_API FMOD_Channel_SetVolume (FMOD_CHANNEL *channel, float volume); +FMOD_RESULT F_API FMOD_Channel_GetVolume (FMOD_CHANNEL *channel, float *volume); +FMOD_RESULT F_API FMOD_Channel_SetVolumeRamp (FMOD_CHANNEL *channel, FMOD_BOOL ramp); +FMOD_RESULT F_API FMOD_Channel_GetVolumeRamp (FMOD_CHANNEL *channel, FMOD_BOOL *ramp); +FMOD_RESULT F_API FMOD_Channel_GetAudibility (FMOD_CHANNEL *channel, float *audibility); +FMOD_RESULT F_API FMOD_Channel_SetPitch (FMOD_CHANNEL *channel, float pitch); +FMOD_RESULT F_API FMOD_Channel_GetPitch (FMOD_CHANNEL *channel, float *pitch); +FMOD_RESULT F_API FMOD_Channel_SetMute (FMOD_CHANNEL *channel, FMOD_BOOL mute); +FMOD_RESULT F_API FMOD_Channel_GetMute (FMOD_CHANNEL *channel, FMOD_BOOL *mute); +FMOD_RESULT F_API FMOD_Channel_SetReverbProperties (FMOD_CHANNEL *channel, int instance, float wet); +FMOD_RESULT F_API FMOD_Channel_GetReverbProperties (FMOD_CHANNEL *channel, int instance, float *wet); +FMOD_RESULT F_API FMOD_Channel_SetLowPassGain (FMOD_CHANNEL *channel, float gain); +FMOD_RESULT F_API FMOD_Channel_GetLowPassGain (FMOD_CHANNEL *channel, float *gain); +FMOD_RESULT F_API FMOD_Channel_SetMode (FMOD_CHANNEL *channel, FMOD_MODE mode); +FMOD_RESULT F_API FMOD_Channel_GetMode (FMOD_CHANNEL *channel, FMOD_MODE *mode); +FMOD_RESULT F_API FMOD_Channel_SetCallback (FMOD_CHANNEL *channel, FMOD_CHANNELCONTROL_CALLBACK callback); +FMOD_RESULT F_API FMOD_Channel_IsPlaying (FMOD_CHANNEL *channel, FMOD_BOOL *isplaying); + +/* + Note all 'set' functions alter a final matrix, this is why the only get function is getMixMatrix, to avoid other get functions returning incorrect/obsolete values. +*/ + +FMOD_RESULT F_API FMOD_Channel_SetPan (FMOD_CHANNEL *channel, float pan); +FMOD_RESULT F_API FMOD_Channel_SetMixLevelsOutput (FMOD_CHANNEL *channel, float frontleft, float frontright, float center, float lfe, float surroundleft, float surroundright, float backleft, float backright); +FMOD_RESULT F_API FMOD_Channel_SetMixLevelsInput (FMOD_CHANNEL *channel, float *levels, int numlevels); +FMOD_RESULT F_API FMOD_Channel_SetMixMatrix (FMOD_CHANNEL *channel, float *matrix, int outchannels, int inchannels, int inchannel_hop); +FMOD_RESULT F_API FMOD_Channel_GetMixMatrix (FMOD_CHANNEL *channel, float *matrix, int *outchannels, int *inchannels, int inchannel_hop); + +/* + Clock based functionality. +*/ + +FMOD_RESULT F_API FMOD_Channel_GetDSPClock (FMOD_CHANNEL *channel, unsigned long long *dspclock, unsigned long long *parentclock); +FMOD_RESULT F_API FMOD_Channel_SetDelay (FMOD_CHANNEL *channel, unsigned long long dspclock_start, unsigned long long dspclock_end, FMOD_BOOL stopchannels); +FMOD_RESULT F_API FMOD_Channel_GetDelay (FMOD_CHANNEL *channel, unsigned long long *dspclock_start, unsigned long long *dspclock_end, FMOD_BOOL *stopchannels); +FMOD_RESULT F_API FMOD_Channel_AddFadePoint (FMOD_CHANNEL *channel, unsigned long long dspclock, float volume); +FMOD_RESULT F_API FMOD_Channel_SetFadePointRamp (FMOD_CHANNEL *channel, unsigned long long dspclock, float volume); +FMOD_RESULT F_API FMOD_Channel_RemoveFadePoints (FMOD_CHANNEL *channel, unsigned long long dspclock_start, unsigned long long dspclock_end); +FMOD_RESULT F_API FMOD_Channel_GetFadePoints (FMOD_CHANNEL *channel, unsigned int *numpoints, unsigned long long *point_dspclock, float *point_volume); + +/* + DSP effects. +*/ + +FMOD_RESULT F_API FMOD_Channel_GetDSP (FMOD_CHANNEL *channel, int index, FMOD_DSP **dsp); +FMOD_RESULT F_API FMOD_Channel_AddDSP (FMOD_CHANNEL *channel, int index, FMOD_DSP *dsp); +FMOD_RESULT F_API FMOD_Channel_RemoveDSP (FMOD_CHANNEL *channel, FMOD_DSP *dsp); +FMOD_RESULT F_API FMOD_Channel_GetNumDSPs (FMOD_CHANNEL *channel, int *numdsps); +FMOD_RESULT F_API FMOD_Channel_SetDSPIndex (FMOD_CHANNEL *channel, FMOD_DSP *dsp, int index); +FMOD_RESULT F_API FMOD_Channel_GetDSPIndex (FMOD_CHANNEL *channel, FMOD_DSP *dsp, int *index); + +/* + 3D functionality. +*/ + +FMOD_RESULT F_API FMOD_Channel_Set3DAttributes (FMOD_CHANNEL *channel, const FMOD_VECTOR *pos, const FMOD_VECTOR *vel); +FMOD_RESULT F_API FMOD_Channel_Get3DAttributes (FMOD_CHANNEL *channel, FMOD_VECTOR *pos, FMOD_VECTOR *vel); +FMOD_RESULT F_API FMOD_Channel_Set3DMinMaxDistance (FMOD_CHANNEL *channel, float mindistance, float maxdistance); +FMOD_RESULT F_API FMOD_Channel_Get3DMinMaxDistance (FMOD_CHANNEL *channel, float *mindistance, float *maxdistance); +FMOD_RESULT F_API FMOD_Channel_Set3DConeSettings (FMOD_CHANNEL *channel, float insideconeangle, float outsideconeangle, float outsidevolume); +FMOD_RESULT F_API FMOD_Channel_Get3DConeSettings (FMOD_CHANNEL *channel, float *insideconeangle, float *outsideconeangle, float *outsidevolume); +FMOD_RESULT F_API FMOD_Channel_Set3DConeOrientation (FMOD_CHANNEL *channel, FMOD_VECTOR *orientation); +FMOD_RESULT F_API FMOD_Channel_Get3DConeOrientation (FMOD_CHANNEL *channel, FMOD_VECTOR *orientation); +FMOD_RESULT F_API FMOD_Channel_Set3DCustomRolloff (FMOD_CHANNEL *channel, FMOD_VECTOR *points, int numpoints); +FMOD_RESULT F_API FMOD_Channel_Get3DCustomRolloff (FMOD_CHANNEL *channel, FMOD_VECTOR **points, int *numpoints); +FMOD_RESULT F_API FMOD_Channel_Set3DOcclusion (FMOD_CHANNEL *channel, float directocclusion, float reverbocclusion); +FMOD_RESULT F_API FMOD_Channel_Get3DOcclusion (FMOD_CHANNEL *channel, float *directocclusion, float *reverbocclusion); +FMOD_RESULT F_API FMOD_Channel_Set3DSpread (FMOD_CHANNEL *channel, float angle); +FMOD_RESULT F_API FMOD_Channel_Get3DSpread (FMOD_CHANNEL *channel, float *angle); +FMOD_RESULT F_API FMOD_Channel_Set3DLevel (FMOD_CHANNEL *channel, float level); +FMOD_RESULT F_API FMOD_Channel_Get3DLevel (FMOD_CHANNEL *channel, float *level); +FMOD_RESULT F_API FMOD_Channel_Set3DDopplerLevel (FMOD_CHANNEL *channel, float level); +FMOD_RESULT F_API FMOD_Channel_Get3DDopplerLevel (FMOD_CHANNEL *channel, float *level); +FMOD_RESULT F_API FMOD_Channel_Set3DDistanceFilter (FMOD_CHANNEL *channel, FMOD_BOOL custom, float customLevel, float centerFreq); +FMOD_RESULT F_API FMOD_Channel_Get3DDistanceFilter (FMOD_CHANNEL *channel, FMOD_BOOL *custom, float *customLevel, float *centerFreq); + +/* + Userdata set/get. +*/ + +FMOD_RESULT F_API FMOD_Channel_SetUserData (FMOD_CHANNEL *channel, void *userdata); +FMOD_RESULT F_API FMOD_Channel_GetUserData (FMOD_CHANNEL *channel, void **userdata); + +/* + Channel specific control functionality. +*/ + +FMOD_RESULT F_API FMOD_Channel_SetFrequency (FMOD_CHANNEL *channel, float frequency); +FMOD_RESULT F_API FMOD_Channel_GetFrequency (FMOD_CHANNEL *channel, float *frequency); +FMOD_RESULT F_API FMOD_Channel_SetPriority (FMOD_CHANNEL *channel, int priority); +FMOD_RESULT F_API FMOD_Channel_GetPriority (FMOD_CHANNEL *channel, int *priority); +FMOD_RESULT F_API FMOD_Channel_SetPosition (FMOD_CHANNEL *channel, unsigned int position, FMOD_TIMEUNIT postype); +FMOD_RESULT F_API FMOD_Channel_GetPosition (FMOD_CHANNEL *channel, unsigned int *position, FMOD_TIMEUNIT postype); +FMOD_RESULT F_API FMOD_Channel_SetChannelGroup (FMOD_CHANNEL *channel, FMOD_CHANNELGROUP *channelgroup); +FMOD_RESULT F_API FMOD_Channel_GetChannelGroup (FMOD_CHANNEL *channel, FMOD_CHANNELGROUP **channelgroup); +FMOD_RESULT F_API FMOD_Channel_SetLoopCount (FMOD_CHANNEL *channel, int loopcount); +FMOD_RESULT F_API FMOD_Channel_GetLoopCount (FMOD_CHANNEL *channel, int *loopcount); +FMOD_RESULT F_API FMOD_Channel_SetLoopPoints (FMOD_CHANNEL *channel, unsigned int loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int loopend, FMOD_TIMEUNIT loopendtype); +FMOD_RESULT F_API FMOD_Channel_GetLoopPoints (FMOD_CHANNEL *channel, unsigned int *loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int *loopend, FMOD_TIMEUNIT loopendtype); + +/* + Information only functions. +*/ + +FMOD_RESULT F_API FMOD_Channel_IsVirtual (FMOD_CHANNEL *channel, FMOD_BOOL *isvirtual); +FMOD_RESULT F_API FMOD_Channel_GetCurrentSound (FMOD_CHANNEL *channel, FMOD_SOUND **sound); +FMOD_RESULT F_API FMOD_Channel_GetIndex (FMOD_CHANNEL *channel, int *index); + +/* + 'ChannelGroup' API +*/ + +FMOD_RESULT F_API FMOD_ChannelGroup_GetSystemObject (FMOD_CHANNELGROUP *channelgroup, FMOD_SYSTEM **system); + +/* + General control functionality for Channels and ChannelGroups. +*/ + +FMOD_RESULT F_API FMOD_ChannelGroup_Stop (FMOD_CHANNELGROUP *channelgroup); +FMOD_RESULT F_API FMOD_ChannelGroup_SetPaused (FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL paused); +FMOD_RESULT F_API FMOD_ChannelGroup_GetPaused (FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL *paused); +FMOD_RESULT F_API FMOD_ChannelGroup_SetVolume (FMOD_CHANNELGROUP *channelgroup, float volume); +FMOD_RESULT F_API FMOD_ChannelGroup_GetVolume (FMOD_CHANNELGROUP *channelgroup, float *volume); +FMOD_RESULT F_API FMOD_ChannelGroup_SetVolumeRamp (FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL ramp); +FMOD_RESULT F_API FMOD_ChannelGroup_GetVolumeRamp (FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL *ramp); +FMOD_RESULT F_API FMOD_ChannelGroup_GetAudibility (FMOD_CHANNELGROUP *channelgroup, float *audibility); +FMOD_RESULT F_API FMOD_ChannelGroup_SetPitch (FMOD_CHANNELGROUP *channelgroup, float pitch); +FMOD_RESULT F_API FMOD_ChannelGroup_GetPitch (FMOD_CHANNELGROUP *channelgroup, float *pitch); +FMOD_RESULT F_API FMOD_ChannelGroup_SetMute (FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL mute); +FMOD_RESULT F_API FMOD_ChannelGroup_GetMute (FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL *mute); +FMOD_RESULT F_API FMOD_ChannelGroup_SetReverbProperties (FMOD_CHANNELGROUP *channelgroup, int instance, float wet); +FMOD_RESULT F_API FMOD_ChannelGroup_GetReverbProperties (FMOD_CHANNELGROUP *channelgroup, int instance, float *wet); +FMOD_RESULT F_API FMOD_ChannelGroup_SetLowPassGain (FMOD_CHANNELGROUP *channelgroup, float gain); +FMOD_RESULT F_API FMOD_ChannelGroup_GetLowPassGain (FMOD_CHANNELGROUP *channelgroup, float *gain); +FMOD_RESULT F_API FMOD_ChannelGroup_SetMode (FMOD_CHANNELGROUP *channelgroup, FMOD_MODE mode); +FMOD_RESULT F_API FMOD_ChannelGroup_GetMode (FMOD_CHANNELGROUP *channelgroup, FMOD_MODE *mode); +FMOD_RESULT F_API FMOD_ChannelGroup_SetCallback (FMOD_CHANNELGROUP *channelgroup, FMOD_CHANNELCONTROL_CALLBACK callback); +FMOD_RESULT F_API FMOD_ChannelGroup_IsPlaying (FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL *isplaying); + +/* + Note all 'set' functions alter a final matrix, this is why the only get function is getMixMatrix, to avoid other get functions returning incorrect/obsolete values. +*/ + +FMOD_RESULT F_API FMOD_ChannelGroup_SetPan (FMOD_CHANNELGROUP *channelgroup, float pan); +FMOD_RESULT F_API FMOD_ChannelGroup_SetMixLevelsOutput (FMOD_CHANNELGROUP *channelgroup, float frontleft, float frontright, float center, float lfe, float surroundleft, float surroundright, float backleft, float backright); +FMOD_RESULT F_API FMOD_ChannelGroup_SetMixLevelsInput (FMOD_CHANNELGROUP *channelgroup, float *levels, int numlevels); +FMOD_RESULT F_API FMOD_ChannelGroup_SetMixMatrix (FMOD_CHANNELGROUP *channelgroup, float *matrix, int outchannels, int inchannels, int inchannel_hop); +FMOD_RESULT F_API FMOD_ChannelGroup_GetMixMatrix (FMOD_CHANNELGROUP *channelgroup, float *matrix, int *outchannels, int *inchannels, int inchannel_hop); + +/* + Clock based functionality. +*/ + +FMOD_RESULT F_API FMOD_ChannelGroup_GetDSPClock (FMOD_CHANNELGROUP *channelgroup, unsigned long long *dspclock, unsigned long long *parentclock); +FMOD_RESULT F_API FMOD_ChannelGroup_SetDelay (FMOD_CHANNELGROUP *channelgroup, unsigned long long dspclock_start, unsigned long long dspclock_end, FMOD_BOOL stopchannels); +FMOD_RESULT F_API FMOD_ChannelGroup_GetDelay (FMOD_CHANNELGROUP *channelgroup, unsigned long long *dspclock_start, unsigned long long *dspclock_end, FMOD_BOOL *stopchannels); +FMOD_RESULT F_API FMOD_ChannelGroup_AddFadePoint (FMOD_CHANNELGROUP *channelgroup, unsigned long long dspclock, float volume); +FMOD_RESULT F_API FMOD_ChannelGroup_SetFadePointRamp (FMOD_CHANNELGROUP *channelgroup, unsigned long long dspclock, float volume); +FMOD_RESULT F_API FMOD_ChannelGroup_RemoveFadePoints (FMOD_CHANNELGROUP *channelgroup, unsigned long long dspclock_start, unsigned long long dspclock_end); +FMOD_RESULT F_API FMOD_ChannelGroup_GetFadePoints (FMOD_CHANNELGROUP *channelgroup, unsigned int *numpoints, unsigned long long *point_dspclock, float *point_volume); + +/* + DSP effects. +*/ + +FMOD_RESULT F_API FMOD_ChannelGroup_GetDSP (FMOD_CHANNELGROUP *channelgroup, int index, FMOD_DSP **dsp); +FMOD_RESULT F_API FMOD_ChannelGroup_AddDSP (FMOD_CHANNELGROUP *channelgroup, int index, FMOD_DSP *dsp); +FMOD_RESULT F_API FMOD_ChannelGroup_RemoveDSP (FMOD_CHANNELGROUP *channelgroup, FMOD_DSP *dsp); +FMOD_RESULT F_API FMOD_ChannelGroup_GetNumDSPs (FMOD_CHANNELGROUP *channelgroup, int *numdsps); +FMOD_RESULT F_API FMOD_ChannelGroup_SetDSPIndex (FMOD_CHANNELGROUP *channelgroup, FMOD_DSP *dsp, int index); +FMOD_RESULT F_API FMOD_ChannelGroup_GetDSPIndex (FMOD_CHANNELGROUP *channelgroup, FMOD_DSP *dsp, int *index); + +/* + 3D functionality. +*/ + +FMOD_RESULT F_API FMOD_ChannelGroup_Set3DAttributes (FMOD_CHANNELGROUP *channelgroup, const FMOD_VECTOR *pos, const FMOD_VECTOR *vel); +FMOD_RESULT F_API FMOD_ChannelGroup_Get3DAttributes (FMOD_CHANNELGROUP *channelgroup, FMOD_VECTOR *pos, FMOD_VECTOR *vel); +FMOD_RESULT F_API FMOD_ChannelGroup_Set3DMinMaxDistance (FMOD_CHANNELGROUP *channelgroup, float mindistance, float maxdistance); +FMOD_RESULT F_API FMOD_ChannelGroup_Get3DMinMaxDistance (FMOD_CHANNELGROUP *channelgroup, float *mindistance, float *maxdistance); +FMOD_RESULT F_API FMOD_ChannelGroup_Set3DConeSettings (FMOD_CHANNELGROUP *channelgroup, float insideconeangle, float outsideconeangle, float outsidevolume); +FMOD_RESULT F_API FMOD_ChannelGroup_Get3DConeSettings (FMOD_CHANNELGROUP *channelgroup, float *insideconeangle, float *outsideconeangle, float *outsidevolume); +FMOD_RESULT F_API FMOD_ChannelGroup_Set3DConeOrientation(FMOD_CHANNELGROUP *channelgroup, FMOD_VECTOR *orientation); +FMOD_RESULT F_API FMOD_ChannelGroup_Get3DConeOrientation(FMOD_CHANNELGROUP *channelgroup, FMOD_VECTOR *orientation); +FMOD_RESULT F_API FMOD_ChannelGroup_Set3DCustomRolloff (FMOD_CHANNELGROUP *channelgroup, FMOD_VECTOR *points, int numpoints); +FMOD_RESULT F_API FMOD_ChannelGroup_Get3DCustomRolloff (FMOD_CHANNELGROUP *channelgroup, FMOD_VECTOR **points, int *numpoints); +FMOD_RESULT F_API FMOD_ChannelGroup_Set3DOcclusion (FMOD_CHANNELGROUP *channelgroup, float directocclusion, float reverbocclusion); +FMOD_RESULT F_API FMOD_ChannelGroup_Get3DOcclusion (FMOD_CHANNELGROUP *channelgroup, float *directocclusion, float *reverbocclusion); +FMOD_RESULT F_API FMOD_ChannelGroup_Set3DSpread (FMOD_CHANNELGROUP *channelgroup, float angle); +FMOD_RESULT F_API FMOD_ChannelGroup_Get3DSpread (FMOD_CHANNELGROUP *channelgroup, float *angle); +FMOD_RESULT F_API FMOD_ChannelGroup_Set3DLevel (FMOD_CHANNELGROUP *channelgroup, float level); +FMOD_RESULT F_API FMOD_ChannelGroup_Get3DLevel (FMOD_CHANNELGROUP *channelgroup, float *level); +FMOD_RESULT F_API FMOD_ChannelGroup_Set3DDopplerLevel (FMOD_CHANNELGROUP *channelgroup, float level); +FMOD_RESULT F_API FMOD_ChannelGroup_Get3DDopplerLevel (FMOD_CHANNELGROUP *channelgroup, float *level); +FMOD_RESULT F_API FMOD_ChannelGroup_Set3DDistanceFilter (FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL custom, float customLevel, float centerFreq); +FMOD_RESULT F_API FMOD_ChannelGroup_Get3DDistanceFilter (FMOD_CHANNELGROUP *channelgroup, FMOD_BOOL *custom, float *customLevel, float *centerFreq); + +/* + Userdata set/get. +*/ + +FMOD_RESULT F_API FMOD_ChannelGroup_SetUserData (FMOD_CHANNELGROUP *channelgroup, void *userdata); +FMOD_RESULT F_API FMOD_ChannelGroup_GetUserData (FMOD_CHANNELGROUP *channelgroup, void **userdata); + +FMOD_RESULT F_API FMOD_ChannelGroup_Release (FMOD_CHANNELGROUP *channelgroup); + +/* + Nested channel groups. +*/ + +FMOD_RESULT F_API FMOD_ChannelGroup_AddGroup (FMOD_CHANNELGROUP *channelgroup, FMOD_CHANNELGROUP *group, FMOD_BOOL propagatedspclock, FMOD_DSPCONNECTION **connection); +FMOD_RESULT F_API FMOD_ChannelGroup_GetNumGroups (FMOD_CHANNELGROUP *channelgroup, int *numgroups); +FMOD_RESULT F_API FMOD_ChannelGroup_GetGroup (FMOD_CHANNELGROUP *channelgroup, int index, FMOD_CHANNELGROUP **group); +FMOD_RESULT F_API FMOD_ChannelGroup_GetParentGroup (FMOD_CHANNELGROUP *channelgroup, FMOD_CHANNELGROUP **group); + +/* + Information only functions. +*/ + +FMOD_RESULT F_API FMOD_ChannelGroup_GetName (FMOD_CHANNELGROUP *channelgroup, char *name, int namelen); +FMOD_RESULT F_API FMOD_ChannelGroup_GetNumChannels (FMOD_CHANNELGROUP *channelgroup, int *numchannels); +FMOD_RESULT F_API FMOD_ChannelGroup_GetChannel (FMOD_CHANNELGROUP *channelgroup, int index, FMOD_CHANNEL **channel); + +/* + 'SoundGroup' API +*/ + +FMOD_RESULT F_API FMOD_SoundGroup_Release (FMOD_SOUNDGROUP *soundgroup); +FMOD_RESULT F_API FMOD_SoundGroup_GetSystemObject (FMOD_SOUNDGROUP *soundgroup, FMOD_SYSTEM **system); + +/* + SoundGroup control functions. +*/ + +FMOD_RESULT F_API FMOD_SoundGroup_SetMaxAudible (FMOD_SOUNDGROUP *soundgroup, int maxaudible); +FMOD_RESULT F_API FMOD_SoundGroup_GetMaxAudible (FMOD_SOUNDGROUP *soundgroup, int *maxaudible); +FMOD_RESULT F_API FMOD_SoundGroup_SetMaxAudibleBehavior (FMOD_SOUNDGROUP *soundgroup, FMOD_SOUNDGROUP_BEHAVIOR behavior); +FMOD_RESULT F_API FMOD_SoundGroup_GetMaxAudibleBehavior (FMOD_SOUNDGROUP *soundgroup, FMOD_SOUNDGROUP_BEHAVIOR *behavior); +FMOD_RESULT F_API FMOD_SoundGroup_SetMuteFadeSpeed (FMOD_SOUNDGROUP *soundgroup, float speed); +FMOD_RESULT F_API FMOD_SoundGroup_GetMuteFadeSpeed (FMOD_SOUNDGROUP *soundgroup, float *speed); +FMOD_RESULT F_API FMOD_SoundGroup_SetVolume (FMOD_SOUNDGROUP *soundgroup, float volume); +FMOD_RESULT F_API FMOD_SoundGroup_GetVolume (FMOD_SOUNDGROUP *soundgroup, float *volume); +FMOD_RESULT F_API FMOD_SoundGroup_Stop (FMOD_SOUNDGROUP *soundgroup); + +/* + Information only functions. +*/ + +FMOD_RESULT F_API FMOD_SoundGroup_GetName (FMOD_SOUNDGROUP *soundgroup, char *name, int namelen); +FMOD_RESULT F_API FMOD_SoundGroup_GetNumSounds (FMOD_SOUNDGROUP *soundgroup, int *numsounds); +FMOD_RESULT F_API FMOD_SoundGroup_GetSound (FMOD_SOUNDGROUP *soundgroup, int index, FMOD_SOUND **sound); +FMOD_RESULT F_API FMOD_SoundGroup_GetNumPlaying (FMOD_SOUNDGROUP *soundgroup, int *numplaying); + +/* + Userdata set/get. +*/ + +FMOD_RESULT F_API FMOD_SoundGroup_SetUserData (FMOD_SOUNDGROUP *soundgroup, void *userdata); +FMOD_RESULT F_API FMOD_SoundGroup_GetUserData (FMOD_SOUNDGROUP *soundgroup, void **userdata); + +/* + 'DSP' API +*/ + +FMOD_RESULT F_API FMOD_DSP_Release (FMOD_DSP *dsp); +FMOD_RESULT F_API FMOD_DSP_GetSystemObject (FMOD_DSP *dsp, FMOD_SYSTEM **system); + +/* + Connection / disconnection / input and output enumeration. +*/ + +FMOD_RESULT F_API FMOD_DSP_AddInput (FMOD_DSP *dsp, FMOD_DSP *input, FMOD_DSPCONNECTION **connection, FMOD_DSPCONNECTION_TYPE type); +FMOD_RESULT F_API FMOD_DSP_DisconnectFrom (FMOD_DSP *dsp, FMOD_DSP *target, FMOD_DSPCONNECTION *connection); +FMOD_RESULT F_API FMOD_DSP_DisconnectAll (FMOD_DSP *dsp, FMOD_BOOL inputs, FMOD_BOOL outputs); +FMOD_RESULT F_API FMOD_DSP_GetNumInputs (FMOD_DSP *dsp, int *numinputs); +FMOD_RESULT F_API FMOD_DSP_GetNumOutputs (FMOD_DSP *dsp, int *numoutputs); +FMOD_RESULT F_API FMOD_DSP_GetInput (FMOD_DSP *dsp, int index, FMOD_DSP **input, FMOD_DSPCONNECTION **inputconnection); +FMOD_RESULT F_API FMOD_DSP_GetOutput (FMOD_DSP *dsp, int index, FMOD_DSP **output, FMOD_DSPCONNECTION **outputconnection); + +/* + DSP unit control. +*/ + +FMOD_RESULT F_API FMOD_DSP_SetActive (FMOD_DSP *dsp, FMOD_BOOL active); +FMOD_RESULT F_API FMOD_DSP_GetActive (FMOD_DSP *dsp, FMOD_BOOL *active); +FMOD_RESULT F_API FMOD_DSP_SetBypass (FMOD_DSP *dsp, FMOD_BOOL bypass); +FMOD_RESULT F_API FMOD_DSP_GetBypass (FMOD_DSP *dsp, FMOD_BOOL *bypass); +FMOD_RESULT F_API FMOD_DSP_SetWetDryMix (FMOD_DSP *dsp, float prewet, float postwet, float dry); +FMOD_RESULT F_API FMOD_DSP_GetWetDryMix (FMOD_DSP *dsp, float *prewet, float *postwet, float *dry); +FMOD_RESULT F_API FMOD_DSP_SetChannelFormat (FMOD_DSP *dsp, FMOD_CHANNELMASK channelmask, int numchannels, FMOD_SPEAKERMODE source_speakermode); +FMOD_RESULT F_API FMOD_DSP_GetChannelFormat (FMOD_DSP *dsp, FMOD_CHANNELMASK *channelmask, int *numchannels, FMOD_SPEAKERMODE *source_speakermode); +FMOD_RESULT F_API FMOD_DSP_GetOutputChannelFormat (FMOD_DSP *dsp, FMOD_CHANNELMASK inmask, int inchannels, FMOD_SPEAKERMODE inspeakermode, FMOD_CHANNELMASK *outmask, int *outchannels, FMOD_SPEAKERMODE *outspeakermode); +FMOD_RESULT F_API FMOD_DSP_Reset (FMOD_DSP *dsp); + +/* + DSP parameter control. +*/ + +FMOD_RESULT F_API FMOD_DSP_SetParameterFloat (FMOD_DSP *dsp, int index, float value); +FMOD_RESULT F_API FMOD_DSP_SetParameterInt (FMOD_DSP *dsp, int index, int value); +FMOD_RESULT F_API FMOD_DSP_SetParameterBool (FMOD_DSP *dsp, int index, FMOD_BOOL value); +FMOD_RESULT F_API FMOD_DSP_SetParameterData (FMOD_DSP *dsp, int index, void *data, unsigned int length); +FMOD_RESULT F_API FMOD_DSP_GetParameterFloat (FMOD_DSP *dsp, int index, float *value, char *valuestr, int valuestrlen); +FMOD_RESULT F_API FMOD_DSP_GetParameterInt (FMOD_DSP *dsp, int index, int *value, char *valuestr, int valuestrlen); +FMOD_RESULT F_API FMOD_DSP_GetParameterBool (FMOD_DSP *dsp, int index, FMOD_BOOL *value, char *valuestr, int valuestrlen); +FMOD_RESULT F_API FMOD_DSP_GetParameterData (FMOD_DSP *dsp, int index, void **data, unsigned int *length, char *valuestr, int valuestrlen); +FMOD_RESULT F_API FMOD_DSP_GetNumParameters (FMOD_DSP *dsp, int *numparams); +FMOD_RESULT F_API FMOD_DSP_GetParameterInfo (FMOD_DSP *dsp, int index, FMOD_DSP_PARAMETER_DESC **desc); +FMOD_RESULT F_API FMOD_DSP_GetDataParameterIndex (FMOD_DSP *dsp, int datatype, int *index); +FMOD_RESULT F_API FMOD_DSP_ShowConfigDialog (FMOD_DSP *dsp, void *hwnd, FMOD_BOOL show); + +/* + DSP attributes. +*/ + +FMOD_RESULT F_API FMOD_DSP_GetInfo (FMOD_DSP *dsp, char *name, unsigned int *version, int *channels, int *configwidth, int *configheight); +FMOD_RESULT F_API FMOD_DSP_GetType (FMOD_DSP *dsp, FMOD_DSP_TYPE *type); +FMOD_RESULT F_API FMOD_DSP_GetIdle (FMOD_DSP *dsp, FMOD_BOOL *idle); + +/* + Userdata set/get. +*/ + +FMOD_RESULT F_API FMOD_DSP_SetUserData (FMOD_DSP *dsp, void *userdata); +FMOD_RESULT F_API FMOD_DSP_GetUserData (FMOD_DSP *dsp, void **userdata); + +/* + Metering. +*/ + +FMOD_RESULT F_API FMOD_DSP_SetMeteringEnabled (FMOD_DSP *dsp, FMOD_BOOL inputEnabled, FMOD_BOOL outputEnabled); +FMOD_RESULT F_API FMOD_DSP_GetMeteringEnabled (FMOD_DSP *dsp, FMOD_BOOL *inputEnabled, FMOD_BOOL *outputEnabled); +FMOD_RESULT F_API FMOD_DSP_GetMeteringInfo (FMOD_DSP *dsp, FMOD_DSP_METERING_INFO *inputInfo, FMOD_DSP_METERING_INFO *outputInfo); +FMOD_RESULT F_API FMOD_DSP_GetCPUUsage (FMOD_DSP *dsp, unsigned int *exclusive, unsigned int *inclusive); + +/* + 'DSPConnection' API +*/ + +FMOD_RESULT F_API FMOD_DSPConnection_GetInput (FMOD_DSPCONNECTION *dspconnection, FMOD_DSP **input); +FMOD_RESULT F_API FMOD_DSPConnection_GetOutput (FMOD_DSPCONNECTION *dspconnection, FMOD_DSP **output); +FMOD_RESULT F_API FMOD_DSPConnection_SetMix (FMOD_DSPCONNECTION *dspconnection, float volume); +FMOD_RESULT F_API FMOD_DSPConnection_GetMix (FMOD_DSPCONNECTION *dspconnection, float *volume); +FMOD_RESULT F_API FMOD_DSPConnection_SetMixMatrix (FMOD_DSPCONNECTION *dspconnection, float *matrix, int outchannels, int inchannels, int inchannel_hop); +FMOD_RESULT F_API FMOD_DSPConnection_GetMixMatrix (FMOD_DSPCONNECTION *dspconnection, float *matrix, int *outchannels, int *inchannels, int inchannel_hop); +FMOD_RESULT F_API FMOD_DSPConnection_GetType (FMOD_DSPCONNECTION *dspconnection, FMOD_DSPCONNECTION_TYPE *type); + +/* + Userdata set/get. +*/ + +FMOD_RESULT F_API FMOD_DSPConnection_SetUserData (FMOD_DSPCONNECTION *dspconnection, void *userdata); +FMOD_RESULT F_API FMOD_DSPConnection_GetUserData (FMOD_DSPCONNECTION *dspconnection, void **userdata); + +/* + 'Geometry' API +*/ + +FMOD_RESULT F_API FMOD_Geometry_Release (FMOD_GEOMETRY *geometry); + +/* + Polygon manipulation. +*/ + +FMOD_RESULT F_API FMOD_Geometry_AddPolygon (FMOD_GEOMETRY *geometry, float directocclusion, float reverbocclusion, FMOD_BOOL doublesided, int numvertices, const FMOD_VECTOR *vertices, int *polygonindex); +FMOD_RESULT F_API FMOD_Geometry_GetNumPolygons (FMOD_GEOMETRY *geometry, int *numpolygons); +FMOD_RESULT F_API FMOD_Geometry_GetMaxPolygons (FMOD_GEOMETRY *geometry, int *maxpolygons, int *maxvertices); +FMOD_RESULT F_API FMOD_Geometry_GetPolygonNumVertices (FMOD_GEOMETRY *geometry, int index, int *numvertices); +FMOD_RESULT F_API FMOD_Geometry_SetPolygonVertex (FMOD_GEOMETRY *geometry, int index, int vertexindex, const FMOD_VECTOR *vertex); +FMOD_RESULT F_API FMOD_Geometry_GetPolygonVertex (FMOD_GEOMETRY *geometry, int index, int vertexindex, FMOD_VECTOR *vertex); +FMOD_RESULT F_API FMOD_Geometry_SetPolygonAttributes (FMOD_GEOMETRY *geometry, int index, float directocclusion, float reverbocclusion, FMOD_BOOL doublesided); +FMOD_RESULT F_API FMOD_Geometry_GetPolygonAttributes (FMOD_GEOMETRY *geometry, int index, float *directocclusion, float *reverbocclusion, FMOD_BOOL *doublesided); + +/* + Object manipulation. +*/ + +FMOD_RESULT F_API FMOD_Geometry_SetActive (FMOD_GEOMETRY *geometry, FMOD_BOOL active); +FMOD_RESULT F_API FMOD_Geometry_GetActive (FMOD_GEOMETRY *geometry, FMOD_BOOL *active); +FMOD_RESULT F_API FMOD_Geometry_SetRotation (FMOD_GEOMETRY *geometry, const FMOD_VECTOR *forward, const FMOD_VECTOR *up); +FMOD_RESULT F_API FMOD_Geometry_GetRotation (FMOD_GEOMETRY *geometry, FMOD_VECTOR *forward, FMOD_VECTOR *up); +FMOD_RESULT F_API FMOD_Geometry_SetPosition (FMOD_GEOMETRY *geometry, const FMOD_VECTOR *position); +FMOD_RESULT F_API FMOD_Geometry_GetPosition (FMOD_GEOMETRY *geometry, FMOD_VECTOR *position); +FMOD_RESULT F_API FMOD_Geometry_SetScale (FMOD_GEOMETRY *geometry, const FMOD_VECTOR *scale); +FMOD_RESULT F_API FMOD_Geometry_GetScale (FMOD_GEOMETRY *geometry, FMOD_VECTOR *scale); +FMOD_RESULT F_API FMOD_Geometry_Save (FMOD_GEOMETRY *geometry, void *data, int *datasize); + +/* + Userdata set/get. +*/ + +FMOD_RESULT F_API FMOD_Geometry_SetUserData (FMOD_GEOMETRY *geometry, void *userdata); +FMOD_RESULT F_API FMOD_Geometry_GetUserData (FMOD_GEOMETRY *geometry, void **userdata); + +/* + 'Reverb3D' API +*/ + +FMOD_RESULT F_API FMOD_Reverb3D_Release (FMOD_REVERB3D *reverb3d); + +/* + Reverb manipulation. +*/ + +FMOD_RESULT F_API FMOD_Reverb3D_Set3DAttributes (FMOD_REVERB3D *reverb3d, const FMOD_VECTOR *position, float mindistance, float maxdistance); +FMOD_RESULT F_API FMOD_Reverb3D_Get3DAttributes (FMOD_REVERB3D *reverb3d, FMOD_VECTOR *position, float *mindistance, float *maxdistance); +FMOD_RESULT F_API FMOD_Reverb3D_SetProperties (FMOD_REVERB3D *reverb3d, const FMOD_REVERB_PROPERTIES *properties); +FMOD_RESULT F_API FMOD_Reverb3D_GetProperties (FMOD_REVERB3D *reverb3d, FMOD_REVERB_PROPERTIES *properties); +FMOD_RESULT F_API FMOD_Reverb3D_SetActive (FMOD_REVERB3D *reverb3d, FMOD_BOOL active); +FMOD_RESULT F_API FMOD_Reverb3D_GetActive (FMOD_REVERB3D *reverb3d, FMOD_BOOL *active); + +/* + Userdata set/get. +*/ + +FMOD_RESULT F_API FMOD_Reverb3D_SetUserData (FMOD_REVERB3D *reverb3d, void *userdata); +FMOD_RESULT F_API FMOD_Reverb3D_GetUserData (FMOD_REVERB3D *reverb3d, void **userdata); + +#ifdef __cplusplus +} +#endif + +#endif /* _FMOD_H */ diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod.hpp b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod.hpp new file mode 100644 index 0000000..a77122c --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod.hpp @@ -0,0 +1,604 @@ +/* ======================================================================================== */ +/* FMOD Core API - C++ header file. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* */ +/* Use this header in conjunction with fmod_common.h (which contains all the constants / */ +/* callbacks) to develop using the C++ language. */ +/* */ +/* For more detail visit: */ +/* https://fmod.com/resources/documentation-api?version=2.0&page=core-api.html */ +/* ======================================================================================== */ +#ifndef _FMOD_HPP +#define _FMOD_HPP + +#include "fmod_common.h" +#include "fmod.h" + +/* + FMOD Namespace +*/ +namespace FMOD +{ + class System; + class Sound; + class ChannelControl; + class Channel; + class ChannelGroup; + class SoundGroup; + class DSP; + class DSPConnection; + class Geometry; + class Reverb3D; + + /* + FMOD global system functions (optional). + */ + inline FMOD_RESULT Memory_Initialize (void *poolmem, int poollen, FMOD_MEMORY_ALLOC_CALLBACK useralloc, FMOD_MEMORY_REALLOC_CALLBACK userrealloc, FMOD_MEMORY_FREE_CALLBACK userfree, FMOD_MEMORY_TYPE memtypeflags = FMOD_MEMORY_ALL) { return FMOD_Memory_Initialize(poolmem, poollen, useralloc, userrealloc, userfree, memtypeflags); } + inline FMOD_RESULT Memory_GetStats (int *currentalloced, int *maxalloced, bool blocking = true) { return FMOD_Memory_GetStats(currentalloced, maxalloced, blocking); } + inline FMOD_RESULT Debug_Initialize (FMOD_DEBUG_FLAGS flags, FMOD_DEBUG_MODE mode = FMOD_DEBUG_MODE_TTY, FMOD_DEBUG_CALLBACK callback = 0, const char *filename = 0) { return FMOD_Debug_Initialize(flags, mode, callback, filename); } + inline FMOD_RESULT File_SetDiskBusy (int busy) { return FMOD_File_SetDiskBusy(busy); } + inline FMOD_RESULT File_GetDiskBusy (int *busy) { return FMOD_File_GetDiskBusy(busy); } + + /* + FMOD System factory functions. + */ + inline FMOD_RESULT System_Create (System **system) { return FMOD_System_Create((FMOD_SYSTEM **)system); } + + /* + 'System' API + */ + class System + { + private: + + // Constructor made private so user cannot statically instance a System class. System_Create must be used. + System(); + System(const System &); + + public: + + FMOD_RESULT F_API release (); + + // Setup functions. + FMOD_RESULT F_API setOutput (FMOD_OUTPUTTYPE output); + FMOD_RESULT F_API getOutput (FMOD_OUTPUTTYPE *output); + FMOD_RESULT F_API getNumDrivers (int *numdrivers); + FMOD_RESULT F_API getDriverInfo (int id, char *name, int namelen, FMOD_GUID *guid, int *systemrate, FMOD_SPEAKERMODE *speakermode, int *speakermodechannels); + FMOD_RESULT F_API setDriver (int driver); + FMOD_RESULT F_API getDriver (int *driver); + FMOD_RESULT F_API setSoftwareChannels (int numsoftwarechannels); + FMOD_RESULT F_API getSoftwareChannels (int *numsoftwarechannels); + FMOD_RESULT F_API setSoftwareFormat (int samplerate, FMOD_SPEAKERMODE speakermode, int numrawspeakers); + FMOD_RESULT F_API getSoftwareFormat (int *samplerate, FMOD_SPEAKERMODE *speakermode, int *numrawspeakers); + FMOD_RESULT F_API setDSPBufferSize (unsigned int bufferlength, int numbuffers); + FMOD_RESULT F_API getDSPBufferSize (unsigned int *bufferlength, int *numbuffers); + FMOD_RESULT F_API setFileSystem (FMOD_FILE_OPEN_CALLBACK useropen, FMOD_FILE_CLOSE_CALLBACK userclose, FMOD_FILE_READ_CALLBACK userread, FMOD_FILE_SEEK_CALLBACK userseek, FMOD_FILE_ASYNCREAD_CALLBACK userasyncread, FMOD_FILE_ASYNCCANCEL_CALLBACK userasynccancel, int blockalign); + FMOD_RESULT F_API attachFileSystem (FMOD_FILE_OPEN_CALLBACK useropen, FMOD_FILE_CLOSE_CALLBACK userclose, FMOD_FILE_READ_CALLBACK userread, FMOD_FILE_SEEK_CALLBACK userseek); + FMOD_RESULT F_API setAdvancedSettings (FMOD_ADVANCEDSETTINGS *settings); + FMOD_RESULT F_API getAdvancedSettings (FMOD_ADVANCEDSETTINGS *settings); + FMOD_RESULT F_API setCallback (FMOD_SYSTEM_CALLBACK callback, FMOD_SYSTEM_CALLBACK_TYPE callbackmask = FMOD_SYSTEM_CALLBACK_ALL); + + // Plug-in support. + FMOD_RESULT F_API setPluginPath (const char *path); + FMOD_RESULT F_API loadPlugin (const char *filename, unsigned int *handle, unsigned int priority = 0); + FMOD_RESULT F_API unloadPlugin (unsigned int handle); + FMOD_RESULT F_API getNumNestedPlugins (unsigned int handle, int *count); + FMOD_RESULT F_API getNestedPlugin (unsigned int handle, int index, unsigned int *nestedhandle); + FMOD_RESULT F_API getNumPlugins (FMOD_PLUGINTYPE plugintype, int *numplugins); + FMOD_RESULT F_API getPluginHandle (FMOD_PLUGINTYPE plugintype, int index, unsigned int *handle); + FMOD_RESULT F_API getPluginInfo (unsigned int handle, FMOD_PLUGINTYPE *plugintype, char *name, int namelen, unsigned int *version); + FMOD_RESULT F_API setOutputByPlugin (unsigned int handle); + FMOD_RESULT F_API getOutputByPlugin (unsigned int *handle); + FMOD_RESULT F_API createDSPByPlugin (unsigned int handle, DSP **dsp); + FMOD_RESULT F_API getDSPInfoByPlugin (unsigned int handle, const FMOD_DSP_DESCRIPTION **description); + FMOD_RESULT F_API registerCodec (FMOD_CODEC_DESCRIPTION *description, unsigned int *handle, unsigned int priority = 0); + FMOD_RESULT F_API registerDSP (const FMOD_DSP_DESCRIPTION *description, unsigned int *handle); + FMOD_RESULT F_API registerOutput (const FMOD_OUTPUT_DESCRIPTION *description, unsigned int *handle); + + // Init/Close. + FMOD_RESULT F_API init (int maxchannels, FMOD_INITFLAGS flags, void *extradriverdata); + FMOD_RESULT F_API close (); + + // General post-init system functions. + FMOD_RESULT F_API update (); /* IMPORTANT! CALL THIS ONCE PER FRAME! */ + + FMOD_RESULT F_API setSpeakerPosition (FMOD_SPEAKER speaker, float x, float y, bool active); + FMOD_RESULT F_API getSpeakerPosition (FMOD_SPEAKER speaker, float *x, float *y, bool *active); + FMOD_RESULT F_API setStreamBufferSize (unsigned int filebuffersize, FMOD_TIMEUNIT filebuffersizetype); + FMOD_RESULT F_API getStreamBufferSize (unsigned int *filebuffersize, FMOD_TIMEUNIT *filebuffersizetype); + FMOD_RESULT F_API set3DSettings (float dopplerscale, float distancefactor, float rolloffscale); + FMOD_RESULT F_API get3DSettings (float *dopplerscale, float *distancefactor, float *rolloffscale); + FMOD_RESULT F_API set3DNumListeners (int numlisteners); + FMOD_RESULT F_API get3DNumListeners (int *numlisteners); + FMOD_RESULT F_API set3DListenerAttributes (int listener, const FMOD_VECTOR *pos, const FMOD_VECTOR *vel, const FMOD_VECTOR *forward, const FMOD_VECTOR *up); + FMOD_RESULT F_API get3DListenerAttributes (int listener, FMOD_VECTOR *pos, FMOD_VECTOR *vel, FMOD_VECTOR *forward, FMOD_VECTOR *up); + FMOD_RESULT F_API set3DRolloffCallback (FMOD_3D_ROLLOFF_CALLBACK callback); + FMOD_RESULT F_API mixerSuspend (); + FMOD_RESULT F_API mixerResume (); + FMOD_RESULT F_API getDefaultMixMatrix (FMOD_SPEAKERMODE sourcespeakermode, FMOD_SPEAKERMODE targetspeakermode, float *matrix, int matrixhop); + FMOD_RESULT F_API getSpeakerModeChannels (FMOD_SPEAKERMODE mode, int *channels); + + // System information functions. + FMOD_RESULT F_API getVersion (unsigned int *version); + FMOD_RESULT F_API getOutputHandle (void **handle); + FMOD_RESULT F_API getChannelsPlaying (int *channels, int *realchannels = 0); + FMOD_RESULT F_API getCPUUsage (float *dsp, float *stream, float *geometry, float *update, float *total); + FMOD_RESULT F_API getFileUsage (long long *sampleBytesRead, long long *streamBytesRead, long long *otherBytesRead); + + // Sound/DSP/Channel/FX creation and retrieval. + FMOD_RESULT F_API createSound (const char *name_or_data, FMOD_MODE mode, FMOD_CREATESOUNDEXINFO *exinfo, Sound **sound); + FMOD_RESULT F_API createStream (const char *name_or_data, FMOD_MODE mode, FMOD_CREATESOUNDEXINFO *exinfo, Sound **sound); + FMOD_RESULT F_API createDSP (const FMOD_DSP_DESCRIPTION *description, DSP **dsp); + FMOD_RESULT F_API createDSPByType (FMOD_DSP_TYPE type, DSP **dsp); + FMOD_RESULT F_API createChannelGroup (const char *name, ChannelGroup **channelgroup); + FMOD_RESULT F_API createSoundGroup (const char *name, SoundGroup **soundgroup); + FMOD_RESULT F_API createReverb3D (Reverb3D **reverb); + + FMOD_RESULT F_API playSound (Sound *sound, ChannelGroup *channelgroup, bool paused, Channel **channel); + FMOD_RESULT F_API playDSP (DSP *dsp, ChannelGroup *channelgroup, bool paused, Channel **channel); + FMOD_RESULT F_API getChannel (int channelid, Channel **channel); + FMOD_RESULT F_API getMasterChannelGroup (ChannelGroup **channelgroup); + FMOD_RESULT F_API getMasterSoundGroup (SoundGroup **soundgroup); + + // Routing to ports. + FMOD_RESULT F_API attachChannelGroupToPort (FMOD_PORT_TYPE portType, FMOD_PORT_INDEX portIndex, ChannelGroup *channelgroup, bool passThru = false); + FMOD_RESULT F_API detachChannelGroupFromPort (ChannelGroup *channelgroup); + + // Reverb API. + FMOD_RESULT F_API setReverbProperties (int instance, const FMOD_REVERB_PROPERTIES *prop); + FMOD_RESULT F_API getReverbProperties (int instance, FMOD_REVERB_PROPERTIES *prop); + + // System level DSP functionality. + FMOD_RESULT F_API lockDSP (); + FMOD_RESULT F_API unlockDSP (); + + // Recording API. + FMOD_RESULT F_API getRecordNumDrivers (int *numdrivers, int *numconnected); + FMOD_RESULT F_API getRecordDriverInfo (int id, char *name, int namelen, FMOD_GUID *guid, int *systemrate, FMOD_SPEAKERMODE *speakermode, int *speakermodechannels, FMOD_DRIVER_STATE *state); + FMOD_RESULT F_API getRecordPosition (int id, unsigned int *position); + FMOD_RESULT F_API recordStart (int id, Sound *sound, bool loop); + FMOD_RESULT F_API recordStop (int id); + FMOD_RESULT F_API isRecording (int id, bool *recording); + + // Geometry API. + FMOD_RESULT F_API createGeometry (int maxpolygons, int maxvertices, Geometry **geometry); + FMOD_RESULT F_API setGeometrySettings (float maxworldsize); + FMOD_RESULT F_API getGeometrySettings (float *maxworldsize); + FMOD_RESULT F_API loadGeometry (const void *data, int datasize, Geometry **geometry); + FMOD_RESULT F_API getGeometryOcclusion (const FMOD_VECTOR *listener, const FMOD_VECTOR *source, float *direct, float *reverb); + + // Network functions. + FMOD_RESULT F_API setNetworkProxy (const char *proxy); + FMOD_RESULT F_API getNetworkProxy (char *proxy, int proxylen); + FMOD_RESULT F_API setNetworkTimeout (int timeout); + FMOD_RESULT F_API getNetworkTimeout (int *timeout); + + // Userdata set/get. + FMOD_RESULT F_API setUserData (void *userdata); + FMOD_RESULT F_API getUserData (void **userdata); + }; + + /* + 'Sound' API + */ + class Sound + { + private: + + // Constructor made private so user cannot statically instance a Sound class. Appropriate Sound creation or retrieval function must be used. + Sound(); + Sound(const Sound &); + + public: + + FMOD_RESULT F_API release (); + FMOD_RESULT F_API getSystemObject (System **system); + + // Standard sound manipulation functions. + FMOD_RESULT F_API lock (unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2); + FMOD_RESULT F_API unlock (void *ptr1, void *ptr2, unsigned int len1, unsigned int len2); + FMOD_RESULT F_API setDefaults (float frequency, int priority); + FMOD_RESULT F_API getDefaults (float *frequency, int *priority); + FMOD_RESULT F_API set3DMinMaxDistance (float min, float max); + FMOD_RESULT F_API get3DMinMaxDistance (float *min, float *max); + FMOD_RESULT F_API set3DConeSettings (float insideconeangle, float outsideconeangle, float outsidevolume); + FMOD_RESULT F_API get3DConeSettings (float *insideconeangle, float *outsideconeangle, float *outsidevolume); + FMOD_RESULT F_API set3DCustomRolloff (FMOD_VECTOR *points, int numpoints); + FMOD_RESULT F_API get3DCustomRolloff (FMOD_VECTOR **points, int *numpoints); + FMOD_RESULT F_API getSubSound (int index, Sound **subsound); + FMOD_RESULT F_API getSubSoundParent (Sound **parentsound); + FMOD_RESULT F_API getName (char *name, int namelen); + FMOD_RESULT F_API getLength (unsigned int *length, FMOD_TIMEUNIT lengthtype); + FMOD_RESULT F_API getFormat (FMOD_SOUND_TYPE *type, FMOD_SOUND_FORMAT *format, int *channels, int *bits); + FMOD_RESULT F_API getNumSubSounds (int *numsubsounds); + FMOD_RESULT F_API getNumTags (int *numtags, int *numtagsupdated); + FMOD_RESULT F_API getTag (const char *name, int index, FMOD_TAG *tag); + FMOD_RESULT F_API getOpenState (FMOD_OPENSTATE *openstate, unsigned int *percentbuffered, bool *starving, bool *diskbusy); + FMOD_RESULT F_API readData (void *buffer, unsigned int length, unsigned int *read); + FMOD_RESULT F_API seekData (unsigned int pcm); + + FMOD_RESULT F_API setSoundGroup (SoundGroup *soundgroup); + FMOD_RESULT F_API getSoundGroup (SoundGroup **soundgroup); + + // Synchronization point API. These points can come from markers embedded in wav files, and can also generate channel callbacks. + FMOD_RESULT F_API getNumSyncPoints (int *numsyncpoints); + FMOD_RESULT F_API getSyncPoint (int index, FMOD_SYNCPOINT **point); + FMOD_RESULT F_API getSyncPointInfo (FMOD_SYNCPOINT *point, char *name, int namelen, unsigned int *offset, FMOD_TIMEUNIT offsettype); + FMOD_RESULT F_API addSyncPoint (unsigned int offset, FMOD_TIMEUNIT offsettype, const char *name, FMOD_SYNCPOINT **point); + FMOD_RESULT F_API deleteSyncPoint (FMOD_SYNCPOINT *point); + + // Functions also in Channel class but here they are the 'default' to save having to change it in Channel all the time. + FMOD_RESULT F_API setMode (FMOD_MODE mode); + FMOD_RESULT F_API getMode (FMOD_MODE *mode); + FMOD_RESULT F_API setLoopCount (int loopcount); + FMOD_RESULT F_API getLoopCount (int *loopcount); + FMOD_RESULT F_API setLoopPoints (unsigned int loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int loopend, FMOD_TIMEUNIT loopendtype); + FMOD_RESULT F_API getLoopPoints (unsigned int *loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int *loopend, FMOD_TIMEUNIT loopendtype); + + // For MOD/S3M/XM/IT/MID sequenced formats only. + FMOD_RESULT F_API getMusicNumChannels (int *numchannels); + FMOD_RESULT F_API setMusicChannelVolume (int channel, float volume); + FMOD_RESULT F_API getMusicChannelVolume (int channel, float *volume); + FMOD_RESULT F_API setMusicSpeed (float speed); + FMOD_RESULT F_API getMusicSpeed (float *speed); + + // Userdata set/get. + FMOD_RESULT F_API setUserData (void *userdata); + FMOD_RESULT F_API getUserData (void **userdata); + }; + + + /* + 'ChannelControl API'. This is a base class for Channel and ChannelGroup so they can share the same functionality. This cannot be used or instansiated explicitly. + */ + class ChannelControl + { + private: + + // Constructor made private so user cannot statically instance a Control class. + ChannelControl(); + ChannelControl(const ChannelControl &); + + public: + + FMOD_RESULT F_API getSystemObject (System **system); + + // General control functionality for Channels and ChannelGroups. + FMOD_RESULT F_API stop (); + FMOD_RESULT F_API setPaused (bool paused); + FMOD_RESULT F_API getPaused (bool *paused); + FMOD_RESULT F_API setVolume (float volume); + FMOD_RESULT F_API getVolume (float *volume); + FMOD_RESULT F_API setVolumeRamp (bool ramp); + FMOD_RESULT F_API getVolumeRamp (bool *ramp); + FMOD_RESULT F_API getAudibility (float *audibility); + FMOD_RESULT F_API setPitch (float pitch); + FMOD_RESULT F_API getPitch (float *pitch); + FMOD_RESULT F_API setMute (bool mute); + FMOD_RESULT F_API getMute (bool *mute); + FMOD_RESULT F_API setReverbProperties (int instance, float wet); + FMOD_RESULT F_API getReverbProperties (int instance, float *wet); + FMOD_RESULT F_API setLowPassGain (float gain); + FMOD_RESULT F_API getLowPassGain (float *gain); + FMOD_RESULT F_API setMode (FMOD_MODE mode); + FMOD_RESULT F_API getMode (FMOD_MODE *mode); + FMOD_RESULT F_API setCallback (FMOD_CHANNELCONTROL_CALLBACK callback); + FMOD_RESULT F_API isPlaying (bool *isplaying); + + // Panning and level adjustment. + // Note all 'set' functions alter a final matrix, this is why the only get function is getMixMatrix, to avoid other get functions returning incorrect/obsolete values. + FMOD_RESULT F_API setPan (float pan); + FMOD_RESULT F_API setMixLevelsOutput (float frontleft, float frontright, float center, float lfe, float surroundleft, float surroundright, float backleft, float backright); + FMOD_RESULT F_API setMixLevelsInput (float *levels, int numlevels); + FMOD_RESULT F_API setMixMatrix (float *matrix, int outchannels, int inchannels, int inchannel_hop = 0); + FMOD_RESULT F_API getMixMatrix (float *matrix, int *outchannels, int *inchannels, int inchannel_hop = 0); + + // Clock based functionality. + FMOD_RESULT F_API getDSPClock (unsigned long long *dspclock, unsigned long long *parentclock); + FMOD_RESULT F_API setDelay (unsigned long long dspclock_start, unsigned long long dspclock_end, bool stopchannels = true); + FMOD_RESULT F_API getDelay (unsigned long long *dspclock_start, unsigned long long *dspclock_end, bool *stopchannels = 0); + FMOD_RESULT F_API addFadePoint (unsigned long long dspclock, float volume); + FMOD_RESULT F_API setFadePointRamp (unsigned long long dspclock, float volume); + FMOD_RESULT F_API removeFadePoints (unsigned long long dspclock_start, unsigned long long dspclock_end); + FMOD_RESULT F_API getFadePoints (unsigned int *numpoints, unsigned long long *point_dspclock, float *point_volume); + + // DSP effects. + FMOD_RESULT F_API getDSP (int index, DSP **dsp); + FMOD_RESULT F_API addDSP (int index, DSP *dsp); + FMOD_RESULT F_API removeDSP (DSP *dsp); + FMOD_RESULT F_API getNumDSPs (int *numdsps); + FMOD_RESULT F_API setDSPIndex (DSP *dsp, int index); + FMOD_RESULT F_API getDSPIndex (DSP *dsp, int *index); + + // 3D functionality. + FMOD_RESULT F_API set3DAttributes (const FMOD_VECTOR *pos, const FMOD_VECTOR *vel); + FMOD_RESULT F_API get3DAttributes (FMOD_VECTOR *pos, FMOD_VECTOR *vel); + FMOD_RESULT F_API set3DMinMaxDistance (float mindistance, float maxdistance); + FMOD_RESULT F_API get3DMinMaxDistance (float *mindistance, float *maxdistance); + FMOD_RESULT F_API set3DConeSettings (float insideconeangle, float outsideconeangle, float outsidevolume); + FMOD_RESULT F_API get3DConeSettings (float *insideconeangle, float *outsideconeangle, float *outsidevolume); + FMOD_RESULT F_API set3DConeOrientation (FMOD_VECTOR *orientation); + FMOD_RESULT F_API get3DConeOrientation (FMOD_VECTOR *orientation); + FMOD_RESULT F_API set3DCustomRolloff (FMOD_VECTOR *points, int numpoints); + FMOD_RESULT F_API get3DCustomRolloff (FMOD_VECTOR **points, int *numpoints); + FMOD_RESULT F_API set3DOcclusion (float directocclusion, float reverbocclusion); + FMOD_RESULT F_API get3DOcclusion (float *directocclusion, float *reverbocclusion); + FMOD_RESULT F_API set3DSpread (float angle); + FMOD_RESULT F_API get3DSpread (float *angle); + FMOD_RESULT F_API set3DLevel (float level); + FMOD_RESULT F_API get3DLevel (float *level); + FMOD_RESULT F_API set3DDopplerLevel (float level); + FMOD_RESULT F_API get3DDopplerLevel (float *level); + FMOD_RESULT F_API set3DDistanceFilter (bool custom, float customLevel, float centerFreq); + FMOD_RESULT F_API get3DDistanceFilter (bool *custom, float *customLevel, float *centerFreq); + + // Userdata set/get. + FMOD_RESULT F_API setUserData (void *userdata); + FMOD_RESULT F_API getUserData (void **userdata); + }; + + /* + 'Channel' API. + */ + class Channel : public ChannelControl + { + private: + + // Constructor made private so user cannot statically instance a Channel class. Appropriate Channel creation or retrieval function must be used. + Channel(); + Channel(const Channel &); + + public: + + // Channel specific control functionality. + FMOD_RESULT F_API setFrequency (float frequency); + FMOD_RESULT F_API getFrequency (float *frequency); + FMOD_RESULT F_API setPriority (int priority); + FMOD_RESULT F_API getPriority (int *priority); + FMOD_RESULT F_API setPosition (unsigned int position, FMOD_TIMEUNIT postype); + FMOD_RESULT F_API getPosition (unsigned int *position, FMOD_TIMEUNIT postype); + FMOD_RESULT F_API setChannelGroup (ChannelGroup *channelgroup); + FMOD_RESULT F_API getChannelGroup (ChannelGroup **channelgroup); + FMOD_RESULT F_API setLoopCount (int loopcount); + FMOD_RESULT F_API getLoopCount (int *loopcount); + FMOD_RESULT F_API setLoopPoints (unsigned int loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int loopend, FMOD_TIMEUNIT loopendtype); + FMOD_RESULT F_API getLoopPoints (unsigned int *loopstart, FMOD_TIMEUNIT loopstarttype, unsigned int *loopend, FMOD_TIMEUNIT loopendtype); + + // Information only functions. + FMOD_RESULT F_API isVirtual (bool *isvirtual); + FMOD_RESULT F_API getCurrentSound (Sound **sound); + FMOD_RESULT F_API getIndex (int *index); + }; + + /* + 'ChannelGroup' API + */ + class ChannelGroup : public ChannelControl + { + private: + + // Constructor made private so user cannot statically instance a ChannelGroup class. Appropriate ChannelGroup creation or retrieval function must be used. + ChannelGroup(); + ChannelGroup(const ChannelGroup &); + + public: + + FMOD_RESULT F_API release (); + + // Nested channel groups. + FMOD_RESULT F_API addGroup (ChannelGroup *group, bool propagatedspclock = true, DSPConnection **connection = 0); + FMOD_RESULT F_API getNumGroups (int *numgroups); + FMOD_RESULT F_API getGroup (int index, ChannelGroup **group); + FMOD_RESULT F_API getParentGroup (ChannelGroup **group); + + // Information only functions. + FMOD_RESULT F_API getName (char *name, int namelen); + FMOD_RESULT F_API getNumChannels (int *numchannels); + FMOD_RESULT F_API getChannel (int index, Channel **channel); + }; + + /* + 'SoundGroup' API + */ + class SoundGroup + { + private: + + // Constructor made private so user cannot statically instance a SoundGroup class. Appropriate SoundGroup creation or retrieval function must be used. + SoundGroup(); + SoundGroup(const SoundGroup &); + + public: + + FMOD_RESULT F_API release (); + FMOD_RESULT F_API getSystemObject (System **system); + + // SoundGroup control functions. + FMOD_RESULT F_API setMaxAudible (int maxaudible); + FMOD_RESULT F_API getMaxAudible (int *maxaudible); + FMOD_RESULT F_API setMaxAudibleBehavior (FMOD_SOUNDGROUP_BEHAVIOR behavior); + FMOD_RESULT F_API getMaxAudibleBehavior (FMOD_SOUNDGROUP_BEHAVIOR *behavior); + FMOD_RESULT F_API setMuteFadeSpeed (float speed); + FMOD_RESULT F_API getMuteFadeSpeed (float *speed); + FMOD_RESULT F_API setVolume (float volume); + FMOD_RESULT F_API getVolume (float *volume); + FMOD_RESULT F_API stop (); + + // Information only functions. + FMOD_RESULT F_API getName (char *name, int namelen); + FMOD_RESULT F_API getNumSounds (int *numsounds); + FMOD_RESULT F_API getSound (int index, Sound **sound); + FMOD_RESULT F_API getNumPlaying (int *numplaying); + + // Userdata set/get. + FMOD_RESULT F_API setUserData (void *userdata); + FMOD_RESULT F_API getUserData (void **userdata); + }; + + /* + 'DSP' API + */ + class DSP + { + private: + + // Constructor made private so user cannot statically instance a DSP class. Appropriate DSP creation or retrieval function must be used. + DSP(); + DSP(const DSP &); + + public: + + FMOD_RESULT F_API release (); + FMOD_RESULT F_API getSystemObject (System **system); + + // Connection / disconnection / input and output enumeration. + FMOD_RESULT F_API addInput (DSP *input, DSPConnection **connection = 0, FMOD_DSPCONNECTION_TYPE type = FMOD_DSPCONNECTION_TYPE_STANDARD); + FMOD_RESULT F_API disconnectFrom (DSP *target, DSPConnection *connection = 0); + FMOD_RESULT F_API disconnectAll (bool inputs, bool outputs); + FMOD_RESULT F_API getNumInputs (int *numinputs); + FMOD_RESULT F_API getNumOutputs (int *numoutputs); + FMOD_RESULT F_API getInput (int index, DSP **input, DSPConnection **inputconnection); + FMOD_RESULT F_API getOutput (int index, DSP **output, DSPConnection **outputconnection); + + // DSP unit control. + FMOD_RESULT F_API setActive (bool active); + FMOD_RESULT F_API getActive (bool *active); + FMOD_RESULT F_API setBypass (bool bypass); + FMOD_RESULT F_API getBypass (bool *bypass); + FMOD_RESULT F_API setWetDryMix (float prewet, float postwet, float dry); + FMOD_RESULT F_API getWetDryMix (float *prewet, float *postwet, float *dry); + FMOD_RESULT F_API setChannelFormat (FMOD_CHANNELMASK channelmask, int numchannels, FMOD_SPEAKERMODE source_speakermode); + FMOD_RESULT F_API getChannelFormat (FMOD_CHANNELMASK *channelmask, int *numchannels, FMOD_SPEAKERMODE *source_speakermode); + FMOD_RESULT F_API getOutputChannelFormat (FMOD_CHANNELMASK inmask, int inchannels, FMOD_SPEAKERMODE inspeakermode, FMOD_CHANNELMASK *outmask, int *outchannels, FMOD_SPEAKERMODE *outspeakermode); + FMOD_RESULT F_API reset (); + + // DSP parameter control. + FMOD_RESULT F_API setParameterFloat (int index, float value); + FMOD_RESULT F_API setParameterInt (int index, int value); + FMOD_RESULT F_API setParameterBool (int index, bool value); + FMOD_RESULT F_API setParameterData (int index, void *data, unsigned int length); + FMOD_RESULT F_API getParameterFloat (int index, float *value, char *valuestr, int valuestrlen); + FMOD_RESULT F_API getParameterInt (int index, int *value, char *valuestr, int valuestrlen); + FMOD_RESULT F_API getParameterBool (int index, bool *value, char *valuestr, int valuestrlen); + FMOD_RESULT F_API getParameterData (int index, void **data, unsigned int *length, char *valuestr, int valuestrlen); + FMOD_RESULT F_API getNumParameters (int *numparams); + FMOD_RESULT F_API getParameterInfo (int index, FMOD_DSP_PARAMETER_DESC **desc); + FMOD_RESULT F_API getDataParameterIndex (int datatype, int *index); + FMOD_RESULT F_API showConfigDialog (void *hwnd, bool show); + + // DSP attributes. + FMOD_RESULT F_API getInfo (char *name, unsigned int *version, int *channels, int *configwidth, int *configheight); + FMOD_RESULT F_API getType (FMOD_DSP_TYPE *type); + FMOD_RESULT F_API getIdle (bool *idle); + + // Userdata set/get. + FMOD_RESULT F_API setUserData (void *userdata); + FMOD_RESULT F_API getUserData (void **userdata); + + // Metering. + FMOD_RESULT F_API setMeteringEnabled (bool inputEnabled, bool outputEnabled); + FMOD_RESULT F_API getMeteringEnabled (bool *inputEnabled, bool *outputEnabled); + FMOD_RESULT F_API getMeteringInfo (FMOD_DSP_METERING_INFO *inputInfo, FMOD_DSP_METERING_INFO *outputInfo); + FMOD_RESULT F_API getCPUUsage (unsigned int *exclusive, unsigned int *inclusive); + }; + + + /* + 'DSPConnection' API + */ + class DSPConnection + { + private: + + // Constructor made private so user cannot statically instance a DSPConnection class. Appropriate DSPConnection creation or retrieval function must be used. + DSPConnection(); + DSPConnection(const DSPConnection &); + + public: + + FMOD_RESULT F_API getInput (DSP **input); + FMOD_RESULT F_API getOutput (DSP **output); + FMOD_RESULT F_API setMix (float volume); + FMOD_RESULT F_API getMix (float *volume); + FMOD_RESULT F_API setMixMatrix (float *matrix, int outchannels, int inchannels, int inchannel_hop = 0); + FMOD_RESULT F_API getMixMatrix (float *matrix, int *outchannels, int *inchannels, int inchannel_hop = 0); + FMOD_RESULT F_API getType (FMOD_DSPCONNECTION_TYPE *type); + + // Userdata set/get. + FMOD_RESULT F_API setUserData (void *userdata); + FMOD_RESULT F_API getUserData (void **userdata); + }; + + + /* + 'Geometry' API + */ + class Geometry + { + private: + + // Constructor made private so user cannot statically instance a Geometry class. Appropriate Geometry creation or retrieval function must be used. + Geometry(); + Geometry(const Geometry &); + + public: + + FMOD_RESULT F_API release (); + + // Polygon manipulation. + FMOD_RESULT F_API addPolygon (float directocclusion, float reverbocclusion, bool doublesided, int numvertices, const FMOD_VECTOR *vertices, int *polygonindex); + FMOD_RESULT F_API getNumPolygons (int *numpolygons); + FMOD_RESULT F_API getMaxPolygons (int *maxpolygons, int *maxvertices); + FMOD_RESULT F_API getPolygonNumVertices (int index, int *numvertices); + FMOD_RESULT F_API setPolygonVertex (int index, int vertexindex, const FMOD_VECTOR *vertex); + FMOD_RESULT F_API getPolygonVertex (int index, int vertexindex, FMOD_VECTOR *vertex); + FMOD_RESULT F_API setPolygonAttributes (int index, float directocclusion, float reverbocclusion, bool doublesided); + FMOD_RESULT F_API getPolygonAttributes (int index, float *directocclusion, float *reverbocclusion, bool *doublesided); + + // Object manipulation. + FMOD_RESULT F_API setActive (bool active); + FMOD_RESULT F_API getActive (bool *active); + FMOD_RESULT F_API setRotation (const FMOD_VECTOR *forward, const FMOD_VECTOR *up); + FMOD_RESULT F_API getRotation (FMOD_VECTOR *forward, FMOD_VECTOR *up); + FMOD_RESULT F_API setPosition (const FMOD_VECTOR *position); + FMOD_RESULT F_API getPosition (FMOD_VECTOR *position); + FMOD_RESULT F_API setScale (const FMOD_VECTOR *scale); + FMOD_RESULT F_API getScale (FMOD_VECTOR *scale); + FMOD_RESULT F_API save (void *data, int *datasize); + + // Userdata set/get. + FMOD_RESULT F_API setUserData (void *userdata); + FMOD_RESULT F_API getUserData (void **userdata); + }; + + + /* + 'Reverb' API + */ + class Reverb3D + { + private: + + // Constructor made private so user cannot statically instance a Reverb3D class. Appropriate Reverb creation or retrieval function must be used. + Reverb3D(); + Reverb3D(const Reverb3D &); + + public: + + FMOD_RESULT F_API release (); + + // Reverb manipulation. + FMOD_RESULT F_API set3DAttributes (const FMOD_VECTOR *position, float mindistance, float maxdistance); + FMOD_RESULT F_API get3DAttributes (FMOD_VECTOR *position, float *mindistance,float *maxdistance); + FMOD_RESULT F_API setProperties (const FMOD_REVERB_PROPERTIES *properties); + FMOD_RESULT F_API getProperties (FMOD_REVERB_PROPERTIES *properties); + FMOD_RESULT F_API setActive (bool active); + FMOD_RESULT F_API getActive (bool *active); + + // Userdata set/get. + FMOD_RESULT F_API setUserData (void *userdata); + FMOD_RESULT F_API getUserData (void **userdata); + }; +} + +#endif diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_android.h b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_android.h new file mode 100644 index 0000000..9456994 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_android.h @@ -0,0 +1,75 @@ +#ifndef _FMOD_ANDROID_H +#define _FMOD_ANDROID_H + +/* +[ENUM] +[ + [DESCRIPTION] + Cores available for mapping threads onto. + + [REMARKS] + + [SEE_ALSO] + FMOD_ANDROID_THREADAFFINITY +] +*/ +typedef enum FMOD_THREAD +{ + FMOD_THREAD_DEFAULT = 0, /* Use default thread assignment. */ + FMOD_THREAD_CORE0 = 1 << 0, + FMOD_THREAD_CORE1 = 1 << 1, + FMOD_THREAD_CORE2 = 1 << 2, + FMOD_THREAD_CORE3 = 1 << 3, + FMOD_THREAD_CORE4 = 1 << 4, + FMOD_THREAD_CORE5 = 1 << 5, + FMOD_THREAD_CORE6 = 1 << 6, + FMOD_THREAD_CORE7 = 1 << 7, +} FMOD_THREAD; + + +/* +[STRUCTURE] +[ + [DESCRIPTION] + Mapping of cores to threads. + + [REMARKS] + + [SEE_ALSO] + FMOD_THREAD + FMOD_Android_SetThreadAffinity +] +*/ +typedef struct FMOD_ANDROID_THREADAFFINITY +{ + unsigned int mixer; /* Software mixer thread. */ + unsigned int stream; /* Stream thread. */ + unsigned int nonblocking; /* Asynchronous sound loading thread. */ + unsigned int file; /* File thread. */ + unsigned int geometry; /* Geometry processing thread. */ + unsigned int profiler; /* Profiler threads. */ + unsigned int studioUpdate; /* Studio update thread. */ + unsigned int studioLoadBank; /* Studio bank loading thread. */ + unsigned int studioLoadSample; /* Studio sample loading thread. */ +} FMOD_ANDROID_THREADAFFINITY; + + +/* +[API] +[ + [DESCRIPTION] + Control which core particular FMOD threads are created on. + + [PARAMETERS] + 'affinity' Pointer to a structure that describes the affinity for each thread. + + [REMARKS] + Call before System::init or affinity values will not apply. + + [SEE_ALSO] + FMOD_ANDROID_THREADAFFINITY +] +*/ +extern "C" FMOD_RESULT F_API FMOD_Android_SetThreadAffinity(FMOD_ANDROID_THREADAFFINITY *affinity); + +#endif /* _FMOD_ANDROID_H */ diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_codec.h b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_codec.h new file mode 100644 index 0000000..59a26f3 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_codec.h @@ -0,0 +1,93 @@ +/* ======================================================================================== */ +/* FMOD Core API - Codec development header file. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* */ +/* Use this header if you are wanting to develop your own file format plugin to use with */ +/* FMOD's codec system. With this header you can make your own fileformat plugin that FMOD */ +/* can register and use. See the documentation and examples on how to make a working */ +/* plugin. */ +/* */ +/* For more detail visit: */ +/* https://fmod.com/resources/documentation-api?version=2.0&page=core-api.html */ +/* ======================================================================================== */ +#ifndef _FMOD_CODEC_H +#define _FMOD_CODEC_H + +/* + Codec types +*/ +typedef struct FMOD_CODEC_STATE FMOD_CODEC_STATE; +typedef struct FMOD_CODEC_WAVEFORMAT FMOD_CODEC_WAVEFORMAT; + +/* + Codec constants +*/ +#define FMOD_CODEC_WAVEFORMAT_VERSION 3 + +/* + Codec callbacks +*/ +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_OPEN_CALLBACK) (FMOD_CODEC_STATE *codec_state, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo); +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_CLOSE_CALLBACK) (FMOD_CODEC_STATE *codec_state); +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_READ_CALLBACK) (FMOD_CODEC_STATE *codec_state, void *buffer, unsigned int samples_in, unsigned int *samples_out); +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_GETLENGTH_CALLBACK) (FMOD_CODEC_STATE *codec_state, unsigned int *length, FMOD_TIMEUNIT lengthtype); +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_SETPOSITION_CALLBACK) (FMOD_CODEC_STATE *codec_state, int subsound, unsigned int position, FMOD_TIMEUNIT postype); +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_GETPOSITION_CALLBACK) (FMOD_CODEC_STATE *codec_state, unsigned int *position, FMOD_TIMEUNIT postype); +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_SOUNDCREATE_CALLBACK) (FMOD_CODEC_STATE *codec_state, int subsound, FMOD_SOUND *sound); +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_METADATA_CALLBACK) (FMOD_CODEC_STATE *codec_state, FMOD_TAGTYPE tagtype, char *name, void *data, unsigned int datalen, FMOD_TAGDATATYPE datatype, int unique); +typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_GETWAVEFORMAT_CALLBACK)(FMOD_CODEC_STATE *codec_state, int index, FMOD_CODEC_WAVEFORMAT *waveformat); + +/* + Codec structures +*/ +typedef struct FMOD_CODEC_DESCRIPTION +{ + const char *name; + unsigned int version; + int defaultasstream; + FMOD_TIMEUNIT timeunits; + FMOD_CODEC_OPEN_CALLBACK open; + FMOD_CODEC_CLOSE_CALLBACK close; + FMOD_CODEC_READ_CALLBACK read; + FMOD_CODEC_GETLENGTH_CALLBACK getlength; + FMOD_CODEC_SETPOSITION_CALLBACK setposition; + FMOD_CODEC_GETPOSITION_CALLBACK getposition; + FMOD_CODEC_SOUNDCREATE_CALLBACK soundcreate; + FMOD_CODEC_GETWAVEFORMAT_CALLBACK getwaveformat; +} FMOD_CODEC_DESCRIPTION; + +struct FMOD_CODEC_WAVEFORMAT +{ + const char* name; + FMOD_SOUND_FORMAT format; + int channels; + int frequency; + unsigned int lengthbytes; + unsigned int lengthpcm; + unsigned int pcmblocksize; + int loopstart; + int loopend; + FMOD_MODE mode; + FMOD_CHANNELMASK channelmask; + FMOD_CHANNELORDER channelorder; + float peakvolume; +}; + +struct FMOD_CODEC_STATE +{ + int numsubsounds; + FMOD_CODEC_WAVEFORMAT *waveformat; + void *plugindata; + + void *filehandle; + unsigned int filesize; + FMOD_FILE_READ_CALLBACK fileread; + FMOD_FILE_SEEK_CALLBACK fileseek; + FMOD_CODEC_METADATA_CALLBACK metadata; + + int waveformatversion; +}; + +#endif + + diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_common.h b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_common.h new file mode 100644 index 0000000..99cb99d --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_common.h @@ -0,0 +1,752 @@ +/* ======================================================================================== */ +/* FMOD Core API - Common C/C++ header file. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* */ +/* This header is included by fmod.hpp (C++ interface) and fmod.h (C interface) */ +/* */ +/* For more detail visit: */ +/* https://fmod.com/resources/documentation-api?version=2.0&page=core-api-common.html */ +/* ======================================================================================== */ +#ifndef _FMOD_COMMON_H +#define _FMOD_COMMON_H + +/* + Library import helpers +*/ +#if defined(_WIN32) || defined(__CYGWIN__) + #define F_CALL __stdcall +#else + #define F_CALL +#endif + +#if defined(_WIN32) || defined(__CYGWIN__) || defined(__ORBIS__) || defined(F_USE_DECLSPEC) + #define F_EXPORT __declspec(dllexport) +#elif defined(__APPLE__) || defined(__ANDROID__) || defined(__linux__) || defined(F_USE_ATTRIBUTE) + #define F_EXPORT __attribute__((visibility("default"))) +#else + #define F_EXPORT +#endif + +#ifdef DLL_EXPORTS + #define F_API F_EXPORT F_CALL +#else + #define F_API F_CALL +#endif + +#define F_CALLBACK F_CALL + +/* + FMOD core types +*/ +typedef int FMOD_BOOL; +typedef struct FMOD_SYSTEM FMOD_SYSTEM; +typedef struct FMOD_SOUND FMOD_SOUND; +typedef struct FMOD_CHANNELCONTROL FMOD_CHANNELCONTROL; +typedef struct FMOD_CHANNEL FMOD_CHANNEL; +typedef struct FMOD_CHANNELGROUP FMOD_CHANNELGROUP; +typedef struct FMOD_SOUNDGROUP FMOD_SOUNDGROUP; +typedef struct FMOD_REVERB3D FMOD_REVERB3D; +typedef struct FMOD_DSP FMOD_DSP; +typedef struct FMOD_DSPCONNECTION FMOD_DSPCONNECTION; +typedef struct FMOD_POLYGON FMOD_POLYGON; +typedef struct FMOD_GEOMETRY FMOD_GEOMETRY; +typedef struct FMOD_SYNCPOINT FMOD_SYNCPOINT; +typedef struct FMOD_ASYNCREADINFO FMOD_ASYNCREADINFO; +typedef unsigned int FMOD_PORT_TYPE; +typedef unsigned long long FMOD_PORT_INDEX; + +/* + FMOD constants +*/ +#define FMOD_VERSION 0x00020010 /* 0xaaaabbcc -> aaaa = product version, bb = major version, cc = minor version.*/ + +typedef unsigned int FMOD_DEBUG_FLAGS; +#define FMOD_DEBUG_LEVEL_NONE 0x00000000 +#define FMOD_DEBUG_LEVEL_ERROR 0x00000001 +#define FMOD_DEBUG_LEVEL_WARNING 0x00000002 +#define FMOD_DEBUG_LEVEL_LOG 0x00000004 +#define FMOD_DEBUG_TYPE_MEMORY 0x00000100 +#define FMOD_DEBUG_TYPE_FILE 0x00000200 +#define FMOD_DEBUG_TYPE_CODEC 0x00000400 +#define FMOD_DEBUG_TYPE_TRACE 0x00000800 +#define FMOD_DEBUG_DISPLAY_TIMESTAMPS 0x00010000 +#define FMOD_DEBUG_DISPLAY_LINENUMBERS 0x00020000 +#define FMOD_DEBUG_DISPLAY_THREAD 0x00040000 + +typedef unsigned int FMOD_MEMORY_TYPE; +#define FMOD_MEMORY_NORMAL 0x00000000 +#define FMOD_MEMORY_STREAM_FILE 0x00000001 +#define FMOD_MEMORY_STREAM_DECODE 0x00000002 +#define FMOD_MEMORY_SAMPLEDATA 0x00000004 +#define FMOD_MEMORY_DSP_BUFFER 0x00000008 +#define FMOD_MEMORY_PLUGIN 0x00000010 +#define FMOD_MEMORY_PERSISTENT 0x00200000 +#define FMOD_MEMORY_ALL 0xFFFFFFFF + +typedef unsigned int FMOD_INITFLAGS; +#define FMOD_INIT_NORMAL 0x00000000 +#define FMOD_INIT_STREAM_FROM_UPDATE 0x00000001 +#define FMOD_INIT_MIX_FROM_UPDATE 0x00000002 +#define FMOD_INIT_3D_RIGHTHANDED 0x00000004 +#define FMOD_INIT_CHANNEL_LOWPASS 0x00000100 +#define FMOD_INIT_CHANNEL_DISTANCEFILTER 0x00000200 +#define FMOD_INIT_PROFILE_ENABLE 0x00010000 +#define FMOD_INIT_VOL0_BECOMES_VIRTUAL 0x00020000 +#define FMOD_INIT_GEOMETRY_USECLOSEST 0x00040000 +#define FMOD_INIT_PREFER_DOLBY_DOWNMIX 0x00080000 +#define FMOD_INIT_THREAD_UNSAFE 0x00100000 +#define FMOD_INIT_PROFILE_METER_ALL 0x00200000 +#define FMOD_INIT_MEMORY_TRACKING 0x00400000 + +typedef unsigned int FMOD_DRIVER_STATE; +#define FMOD_DRIVER_STATE_CONNECTED 0x00000001 +#define FMOD_DRIVER_STATE_DEFAULT 0x00000002 + +typedef unsigned int FMOD_TIMEUNIT; +#define FMOD_TIMEUNIT_MS 0x00000001 +#define FMOD_TIMEUNIT_PCM 0x00000002 +#define FMOD_TIMEUNIT_PCMBYTES 0x00000004 +#define FMOD_TIMEUNIT_RAWBYTES 0x00000008 +#define FMOD_TIMEUNIT_PCMFRACTION 0x00000010 +#define FMOD_TIMEUNIT_MODORDER 0x00000100 +#define FMOD_TIMEUNIT_MODROW 0x00000200 +#define FMOD_TIMEUNIT_MODPATTERN 0x00000400 + +typedef unsigned int FMOD_SYSTEM_CALLBACK_TYPE; +#define FMOD_SYSTEM_CALLBACK_DEVICELISTCHANGED 0x00000001 +#define FMOD_SYSTEM_CALLBACK_DEVICELOST 0x00000002 +#define FMOD_SYSTEM_CALLBACK_MEMORYALLOCATIONFAILED 0x00000004 +#define FMOD_SYSTEM_CALLBACK_THREADCREATED 0x00000008 +#define FMOD_SYSTEM_CALLBACK_BADDSPCONNECTION 0x00000010 +#define FMOD_SYSTEM_CALLBACK_PREMIX 0x00000020 +#define FMOD_SYSTEM_CALLBACK_POSTMIX 0x00000040 +#define FMOD_SYSTEM_CALLBACK_ERROR 0x00000080 +#define FMOD_SYSTEM_CALLBACK_MIDMIX 0x00000100 +#define FMOD_SYSTEM_CALLBACK_THREADDESTROYED 0x00000200 +#define FMOD_SYSTEM_CALLBACK_PREUPDATE 0x00000400 +#define FMOD_SYSTEM_CALLBACK_POSTUPDATE 0x00000800 +#define FMOD_SYSTEM_CALLBACK_RECORDLISTCHANGED 0x00001000 +#define FMOD_SYSTEM_CALLBACK_ALL 0xFFFFFFFF + +typedef unsigned int FMOD_MODE; +#define FMOD_DEFAULT 0x00000000 +#define FMOD_LOOP_OFF 0x00000001 +#define FMOD_LOOP_NORMAL 0x00000002 +#define FMOD_LOOP_BIDI 0x00000004 +#define FMOD_2D 0x00000008 +#define FMOD_3D 0x00000010 +#define FMOD_CREATESTREAM 0x00000080 +#define FMOD_CREATESAMPLE 0x00000100 +#define FMOD_CREATECOMPRESSEDSAMPLE 0x00000200 +#define FMOD_OPENUSER 0x00000400 +#define FMOD_OPENMEMORY 0x00000800 +#define FMOD_OPENMEMORY_POINT 0x10000000 +#define FMOD_OPENRAW 0x00001000 +#define FMOD_OPENONLY 0x00002000 +#define FMOD_ACCURATETIME 0x00004000 +#define FMOD_MPEGSEARCH 0x00008000 +#define FMOD_NONBLOCKING 0x00010000 +#define FMOD_UNIQUE 0x00020000 +#define FMOD_3D_HEADRELATIVE 0x00040000 +#define FMOD_3D_WORLDRELATIVE 0x00080000 +#define FMOD_3D_INVERSEROLLOFF 0x00100000 +#define FMOD_3D_LINEARROLLOFF 0x00200000 +#define FMOD_3D_LINEARSQUAREROLLOFF 0x00400000 +#define FMOD_3D_INVERSETAPEREDROLLOFF 0x00800000 +#define FMOD_3D_CUSTOMROLLOFF 0x04000000 +#define FMOD_3D_IGNOREGEOMETRY 0x40000000 +#define FMOD_IGNORETAGS 0x02000000 +#define FMOD_LOWMEM 0x08000000 +#define FMOD_VIRTUAL_PLAYFROMSTART 0x80000000 + +typedef unsigned int FMOD_CHANNELMASK; +#define FMOD_CHANNELMASK_FRONT_LEFT 0x00000001 +#define FMOD_CHANNELMASK_FRONT_RIGHT 0x00000002 +#define FMOD_CHANNELMASK_FRONT_CENTER 0x00000004 +#define FMOD_CHANNELMASK_LOW_FREQUENCY 0x00000008 +#define FMOD_CHANNELMASK_SURROUND_LEFT 0x00000010 +#define FMOD_CHANNELMASK_SURROUND_RIGHT 0x00000020 +#define FMOD_CHANNELMASK_BACK_LEFT 0x00000040 +#define FMOD_CHANNELMASK_BACK_RIGHT 0x00000080 +#define FMOD_CHANNELMASK_BACK_CENTER 0x00000100 + +#define FMOD_CHANNELMASK_MONO (FMOD_CHANNELMASK_FRONT_LEFT) +#define FMOD_CHANNELMASK_STEREO (FMOD_CHANNELMASK_FRONT_LEFT | FMOD_CHANNELMASK_FRONT_RIGHT) +#define FMOD_CHANNELMASK_LRC (FMOD_CHANNELMASK_FRONT_LEFT | FMOD_CHANNELMASK_FRONT_RIGHT | FMOD_CHANNELMASK_FRONT_CENTER) +#define FMOD_CHANNELMASK_QUAD (FMOD_CHANNELMASK_FRONT_LEFT | FMOD_CHANNELMASK_FRONT_RIGHT | FMOD_CHANNELMASK_SURROUND_LEFT | FMOD_CHANNELMASK_SURROUND_RIGHT) +#define FMOD_CHANNELMASK_SURROUND (FMOD_CHANNELMASK_FRONT_LEFT | FMOD_CHANNELMASK_FRONT_RIGHT | FMOD_CHANNELMASK_FRONT_CENTER | FMOD_CHANNELMASK_SURROUND_LEFT | FMOD_CHANNELMASK_SURROUND_RIGHT) +#define FMOD_CHANNELMASK_5POINT1 (FMOD_CHANNELMASK_FRONT_LEFT | FMOD_CHANNELMASK_FRONT_RIGHT | FMOD_CHANNELMASK_FRONT_CENTER | FMOD_CHANNELMASK_LOW_FREQUENCY | FMOD_CHANNELMASK_SURROUND_LEFT | FMOD_CHANNELMASK_SURROUND_RIGHT) +#define FMOD_CHANNELMASK_5POINT1_REARS (FMOD_CHANNELMASK_FRONT_LEFT | FMOD_CHANNELMASK_FRONT_RIGHT | FMOD_CHANNELMASK_FRONT_CENTER | FMOD_CHANNELMASK_LOW_FREQUENCY | FMOD_CHANNELMASK_BACK_LEFT | FMOD_CHANNELMASK_BACK_RIGHT) +#define FMOD_CHANNELMASK_7POINT0 (FMOD_CHANNELMASK_FRONT_LEFT | FMOD_CHANNELMASK_FRONT_RIGHT | FMOD_CHANNELMASK_FRONT_CENTER | FMOD_CHANNELMASK_SURROUND_LEFT | FMOD_CHANNELMASK_SURROUND_RIGHT | FMOD_CHANNELMASK_BACK_LEFT | FMOD_CHANNELMASK_BACK_RIGHT) +#define FMOD_CHANNELMASK_7POINT1 (FMOD_CHANNELMASK_FRONT_LEFT | FMOD_CHANNELMASK_FRONT_RIGHT | FMOD_CHANNELMASK_FRONT_CENTER | FMOD_CHANNELMASK_LOW_FREQUENCY | FMOD_CHANNELMASK_SURROUND_LEFT | FMOD_CHANNELMASK_SURROUND_RIGHT | FMOD_CHANNELMASK_BACK_LEFT | FMOD_CHANNELMASK_BACK_RIGHT) + +/* Preset for FMOD_REVERB_PROPERTIES */ +#define FMOD_PRESET_OFF { 1000, 7, 11, 5000, 100, 100, 100, 250, 0, 20, 96, -80.0f } +#define FMOD_PRESET_GENERIC { 1500, 7, 11, 5000, 83, 100, 100, 250, 0, 14500, 96, -8.0f } +#define FMOD_PRESET_PADDEDCELL { 170, 1, 2, 5000, 10, 100, 100, 250, 0, 160, 84, -7.8f } +#define FMOD_PRESET_ROOM { 400, 2, 3, 5000, 83, 100, 100, 250, 0, 6050, 88, -9.4f } +#define FMOD_PRESET_BATHROOM { 1500, 7, 11, 5000, 54, 100, 60, 250, 0, 2900, 83, 0.5f } +#define FMOD_PRESET_LIVINGROOM { 500, 3, 4, 5000, 10, 100, 100, 250, 0, 160, 58, -19.0f } +#define FMOD_PRESET_STONEROOM { 2300, 12, 17, 5000, 64, 100, 100, 250, 0, 7800, 71, -8.5f } +#define FMOD_PRESET_AUDITORIUM { 4300, 20, 30, 5000, 59, 100, 100, 250, 0, 5850, 64, -11.7f } +#define FMOD_PRESET_CONCERTHALL { 3900, 20, 29, 5000, 70, 100, 100, 250, 0, 5650, 80, -9.8f } +#define FMOD_PRESET_CAVE { 2900, 15, 22, 5000, 100, 100, 100, 250, 0, 20000, 59, -11.3f } +#define FMOD_PRESET_ARENA { 7200, 20, 30, 5000, 33, 100, 100, 250, 0, 4500, 80, -9.6f } +#define FMOD_PRESET_HANGAR { 10000, 20, 30, 5000, 23, 100, 100, 250, 0, 3400, 72, -7.4f } +#define FMOD_PRESET_CARPETTEDHALLWAY { 300, 2, 30, 5000, 10, 100, 100, 250, 0, 500, 56, -24.0f } +#define FMOD_PRESET_HALLWAY { 1500, 7, 11, 5000, 59, 100, 100, 250, 0, 7800, 87, -5.5f } +#define FMOD_PRESET_STONECORRIDOR { 270, 13, 20, 5000, 79, 100, 100, 250, 0, 9000, 86, -6.0f } +#define FMOD_PRESET_ALLEY { 1500, 7, 11, 5000, 86, 100, 100, 250, 0, 8300, 80, -9.8f } +#define FMOD_PRESET_FOREST { 1500, 162, 88, 5000, 54, 79, 100, 250, 0, 760, 94, -12.3f } +#define FMOD_PRESET_CITY { 1500, 7, 11, 5000, 67, 50, 100, 250, 0, 4050, 66, -26.0f } +#define FMOD_PRESET_MOUNTAINS { 1500, 300, 100, 5000, 21, 27, 100, 250, 0, 1220, 82, -24.0f } +#define FMOD_PRESET_QUARRY { 1500, 61, 25, 5000, 83, 100, 100, 250, 0, 3400, 100, -5.0f } +#define FMOD_PRESET_PLAIN { 1500, 179, 100, 5000, 50, 21, 100, 250, 0, 1670, 65, -28.0f } +#define FMOD_PRESET_PARKINGLOT { 1700, 8, 12, 5000, 100, 100, 100, 250, 0, 20000, 56, -19.5f } +#define FMOD_PRESET_SEWERPIPE { 2800, 14, 21, 5000, 14, 80, 60, 250, 0, 3400, 66, 1.2f } +#define FMOD_PRESET_UNDERWATER { 1500, 7, 11, 5000, 10, 100, 100, 250, 0, 500, 92, 7.0f } + +#define FMOD_MAX_CHANNEL_WIDTH 32 +#define FMOD_MAX_SYSTEMS 8 +#define FMOD_MAX_LISTENERS 8 +#define FMOD_REVERB_MAXINSTANCES 4 +#define FMOD_PORT_INDEX_NONE 0xFFFFFFFFFFFFFFFF + +typedef enum FMOD_RESULT +{ + FMOD_OK, + FMOD_ERR_BADCOMMAND, + FMOD_ERR_CHANNEL_ALLOC, + FMOD_ERR_CHANNEL_STOLEN, + FMOD_ERR_DMA, + FMOD_ERR_DSP_CONNECTION, + FMOD_ERR_DSP_DONTPROCESS, + FMOD_ERR_DSP_FORMAT, + FMOD_ERR_DSP_INUSE, + FMOD_ERR_DSP_NOTFOUND, + FMOD_ERR_DSP_RESERVED, + FMOD_ERR_DSP_SILENCE, + FMOD_ERR_DSP_TYPE, + FMOD_ERR_FILE_BAD, + FMOD_ERR_FILE_COULDNOTSEEK, + FMOD_ERR_FILE_DISKEJECTED, + FMOD_ERR_FILE_EOF, + FMOD_ERR_FILE_ENDOFDATA, + FMOD_ERR_FILE_NOTFOUND, + FMOD_ERR_FORMAT, + FMOD_ERR_HEADER_MISMATCH, + FMOD_ERR_HTTP, + FMOD_ERR_HTTP_ACCESS, + FMOD_ERR_HTTP_PROXY_AUTH, + FMOD_ERR_HTTP_SERVER_ERROR, + FMOD_ERR_HTTP_TIMEOUT, + FMOD_ERR_INITIALIZATION, + FMOD_ERR_INITIALIZED, + FMOD_ERR_INTERNAL, + FMOD_ERR_INVALID_FLOAT, + FMOD_ERR_INVALID_HANDLE, + FMOD_ERR_INVALID_PARAM, + FMOD_ERR_INVALID_POSITION, + FMOD_ERR_INVALID_SPEAKER, + FMOD_ERR_INVALID_SYNCPOINT, + FMOD_ERR_INVALID_THREAD, + FMOD_ERR_INVALID_VECTOR, + FMOD_ERR_MAXAUDIBLE, + FMOD_ERR_MEMORY, + FMOD_ERR_MEMORY_CANTPOINT, + FMOD_ERR_NEEDS3D, + FMOD_ERR_NEEDSHARDWARE, + FMOD_ERR_NET_CONNECT, + FMOD_ERR_NET_SOCKET_ERROR, + FMOD_ERR_NET_URL, + FMOD_ERR_NET_WOULD_BLOCK, + FMOD_ERR_NOTREADY, + FMOD_ERR_OUTPUT_ALLOCATED, + FMOD_ERR_OUTPUT_CREATEBUFFER, + FMOD_ERR_OUTPUT_DRIVERCALL, + FMOD_ERR_OUTPUT_FORMAT, + FMOD_ERR_OUTPUT_INIT, + FMOD_ERR_OUTPUT_NODRIVERS, + FMOD_ERR_PLUGIN, + FMOD_ERR_PLUGIN_MISSING, + FMOD_ERR_PLUGIN_RESOURCE, + FMOD_ERR_PLUGIN_VERSION, + FMOD_ERR_RECORD, + FMOD_ERR_REVERB_CHANNELGROUP, + FMOD_ERR_REVERB_INSTANCE, + FMOD_ERR_SUBSOUNDS, + FMOD_ERR_SUBSOUND_ALLOCATED, + FMOD_ERR_SUBSOUND_CANTMOVE, + FMOD_ERR_TAGNOTFOUND, + FMOD_ERR_TOOMANYCHANNELS, + FMOD_ERR_TRUNCATED, + FMOD_ERR_UNIMPLEMENTED, + FMOD_ERR_UNINITIALIZED, + FMOD_ERR_UNSUPPORTED, + FMOD_ERR_VERSION, + FMOD_ERR_EVENT_ALREADY_LOADED, + FMOD_ERR_EVENT_LIVEUPDATE_BUSY, + FMOD_ERR_EVENT_LIVEUPDATE_MISMATCH, + FMOD_ERR_EVENT_LIVEUPDATE_TIMEOUT, + FMOD_ERR_EVENT_NOTFOUND, + FMOD_ERR_STUDIO_UNINITIALIZED, + FMOD_ERR_STUDIO_NOT_LOADED, + FMOD_ERR_INVALID_STRING, + FMOD_ERR_ALREADY_LOCKED, + FMOD_ERR_NOT_LOCKED, + FMOD_ERR_RECORD_DISCONNECTED, + FMOD_ERR_TOOMANYSAMPLES, + + FMOD_RESULT_FORCEINT = 65536 +} FMOD_RESULT; + +typedef enum FMOD_CHANNELCONTROL_TYPE +{ + FMOD_CHANNELCONTROL_CHANNEL, + FMOD_CHANNELCONTROL_CHANNELGROUP, + + FMOD_CHANNELCONTROL_MAX, + FMOD_CHANNELCONTROL_FORCEINT = 65536 +} FMOD_CHANNELCONTROL_TYPE; + +typedef enum FMOD_OUTPUTTYPE +{ + FMOD_OUTPUTTYPE_AUTODETECT, + FMOD_OUTPUTTYPE_UNKNOWN, + FMOD_OUTPUTTYPE_NOSOUND, + FMOD_OUTPUTTYPE_WAVWRITER, + FMOD_OUTPUTTYPE_NOSOUND_NRT, + FMOD_OUTPUTTYPE_WAVWRITER_NRT, + FMOD_OUTPUTTYPE_WASAPI, + FMOD_OUTPUTTYPE_ASIO, + FMOD_OUTPUTTYPE_PULSEAUDIO, + FMOD_OUTPUTTYPE_ALSA, + FMOD_OUTPUTTYPE_COREAUDIO, + FMOD_OUTPUTTYPE_AUDIOTRACK, + FMOD_OUTPUTTYPE_OPENSL, + FMOD_OUTPUTTYPE_AUDIOOUT, + FMOD_OUTPUTTYPE_AUDIO3D, + FMOD_OUTPUTTYPE_WEBAUDIO, + FMOD_OUTPUTTYPE_NNAUDIO, + FMOD_OUTPUTTYPE_WINSONIC, + FMOD_OUTPUTTYPE_AAUDIO, + + FMOD_OUTPUTTYPE_MAX, + FMOD_OUTPUTTYPE_FORCEINT = 65536 +} FMOD_OUTPUTTYPE; + +typedef enum FMOD_DEBUG_MODE +{ + FMOD_DEBUG_MODE_TTY, + FMOD_DEBUG_MODE_FILE, + FMOD_DEBUG_MODE_CALLBACK, + + FMOD_DEBUG_MODE_FORCEINT = 65536 +} FMOD_DEBUG_MODE; + +typedef enum FMOD_SPEAKERMODE +{ + FMOD_SPEAKERMODE_DEFAULT, + FMOD_SPEAKERMODE_RAW, + FMOD_SPEAKERMODE_MONO, + FMOD_SPEAKERMODE_STEREO, + FMOD_SPEAKERMODE_QUAD, + FMOD_SPEAKERMODE_SURROUND, + FMOD_SPEAKERMODE_5POINT1, + FMOD_SPEAKERMODE_7POINT1, + FMOD_SPEAKERMODE_7POINT1POINT4, + + FMOD_SPEAKERMODE_MAX, + FMOD_SPEAKERMODE_FORCEINT = 65536 +} FMOD_SPEAKERMODE; + +typedef enum FMOD_SPEAKER +{ + FMOD_SPEAKER_NONE = -1, + FMOD_SPEAKER_FRONT_LEFT = 0, + FMOD_SPEAKER_FRONT_RIGHT, + FMOD_SPEAKER_FRONT_CENTER, + FMOD_SPEAKER_LOW_FREQUENCY, + FMOD_SPEAKER_SURROUND_LEFT, + FMOD_SPEAKER_SURROUND_RIGHT, + FMOD_SPEAKER_BACK_LEFT, + FMOD_SPEAKER_BACK_RIGHT, + FMOD_SPEAKER_TOP_FRONT_LEFT, + FMOD_SPEAKER_TOP_FRONT_RIGHT, + FMOD_SPEAKER_TOP_BACK_LEFT, + FMOD_SPEAKER_TOP_BACK_RIGHT, + + FMOD_SPEAKER_MAX, + FMOD_SPEAKER_FORCEINT = 65536 +} FMOD_SPEAKER; + +typedef enum FMOD_CHANNELORDER +{ + FMOD_CHANNELORDER_DEFAULT, + FMOD_CHANNELORDER_WAVEFORMAT, + FMOD_CHANNELORDER_PROTOOLS, + FMOD_CHANNELORDER_ALLMONO, + FMOD_CHANNELORDER_ALLSTEREO, + FMOD_CHANNELORDER_ALSA, + + FMOD_CHANNELORDER_MAX, + FMOD_CHANNELORDER_FORCEINT = 65536 +} FMOD_CHANNELORDER; + +typedef enum FMOD_PLUGINTYPE +{ + FMOD_PLUGINTYPE_OUTPUT, + FMOD_PLUGINTYPE_CODEC, + FMOD_PLUGINTYPE_DSP, + + FMOD_PLUGINTYPE_MAX, + FMOD_PLUGINTYPE_FORCEINT = 65536 +} FMOD_PLUGINTYPE; + +typedef enum FMOD_SOUND_TYPE +{ + FMOD_SOUND_TYPE_UNKNOWN, + FMOD_SOUND_TYPE_AIFF, + FMOD_SOUND_TYPE_ASF, + FMOD_SOUND_TYPE_DLS, + FMOD_SOUND_TYPE_FLAC, + FMOD_SOUND_TYPE_FSB, + FMOD_SOUND_TYPE_IT, + FMOD_SOUND_TYPE_MIDI, + FMOD_SOUND_TYPE_MOD, + FMOD_SOUND_TYPE_MPEG, + FMOD_SOUND_TYPE_OGGVORBIS, + FMOD_SOUND_TYPE_PLAYLIST, + FMOD_SOUND_TYPE_RAW, + FMOD_SOUND_TYPE_S3M, + FMOD_SOUND_TYPE_USER, + FMOD_SOUND_TYPE_WAV, + FMOD_SOUND_TYPE_XM, + FMOD_SOUND_TYPE_XMA, + FMOD_SOUND_TYPE_AUDIOQUEUE, + FMOD_SOUND_TYPE_AT9, + FMOD_SOUND_TYPE_VORBIS, + FMOD_SOUND_TYPE_MEDIA_FOUNDATION, + FMOD_SOUND_TYPE_MEDIACODEC, + FMOD_SOUND_TYPE_FADPCM, + FMOD_SOUND_TYPE_OPUS, + + FMOD_SOUND_TYPE_MAX, + FMOD_SOUND_TYPE_FORCEINT = 65536 +} FMOD_SOUND_TYPE; + +typedef enum FMOD_SOUND_FORMAT +{ + FMOD_SOUND_FORMAT_NONE, + FMOD_SOUND_FORMAT_PCM8, + FMOD_SOUND_FORMAT_PCM16, + FMOD_SOUND_FORMAT_PCM24, + FMOD_SOUND_FORMAT_PCM32, + FMOD_SOUND_FORMAT_PCMFLOAT, + FMOD_SOUND_FORMAT_BITSTREAM, + + FMOD_SOUND_FORMAT_MAX, + FMOD_SOUND_FORMAT_FORCEINT = 65536 +} FMOD_SOUND_FORMAT; + +typedef enum FMOD_OPENSTATE +{ + FMOD_OPENSTATE_READY, + FMOD_OPENSTATE_LOADING, + FMOD_OPENSTATE_ERROR, + FMOD_OPENSTATE_CONNECTING, + FMOD_OPENSTATE_BUFFERING, + FMOD_OPENSTATE_SEEKING, + FMOD_OPENSTATE_PLAYING, + FMOD_OPENSTATE_SETPOSITION, + + FMOD_OPENSTATE_MAX, + FMOD_OPENSTATE_FORCEINT = 65536 +} FMOD_OPENSTATE; + +typedef enum FMOD_SOUNDGROUP_BEHAVIOR +{ + FMOD_SOUNDGROUP_BEHAVIOR_FAIL, + FMOD_SOUNDGROUP_BEHAVIOR_MUTE, + FMOD_SOUNDGROUP_BEHAVIOR_STEALLOWEST, + + FMOD_SOUNDGROUP_BEHAVIOR_MAX, + FMOD_SOUNDGROUP_BEHAVIOR_FORCEINT = 65536 +} FMOD_SOUNDGROUP_BEHAVIOR; + +typedef enum FMOD_CHANNELCONTROL_CALLBACK_TYPE +{ + FMOD_CHANNELCONTROL_CALLBACK_END, + FMOD_CHANNELCONTROL_CALLBACK_VIRTUALVOICE, + FMOD_CHANNELCONTROL_CALLBACK_SYNCPOINT, + FMOD_CHANNELCONTROL_CALLBACK_OCCLUSION, + + FMOD_CHANNELCONTROL_CALLBACK_MAX, + FMOD_CHANNELCONTROL_CALLBACK_FORCEINT = 65536 +} FMOD_CHANNELCONTROL_CALLBACK_TYPE; + +typedef enum FMOD_CHANNELCONTROL_DSP_INDEX +{ + FMOD_CHANNELCONTROL_DSP_HEAD = -1, + FMOD_CHANNELCONTROL_DSP_FADER = -2, + FMOD_CHANNELCONTROL_DSP_TAIL = -3, + + FMOD_CHANNELCONTROL_DSP_FORCEINT = 65536 +} FMOD_CHANNELCONTROL_DSP_INDEX; + +typedef enum FMOD_ERRORCALLBACK_INSTANCETYPE +{ + FMOD_ERRORCALLBACK_INSTANCETYPE_NONE, + FMOD_ERRORCALLBACK_INSTANCETYPE_SYSTEM, + FMOD_ERRORCALLBACK_INSTANCETYPE_CHANNEL, + FMOD_ERRORCALLBACK_INSTANCETYPE_CHANNELGROUP, + FMOD_ERRORCALLBACK_INSTANCETYPE_CHANNELCONTROL, + FMOD_ERRORCALLBACK_INSTANCETYPE_SOUND, + FMOD_ERRORCALLBACK_INSTANCETYPE_SOUNDGROUP, + FMOD_ERRORCALLBACK_INSTANCETYPE_DSP, + FMOD_ERRORCALLBACK_INSTANCETYPE_DSPCONNECTION, + FMOD_ERRORCALLBACK_INSTANCETYPE_GEOMETRY, + FMOD_ERRORCALLBACK_INSTANCETYPE_REVERB3D, + FMOD_ERRORCALLBACK_INSTANCETYPE_STUDIO_SYSTEM, + FMOD_ERRORCALLBACK_INSTANCETYPE_STUDIO_EVENTDESCRIPTION, + FMOD_ERRORCALLBACK_INSTANCETYPE_STUDIO_EVENTINSTANCE, + FMOD_ERRORCALLBACK_INSTANCETYPE_STUDIO_PARAMETERINSTANCE, + FMOD_ERRORCALLBACK_INSTANCETYPE_STUDIO_BUS, + FMOD_ERRORCALLBACK_INSTANCETYPE_STUDIO_VCA, + FMOD_ERRORCALLBACK_INSTANCETYPE_STUDIO_BANK, + FMOD_ERRORCALLBACK_INSTANCETYPE_STUDIO_COMMANDREPLAY, + + FMOD_ERRORCALLBACK_INSTANCETYPE_FORCEINT = 65536 +} FMOD_ERRORCALLBACK_INSTANCETYPE; + +typedef enum FMOD_DSP_RESAMPLER +{ + FMOD_DSP_RESAMPLER_DEFAULT, + FMOD_DSP_RESAMPLER_NOINTERP, + FMOD_DSP_RESAMPLER_LINEAR, + FMOD_DSP_RESAMPLER_CUBIC, + FMOD_DSP_RESAMPLER_SPLINE, + + FMOD_DSP_RESAMPLER_MAX, + FMOD_DSP_RESAMPLER_FORCEINT = 65536 +} FMOD_DSP_RESAMPLER; + +typedef enum FMOD_DSPCONNECTION_TYPE +{ + FMOD_DSPCONNECTION_TYPE_STANDARD, + FMOD_DSPCONNECTION_TYPE_SIDECHAIN, + FMOD_DSPCONNECTION_TYPE_SEND, + FMOD_DSPCONNECTION_TYPE_SEND_SIDECHAIN, + + FMOD_DSPCONNECTION_TYPE_MAX, + FMOD_DSPCONNECTION_TYPE_FORCEINT = 65536 +} FMOD_DSPCONNECTION_TYPE; + +typedef enum FMOD_TAGTYPE +{ + FMOD_TAGTYPE_UNKNOWN, + FMOD_TAGTYPE_ID3V1, + FMOD_TAGTYPE_ID3V2, + FMOD_TAGTYPE_VORBISCOMMENT, + FMOD_TAGTYPE_SHOUTCAST, + FMOD_TAGTYPE_ICECAST, + FMOD_TAGTYPE_ASF, + FMOD_TAGTYPE_MIDI, + FMOD_TAGTYPE_PLAYLIST, + FMOD_TAGTYPE_FMOD, + FMOD_TAGTYPE_USER, + + FMOD_TAGTYPE_MAX, + FMOD_TAGTYPE_FORCEINT = 65536 +} FMOD_TAGTYPE; + +typedef enum FMOD_TAGDATATYPE +{ + FMOD_TAGDATATYPE_BINARY, + FMOD_TAGDATATYPE_INT, + FMOD_TAGDATATYPE_FLOAT, + FMOD_TAGDATATYPE_STRING, + FMOD_TAGDATATYPE_STRING_UTF16, + FMOD_TAGDATATYPE_STRING_UTF16BE, + FMOD_TAGDATATYPE_STRING_UTF8, + + FMOD_TAGDATATYPE_MAX, + FMOD_TAGDATATYPE_FORCEINT = 65536 +} FMOD_TAGDATATYPE; + +/* + FMOD callbacks +*/ +typedef FMOD_RESULT (F_CALL *FMOD_DEBUG_CALLBACK) (FMOD_DEBUG_FLAGS flags, const char *file, int line, const char* func, const char* message); +typedef FMOD_RESULT (F_CALL *FMOD_SYSTEM_CALLBACK) (FMOD_SYSTEM *system, FMOD_SYSTEM_CALLBACK_TYPE type, void *commanddata1, void* commanddata2, void *userdata); +typedef FMOD_RESULT (F_CALL *FMOD_CHANNELCONTROL_CALLBACK) (FMOD_CHANNELCONTROL *channelcontrol, FMOD_CHANNELCONTROL_TYPE controltype, FMOD_CHANNELCONTROL_CALLBACK_TYPE callbacktype, void *commanddata1, void *commanddata2); +typedef FMOD_RESULT (F_CALL *FMOD_SOUND_NONBLOCK_CALLBACK) (FMOD_SOUND *sound, FMOD_RESULT result); +typedef FMOD_RESULT (F_CALL *FMOD_SOUND_PCMREAD_CALLBACK) (FMOD_SOUND *sound, void *data, unsigned int datalen); +typedef FMOD_RESULT (F_CALL *FMOD_SOUND_PCMSETPOS_CALLBACK) (FMOD_SOUND *sound, int subsound, unsigned int position, FMOD_TIMEUNIT postype); +typedef FMOD_RESULT (F_CALL *FMOD_FILE_OPEN_CALLBACK) (const char *name, unsigned int *filesize, void **handle, void *userdata); +typedef FMOD_RESULT (F_CALL *FMOD_FILE_CLOSE_CALLBACK) (void *handle, void *userdata); +typedef FMOD_RESULT (F_CALL *FMOD_FILE_READ_CALLBACK) (void *handle, void *buffer, unsigned int sizebytes, unsigned int *bytesread, void *userdata); +typedef FMOD_RESULT (F_CALL *FMOD_FILE_SEEK_CALLBACK) (void *handle, unsigned int pos, void *userdata); +typedef FMOD_RESULT (F_CALL *FMOD_FILE_ASYNCREAD_CALLBACK) (FMOD_ASYNCREADINFO *info, void *userdata); +typedef FMOD_RESULT (F_CALL *FMOD_FILE_ASYNCCANCEL_CALLBACK)(FMOD_ASYNCREADINFO *info, void *userdata); +typedef void (F_CALL *FMOD_FILE_ASYNCDONE_FUNC) (FMOD_ASYNCREADINFO *info, FMOD_RESULT result); +typedef void* (F_CALL *FMOD_MEMORY_ALLOC_CALLBACK) (unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr); +typedef void* (F_CALL *FMOD_MEMORY_REALLOC_CALLBACK) (void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr); +typedef void (F_CALL *FMOD_MEMORY_FREE_CALLBACK) (void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr); +typedef float (F_CALL *FMOD_3D_ROLLOFF_CALLBACK) (FMOD_CHANNELCONTROL *channelcontrol, float distance); + +/* + FMOD structs +*/ +struct FMOD_ASYNCREADINFO +{ + void *handle; + unsigned int offset; + unsigned int sizebytes; + int priority; + void *userdata; + void *buffer; + unsigned int bytesread; + FMOD_FILE_ASYNCDONE_FUNC done; +}; + +typedef struct FMOD_VECTOR +{ + float x; + float y; + float z; +} FMOD_VECTOR; + +typedef struct FMOD_3D_ATTRIBUTES +{ + FMOD_VECTOR position; + FMOD_VECTOR velocity; + FMOD_VECTOR forward; + FMOD_VECTOR up; +} FMOD_3D_ATTRIBUTES; + +typedef struct FMOD_GUID +{ + unsigned int Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} FMOD_GUID; + +typedef struct FMOD_PLUGINLIST +{ + FMOD_PLUGINTYPE type; + void *description; +} FMOD_PLUGINLIST; + +typedef struct FMOD_ADVANCEDSETTINGS +{ + int cbSize; + int maxMPEGCodecs; + int maxADPCMCodecs; + int maxXMACodecs; + int maxVorbisCodecs; + int maxAT9Codecs; + int maxFADPCMCodecs; + int maxPCMCodecs; + int ASIONumChannels; + char **ASIOChannelList; + FMOD_SPEAKER *ASIOSpeakerList; + float vol0virtualvol; + unsigned int defaultDecodeBufferSize; + unsigned short profilePort; + unsigned int geometryMaxFadeTime; + float distanceFilterCenterFreq; + int reverb3Dinstance; + int DSPBufferPoolSize; + unsigned int stackSizeStream; + unsigned int stackSizeNonBlocking; + unsigned int stackSizeMixer; + FMOD_DSP_RESAMPLER resamplerMethod; + unsigned int commandQueueSize; + unsigned int randomSeed; +} FMOD_ADVANCEDSETTINGS; + +typedef struct FMOD_TAG +{ + FMOD_TAGTYPE type; + FMOD_TAGDATATYPE datatype; + char *name; + void *data; + unsigned int datalen; + FMOD_BOOL updated; +} FMOD_TAG; + +typedef struct FMOD_CREATESOUNDEXINFO +{ + int cbsize; + unsigned int length; + unsigned int fileoffset; + int numchannels; + int defaultfrequency; + FMOD_SOUND_FORMAT format; + unsigned int decodebuffersize; + int initialsubsound; + int numsubsounds; + int *inclusionlist; + int inclusionlistnum; + FMOD_SOUND_PCMREAD_CALLBACK pcmreadcallback; + FMOD_SOUND_PCMSETPOS_CALLBACK pcmsetposcallback; + FMOD_SOUND_NONBLOCK_CALLBACK nonblockcallback; + const char *dlsname; + const char *encryptionkey; + int maxpolyphony; + void *userdata; + FMOD_SOUND_TYPE suggestedsoundtype; + FMOD_FILE_OPEN_CALLBACK fileuseropen; + FMOD_FILE_CLOSE_CALLBACK fileuserclose; + FMOD_FILE_READ_CALLBACK fileuserread; + FMOD_FILE_SEEK_CALLBACK fileuserseek; + FMOD_FILE_ASYNCREAD_CALLBACK fileuserasyncread; + FMOD_FILE_ASYNCCANCEL_CALLBACK fileuserasynccancel; + void *fileuserdata; + int filebuffersize; + FMOD_CHANNELORDER channelorder; + FMOD_SOUNDGROUP *initialsoundgroup; + unsigned int initialseekposition; + FMOD_TIMEUNIT initialseekpostype; + int ignoresetfilesystem; + unsigned int audioqueuepolicy; + unsigned int minmidigranularity; + int nonblockthreadid; + FMOD_GUID *fsbguid; +} FMOD_CREATESOUNDEXINFO; + +typedef struct FMOD_REVERB_PROPERTIES +{ + float DecayTime; + float EarlyDelay; + float LateDelay; + float HFReference; + float HFDecayRatio; + float Diffusion; + float Density; + float LowShelfFrequency; + float LowShelfGain; + float HighCut; + float EarlyLateMix; + float WetLevel; +} FMOD_REVERB_PROPERTIES; + +typedef struct FMOD_ERRORCALLBACK_INFO +{ + FMOD_RESULT result; + FMOD_ERRORCALLBACK_INSTANCETYPE instancetype; + void *instance; + const char *functionname; + const char *functionparams; +} FMOD_ERRORCALLBACK_INFO; + +/* + FMOD optional headers for plugin development +*/ +#include "fmod_codec.h" +#include "fmod_dsp.h" +#include "fmod_output.h" + +#endif diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_dsp.h b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_dsp.h new file mode 100644 index 0000000..549e5b9 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_dsp.h @@ -0,0 +1,414 @@ +/* ======================================================================================== */ +/* FMOD Core API - DSP header file. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* */ +/* Use this header if you are wanting to develop your own DSP plugin to use with FMODs */ +/* dsp system. With this header you can make your own DSP plugin that FMOD can */ +/* register and use. See the documentation and examples on how to make a working plugin. */ +/* */ +/* For more detail visit: */ +/* https://fmod.com/resources/documentation-api?version=2.0&page=plugin-api-dsp.html */ +/* =========================================================================================*/ +#ifndef _FMOD_DSP_H +#define _FMOD_DSP_H + +#include "fmod_dsp_effects.h" + +typedef struct FMOD_DSP_STATE FMOD_DSP_STATE; +typedef struct FMOD_DSP_BUFFER_ARRAY FMOD_DSP_BUFFER_ARRAY; +typedef struct FMOD_COMPLEX FMOD_COMPLEX; + +/* + DSP Constants +*/ +#define FMOD_PLUGIN_SDK_VERSION 110 +#define FMOD_DSP_GETPARAM_VALUESTR_LENGTH 32 + +typedef enum +{ + FMOD_DSP_PROCESS_PERFORM, + FMOD_DSP_PROCESS_QUERY +} FMOD_DSP_PROCESS_OPERATION; + +typedef enum FMOD_DSP_PAN_SURROUND_FLAGS +{ + FMOD_DSP_PAN_SURROUND_DEFAULT = 0, + FMOD_DSP_PAN_SURROUND_ROTATION_NOT_BIASED = 1, + + FMOD_DSP_PAN_SURROUND_FLAGS_FORCEINT = 65536 +} FMOD_DSP_PAN_SURROUND_FLAGS; + +typedef enum +{ + FMOD_DSP_PARAMETER_TYPE_FLOAT, + FMOD_DSP_PARAMETER_TYPE_INT, + FMOD_DSP_PARAMETER_TYPE_BOOL, + FMOD_DSP_PARAMETER_TYPE_DATA, + + FMOD_DSP_PARAMETER_TYPE_MAX, + FMOD_DSP_PARAMETER_TYPE_FORCEINT = 65536 +} FMOD_DSP_PARAMETER_TYPE; + +typedef enum +{ + FMOD_DSP_PARAMETER_FLOAT_MAPPING_TYPE_LINEAR, + FMOD_DSP_PARAMETER_FLOAT_MAPPING_TYPE_AUTO, + FMOD_DSP_PARAMETER_FLOAT_MAPPING_TYPE_PIECEWISE_LINEAR, + + FMOD_DSP_PARAMETER_FLOAT_MAPPING_TYPE_FORCEINT = 65536 +} FMOD_DSP_PARAMETER_FLOAT_MAPPING_TYPE; + +typedef enum +{ + FMOD_DSP_PARAMETER_DATA_TYPE_USER = 0, + FMOD_DSP_PARAMETER_DATA_TYPE_OVERALLGAIN = -1, + FMOD_DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES = -2, + FMOD_DSP_PARAMETER_DATA_TYPE_SIDECHAIN = -3, + FMOD_DSP_PARAMETER_DATA_TYPE_FFT = -4, + FMOD_DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES_MULTI = -5, +} FMOD_DSP_PARAMETER_DATA_TYPE; + +/* + DSP Callbacks +*/ +typedef FMOD_RESULT (F_CALL *FMOD_DSP_CREATE_CALLBACK) (FMOD_DSP_STATE *dsp_state); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_RELEASE_CALLBACK) (FMOD_DSP_STATE *dsp_state); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_RESET_CALLBACK) (FMOD_DSP_STATE *dsp_state); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_READ_CALLBACK) (FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_PROCESS_CALLBACK) (FMOD_DSP_STATE *dsp_state, unsigned int length, const FMOD_DSP_BUFFER_ARRAY *inbufferarray, FMOD_DSP_BUFFER_ARRAY *outbufferarray, FMOD_BOOL inputsidle, FMOD_DSP_PROCESS_OPERATION op); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_SETPOSITION_CALLBACK) (FMOD_DSP_STATE *dsp_state, unsigned int pos); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_SHOULDIPROCESS_CALLBACK) (FMOD_DSP_STATE *dsp_state, FMOD_BOOL inputsidle, unsigned int length, FMOD_CHANNELMASK inmask, int inchannels, FMOD_SPEAKERMODE speakermode); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_SETPARAM_FLOAT_CALLBACK) (FMOD_DSP_STATE *dsp_state, int index, float value); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_SETPARAM_INT_CALLBACK) (FMOD_DSP_STATE *dsp_state, int index, int value); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_SETPARAM_BOOL_CALLBACK) (FMOD_DSP_STATE *dsp_state, int index, FMOD_BOOL value); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_SETPARAM_DATA_CALLBACK) (FMOD_DSP_STATE *dsp_state, int index, void *data, unsigned int length); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETPARAM_FLOAT_CALLBACK) (FMOD_DSP_STATE *dsp_state, int index, float *value, char *valuestr); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETPARAM_INT_CALLBACK) (FMOD_DSP_STATE *dsp_state, int index, int *value, char *valuestr); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETPARAM_BOOL_CALLBACK) (FMOD_DSP_STATE *dsp_state, int index, FMOD_BOOL *value, char *valuestr); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETPARAM_DATA_CALLBACK) (FMOD_DSP_STATE *dsp_state, int index, void **data, unsigned int *length, char *valuestr); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_SYSTEM_REGISTER_CALLBACK) (FMOD_DSP_STATE *dsp_state); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_SYSTEM_DEREGISTER_CALLBACK) (FMOD_DSP_STATE *dsp_state); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_SYSTEM_MIX_CALLBACK) (FMOD_DSP_STATE *dsp_state, int stage); + +/* + DSP Functions +*/ +typedef void * (F_CALL *FMOD_DSP_ALLOC_FUNC) (unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr); +typedef void * (F_CALL *FMOD_DSP_REALLOC_FUNC) (void *ptr, unsigned int size, FMOD_MEMORY_TYPE type, const char *sourcestr); +typedef void (F_CALL *FMOD_DSP_FREE_FUNC) (void *ptr, FMOD_MEMORY_TYPE type, const char *sourcestr); +typedef void (F_CALL *FMOD_DSP_LOG_FUNC) (FMOD_DEBUG_FLAGS level, const char *file, int line, const char *function, const char *string, ...); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETSAMPLERATE_FUNC) (FMOD_DSP_STATE *dsp_state, int *rate); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETBLOCKSIZE_FUNC) (FMOD_DSP_STATE *dsp_state, unsigned int *blocksize); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETSPEAKERMODE_FUNC) (FMOD_DSP_STATE *dsp_state, FMOD_SPEAKERMODE *speakermode_mixer, FMOD_SPEAKERMODE *speakermode_output); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETCLOCK_FUNC) (FMOD_DSP_STATE *dsp_state, unsigned long long *clock, unsigned int *offset, unsigned int *length); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETLISTENERATTRIBUTES_FUNC) (FMOD_DSP_STATE *dsp_state, int *numlisteners, FMOD_3D_ATTRIBUTES *attributes); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_GETUSERDATA_FUNC) (FMOD_DSP_STATE *dsp_state, void **userdata); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_DFT_FFTREAL_FUNC) (FMOD_DSP_STATE *dsp_state, int size, const float *signal, FMOD_COMPLEX* dft, const float *window, int signalhop); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_DFT_IFFTREAL_FUNC) (FMOD_DSP_STATE *dsp_state, int size, const FMOD_COMPLEX *dft, float* signal, const float *window, int signalhop); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_PAN_SUMMONOMATRIX_FUNC) (FMOD_DSP_STATE *dsp_state, FMOD_SPEAKERMODE sourceSpeakerMode, float lowFrequencyGain, float overallGain, float *matrix); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_PAN_SUMSTEREOMATRIX_FUNC) (FMOD_DSP_STATE *dsp_state, FMOD_SPEAKERMODE sourceSpeakerMode, float pan, float lowFrequencyGain, float overallGain, int matrixHop, float *matrix); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_PAN_SUMSURROUNDMATRIX_FUNC) (FMOD_DSP_STATE *dsp_state, FMOD_SPEAKERMODE sourceSpeakerMode, FMOD_SPEAKERMODE targetSpeakerMode, float direction, float extent, float rotation, float lowFrequencyGain, float overallGain, int matrixHop, float *matrix, FMOD_DSP_PAN_SURROUND_FLAGS flags); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_PAN_SUMMONOTOSURROUNDMATRIX_FUNC) (FMOD_DSP_STATE *dsp_state, FMOD_SPEAKERMODE targetSpeakerMode, float direction, float extent, float lowFrequencyGain, float overallGain, int matrixHop, float *matrix); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_PAN_SUMSTEREOTOSURROUNDMATRIX_FUNC) (FMOD_DSP_STATE *dsp_state, FMOD_SPEAKERMODE targetSpeakerMode, float direction, float extent, float rotation, float lowFrequencyGain, float overallGain, int matrixHop, float *matrix); +typedef FMOD_RESULT (F_CALL *FMOD_DSP_PAN_GETROLLOFFGAIN_FUNC) (FMOD_DSP_STATE *dsp_state, FMOD_DSP_PAN_3D_ROLLOFF_TYPE rolloff, float distance, float mindistance, float maxdistance, float *gain); + +/* + DSP Structures +*/ +struct FMOD_DSP_BUFFER_ARRAY +{ + int numbuffers; + int *buffernumchannels; + FMOD_CHANNELMASK *bufferchannelmask; + float **buffers; + FMOD_SPEAKERMODE speakermode; +}; + +struct FMOD_COMPLEX +{ + float real; + float imag; +}; + +typedef struct FMOD_DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR +{ + int numpoints; + float *pointparamvalues; + float *pointpositions; +} FMOD_DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR; + +typedef struct FMOD_DSP_PARAMETER_FLOAT_MAPPING +{ + FMOD_DSP_PARAMETER_FLOAT_MAPPING_TYPE type; + FMOD_DSP_PARAMETER_FLOAT_MAPPING_PIECEWISE_LINEAR piecewiselinearmapping; +} FMOD_DSP_PARAMETER_FLOAT_MAPPING; + +typedef struct FMOD_DSP_PARAMETER_DESC_FLOAT +{ + float min; + float max; + float defaultval; + FMOD_DSP_PARAMETER_FLOAT_MAPPING mapping; +} FMOD_DSP_PARAMETER_DESC_FLOAT; + +typedef struct FMOD_DSP_PARAMETER_DESC_INT +{ + int min; + int max; + int defaultval; + FMOD_BOOL goestoinf; + const char* const* valuenames; +} FMOD_DSP_PARAMETER_DESC_INT; + +typedef struct FMOD_DSP_PARAMETER_DESC_BOOL +{ + FMOD_BOOL defaultval; + const char* const* valuenames; +} FMOD_DSP_PARAMETER_DESC_BOOL; + +typedef struct FMOD_DSP_PARAMETER_DESC_DATA +{ + int datatype; +} FMOD_DSP_PARAMETER_DESC_DATA; + +typedef struct FMOD_DSP_PARAMETER_DESC +{ + FMOD_DSP_PARAMETER_TYPE type; + char name[16]; + char label[16]; + const char *description; + + union + { + FMOD_DSP_PARAMETER_DESC_FLOAT floatdesc; + FMOD_DSP_PARAMETER_DESC_INT intdesc; + FMOD_DSP_PARAMETER_DESC_BOOL booldesc; + FMOD_DSP_PARAMETER_DESC_DATA datadesc; + }; +} FMOD_DSP_PARAMETER_DESC; + +typedef struct FMOD_DSP_PARAMETER_OVERALLGAIN +{ + float linear_gain; + float linear_gain_additive; +} FMOD_DSP_PARAMETER_OVERALLGAIN; + +typedef struct FMOD_DSP_PARAMETER_3DATTRIBUTES +{ + FMOD_3D_ATTRIBUTES relative; + FMOD_3D_ATTRIBUTES absolute; +} FMOD_DSP_PARAMETER_3DATTRIBUTES; + +typedef struct FMOD_DSP_PARAMETER_3DATTRIBUTES_MULTI +{ + int numlisteners; + FMOD_3D_ATTRIBUTES relative[FMOD_MAX_LISTENERS]; + float weight[FMOD_MAX_LISTENERS]; + FMOD_3D_ATTRIBUTES absolute; +} FMOD_DSP_PARAMETER_3DATTRIBUTES_MULTI; + +typedef struct FMOD_DSP_PARAMETER_SIDECHAIN +{ + FMOD_BOOL sidechainenable; +} FMOD_DSP_PARAMETER_SIDECHAIN; + +typedef struct FMOD_DSP_PARAMETER_FFT +{ + int length; + int numchannels; + float *spectrum[32]; +} FMOD_DSP_PARAMETER_FFT; + +typedef struct FMOD_DSP_DESCRIPTION +{ + unsigned int pluginsdkversion; + char name[32]; + unsigned int version; + int numinputbuffers; + int numoutputbuffers; + FMOD_DSP_CREATE_CALLBACK create; + FMOD_DSP_RELEASE_CALLBACK release; + FMOD_DSP_RESET_CALLBACK reset; + FMOD_DSP_READ_CALLBACK read; + FMOD_DSP_PROCESS_CALLBACK process; + FMOD_DSP_SETPOSITION_CALLBACK setposition; + + int numparameters; + FMOD_DSP_PARAMETER_DESC **paramdesc; + FMOD_DSP_SETPARAM_FLOAT_CALLBACK setparameterfloat; + FMOD_DSP_SETPARAM_INT_CALLBACK setparameterint; + FMOD_DSP_SETPARAM_BOOL_CALLBACK setparameterbool; + FMOD_DSP_SETPARAM_DATA_CALLBACK setparameterdata; + FMOD_DSP_GETPARAM_FLOAT_CALLBACK getparameterfloat; + FMOD_DSP_GETPARAM_INT_CALLBACK getparameterint; + FMOD_DSP_GETPARAM_BOOL_CALLBACK getparameterbool; + FMOD_DSP_GETPARAM_DATA_CALLBACK getparameterdata; + FMOD_DSP_SHOULDIPROCESS_CALLBACK shouldiprocess; + void *userdata; + + FMOD_DSP_SYSTEM_REGISTER_CALLBACK sys_register; + FMOD_DSP_SYSTEM_DEREGISTER_CALLBACK sys_deregister; + FMOD_DSP_SYSTEM_MIX_CALLBACK sys_mix; + +} FMOD_DSP_DESCRIPTION; + +typedef struct FMOD_DSP_STATE_DFT_FUNCTIONS +{ + FMOD_DSP_DFT_FFTREAL_FUNC fftreal; + FMOD_DSP_DFT_IFFTREAL_FUNC inversefftreal; +} FMOD_DSP_STATE_DFT_FUNCTIONS; + +typedef struct FMOD_DSP_STATE_PAN_FUNCTIONS +{ + FMOD_DSP_PAN_SUMMONOMATRIX_FUNC summonomatrix; + FMOD_DSP_PAN_SUMSTEREOMATRIX_FUNC sumstereomatrix; + FMOD_DSP_PAN_SUMSURROUNDMATRIX_FUNC sumsurroundmatrix; + FMOD_DSP_PAN_SUMMONOTOSURROUNDMATRIX_FUNC summonotosurroundmatrix; + FMOD_DSP_PAN_SUMSTEREOTOSURROUNDMATRIX_FUNC sumstereotosurroundmatrix; + FMOD_DSP_PAN_GETROLLOFFGAIN_FUNC getrolloffgain; +} FMOD_DSP_STATE_PAN_FUNCTIONS; + +typedef struct FMOD_DSP_STATE_FUNCTIONS +{ + FMOD_DSP_ALLOC_FUNC alloc; + FMOD_DSP_REALLOC_FUNC realloc; + FMOD_DSP_FREE_FUNC free; + FMOD_DSP_GETSAMPLERATE_FUNC getsamplerate; + FMOD_DSP_GETBLOCKSIZE_FUNC getblocksize; + FMOD_DSP_STATE_DFT_FUNCTIONS *dft; + FMOD_DSP_STATE_PAN_FUNCTIONS *pan; + FMOD_DSP_GETSPEAKERMODE_FUNC getspeakermode; + FMOD_DSP_GETCLOCK_FUNC getclock; + FMOD_DSP_GETLISTENERATTRIBUTES_FUNC getlistenerattributes; + FMOD_DSP_LOG_FUNC log; + FMOD_DSP_GETUSERDATA_FUNC getuserdata; +} FMOD_DSP_STATE_FUNCTIONS; + +struct FMOD_DSP_STATE +{ + void *instance; + void *plugindata; + FMOD_CHANNELMASK channelmask; + FMOD_SPEAKERMODE source_speakermode; + float *sidechaindata; + int sidechainchannels; + FMOD_DSP_STATE_FUNCTIONS *functions; + int systemobject; +}; + +typedef struct FMOD_DSP_METERING_INFO +{ + int numsamples; + float peaklevel[32]; + float rmslevel[32]; + short numchannels; +} FMOD_DSP_METERING_INFO; + +/* + DSP Macros +*/ +#define FMOD_DSP_INIT_PARAMDESC_FLOAT(_paramstruct, _name, _label, _description, _min, _max, _defaultval) \ + memset(&(_paramstruct), 0, sizeof(_paramstruct)); \ + (_paramstruct).type = FMOD_DSP_PARAMETER_TYPE_FLOAT; \ + strncpy((_paramstruct).name, _name, 15); \ + strncpy((_paramstruct).label, _label, 15); \ + (_paramstruct).description = _description; \ + (_paramstruct).floatdesc.min = _min; \ + (_paramstruct).floatdesc.max = _max; \ + (_paramstruct).floatdesc.defaultval = _defaultval; \ + (_paramstruct).floatdesc.mapping.type = FMOD_DSP_PARAMETER_FLOAT_MAPPING_TYPE_AUTO; + +#define FMOD_DSP_INIT_PARAMDESC_FLOAT_WITH_MAPPING(_paramstruct, _name, _label, _description, _defaultval, _values, _positions); \ + memset(&(_paramstruct), 0, sizeof(_paramstruct)); \ + (_paramstruct).type = FMOD_DSP_PARAMETER_TYPE_FLOAT; \ + strncpy((_paramstruct).name, _name , 15); \ + strncpy((_paramstruct).label, _label, 15); \ + (_paramstruct).description = _description; \ + (_paramstruct).floatdesc.min = _values[0]; \ + (_paramstruct).floatdesc.max = _values[sizeof(_values) / sizeof(float) - 1]; \ + (_paramstruct).floatdesc.defaultval = _defaultval; \ + (_paramstruct).floatdesc.mapping.type = FMOD_DSP_PARAMETER_FLOAT_MAPPING_TYPE_PIECEWISE_LINEAR; \ + (_paramstruct).floatdesc.mapping.piecewiselinearmapping.numpoints = sizeof(_values) / sizeof(float); \ + (_paramstruct).floatdesc.mapping.piecewiselinearmapping.pointparamvalues = _values; \ + (_paramstruct).floatdesc.mapping.piecewiselinearmapping.pointpositions = _positions; + +#define FMOD_DSP_INIT_PARAMDESC_INT(_paramstruct, _name, _label, _description, _min, _max, _defaultval, _goestoinf, _valuenames) \ + memset(&(_paramstruct), 0, sizeof(_paramstruct)); \ + (_paramstruct).type = FMOD_DSP_PARAMETER_TYPE_INT; \ + strncpy((_paramstruct).name, _name , 15); \ + strncpy((_paramstruct).label, _label, 15); \ + (_paramstruct).description = _description; \ + (_paramstruct).intdesc.min = _min; \ + (_paramstruct).intdesc.max = _max; \ + (_paramstruct).intdesc.defaultval = _defaultval; \ + (_paramstruct).intdesc.goestoinf = _goestoinf; \ + (_paramstruct).intdesc.valuenames = _valuenames; + +#define FMOD_DSP_INIT_PARAMDESC_INT_ENUMERATED(_paramstruct, _name, _label, _description, _defaultval, _valuenames) \ + memset(&(_paramstruct), 0, sizeof(_paramstruct)); \ + (_paramstruct).type = FMOD_DSP_PARAMETER_TYPE_INT; \ + strncpy((_paramstruct).name, _name , 15); \ + strncpy((_paramstruct).label, _label, 15); \ + (_paramstruct).description = _description; \ + (_paramstruct).intdesc.min = 0; \ + (_paramstruct).intdesc.max = sizeof(_valuenames) / sizeof(char*) - 1; \ + (_paramstruct).intdesc.defaultval = _defaultval; \ + (_paramstruct).intdesc.goestoinf = false; \ + (_paramstruct).intdesc.valuenames = _valuenames; + +#define FMOD_DSP_INIT_PARAMDESC_BOOL(_paramstruct, _name, _label, _description, _defaultval, _valuenames) \ + memset(&(_paramstruct), 0, sizeof(_paramstruct)); \ + (_paramstruct).type = FMOD_DSP_PARAMETER_TYPE_BOOL; \ + strncpy((_paramstruct).name, _name , 15); \ + strncpy((_paramstruct).label, _label, 15); \ + (_paramstruct).description = _description; \ + (_paramstruct).booldesc.defaultval = _defaultval; \ + (_paramstruct).booldesc.valuenames = _valuenames; + +#define FMOD_DSP_INIT_PARAMDESC_DATA(_paramstruct, _name, _label, _description, _datatype) \ + memset(&(_paramstruct), 0, sizeof(_paramstruct)); \ + (_paramstruct).type = FMOD_DSP_PARAMETER_TYPE_DATA; \ + strncpy((_paramstruct).name, _name , 15); \ + strncpy((_paramstruct).label, _label, 15); \ + (_paramstruct).description = _description; \ + (_paramstruct).datadesc.datatype = _datatype; + +#define FMOD_DSP_ALLOC(_state, _size) \ + (_state)->functions->alloc(_size, FMOD_MEMORY_NORMAL, __FILE__) +#define FMOD_DSP_REALLOC(_state, _ptr, _size) \ + (_state)->functions->realloc(_ptr, _size, FMOD_MEMORY_NORMAL, __FILE__) +#define FMOD_DSP_FREE(_state, _ptr) \ + (_state)->functions->free(_ptr, FMOD_MEMORY_NORMAL, __FILE__) +#define FMOD_DSP_LOG(_state, _level, _location, _format, ...) \ + (_state)->functions->log(_level, __FILE__, __LINE__, _location, _format, __VA_ARGS__) +#define FMOD_DSP_GETSAMPLERATE(_state, _rate) \ + (_state)->functions->getsamplerate(_state, _rate) +#define FMOD_DSP_GETBLOCKSIZE(_state, _blocksize) \ + (_state)->functions->getblocksize(_state, _blocksize) +#define FMOD_DSP_GETSPEAKERMODE(_state, _speakermodemix, _speakermodeout) \ + (_state)->functions->getspeakermode(_state, _speakermodemix, _speakermodeout) +#define FMOD_DSP_GETCLOCK(_state, _clock, _offset, _length) \ + (_state)->functions->getclock(_state, _clock, _offset, _length) +#define FMOD_DSP_GETLISTENERATTRIBUTES(_state, _numlisteners, _attributes) \ + (_state)->functions->getlistenerattributes(_state, _numlisteners, _attributes) +#define FMOD_DSP_GETUSERDATA(_state, _userdata) \ + (_state)->functions->getuserdata(_state, _userdata) +#define FMOD_DSP_DFT_FFTREAL(_state, _size, _signal, _dft, _window, _signalhop) \ + (_state)->functions->dft->fftreal(_state, _size, _signal, _dft, _window, _signalhop) +#define FMOD_DSP_DFT_IFFTREAL(_state, _size, _dft, _signal, _window, _signalhop) \ + (_state)->functions->dft->inversefftreal(_state, _size, _dft, _signal, _window, _signalhop) +#define FMOD_DSP_PAN_SUMMONOMATRIX(_state, _sourcespeakermode, _lowfrequencygain, _overallgain, _matrix) \ + (_state)->functions->pan->summonomatrix(_state, _sourcespeakermode, _lowfrequencygain, _overallgain, _matrix) +#define FMOD_DSP_PAN_SUMSTEREOMATRIX(_state, _sourcespeakermode, _pan, _lowfrequencygain, _overallgain, _matrixhop, _matrix) \ + (_state)->functions->pan->sumstereomatrix(_state, _sourcespeakermode, _pan, _lowfrequencygain, _overallgain, _matrixhop, _matrix) +#define FMOD_DSP_PAN_SUMSURROUNDMATRIX(_state, _sourcespeakermode, _targetspeakermode, _direction, _extent, _rotation, _lowfrequencygain, _overallgain, _matrixhop, _matrix, _flags) \ + (_state)->functions->pan->sumsurroundmatrix(_state, _sourcespeakermode, _targetspeakermode, _direction, _extent, _rotation, _lowfrequencygain, _overallgain, _matrixhop, _matrix, _flags) +#define FMOD_DSP_PAN_SUMMONOTOSURROUNDMATRIX(_state, _targetspeakermode, _direction, _extent, _lowfrequencygain, _overallgain, _matrixhop, _matrix) \ + (_state)->functions->pan->summonotosurroundmatrix(_state, _targetspeakermode, _direction, _extent, _lowfrequencygain, _overallgain, _matrixhop, _matrix) +#define FMOD_DSP_PAN_SUMSTEREOTOSURROUNDMATRIX(_state, _targetspeakermode, _direction, _extent, _rotation, _lowfrequencygain, _overallgain, matrixhop, _matrix) \ + (_state)->functions->pan->sumstereotosurroundmatrix(_state, _targetspeakermode, _direction, _extent, _rotation, _lowfrequencygain, _overallgain, matrixhop, _matrix) +#define FMOD_DSP_PAN_GETROLLOFFGAIN(_state, _rolloff, _distance, _mindistance, _maxdistance, _gain) \ + (_state)->functions->pan->getrolloffgain(_state, _rolloff, _distance, _mindistance, _maxdistance, _gain) + +#endif + diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_dsp_effects.h b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_dsp_effects.h new file mode 100644 index 0000000..af1a0d6 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_dsp_effects.h @@ -0,0 +1,537 @@ +/* ============================================================================================================= */ +/* FMOD Core API - Built-in effects header file. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* */ +/* In this header you can find parameter structures for FMOD system registered DSP effects */ +/* and generators. */ +/* */ +/* For more detail visit: */ +/* https://fmod.com/resources/documentation-api?version=2.0&page=core-api-common-dsp-effects.html#fmod_dsp_type */ +/* ============================================================================================================= */ + +#ifndef _FMOD_DSP_EFFECTS_H +#define _FMOD_DSP_EFFECTS_H + +typedef enum +{ + FMOD_DSP_TYPE_UNKNOWN, + FMOD_DSP_TYPE_MIXER, + FMOD_DSP_TYPE_OSCILLATOR, + FMOD_DSP_TYPE_LOWPASS, + FMOD_DSP_TYPE_ITLOWPASS, + FMOD_DSP_TYPE_HIGHPASS, + FMOD_DSP_TYPE_ECHO, + FMOD_DSP_TYPE_FADER, + FMOD_DSP_TYPE_FLANGE, + FMOD_DSP_TYPE_DISTORTION, + FMOD_DSP_TYPE_NORMALIZE, + FMOD_DSP_TYPE_LIMITER, + FMOD_DSP_TYPE_PARAMEQ, + FMOD_DSP_TYPE_PITCHSHIFT, + FMOD_DSP_TYPE_CHORUS, + FMOD_DSP_TYPE_VSTPLUGIN, + FMOD_DSP_TYPE_WINAMPPLUGIN, + FMOD_DSP_TYPE_ITECHO, + FMOD_DSP_TYPE_COMPRESSOR, + FMOD_DSP_TYPE_SFXREVERB, + FMOD_DSP_TYPE_LOWPASS_SIMPLE, + FMOD_DSP_TYPE_DELAY, + FMOD_DSP_TYPE_TREMOLO, + FMOD_DSP_TYPE_LADSPAPLUGIN, + FMOD_DSP_TYPE_SEND, + FMOD_DSP_TYPE_RETURN, + FMOD_DSP_TYPE_HIGHPASS_SIMPLE, + FMOD_DSP_TYPE_PAN, + FMOD_DSP_TYPE_THREE_EQ, + FMOD_DSP_TYPE_FFT, + FMOD_DSP_TYPE_LOUDNESS_METER, + FMOD_DSP_TYPE_ENVELOPEFOLLOWER, + FMOD_DSP_TYPE_CONVOLUTIONREVERB, + FMOD_DSP_TYPE_CHANNELMIX, + FMOD_DSP_TYPE_TRANSCEIVER, + FMOD_DSP_TYPE_OBJECTPAN, + FMOD_DSP_TYPE_MULTIBAND_EQ, + + FMOD_DSP_TYPE_MAX, + FMOD_DSP_TYPE_FORCEINT = 65536 /* Makes sure this enum is signed 32bit. */ +} FMOD_DSP_TYPE; + +/* + =================================================================================================== + + FMOD built in effect parameters. + Use DSP::setParameter with these enums for the 'index' parameter. + + =================================================================================================== +*/ + +typedef enum +{ + FMOD_DSP_OSCILLATOR_TYPE, + FMOD_DSP_OSCILLATOR_RATE +} FMOD_DSP_OSCILLATOR; + + +typedef enum +{ + FMOD_DSP_LOWPASS_CUTOFF, + FMOD_DSP_LOWPASS_RESONANCE +} FMOD_DSP_LOWPASS; + + +typedef enum +{ + FMOD_DSP_ITLOWPASS_CUTOFF, + FMOD_DSP_ITLOWPASS_RESONANCE +} FMOD_DSP_ITLOWPASS; + + +typedef enum +{ + FMOD_DSP_HIGHPASS_CUTOFF, + FMOD_DSP_HIGHPASS_RESONANCE +} FMOD_DSP_HIGHPASS; + + +typedef enum +{ + FMOD_DSP_ECHO_DELAY, + FMOD_DSP_ECHO_FEEDBACK, + FMOD_DSP_ECHO_DRYLEVEL, + FMOD_DSP_ECHO_WETLEVEL +} FMOD_DSP_ECHO; + + +typedef enum FMOD_DSP_FADER +{ + FMOD_DSP_FADER_GAIN, + FMOD_DSP_FADER_OVERALL_GAIN, +} FMOD_DSP_FADER; + + +typedef enum +{ + FMOD_DSP_FLANGE_MIX, + FMOD_DSP_FLANGE_DEPTH, + FMOD_DSP_FLANGE_RATE +} FMOD_DSP_FLANGE; + + +typedef enum +{ + FMOD_DSP_DISTORTION_LEVEL +} FMOD_DSP_DISTORTION; + + +typedef enum +{ + FMOD_DSP_NORMALIZE_FADETIME, + FMOD_DSP_NORMALIZE_THRESHHOLD, + FMOD_DSP_NORMALIZE_MAXAMP +} FMOD_DSP_NORMALIZE; + + +typedef enum +{ + FMOD_DSP_LIMITER_RELEASETIME, + FMOD_DSP_LIMITER_CEILING, + FMOD_DSP_LIMITER_MAXIMIZERGAIN, + FMOD_DSP_LIMITER_MODE, +} FMOD_DSP_LIMITER; + + +typedef enum +{ + FMOD_DSP_PARAMEQ_CENTER, + FMOD_DSP_PARAMEQ_BANDWIDTH, + FMOD_DSP_PARAMEQ_GAIN +} FMOD_DSP_PARAMEQ; + + +typedef enum FMOD_DSP_MULTIBAND_EQ +{ + FMOD_DSP_MULTIBAND_EQ_A_FILTER, + FMOD_DSP_MULTIBAND_EQ_A_FREQUENCY, + FMOD_DSP_MULTIBAND_EQ_A_Q, + FMOD_DSP_MULTIBAND_EQ_A_GAIN, + FMOD_DSP_MULTIBAND_EQ_B_FILTER, + FMOD_DSP_MULTIBAND_EQ_B_FREQUENCY, + FMOD_DSP_MULTIBAND_EQ_B_Q, + FMOD_DSP_MULTIBAND_EQ_B_GAIN, + FMOD_DSP_MULTIBAND_EQ_C_FILTER, + FMOD_DSP_MULTIBAND_EQ_C_FREQUENCY, + FMOD_DSP_MULTIBAND_EQ_C_Q, + FMOD_DSP_MULTIBAND_EQ_C_GAIN, + FMOD_DSP_MULTIBAND_EQ_D_FILTER, + FMOD_DSP_MULTIBAND_EQ_D_FREQUENCY, + FMOD_DSP_MULTIBAND_EQ_D_Q, + FMOD_DSP_MULTIBAND_EQ_D_GAIN, + FMOD_DSP_MULTIBAND_EQ_E_FILTER, + FMOD_DSP_MULTIBAND_EQ_E_FREQUENCY, + FMOD_DSP_MULTIBAND_EQ_E_Q, + FMOD_DSP_MULTIBAND_EQ_E_GAIN, +} FMOD_DSP_MULTIBAND_EQ; + + +typedef enum FMOD_DSP_MULTIBAND_EQ_FILTER_TYPE +{ + FMOD_DSP_MULTIBAND_EQ_FILTER_DISABLED, + FMOD_DSP_MULTIBAND_EQ_FILTER_LOWPASS_12DB, + FMOD_DSP_MULTIBAND_EQ_FILTER_LOWPASS_24DB, + FMOD_DSP_MULTIBAND_EQ_FILTER_LOWPASS_48DB, + FMOD_DSP_MULTIBAND_EQ_FILTER_HIGHPASS_12DB, + FMOD_DSP_MULTIBAND_EQ_FILTER_HIGHPASS_24DB, + FMOD_DSP_MULTIBAND_EQ_FILTER_HIGHPASS_48DB, + FMOD_DSP_MULTIBAND_EQ_FILTER_LOWSHELF, + FMOD_DSP_MULTIBAND_EQ_FILTER_HIGHSHELF, + FMOD_DSP_MULTIBAND_EQ_FILTER_PEAKING, + FMOD_DSP_MULTIBAND_EQ_FILTER_BANDPASS, + FMOD_DSP_MULTIBAND_EQ_FILTER_NOTCH, + FMOD_DSP_MULTIBAND_EQ_FILTER_ALLPASS, +} FMOD_DSP_MULTIBAND_EQ_FILTER_TYPE; + + +typedef enum +{ + FMOD_DSP_PITCHSHIFT_PITCH, + FMOD_DSP_PITCHSHIFT_FFTSIZE, + FMOD_DSP_PITCHSHIFT_OVERLAP, + FMOD_DSP_PITCHSHIFT_MAXCHANNELS +} FMOD_DSP_PITCHSHIFT; + + +typedef enum +{ + FMOD_DSP_CHORUS_MIX, + FMOD_DSP_CHORUS_RATE, + FMOD_DSP_CHORUS_DEPTH, +} FMOD_DSP_CHORUS; + + +typedef enum +{ + FMOD_DSP_ITECHO_WETDRYMIX, + FMOD_DSP_ITECHO_FEEDBACK, + FMOD_DSP_ITECHO_LEFTDELAY, + FMOD_DSP_ITECHO_RIGHTDELAY, + FMOD_DSP_ITECHO_PANDELAY +} FMOD_DSP_ITECHO; + +typedef enum +{ + FMOD_DSP_COMPRESSOR_THRESHOLD, + FMOD_DSP_COMPRESSOR_RATIO, + FMOD_DSP_COMPRESSOR_ATTACK, + FMOD_DSP_COMPRESSOR_RELEASE, + FMOD_DSP_COMPRESSOR_GAINMAKEUP, + FMOD_DSP_COMPRESSOR_USESIDECHAIN, + FMOD_DSP_COMPRESSOR_LINKED +} FMOD_DSP_COMPRESSOR; + +typedef enum +{ + FMOD_DSP_SFXREVERB_DECAYTIME, + FMOD_DSP_SFXREVERB_EARLYDELAY, + FMOD_DSP_SFXREVERB_LATEDELAY, + FMOD_DSP_SFXREVERB_HFREFERENCE, + FMOD_DSP_SFXREVERB_HFDECAYRATIO, + FMOD_DSP_SFXREVERB_DIFFUSION, + FMOD_DSP_SFXREVERB_DENSITY, + FMOD_DSP_SFXREVERB_LOWSHELFFREQUENCY, + FMOD_DSP_SFXREVERB_LOWSHELFGAIN, + FMOD_DSP_SFXREVERB_HIGHCUT, + FMOD_DSP_SFXREVERB_EARLYLATEMIX, + FMOD_DSP_SFXREVERB_WETLEVEL, + FMOD_DSP_SFXREVERB_DRYLEVEL +} FMOD_DSP_SFXREVERB; + +typedef enum +{ + FMOD_DSP_LOWPASS_SIMPLE_CUTOFF +} FMOD_DSP_LOWPASS_SIMPLE; + + +typedef enum +{ + FMOD_DSP_DELAY_CH0, + FMOD_DSP_DELAY_CH1, + FMOD_DSP_DELAY_CH2, + FMOD_DSP_DELAY_CH3, + FMOD_DSP_DELAY_CH4, + FMOD_DSP_DELAY_CH5, + FMOD_DSP_DELAY_CH6, + FMOD_DSP_DELAY_CH7, + FMOD_DSP_DELAY_CH8, + FMOD_DSP_DELAY_CH9, + FMOD_DSP_DELAY_CH10, + FMOD_DSP_DELAY_CH11, + FMOD_DSP_DELAY_CH12, + FMOD_DSP_DELAY_CH13, + FMOD_DSP_DELAY_CH14, + FMOD_DSP_DELAY_CH15, + FMOD_DSP_DELAY_MAXDELAY +} FMOD_DSP_DELAY; + + +typedef enum +{ + FMOD_DSP_TREMOLO_FREQUENCY, + FMOD_DSP_TREMOLO_DEPTH, + FMOD_DSP_TREMOLO_SHAPE, + FMOD_DSP_TREMOLO_SKEW, + FMOD_DSP_TREMOLO_DUTY, + FMOD_DSP_TREMOLO_SQUARE, + FMOD_DSP_TREMOLO_PHASE, + FMOD_DSP_TREMOLO_SPREAD +} FMOD_DSP_TREMOLO; + + +typedef enum +{ + FMOD_DSP_SEND_RETURNID, + FMOD_DSP_SEND_LEVEL, +} FMOD_DSP_SEND; + + +typedef enum +{ + FMOD_DSP_RETURN_ID, + FMOD_DSP_RETURN_INPUT_SPEAKER_MODE +} FMOD_DSP_RETURN; + + +typedef enum +{ + FMOD_DSP_HIGHPASS_SIMPLE_CUTOFF +} FMOD_DSP_HIGHPASS_SIMPLE; + + +typedef enum +{ + FMOD_DSP_PAN_2D_STEREO_MODE_DISTRIBUTED, + FMOD_DSP_PAN_2D_STEREO_MODE_DISCRETE +} FMOD_DSP_PAN_2D_STEREO_MODE_TYPE; + + +typedef enum +{ + FMOD_DSP_PAN_MODE_MONO, + FMOD_DSP_PAN_MODE_STEREO, + FMOD_DSP_PAN_MODE_SURROUND +} FMOD_DSP_PAN_MODE_TYPE; + + +typedef enum +{ + FMOD_DSP_PAN_3D_ROLLOFF_LINEARSQUARED, + FMOD_DSP_PAN_3D_ROLLOFF_LINEAR, + FMOD_DSP_PAN_3D_ROLLOFF_INVERSE, + FMOD_DSP_PAN_3D_ROLLOFF_INVERSETAPERED, + FMOD_DSP_PAN_3D_ROLLOFF_CUSTOM +} FMOD_DSP_PAN_3D_ROLLOFF_TYPE; + + +typedef enum +{ + FMOD_DSP_PAN_3D_EXTENT_MODE_AUTO, + FMOD_DSP_PAN_3D_EXTENT_MODE_USER, + FMOD_DSP_PAN_3D_EXTENT_MODE_OFF +} FMOD_DSP_PAN_3D_EXTENT_MODE_TYPE; + + +typedef enum +{ + FMOD_DSP_PAN_MODE, + FMOD_DSP_PAN_2D_STEREO_POSITION, + FMOD_DSP_PAN_2D_DIRECTION, + FMOD_DSP_PAN_2D_EXTENT, + FMOD_DSP_PAN_2D_ROTATION, + FMOD_DSP_PAN_2D_LFE_LEVEL, + FMOD_DSP_PAN_2D_STEREO_MODE, + FMOD_DSP_PAN_2D_STEREO_SEPARATION, + FMOD_DSP_PAN_2D_STEREO_AXIS, + FMOD_DSP_PAN_ENABLED_SPEAKERS, + FMOD_DSP_PAN_3D_POSITION, + FMOD_DSP_PAN_3D_ROLLOFF, + FMOD_DSP_PAN_3D_MIN_DISTANCE, + FMOD_DSP_PAN_3D_MAX_DISTANCE, + FMOD_DSP_PAN_3D_EXTENT_MODE, + FMOD_DSP_PAN_3D_SOUND_SIZE, + FMOD_DSP_PAN_3D_MIN_EXTENT, + FMOD_DSP_PAN_3D_PAN_BLEND, + FMOD_DSP_PAN_LFE_UPMIX_ENABLED, + FMOD_DSP_PAN_OVERALL_GAIN, + FMOD_DSP_PAN_SURROUND_SPEAKER_MODE, + FMOD_DSP_PAN_2D_HEIGHT_BLEND, +} FMOD_DSP_PAN; + + +typedef enum +{ + FMOD_DSP_THREE_EQ_CROSSOVERSLOPE_12DB, + FMOD_DSP_THREE_EQ_CROSSOVERSLOPE_24DB, + FMOD_DSP_THREE_EQ_CROSSOVERSLOPE_48DB +} FMOD_DSP_THREE_EQ_CROSSOVERSLOPE_TYPE; + + +typedef enum +{ + FMOD_DSP_THREE_EQ_LOWGAIN, + FMOD_DSP_THREE_EQ_MIDGAIN, + FMOD_DSP_THREE_EQ_HIGHGAIN, + FMOD_DSP_THREE_EQ_LOWCROSSOVER, + FMOD_DSP_THREE_EQ_HIGHCROSSOVER, + FMOD_DSP_THREE_EQ_CROSSOVERSLOPE +} FMOD_DSP_THREE_EQ; + + +typedef enum +{ + FMOD_DSP_FFT_WINDOW_RECT, + FMOD_DSP_FFT_WINDOW_TRIANGLE, + FMOD_DSP_FFT_WINDOW_HAMMING, + FMOD_DSP_FFT_WINDOW_HANNING, + FMOD_DSP_FFT_WINDOW_BLACKMAN, + FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS +} FMOD_DSP_FFT_WINDOW; + + +typedef enum +{ + FMOD_DSP_FFT_WINDOWSIZE, + FMOD_DSP_FFT_WINDOWTYPE, + FMOD_DSP_FFT_SPECTRUMDATA, + FMOD_DSP_FFT_DOMINANT_FREQ +} FMOD_DSP_FFT; + + +typedef enum +{ + FMOD_DSP_ENVELOPEFOLLOWER_ATTACK, + FMOD_DSP_ENVELOPEFOLLOWER_RELEASE, + FMOD_DSP_ENVELOPEFOLLOWER_ENVELOPE, + FMOD_DSP_ENVELOPEFOLLOWER_USESIDECHAIN +} FMOD_DSP_ENVELOPEFOLLOWER; + +typedef enum +{ + FMOD_DSP_CONVOLUTION_REVERB_PARAM_IR, + FMOD_DSP_CONVOLUTION_REVERB_PARAM_WET, + FMOD_DSP_CONVOLUTION_REVERB_PARAM_DRY, + FMOD_DSP_CONVOLUTION_REVERB_PARAM_LINKED +} FMOD_DSP_CONVOLUTION_REVERB; + +typedef enum +{ + FMOD_DSP_CHANNELMIX_OUTPUT_DEFAULT, + FMOD_DSP_CHANNELMIX_OUTPUT_ALLMONO, + FMOD_DSP_CHANNELMIX_OUTPUT_ALLSTEREO, + FMOD_DSP_CHANNELMIX_OUTPUT_ALLQUAD, + FMOD_DSP_CHANNELMIX_OUTPUT_ALL5POINT1, + FMOD_DSP_CHANNELMIX_OUTPUT_ALL7POINT1, + FMOD_DSP_CHANNELMIX_OUTPUT_ALLLFE, + FMOD_DSP_CHANNELMIX_OUTPUT_ALL7POINT1POINT4 +} FMOD_DSP_CHANNELMIX_OUTPUT; + +typedef enum +{ + FMOD_DSP_CHANNELMIX_OUTPUTGROUPING, + FMOD_DSP_CHANNELMIX_GAIN_CH0, + FMOD_DSP_CHANNELMIX_GAIN_CH1, + FMOD_DSP_CHANNELMIX_GAIN_CH2, + FMOD_DSP_CHANNELMIX_GAIN_CH3, + FMOD_DSP_CHANNELMIX_GAIN_CH4, + FMOD_DSP_CHANNELMIX_GAIN_CH5, + FMOD_DSP_CHANNELMIX_GAIN_CH6, + FMOD_DSP_CHANNELMIX_GAIN_CH7, + FMOD_DSP_CHANNELMIX_GAIN_CH8, + FMOD_DSP_CHANNELMIX_GAIN_CH9, + FMOD_DSP_CHANNELMIX_GAIN_CH10, + FMOD_DSP_CHANNELMIX_GAIN_CH11, + FMOD_DSP_CHANNELMIX_GAIN_CH12, + FMOD_DSP_CHANNELMIX_GAIN_CH13, + FMOD_DSP_CHANNELMIX_GAIN_CH14, + FMOD_DSP_CHANNELMIX_GAIN_CH15, + FMOD_DSP_CHANNELMIX_GAIN_CH16, + FMOD_DSP_CHANNELMIX_GAIN_CH17, + FMOD_DSP_CHANNELMIX_GAIN_CH18, + FMOD_DSP_CHANNELMIX_GAIN_CH19, + FMOD_DSP_CHANNELMIX_GAIN_CH20, + FMOD_DSP_CHANNELMIX_GAIN_CH21, + FMOD_DSP_CHANNELMIX_GAIN_CH22, + FMOD_DSP_CHANNELMIX_GAIN_CH23, + FMOD_DSP_CHANNELMIX_GAIN_CH24, + FMOD_DSP_CHANNELMIX_GAIN_CH25, + FMOD_DSP_CHANNELMIX_GAIN_CH26, + FMOD_DSP_CHANNELMIX_GAIN_CH27, + FMOD_DSP_CHANNELMIX_GAIN_CH28, + FMOD_DSP_CHANNELMIX_GAIN_CH29, + FMOD_DSP_CHANNELMIX_GAIN_CH30, + FMOD_DSP_CHANNELMIX_GAIN_CH31, + FMOD_DSP_CHANNELMIX_OUTPUT_CH0, + FMOD_DSP_CHANNELMIX_OUTPUT_CH1, + FMOD_DSP_CHANNELMIX_OUTPUT_CH2, + FMOD_DSP_CHANNELMIX_OUTPUT_CH3, + FMOD_DSP_CHANNELMIX_OUTPUT_CH4, + FMOD_DSP_CHANNELMIX_OUTPUT_CH5, + FMOD_DSP_CHANNELMIX_OUTPUT_CH6, + FMOD_DSP_CHANNELMIX_OUTPUT_CH7, + FMOD_DSP_CHANNELMIX_OUTPUT_CH8, + FMOD_DSP_CHANNELMIX_OUTPUT_CH9, + FMOD_DSP_CHANNELMIX_OUTPUT_CH10, + FMOD_DSP_CHANNELMIX_OUTPUT_CH11, + FMOD_DSP_CHANNELMIX_OUTPUT_CH12, + FMOD_DSP_CHANNELMIX_OUTPUT_CH13, + FMOD_DSP_CHANNELMIX_OUTPUT_CH14, + FMOD_DSP_CHANNELMIX_OUTPUT_CH15, + FMOD_DSP_CHANNELMIX_OUTPUT_CH16, + FMOD_DSP_CHANNELMIX_OUTPUT_CH17, + FMOD_DSP_CHANNELMIX_OUTPUT_CH18, + FMOD_DSP_CHANNELMIX_OUTPUT_CH19, + FMOD_DSP_CHANNELMIX_OUTPUT_CH20, + FMOD_DSP_CHANNELMIX_OUTPUT_CH21, + FMOD_DSP_CHANNELMIX_OUTPUT_CH22, + FMOD_DSP_CHANNELMIX_OUTPUT_CH23, + FMOD_DSP_CHANNELMIX_OUTPUT_CH24, + FMOD_DSP_CHANNELMIX_OUTPUT_CH25, + FMOD_DSP_CHANNELMIX_OUTPUT_CH26, + FMOD_DSP_CHANNELMIX_OUTPUT_CH27, + FMOD_DSP_CHANNELMIX_OUTPUT_CH28, + FMOD_DSP_CHANNELMIX_OUTPUT_CH29, + FMOD_DSP_CHANNELMIX_OUTPUT_CH30, + FMOD_DSP_CHANNELMIX_OUTPUT_CH31 +} FMOD_DSP_CHANNELMIX; + +typedef enum +{ + FMOD_DSP_TRANSCEIVER_SPEAKERMODE_AUTO = -1, + FMOD_DSP_TRANSCEIVER_SPEAKERMODE_MONO = 0, + FMOD_DSP_TRANSCEIVER_SPEAKERMODE_STEREO, + FMOD_DSP_TRANSCEIVER_SPEAKERMODE_SURROUND, +} FMOD_DSP_TRANSCEIVER_SPEAKERMODE; + + +typedef enum +{ + FMOD_DSP_TRANSCEIVER_TRANSMIT, + FMOD_DSP_TRANSCEIVER_GAIN, + FMOD_DSP_TRANSCEIVER_CHANNEL, + FMOD_DSP_TRANSCEIVER_TRANSMITSPEAKERMODE +} FMOD_DSP_TRANSCEIVER; + + +typedef enum +{ + FMOD_DSP_OBJECTPAN_3D_POSITION, + FMOD_DSP_OBJECTPAN_3D_ROLLOFF, + FMOD_DSP_OBJECTPAN_3D_MIN_DISTANCE, + FMOD_DSP_OBJECTPAN_3D_MAX_DISTANCE, + FMOD_DSP_OBJECTPAN_3D_EXTENT_MODE, + FMOD_DSP_OBJECTPAN_3D_SOUND_SIZE, + FMOD_DSP_OBJECTPAN_3D_MIN_EXTENT, + FMOD_DSP_OBJECTPAN_OVERALL_GAIN, + FMOD_DSP_OBJECTPAN_OUTPUTGAIN +} FMOD_DSP_OBJECTPAN; + +#endif + diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_errors.h b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_errors.h new file mode 100644 index 0000000..2acd594 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_errors.h @@ -0,0 +1,110 @@ +/* ============================================================================================== */ +/* FMOD Core / Studio API - Error string header file. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* */ +/* Use this header if you want to store or display a string version / english explanation */ +/* of the FMOD error codes. */ +/* */ +/* For more detail visit: */ +/* https://fmod.com/resources/documentation-api?version=2.0&page=core-api-common.html#fmod_result */ +/* =============================================================================================== */ +#ifndef _FMOD_ERRORS_H +#define _FMOD_ERRORS_H + +#include "fmod.h" + +#ifdef __GNUC__ +static const char *FMOD_ErrorString(FMOD_RESULT errcode) __attribute__((unused)); +#endif + +static const char *FMOD_ErrorString(FMOD_RESULT errcode) +{ + switch (errcode) + { + case FMOD_OK: return "No errors."; + case FMOD_ERR_BADCOMMAND: return "Tried to call a function on a data type that does not allow this type of functionality (ie calling Sound::lock on a streaming sound)."; + case FMOD_ERR_CHANNEL_ALLOC: return "Error trying to allocate a channel."; + case FMOD_ERR_CHANNEL_STOLEN: return "The specified channel has been reused to play another sound."; + case FMOD_ERR_DMA: return "DMA Failure. See debug output for more information."; + case FMOD_ERR_DSP_CONNECTION: return "DSP connection error. Connection possibly caused a cyclic dependency or connected dsps with incompatible buffer counts."; + case FMOD_ERR_DSP_DONTPROCESS: return "DSP return code from a DSP process query callback. Tells mixer not to call the process callback and therefore not consume CPU. Use this to optimize the DSP graph."; + case FMOD_ERR_DSP_FORMAT: return "DSP Format error. A DSP unit may have attempted to connect to this network with the wrong format, or a matrix may have been set with the wrong size if the target unit has a specified channel map."; + case FMOD_ERR_DSP_INUSE: return "DSP is already in the mixer's DSP network. It must be removed before being reinserted or released."; + case FMOD_ERR_DSP_NOTFOUND: return "DSP connection error. Couldn't find the DSP unit specified."; + case FMOD_ERR_DSP_RESERVED: return "DSP operation error. Cannot perform operation on this DSP as it is reserved by the system."; + case FMOD_ERR_DSP_SILENCE: return "DSP return code from a DSP process query callback. Tells mixer silence would be produced from read, so go idle and not consume CPU. Use this to optimize the DSP graph."; + case FMOD_ERR_DSP_TYPE: return "DSP operation cannot be performed on a DSP of this type."; + case FMOD_ERR_FILE_BAD: return "Error loading file."; + case FMOD_ERR_FILE_COULDNOTSEEK: return "Couldn't perform seek operation. This is a limitation of the medium (ie netstreams) or the file format."; + case FMOD_ERR_FILE_DISKEJECTED: return "Media was ejected while reading."; + case FMOD_ERR_FILE_EOF: return "End of file unexpectedly reached while trying to read essential data (truncated?)."; + case FMOD_ERR_FILE_ENDOFDATA: return "End of current chunk reached while trying to read data."; + case FMOD_ERR_FILE_NOTFOUND: return "File not found."; + case FMOD_ERR_FORMAT: return "Unsupported file or audio format."; + case FMOD_ERR_HEADER_MISMATCH: return "There is a version mismatch between the FMOD header and either the FMOD Studio library or the FMOD Low Level library."; + case FMOD_ERR_HTTP: return "A HTTP error occurred. This is a catch-all for HTTP errors not listed elsewhere."; + case FMOD_ERR_HTTP_ACCESS: return "The specified resource requires authentication or is forbidden."; + case FMOD_ERR_HTTP_PROXY_AUTH: return "Proxy authentication is required to access the specified resource."; + case FMOD_ERR_HTTP_SERVER_ERROR: return "A HTTP server error occurred."; + case FMOD_ERR_HTTP_TIMEOUT: return "The HTTP request timed out."; + case FMOD_ERR_INITIALIZATION: return "FMOD was not initialized correctly to support this function."; + case FMOD_ERR_INITIALIZED: return "Cannot call this command after System::init."; + case FMOD_ERR_INTERNAL: return "An error occurred that wasn't supposed to. Contact support."; + case FMOD_ERR_INVALID_FLOAT: return "Value passed in was a NaN, Inf or denormalized float."; + case FMOD_ERR_INVALID_HANDLE: return "An invalid object handle was used."; + case FMOD_ERR_INVALID_PARAM: return "An invalid parameter was passed to this function."; + case FMOD_ERR_INVALID_POSITION: return "An invalid seek position was passed to this function."; + case FMOD_ERR_INVALID_SPEAKER: return "An invalid speaker was passed to this function based on the current speaker mode."; + case FMOD_ERR_INVALID_SYNCPOINT: return "The syncpoint did not come from this sound handle."; + case FMOD_ERR_INVALID_THREAD: return "Tried to call a function on a thread that is not supported."; + case FMOD_ERR_INVALID_VECTOR: return "The vectors passed in are not unit length, or perpendicular."; + case FMOD_ERR_MAXAUDIBLE: return "Reached maximum audible playback count for this sound's soundgroup."; + case FMOD_ERR_MEMORY: return "Not enough memory or resources."; + case FMOD_ERR_MEMORY_CANTPOINT: return "Can't use FMOD_OPENMEMORY_POINT on non PCM source data, or non mp3/xma/adpcm data if FMOD_CREATECOMPRESSEDSAMPLE was used."; + case FMOD_ERR_NEEDS3D: return "Tried to call a command on a 2d sound when the command was meant for 3d sound."; + case FMOD_ERR_NEEDSHARDWARE: return "Tried to use a feature that requires hardware support."; + case FMOD_ERR_NET_CONNECT: return "Couldn't connect to the specified host."; + case FMOD_ERR_NET_SOCKET_ERROR: return "A socket error occurred. This is a catch-all for socket-related errors not listed elsewhere."; + case FMOD_ERR_NET_URL: return "The specified URL couldn't be resolved."; + case FMOD_ERR_NET_WOULD_BLOCK: return "Operation on a non-blocking socket could not complete immediately."; + case FMOD_ERR_NOTREADY: return "Operation could not be performed because specified sound/DSP connection is not ready."; + case FMOD_ERR_OUTPUT_ALLOCATED: return "Error initializing output device, but more specifically, the output device is already in use and cannot be reused."; + case FMOD_ERR_OUTPUT_CREATEBUFFER: return "Error creating hardware sound buffer."; + case FMOD_ERR_OUTPUT_DRIVERCALL: return "A call to a standard soundcard driver failed, which could possibly mean a bug in the driver or resources were missing or exhausted."; + case FMOD_ERR_OUTPUT_FORMAT: return "Soundcard does not support the specified format."; + case FMOD_ERR_OUTPUT_INIT: return "Error initializing output device."; + case FMOD_ERR_OUTPUT_NODRIVERS: return "The output device has no drivers installed. If pre-init, FMOD_OUTPUT_NOSOUND is selected as the output mode. If post-init, the function just fails."; + case FMOD_ERR_PLUGIN: return "An unspecified error has been returned from a plugin."; + case FMOD_ERR_PLUGIN_MISSING: return "A requested output, dsp unit type or codec was not available."; + case FMOD_ERR_PLUGIN_RESOURCE: return "A resource that the plugin requires cannot be found. (ie the DLS file for MIDI playback)"; + case FMOD_ERR_PLUGIN_VERSION: return "A plugin was built with an unsupported SDK version."; + case FMOD_ERR_RECORD: return "An error occurred trying to initialize the recording device."; + case FMOD_ERR_REVERB_CHANNELGROUP: return "Reverb properties cannot be set on this channel because a parent channelgroup owns the reverb connection."; + case FMOD_ERR_REVERB_INSTANCE: return "Specified instance in FMOD_REVERB_PROPERTIES couldn't be set. Most likely because it is an invalid instance number or the reverb doesn't exist."; + case FMOD_ERR_SUBSOUNDS: return "The error occurred because the sound referenced contains subsounds when it shouldn't have, or it doesn't contain subsounds when it should have. The operation may also not be able to be performed on a parent sound."; + case FMOD_ERR_SUBSOUND_ALLOCATED: return "This subsound is already being used by another sound, you cannot have more than one parent to a sound. Null out the other parent's entry first."; + case FMOD_ERR_SUBSOUND_CANTMOVE: return "Shared subsounds cannot be replaced or moved from their parent stream, such as when the parent stream is an FSB file."; + case FMOD_ERR_TAGNOTFOUND: return "The specified tag could not be found or there are no tags."; + case FMOD_ERR_TOOMANYCHANNELS: return "The sound created exceeds the allowable input channel count. This can be increased using the 'maxinputchannels' parameter in System::setSoftwareFormat."; + case FMOD_ERR_TRUNCATED: return "The retrieved string is too long to fit in the supplied buffer and has been truncated."; + case FMOD_ERR_UNIMPLEMENTED: return "Something in FMOD hasn't been implemented when it should be! contact support!"; + case FMOD_ERR_UNINITIALIZED: return "This command failed because System::init or System::setDriver was not called."; + case FMOD_ERR_UNSUPPORTED: return "A command issued was not supported by this object. Possibly a plugin without certain callbacks specified."; + case FMOD_ERR_VERSION: return "The version number of this file format is not supported."; + case FMOD_ERR_EVENT_ALREADY_LOADED: return "The specified bank has already been loaded."; + case FMOD_ERR_EVENT_LIVEUPDATE_BUSY: return "The live update connection failed due to the game already being connected."; + case FMOD_ERR_EVENT_LIVEUPDATE_MISMATCH: return "The live update connection failed due to the game data being out of sync with the tool."; + case FMOD_ERR_EVENT_LIVEUPDATE_TIMEOUT: return "The live update connection timed out."; + case FMOD_ERR_EVENT_NOTFOUND: return "The requested event, parameter, bus or vca could not be found."; + case FMOD_ERR_STUDIO_UNINITIALIZED: return "The Studio::System object is not yet initialized."; + case FMOD_ERR_STUDIO_NOT_LOADED: return "The specified resource is not loaded, so it can't be unloaded."; + case FMOD_ERR_INVALID_STRING: return "An invalid string was passed to this function."; + case FMOD_ERR_ALREADY_LOCKED: return "The specified resource is already locked."; + case FMOD_ERR_NOT_LOCKED: return "The specified resource is not locked, so it can't be unlocked."; + case FMOD_ERR_RECORD_DISCONNECTED: return "The specified recording driver has been disconnected."; + case FMOD_ERR_TOOMANYSAMPLES: return "The length provided exceeds the allowable limit."; + default : return "Unknown error."; + }; +} + +#endif diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_output.h b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_output.h new file mode 100644 index 0000000..31e4bb4 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_output.h @@ -0,0 +1,129 @@ +/* ======================================================================================== */ +/* FMOD Core API - output development header file. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* */ +/* Use this header if you are wanting to develop your own output plugin to use with */ +/* FMOD's output system. With this header you can make your own output plugin that FMOD */ +/* can register and use. See the documentation and examples on how to make a working */ +/* plugin. */ +/* */ +/* For more detail visit: */ +/* https://fmod.com/resources/documentation-api?version=2.0&page=plugin-api-output.html */ +/* ======================================================================================== */ +#ifndef _FMOD_OUTPUT_H +#define _FMOD_OUTPUT_H + +typedef struct FMOD_OUTPUT_STATE FMOD_OUTPUT_STATE; +typedef struct FMOD_OUTPUT_OBJECT3DINFO FMOD_OUTPUT_OBJECT3DINFO; + +/* + Output constants +*/ +#define FMOD_OUTPUT_PLUGIN_VERSION 4 + +typedef unsigned int FMOD_OUTPUT_METHOD; +#define FMOD_OUTPUT_METHOD_MIX_DIRECT 0 +#define FMOD_OUTPUT_METHOD_POLLING 1 +#define FMOD_OUTPUT_METHOD_MIX_BUFFERED 2 + +/* + Output callbacks +*/ +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_GETNUMDRIVERS_CALLBACK) (FMOD_OUTPUT_STATE *output_state, int *numdrivers); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_GETDRIVERINFO_CALLBACK) (FMOD_OUTPUT_STATE *output_state, int id, char *name, int namelen, FMOD_GUID *guid, int *systemrate, FMOD_SPEAKERMODE *speakermode, int *speakermodechannels); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_INIT_CALLBACK) (FMOD_OUTPUT_STATE *output_state, int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, FMOD_SPEAKERMODE *speakermode, int *speakermodechannels, FMOD_SOUND_FORMAT *outputformat, int dspbufferlength, int dspnumbuffers, void *extradriverdata); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_START_CALLBACK) (FMOD_OUTPUT_STATE *output_state); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_STOP_CALLBACK) (FMOD_OUTPUT_STATE *output_state); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_CLOSE_CALLBACK) (FMOD_OUTPUT_STATE *output_state); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_UPDATE_CALLBACK) (FMOD_OUTPUT_STATE *output_state); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_GETHANDLE_CALLBACK) (FMOD_OUTPUT_STATE *output_state, void **handle); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_GETPOSITION_CALLBACK) (FMOD_OUTPUT_STATE *output_state, unsigned int *pcm); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_LOCK_CALLBACK) (FMOD_OUTPUT_STATE *output_state, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_UNLOCK_CALLBACK) (FMOD_OUTPUT_STATE *output_state, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_MIXER_CALLBACK) (FMOD_OUTPUT_STATE *output_state); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_OBJECT3DGETINFO_CALLBACK) (FMOD_OUTPUT_STATE *output_state, int *maxhardwareobjects); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_OBJECT3DALLOC_CALLBACK) (FMOD_OUTPUT_STATE *output_state, void **object3d); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_OBJECT3DFREE_CALLBACK) (FMOD_OUTPUT_STATE *output_state, void *object3d); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_OBJECT3DUPDATE_CALLBACK) (FMOD_OUTPUT_STATE *output_state, void *object3d, const FMOD_OUTPUT_OBJECT3DINFO *info); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_OPENPORT_CALLBACK) (FMOD_OUTPUT_STATE *output_state, FMOD_PORT_TYPE portType, FMOD_PORT_INDEX portIndex, int *portId, int *portRate, int *portChannels, FMOD_SOUND_FORMAT *portFormat); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_CLOSEPORT_CALLBACK) (FMOD_OUTPUT_STATE *output_state, int portId); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_DEVICELISTCHANGED_CALLBACK)(FMOD_OUTPUT_STATE *output_state); + +/* + Output functions +*/ +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_READFROMMIXER_FUNC) (FMOD_OUTPUT_STATE *output_state, void *buffer, unsigned int length); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_COPYPORT_FUNC) (FMOD_OUTPUT_STATE *output_state, int portId, void *buffer, unsigned int length); +typedef FMOD_RESULT (F_CALL *FMOD_OUTPUT_REQUESTRESET_FUNC) (FMOD_OUTPUT_STATE *output_state); +typedef void * (F_CALL *FMOD_OUTPUT_ALLOC_FUNC) (unsigned int size, unsigned int align, const char *file, int line); +typedef void (F_CALL *FMOD_OUTPUT_FREE_FUNC) (void *ptr, const char *file, int line); +typedef void (F_CALL *FMOD_OUTPUT_LOG_FUNC) (FMOD_DEBUG_FLAGS level, const char *file, int line, const char *function, const char *string, ...); + +/* + Output structures +*/ +typedef struct FMOD_OUTPUT_DESCRIPTION +{ + unsigned int apiversion; + const char *name; + unsigned int version; + FMOD_OUTPUT_METHOD polling; /* This will become "method" on the next major version */ + FMOD_OUTPUT_GETNUMDRIVERS_CALLBACK getnumdrivers; + FMOD_OUTPUT_GETDRIVERINFO_CALLBACK getdriverinfo; + FMOD_OUTPUT_INIT_CALLBACK init; + FMOD_OUTPUT_START_CALLBACK start; + FMOD_OUTPUT_STOP_CALLBACK stop; + FMOD_OUTPUT_CLOSE_CALLBACK close; + FMOD_OUTPUT_UPDATE_CALLBACK update; + FMOD_OUTPUT_GETHANDLE_CALLBACK gethandle; + FMOD_OUTPUT_GETPOSITION_CALLBACK getposition; + FMOD_OUTPUT_LOCK_CALLBACK lock; + FMOD_OUTPUT_UNLOCK_CALLBACK unlock; + FMOD_OUTPUT_MIXER_CALLBACK mixer; + FMOD_OUTPUT_OBJECT3DGETINFO_CALLBACK object3dgetinfo; + FMOD_OUTPUT_OBJECT3DALLOC_CALLBACK object3dalloc; + FMOD_OUTPUT_OBJECT3DFREE_CALLBACK object3dfree; + FMOD_OUTPUT_OBJECT3DUPDATE_CALLBACK object3dupdate; + FMOD_OUTPUT_OPENPORT_CALLBACK openport; + FMOD_OUTPUT_CLOSEPORT_CALLBACK closeport; + FMOD_OUTPUT_DEVICELISTCHANGED_CALLBACK devicelistchanged; +} FMOD_OUTPUT_DESCRIPTION; + +struct FMOD_OUTPUT_STATE +{ + void *plugindata; + FMOD_OUTPUT_READFROMMIXER_FUNC readfrommixer; + FMOD_OUTPUT_ALLOC_FUNC alloc; + FMOD_OUTPUT_FREE_FUNC free; + FMOD_OUTPUT_LOG_FUNC log; + FMOD_OUTPUT_COPYPORT_FUNC copyport; + FMOD_OUTPUT_REQUESTRESET_FUNC requestreset; +}; + +struct FMOD_OUTPUT_OBJECT3DINFO +{ + float *buffer; + unsigned int bufferlength; + FMOD_VECTOR position; + float gain; + float spread; + float priority; +}; + +/* + Output macros +*/ +#define FMOD_OUTPUT_READFROMMIXER(_state, _buffer, _length) \ + (_state)->readfrommixer(_state, _buffer, _length) +#define FMOD_OUTPUT_ALLOC(_state, _size, _align) \ + (_state)->alloc(_size, _align, __FILE__, __LINE__) +#define FMOD_OUTPUT_FREE(_state, _ptr) \ + (_state)->free(_ptr, __FILE__, __LINE__) +#define FMOD_OUTPUT_LOG(_state, _level, _location, _format, ...) \ + (_state)->log(_level, __FILE__, __LINE__, _location, _format, __VA_ARGS__) +#define FMOD_OUTPUT_COPYPORT(_state, _id, _buffer, _length) \ + (_state)->copyport(_state, _id, _buffer, _length) +#define FMOD_OUTPUT_REQUESTRESET(_state) \ + (_state)->requestreset(_state) + +#endif /* _FMOD_OUTPUT_H */ diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_studio.h b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_studio.h new file mode 100644 index 0000000..34ab971 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_studio.h @@ -0,0 +1,236 @@ +/* ======================================================================================== */ +/* FMOD Studio API - C header file. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* */ +/* Use this header in conjunction with fmod_studio_common.h (which contains all the */ +/* constants / callbacks) to develop using the C language. */ +/* */ +/* For more detail visit: */ +/* https://fmod.com/resources/documentation-api?version=2.0&page=page=studio-api.html */ +/* ======================================================================================== */ +#ifndef FMOD_STUDIO_H +#define FMOD_STUDIO_H + +#include "fmod_studio_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + Global +*/ +FMOD_RESULT F_API FMOD_Studio_ParseID(const char *idstring, FMOD_GUID *id); +FMOD_RESULT F_API FMOD_Studio_System_Create(FMOD_STUDIO_SYSTEM **system, unsigned int headerversion); + +/* + System +*/ +FMOD_BOOL F_API FMOD_Studio_System_IsValid(FMOD_STUDIO_SYSTEM *system); +FMOD_RESULT F_API FMOD_Studio_System_SetAdvancedSettings(FMOD_STUDIO_SYSTEM *system, FMOD_STUDIO_ADVANCEDSETTINGS *settings); +FMOD_RESULT F_API FMOD_Studio_System_GetAdvancedSettings(FMOD_STUDIO_SYSTEM *system, FMOD_STUDIO_ADVANCEDSETTINGS *settings); +FMOD_RESULT F_API FMOD_Studio_System_Initialize(FMOD_STUDIO_SYSTEM *system, int maxchannels, FMOD_STUDIO_INITFLAGS studioflags, FMOD_INITFLAGS flags, void *extradriverdata); +FMOD_RESULT F_API FMOD_Studio_System_Release(FMOD_STUDIO_SYSTEM *system); +FMOD_RESULT F_API FMOD_Studio_System_Update(FMOD_STUDIO_SYSTEM *system); +FMOD_RESULT F_API FMOD_Studio_System_GetCoreSystem(FMOD_STUDIO_SYSTEM *system, FMOD_SYSTEM **coresystem); +FMOD_RESULT F_API FMOD_Studio_System_GetEvent(FMOD_STUDIO_SYSTEM *system, const char *pathOrID, FMOD_STUDIO_EVENTDESCRIPTION **event); +FMOD_RESULT F_API FMOD_Studio_System_GetBus(FMOD_STUDIO_SYSTEM *system, const char *pathOrID, FMOD_STUDIO_BUS **bus); +FMOD_RESULT F_API FMOD_Studio_System_GetVCA(FMOD_STUDIO_SYSTEM *system, const char *pathOrID, FMOD_STUDIO_VCA **vca); +FMOD_RESULT F_API FMOD_Studio_System_GetBank(FMOD_STUDIO_SYSTEM *system, const char *pathOrID, FMOD_STUDIO_BANK **bank); +FMOD_RESULT F_API FMOD_Studio_System_GetEventByID(FMOD_STUDIO_SYSTEM *system, const FMOD_GUID *id, FMOD_STUDIO_EVENTDESCRIPTION **event); +FMOD_RESULT F_API FMOD_Studio_System_GetBusByID(FMOD_STUDIO_SYSTEM *system, const FMOD_GUID *id, FMOD_STUDIO_BUS **bus); +FMOD_RESULT F_API FMOD_Studio_System_GetVCAByID(FMOD_STUDIO_SYSTEM *system, const FMOD_GUID *id, FMOD_STUDIO_VCA **vca); +FMOD_RESULT F_API FMOD_Studio_System_GetBankByID(FMOD_STUDIO_SYSTEM *system, const FMOD_GUID *id, FMOD_STUDIO_BANK **bank); +FMOD_RESULT F_API FMOD_Studio_System_GetSoundInfo(FMOD_STUDIO_SYSTEM *system, const char *key, FMOD_STUDIO_SOUND_INFO *info); +FMOD_RESULT F_API FMOD_Studio_System_GetParameterDescriptionByName(FMOD_STUDIO_SYSTEM *system, const char *name, FMOD_STUDIO_PARAMETER_DESCRIPTION *parameter); +FMOD_RESULT F_API FMOD_Studio_System_GetParameterDescriptionByID(FMOD_STUDIO_SYSTEM *system, FMOD_STUDIO_PARAMETER_ID id, FMOD_STUDIO_PARAMETER_DESCRIPTION *parameter); +FMOD_RESULT F_API FMOD_Studio_System_GetParameterByID(FMOD_STUDIO_SYSTEM *system, FMOD_STUDIO_PARAMETER_ID id, float *value, float *finalvalue); +FMOD_RESULT F_API FMOD_Studio_System_SetParameterByID(FMOD_STUDIO_SYSTEM *system, FMOD_STUDIO_PARAMETER_ID id, float value, FMOD_BOOL ignoreseekspeed); +FMOD_RESULT F_API FMOD_Studio_System_SetParametersByIDs(FMOD_STUDIO_SYSTEM *system, const FMOD_STUDIO_PARAMETER_ID *ids, float *values, int count, FMOD_BOOL ignoreseekspeed); +FMOD_RESULT F_API FMOD_Studio_System_GetParameterByName(FMOD_STUDIO_SYSTEM *system, const char *name, float *value, float *finalvalue); +FMOD_RESULT F_API FMOD_Studio_System_SetParameterByName(FMOD_STUDIO_SYSTEM *system, const char *name, float value, FMOD_BOOL ignoreseekspeed); +FMOD_RESULT F_API FMOD_Studio_System_LookupID(FMOD_STUDIO_SYSTEM *system, const char *path, FMOD_GUID *id); +FMOD_RESULT F_API FMOD_Studio_System_LookupPath(FMOD_STUDIO_SYSTEM *system, const FMOD_GUID *id, char *path, int size, int *retrieved); +FMOD_RESULT F_API FMOD_Studio_System_GetNumListeners(FMOD_STUDIO_SYSTEM *system, int *numlisteners); +FMOD_RESULT F_API FMOD_Studio_System_SetNumListeners(FMOD_STUDIO_SYSTEM *system, int numlisteners); +FMOD_RESULT F_API FMOD_Studio_System_GetListenerAttributes(FMOD_STUDIO_SYSTEM *system, int index, FMOD_3D_ATTRIBUTES *attributes); +FMOD_RESULT F_API FMOD_Studio_System_SetListenerAttributes(FMOD_STUDIO_SYSTEM *system, int index, FMOD_3D_ATTRIBUTES *attributes); +FMOD_RESULT F_API FMOD_Studio_System_GetListenerWeight(FMOD_STUDIO_SYSTEM *system, int index, float *weight); +FMOD_RESULT F_API FMOD_Studio_System_SetListenerWeight(FMOD_STUDIO_SYSTEM *system, int index, float weight); +FMOD_RESULT F_API FMOD_Studio_System_LoadBankFile(FMOD_STUDIO_SYSTEM *system, const char *filename, FMOD_STUDIO_LOAD_BANK_FLAGS flags, FMOD_STUDIO_BANK **bank); +FMOD_RESULT F_API FMOD_Studio_System_LoadBankMemory(FMOD_STUDIO_SYSTEM *system, const char *buffer, int length, FMOD_STUDIO_LOAD_MEMORY_MODE mode, FMOD_STUDIO_LOAD_BANK_FLAGS flags, FMOD_STUDIO_BANK **bank); +FMOD_RESULT F_API FMOD_Studio_System_LoadBankCustom(FMOD_STUDIO_SYSTEM *system, const FMOD_STUDIO_BANK_INFO *info, FMOD_STUDIO_LOAD_BANK_FLAGS flags, FMOD_STUDIO_BANK **bank); +FMOD_RESULT F_API FMOD_Studio_System_RegisterPlugin(FMOD_STUDIO_SYSTEM *system, const FMOD_DSP_DESCRIPTION *description); +FMOD_RESULT F_API FMOD_Studio_System_UnregisterPlugin(FMOD_STUDIO_SYSTEM *system, const char *name); +FMOD_RESULT F_API FMOD_Studio_System_UnloadAll(FMOD_STUDIO_SYSTEM *system); +FMOD_RESULT F_API FMOD_Studio_System_FlushCommands(FMOD_STUDIO_SYSTEM *system); +FMOD_RESULT F_API FMOD_Studio_System_FlushSampleLoading(FMOD_STUDIO_SYSTEM *system); +FMOD_RESULT F_API FMOD_Studio_System_StartCommandCapture(FMOD_STUDIO_SYSTEM *system, const char *filename, FMOD_STUDIO_COMMANDCAPTURE_FLAGS flags); +FMOD_RESULT F_API FMOD_Studio_System_StopCommandCapture(FMOD_STUDIO_SYSTEM *system); +FMOD_RESULT F_API FMOD_Studio_System_LoadCommandReplay(FMOD_STUDIO_SYSTEM *system, const char *filename, FMOD_STUDIO_COMMANDREPLAY_FLAGS flags, FMOD_STUDIO_COMMANDREPLAY **replay); +FMOD_RESULT F_API FMOD_Studio_System_GetBankCount(FMOD_STUDIO_SYSTEM *system, int *count); +FMOD_RESULT F_API FMOD_Studio_System_GetBankList(FMOD_STUDIO_SYSTEM *system, FMOD_STUDIO_BANK **array, int capacity, int *count); +FMOD_RESULT F_API FMOD_Studio_System_GetParameterDescriptionCount(FMOD_STUDIO_SYSTEM *system, int *count); +FMOD_RESULT F_API FMOD_Studio_System_GetParameterDescriptionList(FMOD_STUDIO_SYSTEM *system, FMOD_STUDIO_PARAMETER_DESCRIPTION *array, int capacity, int *count); +FMOD_RESULT F_API FMOD_Studio_System_GetCPUUsage(FMOD_STUDIO_SYSTEM *system, FMOD_STUDIO_CPU_USAGE *usage); +FMOD_RESULT F_API FMOD_Studio_System_GetBufferUsage(FMOD_STUDIO_SYSTEM *system, FMOD_STUDIO_BUFFER_USAGE *usage); +FMOD_RESULT F_API FMOD_Studio_System_ResetBufferUsage(FMOD_STUDIO_SYSTEM *system); +FMOD_RESULT F_API FMOD_Studio_System_SetCallback(FMOD_STUDIO_SYSTEM *system, FMOD_STUDIO_SYSTEM_CALLBACK callback, FMOD_STUDIO_SYSTEM_CALLBACK_TYPE callbackmask); +FMOD_RESULT F_API FMOD_Studio_System_SetUserData(FMOD_STUDIO_SYSTEM *system, void *userdata); +FMOD_RESULT F_API FMOD_Studio_System_GetUserData(FMOD_STUDIO_SYSTEM *system, void **userdata); +FMOD_RESULT F_API FMOD_Studio_System_GetMemoryUsage(FMOD_STUDIO_SYSTEM *system, FMOD_STUDIO_MEMORY_USAGE *memoryusage); + +/* + EventDescription +*/ +FMOD_BOOL F_API FMOD_Studio_EventDescription_IsValid(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetID(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, FMOD_GUID *id); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetPath(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, char *path, int size, int *retrieved); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetParameterDescriptionCount(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, int *count); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetParameterDescriptionByIndex(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, int index, FMOD_STUDIO_PARAMETER_DESCRIPTION *parameter); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetParameterDescriptionByName(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, const char *name, FMOD_STUDIO_PARAMETER_DESCRIPTION *parameter); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetParameterDescriptionByID(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, FMOD_STUDIO_PARAMETER_ID id, FMOD_STUDIO_PARAMETER_DESCRIPTION *parameter); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetUserPropertyCount(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, int *count); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetUserPropertyByIndex(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, int index, FMOD_STUDIO_USER_PROPERTY *property); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetUserProperty(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, const char *name, FMOD_STUDIO_USER_PROPERTY *property); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetLength(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, int *length); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetMinimumDistance(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, float *distance); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetMaximumDistance(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, float *distance); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetSoundSize(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, float *size); +FMOD_RESULT F_API FMOD_Studio_EventDescription_IsSnapshot(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, FMOD_BOOL *snapshot); +FMOD_RESULT F_API FMOD_Studio_EventDescription_IsOneshot(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, FMOD_BOOL *oneshot); +FMOD_RESULT F_API FMOD_Studio_EventDescription_IsStream(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, FMOD_BOOL *isStream); +FMOD_RESULT F_API FMOD_Studio_EventDescription_Is3D(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, FMOD_BOOL *is3D); +FMOD_RESULT F_API FMOD_Studio_EventDescription_HasCue(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, FMOD_BOOL *cue); +FMOD_RESULT F_API FMOD_Studio_EventDescription_CreateInstance(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, FMOD_STUDIO_EVENTINSTANCE **instance); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetInstanceCount(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, int *count); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetInstanceList(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, FMOD_STUDIO_EVENTINSTANCE **array, int capacity, int *count); +FMOD_RESULT F_API FMOD_Studio_EventDescription_LoadSampleData(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription); +FMOD_RESULT F_API FMOD_Studio_EventDescription_UnloadSampleData(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetSampleLoadingState(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, FMOD_STUDIO_LOADING_STATE *state); +FMOD_RESULT F_API FMOD_Studio_EventDescription_ReleaseAllInstances(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription); +FMOD_RESULT F_API FMOD_Studio_EventDescription_SetCallback(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, FMOD_STUDIO_EVENT_CALLBACK callback, FMOD_STUDIO_EVENT_CALLBACK_TYPE callbackmask); +FMOD_RESULT F_API FMOD_Studio_EventDescription_GetUserData(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, void **userdata); +FMOD_RESULT F_API FMOD_Studio_EventDescription_SetUserData(FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, void *userdata); + +/* + EventInstance +*/ +FMOD_BOOL F_API FMOD_Studio_EventInstance_IsValid(FMOD_STUDIO_EVENTINSTANCE *eventinstance); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetDescription(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_STUDIO_EVENTDESCRIPTION **description); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetVolume(FMOD_STUDIO_EVENTINSTANCE *eventinstance, float *volume, float *finalvolume); +FMOD_RESULT F_API FMOD_Studio_EventInstance_SetVolume(FMOD_STUDIO_EVENTINSTANCE *eventinstance, float volume); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetPitch(FMOD_STUDIO_EVENTINSTANCE *eventinstance, float *pitch, float *finalpitch); +FMOD_RESULT F_API FMOD_Studio_EventInstance_SetPitch(FMOD_STUDIO_EVENTINSTANCE *eventinstance, float pitch); +FMOD_RESULT F_API FMOD_Studio_EventInstance_Get3DAttributes(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_3D_ATTRIBUTES *attributes); +FMOD_RESULT F_API FMOD_Studio_EventInstance_Set3DAttributes(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_3D_ATTRIBUTES *attributes); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetListenerMask(FMOD_STUDIO_EVENTINSTANCE *eventinstance, unsigned int *mask); +FMOD_RESULT F_API FMOD_Studio_EventInstance_SetListenerMask(FMOD_STUDIO_EVENTINSTANCE *eventinstance, unsigned int mask); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetProperty(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_STUDIO_EVENT_PROPERTY index, float *value); +FMOD_RESULT F_API FMOD_Studio_EventInstance_SetProperty(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_STUDIO_EVENT_PROPERTY index, float value); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetReverbLevel(FMOD_STUDIO_EVENTINSTANCE *eventinstance, int index, float *level); +FMOD_RESULT F_API FMOD_Studio_EventInstance_SetReverbLevel(FMOD_STUDIO_EVENTINSTANCE *eventinstance, int index, float level); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetPaused(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_BOOL *paused); +FMOD_RESULT F_API FMOD_Studio_EventInstance_SetPaused(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_BOOL paused); +FMOD_RESULT F_API FMOD_Studio_EventInstance_Start(FMOD_STUDIO_EVENTINSTANCE *eventinstance); +FMOD_RESULT F_API FMOD_Studio_EventInstance_Stop(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_STUDIO_STOP_MODE mode); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetTimelinePosition(FMOD_STUDIO_EVENTINSTANCE *eventinstance, int *position); +FMOD_RESULT F_API FMOD_Studio_EventInstance_SetTimelinePosition(FMOD_STUDIO_EVENTINSTANCE *eventinstance, int position); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetPlaybackState(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_STUDIO_PLAYBACK_STATE *state); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetChannelGroup(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_CHANNELGROUP **group); +FMOD_RESULT F_API FMOD_Studio_EventInstance_Release(FMOD_STUDIO_EVENTINSTANCE *eventinstance); +FMOD_RESULT F_API FMOD_Studio_EventInstance_IsVirtual(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_BOOL *virtualstate); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetParameterByName(FMOD_STUDIO_EVENTINSTANCE *eventinstance, const char *name, float *value, float *finalvalue); +FMOD_RESULT F_API FMOD_Studio_EventInstance_SetParameterByName(FMOD_STUDIO_EVENTINSTANCE *eventinstance, const char *name, float value, FMOD_BOOL ignoreseekspeed); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetParameterByID(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_STUDIO_PARAMETER_ID id, float *value, float *finalvalue); +FMOD_RESULT F_API FMOD_Studio_EventInstance_SetParameterByID(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_STUDIO_PARAMETER_ID id, float value, FMOD_BOOL ignoreseekspeed); +FMOD_RESULT F_API FMOD_Studio_EventInstance_SetParametersByIDs(FMOD_STUDIO_EVENTINSTANCE *eventinstance, const FMOD_STUDIO_PARAMETER_ID *ids, float *values, int count, FMOD_BOOL ignoreseekspeed); +FMOD_RESULT F_API FMOD_Studio_EventInstance_TriggerCue(FMOD_STUDIO_EVENTINSTANCE *eventinstance); +FMOD_RESULT F_API FMOD_Studio_EventInstance_SetCallback(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_STUDIO_EVENT_CALLBACK callback, FMOD_STUDIO_EVENT_CALLBACK_TYPE callbackmask); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetUserData(FMOD_STUDIO_EVENTINSTANCE *eventinstance, void **userdata); +FMOD_RESULT F_API FMOD_Studio_EventInstance_SetUserData(FMOD_STUDIO_EVENTINSTANCE *eventinstance, void *userdata); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetCPUUsage(FMOD_STUDIO_EVENTINSTANCE *eventinstance, unsigned int *exclusive, unsigned int *inclusive); +FMOD_RESULT F_API FMOD_Studio_EventInstance_GetMemoryUsage(FMOD_STUDIO_EVENTINSTANCE *eventinstance, FMOD_STUDIO_MEMORY_USAGE *memoryusage); + +/* + Bus +*/ +FMOD_BOOL F_API FMOD_Studio_Bus_IsValid(FMOD_STUDIO_BUS *bus); +FMOD_RESULT F_API FMOD_Studio_Bus_GetID(FMOD_STUDIO_BUS *bus, FMOD_GUID *id); +FMOD_RESULT F_API FMOD_Studio_Bus_GetPath(FMOD_STUDIO_BUS *bus, char *path, int size, int *retrieved); +FMOD_RESULT F_API FMOD_Studio_Bus_GetVolume(FMOD_STUDIO_BUS *bus, float *volume, float *finalvolume); +FMOD_RESULT F_API FMOD_Studio_Bus_SetVolume(FMOD_STUDIO_BUS *bus, float volume); +FMOD_RESULT F_API FMOD_Studio_Bus_GetPaused(FMOD_STUDIO_BUS *bus, FMOD_BOOL *paused); +FMOD_RESULT F_API FMOD_Studio_Bus_SetPaused(FMOD_STUDIO_BUS *bus, FMOD_BOOL paused); +FMOD_RESULT F_API FMOD_Studio_Bus_GetMute(FMOD_STUDIO_BUS *bus, FMOD_BOOL *mute); +FMOD_RESULT F_API FMOD_Studio_Bus_SetMute(FMOD_STUDIO_BUS *bus, FMOD_BOOL mute); +FMOD_RESULT F_API FMOD_Studio_Bus_StopAllEvents(FMOD_STUDIO_BUS *bus, FMOD_STUDIO_STOP_MODE mode); +FMOD_RESULT F_API FMOD_Studio_Bus_LockChannelGroup(FMOD_STUDIO_BUS *bus); +FMOD_RESULT F_API FMOD_Studio_Bus_UnlockChannelGroup(FMOD_STUDIO_BUS *bus); +FMOD_RESULT F_API FMOD_Studio_Bus_GetChannelGroup(FMOD_STUDIO_BUS *bus, FMOD_CHANNELGROUP **group); +FMOD_RESULT F_API FMOD_Studio_Bus_GetCPUUsage(FMOD_STUDIO_BUS *bus, unsigned int *exclusive, unsigned int *inclusive); +FMOD_RESULT F_API FMOD_Studio_Bus_GetMemoryUsage(FMOD_STUDIO_BUS *bus, FMOD_STUDIO_MEMORY_USAGE *memoryusage); + +/* + VCA +*/ +FMOD_BOOL F_API FMOD_Studio_VCA_IsValid(FMOD_STUDIO_VCA *vca); +FMOD_RESULT F_API FMOD_Studio_VCA_GetID(FMOD_STUDIO_VCA *vca, FMOD_GUID *id); +FMOD_RESULT F_API FMOD_Studio_VCA_GetPath(FMOD_STUDIO_VCA *vca, char *path, int size, int *retrieved); +FMOD_RESULT F_API FMOD_Studio_VCA_GetVolume(FMOD_STUDIO_VCA *vca, float *volume, float *finalvolume); +FMOD_RESULT F_API FMOD_Studio_VCA_SetVolume(FMOD_STUDIO_VCA *vca, float volume); + +/* + Bank +*/ +FMOD_BOOL F_API FMOD_Studio_Bank_IsValid(FMOD_STUDIO_BANK *bank); +FMOD_RESULT F_API FMOD_Studio_Bank_GetID(FMOD_STUDIO_BANK *bank, FMOD_GUID *id); +FMOD_RESULT F_API FMOD_Studio_Bank_GetPath(FMOD_STUDIO_BANK *bank, char *path, int size, int *retrieved); +FMOD_RESULT F_API FMOD_Studio_Bank_Unload(FMOD_STUDIO_BANK *bank); +FMOD_RESULT F_API FMOD_Studio_Bank_LoadSampleData(FMOD_STUDIO_BANK *bank); +FMOD_RESULT F_API FMOD_Studio_Bank_UnloadSampleData(FMOD_STUDIO_BANK *bank); +FMOD_RESULT F_API FMOD_Studio_Bank_GetLoadingState(FMOD_STUDIO_BANK *bank, FMOD_STUDIO_LOADING_STATE *state); +FMOD_RESULT F_API FMOD_Studio_Bank_GetSampleLoadingState(FMOD_STUDIO_BANK *bank, FMOD_STUDIO_LOADING_STATE *state); +FMOD_RESULT F_API FMOD_Studio_Bank_GetStringCount(FMOD_STUDIO_BANK *bank, int *count); +FMOD_RESULT F_API FMOD_Studio_Bank_GetStringInfo(FMOD_STUDIO_BANK *bank, int index, FMOD_GUID *id, char *path, int size, int *retrieved); +FMOD_RESULT F_API FMOD_Studio_Bank_GetEventCount(FMOD_STUDIO_BANK *bank, int *count); +FMOD_RESULT F_API FMOD_Studio_Bank_GetEventList(FMOD_STUDIO_BANK *bank, FMOD_STUDIO_EVENTDESCRIPTION **array, int capacity, int *count); +FMOD_RESULT F_API FMOD_Studio_Bank_GetBusCount(FMOD_STUDIO_BANK *bank, int *count); +FMOD_RESULT F_API FMOD_Studio_Bank_GetBusList(FMOD_STUDIO_BANK *bank, FMOD_STUDIO_BUS **array, int capacity, int *count); +FMOD_RESULT F_API FMOD_Studio_Bank_GetVCACount(FMOD_STUDIO_BANK *bank, int *count); +FMOD_RESULT F_API FMOD_Studio_Bank_GetVCAList(FMOD_STUDIO_BANK *bank, FMOD_STUDIO_VCA **array, int capacity, int *count); +FMOD_RESULT F_API FMOD_Studio_Bank_GetUserData(FMOD_STUDIO_BANK *bank, void **userdata); +FMOD_RESULT F_API FMOD_Studio_Bank_SetUserData(FMOD_STUDIO_BANK *bank, void *userdata); + +/* + Command playback information +*/ +FMOD_BOOL F_API FMOD_Studio_CommandReplay_IsValid(FMOD_STUDIO_COMMANDREPLAY *replay); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_GetSystem(FMOD_STUDIO_COMMANDREPLAY *replay, FMOD_STUDIO_SYSTEM **system); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_GetLength(FMOD_STUDIO_COMMANDREPLAY *replay, float *length); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_GetCommandCount(FMOD_STUDIO_COMMANDREPLAY *replay, int *count); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_GetCommandInfo(FMOD_STUDIO_COMMANDREPLAY *replay, int commandindex, FMOD_STUDIO_COMMAND_INFO *info); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_GetCommandString(FMOD_STUDIO_COMMANDREPLAY *replay, int commandindex, char *buffer, int length); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_GetCommandAtTime(FMOD_STUDIO_COMMANDREPLAY *replay, float time, int *commandindex); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_SetBankPath(FMOD_STUDIO_COMMANDREPLAY *replay, const char *bankPath); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_Start(FMOD_STUDIO_COMMANDREPLAY *replay); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_Stop(FMOD_STUDIO_COMMANDREPLAY *replay); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_SeekToTime(FMOD_STUDIO_COMMANDREPLAY *replay, float time); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_SeekToCommand(FMOD_STUDIO_COMMANDREPLAY *replay, int commandindex); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_GetPaused(FMOD_STUDIO_COMMANDREPLAY *replay, FMOD_BOOL *paused); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_SetPaused(FMOD_STUDIO_COMMANDREPLAY *replay, FMOD_BOOL paused); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_GetPlaybackState(FMOD_STUDIO_COMMANDREPLAY *replay, FMOD_STUDIO_PLAYBACK_STATE *state); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_GetCurrentCommand(FMOD_STUDIO_COMMANDREPLAY *replay, int *commandindex, float *currenttime); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_Release(FMOD_STUDIO_COMMANDREPLAY *replay); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_SetFrameCallback(FMOD_STUDIO_COMMANDREPLAY *replay, FMOD_STUDIO_COMMANDREPLAY_FRAME_CALLBACK callback); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_SetLoadBankCallback(FMOD_STUDIO_COMMANDREPLAY *replay, FMOD_STUDIO_COMMANDREPLAY_LOAD_BANK_CALLBACK callback); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_SetCreateInstanceCallback(FMOD_STUDIO_COMMANDREPLAY *replay, FMOD_STUDIO_COMMANDREPLAY_CREATE_INSTANCE_CALLBACK callback); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_GetUserData(FMOD_STUDIO_COMMANDREPLAY *replay, void **userdata); +FMOD_RESULT F_API FMOD_Studio_CommandReplay_SetUserData(FMOD_STUDIO_COMMANDREPLAY *replay, void *userdata); + +#ifdef __cplusplus +} +#endif + +#endif /* FMOD_STUDIO_H */ diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_studio.hpp b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_studio.hpp new file mode 100644 index 0000000..f967ec1 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_studio.hpp @@ -0,0 +1,387 @@ +/* ======================================================================================== */ +/* FMOD Studio API - C++ header file. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* */ +/* Use this header in conjunction with fmod_studio_common.h (which contains all the */ +/* constants / callbacks) to develop using the C++ language. */ +/* */ +/* For more detail visit: */ +/* https://fmod.com/resources/documentation-api?version=2.0&page=page=studio-api.html */ +/* ======================================================================================== */ +#ifndef FMOD_STUDIO_HPP +#define FMOD_STUDIO_HPP + +#include "fmod_studio_common.h" +#include "fmod_studio.h" + +#include "fmod.hpp" + +namespace FMOD +{ + +namespace Studio +{ + typedef FMOD_GUID ID; // Deprecated. Please use FMOD_GUID type. + + class System; + class EventDescription; + class EventInstance; + class Bus; + class VCA; + class Bank; + class CommandReplay; + + inline FMOD_RESULT parseID(const char *idstring, FMOD_GUID *id) { return FMOD_Studio_ParseID(idstring, id); } + + class System + { + private: + // Constructor made private so user cannot statically instance a System class. System::create must be used. + System(); + System(const System &); + + public: + static FMOD_RESULT F_API create(System **system, unsigned int headerversion = FMOD_VERSION); + FMOD_RESULT F_API setAdvancedSettings(FMOD_STUDIO_ADVANCEDSETTINGS *settings); + FMOD_RESULT F_API getAdvancedSettings(FMOD_STUDIO_ADVANCEDSETTINGS *settings); + FMOD_RESULT F_API initialize(int maxchannels, FMOD_STUDIO_INITFLAGS studioflags, FMOD_INITFLAGS flags, void *extradriverdata); + FMOD_RESULT F_API release(); + + // Handle validity + bool F_API isValid() const; + + // Update processing + FMOD_RESULT F_API update(); + FMOD_RESULT F_API flushCommands(); + FMOD_RESULT F_API flushSampleLoading(); + + // Low-level API access + FMOD_RESULT F_API getCoreSystem(FMOD::System **system) const; + + // Asset retrieval + FMOD_RESULT F_API getEvent(const char *path, EventDescription **event) const; + FMOD_RESULT F_API getBus(const char *path, Bus **bus) const; + FMOD_RESULT F_API getVCA(const char *path, VCA **vca) const; + FMOD_RESULT F_API getBank(const char *path, Bank **bank) const; + FMOD_RESULT F_API getEventByID(const FMOD_GUID *id, EventDescription **event) const; + FMOD_RESULT F_API getBusByID(const FMOD_GUID *id, Bus **bus) const; + FMOD_RESULT F_API getVCAByID(const FMOD_GUID *id, VCA **vca) const; + FMOD_RESULT F_API getBankByID(const FMOD_GUID *id, Bank **bank) const; + FMOD_RESULT F_API getSoundInfo(const char *key, FMOD_STUDIO_SOUND_INFO *info) const; + FMOD_RESULT F_API getParameterDescriptionByName(const char *name, FMOD_STUDIO_PARAMETER_DESCRIPTION *parameter) const; + FMOD_RESULT F_API getParameterDescriptionByID(FMOD_STUDIO_PARAMETER_ID id, FMOD_STUDIO_PARAMETER_DESCRIPTION *parameter) const; + + // Global parameter control + FMOD_RESULT F_API getParameterByID(FMOD_STUDIO_PARAMETER_ID id, float *value, float *finalvalue = 0) const; + FMOD_RESULT F_API setParameterByID(FMOD_STUDIO_PARAMETER_ID id, float value, bool ignoreseekspeed = false); + FMOD_RESULT F_API setParametersByIDs(const FMOD_STUDIO_PARAMETER_ID *ids, float *values, int count, bool ignoreseekspeed = false); + FMOD_RESULT F_API getParameterByName(const char *name, float *value, float *finalvalue = 0) const; + FMOD_RESULT F_API setParameterByName(const char *name, float value, bool ignoreseekspeed = false); + + // Path lookup + FMOD_RESULT F_API lookupID(const char *path, FMOD_GUID *id) const; + FMOD_RESULT F_API lookupPath(const FMOD_GUID *id, char *path, int size, int *retrieved) const; + + // Listener control + FMOD_RESULT F_API getNumListeners(int *numlisteners); + FMOD_RESULT F_API setNumListeners(int numlisteners); + FMOD_RESULT F_API getListenerAttributes(int listener, FMOD_3D_ATTRIBUTES *attributes) const; + FMOD_RESULT F_API setListenerAttributes(int listener, const FMOD_3D_ATTRIBUTES *attributes); + FMOD_RESULT F_API getListenerWeight(int listener, float *weight); + FMOD_RESULT F_API setListenerWeight(int listener, float weight); + + // Bank control + FMOD_RESULT F_API loadBankFile(const char *filename, FMOD_STUDIO_LOAD_BANK_FLAGS flags, Bank **bank); + FMOD_RESULT F_API loadBankMemory(const char *buffer, int length, FMOD_STUDIO_LOAD_MEMORY_MODE mode, FMOD_STUDIO_LOAD_BANK_FLAGS flags, Bank **bank); + FMOD_RESULT F_API loadBankCustom(const FMOD_STUDIO_BANK_INFO *info, FMOD_STUDIO_LOAD_BANK_FLAGS flags, Bank **bank); + FMOD_RESULT F_API unloadAll(); + + // General functionality + FMOD_RESULT F_API getBufferUsage(FMOD_STUDIO_BUFFER_USAGE *usage) const; + FMOD_RESULT F_API resetBufferUsage(); + FMOD_RESULT F_API registerPlugin(const FMOD_DSP_DESCRIPTION *description); + FMOD_RESULT F_API unregisterPlugin(const char *name); + + // Enumeration + FMOD_RESULT F_API getBankCount(int *count) const; + FMOD_RESULT F_API getBankList(Bank **array, int capacity, int *count) const; + FMOD_RESULT F_API getParameterDescriptionCount(int *count) const; + FMOD_RESULT F_API getParameterDescriptionList(FMOD_STUDIO_PARAMETER_DESCRIPTION *array, int capacity, int *count) const; + + // Command capture and replay + FMOD_RESULT F_API startCommandCapture(const char *filename, FMOD_STUDIO_COMMANDCAPTURE_FLAGS flags); + FMOD_RESULT F_API stopCommandCapture(); + FMOD_RESULT F_API loadCommandReplay(const char *filename, FMOD_STUDIO_COMMANDREPLAY_FLAGS flags, CommandReplay **replay); + + // Callbacks + FMOD_RESULT F_API setCallback(FMOD_STUDIO_SYSTEM_CALLBACK callback, FMOD_STUDIO_SYSTEM_CALLBACK_TYPE callbackmask = FMOD_STUDIO_SYSTEM_CALLBACK_ALL); + FMOD_RESULT F_API getUserData(void **userdata) const; + FMOD_RESULT F_API setUserData(void *userdata); + + // Monitoring + FMOD_RESULT F_API getCPUUsage(FMOD_STUDIO_CPU_USAGE *usage) const; + FMOD_RESULT F_API getMemoryUsage(FMOD_STUDIO_MEMORY_USAGE *memoryusage) const; + }; + + class EventDescription + { + private: + // Constructor made private so user cannot statically instance the class. + EventDescription(); + EventDescription(const EventDescription &); + + public: + // Handle validity + bool F_API isValid() const; + + // Property access + FMOD_RESULT F_API getID(FMOD_GUID *id) const; + FMOD_RESULT F_API getPath(char *path, int size, int *retrieved) const; + FMOD_RESULT F_API getParameterDescriptionCount(int *count) const; + FMOD_RESULT F_API getParameterDescriptionByIndex(int index, FMOD_STUDIO_PARAMETER_DESCRIPTION *parameter) const; + FMOD_RESULT F_API getParameterDescriptionByName(const char *name, FMOD_STUDIO_PARAMETER_DESCRIPTION *parameter) const; + FMOD_RESULT F_API getParameterDescriptionByID(FMOD_STUDIO_PARAMETER_ID id, FMOD_STUDIO_PARAMETER_DESCRIPTION *parameter) const; + FMOD_RESULT F_API getUserPropertyCount(int *count) const; + FMOD_RESULT F_API getUserPropertyByIndex(int index, FMOD_STUDIO_USER_PROPERTY *property) const; + FMOD_RESULT F_API getUserProperty(const char *name, FMOD_STUDIO_USER_PROPERTY *property) const; + FMOD_RESULT F_API getLength(int *length) const; + FMOD_RESULT F_API getMinimumDistance(float *distance) const; + FMOD_RESULT F_API getMaximumDistance(float *distance) const; + FMOD_RESULT F_API getSoundSize(float *size) const; + + FMOD_RESULT F_API isSnapshot(bool *snapshot) const; + FMOD_RESULT F_API isOneshot(bool *oneshot) const; + FMOD_RESULT F_API isStream(bool *isStream) const; + FMOD_RESULT F_API is3D(bool *is3d) const; + FMOD_RESULT F_API hasCue(bool *cue) const; + + // Playback control + FMOD_RESULT F_API createInstance(EventInstance **instance) const; + FMOD_RESULT F_API getInstanceCount(int *count) const; + FMOD_RESULT F_API getInstanceList(EventInstance **array, int capacity, int *count) const; + + // Sample data loading control + FMOD_RESULT F_API loadSampleData(); + FMOD_RESULT F_API unloadSampleData(); + FMOD_RESULT F_API getSampleLoadingState(FMOD_STUDIO_LOADING_STATE *state) const; + + // Convenience functions + FMOD_RESULT F_API releaseAllInstances(); + + // Callbacks + FMOD_RESULT F_API setCallback(FMOD_STUDIO_EVENT_CALLBACK callback, FMOD_STUDIO_EVENT_CALLBACK_TYPE callbackmask = FMOD_STUDIO_EVENT_CALLBACK_ALL); + FMOD_RESULT F_API getUserData(void **userdata) const; + FMOD_RESULT F_API setUserData(void *userdata); + }; + + class EventInstance + { + private: + // Constructor made private so user cannot statically instance the class. + EventInstance(); + EventInstance(const EventInstance &); + + public: + // Handle validity + bool F_API isValid() const; + + // Property access + FMOD_RESULT F_API getDescription(EventDescription **description) const; + + // Playback control + FMOD_RESULT F_API getVolume(float *volume, float *finalvolume = 0) const; + FMOD_RESULT F_API setVolume(float volume); + + FMOD_RESULT F_API getPitch(float *pitch, float *finalpitch = 0) const; + FMOD_RESULT F_API setPitch(float pitch); + + FMOD_RESULT F_API get3DAttributes(FMOD_3D_ATTRIBUTES *attributes) const; + FMOD_RESULT F_API set3DAttributes(const FMOD_3D_ATTRIBUTES *attributes); + + FMOD_RESULT F_API getListenerMask(unsigned int *mask) const; + FMOD_RESULT F_API setListenerMask(unsigned int mask); + + FMOD_RESULT F_API getProperty(FMOD_STUDIO_EVENT_PROPERTY index, float *value) const; + FMOD_RESULT F_API setProperty(FMOD_STUDIO_EVENT_PROPERTY index, float value); + + FMOD_RESULT F_API getReverbLevel(int index, float *level) const; + FMOD_RESULT F_API setReverbLevel(int index, float level); + + FMOD_RESULT F_API getPaused(bool *paused) const; + FMOD_RESULT F_API setPaused(bool paused); + + FMOD_RESULT F_API start(); + FMOD_RESULT F_API stop(FMOD_STUDIO_STOP_MODE mode); + + FMOD_RESULT F_API getTimelinePosition(int *position) const; + FMOD_RESULT F_API setTimelinePosition(int position); + + FMOD_RESULT F_API getPlaybackState(FMOD_STUDIO_PLAYBACK_STATE *state) const; + + FMOD_RESULT F_API getChannelGroup(ChannelGroup **group) const; + + FMOD_RESULT F_API release(); + + FMOD_RESULT F_API isVirtual(bool *virtualstate) const; + + FMOD_RESULT F_API getParameterByID(FMOD_STUDIO_PARAMETER_ID id, float *value, float *finalvalue = 0) const; + FMOD_RESULT F_API setParameterByID(FMOD_STUDIO_PARAMETER_ID id, float value, bool ignoreseekspeed = false); + FMOD_RESULT F_API setParametersByIDs(const FMOD_STUDIO_PARAMETER_ID *ids, float *values, int count, bool ignoreseekspeed = false); + + FMOD_RESULT F_API getParameterByName(const char *name, float *value, float *finalvalue = 0) const; + FMOD_RESULT F_API setParameterByName(const char *name, float value, bool ignoreseekspeed = false); + + FMOD_RESULT F_API triggerCue(); + + // Monitoring + FMOD_RESULT F_API getCPUUsage(unsigned int *exclusive, unsigned int *inclusive) const; + FMOD_RESULT F_API getMemoryUsage(FMOD_STUDIO_MEMORY_USAGE *memoryusage) const; + + // Callbacks + FMOD_RESULT F_API setCallback(FMOD_STUDIO_EVENT_CALLBACK callback, FMOD_STUDIO_EVENT_CALLBACK_TYPE callbackmask = FMOD_STUDIO_EVENT_CALLBACK_ALL); + FMOD_RESULT F_API getUserData(void **userdata) const; + FMOD_RESULT F_API setUserData(void *userdata); + }; + + class Bus + { + private: + // Constructor made private so user cannot statically instance the class. + Bus(); + Bus(const Bus &); + + public: + // Handle validity + bool F_API isValid() const; + + // Property access + FMOD_RESULT F_API getID(FMOD_GUID *id) const; + FMOD_RESULT F_API getPath(char *path, int size, int *retrieved) const; + + // Playback control + FMOD_RESULT F_API getVolume(float *volume, float *finalvolume = 0) const; + FMOD_RESULT F_API setVolume(float volume); + + FMOD_RESULT F_API getPaused(bool *paused) const; + FMOD_RESULT F_API setPaused(bool paused); + + FMOD_RESULT F_API getMute(bool *mute) const; + FMOD_RESULT F_API setMute(bool mute); + + FMOD_RESULT F_API stopAllEvents(FMOD_STUDIO_STOP_MODE mode); + + // Low-level API access + FMOD_RESULT F_API lockChannelGroup(); + FMOD_RESULT F_API unlockChannelGroup(); + FMOD_RESULT F_API getChannelGroup(FMOD::ChannelGroup **group) const; + + // Monitoring + FMOD_RESULT F_API getCPUUsage(unsigned int *exclusive, unsigned int *inclusive) const; + FMOD_RESULT F_API getMemoryUsage(FMOD_STUDIO_MEMORY_USAGE *memoryusage) const; + }; + + class VCA + { + private: + // Constructor made private so user cannot statically instance the class. + VCA(); + VCA(const VCA &); + + public: + // Handle validity + bool F_API isValid() const; + + // Property access + FMOD_RESULT F_API getID(FMOD_GUID *id) const; + FMOD_RESULT F_API getPath(char *path, int size, int *retrieved) const; + + // Playback control + FMOD_RESULT F_API getVolume(float *volume, float *finalvolume = 0) const; + FMOD_RESULT F_API setVolume(float volume); + }; + + class Bank + { + private: + // Constructor made private so user cannot statically instance the class. + Bank(); + Bank(const Bank &); + + public: + // Handle validity + bool F_API isValid() const; + + // Property access + FMOD_RESULT F_API getID(FMOD_GUID *id) const; + FMOD_RESULT F_API getPath(char *path, int size, int *retrieved) const; + + // Loading control + FMOD_RESULT F_API unload(); + FMOD_RESULT F_API loadSampleData(); + FMOD_RESULT F_API unloadSampleData(); + + FMOD_RESULT F_API getLoadingState(FMOD_STUDIO_LOADING_STATE *state) const; + FMOD_RESULT F_API getSampleLoadingState(FMOD_STUDIO_LOADING_STATE *state) const; + + // Enumeration + FMOD_RESULT F_API getStringCount(int *count) const; + FMOD_RESULT F_API getStringInfo(int index, FMOD_GUID *id, char *path, int size, int *retrieved) const; + FMOD_RESULT F_API getEventCount(int *count) const; + FMOD_RESULT F_API getEventList(EventDescription **array, int capacity, int *count) const; + FMOD_RESULT F_API getBusCount(int *count) const; + FMOD_RESULT F_API getBusList(Bus **array, int capacity, int *count) const; + FMOD_RESULT F_API getVCACount(int *count) const; + FMOD_RESULT F_API getVCAList(VCA **array, int capacity, int *count) const; + + FMOD_RESULT F_API getUserData(void **userdata) const; + FMOD_RESULT F_API setUserData(void *userdata); + }; + + class CommandReplay + { + private: + // Constructor made private so user cannot statically instance the class. + CommandReplay(); + CommandReplay(const CommandReplay &); + + public: + // Handle validity + bool F_API isValid() const; + + // Information query + FMOD_RESULT F_API getSystem(System **system) const; + FMOD_RESULT F_API getLength(float *length) const; + + FMOD_RESULT F_API getCommandCount(int *count) const; + FMOD_RESULT F_API getCommandInfo(int commandindex, FMOD_STUDIO_COMMAND_INFO *info) const; + FMOD_RESULT F_API getCommandString(int commandindex, char *buffer, int length) const; + FMOD_RESULT F_API getCommandAtTime(float time, int *commandindex) const; + + // Playback + FMOD_RESULT F_API setBankPath(const char *bankPath); + FMOD_RESULT F_API start(); + FMOD_RESULT F_API stop(); + FMOD_RESULT F_API seekToTime(float time); + FMOD_RESULT F_API seekToCommand(int commandindex); + FMOD_RESULT F_API getPaused(bool *paused) const; + FMOD_RESULT F_API setPaused(bool paused); + FMOD_RESULT F_API getPlaybackState(FMOD_STUDIO_PLAYBACK_STATE *state) const; + FMOD_RESULT F_API getCurrentCommand(int *commandindex, float *currenttime) const; + + // Release + FMOD_RESULT F_API release(); + + // Callbacks + FMOD_RESULT F_API setFrameCallback(FMOD_STUDIO_COMMANDREPLAY_FRAME_CALLBACK callback); + FMOD_RESULT F_API setLoadBankCallback(FMOD_STUDIO_COMMANDREPLAY_LOAD_BANK_CALLBACK callback); + FMOD_RESULT F_API setCreateInstanceCallback(FMOD_STUDIO_COMMANDREPLAY_CREATE_INSTANCE_CALLBACK callback); + + FMOD_RESULT F_API getUserData(void **userdata) const; + FMOD_RESULT F_API setUserData(void *userdata); + }; + +} // namespace Studio + +} // namespace FMOD + +#endif //FMOD_STUDIO_HPP diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_studio_common.h b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_studio_common.h new file mode 100644 index 0000000..e4846a7 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMOD/fmod_studio_common.h @@ -0,0 +1,325 @@ +/* ======================================================================================== */ +/* FMOD Studio API - Common C/C++ header file. */ +/* Copyright (c), Firelight Technologies Pty, Ltd. 2004-2020. */ +/* */ +/* This header defines common enumerations, structs and callbacks that are shared between */ +/* the C and C++ interfaces. */ +/* */ +/* For more detail visit: */ +/* https://fmod.com/resources/documentation-api?version=2.0&page=page=studio-api.html */ +/* ======================================================================================== */ +#ifndef FMOD_STUDIO_COMMON_H +#define FMOD_STUDIO_COMMON_H + +#include "fmod.h" + +/* + FMOD Studio types. +*/ +typedef struct FMOD_STUDIO_SYSTEM FMOD_STUDIO_SYSTEM; +typedef struct FMOD_STUDIO_EVENTDESCRIPTION FMOD_STUDIO_EVENTDESCRIPTION; +typedef struct FMOD_STUDIO_EVENTINSTANCE FMOD_STUDIO_EVENTINSTANCE; +typedef struct FMOD_STUDIO_BUS FMOD_STUDIO_BUS; +typedef struct FMOD_STUDIO_VCA FMOD_STUDIO_VCA; +typedef struct FMOD_STUDIO_BANK FMOD_STUDIO_BANK; +typedef struct FMOD_STUDIO_COMMANDREPLAY FMOD_STUDIO_COMMANDREPLAY; + +/* + FMOD Studio constants +*/ +#define FMOD_STUDIO_LOAD_MEMORY_ALIGNMENT 32 + +typedef unsigned int FMOD_STUDIO_INITFLAGS; +#define FMOD_STUDIO_INIT_NORMAL 0x00000000 +#define FMOD_STUDIO_INIT_LIVEUPDATE 0x00000001 +#define FMOD_STUDIO_INIT_ALLOW_MISSING_PLUGINS 0x00000002 +#define FMOD_STUDIO_INIT_SYNCHRONOUS_UPDATE 0x00000004 +#define FMOD_STUDIO_INIT_DEFERRED_CALLBACKS 0x00000008 +#define FMOD_STUDIO_INIT_LOAD_FROM_UPDATE 0x00000010 +#define FMOD_STUDIO_INIT_MEMORY_TRACKING 0x00000020 + +typedef unsigned int FMOD_STUDIO_PARAMETER_FLAGS; +#define FMOD_STUDIO_PARAMETER_READONLY 0x00000001 +#define FMOD_STUDIO_PARAMETER_AUTOMATIC 0x00000002 +#define FMOD_STUDIO_PARAMETER_GLOBAL 0x00000004 + +typedef unsigned int FMOD_STUDIO_SYSTEM_CALLBACK_TYPE; +#define FMOD_STUDIO_SYSTEM_CALLBACK_PREUPDATE 0x00000001 +#define FMOD_STUDIO_SYSTEM_CALLBACK_POSTUPDATE 0x00000002 +#define FMOD_STUDIO_SYSTEM_CALLBACK_BANK_UNLOAD 0x00000004 +#define FMOD_STUDIO_SYSTEM_CALLBACK_ALL 0xFFFFFFFF + +typedef unsigned int FMOD_STUDIO_EVENT_CALLBACK_TYPE; +#define FMOD_STUDIO_EVENT_CALLBACK_CREATED 0x00000001 +#define FMOD_STUDIO_EVENT_CALLBACK_DESTROYED 0x00000002 +#define FMOD_STUDIO_EVENT_CALLBACK_STARTING 0x00000004 +#define FMOD_STUDIO_EVENT_CALLBACK_STARTED 0x00000008 +#define FMOD_STUDIO_EVENT_CALLBACK_RESTARTED 0x00000010 +#define FMOD_STUDIO_EVENT_CALLBACK_STOPPED 0x00000020 +#define FMOD_STUDIO_EVENT_CALLBACK_START_FAILED 0x00000040 +#define FMOD_STUDIO_EVENT_CALLBACK_CREATE_PROGRAMMER_SOUND 0x00000080 +#define FMOD_STUDIO_EVENT_CALLBACK_DESTROY_PROGRAMMER_SOUND 0x00000100 +#define FMOD_STUDIO_EVENT_CALLBACK_PLUGIN_CREATED 0x00000200 +#define FMOD_STUDIO_EVENT_CALLBACK_PLUGIN_DESTROYED 0x00000400 +#define FMOD_STUDIO_EVENT_CALLBACK_TIMELINE_MARKER 0x00000800 +#define FMOD_STUDIO_EVENT_CALLBACK_TIMELINE_BEAT 0x00001000 +#define FMOD_STUDIO_EVENT_CALLBACK_SOUND_PLAYED 0x00002000 +#define FMOD_STUDIO_EVENT_CALLBACK_SOUND_STOPPED 0x00004000 +#define FMOD_STUDIO_EVENT_CALLBACK_REAL_TO_VIRTUAL 0x00008000 +#define FMOD_STUDIO_EVENT_CALLBACK_VIRTUAL_TO_REAL 0x00010000 +#define FMOD_STUDIO_EVENT_CALLBACK_ALL 0xFFFFFFFF + +typedef unsigned int FMOD_STUDIO_LOAD_BANK_FLAGS; +#define FMOD_STUDIO_LOAD_BANK_NORMAL 0x00000000 +#define FMOD_STUDIO_LOAD_BANK_NONBLOCKING 0x00000001 +#define FMOD_STUDIO_LOAD_BANK_DECOMPRESS_SAMPLES 0x00000002 +#define FMOD_STUDIO_LOAD_BANK_UNENCRYPTED 0x00000004 + +typedef unsigned int FMOD_STUDIO_COMMANDCAPTURE_FLAGS; +#define FMOD_STUDIO_COMMANDCAPTURE_NORMAL 0x00000000 +#define FMOD_STUDIO_COMMANDCAPTURE_FILEFLUSH 0x00000001 +#define FMOD_STUDIO_COMMANDCAPTURE_SKIP_INITIAL_STATE 0x00000002 + +typedef unsigned int FMOD_STUDIO_COMMANDREPLAY_FLAGS; +#define FMOD_STUDIO_COMMANDREPLAY_NORMAL 0x00000000 +#define FMOD_STUDIO_COMMANDREPLAY_SKIP_CLEANUP 0x00000001 +#define FMOD_STUDIO_COMMANDREPLAY_FAST_FORWARD 0x00000002 +#define FMOD_STUDIO_COMMANDREPLAY_SKIP_BANK_LOAD 0x00000004 + +typedef enum FMOD_STUDIO_LOADING_STATE +{ + FMOD_STUDIO_LOADING_STATE_UNLOADING, + FMOD_STUDIO_LOADING_STATE_UNLOADED, + FMOD_STUDIO_LOADING_STATE_LOADING, + FMOD_STUDIO_LOADING_STATE_LOADED, + FMOD_STUDIO_LOADING_STATE_ERROR, + + FMOD_STUDIO_LOADING_STATE_FORCEINT = 65536 /* Makes sure this enum is signed 32bit. */ +} FMOD_STUDIO_LOADING_STATE; + +typedef enum FMOD_STUDIO_LOAD_MEMORY_MODE +{ + FMOD_STUDIO_LOAD_MEMORY, + FMOD_STUDIO_LOAD_MEMORY_POINT, + + FMOD_STUDIO_LOAD_MEMORY_FORCEINT = 65536 /* Makes sure this enum is signed 32bit. */ +} FMOD_STUDIO_LOAD_MEMORY_MODE; + +typedef enum FMOD_STUDIO_PARAMETER_TYPE +{ + FMOD_STUDIO_PARAMETER_GAME_CONTROLLED, + FMOD_STUDIO_PARAMETER_AUTOMATIC_DISTANCE, + FMOD_STUDIO_PARAMETER_AUTOMATIC_EVENT_CONE_ANGLE, + FMOD_STUDIO_PARAMETER_AUTOMATIC_EVENT_ORIENTATION, + FMOD_STUDIO_PARAMETER_AUTOMATIC_DIRECTION, + FMOD_STUDIO_PARAMETER_AUTOMATIC_ELEVATION, + FMOD_STUDIO_PARAMETER_AUTOMATIC_LISTENER_ORIENTATION, + FMOD_STUDIO_PARAMETER_AUTOMATIC_SPEED, + + FMOD_STUDIO_PARAMETER_MAX, + FMOD_STUDIO_PARAMETER_FORCEINT = 65536 /* Makes sure this enum is signed 32bit. */ +} FMOD_STUDIO_PARAMETER_TYPE; + +typedef enum FMOD_STUDIO_USER_PROPERTY_TYPE +{ + FMOD_STUDIO_USER_PROPERTY_TYPE_INTEGER, + FMOD_STUDIO_USER_PROPERTY_TYPE_BOOLEAN, + FMOD_STUDIO_USER_PROPERTY_TYPE_FLOAT, + FMOD_STUDIO_USER_PROPERTY_TYPE_STRING, + + FMOD_STUDIO_USER_PROPERTY_TYPE_FORCEINT = 65536 /* Makes sure this enum is signed 32bit. */ +} FMOD_STUDIO_USER_PROPERTY_TYPE; + +typedef enum FMOD_STUDIO_EVENT_PROPERTY +{ + FMOD_STUDIO_EVENT_PROPERTY_CHANNELPRIORITY, + FMOD_STUDIO_EVENT_PROPERTY_SCHEDULE_DELAY, + FMOD_STUDIO_EVENT_PROPERTY_SCHEDULE_LOOKAHEAD, + FMOD_STUDIO_EVENT_PROPERTY_MINIMUM_DISTANCE, + FMOD_STUDIO_EVENT_PROPERTY_MAXIMUM_DISTANCE, + FMOD_STUDIO_EVENT_PROPERTY_COOLDOWN, + FMOD_STUDIO_EVENT_PROPERTY_MAX, + + FMOD_STUDIO_EVENT_PROPERTY_FORCEINT = 65536 /* Makes sure this enum is signed 32bit. */ +} FMOD_STUDIO_EVENT_PROPERTY; + +typedef enum FMOD_STUDIO_PLAYBACK_STATE +{ + FMOD_STUDIO_PLAYBACK_PLAYING, + FMOD_STUDIO_PLAYBACK_SUSTAINING, + FMOD_STUDIO_PLAYBACK_STOPPED, + FMOD_STUDIO_PLAYBACK_STARTING, + FMOD_STUDIO_PLAYBACK_STOPPING, + + FMOD_STUDIO_PLAYBACK_FORCEINT = 65536 +} FMOD_STUDIO_PLAYBACK_STATE; + +typedef enum FMOD_STUDIO_STOP_MODE +{ + FMOD_STUDIO_STOP_ALLOWFADEOUT, + FMOD_STUDIO_STOP_IMMEDIATE, + + FMOD_STUDIO_STOP_FORCEINT = 65536 /* Makes sure this enum is signed 32bit. */ +} FMOD_STUDIO_STOP_MODE; + +typedef enum FMOD_STUDIO_INSTANCETYPE +{ + FMOD_STUDIO_INSTANCETYPE_NONE, + FMOD_STUDIO_INSTANCETYPE_SYSTEM, + FMOD_STUDIO_INSTANCETYPE_EVENTDESCRIPTION, + FMOD_STUDIO_INSTANCETYPE_EVENTINSTANCE, + FMOD_STUDIO_INSTANCETYPE_PARAMETERINSTANCE, + FMOD_STUDIO_INSTANCETYPE_BUS, + FMOD_STUDIO_INSTANCETYPE_VCA, + FMOD_STUDIO_INSTANCETYPE_BANK, + FMOD_STUDIO_INSTANCETYPE_COMMANDREPLAY, + + FMOD_STUDIO_INSTANCETYPE_FORCEINT = 65536 /* Makes sure this enum is signed 32bit. */ +} FMOD_STUDIO_INSTANCETYPE; + +/* + FMOD Studio structures +*/ +typedef struct FMOD_STUDIO_BANK_INFO +{ + int size; + void *userdata; + int userdatalength; + FMOD_FILE_OPEN_CALLBACK opencallback; + FMOD_FILE_CLOSE_CALLBACK closecallback; + FMOD_FILE_READ_CALLBACK readcallback; + FMOD_FILE_SEEK_CALLBACK seekcallback; +} FMOD_STUDIO_BANK_INFO; + +typedef struct FMOD_STUDIO_PARAMETER_ID +{ + unsigned int data1; + unsigned int data2; +} FMOD_STUDIO_PARAMETER_ID; + +typedef struct FMOD_STUDIO_PARAMETER_DESCRIPTION +{ + const char *name; + FMOD_STUDIO_PARAMETER_ID id; + float minimum; + float maximum; + float defaultvalue; + FMOD_STUDIO_PARAMETER_TYPE type; + FMOD_STUDIO_PARAMETER_FLAGS flags; +} FMOD_STUDIO_PARAMETER_DESCRIPTION; + +typedef struct FMOD_STUDIO_USER_PROPERTY +{ + const char *name; + FMOD_STUDIO_USER_PROPERTY_TYPE type; + + union + { + int intvalue; + FMOD_BOOL boolvalue; + float floatvalue; + const char *stringvalue; + }; +} FMOD_STUDIO_USER_PROPERTY; + +typedef struct FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES +{ + const char *name; + FMOD_SOUND *sound; + int subsoundIndex; +} FMOD_STUDIO_PROGRAMMER_SOUND_PROPERTIES; + +typedef struct FMOD_STUDIO_PLUGIN_INSTANCE_PROPERTIES +{ + const char *name; + FMOD_DSP *dsp; +} FMOD_STUDIO_PLUGIN_INSTANCE_PROPERTIES; + +typedef struct FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES +{ + const char *name; + int position; +} FMOD_STUDIO_TIMELINE_MARKER_PROPERTIES; + +typedef struct FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES +{ + int bar; + int beat; + int position; + float tempo; + int timesignatureupper; + int timesignaturelower; +} FMOD_STUDIO_TIMELINE_BEAT_PROPERTIES; + +typedef struct FMOD_STUDIO_ADVANCEDSETTINGS +{ + int cbsize; + unsigned int commandqueuesize; + unsigned int handleinitialsize; + int studioupdateperiod; + int idlesampledatapoolsize; + unsigned int streamingscheduledelay; + const char* encryptionkey; +} FMOD_STUDIO_ADVANCEDSETTINGS; + +typedef struct FMOD_STUDIO_CPU_USAGE +{ + float dspusage; + float streamusage; + float geometryusage; + float updateusage; + float studiousage; +} FMOD_STUDIO_CPU_USAGE; + +typedef struct FMOD_STUDIO_BUFFER_INFO +{ + int currentusage; + int peakusage; + int capacity; + int stallcount; + float stalltime; +} FMOD_STUDIO_BUFFER_INFO; + +typedef struct FMOD_STUDIO_BUFFER_USAGE +{ + FMOD_STUDIO_BUFFER_INFO studiocommandqueue; + FMOD_STUDIO_BUFFER_INFO studiohandle; +} FMOD_STUDIO_BUFFER_USAGE; + +typedef struct FMOD_STUDIO_SOUND_INFO +{ + const char *name_or_data; + FMOD_MODE mode; + FMOD_CREATESOUNDEXINFO exinfo; + int subsoundindex; +} FMOD_STUDIO_SOUND_INFO; + +typedef struct FMOD_STUDIO_COMMAND_INFO +{ + const char *commandname; + int parentcommandindex; + int framenumber; + float frametime; + FMOD_STUDIO_INSTANCETYPE instancetype; + FMOD_STUDIO_INSTANCETYPE outputtype; + unsigned int instancehandle; + unsigned int outputhandle; +} FMOD_STUDIO_COMMAND_INFO; + +typedef struct FMOD_STUDIO_MEMORY_USAGE +{ + int exclusive; + int inclusive; + int sampledata; +} FMOD_STUDIO_MEMORY_USAGE; + +/* + FMOD Studio callbacks. +*/ +typedef FMOD_RESULT (F_CALLBACK *FMOD_STUDIO_SYSTEM_CALLBACK) (FMOD_STUDIO_SYSTEM *system, FMOD_STUDIO_SYSTEM_CALLBACK_TYPE type, void *commanddata, void *userdata); +typedef FMOD_RESULT (F_CALLBACK *FMOD_STUDIO_EVENT_CALLBACK) (FMOD_STUDIO_EVENT_CALLBACK_TYPE type, FMOD_STUDIO_EVENTINSTANCE *event, void *parameters); +typedef FMOD_RESULT (F_CALLBACK *FMOD_STUDIO_COMMANDREPLAY_FRAME_CALLBACK) (FMOD_STUDIO_COMMANDREPLAY *replay, int commandindex, float currenttime, void *userdata); +typedef FMOD_RESULT (F_CALLBACK *FMOD_STUDIO_COMMANDREPLAY_LOAD_BANK_CALLBACK) (FMOD_STUDIO_COMMANDREPLAY *replay, int commandindex, const FMOD_GUID *bankguid, const char *bankfilename, FMOD_STUDIO_LOAD_BANK_FLAGS flags, FMOD_STUDIO_BANK **bank, void *userdata); +typedef FMOD_RESULT (F_CALLBACK *FMOD_STUDIO_COMMANDREPLAY_CREATE_INSTANCE_CALLBACK) (FMOD_STUDIO_COMMANDREPLAY *replay, int commandindex, FMOD_STUDIO_EVENTDESCRIPTION *eventdescription, FMOD_STUDIO_EVENTINSTANCE **instance, void *userdata); + +#endif // FMOD_STUDIO_COMMON_H diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMODStudioModule.h b/Plugins/FMODStudio/Source/FMODStudio/Public/FMODStudioModule.h new file mode 100644 index 0000000..88adc46 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMODStudioModule.h @@ -0,0 +1,168 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "Modules/ModuleManager.h" + +namespace FMOD +{ +namespace Studio +{ +class System; +class EventDescription; +class EventInstance; +} +} + +class UFMODAsset; +class UFMODBank; +class UFMODEvent; +class UWorld; +class AAudioVolume; +struct FInteriorSettings; +struct FFMODListener; // Currently only for private use, we don't export this type + +// Which FMOD Studio system to use +namespace EFMODSystemContext +{ +enum Type +{ + // For use auditioning sounds within the editor + Auditioning, + + // For use in PIE and in-game + Runtime, + + // For use when playing events in an editor world (e.g. previewing a level sequence) + Editor, + + // Max number of types + Max +}; +} + +/** + * The public interface to this module + */ +class IFMODStudioModule : public IModuleInterface +{ +public: + /** + * Singleton-like access to this module's interface. This is just for convenience! + * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. + * + * @return Returns singleton instance, loading the module on demand if needed + */ + static inline IFMODStudioModule &Get() { return FModuleManager::LoadModuleChecked("FMODStudio"); } + + /** + * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. + * + * @return True if the module is loaded and ready to use + */ + static inline bool IsAvailable() { return FModuleManager::Get().IsModuleLoaded("FMODStudio"); } + + /** + * Get a pointer to the runtime studio system (only valid in-game or in PIE) + */ + virtual FMOD::Studio::System *GetStudioSystem(EFMODSystemContext::Type Context) = 0; + + /** + * Set system paused (for PIE pause) + */ + virtual void SetSystemPaused(bool paused) = 0; + + /** + * Called when user changes any studio settings + */ + virtual void RefreshSettings() = 0; + + /** + * Called when we enter of leave PIE mode + */ + virtual void SetInPIE(bool bInPIE, bool bSimulating) = 0; + + /** + * Look up an asset given its name + */ + virtual UFMODAsset *FindAssetByName(const FString &Name) = 0; + + /** + * Look up an event given its name + */ + virtual UFMODEvent *FindEventByName(const FString &Name) = 0; + + /** + * Get the disk path for a Bank asset + */ + virtual FString GetBankPath(const UFMODBank &Bank) = 0; + + /** + * Get the disk paths for all Banks + */ + virtual void GetAllBankPaths(TArray &Paths, bool IncludeMasterBank) const = 0; + + /** + * Get an event description. + * The system type can control which Studio system to use, or leave it as System_Max for it to choose automatically. + */ + virtual FMOD::Studio::EventDescription *GetEventDescription( + const UFMODEvent *Event, EFMODSystemContext::Type Context = EFMODSystemContext::Max) = 0; + + /** + * Create a single auditioning instance using the auditioning system + */ + virtual FMOD::Studio::EventInstance *CreateAuditioningInstance(const UFMODEvent *Event) = 0; + + /** + * Stop any auditioning instance + */ + virtual void StopAuditioningInstance() = 0; + + /** + * Return whether the listener(s) have moved + */ + virtual bool HasListenerMoved() = 0; + + /** + * Called to change the listener position for editor mode + */ + virtual void SetListenerPosition(int ListenerIndex, UWorld *World, const FTransform &ListenerTransform, float DeltaSeconds) = 0; + + /** + * Called to change the listener position for editor mode + */ + virtual void FinishSetListenerPosition(int NumListeners, float DeltaSeconds) = 0; + + /** + * Return the audio settings for the listener nearest the given location + */ + virtual const FFMODListener &GetNearestListener(const FVector &Location) = 0; + + /** This event is fired after all banks were reloaded */ + virtual FSimpleMulticastDelegate &BanksReloadedEvent() = 0; + + /** Return a list of banks that failed to load due to an error */ + virtual TArray GetFailedBankLoads(EFMODSystemContext::Type Context) = 0; + + /** Return a list of plugins that appear to be needed */ + virtual TArray GetRequiredPlugins() = 0; + + /** Register a plugin that is required */ + virtual void AddRequiredPlugin(const FString &Plugin) = 0; + + /** Returns whether sound is enabled for the game */ + virtual bool UseSound() = 0; + + /** Attempts to load a plugin by name */ + virtual bool LoadPlugin(EFMODSystemContext::Type Context, const TCHAR *ShortName) = 0; + + /** Log a FMOD error */ + virtual void LogError(int result, const char *function) = 0; + + /** Returns if the banks have been loaded */ + virtual bool AreBanksLoaded() = 0; + + /** Set active locale. Locale must be the locale name of one of the configured project locales */ + virtual bool SetLocale(const FString& Locale) = 0; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudio/Public/FMODUtils.h b/Plugins/FMODStudio/Source/FMODStudio/Public/FMODUtils.h new file mode 100644 index 0000000..d8d5dd7 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudio/Public/FMODUtils.h @@ -0,0 +1,202 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "fmod_studio.hpp" +#include "fmod.hpp" + +#include "Runtime/Launch/Resources/Version.h" +#include "Engine/Engine.h" + +#include "FMODStudioModule.h" + +#define verifyfmod(fn) \ + { \ + FMOD_RESULT _result = (fn); \ + if (_result != FMOD_OK) \ + { \ + FMODUtils::LogError(_result, #fn); \ + } \ + } + +namespace FMODUtils +{ + +// Unreal defines 1 unit == 1cm, so convert to metres for Studio automatically +#define FMOD_VECTOR_SCALE_DEFAULT 0.01f + +// Just call into module +inline void LogError(FMOD_RESULT result, const char *function) +{ + IFMODStudioModule::Get().LogError(result, function); +} + +inline void Assign(FMOD_VECTOR &Dest, const FVector &Src) +{ + Dest.x = Src.X; + Dest.y = Src.Y; + Dest.z = Src.Z; +} + +inline FMOD_VECTOR ConvertWorldVector(const FVector &Src) +{ + static FMatrix UE4toFMOD(FVector(0.0f, 0.0f, FMOD_VECTOR_SCALE_DEFAULT), FVector(FMOD_VECTOR_SCALE_DEFAULT, 0.0f, 0.0f), + FVector(0.0f, FMOD_VECTOR_SCALE_DEFAULT, 0.0f), FVector::ZeroVector); + + FMOD_VECTOR Dest; + Assign(Dest, UE4toFMOD.TransformPosition(Src)); + return Dest; +} + +inline FMOD_VECTOR ConvertUnitVector(const FVector &Src) +{ + static FMatrix UE4toFMOD(FVector(0.0f, 0.0f, 1.0f), FVector(1.0f, 0.0f, 0.0f), FVector(0.0f, 1.0f, 0.0f), FVector::ZeroVector); + + FMOD_VECTOR Dest; + Assign(Dest, UE4toFMOD.TransformVector(Src)); + return Dest; +} + +inline void Assign(FMOD_3D_ATTRIBUTES &Dest, const FTransform &Src) +{ + Dest.position = ConvertWorldVector(Src.GetTranslation()); + Dest.forward = ConvertUnitVector(Src.GetUnitAxis(EAxis::X)); + Dest.up = ConvertUnitVector(Src.GetUnitAxis(EAxis::Z)); +} + +inline float DistanceToUEScale(float FMODDistance) +{ + return FMODDistance / FMOD_VECTOR_SCALE_DEFAULT; +} + +inline bool IsWorldAudible(UWorld *World, bool AllowInEditor) +{ + if (GEngine && IFMODStudioModule::Get().UseSound()) + { + if (!IsValid(World)) + { + return true; + } + + if (World->bAllowAudioPlayback && World->GetNetMode() != NM_DedicatedServer) + { + EWorldType::Type previewEnum; + previewEnum = EWorldType::EditorPreview; + if (World->IsGameWorld() || World->WorldType == previewEnum || (AllowInEditor && World->WorldType == EWorldType::Editor)) + { + return true; + } + } + } + return false; +} + +inline FMOD::Studio::ID ConvertGuid(const FGuid &UnrealGuid) +{ + // Unreal doesn't follow the usual windows GUID format, instead it parses + // them as 4 integers + FMOD::Studio::ID StudioGuid; + FMemory::Memcpy(&StudioGuid, &UnrealGuid, sizeof(StudioGuid)); + Swap(StudioGuid.Data2, StudioGuid.Data3); + Swap(StudioGuid.Data4[0], StudioGuid.Data4[3]); + Swap(StudioGuid.Data4[1], StudioGuid.Data4[2]); + Swap(StudioGuid.Data4[4], StudioGuid.Data4[7]); + Swap(StudioGuid.Data4[5], StudioGuid.Data4[6]); + return StudioGuid; +} + +inline FGuid ConvertGuid(const FMOD::Studio::ID &StudioGuid) +{ + // Unreal doesn't follow the usual windows GUID format, instead it parses + // them as 4 integers + FMOD::Studio::ID CopiedGuid; + FMemory::Memcpy(&CopiedGuid, &StudioGuid, sizeof(StudioGuid)); + Swap(CopiedGuid.Data2, CopiedGuid.Data3); + Swap(CopiedGuid.Data4[0], CopiedGuid.Data4[3]); + Swap(CopiedGuid.Data4[1], CopiedGuid.Data4[2]); + Swap(CopiedGuid.Data4[4], CopiedGuid.Data4[7]); + Swap(CopiedGuid.Data4[5], CopiedGuid.Data4[6]); + FGuid UnrealGuid; + FMemory::Memcpy(&UnrealGuid, &CopiedGuid, sizeof(CopiedGuid)); + return UnrealGuid; +} + +template +inline FGuid GetID(StudioType *Instance) +{ + FMOD::Studio::ID StudioID = { 0 }; + verifyfmod(Instance->getID(&StudioID)); + return FMODUtils::ConvertGuid(StudioID); +} + +template +inline FString GetPath(StudioType *Instance) +{ + int ActualSize = 128; // Start with expected enough space + TArray RawBuffer; + FMOD_RESULT Result; + do + { + RawBuffer.SetNum(ActualSize); + Result = Instance->getPath(RawBuffer.GetData(), ActualSize, &ActualSize); + } while (Result == FMOD_ERR_TRUNCATED); + + if (Result == FMOD_OK) + { + return FString(UTF8_TO_TCHAR(RawBuffer.GetData())); + } + else + { + return FString(); + } +} + +inline FString LookupNameFromGuid(FMOD::Studio::System *StudioSystem, const FMOD::Studio::ID &Guid) +{ + int ActualSize = 128; // Start with expected enough space + TArray RawBuffer; + FMOD_RESULT Result; + do + { + RawBuffer.SetNum(ActualSize); + Result = StudioSystem->lookupPath(&Guid, RawBuffer.GetData(), ActualSize, &ActualSize); + } while (Result == FMOD_ERR_TRUNCATED); + + if (Result == FMOD_OK) + { + return FString(UTF8_TO_TCHAR(RawBuffer.GetData())); + } + else + { + return FString(); + } +} + +inline FString LookupNameFromGuid(FMOD::Studio::System *StudioSystem, const FGuid &Guid) +{ + return LookupNameFromGuid(StudioSystem, ConvertGuid(Guid)); +} + +inline FString ParameterTypeToString(FMOD_STUDIO_PARAMETER_TYPE Type) +{ + switch (Type) + { + case FMOD_STUDIO_PARAMETER_GAME_CONTROLLED: + return FString("Game Controlled"); + case FMOD_STUDIO_PARAMETER_AUTOMATIC_DISTANCE: + return FString("Distance (Auto)"); + case FMOD_STUDIO_PARAMETER_AUTOMATIC_EVENT_CONE_ANGLE: + return FString("Event Cone Angle (Auto)"); + case FMOD_STUDIO_PARAMETER_AUTOMATIC_EVENT_ORIENTATION: + return FString("Event Orientation (Auto)"); + case FMOD_STUDIO_PARAMETER_AUTOMATIC_DIRECTION: + return FString("Direction (Auto)"); + case FMOD_STUDIO_PARAMETER_AUTOMATIC_ELEVATION: + return FString("Elevation (Auto)"); + case FMOD_STUDIO_PARAMETER_AUTOMATIC_LISTENER_ORIENTATION: + return FString("Listener Orientation (Auto)"); + } + + return FString(); +} +} \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Classes/FMODAmbientSoundActorFactory.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Classes/FMODAmbientSoundActorFactory.h new file mode 100644 index 0000000..c23d8d8 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Classes/FMODAmbientSoundActorFactory.h @@ -0,0 +1,21 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "ActorFactories/ActorFactory.h" +#include "FMODAmbientSoundActorFactory.generated.h" + +/** FMOD Ambient Sound Actor Factory. +*/ +UCLASS(MinimalAPI, config = Editor, collapsecategories, hidecategories = Object) +class UFMODAmbientSoundActorFactory : public UActorFactory +{ + GENERATED_UCLASS_BODY() + + // Begin UActorFactory Interface + virtual void PostSpawnActor(UObject *Asset, AActor *NewActor) override; + virtual void PostCreateBlueprint(UObject *Asset, AActor *CDO) override; + virtual bool CanCreateActorFrom(const FAssetData &AssetData, FText &OutErrorMsg) override; + virtual UObject *GetAssetFromActorInstance(AActor *ActorInstance) override; + // End UActorFactory Interface +}; diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/FMODStudioEditor.Build.cs b/Plugins/FMODStudio/Source/FMODStudioEditor/FMODStudioEditor.Build.cs new file mode 100644 index 0000000..d0b2204 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/FMODStudioEditor.Build.cs @@ -0,0 +1,63 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. +using System.IO; + +namespace UnrealBuildTool.Rules +{ + public class FMODStudioEditor : ModuleRules + { + #if WITH_FORWARDED_MODULE_RULES_CTOR + public FMODStudioEditor(ReadOnlyTargetRules Target) : base(Target) + #else + public FMODStudioEditor(TargetInfo Target) + #endif + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + PrivatePCHHeaderFile = "Private/FMODStudioEditorPrivatePCH.h"; + + bUseUnity = false; + + PrivateIncludePaths.AddRange( + new string[] { + "FMODStudio/Private", + "FMODStudio/Public/FMOD", + Path.Combine(ModuleDirectory, "Classes") + } + ); + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "CoreUObject", + "Engine", + "FMODStudio", + "InputCore", + "UnrealEd", + "Sequencer" + } + ); + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "Slate", + "SlateCore", + "Settings", + "EditorStyle", + "LevelEditor", + "AssetTools", + "AssetRegistry", + "PropertyEditor", + "WorkspaceMenuStructure", + "Sockets", + "LevelSequence", + "MainFrame", + "MovieScene", + "MovieSceneTracks", + "MovieSceneTools", + "ToolMenus" + } + ); + } + } +} \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/AssetTypeActions_FMODEvent.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/AssetTypeActions_FMODEvent.cpp new file mode 100644 index 0000000..e5abbb0 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/AssetTypeActions_FMODEvent.cpp @@ -0,0 +1,143 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "AssetTypeActions_FMODEvent.h" +#include "AssetTypeActions_Base.h" +#include "FMODEventEditor.h" +#include "FMODEvent.h" +#include "FMODUtils.h" +#include "FMODStudioModule.h" +#include "FMODStudioEditorModule.h" +#include "UnrealEd/Public/Editor.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "EditorStyle/Public/EditorStyleSet.h" + +#define LOCTEXT_NAMESPACE "AssetTypeActions" + +FAssetTypeActions_FMODEvent::FAssetTypeActions_FMODEvent() + : CurrentPreviewEventInstance(nullptr) +{ + BeginPIEDelegateHandle = FEditorDelegates::BeginPIE.AddRaw(this, &FAssetTypeActions_FMODEvent::HandleBeginPIE); + IFMODStudioModule::Get().BanksReloadedEvent().AddRaw(this, &FAssetTypeActions_FMODEvent::HandleBanksReloaded); +} + +FAssetTypeActions_FMODEvent::~FAssetTypeActions_FMODEvent() +{ + FEditorDelegates::BeginPIE.Remove(BeginPIEDelegateHandle); + IFMODStudioModule::Get().BanksReloadedEvent().RemoveAll(this); + IFMODStudioModule::Get().StopAuditioningInstance(); +} + +UClass *FAssetTypeActions_FMODEvent::GetSupportedClass() const +{ + return UFMODEvent::StaticClass(); +} + +void FAssetTypeActions_FMODEvent::GetActions(const TArray &InObjects, FMenuBuilder &MenuBuilder) +{ + auto Events = GetTypedWeakObjectPtrs(InObjects); + + MenuBuilder.AddMenuEntry(LOCTEXT("FMODEvent_Play", "Play"), LOCTEXT("FMODEvent_PlayTooltip", "Plays the selected FMOD event."), + FSlateIcon(FEditorStyle::GetStyleSetName(), "MediaAsset.AssetActions.Play"), + FUIAction(FExecuteAction::CreateSP(this, &FAssetTypeActions_FMODEvent::ExecutePlay, Events), + FCanExecuteAction::CreateSP(this, &FAssetTypeActions_FMODEvent::CanExecutePlayCommand, Events))); + + MenuBuilder.AddMenuEntry(LOCTEXT("FMODEvent_Stop", "Stop"), LOCTEXT("FMODEvent_StopTooltip", "Stops the currently playing FMOD event."), + FSlateIcon(FEditorStyle::GetStyleSetName(), "MediaAsset.AssetActions.Stop"), + FUIAction(FExecuteAction::CreateSP(this, &FAssetTypeActions_FMODEvent::ExecuteStop, Events), FCanExecuteAction())); +} + +void FAssetTypeActions_FMODEvent::OpenAssetEditor(const TArray &InObjects, TSharedPtr EditWithinLevelEditor) +{ + EToolkitMode::Type Mode = EditWithinLevelEditor.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone; + + for (auto ObjIt = InObjects.CreateConstIterator(); ObjIt; ++ObjIt) + { + auto Event = Cast(*ObjIt); + if (IsValid(Event)) + { + TSharedRef NewFMODEventEditor(new FFMODEventEditor()); + NewFMODEventEditor->InitFMODEventEditor(Mode, EditWithinLevelEditor, Event); + } + } +} + +bool FAssetTypeActions_FMODEvent::CanExecutePlayCommand(TArray> Objects) const +{ + return Objects.Num() == 1; +} + +bool FAssetTypeActions_FMODEvent::AssetsActivatedOverride(const TArray &InObjects, EAssetTypeActivationMethod::Type ActivationType) +{ + if (ActivationType == EAssetTypeActivationMethod::Previewed) + { + for (auto ObjIt = InObjects.CreateConstIterator(); ObjIt; ++ObjIt) + { + UFMODEvent *Event = Cast(*ObjIt); + if (IsValid(Event)) + { + // Only play the first valid event + PlayEvent(Event); + break; + } + } + return true; + } + return false; +} + +void FAssetTypeActions_FMODEvent::ExecuteEdit(TArray> Objects) +{ + for (auto ObjIt = Objects.CreateConstIterator(); ObjIt; ++ObjIt) + { + auto Object = (*ObjIt).Get(); + if (IsValid(Object)) + { + GEditor->GetEditorSubsystem()->OpenEditorForAsset(Object); + } + } +} + +void FAssetTypeActions_FMODEvent::ExecutePlay(TArray> Objects) +{ + for (auto ObjIt = Objects.CreateConstIterator(); ObjIt; ++ObjIt) + { + UFMODEvent *Event = (*ObjIt).Get(); + if (IsValid(Event)) + { + // Only play the first valid event + PlayEvent(Event); + break; + } + } +} + +void FAssetTypeActions_FMODEvent::ExecuteStop(TArray> Objects) +{ + IFMODStudioModule::Get().StopAuditioningInstance(); +} + +void FAssetTypeActions_FMODEvent::PlayEvent(UFMODEvent *Event) +{ + if (IsValid(Event)) + { + CurrentPreviewEventInstance = IFMODStudioModule::Get().CreateAuditioningInstance(Event); + if (CurrentPreviewEventInstance != nullptr) + { + CurrentPreviewEventInstance->start(); + } + } +} + +void FAssetTypeActions_FMODEvent::HandleBeginPIE(bool bSimulating) +{ + // Studio module will handle its own auditioning, just clear the handle + CurrentPreviewEventInstance = nullptr; +} + +void FAssetTypeActions_FMODEvent::HandleBanksReloaded() +{ + // Studio module will handle its own auditioning, just clear the handle + CurrentPreviewEventInstance = nullptr; +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/AssetTypeActions_FMODEvent.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/AssetTypeActions_FMODEvent.h new file mode 100644 index 0000000..8f0aff5 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/AssetTypeActions_FMODEvent.h @@ -0,0 +1,56 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "AssetTypeActions_Base.h" + +namespace FMOD +{ +namespace Studio +{ +class EventInstance; +} +} + +class UFMODEvent; + +class FAssetTypeActions_FMODEvent : public FAssetTypeActions_Base +{ +public: + FAssetTypeActions_FMODEvent(); + ~FAssetTypeActions_FMODEvent(); + + // IAssetTypeActions Implementation + virtual FText GetName() const override { return NSLOCTEXT("AssetTypeActions", "AssetTypeActions_FMODEvent", "FMOD Event"); } + virtual FColor GetTypeColor() const override { return FColor(0, 175, 255); } + virtual UClass *GetSupportedClass() const override; + virtual bool HasActions(const TArray &InObjects) const override { return true; } + virtual void GetActions(const TArray &InObjects, FMenuBuilder &MenuBuilder) override; + virtual bool AssetsActivatedOverride(const TArray &InObjects, EAssetTypeActivationMethod::Type ActivationType) override; + virtual void OpenAssetEditor( + const TArray &InObjects, TSharedPtr EditWithinLevelEditor = TSharedPtr()) override; + virtual bool CanFilter() override { return false; } + virtual uint32 GetCategories() override { return EAssetTypeCategories::Sounds; } + +private: + /** Returns true if only one event is selected to play */ + bool CanExecutePlayCommand(TArray> Objects) const; + + /** Handler for when Edit is selected */ + void ExecuteEdit(TArray> Objects); + + /** Handler for when Play is selected */ + void ExecutePlay(TArray> Objects); + + /** Handler for when Stop is selected */ + void ExecuteStop(TArray> Objects); + + /** Plays the event */ + void PlayEvent(UFMODEvent *Event); + + void HandleBeginPIE(bool bSimulating); + void HandleBanksReloaded(); + + FMOD::Studio::EventInstance *CurrentPreviewEventInstance; + FDelegateHandle BeginPIEDelegateHandle; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAmbientSoundActorFactory.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAmbientSoundActorFactory.cpp new file mode 100644 index 0000000..581b652 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAmbientSoundActorFactory.cpp @@ -0,0 +1,67 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODAmbientSoundActorFactory.h" +#include "FMODStudioEditorPrivatePCH.h" +#include "FMODAmbientSound.h" +#include "FMODEvent.h" +#include "AssetRegistry/Public/AssetData.h" +#include "Editor/EditorEngine.h" + +UFMODAmbientSoundActorFactory::UFMODAmbientSoundActorFactory(const FObjectInitializer &ObjectInitializer) + : Super(ObjectInitializer) +{ + DisplayName = NSLOCTEXT("FMOD", "FMODAmbientSoundDisplayName", "FMOD Ambient Sound"); + NewActorClass = AFMODAmbientSound::StaticClass(); +} + +bool UFMODAmbientSoundActorFactory::CanCreateActorFrom(const FAssetData &AssetData, FText &OutErrorMsg) +{ + //We allow creating AAmbientSounds without an existing sound asset + if (UActorFactory::CanCreateActorFrom(AssetData, OutErrorMsg)) + { + return true; + } + + if (AssetData.IsValid() && !AssetData.GetClass()->IsChildOf(UFMODEvent::StaticClass())) + { + OutErrorMsg = NSLOCTEXT("FMOD", "CanCreateActorFrom_NoFMODEventAsset", "A valid FMOD Event asset must be specified."); + return false; + } + + return true; +} + +void UFMODAmbientSoundActorFactory::PostSpawnActor(UObject *Asset, AActor *NewActor) +{ + UFMODEvent *Event = Cast(Asset); + + if (Event != NULL) + { + AFMODAmbientSound *NewSound = CastChecked(NewActor); + FActorLabelUtilities::SetActorLabelUnique(NewSound, Event->GetName()); + NewSound->AudioComponent->Event = Event; + } +} + +UObject *UFMODAmbientSoundActorFactory::GetAssetFromActorInstance(AActor *Instance) +{ + check(Instance->IsA(NewActorClass)); + AFMODAmbientSound *SoundActor = CastChecked(Instance); + + check(SoundActor->AudioComponent); + return SoundActor->AudioComponent->Event.Get(); +} + +void UFMODAmbientSoundActorFactory::PostCreateBlueprint(UObject *Asset, AActor *CDO) +{ + if (Asset != NULL && CDO != NULL) + { + UFMODEvent *Event = Cast(Asset); + + if (Event != NULL) + { + AFMODAmbientSound *NewSound = CastChecked(CDO); + NewSound->AudioComponent->Event = Event; + } + } +} \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAssetBroker.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAssetBroker.h new file mode 100644 index 0000000..b428e59 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAssetBroker.h @@ -0,0 +1,39 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "ComponentAssetBroker.h" +#include "FMODEvent.h" + +////////////////////////////////////////////////////////////////////////// +// FFMODAssetBroker + +class FFMODAssetBroker : public IComponentAssetBroker +{ +public: + UClass *GetSupportedAssetClass() override { return UFMODEvent::StaticClass(); } + + virtual bool AssignAssetToComponent(UActorComponent *InComponent, UObject *InAsset) override + { + if (UFMODAudioComponent *AudioComp = Cast(InComponent)) + { + UFMODEvent *Event = Cast(InAsset); + + if ((Event != NULL) || (InAsset == NULL)) + { + AudioComp->Event = Event; + return true; + } + } + return false; + } + + virtual UObject *GetAssetFromComponent(UActorComponent *InComponent) override + { + if (UFMODAudioComponent *AudioComp = Cast(InComponent)) + { + return AudioComp->Event.Get(); + } + return NULL; + } +}; diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAudioComponentDetails.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAudioComponentDetails.cpp new file mode 100644 index 0000000..246159e --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAudioComponentDetails.cpp @@ -0,0 +1,115 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODAudioComponentDetails.h" +#include "Toolkits/AssetEditorManager.h" +#include "FMODAmbientSound.h" +#include "FMODStudioModule.h" +#include "FMODEvent.h" +#include "fmod_studio.hpp" +#include "UnrealEd/Public/Editor.h" +#include "Widgets/Input/SButton.h" +#include "PropertyEditor/Public/DetailLayoutBuilder.h" +#include "PropertyEditor/Public/DetailCategoryBuilder.h" + +#define LOCTEXT_NAMESPACE "FMODStudio" + +TSharedRef FFMODAudioComponentDetails::MakeInstance() +{ + return MakeShareable(new FFMODAudioComponentDetails); +} + +void FFMODAudioComponentDetails::CustomizeDetails(IDetailLayoutBuilder &DetailBuilder) +{ + const TArray> &SelectedObjects = DetailBuilder.GetSelectedObjects(); + + for (int32 ObjectIndex = 0; !AudioComponent.IsValid() && ObjectIndex < SelectedObjects.Num(); ++ObjectIndex) + { + const TWeakObjectPtr &CurrentObject = SelectedObjects[ObjectIndex]; + if (CurrentObject.Get()->GetClass()->IsChildOf(UFMODAudioComponent::StaticClass())) + { + AudioComponent = Cast(CurrentObject.Get()); + } + else + { + AudioComponent = Cast(CurrentObject.Get())->FindComponentByClass(); + } + } + + DetailBuilder.EditCategory(TEXT("FMODAudio")) + .AddCustomRow( + FText::GetEmpty())[SNew(SVerticalBox) + + SVerticalBox::Slot() + .Padding(0, 2.0f, 0, 0) + .FillHeight(1.0f) + .VAlign( + VAlign_Center)[SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .AutoWidth() + .Padding(2.0f, 0.0f) + .VAlign(VAlign_Center) + .HAlign(HAlign_Left)[SNew(SButton) + .VAlign(VAlign_Center) + .OnClicked(this, &FFMODAudioComponentDetails::OnEditSoundClicked) + .Text(LOCTEXT("View Details", "Details"))] + + SHorizontalBox::Slot() + .AutoWidth() + .Padding(2.0f, 0.0f) + .VAlign(VAlign_Center) + .HAlign(HAlign_Left)[SNew(SButton) + .VAlign(VAlign_Center) + .OnClicked(this, &FFMODAudioComponentDetails::OnPlaySoundClicked) + .Text(LOCTEXT("Play FMOD Event", "Play"))] + + SHorizontalBox::Slot() + .AutoWidth() + .Padding(2.0f, 0.0f) + .VAlign(VAlign_Center) + .HAlign(HAlign_Left)[SNew(SButton) + .VAlign(VAlign_Center) + .OnClicked(this, &FFMODAudioComponentDetails::OnStopSoundClicked) + .Text(LOCTEXT("Stop FMOD Event", "Stop"))]]]; +} + +FReply FFMODAudioComponentDetails::OnEditSoundClicked() +{ + if (AudioComponent.IsValid()) + { + UFMODEvent *Event = AudioComponent.Get()->Event.Get(); + if (Event) + { + GEditor->GetEditorSubsystem()->OpenEditorForAsset(Event); + } + } + + return FReply::Handled(); +} + +FReply FFMODAudioComponentDetails::OnPlaySoundClicked() +{ + if (AudioComponent.IsValid()) + { + UFMODEvent *Event = AudioComponent.Get()->Event.Get(); + if (IsValid(Event)) + { + FMOD::Studio::EventInstance *Instance = IFMODStudioModule::Get().CreateAuditioningInstance(Event); + if (Instance) + { + for (auto param : AudioComponent->ParameterCache) + { + Instance->setParameterByName(TCHAR_TO_UTF8(*param.Key.ToString()), param.Value); + } + Instance->start(); + } + } + } + + return FReply::Handled(); +} + +FReply FFMODAudioComponentDetails::OnStopSoundClicked() +{ + IFMODStudioModule::Get().StopAuditioningInstance(); + + return FReply::Handled(); +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAudioComponentDetails.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAudioComponentDetails.h new file mode 100644 index 0000000..9fc212e --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAudioComponentDetails.h @@ -0,0 +1,24 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +//#include "PropertyEditing.h" +#include "PropertyCustomizationHelpers.h" +#include "PropertyEditor/Public/IDetailCustomization.h" + +class FFMODAudioComponentDetails : public IDetailCustomization +{ +public: + /** Makes a new instance of this detail layout class for a specific detail view requesting it */ + static TSharedRef MakeInstance(); + +private: + /** IDetailCustomization interface */ + virtual void CustomizeDetails(IDetailLayoutBuilder &DetailBuilder) override; + + FReply OnEditSoundClicked(); + FReply OnPlaySoundClicked(); + FReply OnStopSoundClicked(); + + TWeakObjectPtr AudioComponent; +}; \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAudioComponentVisualizer.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAudioComponentVisualizer.cpp new file mode 100644 index 0000000..7234495 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAudioComponentVisualizer.cpp @@ -0,0 +1,55 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODAudioComponentVisualizer.h" +#include "FMODAudioComponent.h" +#include "FMODUtils.h" +#include "FMODEvent.h" +#include "fmod_studio.hpp" +#include "Engine/Public/SceneView.h" +#include "Engine/Public/SceneManagement.h" + +void FFMODAudioComponentVisualizer::DrawVisualization(const UActorComponent *Component, const FSceneView *View, FPrimitiveDrawInterface *PDI) +{ + if (View->Family->EngineShowFlags.AudioRadius) + { + const UFMODAudioComponent *AudioComp = Cast(Component); + if (IsValid(AudioComp) && AudioComp->Event.IsValid()) + { + FMOD::Studio::EventDescription *EventDesc = + IFMODStudioModule::Get().GetEventDescription(AudioComp->Event.Get(), EFMODSystemContext::Auditioning); + if (EventDesc != nullptr) + { + bool bIs3D = false; + EventDesc->is3D(&bIs3D); + if (bIs3D) + { + const FColor AudioOuterRadiusColor(255, 153, 0); + const FColor AudioInnerRadiusColor(216, 130, 0); + + const FTransform &Transform = AudioComp->GetComponentTransform(); + + float MinDistance = 0.0f; + float MaxDistance = 0.0f; + if (AudioComp->AttenuationDetails.bOverrideAttenuation) + { + MinDistance = AudioComp->AttenuationDetails.MinimumDistance; + MaxDistance = AudioComp->AttenuationDetails.MaximumDistance; + } + else + { + EventDesc->getMinimumDistance(&MinDistance); + EventDesc->getMaximumDistance(&MaxDistance); + } + MinDistance = FMODUtils::DistanceToUEScale(MinDistance); + MaxDistance = FMODUtils::DistanceToUEScale(MaxDistance); + + DrawWireSphereAutoSides(PDI, Transform.GetTranslation(), AudioOuterRadiusColor, MinDistance, SDPG_World); + if (MaxDistance != MinDistance) + { + DrawWireSphereAutoSides(PDI, Transform.GetTranslation(), AudioInnerRadiusColor, MaxDistance, SDPG_World); + } + } + } + } + } +} diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAudioComponentVisualizer.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAudioComponentVisualizer.h new file mode 100644 index 0000000..94246f0 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODAudioComponentVisualizer.h @@ -0,0 +1,13 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "ComponentVisualizer.h" + +class FFMODAudioComponentVisualizer : public FComponentVisualizer +{ +public: + // Begin FComponentVisualizer interface + virtual void DrawVisualization(const UActorComponent *Component, const FSceneView *View, FPrimitiveDrawInterface *PDI) override; + // End FComponentVisualizer interface +}; diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODEventEditor.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODEventEditor.cpp new file mode 100644 index 0000000..c01d08f --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODEventEditor.cpp @@ -0,0 +1,188 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODEventEditor.h" +#include "FMODEvent.h" +#include "FMODStudioModule.h" +#include "FMODUtils.h" +#include "SFMODEventEditorPanel.h" +#include "Widgets/Docking/SDockTab.h" +//#include "WorkspaceMenuStructureModule.h" +#include "fmod_studio.hpp" +#include "UnrealEd/Public/Editor.h" + +#define LOCTEXT_NAMESPACE "FMODEventEditor" + +DEFINE_LOG_CATEGORY_STATIC(LogFMODEventEditor, Log, All); + +const FName FFMODEventEditor::EventEditorTabId(TEXT("FFMODEventEditor_EventView")); +const FName FFMODEventEditor::FMODEventEditorAppIdentifier(TEXT("FMODEventEditorApp")); + +void FFMODEventEditor::RegisterTabSpawners(const TSharedRef &NewTabManager) +{ + WorkspaceMenuCategory = NewTabManager->AddLocalWorkspaceMenuCategory(LOCTEXT("WorkspaceMenu_FMODEventEditor", "FMOD Event Editor")); + auto WorkspaceMenuCategoryRef = WorkspaceMenuCategory.ToSharedRef(); + + FAssetEditorToolkit::RegisterTabSpawners(NewTabManager); + + NewTabManager->RegisterTabSpawner(EventEditorTabId, FOnSpawnTab::CreateSP(this, &FFMODEventEditor::SpawnTab_EventEditor)) + .SetDisplayName(LOCTEXT("EventTab", "FMOD Event")) + .SetGroup(WorkspaceMenuCategoryRef); +} + +void FFMODEventEditor::UnregisterTabSpawners(const TSharedRef &NewTabManager) +{ + FAssetEditorToolkit::UnregisterTabSpawners(NewTabManager); + + NewTabManager->UnregisterTabSpawner(EventEditorTabId); +} + +FFMODEventEditor::FFMODEventEditor() + : CurrentPreviewEventInstance(nullptr) +{ + IFMODStudioModule::Get().BanksReloadedEvent().AddRaw(this, &FFMODEventEditor::HandleBanksReloaded); + BeginPIEDelegateHandle = FEditorDelegates::BeginPIE.AddRaw(this, &FFMODEventEditor::HandleBeginPIE); +} + +FFMODEventEditor::~FFMODEventEditor() +{ + IFMODStudioModule::Get().BanksReloadedEvent().RemoveAll(this); + FEditorDelegates::BeginPIE.Remove(BeginPIEDelegateHandle); + + CurrentPreviewEventInstance = nullptr; +} + +UFMODEvent *FFMODEventEditor::GetEditedEvent() const +{ + return EditedEvent; +} + +FMOD::Studio::EventDescription *FFMODEventEditor::GetEventDescription() const +{ + return IFMODStudioModule::Get().GetEventDescription(EditedEvent, EFMODSystemContext::Auditioning); +} + +void FFMODEventEditor::PlayEvent() +{ + CurrentPreviewEventInstance = IFMODStudioModule::Get().CreateAuditioningInstance(EditedEvent); + if (CurrentPreviewEventInstance != nullptr) + { + TArray values; + TArray ids; + + ParameterValues.GenerateKeyArray(ids); + ParameterValues.GenerateValueArray(values); + + CurrentPreviewEventInstance->setParametersByIDs(ids.GetData(), values.GetData(), ParameterValues.Num()); + + CurrentPreviewEventInstance->start(); + } +} + +void FFMODEventEditor::PauseEvent() +{ + if (CurrentPreviewEventInstance != nullptr) + { + bool bIsPaused = false; + CurrentPreviewEventInstance->getPaused(&bIsPaused); + CurrentPreviewEventInstance->setPaused(!bIsPaused); + } +} + +void FFMODEventEditor::StopEvent() +{ + IFMODStudioModule::Get().StopAuditioningInstance(); +} + +void FFMODEventEditor::SetParameterValue(FMOD_STUDIO_PARAMETER_ID ParameterId, float Value) +{ + ParameterValues[ParameterId] = Value; + + if (CurrentPreviewEventInstance != nullptr) + { + CurrentPreviewEventInstance->setParameterByID(ParameterId, Value); + } +} + +void FFMODEventEditor::AddParameter(FMOD_STUDIO_PARAMETER_ID ParameterId, float Value) +{ + ParameterValues.Add(ParameterId, Value); +} + +float FFMODEventEditor::GetParameterValue(FMOD_STUDIO_PARAMETER_ID Id) +{ + return ParameterValues[Id]; +} + +void FFMODEventEditor::InitFMODEventEditor(const EToolkitMode::Type Mode, const TSharedPtr &InitToolkitHost, UFMODEvent *Event) +{ + if (IsValid(Event)) + { + EditedEvent = Event; + + TSharedRef StandaloneDefaultLayout = + FTabManager::NewLayout("Standalone_FMODEventEditor_Layout") + ->AddArea(FTabManager::NewPrimaryArea() + ->SetOrientation(Orient_Vertical) + ->Split(FTabManager::NewStack()->AddTab(EventEditorTabId, ETabState::OpenedTab)->SetHideTabWell(true))); + + const bool bCreateDefaultStandaloneMenu = true; + const bool bCreateDefaultToolbar = false; + FAssetEditorToolkit::InitAssetEditor(Mode, InitToolkitHost, FFMODEventEditor::FMODEventEditorAppIdentifier, StandaloneDefaultLayout, + bCreateDefaultStandaloneMenu, bCreateDefaultToolbar, Event); + } +} + +FName FFMODEventEditor::GetToolkitFName() const +{ + return FName("FMODEventEditor"); +} + +FText FFMODEventEditor::GetBaseToolkitName() const +{ + return LOCTEXT("ToolkitName", "FMOD Event Editor"); +} + +FString FFMODEventEditor::GetWorldCentricTabPrefix() const +{ + return LOCTEXT("WorldCentricTabPrefix", "FMOD Event ").ToString(); +} + +FLinearColor FFMODEventEditor::GetWorldCentricTabColorScale() const +{ + return FLinearColor(0.0f, 0.0f, 0.5f, 0.5f); +} + +void FFMODEventEditor::CreateInternalWidgets() +{ + FMODEventEditorPanel = SNew(SFMODEventEditorPanel).FMODEventEditor(SharedThis(this)); +} + +TSharedRef FFMODEventEditor::SpawnTab_EventEditor(const FSpawnTabArgs &Args) +{ + check(Args.GetTabId().TabType == EventEditorTabId); + + CreateInternalWidgets(); + + return SAssignNew(OwnerTab, SDockTab) + .Label(LOCTEXT("EventEditorTitle", "FMOD Event")) + .TabColorScale(GetTabColorScale())[FMODEventEditorPanel.ToSharedRef()]; +} + +void FFMODEventEditor::HandleBanksReloaded() +{ + CurrentPreviewEventInstance = nullptr; + + CreateInternalWidgets(); + + if (OwnerTab.IsValid()) + { + OwnerTab->SetContent(FMODEventEditorPanel.ToSharedRef()); + } +} + +void FFMODEventEditor::HandleBeginPIE(bool bSimulating) +{ + CurrentPreviewEventInstance = nullptr; +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODEventEditor.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODEventEditor.h new file mode 100644 index 0000000..454758f --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODEventEditor.h @@ -0,0 +1,88 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "Toolkits/AssetEditorToolkit.h" +#include "fmod_studio_common.h" + +namespace FMOD +{ +namespace Studio +{ +class EventDescription; +class EventInstance; +} +} + +static bool operator==(const FMOD_STUDIO_PARAMETER_ID &a, const FMOD_STUDIO_PARAMETER_ID &b) +{ + return (a.data1 == b.data1 && a.data2 == b.data2); +} +FORCEINLINE uint32 GetTypeHash(const FMOD_STUDIO_PARAMETER_ID& id) +{ + return FCrc::MemCrc_DEPRECATED(&id, sizeof(FMOD_STUDIO_PARAMETER_ID)); +} + +class FFMODEventEditor : public FAssetEditorToolkit +{ +public: + virtual void RegisterTabSpawners(const TSharedRef &NewTabManager) override; + virtual void UnregisterTabSpawners(const TSharedRef &NewTabManager) override; + + /** + * Edits the specified event + * + * @param Mode Asset editing mode for this editor (standalone or world-centric) + * @param InitToolkitHost When Mode is WorldCentric, this is the level editor instance to spawn this editor within + * @param Event The event to edit + */ + void InitFMODEventEditor(const EToolkitMode::Type Mode, const TSharedPtr &InitToolkitHost, class UFMODEvent *Event); + + /** Constructor */ + FFMODEventEditor(); + + /** Destructor */ + virtual ~FFMODEventEditor(); + + UFMODEvent *GetEditedEvent() const; + FMOD::Studio::EventDescription *GetEventDescription() const; + void PlayEvent(); + void PauseEvent(); + void StopEvent(); + float GetParameterValue(FMOD_STUDIO_PARAMETER_ID Id); + void SetParameterValue(FMOD_STUDIO_PARAMETER_ID ParameterId, float Value); + void AddParameter(FMOD_STUDIO_PARAMETER_ID ParameterId, float Value); + + /** IToolkit interface */ + virtual FName GetToolkitFName() const override; + virtual FText GetBaseToolkitName() const override; + virtual FString GetWorldCentricTabPrefix() const override; + virtual FLinearColor GetWorldCentricTabColorScale() const override; + +private: + TMap ParameterValues; + FMOD::Studio::EventInstance *CurrentPreviewEventInstance; + + void HandlePreBanksReloaded(); + void HandleBanksReloaded(); + void HandleBeginPIE(bool bSimulating); + + /** Creates all internal widgets for the tabs to point at */ + void CreateInternalWidgets(); + + /** Spawns the tab with the FMOD event inside */ + TSharedRef SpawnTab_EventEditor(const FSpawnTabArgs &Args); + + TSharedPtr FMODEventEditorPanel; + TSharedPtr OwnerTab; + + /** The tab id for the event editor tab */ + static const FName EventEditorTabId; + + /** FMOD event editor app identifier string */ + static const FName FMODEventEditorAppIdentifier; + + class UFMODEvent *EditedEvent; + + FDelegateHandle BeginPIEDelegateHandle; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODSettingsCustomization.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODSettingsCustomization.cpp new file mode 100644 index 0000000..039dd6e --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODSettingsCustomization.cpp @@ -0,0 +1,235 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2020. + +#include "FMODSettingsCustomization.h" + +#include "DetailCategoryBuilder.h" +#include "DetailLayoutBuilder.h" +#include "DetailWidgetRow.h" +#include "FMODSettings.h" +#include "IDetailPropertyRow.h" +#include "Settings/ProjectPackagingSettings.h" +#include "Styling/SlateColor.h" +#include "Widgets/DeclarativeSyntaxSupport.h" +#include "Widgets/SWidget.h" +#include "Widgets/SCompoundWidget.h" +#include "Widgets/SBoxPanel.h" +#include "Widgets/Layout/SBorder.h" +#include "Widgets/Layout/SWidgetSwitcher.h" +#include "Widgets/Images/SImage.h" +#include "Widgets/Text/STextBlock.h" +#include "Widgets/Input/SButton.h" + +#define LOCTEXT_NAMESPACE "FMODSettings" + +class SSettingsMessage : public SCompoundWidget +{ + SLATE_BEGIN_ARGS(SSettingsMessage) + {} + + // Called when the Setup button is clicked + SLATE_EVENT(FSimpleDelegate, OnSetupClicked) + + SLATE_END_ARGS() + +public: + void Construct(const FArguments& InArgs) + { + TSharedRef SettingsOkayWidget = MakeRow( + "SettingsEditor.GoodIcon", + LOCTEXT("SettingsOkayText", "FMOD Settings are valid, run the Validate FMOD command to perform additional checking."), + FText() + ); + + TSharedRef NoContentDirWidget = MakeRow( + "SettingsEditor.WarningIcon", + LOCTEXT("NoContentDirText", "Bank Output Directory directory has not been set."), + FText() + ); + + TSharedRef NotPackagedWidget = MakeRow( + "SettingsEditor.WarningIcon", + LOCTEXT("NotPackagedText", + "Bank Output Directory has not been added to the \"Additional Non-Asset Directories to Copy\" list." + ), + LOCTEXT("AddToNonUFS", "Add") + ); + + TSharedRef AddedToUFSWidget = MakeRow( + "SettingsEditor.WarningIcon", + LOCTEXT("AddedToUFSText", + "Bank Output Directory has been added to the \"Additional Non-Asset Directories to Package\" list. " + "It is recommended to move FMOD to the \"Additional Non-Asset Directories to Copy\" list." + ), + LOCTEXT("MoveToNonUFS", "Move") + ); + + TSharedRef AddedToBothWidget = MakeRow( + "SettingsEditor.WarningIcon", + LOCTEXT("AddedToBothText", + "Bank Output Directory has been added to the \"Additional Non-Asset Directories to Package\" list. " + "It is recommended to remove FMOD from the \"Additional Non-Asset Directories to Package\" list." + ), + LOCTEXT("RemoveFromUFS", "Remove") + ); + + ChildSlot + [ + SNew(SBorder) + .BorderBackgroundColor(this, &SSettingsMessage::GetBorderColor) + .BorderImage(FEditorStyle::GetBrush("ToolPanel.LightGroupBorder")) + .Padding(8.0f) + [ + SNew(SWidgetSwitcher) + .WidgetIndex(this, &SSettingsMessage::GetSetupStateAsInt) + + + SWidgetSwitcher::Slot() + [ + SettingsOkayWidget + ] + + + SWidgetSwitcher::Slot() + [ + NoContentDirWidget + ] + + + SWidgetSwitcher::Slot() + [ + AddedToUFSWidget + ] + + + SWidgetSwitcher::Slot() + [ + NotPackagedWidget + ] + + + SWidgetSwitcher::Slot() + [ + AddedToBothWidget + ] + ] + ]; + + UpdateState(); + } + + void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) + { + UpdateState(); + } + +private: + FSlateColor GetBorderColor() const + { + if (SettingsState == UFMODSettings::Okay) + { + return FLinearColor::Green; + } + else + { + return FLinearColor(0.8f, 0, 0); + } + } + + TSharedRef MakeRow(FName IconName, FText Message, FText ButtonMessage) + { + TSharedRef Result = SNew(SHorizontalBox) + + // Status icon + + SHorizontalBox::Slot().AutoWidth().VAlign(VAlign_Center)[SNew(SImage).Image(FEditorStyle::GetBrush(IconName))] + + // Notice + + SHorizontalBox::Slot() + .FillWidth(1.0f) + .Padding(16.0f, 0.0f) + .VAlign(VAlign_Center)[ + SNew(STextBlock) + .ColorAndOpacity(FLinearColor::White) + .ShadowColorAndOpacity(FLinearColor::Black) + .ShadowOffset(FVector2D::UnitVector) + .AutoWrapText(true) + .Text(Message) + ]; + + if (!ButtonMessage.IsEmpty()) + { + Result->AddSlot() + .AutoWidth() + .VAlign(VAlign_Center) + [ + SNew(SButton) + .OnClicked(this, &SSettingsMessage::OnButtonPressed) + .Text(ButtonMessage) + ]; + } + + return Result; + } + + FReply OnButtonPressed() + { + const UFMODSettings& Settings = *GetDefault(); + UProjectPackagingSettings* PackagingSettings = Cast(UProjectPackagingSettings::StaticClass()->GetDefaultObject()); + bool UpdateConfigFile = false; + + if (SettingsState == UFMODSettings::AddedToUFS || SettingsState == UFMODSettings::AddedToBoth) + { + // Remove from non-asset directories to package list + for (int i = 0; i < PackagingSettings->DirectoriesToAlwaysStageAsUFS.Num(); ++i) + { + if (PackagingSettings->DirectoriesToAlwaysStageAsUFS[i].Path.StartsWith(Settings.BankOutputDirectory.Path)) + { + PackagingSettings->DirectoriesToAlwaysStageAsUFS.RemoveAt(i); + UpdateConfigFile = true; + break; + } + } + } + + if (SettingsState == UFMODSettings::AddedToUFS || SettingsState == UFMODSettings::NotPackaged) + { + // Add to non-asset directories to copy list + PackagingSettings->DirectoriesToAlwaysStageAsNonUFS.Add(Settings.BankOutputDirectory); + UpdateConfigFile = true; + } + + if (UpdateConfigFile) + { + PackagingSettings->UpdateDefaultConfigFile(); + } + + UpdateState(); + return FReply::Handled(); + } + + int32 GetSetupStateAsInt() const + { + return (int32)SettingsState; + } + + void UpdateState() + { + const UFMODSettings& Settings = *GetDefault(); + SettingsState = Settings.Check(); + } + +private: + UFMODSettings::EProblem SettingsState; +}; + +TSharedRef FFMODSettingsCustomization::MakeInstance() +{ + return MakeShareable(new FFMODSettingsCustomization); +} + +FFMODSettingsCustomization::FFMODSettingsCustomization() +{ +} + +void FFMODSettingsCustomization::CustomizeDetails(IDetailLayoutBuilder &DetailLayout) +{ + IDetailCategoryBuilder &PackagingCategory = DetailLayout.EditCategory(TEXT("Basic")); + TSharedRef PlatformSetupMessage = SNew(SSettingsMessage); + PackagingCategory.AddCustomRow(LOCTEXT("Warning", "Warning"), false).WholeRowWidget[PlatformSetupMessage]; +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODSettingsCustomization.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODSettingsCustomization.h new file mode 100644 index 0000000..0321cf4 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODSettingsCustomization.h @@ -0,0 +1,25 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2020. + +#pragma once + +#include "CoreMinimal.h" +#include "Misc/Attribute.h" +#include "Input/Reply.h" +#include "IDetailCustomization.h" +#include "PropertyHandle.h" + +class IDetailLayoutBuilder; + +class FFMODSettingsCustomization : public IDetailCustomization +{ +public: + // Makes a new instance of this detail layout class for a specific detail view requesting it + static TSharedRef MakeInstance(); + + // IDetailCustomization interface + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailLayout) override; + // End of IDetailCustomization interface + +private: + FFMODSettingsCustomization(); +}; diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODStudioEditorModule.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODStudioEditorModule.cpp new file mode 100644 index 0000000..1e40718 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODStudioEditorModule.cpp @@ -0,0 +1,1323 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODStudioEditorModule.h" +#include "FMODStudioModule.h" +#include "FMODStudioStyle.h" +#include "FMODAudioComponent.h" +#include "FMODAssetBroker.h" +#include "FMODSettings.h" +#include "FMODUtils.h" + +#include "FMODEventEditor.h" +#include "FMODAudioComponentVisualizer.h" +#include "FMODAudioComponentDetails.h" +#include "FMODSettingsCustomization.h" +#include "Sequencer/FMODChannelEditors.h" +#include "Sequencer/FMODEventControlSection.h" +#include "Sequencer/FMODEventControlTrackEditor.h" +#include "Sequencer/FMODEventParameterTrackEditor.h" +#include "AssetTypeActions_FMODEvent.h" + +#include "UnrealEd/Public/AssetSelection.h" +#include "Slate/Public/Framework/Notifications/NotificationManager.h" +#include "Slate/Public/Widgets/Notifications/SNotificationList.h" +#include "Developer/Settings/Public/ISettingsModule.h" +#include "Developer/Settings/Public/ISettingsSection.h" +#include "UnrealEd/Public/Editor.h" +#include "Slate/SceneViewport.h" +#include "LevelEditor/Public/LevelEditor.h" +#include "Sockets/Public/SocketSubsystem.h" +#include "Sockets/Public/Sockets.h" +#include "Sockets/Public/IPAddress.h" +#include "UnrealEd/Public/FileHelpers.h" +#include "Sequencer/Public/ISequencerModule.h" +#include "Sequencer/Public/SequencerChannelInterface.h" +#include "MovieSceneTools/Public/ClipboardTypes.h" +#include "Engine/Public/DebugRenderSceneProxy.h" +#include "Engine/Classes/Debug/DebugDrawService.h" +#include "Settings/ProjectPackagingSettings.h" +#include "UnrealEdGlobals.h" +#include "UnrealEd/Public/LevelEditorViewport.h" +#include "ActorFactories/ActorFactory.h" +#include "Engine/Canvas.h" +#include "Editor/UnrealEdEngine.h" +#include "Slate/Public/Framework/MultiBox/MultiBoxBuilder.h" +#include "Misc/MessageDialog.h" +#include "HAL/FileManager.h" +#include "Interfaces/IMainFrameModule.h" +#include "ToolMenus.h" + +#include "fmod_studio.hpp" + +#define LOCTEXT_NAMESPACE "FMODStudio" + +DEFINE_LOG_CATEGORY(LogFMOD); + +class FFMODStudioLink +{ +public: + FFMODStudioLink() + : SocketSubsystem(nullptr) + , Socket(nullptr) + { + SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM); + } + + ~FFMODStudioLink() { Disconnect(); } + + bool Connect() + { + if (!SocketSubsystem) + return false; + + Disconnect(); + Socket = SocketSubsystem->CreateSocket(NAME_Stream, TEXT("FMOD Studio Connection"), false); + + TSharedRef Addr = SocketSubsystem->CreateInternetAddr(); + bool Valid = false; + Addr->SetIp(TEXT("127.0.0.1"), Valid); + if (!Valid) + return false; + + Addr->SetPort(3663); + return Socket->Connect(*Addr); + } + + void Disconnect() + { + if (SocketSubsystem && Socket) + { + SocketSubsystem->DestroySocket(Socket); + Socket = nullptr; + } + } + + bool Execute(const TCHAR *Message, FString &OutMessage) + { + OutMessage = TEXT(""); + if (!Socket) + { + return false; + } + + UE_LOG(LogFMOD, Log, TEXT("Sent studio message: %s"), Message); + + FTCHARToUTF8 MessageChars(Message); + int32 BytesSent = 0; + if (!Socket->Send((const uint8 *)MessageChars.Get(), MessageChars.Length(), BytesSent)) + { + return false; + } + + while (1) + { + FString BackMessage; + if (!ReadMessage(BackMessage)) + { + return false; + } + UE_LOG(LogFMOD, Log, TEXT("Received studio message: %s"), *BackMessage); + if (BackMessage.StartsWith(TEXT("out(): "))) + { + OutMessage = BackMessage.Mid(7).TrimEnd(); + break; + } + else + { + // Keep going + } + } + return true; + } + +private: + bool ReadMessage(FString &OutMessage) + { + while (1) + { + for (int32 i = 0; i < ReceivedMessage.Num(); ++i) + { + if (ReceivedMessage[i] == '\0') + { + OutMessage = FString(UTF8_TO_TCHAR(ReceivedMessage.GetData())); + ReceivedMessage.RemoveAt(0, i + 1); + return true; + } + } + + int32 ExtraSpace = 64; + int32 CurrentSize = ReceivedMessage.Num(); + ReceivedMessage.SetNum(CurrentSize + ExtraSpace); + int32 ActualRead = 0; + if (!Socket->Wait(ESocketWaitConditions::WaitForRead, FTimespan::FromSeconds(10))) + { + return false; + } + else if (!Socket->Recv((uint8 *)ReceivedMessage.GetData() + CurrentSize, ExtraSpace, ActualRead)) + { + return false; + } + ReceivedMessage.SetNum(CurrentSize + ActualRead); + } + } + + ISocketSubsystem *SocketSubsystem; + FSocket *Socket; + TArray ReceivedMessage; +}; + +class FFMODStudioEditorModule : public IFMODStudioEditorModule +{ +public: + /** IModuleInterface implementation */ + FFMODStudioEditorModule() + : bSimulating(false) + , bIsInPIE(false) + , bRegisteredComponentVisualizers(false) + , bRunningTest(false) + , TestDelay(0.0f) + , TestStep(0) + { + } + + virtual void StartupModule() override; + virtual void PostLoadCallback() override; + virtual void ShutdownModule() override; + + bool HandleSettingsSaved(); + + /** Called after all banks were reloaded by the studio module */ + void HandleBanksReloaded(); + + /** Show notification */ + void ShowNotification(const FText &Text, SNotificationItem::ECompletionState State); + + void BeginPIE(bool simulating); + void EndPIE(bool simulating); + void PausePIE(bool simulating); + void ResumePIE(bool simulating); + + void ViewportDraw(UCanvas *Canvas, APlayerController *); + + bool Tick(float DeltaTime); + + /** Add extensions to menu */ + void RegisterHelpMenuEntries(); + void AddFileMenuExtension(FMenuBuilder &MenuBuilder); + + /** Show FMOD version */ + void ShowVersion(); + /** Open CHM */ + void OpenIntegrationDocs(); + /** Open web page to online docs */ + void OpenAPIDocs(); + /** Open Video tutorials page */ + void OpenVideoTutorials(); + /** Set Studio build path */ + void ValidateFMOD(); + + /** Helper to get Studio project locales */ + bool GetStudioLocales(FFMODStudioLink &StudioLink, TArray &StudioLocales); + + /** Reload banks */ + void ReloadBanks(); + + /** Callback for the main frame finishing load */ + void OnMainFrameLoaded(TSharedPtr InRootWindow, bool bIsNewProjectWindow); + + /** Callbacks for bad settings notification buttons */ + void OnBadSettingsPopupSettingsClicked(); + void OnBadSettingsPopupDismissClicked(); + + void TickTest(float DeltaTime); + + TArray RegisteredComponentClassNames; + void RegisterComponentVisualizer(FName ComponentClassName, TSharedPtr Visualizer); + + /** The delegate to be invoked when this profiler manager ticks. */ + FTickerDelegate OnTick; + + /** Handle for registered delegates. */ + FDelegateHandle TickDelegateHandle; + FDelegateHandle BeginPIEDelegateHandle; + FDelegateHandle EndPIEDelegateHandle; + FDelegateHandle PausePIEDelegateHandle; + FDelegateHandle ResumePIEDelegateHandle; + FDelegateHandle HandleBanksReloadedDelegateHandle; + FDelegateHandle FMODControlTrackEditorCreateTrackEditorHandle; + FDelegateHandle FMODParamTrackEditorCreateTrackEditorHandle; + + /** Hook for drawing viewport */ + FDebugDrawDelegate ViewportDrawingDelegate; + FDelegateHandle ViewportDrawingDelegateHandle; + + TSharedPtr AssetBroker; + + /** The extender to pass to the level editor to extend its window menu */ + TSharedPtr MainMenuExtender; + + /** Asset type actions for events (edit, play, stop) */ + TSharedPtr FMODEventAssetTypeActions; + + ISettingsSectionPtr SettingsSection; + + /** Notification popup that settings are bad */ + TWeakPtr BadSettingsNotification; + + bool bSimulating; + bool bIsInPIE; + bool bRegisteredComponentVisualizers; + bool bRunningTest; + float TestDelay; + int TestStep; +}; + +IMPLEMENT_MODULE(FFMODStudioEditorModule, FMODStudioEditor) + +void FFMODStudioEditorModule::StartupModule() +{ + UE_LOG(LogFMOD, Log, TEXT("FFMODStudioEditorModule startup")); + + AssetBroker = MakeShareable(new FFMODAssetBroker); + FComponentAssetBrokerage::RegisterBroker(AssetBroker, UFMODAudioComponent::StaticClass(), true, true); + + if (ISettingsModule *SettingsModule = FModuleManager::GetModulePtr("Settings")) + { + SettingsSection = SettingsModule->RegisterSettings("Project", "Plugins", "FMODStudio", LOCTEXT("FMODStudioSettingsName", "FMOD Studio"), + LOCTEXT("FMODStudioDescription", "Configure the FMOD Studio plugin"), GetMutableDefault()); + + if (SettingsSection.IsValid()) + { + SettingsSection->OnModified().BindRaw(this, &FFMODStudioEditorModule::HandleSettingsSaved); + } + } + + // Register with the sequencer module that we provide auto-key handlers. + ISequencerModule &SequencerModule = FModuleManager::Get().LoadModuleChecked("Sequencer"); + FMODControlTrackEditorCreateTrackEditorHandle = + SequencerModule.RegisterTrackEditor(FOnCreateTrackEditor::CreateStatic(&FFMODEventControlTrackEditor::CreateTrackEditor)); + FMODParamTrackEditorCreateTrackEditorHandle = + SequencerModule.RegisterTrackEditor(FOnCreateTrackEditor::CreateStatic(&FFMODEventParameterTrackEditor::CreateTrackEditor)); + SequencerModule.RegisterChannelInterface(); + + // Register the details customizations + { + FPropertyEditorModule &PropertyModule = FModuleManager::LoadModuleChecked("PropertyEditor"); + + PropertyModule.RegisterCustomClassLayout( + UFMODSettings::StaticClass()->GetFName(), + FOnGetDetailCustomizationInstance::CreateStatic(&FFMODSettingsCustomization::MakeInstance) + ); + + PropertyModule.RegisterCustomClassLayout( + "FMODAudioComponent", FOnGetDetailCustomizationInstance::CreateStatic(&FFMODAudioComponentDetails::MakeInstance)); + PropertyModule.NotifyCustomizationModuleChanged(); + } + + // Need to load the editor module since it gets created after us, and we can't re-order ourselves otherwise our asset registration stops working! + // It only works if we are running the editor, not a commandlet + if (!IsRunningCommandlet() && !IsRunningGame() && FSlateApplication::IsInitialized()) + { + FLevelEditorModule *LevelEditor = FModuleManager::LoadModulePtr(TEXT("LevelEditor")); + if (LevelEditor) + { + RegisterHelpMenuEntries(); + MainMenuExtender = MakeShareable(new FExtender); + MainMenuExtender->AddMenuExtension("FileLoadAndSave", EExtensionHook::After, NULL, + FMenuExtensionDelegate::CreateRaw(this, &FFMODStudioEditorModule::AddFileMenuExtension)); + LevelEditor->GetMenuExtensibilityManager()->AddExtender(MainMenuExtender); + } + } + + // Register AssetTypeActions + IAssetTools &AssetTools = FModuleManager::GetModuleChecked("AssetTools").Get(); + + FMODEventAssetTypeActions = MakeShareable(new FAssetTypeActions_FMODEvent); + AssetTools.RegisterAssetTypeActions(FMODEventAssetTypeActions.ToSharedRef()); + + // Register slate style overrides + FFMODStudioStyle::Initialize(); + + BeginPIEDelegateHandle = FEditorDelegates::BeginPIE.AddRaw(this, &FFMODStudioEditorModule::BeginPIE); + EndPIEDelegateHandle = FEditorDelegates::EndPIE.AddRaw(this, &FFMODStudioEditorModule::EndPIE); + PausePIEDelegateHandle = FEditorDelegates::PausePIE.AddRaw(this, &FFMODStudioEditorModule::PausePIE); + ResumePIEDelegateHandle = FEditorDelegates::ResumePIE.AddRaw(this, &FFMODStudioEditorModule::ResumePIE); + + ViewportDrawingDelegate = FDebugDrawDelegate::CreateRaw(this, &FFMODStudioEditorModule::ViewportDraw); + ViewportDrawingDelegateHandle = UDebugDrawService::Register(TEXT("Editor"), ViewportDrawingDelegate); + + OnTick = FTickerDelegate::CreateRaw(this, &FFMODStudioEditorModule::Tick); + TickDelegateHandle = FTicker::GetCoreTicker().AddTicker(OnTick); + + // This module is loaded after FMODStudioModule + HandleBanksReloadedDelegateHandle = IFMODStudioModule::Get().BanksReloadedEvent().AddRaw(this, &FFMODStudioEditorModule::HandleBanksReloaded); + + if (FParse::Param(FCommandLine::Get(), TEXT("fmodtest"))) + { + bRunningTest = true; + } + + // Register a callback to validate settings on startup + IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked(TEXT("MainFrame")); + MainFrameModule.OnMainFrameCreationFinished().AddRaw(this, &FFMODStudioEditorModule::OnMainFrameLoaded); +} + +void FFMODStudioEditorModule::RegisterHelpMenuEntries() +{ + FToolMenuOwnerScoped OwnerScoped(this); + UToolMenu* HelpMenu = UToolMenus::Get()->ExtendMenu("LevelEditor.MainMenu.Help"); + FToolMenuSection& Section = HelpMenu->AddSection("FMODHelp", LOCTEXT("FMODHelpLabel", "FMOD Help"), + FToolMenuInsert("HelpBrowse", EToolMenuInsertType::Default)); + Section.AddEntry(FToolMenuEntry::InitMenuEntry( + NAME_None, + LOCTEXT("FMODVersionMenuEntryTitle", "About FMOD Studio"), + LOCTEXT("FMODVersionMenuEntryToolTip", "Shows FMOD Studio version information."), + FSlateIcon(), + FUIAction(FExecuteAction::CreateRaw(this, &FFMODStudioEditorModule::ShowVersion)) + )); + +#if PLATFORM_WINDOWS + Section.AddEntry(FToolMenuEntry::InitMenuEntry( + NAME_None, + LOCTEXT("FMODHelpCHMTitle", "FMOD Documentation..."), + LOCTEXT("FMODHelpCHMToolTip", "Opens the local FMOD documentation."), + FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.BrowseAPIReference"), + FUIAction(FExecuteAction::CreateRaw(this, &FFMODStudioEditorModule::OpenIntegrationDocs)) + )); +#endif + + Section.AddEntry(FToolMenuEntry::InitMenuEntry( + NAME_None, + LOCTEXT("FMODHelpOnlineTitle", "FMOD Online Documentation..."), + LOCTEXT("FMODHelpOnlineToolTip", "Go to the online FMOD documentation."), + FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.BrowseDocumentation"), + FUIAction(FExecuteAction::CreateRaw(this, &FFMODStudioEditorModule::OpenAPIDocs)) + )); + + Section.AddEntry(FToolMenuEntry::InitMenuEntry( + NAME_None, + LOCTEXT("FMODHelpVideosTitle", "FMOD Tutorial Videos..."), + LOCTEXT("FMODHelpVideosToolTip", "Go to the online FMOD tutorial videos."), + FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.Tutorials"), + FUIAction(FExecuteAction::CreateRaw(this, &FFMODStudioEditorModule::OpenVideoTutorials)) + )); + + Section.AddEntry(FToolMenuEntry::InitMenuEntry( + NAME_None, + LOCTEXT("FMODSetStudioBuildTitle", "Validate FMOD"), + LOCTEXT("FMODSetStudioBuildToolTip", "Verifies that FMOD and FMOD Studio are working as expected."), + FSlateIcon(), + FUIAction(FExecuteAction::CreateRaw(this, &FFMODStudioEditorModule::ValidateFMOD)) + )); +} + +void FFMODStudioEditorModule::AddFileMenuExtension(FMenuBuilder &MenuBuilder) +{ + MenuBuilder.BeginSection("FMODFile", LOCTEXT("FMODFileLabel", "FMOD")); + MenuBuilder.AddMenuEntry(LOCTEXT("FMODFileMenuEntryTitle", "Reload Banks"), + LOCTEXT("FMODFileMenuEntryToolTip", "Force a manual reload of all FMOD Studio banks."), FSlateIcon(), + FUIAction(FExecuteAction::CreateRaw(this, &FFMODStudioEditorModule::ReloadBanks))); + MenuBuilder.EndSection(); +} + +unsigned int GetDLLVersion() +{ + // Just grab it from the audition context which is always valid + unsigned int DLLVersion = 0; + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Auditioning); + if (StudioSystem) + { + FMOD::System *LowLevelSystem = nullptr; + if (StudioSystem->getCoreSystem(&LowLevelSystem) == FMOD_OK) + { + LowLevelSystem->getVersion(&DLLVersion); + } + } + return DLLVersion; +} + +FString VersionToString(unsigned int Version) +{ + unsigned int ProductVersion = (Version & 0xffff0000) >> 16; + unsigned int MajorVersion = (Version & 0x0000ff00) >> 8; + unsigned int MinorVersion = (Version & 0x000000ff); + return FString::Printf(TEXT("%x.%02x.%02x"), ProductVersion, MajorVersion, MinorVersion); +} + +unsigned int MakeVersion(unsigned int ProductVersion, unsigned int MajorVersion, unsigned int MinorVersion) +{ + auto EncodeAsHex = [](unsigned int Value) -> unsigned int + { + return 16 * (Value / 10) + Value % 10; + }; + + ProductVersion = EncodeAsHex(ProductVersion); + MajorVersion = EncodeAsHex(MajorVersion); + MinorVersion = EncodeAsHex(MinorVersion); + + return ((ProductVersion & 0xffff) << 16) | ((MajorVersion & 0xff) << 8) | (MinorVersion & 0xff); +} + +unsigned int VersionFromString(FString Version) +{ + unsigned int ProductVersion = 0; + unsigned int MajorVersion = 0; + unsigned int MinorVersion = 0; + TArray VersionFields; + + if (Version.ParseIntoArray(VersionFields, TEXT(".")) == 3) + { + ProductVersion = FCString::Atoi(*VersionFields[0]); + MajorVersion = FCString::Atoi(*VersionFields[1]); + MinorVersion = FCString::Atoi(*VersionFields[2]); + } + + return MakeVersion(ProductVersion, MajorVersion, MinorVersion); +} + +void FFMODStudioEditorModule::ShowVersion() +{ + FString HeaderVersion = VersionToString(FMOD_VERSION); + FString DLLVersion = VersionToString(GetDLLVersion()); + + FText VersionMessage = FText::Format(LOCTEXT("FMODStudio_About", + "FMOD Studio\n\nBuilt Version: {0}\nDLL Version: {1}\n\nCopyright \u00A9 Firelight Technologies Pty " + "Ltd.\n\nSee LICENSE.TXT for additional license information."), + FText::FromString(HeaderVersion), FText::FromString(DLLVersion)); + + FMessageDialog::Open(EAppMsgType::Ok, VersionMessage); +} + +void FFMODStudioEditorModule::OpenIntegrationDocs() +{ + FPlatformProcess::LaunchFileInDefaultExternalApplication(TEXT("https://fmod.com/resources/documentation-ue4")); +} + +void FFMODStudioEditorModule::OpenAPIDocs() +{ + FPlatformProcess::LaunchFileInDefaultExternalApplication(TEXT("https://fmod.com/resources/documentation-api")); +} + +void FFMODStudioEditorModule::OpenVideoTutorials() +{ + FPlatformProcess::LaunchFileInDefaultExternalApplication(TEXT("http://www.youtube.com/user/FMODTV")); +} + +bool FFMODStudioEditorModule::GetStudioLocales(FFMODStudioLink &StudioLink, TArray &StudioLocales) +{ + FString OutMessage; + + if (!StudioLink.Execute(TEXT("studio.project.workspace.locales.length"), OutMessage)) + { + return false; + } + + int NumStudioLocales = FCString::Atoi(*OutMessage); + StudioLocales.Reserve(NumStudioLocales); + + for (int i = 0; i < NumStudioLocales; ++i) + { + FFMODProjectLocale Locale{}; + FString Message = FString::Printf(TEXT("studio.project.workspace.locales[%d].name"), i); + + if (!StudioLink.Execute(*Message, Locale.LocaleName)) + { + return false; + } + + Message = FString::Printf(TEXT("studio.project.workspace.locales[%d].localeCode"), i); + + if (!StudioLink.Execute(*Message, Locale.LocaleCode)) + { + return false; + } + + StudioLocales.Push(Locale); + } + + return true; +} + +void FFMODStudioEditorModule::ValidateFMOD() +{ + int ProblemsFound = 0; + FFMODStudioLink StudioLink; + bool Connected = StudioLink.Connect(); + + if (!Connected) + { + if (EAppReturnType::No == + FMessageDialog::Open(EAppMsgType::YesNo, + LOCTEXT("SetStudioBuildStudioNotRunning", + "FMODStudio does not appear to be running. Only some validation will occur. Do you want to continue anyway?"))) + { + return; + } + } + + unsigned int HeaderVersion = FMOD_VERSION; + unsigned int DLLVersion = GetDLLVersion(); + unsigned int StudioVersion = 0; + + if (Connected) + { + FString StudioVersionString; + + if (StudioLink.Execute(TEXT("studio.version"), StudioVersionString)) + { + // We expect something like "Version xx.yy.zz, 32/64, Some build number" + UE_LOG(LogFMOD, Log, TEXT("Received studio version: %s"), *StudioVersionString); + TArray VersionParts; + + if (StudioVersionString.StartsWith(TEXT("Version ")) && StudioVersionString.ParseIntoArray(VersionParts, TEXT(",")) >= 1) + { + StudioVersion = VersionFromString(VersionParts[0].RightChop(8)); + } + } + } + + if (HeaderVersion != DLLVersion) + { + FText VersionMessage = FText::Format(LOCTEXT("SetStudioBuildStudio_Status", + "The FMOD DLL version is different to the version the integration was built against. This may " + "cause problems running the game.\nBuilt Version: {0}\nDLL Version: {1}\n"), + FText::FromString(VersionToString(HeaderVersion)), FText::FromString(VersionToString(DLLVersion))); + FMessageDialog::Open(EAppMsgType::Ok, VersionMessage); + ProblemsFound++; + } + + if (Connected && StudioVersion != DLLVersion) + { + FText VersionMessage = + FText::Format(LOCTEXT("SetStudioBuildStudio_Version", + "The Studio tool is different to the version the integration was built against. The integration may not be able to " + "load the banks that the tool builds.\n\nBuilt Version: {0}\nDLL Version: {1}\nStudio Version: {2}\n\nWe recommend " + "using the Studio tool that matches the integration.\n\nDo you want to continue with the validation?"), + FText::FromString(VersionToString(HeaderVersion)), FText::FromString(VersionToString(DLLVersion)), + FText::FromString(VersionToString(StudioVersion))); + + if (EAppReturnType::No == FMessageDialog::Open(EAppMsgType::YesNo, VersionMessage)) + { + return; + } + + ProblemsFound++; + } + + UFMODSettings& Settings = *GetMutableDefault(); + + FString FullBankPath = Settings.BankOutputDirectory.Path; + + if (FPaths::IsRelative(FullBankPath)) + { + FullBankPath = FPaths::ProjectContentDir() / FullBankPath; + } + + FString PlatformBankPath = Settings.GetFullBankPath(); + FullBankPath = FPaths::ConvertRelativePathToFull(FullBankPath); + PlatformBankPath = FPaths::ConvertRelativePathToFull(PlatformBankPath); + + if (Connected) + { + // File path was added in FMOD Studio 1.07.00 + FString StudioProjectPath; + FString StudioProjectDir; + + if (StudioVersion >= MakeVersion(1, 7, 0)) + { + StudioLink.Execute(TEXT("studio.project.filePath"), StudioProjectPath); + + if (StudioProjectPath.IsEmpty() || StudioProjectPath == TEXT("undefined")) + { + FMessageDialog::Open(EAppMsgType::Ok, + LOCTEXT("SetStudioBuildStudio_NewProject", + "FMOD Studio has an empty project. Please go to FMOD Studio, and press Save to create your new project.")); + // Just try to save anyway + FString Result; + StudioLink.Execute(TEXT("studio.project.save()"), Result); + } + + StudioLink.Execute(TEXT("studio.project.filePath"), StudioProjectPath); + + if (StudioProjectPath != TEXT("undefined")) + { + StudioProjectDir = FPaths::GetPath(StudioProjectPath); + } + } + + FString StudioPathString; + StudioLink.Execute(TEXT("studio.project.workspace.builtBanksOutputDirectory"), StudioPathString); + + if (StudioPathString == TEXT("undefined")) + { + StudioPathString = TEXT(""); + } + + FString CanonicalBankPath = FullBankPath; + FPaths::CollapseRelativeDirectories(CanonicalBankPath); + FPaths::NormalizeDirectoryName(CanonicalBankPath); + FPaths::RemoveDuplicateSlashes(CanonicalBankPath); + FPaths::NormalizeDirectoryName(CanonicalBankPath); + FString CanonicalStudioPath = StudioPathString; + + if (FPaths::IsRelative(CanonicalStudioPath) && !StudioProjectDir.IsEmpty() && !StudioPathString.IsEmpty()) + { + CanonicalStudioPath = FPaths::Combine(*StudioProjectDir, *CanonicalStudioPath); + } + + FPaths::CollapseRelativeDirectories(CanonicalStudioPath); + FPaths::NormalizeDirectoryName(CanonicalStudioPath); + FPaths::RemoveDuplicateSlashes(CanonicalStudioPath); + FPaths::NormalizeDirectoryName(CanonicalStudioPath); + + if (!FPaths::IsSamePath(CanonicalBankPath, CanonicalStudioPath)) + { + FString BankPathToSet = FullBankPath; + + // Extra logic - if we have put the studio project inside the game project, then make it relative + if (!StudioProjectDir.IsEmpty()) + { + FString GameBaseDir = FPaths::ConvertRelativePathToFull(FPaths::ProjectDir()); + FString BankPathFromGameProject = FullBankPath; + FString StudioProjectFromGameProject = StudioProjectDir; + if (FPaths::MakePathRelativeTo(BankPathFromGameProject, *GameBaseDir) && !BankPathFromGameProject.Contains(TEXT("..")) && + FPaths::MakePathRelativeTo(StudioProjectFromGameProject, *GameBaseDir) && !StudioProjectFromGameProject.Contains(TEXT(".."))) + { + FPaths::MakePathRelativeTo(BankPathToSet, *(StudioProjectDir + TEXT("/"))); + } + } + + ProblemsFound++; + + FText AskMessage = FText::Format(LOCTEXT("SetStudioBuildStudio_Ask", + "FMOD Studio build path should be set up.\n\nCurrent Studio build path: {0}\nNew build path: " + "{1}\n\nDo you want to fix up the project now?"), + FText::FromString(StudioPathString), FText::FromString(BankPathToSet)); + + if (EAppReturnType::Yes == FMessageDialog::Open(EAppMsgType::YesNo, AskMessage)) + { + FString Result; + StudioLink.Execute(*FString::Printf(TEXT("studio.project.workspace.builtBanksOutputDirectory = \"%s\";"), *BankPathToSet), Result); + StudioLink.Execute(TEXT("studio.project.workspace.builtBanksOutputDirectory"), Result); + + if (Result != BankPathToSet) + { + FMessageDialog::Open(EAppMsgType::Ok, + LOCTEXT("SetStudioBuildStudio_Save", + "Failed to set bank directory. Please go to FMOD Studio, and set the bank path in FMOD Studio project settings.")); + } + + FMessageDialog::Open( + EAppMsgType::Ok, LOCTEXT("SetStudioBuildStudio_Save", "Please go to FMOD Studio, save your project and build banks.")); + // Just try to do it again anyway + StudioLink.Execute(TEXT("studio.project.save()"), Result); + StudioLink.Execute(TEXT("studio.project.build()"), Result); + // Pretend settings have changed which will force a reload + IFMODStudioModule::Get().RefreshSettings(); + } + } + + if (StudioVersion >= MakeVersion(2, 0, 0)) + { + // Check whether Studio project locales match those setup in UE4 + TArray StudioLocales; + + if (GetStudioLocales(StudioLink, StudioLocales)) + { + bool bAllMatch = true; + + if (StudioLocales.Num() == Settings.Locales.Num()) + { + for (const FFMODProjectLocale& StudioLocale : StudioLocales) + { + bool bMatch = false; + + for (const FFMODProjectLocale& Locale : Settings.Locales) + { + if (Locale.LocaleCode == StudioLocale.LocaleCode && Locale.LocaleName == StudioLocale.LocaleName) + { + bMatch = true; + break; + } + } + + if (!bMatch) + { + bAllMatch = false; + break; + } + } + } + else + { + bAllMatch = false; + } + + if (!bAllMatch) + { + ProblemsFound++; + FText Message = LOCTEXT("LocalesMismatch", + "The project locales do not match those defined in the FMOD Studio Project.\n"); + FMessageDialog::Open(EAppMsgType::Ok, Message); + } + } + } + } + + bool bAnyBankFiles = false; + + // Check bank path + if (!FPaths::DirectoryExists(FullBankPath) || !FPaths::DirectoryExists(PlatformBankPath)) + { + FText DirMessage = FText::Format(LOCTEXT("SetStudioBuildStudio_Dir", + "The FMOD Content directory does not exist. Please make sure FMOD Studio is exporting banks into the " + "correct location.\n\nBanks should be exported to: {0}\nBanks files should exist in: {1}\n"), + FText::FromString(FullBankPath), FText::FromString(PlatformBankPath)); + FMessageDialog::Open(EAppMsgType::Ok, DirMessage); + ProblemsFound++; + } + else + { + TArray BankFiles; + IFMODStudioModule::Get().GetAllBankPaths(BankFiles, true); + + if (BankFiles.Num() != 0) + { + bAnyBankFiles = true; + } + else + { + FText EmptyBankDirMessage = + FText::Format(LOCTEXT("SetStudioBuildStudio_EmptyBankDir", + "The FMOD Content directory does not have any bank files in them. Please make sure FMOD Studio is exporting banks " + "into the correct location.\n\nBanks should be exported to: {0}\nBanks files should exist in: {1}\n"), + FText::FromString(FullBankPath), FText::FromString(PlatformBankPath)); + FMessageDialog::Open(EAppMsgType::Ok, EmptyBankDirMessage); + ProblemsFound++; + } + } + + // Look for banks that may have failed to load + if (bAnyBankFiles) + { + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Auditioning); + int BankCount = 0; + StudioSystem->getBankCount(&BankCount); + TArray FailedBanks = IFMODStudioModule::Get().GetFailedBankLoads(EFMODSystemContext::Auditioning); + + if (BankCount == 0 || FailedBanks.Num() != 0) + { + FString CombinedBanks; + + for (auto Bank : FailedBanks) + { + CombinedBanks += Bank; + CombinedBanks += TEXT("\n"); + } + + FText BankLoadMessage; + + if (BankCount == 0 && FailedBanks.Num() == 0) + { + BankLoadMessage = LOCTEXT("SetStudioBuildStudio_BankLoad", "Failed to load banks\n"); + } + else if (BankCount == 0) + { + BankLoadMessage = + FText::Format(LOCTEXT("SetStudioBuildStudio_BankLoad", "Failed to load banks:\n{0}\n"), FText::FromString(CombinedBanks)); + } + else + { + BankLoadMessage = + FText::Format(LOCTEXT("SetStudioBuildStudio_BankLoad", "Some banks failed to load:\n{0}\n"), FText::FromString(CombinedBanks)); + } + + FMessageDialog::Open(EAppMsgType::Ok, BankLoadMessage); + ProblemsFound++; + } + else + { + int TotalEventCount = 0; + TArray Banks; + Banks.SetNum(BankCount); + StudioSystem->getBankList(Banks.GetData(), BankCount, &BankCount); + + for (FMOD::Studio::Bank *Bank : Banks) + { + int EventCount = 0; + Bank->getEventCount(&EventCount); + TotalEventCount += EventCount; + } + + if (TotalEventCount == 0) + { + FMessageDialog::Open(EAppMsgType::Ok, + LOCTEXT("SetStudioBuildStudio_NoEvents", + "Banks have been loaded but they didn't have any events in them. Please make sure you have added some events to banks.")); + ProblemsFound++; + } + } + } + + // Look for required plugins that have not been registered + TArray RequiredPlugins = IFMODStudioModule::Get().GetRequiredPlugins(); + + if (RequiredPlugins.Num() != 0 && Settings.PluginFiles.Num() == 0) + { + FString CombinedPlugins; + + for (auto Name : RequiredPlugins) + { + CombinedPlugins += Name; + CombinedPlugins += TEXT("\n"); + } + + FText PluginMessage = + FText::Format(LOCTEXT("SetStudioBuildStudio_Plugins", + "The banks require the following plugins, but no plugin filenames are listed in the settings:\n{0}\n"), + FText::FromString(CombinedPlugins)); + FMessageDialog::Open(EAppMsgType::Ok, PluginMessage); + ProblemsFound++; + } + + // Look for FMOD in packaging settings + UProjectPackagingSettings *PackagingSettings = Cast(UProjectPackagingSettings::StaticClass()->GetDefaultObject()); + bool bPackagingFound = false; + + for (int i = 0; i < PackagingSettings->DirectoriesToAlwaysStageAsNonUFS.Num(); ++i) + { + // We allow subdirectory references, such as "FMOD/Mobile" + if (PackagingSettings->DirectoriesToAlwaysStageAsNonUFS[i].Path.StartsWith(Settings.BankOutputDirectory.Path)) + { + bPackagingFound = true; + break; + } + } + + int OldPackagingIndex = -1; + + for (int i = 0; i < PackagingSettings->DirectoriesToAlwaysStageAsUFS.Num(); ++i) + { + if (PackagingSettings->DirectoriesToAlwaysStageAsUFS[i].Path.StartsWith(Settings.BankOutputDirectory.Path)) + { + OldPackagingIndex = i; + break; + } + } + + if (OldPackagingIndex >= 0) + { + ProblemsFound++; + + FText message = bPackagingFound ? + LOCTEXT("PackagingFMOD_Both", + "FMOD has been added to both the \"Additional Non-Asset Directories to Copy\" and the \"Additional Non-Asset Directories to Package\" " + "lists. It is recommended to remove FMOD from the \"Additional Non-Asset Directories to Package\" list.\n\n" + "Do you want to remove it now?") : + LOCTEXT("PackagingFMOD_AskMove", + "FMOD has been added to the \"Additional Non-Asset Directories to Package\" list. " + "Packaging FMOD content may lead to deadlocks at runtime. " + "It is recommended to move FMOD to the \"Additional Non-Asset Directories to Copy\" list.\n\n" + "Do you want to move it now?"); + + if (EAppReturnType::Yes == FMessageDialog::Open(EAppMsgType::YesNo, message)) + { + PackagingSettings->DirectoriesToAlwaysStageAsUFS.RemoveAt(OldPackagingIndex); + + if (!bPackagingFound) + { + PackagingSettings->DirectoriesToAlwaysStageAsNonUFS.Add(Settings.BankOutputDirectory); + } + + PackagingSettings->UpdateDefaultConfigFile(); + } + } + else if (!bPackagingFound) + { + ProblemsFound++; + + FText message = LOCTEXT("PackagingFMOD_Ask", + "FMOD has not been added to the \"Additional Non-Asset Directories to Copy\" list.\n\nDo you want add it now?"); + + if (EAppReturnType::Yes == FMessageDialog::Open(EAppMsgType::YesNo, message)) + { + PackagingSettings->DirectoriesToAlwaysStageAsNonUFS.Add(Settings.BankOutputDirectory); + PackagingSettings->UpdateDefaultConfigFile(); + } + } + + // Summary + if (ProblemsFound) + { + FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("SetStudioBuildStudio_FinishedBad", "Finished validation.\n")); + } + else + { + FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT("SetStudioBuildStudio_FinishedGood", "Finished validation. No problems detected.\n")); + } +} + +void FFMODStudioEditorModule::ReloadBanks() +{ + // Pretend settings have changed which will force a reload + IFMODStudioModule::Get().RefreshSettings(); +} + +void FFMODStudioEditorModule::OnMainFrameLoaded(TSharedPtr InRootWindow, bool bIsNewProjectWindow) +{ + // Show a popup notification that allows the user to fix bad settings + const UFMODSettings& Settings = *GetDefault(); + + if (Settings.Check() != UFMODSettings::Okay) + { + FNotificationInfo Info(LOCTEXT("BadSettingsPopupTitle", "FMOD Settings Problem Detected")); + Info.bFireAndForget = false; + Info.bUseLargeFont = true; + Info.bUseThrobber = false; + Info.FadeOutDuration = 0.5f; + Info.ButtonDetails.Add(FNotificationButtonInfo(LOCTEXT("BadSettingsPopupSettings", "Settings..."), + LOCTEXT("BadSettingsPopupSettingsTT", "Open the settings editor"), + FSimpleDelegate::CreateRaw(this, &FFMODStudioEditorModule::OnBadSettingsPopupSettingsClicked))); + Info.ButtonDetails.Add(FNotificationButtonInfo(LOCTEXT("BadSettingsPopupDismiss", "Dismiss"), + LOCTEXT("BadSettingsPopupDismissTT", "Dismiss this notification"), + FSimpleDelegate::CreateRaw(this, &FFMODStudioEditorModule::OnBadSettingsPopupDismissClicked))); + + BadSettingsNotification = FSlateNotificationManager::Get().AddNotification(Info); + BadSettingsNotification.Pin()->SetCompletionState(SNotificationItem::CS_Pending); + } +} + +void FFMODStudioEditorModule::OnBadSettingsPopupSettingsClicked() +{ + if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr("Settings")) + { + SettingsModule->ShowViewer("Project", "Plugins", "FMODStudio"); + } + + BadSettingsNotification.Pin()->ExpireAndFadeout(); +} + +void FFMODStudioEditorModule::OnBadSettingsPopupDismissClicked() +{ + BadSettingsNotification.Pin()->ExpireAndFadeout(); +} + +bool FFMODStudioEditorModule::Tick(float DeltaTime) +{ + if (!bRegisteredComponentVisualizers && GUnrealEd != nullptr) + { + // Register component visualizers (GUnrealED is required for this, but not initialized before this module loads, so we have to wait until GUnrealEd is available) + RegisterComponentVisualizer(UFMODAudioComponent::StaticClass()->GetFName(), MakeShareable(new FFMODAudioComponentVisualizer)); + + bRegisteredComponentVisualizers = true; + } + + if (bRunningTest) + { + TickTest(DeltaTime); + } + + // Update listener position for Editor sound system + FMOD::Studio::System *StudioSystem = IFMODStudioModule::Get().GetStudioSystem(EFMODSystemContext::Editor); + if (StudioSystem) + { + if (GCurrentLevelEditingViewportClient) + { + const FVector &ViewLocation = GCurrentLevelEditingViewportClient->GetViewLocation(); + FMatrix CameraToWorld = FRotationMatrix::Make(GCurrentLevelEditingViewportClient->GetViewRotation()); + FVector Up = CameraToWorld.GetUnitAxis(EAxis::Z); + FVector Forward = CameraToWorld.GetUnitAxis(EAxis::X); + + FMOD_3D_ATTRIBUTES Attributes = { { 0 } }; + Attributes.position = FMODUtils::ConvertWorldVector(ViewLocation); + Attributes.forward = FMODUtils::ConvertUnitVector(Forward); + Attributes.up = FMODUtils::ConvertUnitVector(Up); + + verifyfmod(StudioSystem->setListenerAttributes(0, &Attributes)); + } + } + + return true; +} + +void FFMODStudioEditorModule::TickTest(float DeltaTime) +{ + TestDelay -= DeltaTime; + if (TestDelay > 0.0f) + { + return; // Still waiting + } + + // Default time to next step + TestDelay = 1.0f; + TestStep++; + + UE_LOG(LogFMOD, Log, TEXT("Test step %d"), TestStep); + + switch (TestStep) + { + case 1: + { + // Spawn event in level + FString EventPath; + if (FParse::Value(FCommandLine::Get(), TEXT("spawnevent="), EventPath)) + { + UFMODEvent *FoundEvent = IFMODStudioModule::Get().FindEventByName(EventPath); + if (FoundEvent) + { + UActorFactory *ActorFactory = FActorFactoryAssetProxy::GetFactoryForAssetObject(FoundEvent); + if (ActorFactory) + { + AActor *NewActor = ActorFactory->CreateActor(FoundEvent, GWorld->GetCurrentLevel(), FTransform()); + UE_LOG(LogFMOD, Log, TEXT("Placing '%s' in world: New actor %p"), *EventPath, NewActor); + } + else + { + UE_LOG(LogFMOD, Error, TEXT("Failed to find factory for event: '%s'"), *EventPath); + } + } + else + { + UE_LOG(LogFMOD, Error, TEXT("Failed to find event: '%s'"), *EventPath); + } + } + break; + } + case 2: + { + // Save FMOD directory to package + UProjectPackagingSettings *PackagingSettings = + Cast(UProjectPackagingSettings::StaticClass()->GetDefaultObject()); + const UFMODSettings &Settings = *GetDefault(); + PackagingSettings->DirectoriesToAlwaysStageAsNonUFS.Add(Settings.BankOutputDirectory); + PackagingSettings->UpdateDefaultConfigFile(); + break; + } + case 3: + { + // Save map + FEditorFileUtils::SaveDirtyPackages(false, true, false, true, false, false); + break; + } + case 4: + { + // Begin PIE + UWorld *EditorWorld = GEditor->GetEditorWorldContext().World(); + GEditor->PlayInEditor(EditorWorld, false); + break; + } + case 5: + { + // Extra delay + TestDelay = 10.0f; + break; + } + case 6: + { + // Finish test + RequestEngineExit("Test"); + break; + } + } +} + +void FFMODStudioEditorModule::BeginPIE(bool simulating) +{ + UE_LOG(LogFMOD, Verbose, TEXT("FFMODStudioEditorModule BeginPIE: %d"), simulating); + bSimulating = simulating; + bIsInPIE = true; + IFMODStudioModule::Get().SetInPIE(true, simulating); +} + +void FFMODStudioEditorModule::EndPIE(bool simulating) +{ + UE_LOG(LogFMOD, Verbose, TEXT("FFMODStudioEditorModule EndPIE: %d"), simulating); + bSimulating = false; + bIsInPIE = false; + IFMODStudioModule::Get().SetInPIE(false, simulating); +} + +void FFMODStudioEditorModule::PausePIE(bool simulating) +{ + UE_LOG(LogFMOD, Verbose, TEXT("FFMODStudioEditorModule PausePIE%d")); + IFMODStudioModule::Get().SetSystemPaused(true); +} + +void FFMODStudioEditorModule::ResumePIE(bool simulating) +{ + UE_LOG(LogFMOD, Verbose, TEXT("FFMODStudioEditorModule ResumePIE")); + IFMODStudioModule::Get().SetSystemPaused(false); +} + +void FFMODStudioEditorModule::PostLoadCallback() +{ + UE_LOG(LogFMOD, Verbose, TEXT("FFMODStudioEditorModule PostLoadCallback")); +} + +void FFMODStudioEditorModule::ViewportDraw(UCanvas *Canvas, APlayerController *) +{ + // Only want to update based on viewport in simulate mode. + // In PIE/game, we update from the player controller instead. + if (!bSimulating) + { + return; + } + + const FSceneView *View = Canvas->SceneView; + + if (View->Drawer == GCurrentLevelEditingViewportClient) + { + UWorld *World = GCurrentLevelEditingViewportClient->GetWorld(); + const FVector &ViewLocation = GCurrentLevelEditingViewportClient->GetViewLocation(); + + FMatrix CameraToWorld = View->ViewMatrices.GetViewMatrix().InverseFast(); + FVector ProjUp = CameraToWorld.TransformVector(FVector(0, 1000, 0)); + FVector ProjRight = CameraToWorld.TransformVector(FVector(1000, 0, 0)); + + FTransform ListenerTransform(FRotationMatrix::MakeFromZY(ProjUp, ProjRight)); + ListenerTransform.SetTranslation(ViewLocation); + ListenerTransform.NormalizeRotation(); + + IFMODStudioModule::Get().SetListenerPosition(0, World, ListenerTransform, 0.0f); + IFMODStudioModule::Get().FinishSetListenerPosition(1, 0.0f); + } +} + +void FFMODStudioEditorModule::ShutdownModule() +{ + UE_LOG(LogFMOD, Verbose, TEXT("FFMODStudioEditorModule shutdown")); + + if (UObjectInitialized()) + { + // Unregister tick function. + FTicker::GetCoreTicker().RemoveTicker(TickDelegateHandle); + + FEditorDelegates::BeginPIE.Remove(BeginPIEDelegateHandle); + FEditorDelegates::EndPIE.Remove(EndPIEDelegateHandle); + FEditorDelegates::PausePIE.Remove(PausePIEDelegateHandle); + FEditorDelegates::ResumePIE.Remove(ResumePIEDelegateHandle); + + if (ViewportDrawingDelegate.IsBound()) + { + UDebugDrawService::Unregister(ViewportDrawingDelegateHandle); + } + + FComponentAssetBrokerage::UnregisterBroker(AssetBroker); + + if (MainMenuExtender.IsValid()) + { + FLevelEditorModule *LevelEditorModule = FModuleManager::GetModulePtr("LevelEditor"); + if (LevelEditorModule) + { + LevelEditorModule->GetMenuExtensibilityManager()->RemoveExtender(MainMenuExtender); + } + } + } + + if (ISettingsModule *SettingsModule = FModuleManager::GetModulePtr("Settings")) + { + SettingsModule->UnregisterSettings("Project", "Plugins", "FMODStudio"); + } + + // Unregister AssetTypeActions + if (FModuleManager::Get().IsModuleLoaded("AssetTools")) + { + IAssetTools &AssetTools = FModuleManager::GetModuleChecked("AssetTools").Get(); + + AssetTools.UnregisterAssetTypeActions(FMODEventAssetTypeActions.ToSharedRef()); + } + + // Unregister component visualizers + if (GUnrealEd != nullptr) + { + // Iterate over all class names we registered for + for (FName ClassName : RegisteredComponentClassNames) + { + GUnrealEd->UnregisterComponentVisualizer(ClassName); + } + } + + // Unregister sequencer track creation delegates + ISequencerModule *SequencerModule = FModuleManager::GetModulePtr("Sequencer"); + if (SequencerModule != nullptr) + { + SequencerModule->UnRegisterTrackEditor(FMODControlTrackEditorCreateTrackEditorHandle); + SequencerModule->UnRegisterTrackEditor(FMODParamTrackEditorCreateTrackEditorHandle); + } + IFMODStudioModule::Get().BanksReloadedEvent().Remove(HandleBanksReloadedDelegateHandle); +} + +bool FFMODStudioEditorModule::HandleSettingsSaved() +{ + IFMODStudioModule::Get().RefreshSettings(); + + return true; +} + +void FFMODStudioEditorModule::HandleBanksReloaded() +{ + // Show a reload notification + TArray FailedBanks = IFMODStudioModule::Get().GetFailedBankLoads(EFMODSystemContext::Auditioning); + FText Message; + SNotificationItem::ECompletionState State; + if (FailedBanks.Num() == 0) + { + Message = LOCTEXT("FMODBanksReloaded", "Reloaded FMOD Banks\n"); + State = SNotificationItem::CS_Success; + } + else + { + FString CombinedMessage = "Problem loading FMOD Banks:"; + for (auto Entry : FailedBanks) + { + CombinedMessage += TEXT("\n"); + CombinedMessage += Entry; + + UE_LOG(LogFMOD, Warning, TEXT("Problem loading FMOD Bank: %s"), *Entry); + } + + Message = FText::Format(LOCTEXT("FMODBanksReloaded", "{0}"), FText::FromString(CombinedMessage)); + State = SNotificationItem::CS_Fail; + } + ShowNotification(Message, State); +} + +void FFMODStudioEditorModule::ShowNotification(const FText &Text, SNotificationItem::ECompletionState State) +{ + FNotificationInfo Info(Text); + Info.Image = FEditorStyle::GetBrush(TEXT("NoBrush")); + Info.FadeInDuration = 0.1f; + Info.FadeOutDuration = 0.5f; + Info.ExpireDuration = State == SNotificationItem::CS_Fail ? 6.0f : 1.5f; + Info.bUseThrobber = false; + Info.bUseSuccessFailIcons = true; + Info.bUseLargeFont = true; + Info.bFireAndForget = false; + Info.bAllowThrottleWhenFrameRateIsLow = false; + auto NotificationItem = FSlateNotificationManager::Get().AddNotification(Info); + NotificationItem->SetCompletionState(State); + NotificationItem->ExpireAndFadeout(); + + if (GCurrentLevelEditingViewportClient) + { + // Refresh any 3d event visualization + GCurrentLevelEditingViewportClient->bNeedsRedraw = true; + } +} + +void FFMODStudioEditorModule::RegisterComponentVisualizer(FName ComponentClassName, TSharedPtr Visualizer) +{ + if (GUnrealEd != nullptr) + { + GUnrealEd->RegisterComponentVisualizer(ComponentClassName, Visualizer); + } + + RegisteredComponentClassNames.Add(ComponentClassName); + + if (Visualizer.IsValid()) + { + Visualizer->OnRegister(); + } +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODStudioEditorPrivatePCH.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODStudioEditorPrivatePCH.h new file mode 100644 index 0000000..ed30c4d --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODStudioEditorPrivatePCH.h @@ -0,0 +1,19 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. +#pragma once + +#include "Runtime/Engine/Classes/Components/SceneComponent.h" +#include "Runtime/Engine/Classes/Camera/CameraComponent.h" +#include "Runtime/Engine/Classes/Curves/IntegralCurve.h" +#include "Runtime/Engine/Classes/Curves/NameCurve.h" +#include "Runtime/Engine/Classes/Curves/RichCurve.h" +#include "Runtime/MovieScene/Public/MovieScene.h" +#include "Runtime/MovieScene/Public/KeyParams.h" + +#include "Editor/Sequencer/Public/ISectionLayoutBuilder.h" +#include "Editor/Sequencer/Public/ISequencerSection.h" +#include "Editor/Sequencer/Public/MovieSceneTrackEditor.h" +#include "Runtime/MovieScene/Public/MovieSceneCommonHelpers.h" +#include "Runtime/MovieScene/Public/MovieSceneSection.h" +#include "Editor/UnrealEd/Public/ScopedTransaction.h" + +DECLARE_LOG_CATEGORY_EXTERN(LogFMOD, Log, All); \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODStudioStyle.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODStudioStyle.cpp new file mode 100644 index 0000000..3eaca49 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODStudioStyle.cpp @@ -0,0 +1,53 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODStudioStyle.h" +#include "EditorStyle/Public/Interfaces/IEditorStyleModule.h" +#include "Modules/ModuleManager.h" + +#define IMAGE_BRUSH(RelativePath, ...) FSlateImageBrush(Style.RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__) +#define BOX_BRUSH(RelativePath, ...) FSlateBoxBrush(Style.RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__) + +////////////////////////////////////////////////////////////////////////// +// FFMODStudioStyle + +TSharedPtr FFMODStudioStyle::StyleInstance = NULL; + +void FFMODStudioStyle::Initialize() +{ + if (!StyleInstance.IsValid()) + { + StyleInstance = Create(); + } + + SetStyle(StyleInstance.ToSharedRef()); +} + +void FFMODStudioStyle::Shutdown() +{ + ResetToDefault(); + ensure(StyleInstance.IsUnique()); + StyleInstance.Reset(); +} + +TSharedRef FFMODStudioStyle::Create() +{ + IEditorStyleModule &EditorStyle = FModuleManager::LoadModuleChecked(TEXT("EditorStyle")); + TSharedRef StyleRef = EditorStyle.CreateEditorStyleInstance(); + FSlateStyleSet &Style = StyleRef.Get(); + + const FVector2D Icon20x20(20.0f, 20.0f); + const FVector2D Icon40x40(40.0f, 40.0f); + + Style.Set("ClassIcon.FMODAmbientSound", new IMAGE_BRUSH("Icons/AssetIcons/AmbientSound_16x", FVector2D(16.0f, 16.0f))); + Style.Set("ClassThumbnail.FMODAmbientSound", new IMAGE_BRUSH("Icons/AssetIcons/AmbientSound_64x", FVector2D(64.0f, 64.0f))); + + Style.Set("ClassIcon.FMODAudioComponent", new IMAGE_BRUSH("Icons/ActorIcons/SoundActor_16x", FVector2D(16.0f, 16.0f))); + + Style.Set("ClassIcon.FMODAsset", new IMAGE_BRUSH("Icons/ActorIcons/SoundActor_16x", FVector2D(16.0f, 16.0f))); + + return StyleRef; +} + +////////////////////////////////////////////////////////////////////////// + +#undef IMAGE_BRUSH diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODStudioStyle.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODStudioStyle.h new file mode 100644 index 0000000..7538758 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/FMODStudioStyle.h @@ -0,0 +1,22 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once +#include "SlateCore/Public/Styling/SlateStyle.h" +#include "EditorStyle/Public/EditorStyleSet.h" + +class FFMODStudioStyle : public FEditorStyle +{ +public: + static void Initialize(); + + static void Shutdown(); + +private: + static TSharedRef Create(); + +private: + static TSharedPtr StyleInstance; + +private: + FFMODStudioStyle() {} +}; diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/SFMODEventEditorPanel.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/SFMODEventEditorPanel.cpp new file mode 100644 index 0000000..9937416 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/SFMODEventEditorPanel.cpp @@ -0,0 +1,287 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "SFMODEventEditorPanel.h" +#include "FMODStudioModule.h" +#include "FMODUtils.h" +#include "Input/Reply.h" +#include "Widgets/Input/SNumericEntryBox.h" +#include "Widgets/Layout/SExpandableArea.h" +#include "EditorStyle/Public/EditorStyleSet.h" +#include "Widgets/Input/SButton.h" +#include "Widgets/Layout/SScrollBox.h" +#include "fmod_studio.hpp" + +#define LOCTEXT_NAMESPACE "FMODEventEditor" + +SFMODEventEditorPanel::~SFMODEventEditorPanel() +{ +} + +void SFMODEventEditorPanel::Construct(const FArguments &InArgs) +{ + FMODEventEditorPtr = InArgs._FMODEventEditor; + + FMOD::Studio::EventDescription *EventDescription = FMODEventEditorPtr.Pin()->GetEventDescription(); + + TSharedRef ToolbarBorder = ConstructToolbar(EventDescription); + TSharedRef InfoArea = ConstructInfo(EventDescription); + TSharedRef ParametersArea = ConstructParameters(EventDescription); + TSharedRef UserPropertiesArea = ConstructUserProperties(EventDescription); + + TSharedRef ChildWidget = SNew(SVerticalBox) + SVerticalBox::Slot().AutoHeight().Padding(0.0f, 3.0f)[InfoArea] + + SVerticalBox::Slot().AutoHeight().Padding(0.0f, 3.0f)[ParametersArea] + + SVerticalBox::Slot().AutoHeight().Padding(0.0f, 3.0f)[UserPropertiesArea]; + + ChildSlot[SNew(SVerticalBox) + SVerticalBox::Slot().AutoHeight().Padding(0.0f, 3.0f)[ToolbarBorder] + + SVerticalBox::Slot().FillHeight( + 1.0f)[SNew(SScrollBox) + + SScrollBox::Slot().Padding(0.0f)[SNew(SVerticalBox) + SVerticalBox::Slot().AutoHeight().Padding(0.0f)[ChildWidget]]]]; +} + +TSharedRef SFMODEventEditorPanel::ConstructToolbar(FMOD::Studio::EventDescription *EventDescription) +{ + float MinDistance = 0.0f; + float MaxDistance = 0.0f; + int32 EventLengthMS = 0; + bool bIsOneshot = false, bIsStream = false, bIs3D = false; + if (EventDescription != nullptr) + { + EventDescription->getMinimumDistance(&MinDistance); + EventDescription->getMaximumDistance(&MaxDistance); + EventDescription->getLength(&EventLengthMS); + EventDescription->isOneshot(&bIsOneshot); + EventDescription->isStream(&bIsStream); + EventDescription->is3D(&bIs3D); + } + + const FTimespan EventLength = FTimespan::FromMilliseconds((double)EventLengthMS); + const FString EventLengthString = + EventLength.GetHours() <= 0 ? EventLength.ToString(TEXT("%m:%s.%f")) : EventLength.ToString(TEXT("%h:%m:%s.%f")); + + const FText RadiusText = + FText::Format(LOCTEXT("RadiusFormat", "Distance Attenuation: {0}m to {1}m"), FText::AsNumber(MinDistance), FText::AsNumber(MaxDistance)); + const FText LengthText = FText::Format(LOCTEXT("LengthFormat", "Length: {0}"), FText::FromString(EventLengthString)); + + FText EventInfoText; + if (bIs3D && bIsOneshot) + { + EventInfoText = FText::Format(LOCTEXT("RadiusLengthFormat", "{0} - {1}"), RadiusText, LengthText); + } + else if (!bIs3D && bIsOneshot) + { + EventInfoText = LengthText; + } + else if (bIs3D && !bIsOneshot) + { + EventInfoText = RadiusText; + } + + return SNew(SBorder) + .BorderImage(FEditorStyle::Get().GetBrush("ToolPanel.GroupBorder")) + .Padding(6.0f) + .Content()[SNew(SHorizontalBox) + + SHorizontalBox::Slot() + .AutoWidth() + .Padding(0.0f, 0.0f, 2.0f, 0.0f) + .VAlign(VAlign_Center) + .HAlign(HAlign_Left)[SNew(SButton) + .VAlign(VAlign_Center) + .Text(LOCTEXT("Play", "Play")) + .ContentPadding(4) + .OnClicked(this, &SFMODEventEditorPanel::OnClickedPlay)] + + SHorizontalBox::Slot() + .AutoWidth() + .Padding(2.0f, 0.0f) + .VAlign(VAlign_Center) + .HAlign(HAlign_Left) + [SNew(SButton).Text(LOCTEXT("Pause", "Pause")).ContentPadding(4).OnClicked(this, &SFMODEventEditorPanel::OnClickedPause)] + + SHorizontalBox::Slot() + .AutoWidth() + .Padding(2.0f, 0.0f) + .VAlign(VAlign_Center) + .HAlign(HAlign_Left)[SNew(SButton) + .VAlign(VAlign_Center) + .Text(LOCTEXT("Stop", "Stop")) + .ContentPadding(4) + .OnClicked(this, &SFMODEventEditorPanel::OnClickedStop)] + + SHorizontalBox::Slot() + .FillWidth(1.0f) + .Padding(2.0f, 0.0f) + .VAlign(VAlign_Center) + .HAlign(HAlign_Right)[SNew(STextBlock).Text(EventInfoText)]]; +} + +void AddTextField(TSharedRef &InfoBox, const TCHAR *Name, const FText &Value) +{ + InfoBox->AddSlot().Padding( + 4.0f, 3.0f)[SNew(SHorizontalBox) + SHorizontalBox::Slot().FillWidth(0.3f)[SNew(STextBlock).Text(FText::FromString(Name))] + + SHorizontalBox::Slot()[SNew(SEditableText).Text(Value).IsReadOnly(true)]]; +} + +void AddBoolField(TSharedRef &InfoBox, const TCHAR *Name, bool bValue) +{ + AddTextField(InfoBox, Name, bValue ? LOCTEXT("True", "True") : LOCTEXT("False", "False")); +} + +void AddFloatField(TSharedRef &InfoBox, const TCHAR *Name, float Value) +{ + AddTextField(InfoBox, Name, FText::AsNumber(Value)); +} + +TSharedRef MakeBox(TSharedRef &InfoBox, const FText &Value) +{ + return SNew(SExpandableArea) + .AreaTitle(Value) + .InitiallyCollapsed(false) + .BodyContent()[SNew(SBorder).BorderImage(FCoreStyle::Get().GetBrush("NoBorder")).Padding(4.0f).Content()[InfoBox]]; +} + +TSharedRef SFMODEventEditorPanel::ConstructInfo(FMOD::Studio::EventDescription *EventDescription) +{ + TSharedRef InfoBox = SNew(SVerticalBox); + + if (EventDescription != nullptr) + { + FString EventPath = FMODUtils::GetPath(EventDescription); + FGuid Guid = FMODUtils::GetID(EventDescription); + + int Length = 0.0f; + float MinDist = 0.0f; + float MaxDist = 0.0f; + EventDescription->getLength(&Length); + EventDescription->getMinimumDistance(&MinDist); + EventDescription->getMaximumDistance(&MaxDist); + + bool bOneShot = false; + bool bStream = false; + bool b3D = false; + EventDescription->isOneshot(&bOneShot); + EventDescription->isStream(&bStream); + EventDescription->is3D(&b3D); + + AddTextField(InfoBox, TEXT("Path"), FText::FromString(EventPath)); + AddTextField(InfoBox, TEXT("Guid"), FText::FromString(Guid.ToString(EGuidFormats::DigitsWithHyphensInBraces))); + AddBoolField(InfoBox, TEXT("OneShot"), bOneShot); + AddBoolField(InfoBox, TEXT("Streaming"), bStream); + AddBoolField(InfoBox, TEXT("3D"), b3D); + + AddFloatField(InfoBox, TEXT("Length"), static_cast(Length)); + if (b3D) + { + AddFloatField(InfoBox, TEXT("Min Dist"), MinDist); + AddFloatField(InfoBox, TEXT("Max Dist"), MaxDist); + } + } + + return MakeBox(InfoBox, LOCTEXT("EventInfo", "Event Info")); +} + +TSharedRef SFMODEventEditorPanel::ConstructParameters(FMOD::Studio::EventDescription *EventDescription) +{ + auto EventEditor = FMODEventEditorPtr.Pin(); + TSharedRef ParametersBox = SNew(SVerticalBox); + + FNumberFormattingOptions Options; + Options.MinimumFractionalDigits = 1; + + if (EventDescription != nullptr) + { + int32 ParameterCount; + EventDescription->getParameterDescriptionCount(&ParameterCount); + for (int32 ParamIdx = 0; ParamIdx < ParameterCount; ParamIdx++) + { + FMOD_STUDIO_PARAMETER_DESCRIPTION Parameter; + EventDescription->getParameterDescriptionByIndex(ParamIdx, &Parameter); + + EventEditor->AddParameter(Parameter.id, Parameter.minimum); + + const FString ParameterName = Parameter.type == FMOD_STUDIO_PARAMETER_GAME_CONTROLLED ? FString(UTF8_TO_TCHAR(Parameter.name)) : + FMODUtils::ParameterTypeToString(Parameter.type); + const FText ToolTipText = FText::Format(LOCTEXT("ParameterTooltipFormat", "{0} (Min Value: {1} - Max Value: {2})"), + FText::FromString(ParameterName), FText::AsNumber(Parameter.minimum, &Options), FText::AsNumber(Parameter.maximum, &Options)); + + ParametersBox->AddSlot().Padding(4.0f, + 2.0f)[SNew(SHorizontalBox).ToolTipText(ToolTipText) + + SHorizontalBox::Slot().FillWidth(0.3f)[SNew(STextBlock).Text(FText::FromString(ParameterName))] + + SHorizontalBox::Slot().MaxWidth(200.0f)[SNew(SNumericEntryBox) + .Value(this, &SFMODEventEditorPanel::GetParameterValue, Parameter.id) + .OnValueChanged(this, &SFMODEventEditorPanel::OnParameterValueChanged, Parameter.id) + .AllowSpin(true) + .MinValue(Parameter.minimum) + .MaxValue(Parameter.maximum) + .MinSliderValue(Parameter.minimum) + .MaxSliderValue(Parameter.maximum) + .Delta(0.01f)]]; + } + } + + return MakeBox(ParametersBox, LOCTEXT("EventParameters", "Event Parameters")); +} + +TSharedRef SFMODEventEditorPanel::ConstructUserProperties(FMOD::Studio::EventDescription *EventDescription) +{ + TSharedRef UserPropertiesBox = SNew(SVerticalBox); + + if (EventDescription != nullptr) + { + int32 UserPropertyCount; + EventDescription->getUserPropertyCount(&UserPropertyCount); + for (int32 PropertyIdx = 0; PropertyIdx < UserPropertyCount; PropertyIdx++) + { + FMOD_STUDIO_USER_PROPERTY UserProperty; + EventDescription->getUserPropertyByIndex(PropertyIdx, &UserProperty); + + FText PropertyText; + switch (UserProperty.type) + { + case FMOD_STUDIO_USER_PROPERTY_TYPE_INTEGER: + PropertyText = FText::AsNumber(UserProperty.intvalue); + break; + case FMOD_STUDIO_USER_PROPERTY_TYPE_BOOLEAN: + PropertyText = UserProperty.boolvalue ? LOCTEXT("True", "True") : LOCTEXT("False", "False"); + break; + case FMOD_STUDIO_USER_PROPERTY_TYPE_FLOAT: + PropertyText = FText::AsNumber(UserProperty.floatvalue); + break; + case FMOD_STUDIO_USER_PROPERTY_TYPE_STRING: + PropertyText = FText::FromString(UTF8_TO_TCHAR(UserProperty.stringvalue)); + break; + } + + FString UserName(UTF8_TO_TCHAR(UserProperty.name)); + AddTextField(UserPropertiesBox, *UserName, PropertyText); + } + } + + return MakeBox(UserPropertiesBox, LOCTEXT("EventUserProperties", "Event User Properties")); +} + +FReply SFMODEventEditorPanel::OnClickedPlay() +{ + FMODEventEditorPtr.Pin()->PlayEvent(); + return FReply::Handled(); +} + +FReply SFMODEventEditorPanel::OnClickedStop() +{ + FMODEventEditorPtr.Pin()->StopEvent(); + return FReply::Handled(); +} + +FReply SFMODEventEditorPanel::OnClickedPause() +{ + FMODEventEditorPtr.Pin()->PauseEvent(); + return FReply::Handled(); +} + +void SFMODEventEditorPanel::OnParameterValueChanged(float NewValue, FMOD_STUDIO_PARAMETER_ID ParameterId) +{ + FMODEventEditorPtr.Pin()->SetParameterValue(ParameterId, NewValue); +} + +TOptional SFMODEventEditorPanel::GetParameterValue(FMOD_STUDIO_PARAMETER_ID ParameterId) const +{ + return FMODEventEditorPtr.Pin()->GetParameterValue(ParameterId); +} + +#undef LOC_NAMESPACE diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/SFMODEventEditorPanel.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/SFMODEventEditorPanel.h new file mode 100644 index 0000000..ed1e4d5 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/SFMODEventEditorPanel.h @@ -0,0 +1,42 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "FMODEventEditor.h" + +namespace FMOD +{ +namespace Studio +{ +class EventDescription; +} +} + +class SFMODEventEditorPanel : public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SFMODEventEditorPanel) {} + SLATE_ARGUMENT(TWeakPtr, FMODEventEditor) + SLATE_END_ARGS() + + ~SFMODEventEditorPanel(); + + /** SCompoundWidget interface */ + void Construct(const FArguments &InArgs); + +private: + TSharedRef ConstructToolbar(FMOD::Studio::EventDescription *EventDescription); + TSharedRef ConstructInfo(FMOD::Studio::EventDescription *EventDescription); + TSharedRef ConstructParameters(FMOD::Studio::EventDescription *EventDescription); + TSharedRef ConstructUserProperties(FMOD::Studio::EventDescription *EventDescription); + + /** Editor that owns this panel */ + TWeakPtr FMODEventEditorPtr; + + FReply OnClickedPlay(); + FReply OnClickedStop(); + FReply OnClickedPause(); + + TOptional GetParameterValue(FMOD_STUDIO_PARAMETER_ID ParameterId) const; + void OnParameterValueChanged(float NewValue, FMOD_STUDIO_PARAMETER_ID ParameterId); +}; diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODChannelEditors.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODChannelEditors.cpp new file mode 100644 index 0000000..d496bca --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODChannelEditors.cpp @@ -0,0 +1,211 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "Sequencer/FMODChannelEditors.h" +#include "ISequencerChannelInterface.h" +#include "Widgets/DeclarativeSyntaxSupport.h" +#include "Widgets/SCompoundWidget.h" +#include "MovieSceneTimeHelpers.h" +#include "MovieSceneToolHelpers.h" +#include "ScopedTransaction.h" +#include "EditorWidgets/Public/SEnumCombobox.h" +#include "EditorStyleSet.h" + +class SFMODEventControlKeyEditor : public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SFMODEventControlKeyEditor) {} + SLATE_END_ARGS(); + + void Construct(const FArguments &InArgs, TMovieSceneChannelHandle InChannelHandle, + TWeakObjectPtr InWeakSection, TWeakPtr InWeakSequencer, UEnum *InEnum) + { + ChannelHandle = InChannelHandle; + WeakSection = InWeakSection; + WeakSequencer = InWeakSequencer; + + ChildSlot[MovieSceneToolHelpers::MakeEnumComboBox(InEnum, + TAttribute::Create(TAttribute::FGetter::CreateSP(this, &SFMODEventControlKeyEditor::OnGetCurrentValueAsInt)), + SEnumComboBox::FOnEnumSelectionChanged::CreateSP(this, &SFMODEventControlKeyEditor::OnChangeKey))]; + } + +private: + int32 OnGetCurrentValueAsInt() const + { + using namespace MovieScene; + + FMovieSceneByteChannel *Channel = ChannelHandle.Get(); + ISequencer *Sequencer = WeakSequencer.Pin().Get(); + UMovieSceneSection *OwningSection = WeakSection.Get(); + uint8 Result = 0; + + if (Channel && Sequencer && OwningSection) + { + const FFrameTime CurrentTime = MovieScene::ClampToDiscreteRange(Sequencer->GetLocalTime().Time, OwningSection->GetRange()); + EvaluateChannel(Channel, CurrentTime, Result); + } + + return Result; + } + + void SetValue(uint8 InValue) + { + using namespace MovieScene; + using namespace Sequencer; + + UMovieSceneSection *OwningSection = WeakSection.Get(); + if (!OwningSection) + { + return; + } + + OwningSection->SetFlags(RF_Transactional); + + FMovieSceneByteChannel *Channel = ChannelHandle.Get(); + ISequencer *Sequencer = WeakSequencer.Pin().Get(); + + if (!OwningSection->TryModify() || !Channel || !Sequencer) + { + return; + } + + const FFrameNumber CurrentTime = Sequencer->GetLocalTime().Time.FloorToFrame(); + const bool bAutoSetTrackDefaults = Sequencer->GetAutoSetTrackDefaults(); + + EMovieSceneKeyInterpolation Interpolation = Sequencer->GetKeyInterpolation(); + + TArray KeysAtCurrentTime; + Channel->GetKeys(TRange(CurrentTime), nullptr, &KeysAtCurrentTime); + + if (KeysAtCurrentTime.Num() > 0) + { + AssignValue(Channel, KeysAtCurrentTime[0], InValue); + } + else + { + const bool bHasAnyKeys = Channel->GetNumKeys() != 0; + + if (bHasAnyKeys || bAutoSetTrackDefaults == false) + { + // When auto setting track defaults are disabled, add a key even when it's empty so that the changed + // value is saved and is propagated to the property. + AddKeyToChannel(Channel, CurrentTime, InValue, Interpolation); + } + + if (bHasAnyKeys) + { + TRange KeyRange = TRange(CurrentTime); + TRange SectionRange = OwningSection->GetRange(); + + if (!SectionRange.Contains(KeyRange)) + { + OwningSection->SetRange(TRange::Hull(KeyRange, SectionRange)); + } + } + } + + // Always update the default value when auto-set default values is enabled so that the last changes + // are always saved to the track. + if (bAutoSetTrackDefaults) + { + SetChannelDefault(Channel, InValue); + } + } + + void OnChangeKey(int32 Selection, ESelectInfo::Type SelectionType) + { + FScopedTransaction Transaction(FText::FromString("Set FMOD Event Control Key Value")); + SetValue(Selection); + if (ISequencer *Sequencer = WeakSequencer.Pin().Get()) + { + Sequencer->NotifyMovieSceneDataChanged(EMovieSceneDataChangeType::TrackValueChangedRefreshImmediately); + } + } + + TMovieSceneChannelHandle ChannelHandle; + TWeakObjectPtr WeakSection; + TWeakPtr WeakSequencer; +}; + +bool CanCreateKeyEditor(const FMovieSceneByteChannel *Channel) +{ + return true; +} + +TSharedRef CreateKeyEditor(const TMovieSceneChannelHandle &Channel, UMovieSceneSection *Section, + const FGuid &InObjectBindingID, TWeakPtr PropertyBindings, TWeakPtr InSequencer) +{ + const FMovieSceneByteChannel *RawChannel = Channel.Get(); + + if (!RawChannel) + { + return SNullWidget::NullWidget; + } + + UEnum *Enum = RawChannel->GetEnum(); + return SNew(SFMODEventControlKeyEditor, Channel, Section, InSequencer, Enum); +} + +TSharedPtr GetKeyStruct(const TMovieSceneChannelHandle &ChannelHandle, FKeyHandle InHandle) +{ + FFMODEventControlChannel *Channel = ChannelHandle.Get(); + if (!Channel) + { + return nullptr; + } + + TMovieSceneChannelData ChannelData = Channel->GetData(); + const int32 KeyIndex = ChannelData.GetIndex(InHandle); + + if (KeyIndex == INDEX_NONE) + { + return nullptr; + } + + TSharedPtr KeyStruct = MakeShared(FFMODEventControlKeyStruct::StaticStruct()); + FFMODEventControlKeyStruct *Struct = reinterpret_cast(KeyStruct->GetStructMemory()); + + Struct->Time = ChannelData.GetTimes()[KeyIndex]; + Struct->Value = (EFMODEventControlKey)ChannelData.GetValues()[KeyIndex]; + + Struct->KeyStructInterop.Add(FMovieSceneChannelValueHelper(ChannelHandle, &Struct->Value, MakeTuple(InHandle, Struct->Time))); + return KeyStruct; +} + +void DrawKeys(FFMODEventControlChannel *Channel, TArrayView InKeyHandles, TArrayView OutKeyDrawParams) +{ + static const FName KeyLeftBrushName("Sequencer.KeyLeft"); + static const FName KeyRightBrushName("Sequencer.KeyRight"); + static const FName KeyDiamondBrushName("Sequencer.KeyDiamond"); + + const FSlateBrush *LeftKeyBrush = FEditorStyle::GetBrush(KeyLeftBrushName); + const FSlateBrush *RightKeyBrush = FEditorStyle::GetBrush(KeyRightBrushName); + const FSlateBrush *DiamondBrush = FEditorStyle::GetBrush(KeyDiamondBrushName); + + TMovieSceneChannelData ChannelData = Channel->GetData(); + + for (int32 Index = 0; Index < InKeyHandles.Num(); ++Index) + { + FKeyHandle Handle = InKeyHandles[Index]; + + FKeyDrawParams Params; + Params.BorderBrush = Params.FillBrush = DiamondBrush; + + const int32 KeyIndex = ChannelData.GetIndex(Handle); + if (KeyIndex != INDEX_NONE) + { + const EFMODEventControlKey Value = (EFMODEventControlKey)ChannelData.GetValues()[KeyIndex]; + if (Value == EFMODEventControlKey::Play) + { + Params.BorderBrush = Params.FillBrush = LeftKeyBrush; + Params.FillOffset = FVector2D(-1.0f, 1.0f); + } + else if (Value == EFMODEventControlKey::Stop) + { + Params.BorderBrush = Params.FillBrush = RightKeyBrush; + Params.FillOffset = FVector2D(1.0f, 1.0f); + } + } + + OutKeyDrawParams[Index] = Params; + } +} diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODChannelEditors.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODChannelEditors.h new file mode 100644 index 0000000..aaff3e1 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODChannelEditors.h @@ -0,0 +1,43 @@ +#pragma once + +#include "CoreTypes.h" +#include "Templates/SharedPointer.h" +#include "Containers/Array.h" +#include "UObject/ObjectMacros.h" +#include "UObject/Class.h" + +#include "MovieSceneKeyStruct.h" +#include "SequencerChannelTraits.h" +#include "Channels/MovieSceneChannelHandle.h" +#include "Channels/MovieSceneByteChannel.h" +#include "Sequencer/FMODEventControlSection.h" + +#include "FMODChannelEditors.generated.h" + +/** Key editor overrides */ +bool CanCreateKeyEditor(const FMovieSceneByteChannel *Channel); +TSharedRef CreateKeyEditor(const TMovieSceneChannelHandle &Channel, UMovieSceneSection *Section, + const FGuid &InObjectBindingID, TWeakPtr PropertyBindings, TWeakPtr InSequencer); + +/** KeyStruct overrides */ +TSharedPtr GetKeyStruct(const TMovieSceneChannelHandle &Channel, FKeyHandle InHandle); + +/** Key drawing overrides */ +void DrawKeys(FFMODEventControlChannel *Channel, TArrayView InKeyHandles, TArrayView OutKeyDrawParams); + +USTRUCT() +struct FFMODEventControlKeyStruct : public FMovieSceneKeyTimeStruct +{ + GENERATED_BODY(); + + UPROPERTY(EditAnywhere, Category = "Key") + EFMODEventControlKey Value; +}; +template <> +struct TStructOpsTypeTraits : public TStructOpsTypeTraitsBase2 +{ + enum + { + WithCopy = false + }; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODEventControlTrackEditor.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODEventControlTrackEditor.cpp new file mode 100644 index 0000000..b220ed0 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODEventControlTrackEditor.cpp @@ -0,0 +1,190 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODEventControlTrackEditor.h" +#include "Rendering/DrawElements.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "Curves/IntegralCurve.h" +#include "SequencerSectionPainter.h" +#include "EditorStyleSet.h" +#include "Editor/UnrealEdEngine.h" +#include "Sequencer/FMODEventControlSection.h" +#include "Sequencer/FMODEventControlTrack.h" +#include "ISectionLayoutBuilder.h" +#include "FMODAmbientSound.h" +#include "CommonMovieSceneTools.h" +#include "Channels/MovieSceneChannelProxy.h" +#include "Channels/MovieSceneChannelEditorData.h" + +#define LOCTEXT_NAMESPACE "FFMODEventControlTrackEditor" + +FFMODEventControlSection::FFMODEventControlSection(UMovieSceneSection &InSection, TSharedRef InOwningSequencer) + : Section(InSection) + , OwningSequencerPtr(InOwningSequencer) +{ +} + +UMovieSceneSection *FFMODEventControlSection::GetSectionObject() +{ + return &Section; +} + +float FFMODEventControlSection::GetSectionHeight() const +{ + static const float SectionHeight = 20.f; + return SectionHeight; +} + +int32 FFMODEventControlSection::OnPaintSection(FSequencerSectionPainter &InPainter) const +{ + TSharedPtr OwningSequencer = OwningSequencerPtr.Pin(); + + if (!OwningSequencer.IsValid()) + { + return InPainter.LayerId + 1; + } + + const ESlateDrawEffect DrawEffects = InPainter.bParentEnabled ? ESlateDrawEffect::None : ESlateDrawEffect::DisabledEffect; + const FTimeToPixel &TimeToPixelConverter = InPainter.GetTimeConverter(); + + FLinearColor TrackColor; + + // TODO: Set / clip stop time based on event length + UFMODEventControlSection *ControlSection = Cast(&Section); + if (IsValid(ControlSection)) + { + UFMODEventControlTrack *ParentTrack = Cast(ControlSection->GetOuter()); + if (IsValid(ParentTrack)) + { + TrackColor = ParentTrack->GetColorTint(); + } + } + + // TODO: This should only draw the visible ranges. + TArray> DrawRanges; + TOptional CurrentRangeStart; + + if (ControlSection != nullptr) + { + TMovieSceneChannelData ChannelData = ControlSection->ControlKeys.GetData(); + TArrayView Times = ChannelData.GetTimes(); + TArrayView Values = ChannelData.GetValues(); + + for (int32 Index = 0; Index < Times.Num(); ++Index) + { + const double Time = Times[Index] / TimeToPixelConverter.GetTickResolution(); + const EFMODEventControlKey Value = (EFMODEventControlKey)Values[Index]; + + if (Value == EFMODEventControlKey::Play) + { + if (CurrentRangeStart.IsSet() == false) + { + CurrentRangeStart = Time; + } + } + if (Value == EFMODEventControlKey::Stop) + { + if (CurrentRangeStart.IsSet()) + { + DrawRanges.Add(TRange(CurrentRangeStart.GetValue(), Time)); + CurrentRangeStart.Reset(); + } + } + } + } + + if (CurrentRangeStart.IsSet()) + { + DrawRanges.Add(TRange(CurrentRangeStart.GetValue(), OwningSequencer->GetViewRange().GetUpperBoundValue())); + } + + for (const TRange &DrawRange : DrawRanges) + { + float XOffset = TimeToPixelConverter.SecondsToPixel(DrawRange.GetLowerBoundValue()); + float XSize = TimeToPixelConverter.SecondsToPixel(DrawRange.GetUpperBoundValue()) - XOffset; + FSlateDrawElement::MakeBox(InPainter.DrawElements, InPainter.LayerId, + InPainter.SectionGeometry.ToPaintGeometry( + FVector2D(XOffset, (InPainter.SectionGeometry.GetLocalSize().Y - SequencerSectionConstants::KeySize.Y) / 2), + FVector2D(XSize, SequencerSectionConstants::KeySize.Y)), + FEditorStyle::GetBrush("Sequencer.Section.Background"), DrawEffects); + FSlateDrawElement::MakeBox(InPainter.DrawElements, InPainter.LayerId, + InPainter.SectionGeometry.ToPaintGeometry( + FVector2D(XOffset, (InPainter.SectionGeometry.GetLocalSize().Y - SequencerSectionConstants::KeySize.Y) / 2), + FVector2D(XSize, SequencerSectionConstants::KeySize.Y)), + FEditorStyle::GetBrush("Sequencer.Section.BackgroundTint"), DrawEffects, TrackColor); + } + + return InPainter.LayerId + 1; +} + +FFMODEventControlTrackEditor::FFMODEventControlTrackEditor(TSharedRef InSequencer) + : FMovieSceneTrackEditor(InSequencer) +{ +} + +TSharedRef FFMODEventControlTrackEditor::CreateTrackEditor(TSharedRef InSequencer) +{ + return MakeShareable(new FFMODEventControlTrackEditor(InSequencer)); +} + +bool FFMODEventControlTrackEditor::SupportsType(TSubclassOf Type) const +{ + return Type == UFMODEventControlTrack::StaticClass(); +} + +TSharedRef FFMODEventControlTrackEditor::MakeSectionInterface( + UMovieSceneSection &SectionObject, UMovieSceneTrack &Track, FGuid ObjectBinding) +{ + check(SupportsType(SectionObject.GetOuter()->GetClass())); + const TSharedPtr OwningSequencer = GetSequencer(); + return MakeShareable(new FFMODEventControlSection(SectionObject, OwningSequencer.ToSharedRef())); +} + +void FFMODEventControlTrackEditor::BuildObjectBindingTrackMenu(FMenuBuilder &MenuBuilder, const TArray &ObjectBindings, const UClass *ObjectClass) +{ + if (ObjectClass->IsChildOf(AFMODAmbientSound::StaticClass()) || ObjectClass->IsChildOf(UFMODAudioComponent::StaticClass())) + { + const TSharedPtr ParentSequencer = GetSequencer(); + + MenuBuilder.AddMenuEntry(LOCTEXT("AddFMODEventControlTrack", "FMOD Event Control Track"), + LOCTEXT("FMODEventControlTooltip", "Adds a track for controlling FMOD event."), FSlateIcon(), + FUIAction(FExecuteAction::CreateSP(this, &FFMODEventControlTrackEditor::AddControlKey, ObjectBindings[0]))); + } +} + +void FFMODEventControlTrackEditor::AddControlKey(const FGuid ObjectGuid) +{ + TSharedPtr SequencerPtr = GetSequencer(); + UObject *Object = SequencerPtr.IsValid() ? SequencerPtr->FindSpawnedObjectOrTemplate(ObjectGuid) : nullptr; + + if (IsValid(Object)) + { + AnimatablePropertyChanged(FOnKeyProperty::CreateRaw(this, &FFMODEventControlTrackEditor::AddKeyInternal, Object)); + } +} + +FKeyPropertyResult FFMODEventControlTrackEditor::AddKeyInternal(FFrameNumber KeyTime, UObject *Object) +{ + FKeyPropertyResult KeyPropertyResult; + + FFindOrCreateHandleResult HandleResult = FindOrCreateHandleToObject(Object); + FGuid ObjectHandle = HandleResult.Handle; + KeyPropertyResult.bHandleCreated |= HandleResult.bWasCreated; + + if (ObjectHandle.IsValid()) + { + FFindOrCreateTrackResult TrackResult = FindOrCreateTrackForObject(ObjectHandle, UFMODEventControlTrack::StaticClass()); + UMovieSceneTrack *Track = TrackResult.Track; + KeyPropertyResult.bTrackCreated |= TrackResult.bWasCreated; + + if (KeyPropertyResult.bTrackCreated && ensure(Track)) + { + UFMODEventControlTrack *EventTrack = Cast(Track); + EventTrack->AddNewSection(KeyTime); + EventTrack->SetDisplayName(LOCTEXT("TrackName", "FMOD Event")); + } + } + + return KeyPropertyResult; +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODEventControlTrackEditor.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODEventControlTrackEditor.h new file mode 100644 index 0000000..e66f457 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODEventControlTrackEditor.h @@ -0,0 +1,59 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "CoreMinimal.h" +#include "Misc/Guid.h" +#include "Templates/SubclassOf.h" +#include "Curves/KeyHandle.h" +#include "ISequencer.h" +#include "MovieSceneTrack.h" +#include "ISequencerSection.h" +#include "ISequencerTrackEditor.h" +#include "MovieSceneTrackEditor.h" + +class FMenuBuilder; +class FSequencerSectionPainter; + +/** FMOD Event control track */ +class FFMODEventControlTrackEditor : public FMovieSceneTrackEditor +{ +public: + FFMODEventControlTrackEditor(TSharedRef InSequencer); + + static TSharedRef CreateTrackEditor(TSharedRef OwningSequencer); + + void AddControlKey(const FGuid ObjectGuid); + + // Begin ISequencerTrackEditor interface + virtual void BuildObjectBindingTrackMenu(FMenuBuilder &MenuBuilder, const TArray &ObjectBindings, const UClass *ObjectClass) override; + virtual TSharedRef MakeSectionInterface( + UMovieSceneSection &SectionObject, UMovieSceneTrack &Track, FGuid ObjectBinding) override; + virtual bool SupportsType(TSubclassOf Type) const override; + // End ISequencerTrackEditor interface + +private: + /** Delegate for AnimatablePropertyChanged in AddKey. */ + virtual FKeyPropertyResult AddKeyInternal(FFrameNumber KeyTime, UObject *Object); +}; + +/** Class for event control sections. */ +class FFMODEventControlSection : public ISequencerSection, public TSharedFromThis +{ +public: + FFMODEventControlSection(UMovieSceneSection &InSection, TSharedRef InOwningSequencer); + + // Begin ISequencerSection interface + virtual UMovieSceneSection *GetSectionObject() override; + virtual float GetSectionHeight() const override; + virtual int32 OnPaintSection(FSequencerSectionPainter &InPainter) const override; + virtual bool SectionIsResizable() const override { return false; } + // End ISequencerSection interface + +private: + /** The section we are visualizing. */ + UMovieSceneSection &Section; + + /** The sequencer that owns this section */ + TWeakPtr OwningSequencerPtr; +}; diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODEventParameterTrackEditor.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODEventParameterTrackEditor.cpp new file mode 100644 index 0000000..95902e6 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODEventParameterTrackEditor.cpp @@ -0,0 +1,156 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODEventParameterTrackEditor.h" +#include "FMODAmbientSound.h" +#include "FMODEvent.h" +#include "FMODStudioModule.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "Sequencer/FMODEventParameterTrack.h" +#include "Sections/MovieSceneParameterSection.h" +#include "Sequencer/FMODParameterSection.h" +#include "SequencerUtilities.h" +#include "fmod_studio.hpp" + +#define LOCTEXT_NAMESPACE "FMODEeventParameterTrackEditor" + +FName FFMODEventParameterTrackEditor::TrackName("FMODEventParameter"); + +FFMODEventParameterTrackEditor::FFMODEventParameterTrackEditor(TSharedRef InSequencer) + : FMovieSceneTrackEditor(InSequencer) +{ +} + +TSharedRef FFMODEventParameterTrackEditor::CreateTrackEditor(TSharedRef OwningSequencer) +{ + return MakeShareable(new FFMODEventParameterTrackEditor(OwningSequencer)); +} + +TSharedRef FFMODEventParameterTrackEditor::MakeSectionInterface( + UMovieSceneSection &SectionObject, UMovieSceneTrack &Track, FGuid ObjectBinding) +{ + UMovieSceneParameterSection *ParameterSection = Cast(&SectionObject); + checkf(ParameterSection != nullptr, TEXT("Unsupported section type.")); + return MakeShareable(new FFMODParameterSection(*ParameterSection)); +} + +TSharedPtr FFMODEventParameterTrackEditor::BuildOutlinerEditWidget( + const FGuid &ObjectBinding, UMovieSceneTrack *Track, const FBuildEditWidgetParams &Params) +{ + UFMODEventParameterTrack *EventParameterTrack = Cast(Track); + + // Create a container edit box + return FSequencerUtilities::MakeAddButton(LOCTEXT("ParameterText", "Parameter"), + FOnGetContent::CreateSP(this, &FFMODEventParameterTrackEditor::OnGetAddParameterMenuContent, ObjectBinding, EventParameterTrack), + Params.NodeIsHovered, + GetSequencer()); +} + +void FFMODEventParameterTrackEditor::BuildObjectBindingTrackMenu(FMenuBuilder &MenuBuilder, const TArray &ObjectBindings, const UClass *ObjectClass) +{ + if (ObjectClass->IsChildOf(AFMODAmbientSound::StaticClass()) || ObjectClass->IsChildOf(UFMODAudioComponent::StaticClass())) + { + const TSharedPtr ParentSequencer = GetSequencer(); + + MenuBuilder.AddMenuEntry(LOCTEXT("AddFMODParameterTrack", "FMOD Event Parameter Track"), + LOCTEXT("AddFMODParameterTrackTooltip", "Adds a track for controlling FMOD event parameter values."), FSlateIcon(), + FUIAction(FExecuteAction::CreateSP(this, &FFMODEventParameterTrackEditor::AddEventParameterTrack, ObjectBindings[0]), + FCanExecuteAction::CreateSP(this, &FFMODEventParameterTrackEditor::CanAddEventParameterTrack, ObjectBindings[0]))); + } +} + +bool FFMODEventParameterTrackEditor::SupportsType(TSubclassOf Type) const +{ + return Type == UFMODEventParameterTrack::StaticClass(); +} + +TSharedRef FFMODEventParameterTrackEditor::OnGetAddParameterMenuContent(FGuid ObjectBinding, UFMODEventParameterTrack *EventParameterTrack) +{ + TSharedPtr SequencerPtr = GetSequencer(); + AFMODAmbientSound *Sound = SequencerPtr.IsValid() ? Cast(SequencerPtr->FindSpawnedObjectOrTemplate(ObjectBinding)) : nullptr; + UFMODAudioComponent *AudioComponent; + + if (IsValid(Sound)) + { + AudioComponent = Sound->AudioComponent; + } + else + { + AudioComponent = SequencerPtr.IsValid() ? Cast(SequencerPtr->FindSpawnedObjectOrTemplate(ObjectBinding)) : nullptr; + } + return BuildParameterMenu(ObjectBinding, EventParameterTrack, AudioComponent); +} + +TSharedRef FFMODEventParameterTrackEditor::BuildParameterMenu( + FGuid ObjectBinding, UFMODEventParameterTrack *EventParameterTrack, UFMODAudioComponent *AudioComponent) +{ + FMenuBuilder AddParameterMenuBuilder(true, nullptr); + + if (IsValid(AudioComponent) && AudioComponent->Event.IsValid()) + { + TArray ParameterNamesAndActions; + TArray ParameterDescriptions; + AudioComponent->Event->GetParameterDescriptions(ParameterDescriptions); + + for (FMOD_STUDIO_PARAMETER_DESCRIPTION &ParameterDescription : ParameterDescriptions) + { + FName ParameterName(ParameterDescription.name); + FExecuteAction InitAction = + FExecuteAction::CreateSP(this, &FFMODEventParameterTrackEditor::AddParameter, ObjectBinding, EventParameterTrack, ParameterName); + FUIAction AddParameterMenuAction(InitAction); + FParameterNameAndAction NameAndAction(ParameterName, AddParameterMenuAction); + ParameterNamesAndActions.Add(NameAndAction); + } + + // Sort and generate menu. + ParameterNamesAndActions.Sort(); + for (FParameterNameAndAction NameAndAction : ParameterNamesAndActions) + { + AddParameterMenuBuilder.AddMenuEntry(FText::FromName(NameAndAction.ParameterName), FText(), FSlateIcon(), NameAndAction.Action); + } + } + return AddParameterMenuBuilder.MakeWidget(); +} + +bool FFMODEventParameterTrackEditor::CanAddEventParameterTrack(FGuid ObjectBinding) +{ + return GetSequencer()->GetFocusedMovieSceneSequence()->GetMovieScene()->FindTrack( + UFMODEventParameterTrack::StaticClass(), ObjectBinding, TrackName) == nullptr; +} + +void FFMODEventParameterTrackEditor::AddEventParameterTrack(FGuid ObjectBinding) +{ + FindOrCreateTrackForObject(ObjectBinding, UFMODEventParameterTrack::StaticClass(), TrackName, true); + GetSequencer()->NotifyMovieSceneDataChanged(EMovieSceneDataChangeType::MovieSceneStructureItemAdded); +} + +void FFMODEventParameterTrackEditor::AddParameter(FGuid ObjectBinding, UFMODEventParameterTrack *EventParameterTrack, FName ParameterName) +{ + UMovieSceneSequence *MovieSceneSequence = GetMovieSceneSequence(); + FFrameNumber KeyTime = GetTimeForKey(); + + for (TWeakObjectPtr<> Object : GetSequencer()->FindObjectsInCurrentSequence(ObjectBinding)) + { + AFMODAmbientSound *Sound = Cast(Object.Get()); + UFMODAudioComponent *AudioComponent = nullptr; + + if (IsValid(Sound)) + { + AudioComponent = Sound->AudioComponent; + } + else + { + AudioComponent = Cast(Object.Get()); + } + + if (IsValid(AudioComponent)) + { + float Value = AudioComponent->GetParameter(ParameterName); + const FScopedTransaction Transaction(LOCTEXT("AddEventParameter", "Add event parameter")); + EventParameterTrack->Modify(); + EventParameterTrack->AddParameterKey(ParameterName, KeyTime, Value); + } + } + GetSequencer()->NotifyMovieSceneDataChanged(EMovieSceneDataChangeType::MovieSceneStructureItemAdded); +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODEventParameterTrackEditor.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODEventParameterTrackEditor.h new file mode 100644 index 0000000..c74babd --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODEventParameterTrackEditor.h @@ -0,0 +1,77 @@ +// Taken from ParticleParameterTrackEditor + +#pragma once +#include "CoreMinimal.h" +#include "Misc/Guid.h" +#include "Templates/SubclassOf.h" +#include "Widgets/SWidget.h" +#include "ISequencer.h" +#include "MovieSceneTrack.h" +#include "ISequencerSection.h" +#include "Framework/Commands/UIAction.h" +#include "ISequencerTrackEditor.h" +#include "MovieSceneTrackEditor.h" + +class FMenuBuilder; +class UFMODEventParameterTrack; +class UFMODAudioComponent; +struct FMOD_STUDIO_PARAMETER_DESCRIPTION; + +/** + * Track editor for material parameters. + */ +class FFMODEventParameterTrackEditor : public FMovieSceneTrackEditor +{ +public: + /** Constructor. */ + FFMODEventParameterTrackEditor(TSharedRef InSequencer); + + /** Virtual destructor. */ + virtual ~FFMODEventParameterTrackEditor() {} + + /** + * Creates an instance of this class. Called by a sequencer. + * + * @param OwningSequencer The sequencer instance to be used by this tool. + * @return The new instance of this class. + */ + static TSharedRef CreateTrackEditor(TSharedRef OwningSequencer); + + // ISequencerTrackEditor interface + + virtual TSharedPtr BuildOutlinerEditWidget( + const FGuid &ObjectBinding, UMovieSceneTrack *Track, const FBuildEditWidgetParams &Params) override; + virtual TSharedRef MakeSectionInterface( + UMovieSceneSection &SectionObject, UMovieSceneTrack &Track, FGuid ObjectBinding) override; + virtual bool SupportsType(TSubclassOf Type) const override; + +private: + static FName TrackName; + + // Struct used for building the parameter menu. + struct FParameterNameAndAction + { + FName ParameterName; + FUIAction Action; + + FParameterNameAndAction(FName InParameterName, FUIAction InAction) + { + ParameterName = InParameterName; + Action = InAction; + } + + bool operator<(FParameterNameAndAction const &Other) const { return ParameterName.FastLess(Other.ParameterName); } + }; + + void BuildObjectBindingTrackMenu(FMenuBuilder &MenuBuilder, const TArray &ObjectBindings, const UClass *ObjectClass); + + /** Provides the contents of the add parameter menu. */ + TSharedRef OnGetAddParameterMenuContent(FGuid ObjectBinding, UFMODEventParameterTrack *EventParameterTrack); + TSharedRef BuildParameterMenu(FGuid ObjectBinding, UFMODEventParameterTrack *EventParameterTrack, UFMODAudioComponent *AudioComponent); + + bool CanAddEventParameterTrack(FGuid ObjectBinding); + void AddEventParameterTrack(FGuid ObjectBinding); + + /** Adds an event parameter and initial key to a track. */ + void AddParameter(FGuid ObjectBinding, UFMODEventParameterTrack *EventParameterTrack, FName ParameterName); +}; diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODParameterSection.cpp b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODParameterSection.cpp new file mode 100644 index 0000000..6a93faf --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODParameterSection.cpp @@ -0,0 +1,25 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#include "FMODParameterSection.h" +#include "ISectionLayoutBuilder.h" +#include "ScopedTransaction.h" +#include "Sections/MovieSceneParameterSection.h" + +#define LOCTEXT_NAMESPACE "FMODParameterSection" + +bool FFMODParameterSection::RequestDeleteKeyArea(const TArray &KeyAreaNamePath) +{ + if (KeyAreaNamePath.Num() == 1) + { + const FScopedTransaction Transaction(LOCTEXT("DeleteEventParameter", "Delete event parameter")); + UMovieSceneParameterSection *ParameterSection = Cast(WeakSection.Get()); + if (ParameterSection->TryModify()) + { + return ParameterSection->RemoveScalarParameter(KeyAreaNamePath[0]); + } + } + + return true; +} + +#undef LOCTEXT_NAMESPACE diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODParameterSection.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODParameterSection.h new file mode 100644 index 0000000..3fc4987 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Private/Sequencer/FMODParameterSection.h @@ -0,0 +1,21 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "ISequencerSection.h" + +class UMovieSceneSection; + +/** A movie scene section for Event parameters. */ +class FFMODParameterSection : public FSequencerSection +{ +public: + FFMODParameterSection(UMovieSceneSection &InSectionObject) + : FSequencerSection(InSectionObject) + { + } + + // Begin ISequencerSection interface + virtual bool RequestDeleteKeyArea(const TArray &KeyAreaNamePath) override; + // End ISequencerSection interface +}; \ No newline at end of file diff --git a/Plugins/FMODStudio/Source/FMODStudioEditor/Public/FMODStudioEditorModule.h b/Plugins/FMODStudio/Source/FMODStudioEditor/Public/FMODStudioEditorModule.h new file mode 100644 index 0000000..b6b9584 --- /dev/null +++ b/Plugins/FMODStudio/Source/FMODStudioEditor/Public/FMODStudioEditorModule.h @@ -0,0 +1,28 @@ +// Copyright (c), Firelight Technologies Pty, Ltd. 2012-2020. + +#pragma once + +#include "Modules/ModuleManager.h" + +/** + * The public interface to this module + */ +class IFMODStudioEditorModule : public IModuleInterface +{ + +public: + /** + * Singleton-like access to this module's interface. This is just for convenience! + * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. + * + * @return Returns singleton instance, loading the module on demand if needed + */ + static inline IFMODStudioEditorModule &Get() { return FModuleManager::LoadModuleChecked("FMODStudioEditor"); } + + /** + * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. + * + * @return True if the module is loaded and ready to use + */ + static inline bool IsAvailable() { return FModuleManager::Get().IsModuleLoaded("FMODStudioEditor"); } +}; diff --git a/Source/JamTeacher.Target.cs b/Source/JamTeacher.Target.cs new file mode 100644 index 0000000..98d4500 --- /dev/null +++ b/Source/JamTeacher.Target.cs @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class JamTeacherTarget : TargetRules +{ + public JamTeacherTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Game; + DefaultBuildSettings = BuildSettingsVersion.V2; + + ExtraModuleNames.AddRange( new string[] { "JamTeacher" } ); + } +} diff --git a/Source/JamTeacher/CtoBPLibrary.cpp b/Source/JamTeacher/CtoBPLibrary.cpp new file mode 100644 index 0000000..6f41785 --- /dev/null +++ b/Source/JamTeacher/CtoBPLibrary.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "CtoBPLibrary.h" + diff --git a/Source/JamTeacher/CtoBPLibrary.h b/Source/JamTeacher/CtoBPLibrary.h new file mode 100644 index 0000000..219f39e --- /dev/null +++ b/Source/JamTeacher/CtoBPLibrary.h @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "CtoBPLibrary.generated.h" + +/** + * + */ +UCLASS() +class JAMTEACHER_API UCtoBPLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +}; diff --git a/Source/JamTeacher/JamTeacher.Build.cs b/Source/JamTeacher/JamTeacher.Build.cs new file mode 100644 index 0000000..19e1f1d --- /dev/null +++ b/Source/JamTeacher/JamTeacher.Build.cs @@ -0,0 +1,23 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using UnrealBuildTool; + +public class JamTeacher : ModuleRules +{ + public JamTeacher(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); + + PrivateDependencyModuleNames.AddRange(new string[] { }); + + // Uncomment if you are using Slate UI + // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); + + // Uncomment if you are using online features + // PrivateDependencyModuleNames.Add("OnlineSubsystem"); + + // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true + } +} diff --git a/Source/JamTeacher/JamTeacher.cpp b/Source/JamTeacher/JamTeacher.cpp new file mode 100644 index 0000000..c80d5c9 --- /dev/null +++ b/Source/JamTeacher/JamTeacher.cpp @@ -0,0 +1,6 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#include "JamTeacher.h" +#include "Modules/ModuleManager.h" + +IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, JamTeacher, "JamTeacher" ); diff --git a/Source/JamTeacher/JamTeacher.h b/Source/JamTeacher/JamTeacher.h new file mode 100644 index 0000000..90aad9e --- /dev/null +++ b/Source/JamTeacher/JamTeacher.h @@ -0,0 +1,6 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" + diff --git a/Source/JamTeacherEditor.Target.cs b/Source/JamTeacherEditor.Target.cs new file mode 100644 index 0000000..7fd219d --- /dev/null +++ b/Source/JamTeacherEditor.Target.cs @@ -0,0 +1,15 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using UnrealBuildTool; +using System.Collections.Generic; + +public class JamTeacherEditorTarget : TargetRules +{ + public JamTeacherEditorTarget(TargetInfo Target) : base(Target) + { + Type = TargetType.Editor; + DefaultBuildSettings = BuildSettingsVersion.V2; + + ExtraModuleNames.AddRange( new string[] { "JamTeacher" } ); + } +}