Add IIR Filter (#2704)

Signed-off-by: Martmists <martmists@gmail.com>
This commit is contained in:
Martmists 2021-10-26 06:35:31 +02:00 committed by GitHub
parent 4969f9f153
commit 4e4f368669
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 94 additions and 0 deletions

View File

@ -0,0 +1,91 @@
package AudioFilters;
/**
* N-Order IIR Filter
* Assumes inputs are normalized to [-1, 1]
*
* Based on the difference equation from https://en.wikipedia.org/wiki/Infinite_impulse_response
*/
public class IIRFilter {
private final int order;
private final double[] coeffsA;
private final double[] coeffsB;
private final double[] historyX;
private final double[] historyY;
/**
* Construct an IIR Filter
*
* @param order the filter's order
* @throws IllegalArgumentException if order is zero or less
*/
public IIRFilter(int order) throws IllegalArgumentException {
if (order < 1) {
throw new IllegalArgumentException("order must be greater than zero");
}
this.order = order;
coeffsA = new double[order+1];
coeffsB = new double[order+1];
// Sane defaults
coeffsA[0] = 1.0;
coeffsB[0] = 1.0;
historyX = new double[order];
historyY = new double[order];
}
/**
* Set coefficients
* @param aCoeffs Denominator coefficients
* @param bCoeffs Numerator coefficients
* @throws IllegalArgumentException if {@code aCoeffs} or {@code bCoeffs} is not of size {@code order},
* or if {@code aCoeffs[0]} is 0.0
*/
public void setCoeffs(double[] aCoeffs, double[] bCoeffs) throws IllegalArgumentException {
if (aCoeffs.length != order) {
throw new IllegalArgumentException("aCoeffs must be of size " + order + ", got " + aCoeffs.length);
}
if (aCoeffs[0] == 0.0) {
throw new IllegalArgumentException("aCoeffs.get(0) must not be zero");
}
if (bCoeffs.length != order) {
throw new IllegalArgumentException("bCoeffs must be of size " + order + ", got " + bCoeffs.length);
}
for (int i = 0; i <= order; i++) {
coeffsA[i] = aCoeffs[i];
coeffsB[i] = bCoeffs[i];
}
}
/**
* Process a single sample
*
* @param sample the sample to process
* @return the processed sample
*/
public double process(double sample) {
double result = 0.0;
// Process
for (int i = 1; i <= order; i++) {
result += (coeffsB[i] * historyX[i-1] - coeffsA[i] * historyY[i-1]);
}
result = (result + coeffsB[0] * sample) / coeffsA[0];
// Feedback
for (int i = order-1; i > 0; i--) {
historyX[i] = historyX[i-1];
historyY[i] = historyY[i-1];
}
historyX[0] = sample;
historyY[0] = result;
return result;
}
}

View File

@ -1,4 +1,7 @@
## Audio Filters
* [IIRFilter](https://github.com/TheAlgorithms/Java/blob/master/AudioFilters/IIRFilter.java)
## Backtracking
* [NQueens](https://github.com/TheAlgorithms/Java/blob/master/Backtracking/NQueens.java)
* [PowerSum](https://github.com/TheAlgorithms/Java/blob/master/Backtracking/PowerSum.java)