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 "gtest/gtest.h" 18 #include "webrtc/modules/audio_coding/neteq/audio_multi_vector.h" 19 20 namespace webrtc { 21 22 TEST(DtmfToneGenerator, CreateAndDestroy) { 23 DtmfToneGenerator* tone_gen = new DtmfToneGenerator(); 24 delete tone_gen; 25 } 26 27 TEST(DtmfToneGenerator, TestErrors) { 28 DtmfToneGenerator tone_gen; 29 const int kNumSamples = 10; 30 AudioMultiVector signal(1); // One channel. 31 32 // Try to generate tones without initializing. 33 EXPECT_EQ(DtmfToneGenerator::kNotInitialized, 34 tone_gen.Generate(kNumSamples, &signal)); 35 36 const int fs = 16000; // Valid sample rate. 37 const int event = 7; // Valid event. 38 const int attenuation = 0; // Valid attenuation. 39 // Initialize with invalid event -1. 40 EXPECT_EQ(DtmfToneGenerator::kParameterError, 41 tone_gen.Init(fs, -1, attenuation)); 42 // Initialize with invalid event 16. 43 EXPECT_EQ(DtmfToneGenerator::kParameterError, 44 tone_gen.Init(fs, 16, attenuation)); 45 // Initialize with invalid attenuation -1. 46 EXPECT_EQ(DtmfToneGenerator::kParameterError, tone_gen.Init(fs, event, -1)); 47 // Initialize with invalid attenuation 37. 48 EXPECT_EQ(DtmfToneGenerator::kParameterError, tone_gen.Init(fs, event, 37)); 49 EXPECT_FALSE(tone_gen.initialized()); // Should still be uninitialized. 50 51 // Initialize with valid parameters. 52 ASSERT_EQ(0, tone_gen.Init(fs, event, attenuation)); 53 EXPECT_TRUE(tone_gen.initialized()); 54 // Negative number of samples. 55 EXPECT_EQ(DtmfToneGenerator::kParameterError, tone_gen.Generate(-1, &signal)); 56 // NULL pointer to destination. 57 EXPECT_EQ(DtmfToneGenerator::kParameterError, 58 tone_gen.Generate(kNumSamples, NULL)); 59 } 60 61 TEST(DtmfToneGenerator, TestTones) { 62 DtmfToneGenerator tone_gen; 63 const int kAttenuation = 0; 64 const int kNumSamples = 10; 65 AudioMultiVector signal(1); // One channel. 66 67 // Low and high frequencies for events 0 through 15. 68 const double low_freq_hz[] = { 941.0, 697.0, 697.0, 697.0, 770.0, 770.0, 69 770.0, 852.0, 852.0, 852.0, 941.0, 941.0, 697.0, 770.0, 852.0, 941.0 }; 70 const double hi_freq_hz[] = { 1336.0, 1209.0, 1336.0, 1477.0, 1209.0, 1336.0, 71 1477.0, 1209.0, 1336.0, 1477.0, 1209.0, 1477.0, 1633.0, 1633.0, 1633.0, 72 1633.0 }; 73 const double attenuate_3dB = 23171.0 / 32768; // 3 dB attenuation. 74 const double base_attenuation = 16141.0 / 16384.0; // This is the attenuation 75 // applied to all cases. 76 const int fs_vec[] = { 8000, 16000, 32000, 48000 }; 77 for (int f = 0; f < 4; ++f) { 78 int fs = fs_vec[f]; 79 for (int event = 0; event <= 15; ++event) { 80 std::ostringstream ss; 81 ss << "Checking event " << event << " at sample rate " << fs; 82 SCOPED_TRACE(ss.str()); 83 ASSERT_EQ(0, tone_gen.Init(fs, event, kAttenuation)); 84 EXPECT_TRUE(tone_gen.initialized()); 85 EXPECT_EQ(kNumSamples, tone_gen.Generate(kNumSamples, &signal)); 86 87 double f1 = low_freq_hz[event]; 88 double f2 = hi_freq_hz[event]; 89 const double pi = 3.14159265358979323846; 90 91 for (int n = 0; n < kNumSamples; ++n) { 92 double x = attenuate_3dB * sin(2.0 * pi * f1 / fs * (-n - 1)) 93 + sin(2.0 * pi * f2 / fs * (-n - 1)); 94 x *= base_attenuation; 95 x = ldexp(x, 14); // Scale to Q14. 96 static const int kChannel = 0; 97 EXPECT_NEAR(x, static_cast<double>(signal[kChannel][n]), 25); 98 } 99 100 tone_gen.Reset(); 101 EXPECT_FALSE(tone_gen.initialized()); 102 } 103 } 104 } 105 106 TEST(DtmfToneGenerator, TestAmplitudes) { 107 DtmfToneGenerator tone_gen; 108 const int kNumSamples = 10; 109 AudioMultiVector signal(1); // One channel. 110 AudioMultiVector ref_signal(1); // One channel. 111 112 const int fs_vec[] = { 8000, 16000, 32000, 48000 }; 113 const int event_vec[] = { 0, 4, 9, 13 }; // Test a few events. 114 for (int f = 0; f < 4; ++f) { 115 int fs = fs_vec[f]; 116 int event = event_vec[f]; 117 // Create full-scale reference. 118 ASSERT_EQ(0, tone_gen.Init(fs, event, 0)); // 0 attenuation. 119 EXPECT_EQ(kNumSamples, tone_gen.Generate(kNumSamples, &ref_signal)); 120 // Test every 5 steps (to save time). 121 for (int attenuation = 1; attenuation <= 36; attenuation += 5) { 122 std::ostringstream ss; 123 ss << "Checking event " << event << " at sample rate " << fs; 124 ss << "; attenuation " << attenuation; 125 SCOPED_TRACE(ss.str()); 126 ASSERT_EQ(0, tone_gen.Init(fs, event, attenuation)); 127 EXPECT_EQ(kNumSamples, tone_gen.Generate(kNumSamples, &signal)); 128 for (int n = 0; n < kNumSamples; ++n) { 129 double attenuation_factor = 130 pow(10, -static_cast<double>(attenuation)/20); 131 // Verify that the attenuation is correct. 132 static const int kChannel = 0; 133 EXPECT_NEAR(attenuation_factor * ref_signal[kChannel][n], 134 signal[kChannel][n], 2); 135 } 136 137 tone_gen.Reset(); 138 } 139 } 140 } 141 142 } // namespace webrtc 143