Mercurial > hg > aimc
view 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 |
line wrap: on
line source
#include "AGC.h" #include <cmath> #include <stdlib.h> #include <stdio.h> AGC_parameters::AGC_parameters(): n_stages_(4), time_constants_({0.002*1, 0.002*4, 0.002*16, 0.002*64}), agc_stage_gain_(2), decimation_({8, 2, 2, 2}), agc1_scales_({1.0, 1.4, 2.0, 2.8}), agc2_scales_({1.6, 2.25, 3.2, 4.5}), detect_scale_(0.25), agc_mix_coeff_(0.5) { // do nothing more } AGC_coefficients::AGC_coefficients(AGC_parameters* AGC_params_p, float fs, int n_ch){ float decim = 1.0; float total_DC_gain = 0.0; float tau, ntimes, delay, spread_sq, u, p, dp; int n_taps = 0, n_iterations = 1; n_ch_ = n_ch; n_agc_stages_ = AGC_params_p->n_stages_; agc_stage_gain_ = AGC_params_p->agc_stage_gain_; // FloatArray initialization using assign method - dont know if this is good enough agc_epsilon_.assign(n_agc_stages_, 0.0); //the 1/(tau*fs) roughly agc_polez1_ = agc_epsilon_; agc_polez2_ = agc_epsilon_; agc_spatial_iterations_ = agc_epsilon_; agc_spatial_n_taps_ = agc_epsilon_; agc_mix_coeffs_ = agc_epsilon_; FloatArray agc1_scales = AGC_params_p->agc1_scales_; FloatArray agc2_scales = AGC_params_p->agc2_scales_; FloatArray agc_spatial_FIR; decimation_ = AGC_params_p->decimation_; for(int stage=0; stage < n_agc_stages_; stage++){ tau = AGC_params_p->time_constants_[stage]; decim *= AGC_params_p->decimation_[stage]; agc_epsilon_[stage] = 1.0 - exp(-decim/(tau*fs)); ntimes = tau * (fs/decim); delay = (agc2_scales[stage]-agc1_scales[stage])/ntimes; spread_sq = (agc1_scales[stage]*agc1_scales[stage] + agc2_scales[stage]*agc2_scales[stage])/ntimes; u = 1.0 + 1.0/spread_sq; p = u - sqrt(u*u-1); dp = delay*(1 - 2*p + p*p)*0.5; agc_polez1_[stage] = p - dp; agc_polez2_[stage] = p + dp; agc_spatial_FIR = Build_FIR_coeffs(spread_sq, delay, &n_iterations, &n_taps); agc_spatial_iterations_[stage] = (float) n_iterations; agc_spatial_n_taps_[stage] = (float) n_taps; agc_spatial_fir_.push_back(FloatArray()); for(int i =0; i < 3; i++) agc_spatial_fir_[stage].push_back(agc_spatial_FIR[i]); total_DC_gain += pow(AGC_params_p->agc_stage_gain_,stage); if(stage == 0) agc_mix_coeffs_[stage] = 0.0; else agc_mix_coeffs_[stage] = AGC_params_p->agc_mix_coeff_/(tau * (fs/decim)); } agc_gain_ = total_DC_gain; detect_scale_ = AGC_params_p->detect_scale_/total_DC_gain; } FloatArray AGC_coefficients::Build_FIR_coeffs(float var, float mn, int* ptr_iters, int* ptr_taps){ float a, b; FloatArray FIR(3); // Try with 3 FIR taps a = (var + mn*mn - mn)/2; b = (var + mn*mn + mn)/2; FIR[0] = a; FIR[1] = 1.0 - a - b; FIR[2] = b; if(FIR[1] >= 0.2){ *ptr_taps = 3; return FIR; } else //Try with 5 FIR taps { for(int n_iter = 1; n_iter<16; n_iter++){ mn /= n_iter; var /= n_iter; a = ((var + mn*mn)*2/5 - mn*2/3)/2; b = ((var + mn*mn)*2/5 + mn*2/3)/2; FIR[0] = a/2; FIR[1] = 1.0 - a - b; FIR[2] = b; *ptr_iters = n_iter; if(FIR[1] >= 0.1){ *ptr_taps = 5; return FIR; } } //TODO: discuss how we handle errors printf("Too many iterations in FIR_coeffs\n"); FIR = {0, 0, 0}; return FIR; } }