Mercurial > hg > aimc
diff carfac/sai_test.cc @ 642:20f64146c2ce
Initial translation of SAI code to C++.
This only implements the simple (as opposed to the layered) SAI, as
implemented in SAI_Run.m.
author | ronw@google.com |
---|---|
date | Fri, 31 May 2013 21:46:48 +0000 |
parents | |
children | 8b70f4cf00c7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/carfac/sai_test.cc Fri May 31 21:46:48 2013 +0000 @@ -0,0 +1,95 @@ +// Copyright 2013, Google, Inc. +// Author: Ron Weiss <ronw@google.com> +// +// This C++ file is part of an implementation of Lyon's cochlear model: +// "Cascade of Asymmetric Resonators with Fast-Acting Compression" +// to supplement Lyon's upcoming book "Human and Machine Hearing" +// +// 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. + +#include "sai.h" + +#include <iostream> +#include <vector> + +#include "gtest/gtest.h" + +using testing::Values; +using std::vector; + +vector<FloatArray> CreateZeroSegment(int n_ch, int length) { + vector<FloatArray> segment; + for (int i = 0; i < length; ++i) { + segment.push_back(FloatArray::Zero(n_ch)); + } + return segment; +} + +bool HasPeakAt(const Float2dArray& frame, int index) { + if (index == 0) { + return frame(index) > frame(index + 1); + } else if (index == frame.size() - 1) { + return frame(index) > frame(index - 1); + } + return frame(index) > frame(index + 1) && frame(index) > frame(index - 1); +} + +class SAIPeriodicInputTest + : public testing::TestWithParam<std::tr1::tuple<int, int>> { + protected: + void SetUp() { + period_ = std::tr1::get<0>(GetParam()); + phase_ = std::tr1::get<1>(GetParam()); + } + + int period_; + int phase_; +}; + +TEST_P(SAIPeriodicInputTest, SingleChannelPulseTrain) { + vector<FloatArray> segment = CreateZeroSegment(1, 38); + for (int i = phase_; i < segment.size(); i += period_) { + segment[i](0) = 1; + } + + SAIParams sai_params; + sai_params.window_width = segment.size(); + sai_params.n_ch = 1; + sai_params.width = 15; + // Half of the SAI should come from the future. + // sai_params.future_lags = sai_params.width / 2; + sai_params.future_lags = 0; + sai_params.n_window_pos = 2; + + SAI sai(sai_params); + Float2dArray sai_frame; + sai.RunSegment(segment, &sai_frame); + + // The output should have peaks at the same positions, regardless of + // input phase. + for (int i = sai_frame.size() - 1; i >= 0 ; i -= period_) { + EXPECT_TRUE(HasPeakAt(sai_frame, i)); + } + + for (int i = 0; i < segment.size(); ++i) { + std::cout << segment[i](0) << " "; + } + std::cout << "\n"; + for (int i = 0; i < sai_frame.size(); ++i) { + std::cout << sai_frame(i) << " "; + } + std::cout << "\n"; +} +INSTANTIATE_TEST_CASE_P(PeriodicInputVariations, SAIPeriodicInputTest, + testing::Combine(Values(25, 10, 5, 2), // periods. + Values(0, 3))); // phases.