Mercurial > hg > aimc
comparison src/Modules/Strobes/ModuleLocalMax.cc @ 32:9122efd2b227
-New AIMCopy main for the SSI features (temporary hack till I get a working module load system)
-LocalMax strobe criterion. This is faster and better than the parabola version, which still seems buggy.
-Noise generator module. Adds noise to a signal. Uses boost for the random number generator.
-New options for the SSI
-Slice now respects all its flags (oops!).
-MATLAB functions for visualisation
-Scripts for generating data to view in MATLAB
-Script to download and build HTK - useful for running experiments
author | tomwalters |
---|---|
date | Thu, 25 Feb 2010 22:02:00 +0000 |
parents | |
children | c5f5e9569863 |
comparison
equal
deleted
inserted
replaced
31:fa06bfacf004 | 32:9122efd2b227 |
---|---|
1 // Copyright 2010, Thomas Walters | |
2 // | |
3 // AIM-C: A C++ implementation of the Auditory Image Model | |
4 // http://www.acousticscale.org/AIMC | |
5 // | |
6 // This program is free software: you can redistribute it and/or modify | |
7 // it under the terms of the GNU General Public License as published by | |
8 // the Free Software Foundation, either version 3 of the License, or | |
9 // (at your option) any later version. | |
10 // | |
11 // This program is distributed in the hope that it will be useful, | |
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 // GNU General Public License for more details. | |
15 // | |
16 // You should have received a copy of the GNU General Public License | |
17 // along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | |
19 /*! | |
20 * \file | |
21 * \brief | |
22 * | |
23 * \author Thomas Walters <tom@acousticscale.org> | |
24 * \date created 2010/02/23 | |
25 * \version \$Id$ | |
26 */ | |
27 | |
28 #include <math.h> | |
29 #include "Modules/Strobes/ModuleLocalMax.h" | |
30 | |
31 namespace aimc { | |
32 ModuleLocalMax::ModuleLocalMax(Parameters *params) : Module(params) { | |
33 module_description_ = "Local maximum strobe criterion: decaying threshold " | |
34 "with timeout"; | |
35 module_identifier_ = "local_max"; | |
36 module_type_ = "strobes"; | |
37 module_version_ = "$Id$"; | |
38 | |
39 decay_time_ms_ = parameters_->DefaultFloat("strobes.decay_time_ms", 20.0f); | |
40 timeout_ms_ = parameters_->DefaultFloat("strobes.timeout_ms", 3.0f); | |
41 } | |
42 | |
43 ModuleLocalMax::~ModuleLocalMax() { | |
44 } | |
45 | |
46 bool ModuleLocalMax::InitializeInternal(const SignalBank &input) { | |
47 // Copy the parameters of the input signal bank into internal variables, so | |
48 // that they can be checked later. | |
49 sample_rate_ = input.sample_rate(); | |
50 buffer_length_ = input.buffer_length(); | |
51 channel_count_ = input.channel_count(); | |
52 output_.Initialize(input); | |
53 strobe_timeout_samples_ = floor(timeout_ms_ * sample_rate_ / 1000.0f); | |
54 strobe_decay_samples_ = floor(decay_time_ms_ * sample_rate_ / 1000.0f); | |
55 ResetInternal(); | |
56 return true; | |
57 } | |
58 | |
59 void ModuleLocalMax::ResetInternal() { | |
60 threshold_.clear(); | |
61 threshold_.resize(channel_count_, 0.0f); | |
62 | |
63 decay_constant_.clear(); | |
64 decay_constant_.resize(channel_count_, 1.0f); | |
65 | |
66 prev_sample_.clear(); | |
67 prev_sample_.resize(channel_count_, 10000.0f); | |
68 curr_sample_.clear(); | |
69 curr_sample_.resize(channel_count_, 5000.0f); | |
70 next_sample_.clear(); | |
71 next_sample_.resize(channel_count_, 0.0f); | |
72 } | |
73 | |
74 void ModuleLocalMax::Process(const SignalBank &input) { | |
75 // Check to see if the module has been initialized. If not, processing | |
76 // should not continue. | |
77 if (!initialized_) { | |
78 LOG_ERROR(_T("Module %s not initialized."), module_identifier_.c_str()); | |
79 return; | |
80 } | |
81 | |
82 // Check that ths input this time is the same as the input passed to | |
83 // Initialize() | |
84 if (buffer_length_ != input.buffer_length() | |
85 || channel_count_ != input.channel_count()) { | |
86 LOG_ERROR(_T("Mismatch between input to Initialize() and input to " | |
87 "Process() in module %s."), module_identifier_.c_str()); | |
88 return; | |
89 } | |
90 | |
91 for (int ch = 0; ch < output_.channel_count(); ch++) { | |
92 output_.ResetStrobes(ch); | |
93 } | |
94 output_.set_start_time(input.start_time()); | |
95 for (int i = 0; i < input.buffer_length(); i++) { | |
96 for (int ch = 0; ch < input.channel_count(); ++ch) { | |
97 // curr_sample is the sample at time (i - 1) | |
98 prev_sample_[ch] = curr_sample_[ch]; | |
99 curr_sample_[ch] = next_sample_[ch]; | |
100 next_sample_[ch] = input.sample(ch, i); | |
101 // Copy input signal to output signal | |
102 output_.set_sample(ch, i, input.sample(ch, i)); | |
103 | |
104 // If the current sample is above threshold, the threshold is raised to | |
105 // the level of the current sample, and decays from there. | |
106 if (curr_sample_[ch] >= threshold_[ch]) { | |
107 threshold_[ch] = curr_sample_[ch]; | |
108 decay_constant_[ch] = threshold_[ch] / strobe_decay_samples_; | |
109 | |
110 // If the current sample is also a peak, then it is a potential strobe | |
111 // point. | |
112 if (prev_sample_[ch] < curr_sample_[ch] | |
113 && next_sample_[ch] < curr_sample_[ch]) { | |
114 // If there are no strobes so far in this channel, then the sample | |
115 // is definitely a strobe (this means that the timeout is not | |
116 // respected across frame boundaries. This is a minor bug, but I | |
117 // don't believe that it's serious enough to warrant updating the | |
118 // samples since last strobe all the time.) | |
119 int count = output_.strobe_count(ch); | |
120 if (count > 0) { | |
121 // If there are previous strobes, then calculate the time since | |
122 // the last one. If it's long enough, then this is a strobe point, | |
123 // if not, then just move on. | |
124 int samples_since_last = (i - 1) - output_.strobe(ch, count - 1); | |
125 if (samples_since_last > strobe_timeout_samples_) { | |
126 output_.AddStrobe(ch, i - 1); | |
127 } | |
128 } else { | |
129 output_.AddStrobe(ch, i - 1); | |
130 } | |
131 } | |
132 } | |
133 | |
134 // Update the threshold, decaying as necessary | |
135 if (threshold_[ch] > decay_constant_[ch]) | |
136 threshold_[ch] -= decay_constant_[ch]; | |
137 else | |
138 threshold_[ch] = 0.0f; | |
139 } | |
140 } | |
141 PushOutput(); | |
142 } | |
143 } // namespace aimc | |
144 |