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