A parametric EQ that uses a fixed point, direct form 2 transposed, implementation of a Butterworth filter. The following parameters can be adjusted: Gain (dB), Bandwidth Gain (dB), Centre frequency (Hz), Bandwidth (Hz), Order, Type (Peaking, Bandstop, Bandpass, Low Shelf, High Shelf, Low Pass or High Pass).

Committer:
Padman
Date:
Thu Aug 04 20:08:32 2016 +0000
Revision:
5:407aa8a0a5c2
Parent:
4:ec48ce56b8c1
Improved link

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Padman 0:2e17a3d6907c 1 /**
Padman 0:2e17a3d6907c 2 * @file ParametricEQ.h
Padman 0:2e17a3d6907c 3 * @brief ParametricEQ - fixed point implementation of a Parametric EQ
Padman 0:2e17a3d6907c 4 * @author Patrick Thomas
Padman 0:2e17a3d6907c 5 * @version 1.0
Padman 0:2e17a3d6907c 6 * @see
Padman 0:2e17a3d6907c 7 *
Padman 0:2e17a3d6907c 8 * Copyright (c) 2016
Padman 0:2e17a3d6907c 9 *
Padman 0:2e17a3d6907c 10 * Licensed under the Apache License, Version 2.0 (the "License");
Padman 0:2e17a3d6907c 11 * you may not use this file except in compliance with the License.
Padman 0:2e17a3d6907c 12 * You may obtain a copy of the License at
Padman 0:2e17a3d6907c 13 *
Padman 0:2e17a3d6907c 14 * http://www.apache.org/licenses/LICENSE-2.0
Padman 0:2e17a3d6907c 15 *
Padman 0:2e17a3d6907c 16 * Unless required by applicable law or agreed to in writing, software
Padman 0:2e17a3d6907c 17 * distributed under the License is distributed on an "AS IS" BASIS,
Padman 0:2e17a3d6907c 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Padman 0:2e17a3d6907c 19 * See the License for the specific language governing permissions and
Padman 0:2e17a3d6907c 20 * limitations under the License.
Padman 0:2e17a3d6907c 21 */
Padman 0:2e17a3d6907c 22
Padman 0:2e17a3d6907c 23 #ifndef PARAMETRICEQ_H
Padman 0:2e17a3d6907c 24 #define PARAMETRICEQ_H
Padman 0:2e17a3d6907c 25
Padman 0:2e17a3d6907c 26 #include <math.h>
Padman 0:2e17a3d6907c 27
Padman 0:2e17a3d6907c 28 #define M_PI 3.14159265358979323846
Padman 0:2e17a3d6907c 29
Padman 0:2e17a3d6907c 30 // Parameter limits
Padman 0:2e17a3d6907c 31 #define GAIN_DB_MAX 20
Padman 0:2e17a3d6907c 32 #define BW_HZ_MIN 20
Padman 0:2e17a3d6907c 33 #define GBW_MARGIN 0.01
Padman 0:2e17a3d6907c 34 #define MAX_ORDER 4
Padman 0:2e17a3d6907c 35
Padman 0:2e17a3d6907c 36 // Sampling limits
Padman 0:2e17a3d6907c 37 #define SAMPLE_RATE_MAX 192000
Padman 0:2e17a3d6907c 38 #define SAMPLE_RATE_MIN 32000
Padman 0:2e17a3d6907c 39 #define SAMPLE_BITS_MIN 8
Padman 0:2e17a3d6907c 40 #define SAMPLE_BITS_MAX 24
Padman 0:2e17a3d6907c 41
Padman 0:2e17a3d6907c 42 #define PIN(n,min,max) ((n) > (max) ? max : ((n) < (min) ? (min) : (n)))
Padman 0:2e17a3d6907c 43
Padman 2:74e41881a5d9 44 enum FilterType {
Padman 2:74e41881a5d9 45
Padman 2:74e41881a5d9 46 Peaking,
Padman 2:74e41881a5d9 47 BandPass,
Padman 2:74e41881a5d9 48 BandStop,
Padman 2:74e41881a5d9 49 LowShelf,
Padman 2:74e41881a5d9 50 HighShelf,
Padman 2:74e41881a5d9 51 LowPass,
Padman 2:74e41881a5d9 52 HighPass
Padman 2:74e41881a5d9 53 };
Padman 2:74e41881a5d9 54
Padman 5:407aa8a0a5c2 55 /** A fixed point parametric EQ implementing Butterworth coefficients in direct form 2 transposed realisation.
Padman 5:407aa8a0a5c2 56 * The theory of operation is outlined in <a href="http://www.ece.rutgers.edu/~orfanidi/ece346/hpeq.pdf">this paper</a>
Padman 0:2e17a3d6907c 57 *
Padman 0:2e17a3d6907c 58 * Example:
Padman 0:2e17a3d6907c 59 * @code
Padman 0:2e17a3d6907c 60 * #include "mbed.h"
Padman 0:2e17a3d6907c 61 * #include "ParametricEQ.h"
Padman 0:2e17a3d6907c 62 *
Padman 0:2e17a3d6907c 63 * ParametricEQ myEQ;
Padman 0:2e17a3d6907c 64 * Serial pc(USBTX, USBRX);
Padman 0:2e17a3d6907c 65 *
Padman 0:2e17a3d6907c 66 * int main()
Padman 0:2e17a3d6907c 67 * {
Padman 0:2e17a3d6907c 68 * while(1) {
Padman 0:2e17a3d6907c 69 *
Padman 0:2e17a3d6907c 70 * while(pc.readable()) {
Padman 0:2e17a3d6907c 71 *
Padman 3:495d3542ccb5 72 * pc.printf("%d\n", myEQ.filter(pc.getc()));
Padman 0:2e17a3d6907c 73 * }
Padman 0:2e17a3d6907c 74 *
Padman 0:2e17a3d6907c 75 * }
Padman 0:2e17a3d6907c 76 * }
Padman 0:2e17a3d6907c 77 * @endcode
Padman 0:2e17a3d6907c 78 */
Padman 1:0545d8890dc6 79
Padman 1:0545d8890dc6 80 class ParametricEQ {
Padman 0:2e17a3d6907c 81
Padman 0:2e17a3d6907c 82 class biquad {
Padman 0:2e17a3d6907c 83
Padman 0:2e17a3d6907c 84 private:
Padman 0:2e17a3d6907c 85
Padman 0:2e17a3d6907c 86 // Local accumulators
Padman 0:2e17a3d6907c 87 int v1;
Padman 0:2e17a3d6907c 88 int v2;
Padman 0:2e17a3d6907c 89 int v3;
Padman 0:2e17a3d6907c 90 int v4;
Padman 0:2e17a3d6907c 91 int w1;
Padman 0:2e17a3d6907c 92 int w2;
Padman 0:2e17a3d6907c 93
Padman 0:2e17a3d6907c 94 public:
Padman 0:2e17a3d6907c 95
Padman 0:2e17a3d6907c 96 // Local coefficients
Padman 0:2e17a3d6907c 97 int c0;
Padman 0:2e17a3d6907c 98 int s0;
Padman 0:2e17a3d6907c 99 int bhat_0;
Padman 0:2e17a3d6907c 100 int bhat_1;
Padman 0:2e17a3d6907c 101 int bhat_2;
Padman 0:2e17a3d6907c 102 int ahat_1;
Padman 0:2e17a3d6907c 103 int ahat_2;
Padman 0:2e17a3d6907c 104
Padman 0:2e17a3d6907c 105 // Sampling variables
Padman 0:2e17a3d6907c 106 int scaling_factor;
Padman 0:2e17a3d6907c 107 int sample_bounds;
Padman 0:2e17a3d6907c 108
Padman 0:2e17a3d6907c 109 int execute(int input);
Padman 0:2e17a3d6907c 110 };
Padman 0:2e17a3d6907c 111
Padman 0:2e17a3d6907c 112 // This module's fx blocks
Padman 0:2e17a3d6907c 113 biquad fx_blocks[(MAX_ORDER + 1)/2];
Padman 0:2e17a3d6907c 114
Padman 0:2e17a3d6907c 115 // Parameter variables
Padman 0:2e17a3d6907c 116 float Gain_dB;
Padman 0:2e17a3d6907c 117 float GBW_dB;
Padman 0:2e17a3d6907c 118 int F0_Hz;
Padman 0:2e17a3d6907c 119 int BW_Hz;
Padman 0:2e17a3d6907c 120 int Order;
Padman 0:2e17a3d6907c 121 FilterType Type;
Padman 0:2e17a3d6907c 122
Padman 0:2e17a3d6907c 123 // Sampling variables
Padman 0:2e17a3d6907c 124 int Sample_rate;
Padman 0:2e17a3d6907c 125 int Sample_bits;
Padman 0:2e17a3d6907c 126
Padman 0:2e17a3d6907c 127 // Intermediary parameter variables
Padman 0:2e17a3d6907c 128 double Gain_amplitude, Bandwidth_gain_amplitude, G0_amplitude, Normalised_centre_frequency, Normalised_bandwidth,
Padman 0:2e17a3d6907c 129 g, epsilon, beta, g_squared, beta_squared, f0_cosine, f0_sine, D, phi, si, g0, g0_squared;
Padman 0:2e17a3d6907c 130 int counter;
Padman 0:2e17a3d6907c 131
Padman 0:2e17a3d6907c 132 // Intermediary sampling variables
Padman 0:2e17a3d6907c 133 int Scaling_factor, Sample_bounds;
Padman 0:2e17a3d6907c 134
Padman 0:2e17a3d6907c 135 void check_GBW();
Padman 0:2e17a3d6907c 136 void calculate();
Padman 0:2e17a3d6907c 137 void update_blocks();
Padman 0:2e17a3d6907c 138
Padman 0:2e17a3d6907c 139 public:
Padman 0:2e17a3d6907c 140
Padman 0:2e17a3d6907c 141 /** Create an EQ
Padman 0:2e17a3d6907c 142 */
Padman 0:2e17a3d6907c 143 ParametricEQ();
Padman 0:2e17a3d6907c 144
Padman 0:2e17a3d6907c 145 /** Set the Gain
Padman 0:2e17a3d6907c 146 * @param value The target gain (dB)
Padman 0:2e17a3d6907c 147 * @return The actual gain (dB)
Padman 0:2e17a3d6907c 148 */
Padman 0:2e17a3d6907c 149 float set_Gain_dB(float value);
Padman 0:2e17a3d6907c 150
Padman 0:2e17a3d6907c 151 /** Set the Bandwidth Gain. NB |GBW_dB| must be less than |Gain_dB|
Padman 0:2e17a3d6907c 152 * @param value The target bandwidth gain (dB)
Padman 0:2e17a3d6907c 153 * @return The actual bandwidth gain (dB)
Padman 0:2e17a3d6907c 154 */
Padman 0:2e17a3d6907c 155 float set_GBW_dB(float value);
Padman 0:2e17a3d6907c 156
Padman 0:2e17a3d6907c 157 /** Set the Centre frequency
Padman 0:2e17a3d6907c 158 * @param value The target centre frequency (Hz)
Padman 0:2e17a3d6907c 159 * @return The actual centre frequency (Hz)
Padman 0:2e17a3d6907c 160 */
Padman 0:2e17a3d6907c 161 int set_F0_Hz(int value);
Padman 0:2e17a3d6907c 162
Padman 0:2e17a3d6907c 163 /** Set the Bandwidth
Padman 0:2e17a3d6907c 164 * @param value The target bandwidth (Hz)
Padman 0:2e17a3d6907c 165 * @return The actual bandwidth (Hz)
Padman 0:2e17a3d6907c 166 */
Padman 0:2e17a3d6907c 167 int set_BW_Hz(int value);
Padman 0:2e17a3d6907c 168
Padman 0:2e17a3d6907c 169 /** Set the Order. Higher order increases cutoff
Padman 0:2e17a3d6907c 170 * @param value The target order
Padman 0:2e17a3d6907c 171 * @return The actual order
Padman 0:2e17a3d6907c 172 */
Padman 0:2e17a3d6907c 173 int set_Order(int value);
Padman 0:2e17a3d6907c 174
Padman 0:2e17a3d6907c 175 /** Set the Filter type.
Padman 0:2e17a3d6907c 176 * @param value The target type: 0 - Peaking, 1 - BandPass, 2 - BandStop, 3 - LowShelf, 4 - HighShelf, 5 - LowPass, 6 - HighPass
Padman 0:2e17a3d6907c 177 * @return The actual type
Padman 0:2e17a3d6907c 178 */
Padman 0:2e17a3d6907c 179 FilterType set_Type(FilterType type);
Padman 0:2e17a3d6907c 180
Padman 0:2e17a3d6907c 181 /** Set the Sample rate
Padman 0:2e17a3d6907c 182 * @param value The target sample rate
Padman 0:2e17a3d6907c 183 * @return The actual sample rate
Padman 0:2e17a3d6907c 184 */
Padman 0:2e17a3d6907c 185 int set_Sample_rate(int value);
Padman 0:2e17a3d6907c 186
Padman 0:2e17a3d6907c 187 /** Set the number of Sample bits
Padman 0:2e17a3d6907c 188 * @param value The target number of sample bits
Padman 0:2e17a3d6907c 189 * @return The actual number of sample bits
Padman 0:2e17a3d6907c 190 */
Padman 0:2e17a3d6907c 191 int set_Sample_bits(int value);
Padman 0:2e17a3d6907c 192
Padman 0:2e17a3d6907c 193 /** Pass a sample through the EQ
Padman 0:2e17a3d6907c 194 * @param input The input sample
Padman 0:2e17a3d6907c 195 * @return The filtered output
Padman 0:2e17a3d6907c 196 */
Padman 0:2e17a3d6907c 197 int filter(int input);
Padman 0:2e17a3d6907c 198 };
Padman 0:2e17a3d6907c 199
Padman 0:2e17a3d6907c 200 #endif