1/* 2 * Copyright (c) 2012 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// Unit tests for DtmfToneGenerator class. 12 13#include "webrtc/modules/audio_coding/neteq/dtmf_tone_generator.h" 14 15#include <math.h> 16 17#include "testing/gtest/include/gtest/gtest.h" 18#include "webrtc/modules/audio_coding/neteq/audio_multi_vector.h" 19 20namespace webrtc { 21 22class DtmfToneGeneratorTest : public ::testing::Test { 23 protected: 24 static const double kLowFreqHz[16]; 25 static const double kHighFreqHz[16]; 26 // This is the attenuation applied to all cases. 27 const double kBaseAttenuation = 16141.0 / 16384.0; 28 const double k3dbAttenuation = 23171.0 / 32768; 29 const int kNumSamples = 10; 30 31 void TestAllTones(int fs_hz, int channels) { 32 AudioMultiVector signal(channels); 33 34 for (int event = 0; event <= 15; ++event) { 35 std::ostringstream ss; 36 ss << "Checking event " << event << " at sample rate " << fs_hz; 37 SCOPED_TRACE(ss.str()); 38 const int kAttenuation = 0; 39 ASSERT_EQ(0, tone_gen_.Init(fs_hz, event, kAttenuation)); 40 EXPECT_TRUE(tone_gen_.initialized()); 41 EXPECT_EQ(kNumSamples, tone_gen_.Generate(kNumSamples, &signal)); 42 43 double f1 = kLowFreqHz[event]; 44 double f2 = kHighFreqHz[event]; 45 const double pi = 3.14159265358979323846; 46 47 for (int n = 0; n < kNumSamples; ++n) { 48 double x = k3dbAttenuation * sin(2.0 * pi * f1 / fs_hz * (-n - 1)) + 49 sin(2.0 * pi * f2 / fs_hz * (-n - 1)); 50 x *= kBaseAttenuation; 51 x = ldexp(x, 14); // Scale to Q14. 52 for (int channel = 0; channel < channels; ++channel) { 53 EXPECT_NEAR(x, static_cast<double>(signal[channel][n]), 25); 54 } 55 } 56 57 tone_gen_.Reset(); 58 EXPECT_FALSE(tone_gen_.initialized()); 59 } 60 } 61 62 void TestAmplitudes(int fs_hz, int channels) { 63 AudioMultiVector signal(channels); 64 AudioMultiVector ref_signal(channels); 65 66 const int event_vec[] = {0, 4, 9, 13}; // Test a few events. 67 for (int e = 0; e < 4; ++e) { 68 int event = event_vec[e]; 69 // Create full-scale reference. 70 ASSERT_EQ(0, tone_gen_.Init(fs_hz, event, 0)); // 0 attenuation. 71 EXPECT_EQ(kNumSamples, tone_gen_.Generate(kNumSamples, &ref_signal)); 72 // Test every 5 steps (to save time). 73 for (int attenuation = 1; attenuation <= 36; attenuation += 5) { 74 std::ostringstream ss; 75 ss << "Checking event " << event << " at sample rate " << fs_hz; 76 ss << "; attenuation " << attenuation; 77 SCOPED_TRACE(ss.str()); 78 ASSERT_EQ(0, tone_gen_.Init(fs_hz, event, attenuation)); 79 EXPECT_EQ(kNumSamples, tone_gen_.Generate(kNumSamples, &signal)); 80 for (int n = 0; n < kNumSamples; ++n) { 81 double attenuation_factor = 82 pow(10, -static_cast<double>(attenuation) / 20); 83 // Verify that the attenuation is correct. 84 for (int channel = 0; channel < channels; ++channel) { 85 EXPECT_NEAR(attenuation_factor * ref_signal[channel][n], 86 signal[channel][n], 87 2); 88 } 89 } 90 91 tone_gen_.Reset(); 92 } 93 } 94 } 95 96 DtmfToneGenerator tone_gen_; 97}; 98 99// Low and high frequencies for events 0 through 15. 100const double DtmfToneGeneratorTest::kLowFreqHz[16] = { 101 941.0, 697.0, 697.0, 697.0, 770.0, 770.0, 770.0, 852.0, 102 852.0, 852.0, 941.0, 941.0, 697.0, 770.0, 852.0, 941.0}; 103const double DtmfToneGeneratorTest::kHighFreqHz[16] = { 104 1336.0, 1209.0, 1336.0, 1477.0, 1209.0, 1336.0, 1477.0, 1209.0, 105 1336.0, 1477.0, 1209.0, 1477.0, 1633.0, 1633.0, 1633.0, 1633.0}; 106 107TEST_F(DtmfToneGeneratorTest, Test8000Mono) { 108 TestAllTones(8000, 1); 109 TestAmplitudes(8000, 1); 110} 111 112TEST_F(DtmfToneGeneratorTest, Test16000Mono) { 113 TestAllTones(16000, 1); 114 TestAmplitudes(16000, 1); 115} 116 117TEST_F(DtmfToneGeneratorTest, Test32000Mono) { 118 TestAllTones(32000, 1); 119 TestAmplitudes(32000, 1); 120} 121 122TEST_F(DtmfToneGeneratorTest, Test48000Mono) { 123 TestAllTones(48000, 1); 124 TestAmplitudes(48000, 1); 125} 126 127TEST_F(DtmfToneGeneratorTest, Test8000Stereo) { 128 TestAllTones(8000, 2); 129 TestAmplitudes(8000, 2); 130} 131 132TEST_F(DtmfToneGeneratorTest, Test16000Stereo) { 133 TestAllTones(16000, 2); 134 TestAmplitudes(16000, 2); 135} 136 137TEST_F(DtmfToneGeneratorTest, Test32000Stereo) { 138 TestAllTones(32000, 2); 139 TestAmplitudes(32000, 2); 140} 141 142TEST_F(DtmfToneGeneratorTest, Test48000Stereo) { 143 TestAllTones(48000, 2); 144 TestAmplitudes(48000, 2); 145} 146 147TEST(DtmfToneGenerator, TestErrors) { 148 DtmfToneGenerator tone_gen; 149 const int kNumSamples = 10; 150 AudioMultiVector signal(1); // One channel. 151 152 // Try to generate tones without initializing. 153 EXPECT_EQ(DtmfToneGenerator::kNotInitialized, 154 tone_gen.Generate(kNumSamples, &signal)); 155 156 const int fs = 16000; // Valid sample rate. 157 const int event = 7; // Valid event. 158 const int attenuation = 0; // Valid attenuation. 159 // Initialize with invalid event -1. 160 EXPECT_EQ(DtmfToneGenerator::kParameterError, 161 tone_gen.Init(fs, -1, attenuation)); 162 // Initialize with invalid event 16. 163 EXPECT_EQ(DtmfToneGenerator::kParameterError, 164 tone_gen.Init(fs, 16, attenuation)); 165 // Initialize with invalid attenuation -1. 166 EXPECT_EQ(DtmfToneGenerator::kParameterError, tone_gen.Init(fs, event, -1)); 167 // Initialize with invalid attenuation 37. 168 EXPECT_EQ(DtmfToneGenerator::kParameterError, tone_gen.Init(fs, event, 37)); 169 EXPECT_FALSE(tone_gen.initialized()); // Should still be uninitialized. 170 171 // Initialize with valid parameters. 172 ASSERT_EQ(0, tone_gen.Init(fs, event, attenuation)); 173 EXPECT_TRUE(tone_gen.initialized()); 174 // Negative number of samples. 175 EXPECT_EQ(DtmfToneGenerator::kParameterError, tone_gen.Generate(-1, &signal)); 176 // NULL pointer to destination. 177 EXPECT_EQ(DtmfToneGenerator::kParameterError, 178 tone_gen.Generate(kNumSamples, NULL)); 179} 180 181} // namespace webrtc 182