fmodex/fmod/lib/neural_thx/Limiter.c

111 lines
3.4 KiB
C
Raw Permalink Normal View History

// _____________
// _________________
// _____/~\___________/\_
// ______/\_/\_________/\____
// ______/\___/\_______/\______
// _____/\_____/\_____/\_______
// ____/\_______/\___/\________
// __/\_________/\_/\________
// /\___________/~\_______
// ___________________
// _____________
//
//***************************************************************************//
//* *//
//* Project : Neural Audio *//
//* File : Limiter.c *//
//* Description : Limiter *//
//* Author(s) : Jeff Thompson *//
//* *//
//* Copyright (c) Neural Audio Corp. 2008 *//
//* *//
//***************************************************************************//
#include "Neural_THX_Encoders.h"
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "fmod_types.h"
//***************************************************************************//
//* Limiter_INIT(...) *//
//***************************************************************************//
int Limiter_INIT(float * TempBuffer,
Limiter_Struct * pPtr)
{
pPtr->TempBuffer = TempBuffer;
PeakConverter_INIT(0.0f,0.0f,0.0f,0.0f,0,&pPtr->EnvSmoother);
return NRLSUR_OK;
}
//***************************************************************************//
//* Compressor(...) *//
//***************************************************************************//
int Limiter(float * AudioIn,
float * AudioOut,
float MaxAudioValue,
float Knee, //in dB referenced to zero dB
float Ceiling, //in dB referenced to zero dB
float RiseTime, //in msec
float FallTime, //in msec
unsigned int Framesize,
unsigned int SampleRate,
Limiter_Struct * pPtr)
{
int n;
float fTemp;
if(Knee > Ceiling) Knee = Ceiling;
CopyArray(AudioIn,pPtr->TempBuffer,Framesize);
//First normalize audio
if(MaxAudioValue < (float)FLT_EPSILON)
MaxAudioValue = (float)FLT_EPSILON;
fTemp = 1.0f / MaxAudioValue;
ScaleArray(pPtr->TempBuffer,fTemp,Framesize);
//First convert the audio to the dB domain
AbsValue(pPtr->TempBuffer,Framesize);
MinClip(pPtr->TempBuffer,(float)FLT_EPSILON,Framesize);
MaxClip(pPtr->TempBuffer,1.0f,Framesize);
FastLog10_ARRAY(pPtr->TempBuffer,pPtr->TempBuffer,Framesize);
ScaleArray(pPtr->TempBuffer,20.0f,Framesize);
//Smooth the envelope
PeakConverter(pPtr->TempBuffer,
pPtr->TempBuffer,
RiseTime, //in msec
FallTime, //in msec
-60.0f,
0.0f,
Framesize,
SampleRate,
&pPtr->EnvSmoother);
//Apply the knee and ceiling parameters
for(n = 0; n < (int)Framesize; n++){
fTemp = pPtr->TempBuffer[n];
pPtr->TempBuffer[n] = 0.0f;
if(fTemp > Knee){
pPtr->TempBuffer[n] = 0.5f * (Knee - fTemp);
fTemp = fTemp + pPtr->TempBuffer[n];
}
if(fTemp > Ceiling){
pPtr->TempBuffer[n] += Ceiling - fTemp;
fTemp = fTemp + pPtr->TempBuffer[n];
}
}
//Convert back to linear domain
MaxClip(pPtr->TempBuffer,0.0f,Framesize);
ScaleArray(pPtr->TempBuffer,0.05f,Framesize);
FastPow10_ARRAY(pPtr->TempBuffer,pPtr->TempBuffer,Framesize);
//Limit the audio signal
Multiply2(AudioIn,pPtr->TempBuffer,AudioOut,Framesize);
Ceiling = FMOD_POW(10.0f,0.05f*Ceiling) * MaxAudioValue;
SaturateArray(AudioOut,Ceiling,Framesize);
return NRLSUR_OK;
}