annotate src/Modules/Strobes/ModuleParabola.cc @ 35:b893a04a845e

-More fixes
author tomwalters
date Fri, 26 Feb 2010 07:16:34 +0000
parents 9122efd2b227
children c5f5e9569863
rev   line source
tomwalters@5 1 // Copyright 2007-2010, Thomas Walters
tomwalters@5 2 //
tomwalters@5 3 // AIM-C: A C++ implementation of the Auditory Image Model
tomwalters@5 4 // http://www.acousticscale.org/AIMC
tomwalters@5 5 //
tomwalters@5 6 // This program is free software: you can redistribute it and/or modify
tomwalters@5 7 // it under the terms of the GNU General Public License as published by
tomwalters@5 8 // the Free Software Foundation, either version 3 of the License, or
tomwalters@5 9 // (at your option) any later version.
tomwalters@5 10 //
tomwalters@5 11 // This program is distributed in the hope that it will be useful,
tomwalters@5 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
tomwalters@5 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
tomwalters@5 14 // GNU General Public License for more details.
tomwalters@5 15 //
tomwalters@5 16 // You should have received a copy of the GNU General Public License
tomwalters@5 17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
tomwalters@5 18
tomwalters@5 19 /*!
tomwalters@5 20 * \file
tomwalters@5 21 * \brief Parabola strobe detection module - Using the 'parabloa' strobe
tomwalters@5 22 * criterion from the AIM-MAT sf2003 module
tomwalters@5 23 *
tomwalters@11 24 * \author Thomas Walters <tom@acousticscale.org>
tomwalters@5 25 * \date created 2007/08/01
tomwalters@23 26 * \version \$Id$
tomwalters@5 27 */
tomwalters@5 28
tomwalters@21 29 #include <limits.h>
tomwalters@15 30 #include <cmath>
tomwalters@5 31
tomwalters@5 32 #include "Modules/Strobes/ModuleParabola.h"
tomwalters@5 33
tomwalters@5 34 namespace aimc {
tomwalters@5 35 ModuleParabola::ModuleParabola(Parameters *params) : Module(params) {
tomwalters@5 36 module_description_ = "sf2003 parabola algorithm";
tomwalters@5 37 module_identifier_ = "parabola";
tomwalters@5 38 module_type_ = "strobes";
tomwalters@5 39 module_version_ = "$Id$";
tomwalters@5 40
tomwalters@5 41 // Get data from parameters
tomwalters@5 42 height_ = parameters_->DefaultFloat("parabola.height", 1.2f);
tomwalters@5 43 parabw_ = parameters_->DefaultFloat("parabola.width_cycles", 1.5f);
tomwalters@5 44 strobe_decay_time_ = parameters_->DefaultFloat("parabla.strobe_decay_time",
tomwalters@5 45 0.02f);
tomwalters@5 46 channel_count_ = 0;
tomwalters@5 47 }
tomwalters@5 48
tomwalters@5 49 bool ModuleParabola::InitializeInternal(const SignalBank &input) {
tomwalters@5 50 output_.Initialize(input);
tomwalters@5 51 channel_count_ = input.channel_count();
tomwalters@5 52 sample_rate_ = input.sample_rate();
tomwalters@5 53
tomwalters@5 54 // Parameters for the parabola
tomwalters@5 55 parab_a_.resize(channel_count_);
tomwalters@5 56 parab_b_.resize(channel_count_);
tomwalters@5 57 parab_wnull_.resize(channel_count_);
tomwalters@5 58 parab_var_samples_.resize(channel_count_);
tomwalters@5 59
tomwalters@5 60 for (int ch = 0; ch < channel_count_; ++ch) {
tomwalters@5 61 parab_wnull_[ch] = parabw_ / input.centre_frequency(ch);
tomwalters@5 62 parab_var_samples_[ch] = floor(parab_wnull_[ch] * sample_rate_);
tomwalters@5 63 parab_a_[ch] = 4.0f * (1.0f - height_)
tomwalters@5 64 / (parab_wnull_[ch] * parab_wnull_[ch]);
tomwalters@5 65 parab_b_[ch] = -parab_wnull_[ch] / 2.0f;
tomwalters@5 66 }
tomwalters@5 67
tomwalters@5 68 // Number of samples over which the threshold should decay
tomwalters@5 69 strobe_decay_samples_ = floor(sample_rate_ * strobe_decay_time_);
tomwalters@5 70
tomwalters@5 71 // Prepare internal buffers
tomwalters@5 72 ResetInternal();
tomwalters@5 73
tomwalters@5 74 return true;
tomwalters@5 75 }
tomwalters@5 76
tomwalters@5 77 void ModuleParabola::ResetInternal() {
tomwalters@32 78 threshold_.clear();
tomwalters@5 79 threshold_.resize(channel_count_, 0.0f);
tomwalters@32 80 last_threshold_.clear();
tomwalters@5 81 last_threshold_.resize(channel_count_, 0.0f);
tomwalters@32 82 samples_since_last_strobe_.clear();
tomwalters@5 83 samples_since_last_strobe_.resize(channel_count_, 0);
tomwalters@5 84
tomwalters@32 85 prev_sample_.clear();
tomwalters@5 86 prev_sample_.resize(channel_count_, 10000.0f);
tomwalters@32 87 curr_sample_.clear();
tomwalters@5 88 curr_sample_.resize(channel_count_, 5000.0f);
tomwalters@32 89 next_sample_.clear();
tomwalters@5 90 next_sample_.resize(channel_count_, 0.0f);
tomwalters@5 91 }
tomwalters@5 92
tomwalters@5 93 void ModuleParabola::Process(const SignalBank &input) {
tomwalters@5 94 float decay_constant;
tomwalters@5 95
tomwalters@5 96 for (int ch = 0; ch < output_.channel_count(); ch++) {
tomwalters@5 97 output_.ResetStrobes(ch);
tomwalters@5 98 }
tomwalters@5 99 output_.set_start_time(input.start_time());
tomwalters@5 100
tomwalters@5 101 // Loop across samples first, then channels
tomwalters@5 102 for (int i = 0; i < input.buffer_length(); i++) {
tomwalters@5 103 // Find strobes in each channel first
tomwalters@5 104 for (int ch = 0; ch < input.channel_count(); ++ch) {
tomwalters@5 105 // Shift all the samples by one
tomwalters@5 106 // curr_sample is the sample at time (i - 1)
tomwalters@5 107 prev_sample_[ch] = curr_sample_[ch];
tomwalters@5 108 curr_sample_[ch] = next_sample_[ch];
tomwalters@5 109 next_sample_[ch] = input.sample(ch, i);
tomwalters@5 110
tomwalters@5 111 // Copy input signal to output signal
tomwalters@5 112 output_.set_sample(ch, i, input.sample(ch, i));
tomwalters@5 113
tomwalters@7 114 if (curr_sample_[ch] >= threshold_[ch]) {
tomwalters@7 115 threshold_[ch] = curr_sample_[ch];
tomwalters@7 116 if (prev_sample_[ch] < curr_sample_[ch]
tomwalters@7 117 && next_sample_[ch] < curr_sample_[ch]) {
tomwalters@7 118 // We have a strobe: set threshold and add strobe to the list
tomwalters@7 119 output_.AddStrobe(ch, i - 1);
tomwalters@7 120 last_threshold_[ch] = threshold_[ch];
tomwalters@7 121 parab_var_samples_[ch] =
tomwalters@7 122 floor(input.sample_rate()
tomwalters@7 123 * (parab_wnull_[ch] - (threshold_[ch]
tomwalters@7 124 - 2.0f * parab_a_[ch] *parab_b_[ch])
tomwalters@7 125 / (2.0f * parab_a_[ch])));
tomwalters@7 126 }
tomwalters@5 127 }
tomwalters@7 128 if (output_.strobe_count(ch) > 0) {
tomwalters@5 129 samples_since_last_strobe_[ch] = (i - 1)
tomwalters@5 130 - output_.strobe(ch, output_.strobe_count(ch) - 1);
tomwalters@5 131 } else {
tomwalters@7 132 samples_since_last_strobe_[ch] = UINT_MAX;
tomwalters@5 133 }
tomwalters@5 134
tomwalters@7 135 if (samples_since_last_strobe_[ch] > parab_var_samples_[ch]) {
tomwalters@7 136 decay_constant = last_threshold_[ch] / strobe_decay_samples_;
tomwalters@7 137 if (threshold_[ch] > decay_constant)
tomwalters@7 138 threshold_[ch] -= decay_constant;
tomwalters@7 139 else
tomwalters@7 140 threshold_[ch] = 0.0f;
tomwalters@5 141 } else {
tomwalters@7 142 threshold_[ch] = last_threshold_[ch]
tomwalters@7 143 * (parab_a_[ch] * pow((samples_since_last_strobe_[ch]
tomwalters@7 144 / input.sample_rate() + parab_b_[ch]),
tomwalters@7 145 2.0f) + height_);
tomwalters@5 146 }
tomwalters@5 147 }
tomwalters@5 148 }
tomwalters@5 149
tomwalters@5 150 PushOutput();
tomwalters@5 151 }
tomwalters@5 152
tomwalters@5 153
tomwalters@5 154
tomwalters@5 155 ModuleParabola::~ModuleParabola() {
tomwalters@5 156 }
tomwalters@5 157 } // namespace aimc