Code/FX/HighPass.cs
using System;
using Sandbox;
namespace SFXR;
[Title( "High Pass Filter" )]
[Category( "SFXR Effects" )]
[Icon( "align_horizontal_left" )]
public class SFXRHighPass : SFXREffect
{
/// <summary>
/// Cutoff value of the high-pass filter
/// (Default: 0, Range: 0 - 1)
/// </summary>
[Property, Range( 0f, 12000f, 0.01f )]
public float Cutoff { get; set; } = 4000;
/// <summary>
/// Amount by which the high-pass cutoff frequency is increased or decreased over time
/// (Default: 0, Range: -1 - 1)
/// </summary>
[Property, Range( -12000f, 12000f, 0.01f )]
public float Sweep { get; set; } = 0;
/// <summary>
/// Controls the high-pass filter's resonance (peak)
/// (Default: 0, Range: 0 - 1)
/// </summary>
[Property, Range( 0f, 1f, 0.01f )]
public float Resonance { get; set; } = 0;
public override short[] Apply( short[] samples, SFXRComponent sound )
{
short[] outputSamples = new short[samples.Length];
double currentCutoff = Cutoff;
double previousInput = 0;
double previousOutput = 0;
for ( int i = 0; i < samples.Length; i++ )
{
// Update cutoff frequency based on Sweep
currentCutoff += Sweep / (double)sound.SampleRate;
double RC = 1.0 / (2 * Math.PI * currentCutoff);
double dt = 1.0 / (double)sound.SampleRate;
double alpha = RC / (RC + dt);
double inputSample = samples[i];
double outputSample = alpha * (previousOutput + inputSample - previousInput);
// Apply resonance
if ( Resonance > 0 )
{
double feedback = Resonance + Resonance / (1 - currentCutoff);
outputSample = (1 - feedback) * outputSample + feedback * previousOutput;
}
outputSamples[i] = (short)Math.Clamp( outputSample, short.MinValue, short.MaxValue );
previousInput = inputSample;
previousOutput = outputSample;
}
return outputSamples;
}
}