00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "AimGammatone.h"
00020
00021
00022 using std::ostringstream;
00023 using std::complex;
00024 using std::abs;
00025 using std::cout;
00026 using std::endl;
00027
00028 using namespace Marsyas;
00029
00030 AimGammatone::AimGammatone(mrs_string name):MarSystem("AimGammatone",name)
00031 {
00032 is_initialized = false;
00033 initialized_num_channels = 0;
00034 initialized_min_frequency = 0.0;
00035 initialized_max_frequency = 0.0;
00036 initialized_israte = 0.0;
00037
00038 is_reset = false;
00039 reset_num_channels = 0;
00040
00041 addControls();
00042 }
00043
00044
00045 AimGammatone::AimGammatone(const AimGammatone& a): MarSystem(a)
00046 {
00047 is_initialized = false;
00048 initialized_num_channels = 0;
00049 initialized_min_frequency = 0.0;
00050 initialized_max_frequency = 0.0;
00051 initialized_israte = 0.0;
00052
00053 is_reset = false;
00054 reset_num_channels = 0;
00055
00056 ctrl_num_channels_= getctrl("mrs_natural/num_channels");
00057 ctrl_min_frequency_ = getctrl("mrs_real/min_frequency");
00058 ctrl_max_frequency_ = getctrl("mrs_real/max_frequency");
00059 }
00060
00061 AimGammatone::~AimGammatone()
00062 {
00063 }
00064
00065
00066 MarSystem*
00067 AimGammatone::clone() const
00068 {
00069 return new AimGammatone(*this);
00070 }
00071
00072 void
00073 AimGammatone::addControls()
00074 {
00075 addControl("mrs_natural/num_channels", 200 , ctrl_num_channels_);
00076 addControl("mrs_real/min_frequency", 86.0 , ctrl_min_frequency_);
00077 addControl("mrs_real/max_frequency", 16000.0 , ctrl_max_frequency_);
00078 }
00079
00080 void
00081 AimGammatone::myUpdate(MarControlPtr sender)
00082 {
00083 (void) sender;
00084
00085 MRSDIAG("AimGammatone.cpp - AimGammatone:myUpdate");
00086 ctrl_onSamples_->setValue(ctrl_inSamples_, NOUPDATE);
00087 ctrl_osrate_->setValue(ctrl_israte_->to<mrs_real>());
00088 ctrl_onObsNames_->setValue("AimGammatone_" + ctrl_inObsNames_->to<mrs_string>() , NOUPDATE);
00089
00090
00091
00092
00093 ctrl_onObservations_->setValue(ctrl_num_channels_->to<mrs_natural>() , NOUPDATE);
00094
00095
00096
00097
00098 if (initialized_num_channels != ctrl_num_channels_->to<mrs_natural>() ||
00099 initialized_min_frequency != ctrl_min_frequency_->to<mrs_real>() ||
00100 initialized_max_frequency != ctrl_max_frequency_->to<mrs_real>() ||
00101 initialized_israte != ctrl_israte_->to<mrs_real>()) {
00102 is_initialized = false;
00103 }
00104
00105 if (!is_initialized) {
00106 InitializeInternal();
00107 is_initialized = true;
00108 initialized_num_channels = ctrl_num_channels_->to<mrs_natural>();
00109 initialized_min_frequency = ctrl_min_frequency_->to<mrs_real>();
00110 initialized_max_frequency = ctrl_max_frequency_->to<mrs_real>();
00111 initialized_israte = ctrl_israte_->to<mrs_real>();
00112 }
00113
00114
00115
00116
00117 if (reset_num_channels != ctrl_num_channels_->to<mrs_natural>()) {
00118 is_reset = false;
00119 }
00120
00121 if (!is_reset) {
00122 ResetInternal();
00123 is_reset = true;
00124 reset_num_channels = ctrl_num_channels_->to<mrs_natural>();
00125 }
00126
00127 }
00128
00129 bool
00130 AimGammatone::InitializeInternal() {
00131 mrs_natural num_channels = ctrl_num_channels_->to<mrs_natural>();
00132 double min_frequency = ctrl_min_frequency_->to<mrs_real>();
00133 double max_frequency = ctrl_max_frequency_->to<mrs_real>();
00134
00135
00136 double erb_max = ERBTools::Freq2ERB(max_frequency);
00137 double erb_min = ERBTools::Freq2ERB(min_frequency);
00138 double delta_erb = (erb_max - erb_min) / (num_channels - 1);
00139
00140 centre_frequencies_.resize(num_channels);
00141 double erb_current = erb_min;
00142
00143 for (int i = 0; i < num_channels; ++i) {
00144 centre_frequencies_[i] = ERBTools::ERB2Freq(erb_current);
00145 erb_current += delta_erb;
00146 }
00147
00148 a_.resize(num_channels);
00149 b1_.resize(num_channels);
00150 b2_.resize(num_channels);
00151 b3_.resize(num_channels);
00152 b4_.resize(num_channels);
00153 state_1_.resize(num_channels);
00154 state_2_.resize(num_channels);
00155 state_3_.resize(num_channels);
00156 state_4_.resize(num_channels);
00157
00158 for (int ch = 0; ch < num_channels; ++ch) {
00159 double cf = centre_frequencies_[ch];
00160 double erb = ERBTools::Freq2ERBw(cf);
00161
00162
00163 double dt = 1.0 / ctrl_israte_->to<mrs_real>();
00164
00165
00166 double b = 1.019 * 2.0 * PI * erb;
00167
00168
00169
00170
00171
00172
00173
00174 double cpt = cf * PI * dt;
00175 complex<double> exponent(0.0, 2.0 * cpt);
00176 complex<double> ec = exp(2.0 * exponent);
00177 complex<double> two_cf_pi_t(2.0 * cpt, 0.0);
00178 complex<double> two_pow(pow(2.0, (3.0 / 2.0)), 0.0);
00179 complex<double> p1 = -2.0 * ec * dt;
00180 complex<double> p2 = 2.0 * exp(-(b * dt) + exponent) * dt;
00181 complex<double> b_dt(b * dt, 0.0);
00182
00183 double gain = abs(
00184 (p1 + p2 * (cos(two_cf_pi_t) - sqrt(3.0 - two_pow) * sin(two_cf_pi_t)))
00185 * (p1 + p2 * (cos(two_cf_pi_t) + sqrt(3.0 - two_pow) * sin(two_cf_pi_t)))
00186 * (p1 + p2 * (cos(two_cf_pi_t) - sqrt(3.0 + two_pow) * sin(two_cf_pi_t)))
00187 * (p1 + p2 * (cos(two_cf_pi_t) + sqrt(3.0 + two_pow) * sin(two_cf_pi_t)))
00188 / pow((-2.0 / exp(2.0 * b_dt) - 2.0 * ec + 2.0 * (1.0 + ec)
00189 / exp(b_dt)), 4));
00190
00191
00192 const int coeff_count = 3;
00193 a_[ch].resize(coeff_count, 0.0);
00194 b1_[ch].resize(coeff_count, 0.0);
00195 b2_[ch].resize(coeff_count, 0.0);
00196 b3_[ch].resize(coeff_count, 0.0);
00197 b4_[ch].resize(coeff_count, 0.0);
00198 state_1_[ch].resize(coeff_count, 0.0);
00199 state_2_[ch].resize(coeff_count, 0.0);
00200 state_3_[ch].resize(coeff_count, 0.0);
00201 state_4_[ch].resize(coeff_count, 0.0);
00202
00203 double B0 = dt;
00204 double B2 = 0.0;
00205
00206 double B11 = -(2.0 * dt * cos(2.0 * cf * PI * dt) / exp(b * dt)
00207 + 2.0 * sqrt(3 + pow(2.0, 1.5)) * dt
00208 * sin(2.0 * cf * PI * dt) / exp(b * dt)) / 2.0;
00209 double B12 = -(2.0 * dt * cos(2.0 * cf * PI * dt) / exp(b * dt)
00210 - 2.0 * sqrt(3 + pow(2.0, 1.5)) * dt
00211 * sin(2.0 * cf * PI * dt) / exp(b * dt)) / 2.0;
00212 double B13 = -(2.0 * dt * cos(2.0 * cf * PI * dt) / exp(b * dt)
00213 + 2.0 * sqrt(3 - pow(2.0, 1.5)) * dt
00214 * sin(2.0 * cf * PI * dt) / exp(b * dt)) / 2.0;
00215 double B14 = -(2.0 * dt * cos(2.0 * cf * PI * dt) / exp(b * dt)
00216 - 2.0 * sqrt(3 - pow(2.0, 1.5)) * dt
00217 * sin(2.0 * cf * PI * dt) / exp(b * dt)) / 2.0;
00218
00219 a_[ch][0] = 1.0;
00220 a_[ch][1] = -2.0 * cos(2.0 * cf * PI * dt) / exp(b * dt);
00221 a_[ch][2] = exp(-2.0 * b * dt);
00222 b1_[ch][0] = B0 / gain;
00223 b1_[ch][1] = B11 / gain;
00224 b1_[ch][2] = B2 / gain;
00225 b2_[ch][0] = B0;
00226 b2_[ch][1] = B12;
00227 b2_[ch][2] = B2;
00228 b3_[ch][0] = B0;
00229 b3_[ch][1] = B13;
00230 b3_[ch][2] = B2;
00231 b4_[ch][0] = B0;
00232 b4_[ch][1] = B14;
00233 b4_[ch][2] = B2;
00234 }
00235 return true;
00236 }
00237
00238 void
00239 AimGammatone::ResetInternal() {
00240 mrs_natural num_channels = ctrl_num_channels_->to<mrs_natural>();
00241
00242 state_1_.resize(num_channels);
00243 state_2_.resize(num_channels);
00244 state_3_.resize(num_channels);
00245 state_4_.resize(num_channels);
00246 for (int i = 0; i < num_channels; ++i) {
00247 state_1_[i].resize(3, 0.0);
00248 state_2_[i].resize(3, 0.0);
00249 state_3_[i].resize(3, 0.0);
00250 state_4_[i].resize(3, 0.0);
00251 }
00252 }
00253
00254 void
00255 AimGammatone::myProcess(realvec& in, realvec& out)
00256 {
00257 int audio_channel = 0;
00258
00259 std::vector<std::vector<double> >::iterator b1 = b1_.begin();
00260 std::vector<std::vector<double> >::iterator b2 = b2_.begin();
00261 std::vector<std::vector<double> >::iterator b3 = b3_.begin();
00262 std::vector<std::vector<double> >::iterator b4 = b4_.begin();
00263 std::vector<std::vector<double> >::iterator a = a_.begin();
00264 std::vector<std::vector<double> >::iterator s1 = state_1_.begin();
00265 std::vector<std::vector<double> >::iterator s2 = state_2_.begin();
00266 std::vector<std::vector<double> >::iterator s3 = state_3_.begin();
00267 std::vector<std::vector<double> >::iterator s4 = state_4_.begin();
00268
00269
00270 std::vector<double> outbuff(ctrl_inSamples_->to<mrs_natural>());
00271 mrs_natural _channel_count = ctrl_num_channels_->to<mrs_natural>();
00272 mrs_natural _inSamples = ctrl_inSamples_->to<mrs_natural>();
00273
00274 for (int ch = 0; ch < _channel_count;
00275 ++ch, ++b1, ++b2, ++b3, ++b4, ++a, ++s1, ++s2, ++s3, ++s4) {
00276 for (int i = 0; i < _inSamples; ++i) {
00277
00278 double inputsample = in(audio_channel, i);
00279 outbuff[i] = (*b1)[0] * inputsample + (*s1)[0];
00280 for (unsigned int stage = 1; stage < s1->size(); ++stage)
00281 (*s1)[stage - 1] = (*b1)[stage] * inputsample
00282 - (*a)[stage] * outbuff[i] + (*s1)[stage];
00283 }
00284 for (int i = 0; i < _inSamples; ++i) {
00285
00286 double inputsample = outbuff[i];
00287 outbuff[i] = (*b2)[0] * inputsample + (*s2)[0];
00288 for (unsigned int stage = 1; stage < s2->size(); ++stage)
00289 (*s2)[stage - 1] = (*b2)[stage] * inputsample
00290 - (*a)[stage] * outbuff[i] + (*s2)[stage];
00291 }
00292 for (int i = 0; i < _inSamples; ++i) {
00293
00294 double inputsample = outbuff[i];
00295 outbuff[i] = (*b3)[0] * inputsample + (*s3)[0];
00296 for (unsigned int stage = 1; stage < s3->size(); ++stage)
00297 (*s3)[stage - 1] = (*b3)[stage] * inputsample
00298 - (*a)[stage] * outbuff[i] + (*s3)[stage];
00299 }
00300 for (int i = 0; i < _inSamples; ++i) {
00301
00302 double inputsample = outbuff[i];
00303 outbuff[i] = (*b4)[0] * inputsample + (*s4)[0];
00304 for (unsigned int stage = 1; stage < s4->size(); ++stage)
00305 (*s4)[stage - 1] = (*b4)[stage] * inputsample
00306 - (*a)[stage] * outbuff[i] + (*s4)[stage];
00307 out(ch, i) = outbuff[i];
00308 }
00309 }
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 }