| /* |
| * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| // MSVC++ requires this to be set before any other includes to get M_PI. |
| #define _USE_MATH_DEFINES |
| |
| #include <math.h> |
| |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "webrtc/common_audio/channel_buffer.h" |
| #include "webrtc/modules/audio_processing/splitting_filter.h" |
| #include "webrtc/common_audio/include/audio_util.h" |
| |
| namespace webrtc { |
| |
| // Generates a signal from presence or absence of sine waves of different |
| // frequencies. |
| // Splits into 3 bands and checks their presence or absence. |
| // Recombines the bands. |
| // Calculates the delay. |
| // Checks that the cross correlation of input and output is high enough at the |
| // calculated delay. |
| TEST(SplittingFilterTest, SplitsIntoThreeBandsAndReconstructs) { |
| static const int kChannels = 1; |
| static const int kSampleRateHz = 48000; |
| static const int kNumBands = 3; |
| static const int kFrequenciesHz[kNumBands] = {1000, 12000, 18000}; |
| static const float kAmplitude = 8192; |
| static const int kChunks = 8; |
| SplittingFilter splitting_filter(kChannels); |
| IFChannelBuffer in_data(kSamplesPer48kHzChannel, kChannels); |
| IFChannelBuffer out_data(kSamplesPer48kHzChannel, kChannels); |
| ScopedVector<IFChannelBuffer> bands; |
| for (int i = 0; i < kNumBands; ++i) { |
| bands.push_back(new IFChannelBuffer(kSamplesPer16kHzChannel, kChannels)); |
| } |
| for (int i = 0; i < kChunks; ++i) { |
| // Input signal generation. |
| bool is_present[kNumBands]; |
| memset(in_data.fbuf()->channel(0), |
| 0, |
| kSamplesPer48kHzChannel * sizeof(in_data.fbuf()->channel(0)[0])); |
| for (int j = 0; j < kNumBands; ++j) { |
| is_present[j] = i & (1 << j); |
| float amplitude = is_present[j] ? kAmplitude : 0; |
| for (int k = 0; k < kSamplesPer48kHzChannel; ++k) { |
| in_data.fbuf()->channel(0)[k] += |
| amplitude * sin(2 * M_PI * kFrequenciesHz[j] * |
| (i * kSamplesPer48kHzChannel + k) / kSampleRateHz); |
| } |
| } |
| // Three band splitting filter. |
| splitting_filter.Analysis(&in_data, bands.get()); |
| // Energy calculation. |
| float energy[kNumBands]; |
| for (int j = 0; j < kNumBands; ++j) { |
| energy[j] = 0; |
| for (int k = 0; k < kSamplesPer16kHzChannel; ++k) { |
| energy[j] += bands[j]->fbuf_const()->channel(0)[k] * |
| bands[j]->fbuf_const()->channel(0)[k]; |
| } |
| energy[j] /= kSamplesPer16kHzChannel; |
| if (is_present[j]) { |
| EXPECT_GT(energy[j], kAmplitude * kAmplitude / 4); |
| } else { |
| EXPECT_LT(energy[j], kAmplitude * kAmplitude / 4); |
| } |
| } |
| // Three band merge. |
| splitting_filter.Synthesis(bands.get(), &out_data); |
| // Delay and cross correlation estimation. |
| float xcorr = 0; |
| for (int delay = 0; delay < kSamplesPer48kHzChannel; ++delay) { |
| float tmpcorr = 0; |
| for (int j = delay; j < kSamplesPer48kHzChannel; ++j) { |
| tmpcorr += in_data.fbuf_const()->channel(0)[j] * |
| out_data.fbuf_const()->channel(0)[j - delay]; |
| } |
| tmpcorr /= kSamplesPer48kHzChannel; |
| if (tmpcorr > xcorr) { |
| xcorr = tmpcorr; |
| } |
| } |
| // High cross correlation check. |
| bool any_present = false; |
| for (int j = 0; j < kNumBands; ++j) { |
| any_present |= is_present[j]; |
| } |
| if (any_present) { |
| EXPECT_GT(xcorr, kAmplitude * kAmplitude / 4); |
| } |
| } |
| } |
| |
| } // namespace webrtc |