Mercurial > hg > aimc
view 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 |
line wrap: on
line source
// Copyright 2007-2010, Thomas Walters // // AIM-C: A C++ implementation of the Auditory Image Model // http://www.acousticscale.org/AIMC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /*! * \file * \brief Parabola strobe detection module - Using the 'parabloa' strobe * criterion from the AIM-MAT sf2003 module * * \author Thomas Walters <tom@acousticscale.org> * \date created 2007/08/01 * \version \$Id$ */ #include <limits.h> #include <cmath> #include "Modules/Strobes/ModuleParabola.h" namespace aimc { ModuleParabola::ModuleParabola(Parameters *params) : Module(params) { module_description_ = "sf2003 parabola algorithm"; module_identifier_ = "parabola"; module_type_ = "strobes"; module_version_ = "$Id$"; // Get data from parameters height_ = parameters_->DefaultFloat("parabola.height", 1.2f); parabw_ = parameters_->DefaultFloat("parabola.width_cycles", 1.5f); strobe_decay_time_ = parameters_->DefaultFloat("parabla.strobe_decay_time", 0.02f); channel_count_ = 0; } bool ModuleParabola::InitializeInternal(const SignalBank &input) { output_.Initialize(input); channel_count_ = input.channel_count(); sample_rate_ = input.sample_rate(); // Parameters for the parabola parab_a_.resize(channel_count_); parab_b_.resize(channel_count_); parab_wnull_.resize(channel_count_); parab_var_samples_.resize(channel_count_); for (int ch = 0; ch < channel_count_; ++ch) { parab_wnull_[ch] = parabw_ / input.centre_frequency(ch); parab_var_samples_[ch] = floor(parab_wnull_[ch] * sample_rate_); parab_a_[ch] = 4.0f * (1.0f - height_) / (parab_wnull_[ch] * parab_wnull_[ch]); parab_b_[ch] = -parab_wnull_[ch] / 2.0f; } // Number of samples over which the threshold should decay strobe_decay_samples_ = floor(sample_rate_ * strobe_decay_time_); // Prepare internal buffers ResetInternal(); return true; } void ModuleParabola::ResetInternal() { threshold_.clear(); threshold_.resize(channel_count_, 0.0f); last_threshold_.clear(); last_threshold_.resize(channel_count_, 0.0f); samples_since_last_strobe_.clear(); samples_since_last_strobe_.resize(channel_count_, 0); prev_sample_.clear(); prev_sample_.resize(channel_count_, 10000.0f); curr_sample_.clear(); curr_sample_.resize(channel_count_, 5000.0f); next_sample_.clear(); next_sample_.resize(channel_count_, 0.0f); } void ModuleParabola::Process(const SignalBank &input) { float decay_constant; for (int ch = 0; ch < output_.channel_count(); ch++) { output_.ResetStrobes(ch); } output_.set_start_time(input.start_time()); // Loop across samples first, then channels for (int i = 0; i < input.buffer_length(); i++) { // Find strobes in each channel first for (int ch = 0; ch < input.channel_count(); ++ch) { // Shift all the samples by one // curr_sample is the sample at time (i - 1) prev_sample_[ch] = curr_sample_[ch]; curr_sample_[ch] = next_sample_[ch]; next_sample_[ch] = input.sample(ch, i); // Copy input signal to output signal output_.set_sample(ch, i, input.sample(ch, i)); if (curr_sample_[ch] >= threshold_[ch]) { threshold_[ch] = curr_sample_[ch]; if (prev_sample_[ch] < curr_sample_[ch] && next_sample_[ch] < curr_sample_[ch]) { // We have a strobe: set threshold and add strobe to the list output_.AddStrobe(ch, i - 1); last_threshold_[ch] = threshold_[ch]; parab_var_samples_[ch] = floor(input.sample_rate() * (parab_wnull_[ch] - (threshold_[ch] - 2.0f * parab_a_[ch] *parab_b_[ch]) / (2.0f * parab_a_[ch]))); } } if (output_.strobe_count(ch) > 0) { samples_since_last_strobe_[ch] = (i - 1) - output_.strobe(ch, output_.strobe_count(ch) - 1); } else { samples_since_last_strobe_[ch] = UINT_MAX; } if (samples_since_last_strobe_[ch] > parab_var_samples_[ch]) { decay_constant = last_threshold_[ch] / strobe_decay_samples_; if (threshold_[ch] > decay_constant) threshold_[ch] -= decay_constant; else threshold_[ch] = 0.0f; } else { threshold_[ch] = last_threshold_[ch] * (parab_a_[ch] * pow((samples_since_last_strobe_[ch] / input.sample_rate() + parab_b_[ch]), 2.0f) + height_); } } } PushOutput(); } ModuleParabola::~ModuleParabola() { } } // namespace aimc