annotate trunk/src/Modules/Strobes/ModuleLocalMax.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 0f54006e91ea
children
rev   line source
tomwalters@305 1 // Copyright 2010, Thomas Walters
tomwalters@305 2 //
tomwalters@305 3 // AIM-C: A C++ implementation of the Auditory Image Model
tomwalters@305 4 // http://www.acousticscale.org/AIMC
tomwalters@305 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@305 9 //
tomwalters@318 10 // http://www.apache.org/licenses/LICENSE-2.0
tomwalters@305 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@305 17
tomwalters@305 18 /*!
tomwalters@305 19 * \file
tomwalters@305 20 * \brief
tomwalters@305 21 *
tomwalters@305 22 * \author Thomas Walters <tom@acousticscale.org>
tomwalters@305 23 * \date created 2010/02/23
tomwalters@305 24 * \version \$Id$
tomwalters@305 25 */
tomwalters@305 26
tomwalters@305 27 #include <math.h>
tomwalters@305 28 #include "Modules/Strobes/ModuleLocalMax.h"
tomwalters@305 29
tomwalters@305 30 namespace aimc {
tomwalters@305 31 ModuleLocalMax::ModuleLocalMax(Parameters *params) : Module(params) {
tomwalters@305 32 module_description_ = "Local maximum strobe criterion: decaying threshold "
tomwalters@305 33 "with timeout";
tomwalters@305 34 module_identifier_ = "local_max";
tomwalters@305 35 module_type_ = "strobes";
tomwalters@323 36 module_version_ = "$Id: $";
tomwalters@305 37
tomwalters@305 38 decay_time_ms_ = parameters_->DefaultFloat("strobes.decay_time_ms", 20.0f);
tomwalters@305 39 timeout_ms_ = parameters_->DefaultFloat("strobes.timeout_ms", 3.0f);
tomwalters@305 40 }
tomwalters@305 41
tomwalters@305 42 ModuleLocalMax::~ModuleLocalMax() {
tomwalters@305 43 }
tomwalters@305 44
tomwalters@305 45 bool ModuleLocalMax::InitializeInternal(const SignalBank &input) {
tomwalters@305 46 // Copy the parameters of the input signal bank into internal variables, so
tomwalters@305 47 // that they can be checked later.
tomwalters@305 48 sample_rate_ = input.sample_rate();
tomwalters@305 49 buffer_length_ = input.buffer_length();
tomwalters@305 50 channel_count_ = input.channel_count();
tomwalters@305 51 output_.Initialize(input);
tomwalters@305 52 strobe_timeout_samples_ = floor(timeout_ms_ * sample_rate_ / 1000.0f);
tomwalters@305 53 strobe_decay_samples_ = floor(decay_time_ms_ * sample_rate_ / 1000.0f);
tomwalters@305 54 ResetInternal();
tomwalters@305 55 return true;
tomwalters@305 56 }
tomwalters@305 57
tomwalters@305 58 void ModuleLocalMax::ResetInternal() {
tomwalters@305 59 threshold_.clear();
tomwalters@305 60 threshold_.resize(channel_count_, 0.0f);
tomwalters@305 61
tomwalters@305 62 decay_constant_.clear();
tomwalters@305 63 decay_constant_.resize(channel_count_, 1.0f);
tomwalters@305 64
tomwalters@305 65 prev_sample_.clear();
tomwalters@305 66 prev_sample_.resize(channel_count_, 10000.0f);
tomwalters@305 67 curr_sample_.clear();
tomwalters@305 68 curr_sample_.resize(channel_count_, 5000.0f);
tomwalters@305 69 next_sample_.clear();
tomwalters@305 70 next_sample_.resize(channel_count_, 0.0f);
tomwalters@305 71 }
tomwalters@305 72
tomwalters@305 73 void ModuleLocalMax::Process(const SignalBank &input) {
tomwalters@305 74 // Check to see if the module has been initialized. If not, processing
tomwalters@305 75 // should not continue.
tomwalters@305 76 if (!initialized_) {
tomwalters@305 77 LOG_ERROR(_T("Module %s not initialized."), module_identifier_.c_str());
tomwalters@305 78 return;
tomwalters@305 79 }
tomwalters@305 80
tomwalters@305 81 // Check that ths input this time is the same as the input passed to
tomwalters@305 82 // Initialize()
tomwalters@305 83 if (buffer_length_ != input.buffer_length()
tomwalters@305 84 || channel_count_ != input.channel_count()) {
tomwalters@305 85 LOG_ERROR(_T("Mismatch between input to Initialize() and input to "
tomwalters@305 86 "Process() in module %s."), module_identifier_.c_str());
tomwalters@305 87 return;
tomwalters@305 88 }
tomwalters@305 89
tomwalters@305 90 for (int ch = 0; ch < output_.channel_count(); ch++) {
tomwalters@305 91 output_.ResetStrobes(ch);
tomwalters@305 92 }
tomwalters@305 93 output_.set_start_time(input.start_time());
tomwalters@305 94 for (int i = 0; i < input.buffer_length(); i++) {
tomwalters@305 95 for (int ch = 0; ch < input.channel_count(); ++ch) {
tomwalters@305 96 // curr_sample is the sample at time (i - 1)
tomwalters@305 97 prev_sample_[ch] = curr_sample_[ch];
tomwalters@305 98 curr_sample_[ch] = next_sample_[ch];
tomwalters@305 99 next_sample_[ch] = input.sample(ch, i);
tomwalters@305 100 // Copy input signal to output signal
tomwalters@305 101 output_.set_sample(ch, i, input.sample(ch, i));
tomwalters@305 102
tomwalters@305 103 // If the current sample is above threshold, the threshold is raised to
tomwalters@305 104 // the level of the current sample, and decays from there.
tomwalters@305 105 if (curr_sample_[ch] >= threshold_[ch]) {
tomwalters@305 106 threshold_[ch] = curr_sample_[ch];
tomwalters@305 107 decay_constant_[ch] = threshold_[ch] / strobe_decay_samples_;
tomwalters@305 108
tomwalters@305 109 // If the current sample is also a peak, then it is a potential strobe
tomwalters@305 110 // point.
tomwalters@305 111 if (prev_sample_[ch] < curr_sample_[ch]
tomwalters@305 112 && next_sample_[ch] < curr_sample_[ch]) {
tomwalters@305 113 // If there are no strobes so far in this channel, then the sample
tomwalters@305 114 // is definitely a strobe (this means that the timeout is not
tomwalters@305 115 // respected across frame boundaries. This is a minor bug, but I
tomwalters@305 116 // don't believe that it's serious enough to warrant updating the
tomwalters@305 117 // samples since last strobe all the time.)
tomwalters@305 118 int count = output_.strobe_count(ch);
tomwalters@305 119 if (count > 0) {
tomwalters@305 120 // If there are previous strobes, then calculate the time since
tomwalters@305 121 // the last one. If it's long enough, then this is a strobe point,
tomwalters@305 122 // if not, then just move on.
tomwalters@305 123 int samples_since_last = (i - 1) - output_.strobe(ch, count - 1);
tomwalters@305 124 if (samples_since_last > strobe_timeout_samples_) {
tomwalters@305 125 output_.AddStrobe(ch, i - 1);
tomwalters@305 126 }
tomwalters@305 127 } else {
tomwalters@305 128 output_.AddStrobe(ch, i - 1);
tomwalters@305 129 }
tomwalters@305 130 }
tomwalters@305 131 }
tomwalters@305 132
tomwalters@305 133 // Update the threshold, decaying as necessary
tomwalters@305 134 if (threshold_[ch] > decay_constant_[ch])
tomwalters@305 135 threshold_[ch] -= decay_constant_[ch];
tomwalters@305 136 else
tomwalters@305 137 threshold_[ch] = 0.0f;
tomwalters@305 138 }
tomwalters@305 139 }
tomwalters@305 140 PushOutput();
tomwalters@305 141 }
tomwalters@305 142 } // namespace aimc
tomwalters@305 143