annotate branches/carfac_cpp/src/AGC.cpp @ 695:2e3672df5698

Simple integration test between CARFAC and SAI. The interface between the two classes is pretty clunky because of the way CARFACOutput stores things. We should work on this, probably by rotating the outer two dimensions of CARFACOutput (i.e. store outputs in containers with sizes n_ears x n_samples x n_channels instead of n_samples x n_ears x n_channels).
author ronw@google.com
date Wed, 26 Jun 2013 23:35:47 +0000
parents f3dde307f4b8
children
rev   line source
Ulf@538 1 #include "AGC.h"
pfh1976@554 2 #include <cmath>
pfh1976@554 3 #include <stdlib.h>
pfh1976@554 4 #include <stdio.h>
Ulf@538 5
Ulf@586 6 AGC_parameters::AGC_parameters():
Ulf@586 7 n_stages_(4),
Ulf@586 8 time_constants_({0.002*1, 0.002*4, 0.002*16, 0.002*64}),
Ulf@586 9 agc_stage_gain_(2),
Ulf@586 10 decimation_({8, 2, 2, 2}),
Ulf@586 11 agc1_scales_({1.0, 1.4, 2.0, 2.8}),
Ulf@586 12 agc2_scales_({1.6, 2.25, 3.2, 4.5}),
Ulf@586 13 detect_scale_(0.25),
Ulf@586 14 agc_mix_coeff_(0.5)
Ulf@586 15 {
Ulf@586 16 // do nothing more
Ulf@586 17 }
Ulf@586 18
Ulf@564 19 AGC_coefficients::AGC_coefficients(AGC_parameters* AGC_params_p,
Ulf@545 20 float fs, int n_ch){
pfh1976@554 21 float decim = 1.0;
pfh1976@554 22 float total_DC_gain = 0.0;
pfh1976@554 23 float tau, ntimes, delay, spread_sq, u, p, dp;
pfh1976@554 24 int n_taps = 0, n_iterations = 1;
Ulf@557 25
pfh1976@554 26 n_ch_ = n_ch;
Ulf@564 27 n_agc_stages_ = AGC_params_p->n_stages_;
Ulf@564 28 agc_stage_gain_ = AGC_params_p->agc_stage_gain_;
pfh1976@554 29
pfh1976@554 30 // FloatArray initialization using assign method - dont know if this is good enough
pfh1976@554 31 agc_epsilon_.assign(n_agc_stages_, 0.0); //the 1/(tau*fs) roughly
pfh1976@554 32 agc_polez1_ = agc_epsilon_;
pfh1976@554 33 agc_polez2_ = agc_epsilon_;
pfh1976@554 34 agc_spatial_iterations_ = agc_epsilon_;
pfh1976@554 35 agc_spatial_n_taps_ = agc_epsilon_;
pfh1976@554 36 agc_mix_coeffs_ = agc_epsilon_;
Ulf@564 37 FloatArray agc1_scales = AGC_params_p->agc1_scales_;
Ulf@564 38 FloatArray agc2_scales = AGC_params_p->agc2_scales_;
pfh1976@554 39 FloatArray agc_spatial_FIR;
Ulf@564 40 decimation_ = AGC_params_p->decimation_;
pfh1976@554 41
pfh1976@554 42 for(int stage=0; stage < n_agc_stages_; stage++){
Ulf@564 43 tau = AGC_params_p->time_constants_[stage];
Ulf@564 44 decim *= AGC_params_p->decimation_[stage];
pfh1976@554 45 agc_epsilon_[stage] = 1.0 - exp(-decim/(tau*fs));
pfh1976@554 46 ntimes = tau * (fs/decim);
pfh1976@554 47 delay = (agc2_scales[stage]-agc1_scales[stage])/ntimes;
pfh1976@554 48 spread_sq = (agc1_scales[stage]*agc1_scales[stage] + agc2_scales[stage]*agc2_scales[stage])/ntimes;
pfh1976@554 49
pfh1976@554 50 u = 1.0 + 1.0/spread_sq;
pfh1976@554 51 p = u - sqrt(u*u-1);
pfh1976@554 52 dp = delay*(1 - 2*p + p*p)*0.5;
pfh1976@554 53 agc_polez1_[stage] = p - dp;
pfh1976@554 54 agc_polez2_[stage] = p + dp;
Ulf@557 55
Ulf@557 56 agc_spatial_FIR = Build_FIR_coeffs(spread_sq, delay, &n_iterations, &n_taps);
Ulf@557 57
pfh1976@554 58 agc_spatial_iterations_[stage] = (float) n_iterations;
pfh1976@554 59 agc_spatial_n_taps_[stage] = (float) n_taps;
pfh1976@554 60 agc_spatial_fir_.push_back(FloatArray());
pfh1976@554 61
pfh1976@554 62 for(int i =0; i < 3; i++)
pfh1976@554 63 agc_spatial_fir_[stage].push_back(agc_spatial_FIR[i]);
pfh1976@554 64
Ulf@564 65 total_DC_gain += pow(AGC_params_p->agc_stage_gain_,stage);
pfh1976@554 66
pfh1976@554 67 if(stage == 0)
pfh1976@554 68 agc_mix_coeffs_[stage] = 0.0;
pfh1976@554 69 else
Ulf@564 70 agc_mix_coeffs_[stage] = AGC_params_p->agc_mix_coeff_/(tau * (fs/decim));
pfh1976@554 71 }
pfh1976@554 72 agc_gain_ = total_DC_gain;
Ulf@564 73 detect_scale_ = AGC_params_p->detect_scale_/total_DC_gain;
Ulf@538 74 }
pfh1976@554 75
Ulf@557 76 FloatArray AGC_coefficients::Build_FIR_coeffs(float var, float mn, int* ptr_iters, int* ptr_taps){
pfh1976@554 77 float a, b;
pfh1976@554 78 FloatArray FIR(3);
Ulf@557 79
Ulf@557 80 // Try with 3 FIR taps
Ulf@557 81 a = (var + mn*mn - mn)/2;
Ulf@557 82 b = (var + mn*mn + mn)/2;
Ulf@557 83 FIR[0] = a;
Ulf@557 84 FIR[1] = 1.0 - a - b;
Ulf@557 85 FIR[2] = b;
Ulf@557 86
Ulf@557 87 if(FIR[1] >= 0.2){
Ulf@557 88 *ptr_taps = 3;
Ulf@557 89 return FIR;
pfh1976@554 90 }
Ulf@557 91 else //Try with 5 FIR taps
Ulf@557 92 {
Ulf@557 93 for(int n_iter = 1; n_iter<16; n_iter++){
Ulf@557 94 mn /= n_iter;
Ulf@557 95 var /= n_iter;
Ulf@557 96
Ulf@557 97 a = ((var + mn*mn)*2/5 - mn*2/3)/2;
Ulf@557 98 b = ((var + mn*mn)*2/5 + mn*2/3)/2;
Ulf@557 99 FIR[0] = a/2;
Ulf@557 100 FIR[1] = 1.0 - a - b;
Ulf@557 101 FIR[2] = b;
Ulf@557 102
Ulf@557 103 *ptr_iters = n_iter;
Ulf@557 104
Ulf@557 105 if(FIR[1] >= 0.1){
Ulf@557 106 *ptr_taps = 5;
Ulf@557 107 return FIR;
Ulf@557 108 }
Ulf@557 109 }
Ulf@557 110 //TODO: discuss how we handle errors
Ulf@557 111 printf("Too many iterations in FIR_coeffs\n");
Ulf@557 112 FIR = {0, 0, 0};
Ulf@557 113 return FIR;
Ulf@557 114 }
pfh1976@554 115 }