tomwalters@276
|
1 // Copyright 2009-2010, Thomas Walters
|
tomwalters@276
|
2 //
|
tomwalters@276
|
3 // AIM-C: A C++ implementation of the Auditory Image Model
|
tomwalters@276
|
4 // http://www.acousticscale.org/AIMC
|
tomwalters@276
|
5 //
|
tomwalters@276
|
6 // This program is free software: you can redistribute it and/or modify
|
tomwalters@276
|
7 // it under the terms of the GNU General Public License as published by
|
tomwalters@276
|
8 // the Free Software Foundation, either version 3 of the License, or
|
tomwalters@276
|
9 // (at your option) any later version.
|
tomwalters@276
|
10 //
|
tomwalters@276
|
11 // This program is distributed in the hope that it will be useful,
|
tomwalters@276
|
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
tomwalters@276
|
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
tomwalters@276
|
14 // GNU General Public License for more details.
|
tomwalters@276
|
15 //
|
tomwalters@276
|
16 // You should have received a copy of the GNU General Public License
|
tomwalters@276
|
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
|
tomwalters@276
|
18
|
tomwalters@276
|
19 /*! \file
|
tomwalters@276
|
20 * \brief Slaney's gammatone filterbank
|
tomwalters@276
|
21 *
|
tomwalters@276
|
22 * \author Thomas Walters <tom@acousticscale.org>
|
tomwalters@276
|
23 * \date created 2009/11/13
|
tomwalters@276
|
24 * \version \$Id$
|
tomwalters@276
|
25 */
|
tomwalters@276
|
26
|
tomwalters@276
|
27 #include <complex>
|
tomwalters@276
|
28
|
tomwalters@276
|
29 #include "Modules/BMM/ModuleGammatone.h"
|
tomwalters@276
|
30
|
tomwalters@276
|
31 namespace aimc {
|
tomwalters@276
|
32 using std::complex;
|
tomwalters@276
|
33 ModuleGammatone::ModuleGammatone(Parameters *params) : Module(params) {
|
tomwalters@276
|
34 module_identifier_ = "gtfb";
|
tomwalters@276
|
35 module_type_ = "bmm";
|
tomwalters@276
|
36 module_description_ = "Gammatone filterbank (Slaney's IIR gammatone)";
|
tomwalters@276
|
37 module_version_ = "$Id$";
|
tomwalters@276
|
38
|
tomwalters@276
|
39 num_channels_ = parameters_->DefaultInt("gtfb.channel_count", 200);
|
tomwalters@276
|
40 min_frequency_ = parameters_->DefaultFloat("gtfb.min_frequency", 86.0f);
|
tomwalters@276
|
41 max_frequency_ = parameters_->DefaultFloat("gtfb.max_frequency", 16000.0f);
|
tomwalters@276
|
42 }
|
tomwalters@276
|
43
|
tomwalters@276
|
44 bool ModuleGammatone::InitializeInternal(const SignalBank& input) {
|
tomwalters@276
|
45 // Calculate number of channels, and centre frequencies
|
tomwalters@276
|
46
|
tomwalters@276
|
47 forward_.resize(num_channels_);
|
tomwalters@276
|
48 feedback_.resize(num_channels_);
|
tomwalters@276
|
49
|
tomwalters@276
|
50 for (int ch = 0; ch < num_channels_; ++ch) {
|
tomwalters@276
|
51 float erb = Freq2ERBw(cf)
|
tomwalters@276
|
52
|
tomwalters@276
|
53 // Sample interval
|
tomwalters@276
|
54 float dt = 1.0f / fs;
|
tomwalters@276
|
55
|
tomwalters@276
|
56 // Bandwidth parameter
|
tomwalters@276
|
57 float b = 1.019f * 2.0f * M_PI * erb;
|
tomwalters@276
|
58
|
tomwalters@276
|
59 // All of the following expressions are derived in Apple TR #35, "An
|
tomwalters@276
|
60 // Efficient Implementation of the Patterson-Holdsworth Cochlear
|
tomwalters@276
|
61 // Filter Bank".
|
tomwalters@276
|
62
|
tomwalters@276
|
63 // Calculate the gain:
|
tomwalters@276
|
64 complex<float> exponent(0.0f, 2.0f * cf * M_PI * T);
|
tomwalters@276
|
65 complex<float> ec = exp(2.0f * complex_exponent);
|
tomwalters@276
|
66 complex<float> two_cf_pi_t(2.0f * cf * M_PI * T, 0.0f);
|
tomwalters@276
|
67 complex<float> two_pow(pow(2.0f, (3.0f/2.0f)), 0.0f);
|
tomwalters@276
|
68
|
tomwalters@276
|
69 complex<float> p = -2.0f * ec * T + 2.0f * exp(-(B * T) + exponent) * dt;
|
tomwalters@276
|
70
|
tomwalters@276
|
71 float gain = abs(
|
tomwalters@276
|
72 (part1 * (cos(two_cf_pi_t) - sqrt(3.0f - twopow) * sin(two_cf_pi_t)))
|
tomwalters@276
|
73 * (part1 * (cos(two_cf_pi_t) + sqrt(3.0f - twopow) * sin(two_cf_pi_t)))
|
tomwalters@276
|
74 * (part1 * (cos(two_cf_pi_t) - sqrt(3.0f + twopow) * sin(two_cf_pi_t)))
|
tomwalters@276
|
75 * (part1 * (cos(two_cf_pi_t) + sqrt(3.0f + twopow) * sin(two_cf_pi_t)))
|
tomwalters@276
|
76 / pow(-2.0f / exp(2.0f * b * dt) - 2.0f * ec + 2.0f * (1.0f + ec)
|
tomwalters@276
|
77 / exp(b * dt), 4.0f));
|
tomwalters@276
|
78
|
tomwalters@276
|
79 // The filter coefficients themselves:
|
tomwalters@276
|
80 forward[ch].resize(5, 0.0f);
|
tomwalters@276
|
81 feedback[ch].resize(9, 0.0f);
|
tomwalters@276
|
82
|
tomwalters@276
|
83 forward[ch][0] = pow(T, 4.0f) / gain;
|
tomwalters@276
|
84 forward[ch][1] = (-4.0f * pow(T, 4.0f) * cos(2.0f * cf * M_PI * dt)
|
tomwalters@276
|
85 / exp(b * dt) / gain);
|
tomwalters@276
|
86 forward[ch][2] = (6.0f * pow(T, 4.0f) * cos(4.0f * cf * M_PI * dt)
|
tomwalters@276
|
87 / exp(2.0f * b * dt) / gain);
|
tomwalters@276
|
88 forward[ch][3] = (-4.0f * pow(T, 4.0f) * cos(6.0f * cf * M_PI * dt)
|
tomwalters@276
|
89 / exp(3.0f * b * dt) / gain);
|
tomwalters@276
|
90 forward[ch][4] = (pow(T,4.0f) * cos(8.0f * cf * M_PI * dt)
|
tomwalters@276
|
91 / exp(4.0f * b * dt) / gain);
|
tomwalters@276
|
92
|
tomwalters@276
|
93 feedback[ch][0] = 1.0f;
|
tomwalters@276
|
94 feedback[ch][1] = -8.0f * cos(2.0f * cf * M_PI * T) / exp(b * dt);
|
tomwalters@276
|
95 feedback[ch][2] = (4.0f * (4.0f + 3.0f * cos(4.0f * cf * M_PI * dt))
|
tomwalters@276
|
96 / exp(2.0f * b * dt));
|
tomwalters@276
|
97 feedback[ch][3] = (-8.0f * (6.0f * cos(2.0f * cf * M_PI * dt)
|
tomwalters@276
|
98 + cos(6.0f * cf * M_PI * dt))
|
tomwalters@276
|
99 / exp(3.0f * b * dt));
|
tomwalters@276
|
100 feedback[ch][4] = (2.0f * (18.0f + 16.0f * cos(4.0f * cf * M_PI * dt)
|
tomwalters@276
|
101 + cos(8.0f * cf * M_PI * dt))
|
tomwalters@276
|
102 / exp(4.0f * b * dt));
|
tomwalters@276
|
103 feedback[ch][5] = (-8.0f * (6.0f * cos(2.0f * cf * M_PI * T)
|
tomwalters@276
|
104 + cos(6.0f * cf * M_PI * T))
|
tomwalters@276
|
105 / exp(5.0f * B * T));
|
tomwalters@276
|
106 feedback[ch][6] = (4.0f * (4.0f + 3.0f * cos(4.0f * cf * M_PI * T))
|
tomwalters@276
|
107 / exp(6.0f * B * T));
|
tomwalters@276
|
108 feedback[ch][7] = -8.0f * cos(2.0f * cf * M_PI * dt) / exp(7.0f * b * dt);
|
tomwalters@276
|
109 feedback[ch][8] = exp(-8.0f * b * dt);
|
tomwalters@276
|
110 }
|
tomwalters@276
|
111 }
|
tomwalters@276
|
112 } // namespace aimc |