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).
ParametricEQ.h@5:407aa8a0a5c2, 2016-08-04 (annotated)
- 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?
User | Revision | Line number | New 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 |