Files
UnrealEngineUWP/Engine/Source/Runtime/AudioExtensions/Public/IAudioModulation.h
rob gay 9b977d30c6 - Fix upcast copy causing parameters to not be cached properly on proxy by removing unnecessary virtual function
- Fix return value improperly assigning value in MixModulatorNode, causing it always to be 0 or 1 based on if the modulator was registered (as return is if the value was found and assigned, and its a boolean cast when the modulator is found)
- Remove unused parameter proxy ModHandle member
- Don't re-register if parameter already registered
- Remove duplicate validation call
#rb helen.yang
#rnx
#jira UE-144721
#preflight 6221645ca00412627d1bfde2

#ROBOMERGE-AUTHOR: rob.gay
#ROBOMERGE-SOURCE: CL 19259386 in //UE5/Release-5.0/... via CL 19260159
#ROBOMERGE-BOT: UE5 (Release-Engine-Staging -> Main) (v924-19243027)

[CL 19263839 by rob gay in ue5-main branch]
2022-03-04 04:11:49 -05:00

292 lines
10 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "AudioDefines.h"
#include "DSP/BufferVectorOperations.h"
#include "IAudioExtensionPlugin.h"
#include "IAudioProxyInitializer.h"
#include "Templates/SharedPointer.h"
#include "UObject/NameTypes.h"
#include "IAudioModulation.generated.h"
// Forward Declarations
class IAudioModulationManager;
class ISoundModulatable;
class USoundModulatorBase;
class UObject;
#if !UE_BUILD_SHIPPING
class FCanvas;
class FCommonViewportClient;
class FViewport;
class UFont;
#endif // !UE_BUILD_SHIPPING
namespace Audio
{
using FModulatorId = uint32;
using FModulatorTypeId = uint32;
using FModulatorHandleId = uint32;
using FModulationUnitConversionFunction = TFunction<void(float& /* OutValueNormalizedToUnit */)>;
using FModulationNormalizedConversionFunction = TFunction<void(float& /* OutValueUnitToNormalized */)>;
using FModulationMixFunction = TFunction<void(float& /* OutNormalizedA */, float /* InNormalizedB */)>;
struct AUDIOEXTENSIONS_API FModulationParameter
{
FModulationParameter();
FModulationParameter(const FModulationParameter& InParam);
FModulationParameter(FModulationParameter&& InParam);
FModulationParameter& operator=(FModulationParameter&& InParam);
FModulationParameter& operator=(const FModulationParameter& InParam);
FName ParameterName;
// Default value of parameter in unit space
float DefaultValue = 1.0f;
// Default minimum value of parameter in unit space
float MinValue = 0.0f;
// Default minimum value of parameter in unit space
float MaxValue = 1.0f;
// Whether or not unit conversion is required
bool bRequiresConversion = false;
#if WITH_EDITORONLY_DATA
FText UnitDisplayName;
#endif // WITH_EDITORONLY_DATA
// Function used to mix normalized values together.
FModulationMixFunction MixFunction;
// Function used to convert value buffer from normalized, unitless space [0.0f, 1.0f] to unit space.
FModulationUnitConversionFunction UnitFunction;
// Function used to convert value buffer from unit space to normalized, unitless [0.0f, 1.0f] space.
FModulationNormalizedConversionFunction NormalizedFunction;
static const FModulationMixFunction& GetDefaultMixFunction();
static const FModulationUnitConversionFunction& GetDefaultUnitConversionFunction();
static const FModulationNormalizedConversionFunction& GetDefaultNormalizedConversionFunction();
};
AUDIOEXTENSIONS_API bool IsModulationParameterRegistered(FName InName);
AUDIOEXTENSIONS_API void RegisterModulationParameter(FName InName, FModulationParameter&& InParameter);
AUDIOEXTENSIONS_API bool UnregisterModulationParameter(FName InName);
AUDIOEXTENSIONS_API void UnregisterAllModulationParameters();
AUDIOEXTENSIONS_API const FModulationParameter& GetModulationParameter(FName InName);
/** Interface for cached off Modulator UObject data used as default settings to
* be converted to instanced proxy data per AudioDevice on the AudioRenderThread.
* If proxy is already active, implementation is expected to ignore register call
* and return existing modulator proxy's type Id & set parameter accordingly.
*/
class AUDIOEXTENSIONS_API IModulatorSettings
{
public:
virtual ~IModulatorSettings() = default;
virtual TUniquePtr<IModulatorSettings> Clone() const = 0;
virtual FModulatorId GetModulatorId() const = 0;
virtual const Audio::FModulationParameter& GetOutputParameter() const = 0;
virtual Audio::FModulatorTypeId Register(
Audio::FModulatorHandleId HandleId,
IAudioModulationManager& InModulation) const = 0;
};
/** Handle to a modulator which interacts with the modulation API to manage lifetime
* of modulator proxy objects internal to modulation plugin implementation.
*/
struct AUDIOEXTENSIONS_API FModulatorHandle
{
FModulatorHandle() = default;
FModulatorHandle(Audio::FModulationParameter&& InParameter);
FModulatorHandle(IAudioModulationManager& InModulation, const Audio::IModulatorSettings& InModulatorSettings, Audio::FModulationParameter&& InParameter);
FModulatorHandle(const FModulatorHandle& InOther);
FModulatorHandle(FModulatorHandle&& InOther);
~FModulatorHandle();
FModulatorHandle& operator=(const FModulatorHandle& InOther);
FModulatorHandle& operator=(FModulatorHandle&& InOther);
FModulatorId GetModulatorId() const;
const FModulationParameter& GetParameter() const;
FModulatorTypeId GetTypeId() const;
FModulatorHandleId GetHandleId() const;
bool GetValue(float& OutValue) const;
bool GetValueThreadSafe(float& OutValue) const;
bool IsValid() const;
private:
FModulationParameter Parameter;
FModulatorHandleId HandleId = INDEX_NONE;
FModulatorTypeId ModulatorTypeId = INDEX_NONE;
FModulatorId ModulatorId = INDEX_NONE;
TWeakPtr<IAudioModulationManager> Modulation;
};
} // namespace Audio
class AUDIOEXTENSIONS_API IAudioModulationManager : public TSharedFromThis<IAudioModulationManager>
{
public:
/** Virtual destructor */
virtual ~IAudioModulationManager() { }
/** Initialize the modulation plugin with the same rate and number of sources */
virtual void Initialize(const FAudioPluginInitializationParams& InitializationParams) { }
virtual void OnAuditionEnd() { }
#if !UE_BUILD_SHIPPING
/** Request to post help from active plugin (non-shipping builds only) */
virtual bool OnPostHelp(FCommonViewportClient* ViewportClient, const TCHAR* Stream) { return false; };
/** Render stats pertaining to modulation (non-shipping builds only) */
virtual int32 OnRenderStat(FViewport* Viewport, FCanvas* Canvas, int32 X, int32 Y, const UFont& Font, const FVector* ViewLocation, const FRotator* ViewRotation) { return Y; }
/** Toggle showing render stats pertaining to modulation (non-shipping builds only) */
virtual bool OnToggleStat(FCommonViewportClient* ViewportClient, const TCHAR* Stream) { return false; }
#endif //!UE_BUILD_SHIPPING
/** Processes audio with the given input and output data structs.*/
virtual void ProcessAudio(const FAudioPluginSourceInputData& InputData, FAudioPluginSourceOutputData& OutputData) { }
/** Processes all modulators Run on the audio render thread prior to processing audio */
virtual void ProcessModulators(const double InElapsed) { }
/** Updates modulator definition on the AudioRender Thread with that provided by the UObject representation */
virtual void UpdateModulator(const USoundModulatorBase& InModulator) { }
protected:
virtual void RegisterModulator(uint32 InHandleId, Audio::FModulatorId InModulatorId) { }
// Get the modulator value from the AudioRender Thread
virtual bool GetModulatorValue(const Audio::FModulatorHandle& ModulatorHandle, float& OutValue) const { return false; }
// Get the modulator value from any thread.
virtual bool GetModulatorValueThreadSafe(const Audio::FModulatorHandle& ModulatorHandle, float& OutValue) const { return false; }
virtual void UnregisterModulator(const Audio::FModulatorHandle& InHandle) { }
friend Audio::FModulatorHandle;
};
/**
* Base class for all modulators
*/
UCLASS(config = Engine, abstract, editinlinenew, BlueprintType)
class AUDIOEXTENSIONS_API USoundModulatorBase : public UObject, public IAudioProxyDataFactory
{
GENERATED_BODY()
public:
virtual const Audio::FModulationParameter& GetOutputParameter() const;
virtual TUniquePtr<Audio::IProxyData> CreateNewProxyData(const Audio::FProxyDataInitParams& InitParams) override;
virtual TUniquePtr<Audio::IModulatorSettings> CreateProxySettings() const;
};
/** Proxy to modulator, allowing for modulator to be referenced by the Audio Render Thread independently
* from the implementing modulation plugin (ex. for MetaSound implementation).
*/
class AUDIOEXTENSIONS_API FSoundModulatorAssetProxy : public Audio::TProxyData<FSoundModulatorAssetProxy>, public TSharedFromThis<FSoundModulatorAssetProxy, ESPMode::ThreadSafe>
{
public:
IMPL_AUDIOPROXY_CLASS(FSoundModulatorAssetProxy);
FSoundModulatorAssetProxy(const FSoundModulatorAssetProxy& InAssetProxy)
: Parameter(InAssetProxy.Parameter)
, ModulatorSettings(InAssetProxy.ModulatorSettings.IsValid() ? InAssetProxy.ModulatorSettings->Clone() : nullptr)
{
}
FSoundModulatorAssetProxy(const USoundModulatorBase& InModulatorBase)
: Parameter(InModulatorBase.GetOutputParameter())
, ModulatorSettings(InModulatorBase.CreateProxySettings())
{
}
virtual Audio::IProxyDataPtr Clone() const
{
return MakeUnique<FSoundModulatorAssetProxy>(*this);
}
virtual Audio::FModulatorHandle CreateModulatorHandle(IAudioModulationManager& InModulation) const
{
check(ModulatorSettings.IsValid());
Audio::FModulationParameter HandleParameter = Parameter;
return Audio::FModulatorHandle(InModulation, *ModulatorSettings.Get(), MoveTemp(HandleParameter));
}
virtual Audio::FModulatorId GetModulatorId() const
{
check(ModulatorSettings.IsValid())
return ModulatorSettings->GetModulatorId();
}
protected:
Audio::FModulationParameter Parameter;
TUniquePtr<Audio::IModulatorSettings> ModulatorSettings;
};
using FSoundModulatorAssetProxyPtr = TSharedPtr<FSoundModulatorAssetProxy, ESPMode::ThreadSafe>;
/** Proxy to modulator, allowing for modulator to be referenced by the Audio Render Thread independently
* from the implementing modulation plugin (ex. for MetaSound implementation).
*/
class AUDIOEXTENSIONS_API FSoundModulationParameterAssetProxy : public Audio::TProxyData<FSoundModulationParameterAssetProxy>, public TSharedFromThis<FSoundModulationParameterAssetProxy, ESPMode::ThreadSafe>
{
public:
IMPL_AUDIOPROXY_CLASS(FSoundModulationParameterAssetProxy);
virtual Audio::IProxyDataPtr Clone() const override
{
return Audio::IProxyDataPtr();
}
virtual const Audio::FModulationParameter& GetParameter() const
{
return Parameter;
}
protected:
Audio::FModulationParameter Parameter;
};
using FSoundModulationParameterAssetProxyPtr = TSharedPtr<FSoundModulationParameterAssetProxy, ESPMode::ThreadSafe>;
/** Interface to sound that is modulatable, allowing for certain specific
* behaviors to be controlled on the sound level by the modulation system.
*/
class AUDIOEXTENSIONS_API ISoundModulatable
{
public:
virtual ~ISoundModulatable() = default;
/**
* Gets the object definition id of the given playing sound's instance
*/
virtual uint32 GetObjectId() const = 0;
/**
* Returns number of actively instances of sound playing (including virtualized instances)
*/
virtual int32 GetPlayCount() const = 0;
/**
* Returns whether or not sound is an editor preview sound
*/
virtual bool IsPreviewSound() const = 0;
/**
* Stops sound.
*/
virtual void Stop() = 0;
};