1 /* 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 // MSVC++ requires this to be set before any other includes to get M_PI. 12 #define _USE_MATH_DEFINES 13 14 #include <cmath> 15 16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "webrtc/common_audio/channel_buffer.h" 18 #include "webrtc/modules/audio_processing/splitting_filter.h" 19 20 namespace webrtc { 21 namespace { 22 23 const size_t kSamplesPer16kHzChannel = 160; 24 const size_t kSamplesPer48kHzChannel = 480; 25 26 } // namespace 27 28 // Generates a signal from presence or absence of sine waves of different 29 // frequencies. 30 // Splits into 3 bands and checks their presence or absence. 31 // Recombines the bands. 32 // Calculates the delay. 33 // Checks that the cross correlation of input and output is high enough at the 34 // calculated delay. 35 TEST(SplittingFilterTest, SplitsIntoThreeBandsAndReconstructs) { 36 static const int kChannels = 1; 37 static const int kSampleRateHz = 48000; 38 static const size_t kNumBands = 3; 39 static const int kFrequenciesHz[kNumBands] = {1000, 12000, 18000}; 40 static const float kAmplitude = 8192.f; 41 static const size_t kChunks = 8; 42 SplittingFilter splitting_filter(kChannels, 43 kNumBands, 44 kSamplesPer48kHzChannel); 45 IFChannelBuffer in_data(kSamplesPer48kHzChannel, kChannels, kNumBands); 46 IFChannelBuffer bands(kSamplesPer48kHzChannel, kChannels, kNumBands); 47 IFChannelBuffer out_data(kSamplesPer48kHzChannel, kChannels, kNumBands); 48 for (size_t i = 0; i < kChunks; ++i) { 49 // Input signal generation. 50 bool is_present[kNumBands]; 51 memset(in_data.fbuf()->channels()[0], 52 0, 53 kSamplesPer48kHzChannel * sizeof(in_data.fbuf()->channels()[0][0])); 54 for (size_t j = 0; j < kNumBands; ++j) { 55 is_present[j] = i & (static_cast<size_t>(1) << j); 56 float amplitude = is_present[j] ? kAmplitude : 0.f; 57 for (size_t k = 0; k < kSamplesPer48kHzChannel; ++k) { 58 in_data.fbuf()->channels()[0][k] += 59 amplitude * sin(2.f * M_PI * kFrequenciesHz[j] * 60 (i * kSamplesPer48kHzChannel + k) / kSampleRateHz); 61 } 62 } 63 // Three band splitting filter. 64 splitting_filter.Analysis(&in_data, &bands); 65 // Energy calculation. 66 float energy[kNumBands]; 67 for (size_t j = 0; j < kNumBands; ++j) { 68 energy[j] = 0.f; 69 for (size_t k = 0; k < kSamplesPer16kHzChannel; ++k) { 70 energy[j] += bands.fbuf_const()->channels(j)[0][k] * 71 bands.fbuf_const()->channels(j)[0][k]; 72 } 73 energy[j] /= kSamplesPer16kHzChannel; 74 if (is_present[j]) { 75 EXPECT_GT(energy[j], kAmplitude * kAmplitude / 4); 76 } else { 77 EXPECT_LT(energy[j], kAmplitude * kAmplitude / 4); 78 } 79 } 80 // Three band merge. 81 splitting_filter.Synthesis(&bands, &out_data); 82 // Delay and cross correlation estimation. 83 float xcorr = 0.f; 84 for (size_t delay = 0; delay < kSamplesPer48kHzChannel; ++delay) { 85 float tmpcorr = 0.f; 86 for (size_t j = delay; j < kSamplesPer48kHzChannel; ++j) { 87 tmpcorr += in_data.fbuf_const()->channels()[0][j - delay] * 88 out_data.fbuf_const()->channels()[0][j]; 89 } 90 tmpcorr /= kSamplesPer48kHzChannel; 91 if (tmpcorr > xcorr) { 92 xcorr = tmpcorr; 93 } 94 } 95 // High cross correlation check. 96 bool any_present = false; 97 for (size_t j = 0; j < kNumBands; ++j) { 98 any_present |= is_present[j]; 99 } 100 if (any_present) { 101 EXPECT_GT(xcorr, kAmplitude * kAmplitude / 4); 102 } 103 } 104 } 105 106 } // namespace webrtc 107