annotate trunk/src/Modules/Strobes/ModuleParabola.cc @ 402:69466da9745e

- Massive refactoring to make module tree stuff work. In theory we now support configuration files again. The graphics stuff is untested as yet.
author tomwalters
date Mon, 18 Oct 2010 04:42:28 +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