Ref T730, namespace BiQuadFilter

This commit is contained in:
Klaus Basan
2019-10-05 23:20:33 +02:00
committed by Mat Sutcliffe
parent 1c0dc8b34c
commit 4dbe1c49c8
4 changed files with 147 additions and 112 deletions

View File

@@ -1,101 +1,116 @@
/* Copyright (C) 2019
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
#include "biquadfilter.h"
#include <QtMath>
#include <algorithm>
float BiQuadFilter::transform(float inSample)
namespace BlackSound
{
// compute result
double result = a0 * inSample + a1 * x1 + a2 * x2 - a3 * y1 - a4 * y2;
namespace Dsp
{
float BiQuadFilter::transform(float inSample)
{
// compute result
double result = a0 * inSample + a1 * x1 + a2 * x2 - a3 * y1 - a4 * y2;
// shift x1 to x2, sample to x1
x2 = x1;
x1 = inSample;
// shift x1 to x2, sample to x1
x2 = x1;
x1 = inSample;
// shift y1 to y2, result to y1
y2 = y1;
y1 = (float)result;
// shift y1 to y2, result to y1
y2 = y1;
y1 = static_cast<float>(result);
return y1;
}
return y1;
}
void BiQuadFilter::setCoefficients(double aa0, double aa1, double aa2, double b0, double b1, double b2)
{
// precompute the coefficients
a0 = b0 / aa0;
a1 = b1 / aa0;
a2 = b2 / aa0;
a3 = aa1 / aa0;
a4 = aa2 / aa0;
}
void BiQuadFilter::setCoefficients(double aa0, double aa1, double aa2, double b0, double b1, double b2)
{
// precompute the coefficients
a0 = b0 / aa0;
a1 = b1 / aa0;
a2 = b2 / aa0;
a3 = aa1 / aa0;
a4 = aa2 / aa0;
}
void BiQuadFilter::setLowPassFilter(float sampleRate, float cutoffFrequency, float q)
{
// H(s) = 1 / (s^2 + s/Q + 1)
auto w0 = 2 * M_PI * cutoffFrequency / sampleRate;
auto cosw0 = qCos(w0);
auto alpha = qSin(w0) / (2 * q);
void BiQuadFilter::setLowPassFilter(float sampleRate, float cutoffFrequency, float q)
{
// H(s) = 1 / (s^2 + s/Q + 1)
auto w0 = 2 * M_PI * cutoffFrequency / sampleRate;
auto cosw0 = qCos(w0);
auto alpha = qSin(w0) / (2 * q);
auto b0 = (1 - cosw0) / 2;
auto b1 = 1 - cosw0;
auto b2 = (1 - cosw0) / 2;
auto aa0 = 1 + alpha;
auto aa1 = -2 * cosw0;
auto aa2 = 1 - alpha;
setCoefficients(aa0, aa1, aa2, b0, b1, b2);
}
auto b0 = (1 - cosw0) / 2;
auto b1 = 1 - cosw0;
auto b2 = (1 - cosw0) / 2;
auto aa0 = 1 + alpha;
auto aa1 = -2 * cosw0;
auto aa2 = 1 - alpha;
setCoefficients(aa0, aa1, aa2, b0, b1, b2);
}
void BiQuadFilter::setPeakingEq(float sampleRate, float centreFrequency, float q, float dbGain)
{
// H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1)
auto w0 = 2 * M_PI * centreFrequency / sampleRate;
auto cosw0 = qCos(w0);
auto sinw0 = qSin(w0);
auto alpha = sinw0 / (2 * q);
auto a = qPow(10, dbGain / 40); // TODO: should we square root this value?
void BiQuadFilter::setPeakingEq(float sampleRate, float centreFrequency, float q, float dbGain)
{
// H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1)
auto w0 = 2 * M_PI * centreFrequency / sampleRate;
auto cosw0 = qCos(w0);
auto sinw0 = qSin(w0);
auto alpha = sinw0 / (2 * q);
auto a = qPow(10, dbGain / 40); // TODO: should we square root this value?
auto b0 = 1 + alpha * a;
auto b1 = -2 * cosw0;
auto b2 = 1 - alpha * a;
auto aa0 = 1 + alpha / a;
auto aa1 = -2 * cosw0;
auto aa2 = 1 - alpha / a;
setCoefficients(aa0, aa1, aa2, b0, b1, b2);
}
auto b0 = 1 + alpha * a;
auto b1 = -2 * cosw0;
auto b2 = 1 - alpha * a;
auto aa0 = 1 + alpha / a;
auto aa1 = -2 * cosw0;
auto aa2 = 1 - alpha / a;
setCoefficients(aa0, aa1, aa2, b0, b1, b2);
}
void BiQuadFilter::setHighPassFilter(float sampleRate, float cutoffFrequency, float q)
{
// H(s) = s^2 / (s^2 + s/Q + 1)
auto w0 = 2 * M_PI * cutoffFrequency / sampleRate;
auto cosw0 = qCos(w0);
auto alpha = qSin(w0) / (2 * q);
void BiQuadFilter::setHighPassFilter(float sampleRate, float cutoffFrequency, float q)
{
// H(s) = s^2 / (s^2 + s/Q + 1)
auto w0 = 2 * M_PI * cutoffFrequency / sampleRate;
auto cosw0 = qCos(w0);
auto alpha = qSin(w0) / (2 * q);
auto b0 = (1 + cosw0) / 2;
auto b1 = -(1 + cosw0);
auto b2 = (1 + cosw0) / 2;
auto aa0 = 1 + alpha;
auto aa1 = -2 * cosw0;
auto aa2 = 1 - alpha;
setCoefficients(aa0, aa1, aa2, b0, b1, b2);
}
auto b0 = (1 + cosw0) / 2;
auto b1 = -(1 + cosw0);
auto b2 = (1 + cosw0) / 2;
auto aa0 = 1 + alpha;
auto aa1 = -2 * cosw0;
auto aa2 = 1 - alpha;
setCoefficients(aa0, aa1, aa2, b0, b1, b2);
}
BiQuadFilter BiQuadFilter::lowPassFilter(float sampleRate, float cutoffFrequency, float q)
{
BiQuadFilter filter;
filter.setLowPassFilter(sampleRate, cutoffFrequency, q);
return filter;
}
BiQuadFilter BiQuadFilter::lowPassFilter(float sampleRate, float cutoffFrequency, float q)
{
BiQuadFilter filter;
filter.setLowPassFilter(sampleRate, cutoffFrequency, q);
return filter;
}
BiQuadFilter BiQuadFilter::highPassFilter(float sampleRate, float cutoffFrequency, float q)
{
BiQuadFilter filter;
filter.setHighPassFilter(sampleRate, cutoffFrequency, q);
return filter;
}
BiQuadFilter BiQuadFilter::highPassFilter(float sampleRate, float cutoffFrequency, float q)
{
BiQuadFilter filter;
filter.setHighPassFilter(sampleRate, cutoffFrequency, q);
return filter;
}
BiQuadFilter BiQuadFilter::peakingEQ(float sampleRate, float centreFrequency, float q, float dbGain)
{
BiQuadFilter filter;
filter.setPeakingEq(sampleRate, centreFrequency, q, dbGain);
return filter;
}
BiQuadFilter BiQuadFilter::peakingEQ(float sampleRate, float centreFrequency, float q, float dbGain)
{
BiQuadFilter filter;
filter.setPeakingEq(sampleRate, centreFrequency, q, dbGain);
return filter;
}
} // ns
} // ns

View File

@@ -1,35 +1,54 @@
/* Copyright (C) 2019
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
//! \file
#ifndef BIQUADFILTER_H
#define BIQUADFILTER_H
#include "blacksound/blacksoundexport.h"
class BiQuadFilter
namespace BlackSound
{
public:
BiQuadFilter() = default;
namespace Dsp
{
//! Digital biquad filter
class BiQuadFilter
{
public:
//! Ctor
BiQuadFilter() = default;
float transform(float inSample);
void setCoefficients(double aa0, double aa1, double aa2, double b0, double b1, double b2);
void setLowPassFilter(float sampleRate, float cutoffFrequency, float q);
void setPeakingEq(float sampleRate, float centreFrequency, float q, float dbGain);
void setHighPassFilter(float sampleRate, float cutoffFrequency, float q);
float transform(float inSample);
void setCoefficients(double aa0, double aa1, double aa2, double b0, double b1, double b2);
void setLowPassFilter(float sampleRate, float cutoffFrequency, float q);
void setPeakingEq(float sampleRate, float centreFrequency, float q, float dbGain);
void setHighPassFilter(float sampleRate, float cutoffFrequency, float q);
static BiQuadFilter lowPassFilter(float sampleRate, float cutoffFrequency, float q);
static BiQuadFilter highPassFilter(float sampleRate, float cutoffFrequency, float q);
static BiQuadFilter peakingEQ(float sampleRate, float centreFrequency, float q, float dbGain);
private:
double a0;
double a1;
double a2;
double a3;
double a4;
static BiQuadFilter lowPassFilter(float sampleRate, float cutoffFrequency, float q);
static BiQuadFilter highPassFilter(float sampleRate, float cutoffFrequency, float q);
static BiQuadFilter peakingEQ(float sampleRate, float centreFrequency, float q, float dbGain);
// state
float x1 = 0.0;
float x2 = 0.0;
float y1 = 0.0;
float y2 = 0.0;
};
private:
double a0;
double a1;
double a2;
double a3;
double a4;
#endif // BIQUADFILTER_H
// state
float x1 = 0.0;
float x2 = 0.0;
float y1 = 0.0;
float y2 = 0.0;
};
} // ns
} // ns
#endif // guard

View File

@@ -2,6 +2,8 @@
#include "blacksound/audioutilities.h"
#include <QDebug>
using namespace BlackSound::Dsp;
namespace BlackSound
{
namespace SampleProvider
@@ -52,5 +54,5 @@ namespace BlackSound
{
m_outputGain = outputGain;
}
}
}
} // ns
} // ns

View File

@@ -52,11 +52,10 @@ namespace BlackSound
void setupPreset(EqualizerPresets preset);
ISampleProvider *m_sourceProvider = nullptr;
int m_channels = 1;
bool m_bypass = false;
int m_channels = 1;
bool m_bypass = false;
double m_outputGain = 1.0;
QVector<BiQuadFilter> m_filters;
QVector<Dsp::BiQuadFilter> m_filters;
};
} // ns
} // ns