My calculations are working without causing any sound gaps, pops, or crackles; but I cannot hear the changes.
16hz through 500khz at 5db with the high frequencies at -5db should sound like the music is being muffled.
1000hz - 16000hz at 5db with low frequencies at -5db should sound tinny.
FilterSampleProvider:
BiQuadFilter.ProcessSample:
16hz through 500khz at 5db with the high frequencies at -5db should sound like the music is being muffled.
1000hz - 16000hz at 5db with low frequencies at -5db should sound tinny.
FilterSampleProvider:
public class FilterSampleProvider : ISampleProvider
{
private readonly BiQuadFilter[] _sampleFilters;
private readonly WaveFormat _waveFormat;
private readonly ISampleProvider _sampleProvider;
public WaveFormat WaveFormat { get { return _waveFormat; } }
public FilterSampleProvider(ISampleProvider source, BiQuadFilter[] filters)
{
_sampleFilters = filters;
_sampleProvider = source;
_waveFormat = _sampleProvider.WaveFormat;
}
public int Read(float[] buffer, int offset, int sampleCount)
{
var read = _sampleProvider.Read(buffer, offset, sampleCount);
var filterBuffer = new float[buffer.Length];
//cascade the filters
for (var j = _sampleFilters.Length; j-- > 0; )
{
if (j == _sampleFilters.Length - 1)
{
filterBuffer = _sampleFilters[j].ProcessSample(buffer, offset, sampleCount);
continue;
}
filterBuffer = _sampleFilters[j].ProcessSample(filterBuffer, offset, sampleCount);
}
buffer = filterBuffer;
return read;
}
}
I pre-calculate the coefficients when the dbGain or Q changes.BiQuadFilter.ProcessSample:
public float[] ProcessSample(float[] buffer, int offset, int sampleCount)
{
//skip processing if gain is 0 or we are recalculating due to a Gain or Q change
if (_dbGain != 0f && !_calcInProgress)
{
//if Gain or Q changes during this process, ReCalculate will wait. Prevents odd results.
_transformInProgress = true;
var current = new float[buffer.Length];
for (int i = 0; i < sampleCount; i += 2)
{
if (_counter == _blockAlign)
{
_counter = 0;
Reset();
}
//Left channel
var left = (_biQuadLeft.A0 * buffer[offset + i] + _biQuadLeft.A1 * _biQuadLeft.X1 + _biQuadLeft.A2
* _biQuadLeft.X2 - _biQuadLeft.A3 * _biQuadLeft.Y1 - _biQuadLeft.A4 * _biQuadLeft.Y1);
_biQuadLeft.X2 = _biQuadLeft.X1;
_biQuadLeft.X1 = buffer[offset + i];
_biQuadLeft.Y2 = _biQuadLeft.Y1;
_biQuadLeft.Y1 = double.IsNaN(left) ? 0 : left;
current[offset + i] = (float)_biQuadLeft.Y1;
//Right channel
var right = (_biQuadRight.A0 * buffer[offset + i + 1] + _biQuadRight.A1 * _biQuadRight.X1 + _biQuadRight.A2
* _biQuadRight.X2 - _biQuadRight.A3 * _biQuadRight.Y1 - _biQuadRight.A4 * _biQuadRight.Y1);
_biQuadRight.X2 = _biQuadRight.X1;
_biQuadRight.X1 = buffer[offset + i + 1];
_biQuadRight.Y2 = _biQuadRight.Y1;
_biQuadRight.Y1 = double.IsNaN(right) ? 0 : right;
current[offset + i + 1] = (float)_biQuadRight.Y1;
_counter++;
}
_transformInProgress = false;
return current;
}
return buffer;
}
private void Reset()
{
_biQuadLeft.X1 = 0;
_biQuadLeft.X2 = 0;
_biQuadLeft.Y1 = 0;
_biQuadLeft.Y2 = 0;
_biQuadRight.X1 = 0;
_biQuadRight.X2 = 0;
_biQuadRight.Y1 = 0;
_biQuadRight.Y2 = 0;
}