202 lines
4.3 KiB
C++
202 lines
4.3 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "DSP/Amp.h"
|
|
#include "DSP/Dsp.h"
|
|
|
|
namespace Audio
|
|
{
|
|
FAmp::FAmp()
|
|
: VoiceId(0)
|
|
, LeftGain(0.0f)
|
|
, RightGain(0.0f)
|
|
, TargetLeftGain(0.0f)
|
|
, TargetRightGain(0.0f)
|
|
, TargetDeltaSamples(0)
|
|
, CurrentLerpSample(0)
|
|
, TargetLeftSlope(0.0f)
|
|
, TargetRightSlope(0.0f)
|
|
, GainMin(0.0f)
|
|
, GainMax(1.0f)
|
|
, GainControl(1.0f)
|
|
, GainVelocity(1.0f)
|
|
, GainMod(1.0f)
|
|
, GainEnv(1.0f)
|
|
, Pan(0.0f)
|
|
, PanMod(0.0f)
|
|
, ModMatrix(nullptr)
|
|
, bChanged(false)
|
|
{
|
|
}
|
|
|
|
FAmp::~FAmp()
|
|
{
|
|
}
|
|
|
|
void FAmp::Init(const int32 InVoiceId, FModulationMatrix* InModMatrix)
|
|
{
|
|
VoiceId = InVoiceId;
|
|
ModMatrix = InModMatrix;
|
|
|
|
// Number of samples to interpolate
|
|
TargetDeltaSamples = 256;
|
|
|
|
if (ModMatrix)
|
|
{
|
|
GainScaleDest = ModMatrix->CreatePatchDestination(VoiceId, 1, 1.0f);
|
|
GainEnvDest = ModMatrix->CreatePatchDestination(VoiceId, 1, 1.0f);
|
|
GainPanDest = ModMatrix->CreatePatchDestination(VoiceId, 1, 1.0f);
|
|
|
|
GainScaleDest.SetName("GainScaleDest");
|
|
|
|
#if MOD_MATRIX_DEBUG_NAMES
|
|
GainScaleDest.Name = TEXT("GainScaleDest");
|
|
GainEnvDest.Name = TEXT("GainEnvDest");
|
|
GainPanDest.Name = TEXT("GainPanDest");
|
|
#endif
|
|
}
|
|
bChanged = true;
|
|
}
|
|
|
|
void FAmp::SetGainDb(const float InGainDb)
|
|
{
|
|
GainControl = ConvertToLinear(InGainDb);
|
|
bChanged = true;
|
|
}
|
|
|
|
void FAmp::SetGainModDb(const float InGainModDb)
|
|
{
|
|
GainMod = ConvertToLinear(InGainModDb);
|
|
GainMod = GetUnipolar(GainMod);
|
|
bChanged = true;
|
|
}
|
|
|
|
void FAmp::SetGain(const float InGainLinear)
|
|
{
|
|
GainControl = InGainLinear;
|
|
bChanged = true;
|
|
}
|
|
|
|
void FAmp::SetGainMod(const float InBipolarGainModLinear)
|
|
{
|
|
GainMod = GetUnipolar(InBipolarGainModLinear);
|
|
bChanged = true;
|
|
}
|
|
|
|
void FAmp::SetGainEnv(const float InGainEnv)
|
|
{
|
|
GainEnv = InGainEnv;
|
|
bChanged = true;
|
|
}
|
|
|
|
void FAmp::SetGainEnvDb(const float InGainEnvDb)
|
|
{
|
|
GainEnv = ConvertToLinear(InGainEnvDb);
|
|
}
|
|
|
|
void FAmp::SetGainRange(const float InMin, const float InMax)
|
|
{
|
|
GainMin = InMin;
|
|
GainMax = InMax;
|
|
bChanged = true;
|
|
}
|
|
|
|
void FAmp::SetVelocity(const float InVelocity)
|
|
{
|
|
GainVelocity = GetGainFromVelocity(InVelocity);
|
|
bChanged = true;
|
|
}
|
|
|
|
void FAmp::SetPan(const float InPan)
|
|
{
|
|
Pan = InPan;
|
|
bChanged = true;
|
|
}
|
|
|
|
void FAmp::SetPanModulator(const float InPanMod)
|
|
{
|
|
PanMod = InPanMod;
|
|
bChanged = true;
|
|
}
|
|
|
|
void FAmp::Update()
|
|
{
|
|
if (ModMatrix)
|
|
{
|
|
bChanged |= ModMatrix->GetDestinationValue(VoiceId, GainScaleDest, GainMod);
|
|
bChanged |= ModMatrix->GetDestinationValue(VoiceId, GainEnvDest, GainEnv);
|
|
bChanged |= ModMatrix->GetDestinationValue(VoiceId, GainPanDest, PanMod);
|
|
}
|
|
|
|
if (bChanged)
|
|
{
|
|
bChanged = false;
|
|
|
|
// Update the pan values
|
|
const float PanSum = FMath::Clamp(Pan + PanMod, -1.0f, 1.0f);
|
|
float PanLeft = 0.0f;
|
|
float PanRight = 0.0f;
|
|
GetStereoPan(PanSum, PanLeft, PanRight);
|
|
|
|
// Compute the gain product accounting for the gain stages
|
|
// TODO: look at this more closely
|
|
float GainProduct = GainControl * GainMod * GainVelocity * GainEnv;
|
|
|
|
GainProduct = FMath::Clamp(GainProduct, GainMin, GainMax);
|
|
|
|
// Mix in the pan value
|
|
TargetLeftGain = GainProduct * PanLeft;
|
|
TargetRightGain = GainProduct * PanRight;
|
|
|
|
CurrentLerpSample = 0;
|
|
TargetLeftSlope = (TargetLeftGain - LeftGain) / TargetDeltaSamples;
|
|
TargetRightSlope = (TargetRightGain - RightGain) / TargetDeltaSamples;
|
|
}
|
|
}
|
|
|
|
void FAmp::Generate(float& OutGainLeft, float& OutGainRight)
|
|
{
|
|
if (CurrentLerpSample < TargetDeltaSamples)
|
|
{
|
|
LeftGain += TargetLeftSlope;
|
|
RightGain += TargetRightSlope;
|
|
++CurrentLerpSample;
|
|
}
|
|
|
|
OutGainLeft *= LeftGain;
|
|
OutGainRight *= RightGain;
|
|
}
|
|
|
|
void FAmp::ProcessAudio(const float LeftIn, float* LeftOutput, float* RightOutput)
|
|
{
|
|
if (CurrentLerpSample < TargetDeltaSamples)
|
|
{
|
|
LeftGain += TargetLeftSlope;
|
|
RightGain += TargetRightSlope;
|
|
++CurrentLerpSample;
|
|
}
|
|
|
|
*LeftOutput = (LeftIn * LeftGain);
|
|
*RightOutput = (LeftIn * RightGain);
|
|
}
|
|
|
|
void FAmp::ProcessAudio(const float LeftIn, const float RightIn, float* LeftOutput, float* RightOutput)
|
|
{
|
|
if (CurrentLerpSample < TargetDeltaSamples)
|
|
{
|
|
LeftGain += TargetLeftSlope;
|
|
RightGain += TargetRightSlope;
|
|
++CurrentLerpSample;
|
|
}
|
|
|
|
*LeftOutput = (LeftIn * LeftGain);
|
|
*RightOutput = (RightIn * RightGain);
|
|
}
|
|
|
|
void FAmp::Reset()
|
|
{
|
|
GainEnv = 1.0f;
|
|
GainMod = 1.0f;
|
|
}
|
|
|
|
}
|