annotate carfac/agc_coeffs.cc @ 609:aefe2ca0674f

First version of a C++ implementation by Alex Brandmeyer
author alexbrandmeyer
date Mon, 13 May 2013 22:51:15 +0000
parents
children
rev   line source
alexbrandmeyer@609 1 //
alexbrandmeyer@609 2 // agc_coeffs.cc
alexbrandmeyer@609 3 // CARFAC Open Source C++ Library
alexbrandmeyer@609 4 //
alexbrandmeyer@609 5 // Created by Alex Brandmeyer on 5/10/13.
alexbrandmeyer@609 6 //
alexbrandmeyer@609 7 // This C++ file is part of an implementation of Lyon's cochlear model:
alexbrandmeyer@609 8 // "Cascade of Asymmetric Resonators with Fast-Acting Compression"
alexbrandmeyer@609 9 // to supplement Lyon's upcoming book "Human and Machine Hearing"
alexbrandmeyer@609 10 //
alexbrandmeyer@609 11 // Licensed under the Apache License, Version 2.0 (the "License");
alexbrandmeyer@609 12 // you may not use this file except in compliance with the License.
alexbrandmeyer@609 13 // You may obtain a copy of the License at
alexbrandmeyer@609 14 //
alexbrandmeyer@609 15 // http://www.apache.org/licenses/LICENSE-2.0
alexbrandmeyer@609 16 //
alexbrandmeyer@609 17 // Unless required by applicable law or agreed to in writing, software
alexbrandmeyer@609 18 // distributed under the License is distributed on an "AS IS" BASIS,
alexbrandmeyer@609 19 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
alexbrandmeyer@609 20 // See the License for the specific language governing permissions and
alexbrandmeyer@609 21 // limitations under the License.
alexbrandmeyer@609 22
alexbrandmeyer@609 23 #include "agc_coeffs.h"
alexbrandmeyer@609 24
alexbrandmeyer@609 25 //This method has been created for debugging purposes and depends on <iostream>.
alexbrandmeyer@609 26 //Could possibly be removed in the final version to reduce dependencies.
alexbrandmeyer@609 27 void AGCCoeffs::OutputCoeffs(){
alexbrandmeyer@609 28 std::cout << "AGCCoeffs Values" << std::endl;
alexbrandmeyer@609 29 std::cout << "****************" << std::endl;
alexbrandmeyer@609 30 std::cout << "n_ch_ = " << n_ch_ << std::endl;
alexbrandmeyer@609 31 std::cout << "n_agc_stages_ = " << n_agc_stages_ << std::endl;
alexbrandmeyer@609 32 std::cout << "agc_stage_gain_ = " << agc_stage_gain_ << std::endl;
alexbrandmeyer@609 33 std::cout << "agc_epsilon_ = " << agc_epsilon_ << std::endl;
alexbrandmeyer@609 34 std::cout << "decimation_ = " << decimation_ << std::endl;
alexbrandmeyer@609 35 std::cout << "agc_pole_z1_ = " << agc_pole_z1_ << std::endl;
alexbrandmeyer@609 36 std::cout << "agc_pole_z2_ = " << agc_pole_z2_ << std::endl;
alexbrandmeyer@609 37 std::cout << "agc_spatial_iterations_ = " << agc_spatial_iterations_
alexbrandmeyer@609 38 << std::endl;
alexbrandmeyer@609 39 std::cout << "agc_spatial_fir_ = " << agc_spatial_fir_ << std::endl;
alexbrandmeyer@609 40 std::cout << "agc_spatial_n_taps_ = " << agc_spatial_n_taps_ << std::endl;
alexbrandmeyer@609 41 std::cout << "agc_mix_coeffs_ = " << agc_mix_coeffs_ << std::endl;
alexbrandmeyer@609 42 std::cout << "agc1_scales_ = " << agc1_scales_ << std::endl;
alexbrandmeyer@609 43 std::cout << "agc2_scales_ = " << agc2_scales_ << std::endl;
alexbrandmeyer@609 44 std::cout << "time_constants_ = " << time_constants_
alexbrandmeyer@609 45 << std::endl << std::endl;
alexbrandmeyer@609 46 }
alexbrandmeyer@609 47
alexbrandmeyer@609 48 void AGCCoeffs::DesignAGC(AGCParams agc_params, long fs, int n_ch){
alexbrandmeyer@609 49 n_ch_ = n_ch;
alexbrandmeyer@609 50 n_agc_stages_ = agc_params.n_stages_;
alexbrandmeyer@609 51 agc_stage_gain_ = agc_params.agc_stage_gain_;
alexbrandmeyer@609 52 agc1_scales_ = agc_params.agc1_scales_;
alexbrandmeyer@609 53 agc2_scales_ = agc_params.agc2_scales_;
alexbrandmeyer@609 54 time_constants_ = agc_params.time_constants_;
alexbrandmeyer@609 55 agc_epsilon_.resize(n_agc_stages_);
alexbrandmeyer@609 56 agc_pole_z1_.resize(n_agc_stages_);
alexbrandmeyer@609 57 agc_pole_z2_.resize(n_agc_stages_);
alexbrandmeyer@609 58 agc_spatial_iterations_.resize(n_agc_stages_);
alexbrandmeyer@609 59 agc_spatial_n_taps_.resize(n_agc_stages_);
alexbrandmeyer@609 60 agc_spatial_fir_.resize(3,n_agc_stages_);
alexbrandmeyer@609 61 agc_mix_coeffs_.resize(n_agc_stages_);
alexbrandmeyer@609 62 mix_coeff_ = agc_params.agc_mix_coeff_;
alexbrandmeyer@609 63 fir_.resize(3);
alexbrandmeyer@609 64 decim_ = 1;
alexbrandmeyer@609 65 decimation_ = agc_params.decimation_;
alexbrandmeyer@609 66 total_dc_gain_ = 0;
alexbrandmeyer@609 67
alexbrandmeyer@609 68 for (int stage=0; stage < n_agc_stages_; stage++){
alexbrandmeyer@609 69 tau_ = time_constants_(stage);
alexbrandmeyer@609 70 decim_ = decim_ * decimation_(stage);
alexbrandmeyer@609 71 agc_epsilon_(stage) = 1 - exp((-1 * decim_) / (tau_ * fs));
alexbrandmeyer@609 72 n_times_ = tau_ * (fs / decim_);
alexbrandmeyer@609 73 delay_ = (agc2_scales_(stage) - agc1_scales_(stage)) / n_times_;
alexbrandmeyer@609 74 spread_sq_ = (pow(agc1_scales_(stage),2) + pow(agc2_scales_(stage),2)) /
alexbrandmeyer@609 75 n_times_;
alexbrandmeyer@609 76 u_ = 1 + (1 / spread_sq_);
alexbrandmeyer@609 77 p_ = u_ - sqrt(pow(u_,2) - 1);
alexbrandmeyer@609 78 dp_ = delay_ * (1 - (2 * p_) + pow(p_,2)) / 2;
alexbrandmeyer@609 79 pole_z1_ = p_ - dp_;
alexbrandmeyer@609 80 pole_z2_ = p_ + dp_;
alexbrandmeyer@609 81 agc_pole_z1_(stage) = pole_z1_;
alexbrandmeyer@609 82 agc_pole_z2_(stage) = pole_z2_;
alexbrandmeyer@609 83 n_taps_ = 0;
alexbrandmeyer@609 84 fir_ok_ = 0;
alexbrandmeyer@609 85 n_iterations_ = 1;
alexbrandmeyer@609 86 //initialize FIR coeffs settings
alexbrandmeyer@609 87 try {
alexbrandmeyer@609 88 while (! fir_ok_){
alexbrandmeyer@609 89 switch (n_taps_){
alexbrandmeyer@609 90 case 0:
alexbrandmeyer@609 91 n_taps_ = 3;
alexbrandmeyer@609 92 break;
alexbrandmeyer@609 93 case 3:
alexbrandmeyer@609 94 n_taps_ = 5;
alexbrandmeyer@609 95 break;
alexbrandmeyer@609 96 case 5:
alexbrandmeyer@609 97 n_iterations_ ++;
alexbrandmeyer@609 98 if (n_iterations_ > 16){
alexbrandmeyer@609 99 throw 10; //too many iterations
alexbrandmeyer@609 100 }
alexbrandmeyer@609 101 break;
alexbrandmeyer@609 102 default:
alexbrandmeyer@609 103 throw 20; //bad n_taps
alexbrandmeyer@609 104 }
alexbrandmeyer@609 105 //Design FIR Coeffs
alexbrandmeyer@609 106 FPType var = spread_sq_ / n_iterations_;
alexbrandmeyer@609 107 FPType mn = delay_ / n_iterations_;
alexbrandmeyer@609 108 switch (n_taps_){
alexbrandmeyer@609 109 case 3:
alexbrandmeyer@609 110 a = (var + pow(mn,2) - mn) / 2;
alexbrandmeyer@609 111 b = (var + pow(mn,2) + mn) / 2;
alexbrandmeyer@609 112 fir_ << a, 1 - a - b, b;
alexbrandmeyer@609 113 if (fir_(2) >= 0.2) {
alexbrandmeyer@609 114 fir_ok_ = true;
alexbrandmeyer@609 115 } else {
alexbrandmeyer@609 116 fir_ok_ = false;
alexbrandmeyer@609 117 }
alexbrandmeyer@609 118 break;
alexbrandmeyer@609 119 case 5:
alexbrandmeyer@609 120 a = (((var + pow(mn,2)) * 2/5) - (mn * 2/3)) / 2;
alexbrandmeyer@609 121 b = (((var + pow(mn,2)) * 2/5) + (mn * 2/3)) / 2;
alexbrandmeyer@609 122 fir_ << a/2, 1 - a - b, b/2;
alexbrandmeyer@609 123 if (fir_(2) >= 0.1) {
alexbrandmeyer@609 124 fir_ok_ = true;
alexbrandmeyer@609 125 } else {
alexbrandmeyer@609 126 fir_ok_ = false;
alexbrandmeyer@609 127 }
alexbrandmeyer@609 128 break;
alexbrandmeyer@609 129 default:
alexbrandmeyer@609 130 throw 30; //bad n_taps in FIR design
alexbrandmeyer@609 131 }
alexbrandmeyer@609 132 }
alexbrandmeyer@609 133 }
alexbrandmeyer@609 134 catch (int e) {
alexbrandmeyer@609 135 switch (e) {
alexbrandmeyer@609 136 case 10:
alexbrandmeyer@609 137 std::cout << "ERROR: Too many n_iterations in agc_coeffs.DesignAGC"
alexbrandmeyer@609 138 << std::endl;
alexbrandmeyer@609 139 break;
alexbrandmeyer@609 140 case 20:
alexbrandmeyer@609 141 std::cout << "ERROR: Bad n_taps in agc_coeffs.DesignAGC" << std::endl;
alexbrandmeyer@609 142 break;
alexbrandmeyer@609 143 case 30:
alexbrandmeyer@609 144 std::cout << "ERROR: Bad n_taps in agc_coeffs.DesignAGC/FIR"
alexbrandmeyer@609 145 << std::endl;
alexbrandmeyer@609 146 break;
alexbrandmeyer@609 147 default:
alexbrandmeyer@609 148 std::cout << "ERROR: unknown error in agc_coeffs.DesignAGC"
alexbrandmeyer@609 149 << std::endl;
alexbrandmeyer@609 150 }
alexbrandmeyer@609 151 }
alexbrandmeyer@609 152 //assign output of filter design
alexbrandmeyer@609 153 agc_spatial_iterations_(stage) = n_iterations_;
alexbrandmeyer@609 154 agc_spatial_n_taps_(stage) = n_taps_;
alexbrandmeyer@609 155 agc_spatial_fir_(0,stage) = fir_(0);
alexbrandmeyer@609 156 agc_spatial_fir_(1,stage) = fir_(1);
alexbrandmeyer@609 157 agc_spatial_fir_(2,stage) = fir_(2);
alexbrandmeyer@609 158 total_dc_gain_ = total_dc_gain_ + pow(agc_stage_gain_,(stage));
alexbrandmeyer@609 159 if (stage == 0) {
alexbrandmeyer@609 160 agc_mix_coeffs_(stage) = 0;
alexbrandmeyer@609 161 } else {
alexbrandmeyer@609 162 agc_mix_coeffs_(stage) = mix_coeff_ / (tau_ * (fs /decim_));
alexbrandmeyer@609 163 }
alexbrandmeyer@609 164 }
alexbrandmeyer@609 165 agc_gain_ = total_dc_gain_;
alexbrandmeyer@609 166 detect_scale_ = 1 / total_dc_gain_;
alexbrandmeyer@609 167 }