blob: 393648c499f28840563cbbe0afe66ddd2ee9fdf4 [file] [log] [blame]
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +00001/*
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/neteq4/dtmf_tone_generator.h"
14
pbos@webrtc.org3f45c2e2013-08-05 16:22:53 +000015#include <math.h>
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +000016
17#include "gtest/gtest.h"
18#include "webrtc/modules/audio_coding/neteq4/audio_multi_vector.h"
19
20namespace webrtc {
21
22TEST(DtmfToneGenerator, CreateAndDestroy) {
23 DtmfToneGenerator* tone_gen = new DtmfToneGenerator();
24 delete tone_gen;
25}
26
27TEST(DtmfToneGenerator, TestErrors) {
28 DtmfToneGenerator tone_gen;
29 const int kNumSamples = 10;
30 AudioMultiVector<int16_t> 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
61TEST(DtmfToneGenerator, TestTones) {
62 DtmfToneGenerator tone_gen;
63 const int kAttenuation = 0;
64 const int kNumSamples = 10;
65 AudioMultiVector<int16_t> 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
106TEST(DtmfToneGenerator, TestAmplitudes) {
107 DtmfToneGenerator tone_gen;
108 const int kNumSamples = 10;
109 AudioMultiVector<int16_t> signal(1); // One channel.
110 AudioMultiVector<int16_t> 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