Audacity 3.2.0
EqualizationFilter.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 EqualizationFilter.cpp
6
7 Mitch Golden
8 Vaughan Johnson (Preview)
9 Martyn Shaw (FIR filters, response curve, graphic EQ)
10
11 Paul Licameli split from Equalization.cpp
12
13**********************************************************************/
14#include "EqualizationFilter.h"
15#include "Envelope.h"
16#include "FFT.h"
17
20 , mLogEnvelope{ false,
21 dBMin.min, dBMax.max, // MB: this is the highest possible range
22 0.0 }
23 , mLinEnvelope{ false,
24 dBMin.min, dBMax.max, // MB: this is the highest possible range
25 0.0 }
26{
29}
30
31#include "RealFFTf.h"
33{
34 // Inverse-transform the given curve from frequency domain to time;
35 // Apply a taper to define a finite impulse response;
36 // Transform that back to frequency domain to get the modified curve.
37
38 double loLog = log10(mLoFreq);
39 double hiLog = log10(mHiFreq);
40 double denom = hiLog - loLog;
41
42 double delta = mHiFreq / ((double)(mWindowSize / 2.));
43 double val0;
44 double val1;
45
46 if ( IsLinear() )
47 {
48 val0 = mLinEnvelope.GetValue(0.0); //no scaling required - saved as dB
49 val1 = mLinEnvelope.GetValue(1.0);
50 }
51 else
52 {
53 val0 = mLogEnvelope.GetValue(0.0); //no scaling required - saved as dB
54 val1 = mLogEnvelope.GetValue(1.0);
55 }
56 mFilterFuncR[0] = val0;
57 double freq = delta;
58
59 for(size_t i = 1; i <= mWindowSize / 2; i++)
60 {
61 double when;
62 if ( IsLinear() )
63 when = freq/mHiFreq;
64 else
65 when = (log10(freq) - loLog)/denom;
66 if(when < 0.)
67 {
68 mFilterFuncR[i] = val0;
69 }
70 else if(when > 1.0)
71 {
72 mFilterFuncR[i] = val1;
73 }
74 else
75 {
76 if ( IsLinear() )
78 else
80 }
81 freq += delta;
82 }
83 mFilterFuncR[mWindowSize / 2] = val1;
84
86
87 {
88 size_t i = 1;
89 for(; i < mWindowSize / 2; i++)
90 {
92 mFilterFuncR[mWindowSize - i] = mFilterFuncR[i]; //Fill entire array
93 }
94 mFilterFuncR[i] = DB_TO_LINEAR(mFilterFuncR[i]); //do last one
95 }
96
97 //transfer to time domain to do the padding and windowing
98 Floats outr{ mWindowSize };
99 Floats outi{ mWindowSize };
100 InverseRealFFT(mWindowSize, mFilterFuncR.get(), NULL, outr.get()); // To time domain
101
102 {
103 size_t i = 0;
104 for(; i <= (mM - 1) / 2; i++)
105 { //Windowing - could give a choice, fixed for now - MJS
106 // double mult=0.54-0.46*cos(2*M_PI*(i+(mM-1)/2.0)/(mM-1)); //Hamming
107 //Blackman
108 double mult =
109 0.42 -
110 0.5 * cos(2 * M_PI * (i + (mM - 1) / 2.0) / (mM - 1)) +
111 .08 * cos(4 * M_PI * (i + (mM - 1) / 2.0) / (mM - 1));
112 outr[i] *= mult;
113 if(i != 0){
114 outr[mWindowSize - i] *= mult;
115 }
116 }
117 for(; i <= mWindowSize / 2; i++)
118 { //Padding
119 outr[i] = 0;
120 outr[mWindowSize - i] = 0;
121 }
122 }
123 Floats tempr{ mM };
124 {
125 size_t i = 0;
126 for(; i < (mM - 1) / 2; i++)
127 { //shift so that padding on right
128 tempr[(mM - 1) / 2 + i] = outr[i];
129 tempr[i] = outr[mWindowSize - (mM - 1) / 2 + i];
130 }
131 tempr[(mM - 1) / 2 + i] = outr[i];
132 }
133
134 for (size_t i = 0; i < mM; i++)
135 { //and copy useful values back
136 outr[i] = tempr[i];
137 }
138 for (size_t i = mM; i < mWindowSize; i++)
139 { //rest is padding
140 outr[i]=0.;
141 }
142
143 //Back to the frequency domain so we can use it
144 RealFFT(mWindowSize, outr.get(), mFilterFuncR.get(), mFilterFuncI.get());
145
146 return TRUE;
147}
148
149void EqualizationFilter::Filter(size_t len, float *buffer) const
150{
151 // Transform a window of the time-domain signal to frequency;
152 // Multiply by corresponding coefficients;
153 // Inverse transform back to time domain: that's fast convolution.
154
155 float re,im;
156 // Apply FFT
157 RealFFTf(buffer, hFFT.get());
158 //FFT(len, false, inr, NULL, outr, outi);
159
160 // Apply filter
161 // DC component is purely real
162 mFFTBuffer[0] = buffer[0] * mFilterFuncR[0];
163 for(size_t i = 1; i < (len / 2); i++)
164 {
165 re=buffer[hFFT->BitReversed[i] ];
166 im=buffer[hFFT->BitReversed[i]+1];
167 mFFTBuffer[2*i ] = re*mFilterFuncR[i] - im*mFilterFuncI[i];
168 mFFTBuffer[2*i+1] = re*mFilterFuncI[i] + im*mFilterFuncR[i];
169 }
170 // Fs/2 component is purely real
171 mFFTBuffer[1] = buffer[1] * mFilterFuncR[len/2];
172
173 // Inverse FFT and normalization
174 InverseRealFFTf(mFFTBuffer.get(), hFFT.get());
175 ReorderToTime(hFFT.get(), mFFTBuffer.get(), buffer);
176}
int min(int a, int b)
#define M_PI
Definition: Distortion.cpp:30
void InverseRealFFT(size_t NumSamples, const float *RealIn, const float *ImagIn, float *RealOut)
Definition: FFT.cpp:266
void RealFFT(size_t NumSamples, const float *RealIn, float *RealOut, float *ImagOut)
Definition: FFT.cpp:228
#define DB_TO_LINEAR(x)
Definition: MemoryX.h:335
void RealFFTf(fft_type *buffer, const FFTParam *h)
Definition: RealFFTf.cpp:161
void InverseRealFFTf(fft_type *buffer, const FFTParam *h)
Definition: RealFFTf.cpp:263
void ReorderToTime(const FFTParam *hFFT, const fft_type *buffer, fft_type *TimeOut)
Definition: RealFFTf.cpp:360
static const AttachedProjectObjects::RegisteredFactory manager
EffectSettingsManager is an EffectDefinitionInterface that adds a factory function for EffectSettings...
double GetValue(double t, double sampleDur=0) const
Get envelope value at time t.
Definition: Envelope.cpp:837
void SetTrackLen(double trackLen, double sampleDur=0.0)
Definition: Envelope.cpp:793
EqualizationFilter(const EffectSettingsManager &manager)
void Filter(size_t len, float *buffer) const
Parameters of the Equalization effects that persist in configuration files.