annotate trunk/src/Modules/Strobes/ModuleParabola.cc @ 706:f8e90b5d85fd tip

Delete CARFAC code from this repository. It has been moved to https://github.com/google/carfac Please email me with your github username to get access. I've also created a new mailing list to discuss CARFAC development: https://groups.google.com/forum/#!forum/carfac-dev
author ronw@google.com
date Thu, 18 Jul 2013 20:56:51 +0000
parents 30dde71d0230
children
rev   line source
tomwalters@277 1 // Copyright 2007-2010, Thomas Walters
tomwalters@277 2 //
tomwalters@277 3 // AIM-C: A C++ implementation of the Auditory Image Model
tomwalters@277 4 // http://www.acousticscale.org/AIMC
tomwalters@277 5 //
tomwalters@318 6 // Licensed under the Apache License, Version 2.0 (the "License");
tomwalters@318 7 // you may not use this file except in compliance with the License.
tomwalters@318 8 // You may obtain a copy of the License at
tomwalters@277 9 //
tomwalters@318 10 // http://www.apache.org/licenses/LICENSE-2.0
tomwalters@277 11 //
tomwalters@318 12 // Unless required by applicable law or agreed to in writing, software
tomwalters@318 13 // distributed under the License is distributed on an "AS IS" BASIS,
tomwalters@318 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
tomwalters@318 15 // See the License for the specific language governing permissions and
tomwalters@318 16 // limitations under the License.
tomwalters@277 17
tomwalters@277 18 /*!
tomwalters@277 19 * \file
tomwalters@277 20 * \brief Parabola strobe detection module - Using the 'parabloa' strobe
tomwalters@277 21 * criterion from the AIM-MAT sf2003 module
tomwalters@277 22 *
tomwalters@283 23 * \author Thomas Walters <tom@acousticscale.org>
tomwalters@277 24 * \date created 2007/08/01
tomwalters@296 25 * \version \$Id$
tomwalters@277 26 */
tomwalters@277 27
tomwalters@293 28 #include <limits.h>
tomwalters@287 29 #include <cmath>
tomwalters@277 30
tomwalters@277 31 #include "Modules/Strobes/ModuleParabola.h"
tomwalters@277 32
tomwalters@277 33 namespace aimc {
tomwalters@277 34 ModuleParabola::ModuleParabola(Parameters *params) : Module(params) {
tomwalters@277 35 module_description_ = "sf2003 parabola algorithm";
tomwalters@277 36 module_identifier_ = "parabola";
tomwalters@277 37 module_type_ = "strobes";
tomwalters@277 38 module_version_ = "$Id$";
tomwalters@277 39
tomwalters@277 40 // Get data from parameters
tomwalters@277 41 height_ = parameters_->DefaultFloat("parabola.height", 1.2f);
tomwalters@277 42 parabw_ = parameters_->DefaultFloat("parabola.width_cycles", 1.5f);
tomwalters@277 43 strobe_decay_time_ = parameters_->DefaultFloat("parabla.strobe_decay_time",
tomwalters@277 44 0.02f);
tomwalters@277 45 channel_count_ = 0;
tomwalters@277 46 }
tomwalters@277 47
tomwalters@277 48 bool ModuleParabola::InitializeInternal(const SignalBank &input) {
tomwalters@277 49 output_.Initialize(input);
tomwalters@277 50 channel_count_ = input.channel_count();
tomwalters@277 51 sample_rate_ = input.sample_rate();
tomwalters@277 52
tomwalters@277 53 // Parameters for the parabola
tomwalters@277 54 parab_a_.resize(channel_count_);
tomwalters@277 55 parab_b_.resize(channel_count_);
tomwalters@277 56 parab_wnull_.resize(channel_count_);
tomwalters@277 57 parab_var_samples_.resize(channel_count_);
tomwalters@277 58
tomwalters@277 59 for (int ch = 0; ch < channel_count_; ++ch) {
tomwalters@277 60 parab_wnull_[ch] = parabw_ / input.centre_frequency(ch);
tomwalters@277 61 parab_var_samples_[ch] = floor(parab_wnull_[ch] * sample_rate_);
tomwalters@277 62 parab_a_[ch] = 4.0f * (1.0f - height_)
tomwalters@277 63 / (parab_wnull_[ch] * parab_wnull_[ch]);
tomwalters@277 64 parab_b_[ch] = -parab_wnull_[ch] / 2.0f;
tomwalters@277 65 }
tomwalters@277 66
tomwalters@277 67 // Number of samples over which the threshold should decay
tomwalters@277 68 strobe_decay_samples_ = floor(sample_rate_ * strobe_decay_time_);
tomwalters@277 69
tomwalters@277 70 // Prepare internal buffers
tomwalters@277 71 ResetInternal();
tomwalters@277 72
tomwalters@277 73 return true;
tomwalters@277 74 }
tomwalters@277 75
tomwalters@277 76 void ModuleParabola::ResetInternal() {
tomwalters@305 77 threshold_.clear();
tomwalters@277 78 threshold_.resize(channel_count_, 0.0f);
tomwalters@305 79 last_threshold_.clear();
tomwalters@277 80 last_threshold_.resize(channel_count_, 0.0f);
tomwalters@305 81 samples_since_last_strobe_.clear();
tomwalters@277 82 samples_since_last_strobe_.resize(channel_count_, 0);
tomwalters@277 83
tomwalters@305 84 prev_sample_.clear();
tomwalters@277 85 prev_sample_.resize(channel_count_, 10000.0f);
tomwalters@305 86 curr_sample_.clear();
tomwalters@277 87 curr_sample_.resize(channel_count_, 5000.0f);
tomwalters@305 88 next_sample_.clear();
tomwalters@277 89 next_sample_.resize(channel_count_, 0.0f);
tomwalters@277 90 }
tomwalters@277 91
tomwalters@277 92 void ModuleParabola::Process(const SignalBank &input) {
tomwalters@277 93 float decay_constant;
tomwalters@277 94
tomwalters@277 95 for (int ch = 0; ch < output_.channel_count(); ch++) {
tomwalters@277 96 output_.ResetStrobes(ch);
tomwalters@277 97 }
tomwalters@277 98 output_.set_start_time(input.start_time());
tomwalters@277 99
tomwalters@277 100 // Loop across samples first, then channels
tomwalters@277 101 for (int i = 0; i < input.buffer_length(); i++) {
tomwalters@277 102 // Find strobes in each channel first
tomwalters@277 103 for (int ch = 0; ch < input.channel_count(); ++ch) {
tomwalters@277 104 // Shift all the samples by one
tomwalters@277 105 // curr_sample is the sample at time (i - 1)
tomwalters@277 106 prev_sample_[ch] = curr_sample_[ch];
tomwalters@277 107 curr_sample_[ch] = next_sample_[ch];
tomwalters@277 108 next_sample_[ch] = input.sample(ch, i);
tomwalters@277 109
tomwalters@277 110 // Copy input signal to output signal
tomwalters@277 111 output_.set_sample(ch, i, input.sample(ch, i));
tomwalters@277 112
tomwalters@279 113 if (curr_sample_[ch] >= threshold_[ch]) {
tomwalters@279 114 threshold_[ch] = curr_sample_[ch];
tomwalters@279 115 if (prev_sample_[ch] < curr_sample_[ch]
tomwalters@279 116 && next_sample_[ch] < curr_sample_[ch]) {
tomwalters@279 117 // We have a strobe: set threshold and add strobe to the list
tomwalters@279 118 output_.AddStrobe(ch, i - 1);
tomwalters@279 119 last_threshold_[ch] = threshold_[ch];
tomwalters@279 120 parab_var_samples_[ch] =
tomwalters@279 121 floor(input.sample_rate()
tomwalters@279 122 * (parab_wnull_[ch] - (threshold_[ch]
tomwalters@279 123 - 2.0f * parab_a_[ch] *parab_b_[ch])
tomwalters@279 124 / (2.0f * parab_a_[ch])));
tomwalters@279 125 }
tomwalters@277 126 }
tomwalters@279 127 if (output_.strobe_count(ch) > 0) {
tomwalters@277 128 samples_since_last_strobe_[ch] = (i - 1)
tomwalters@277 129 - output_.strobe(ch, output_.strobe_count(ch) - 1);
tomwalters@277 130 } else {
tomwalters@279 131 samples_since_last_strobe_[ch] = UINT_MAX;
tomwalters@277 132 }
tomwalters@277 133
tomwalters@279 134 if (samples_since_last_strobe_[ch] > parab_var_samples_[ch]) {
tomwalters@279 135 decay_constant = last_threshold_[ch] / strobe_decay_samples_;
tomwalters@279 136 if (threshold_[ch] > decay_constant)
tomwalters@279 137 threshold_[ch] -= decay_constant;
tomwalters@279 138 else
tomwalters@279 139 threshold_[ch] = 0.0f;
tomwalters@277 140 } else {
tomwalters@279 141 threshold_[ch] = last_threshold_[ch]
tomwalters@279 142 * (parab_a_[ch] * pow((samples_since_last_strobe_[ch]
tomwalters@279 143 / input.sample_rate() + parab_b_[ch]),
tomwalters@279 144 2.0f) + height_);
tomwalters@277 145 }
tomwalters@277 146 }
tomwalters@277 147 }
tomwalters@277 148
tomwalters@277 149 PushOutput();
tomwalters@277 150 }
tomwalters@277 151
tomwalters@277 152
tomwalters@277 153
tomwalters@277 154 ModuleParabola::~ModuleParabola() {
tomwalters@277 155 }
tomwalters@277 156 } // namespace aimc