Home | History | Annotate | Download | only in neteq
      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 
     20 namespace webrtc {
     21 
     22 class 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.
    100 const 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};
    103 const 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 
    107 TEST_F(DtmfToneGeneratorTest, Test8000Mono) {
    108   TestAllTones(8000, 1);
    109   TestAmplitudes(8000, 1);
    110 }
    111 
    112 TEST_F(DtmfToneGeneratorTest, Test16000Mono) {
    113   TestAllTones(16000, 1);
    114   TestAmplitudes(16000, 1);
    115 }
    116 
    117 TEST_F(DtmfToneGeneratorTest, Test32000Mono) {
    118   TestAllTones(32000, 1);
    119   TestAmplitudes(32000, 1);
    120 }
    121 
    122 TEST_F(DtmfToneGeneratorTest, Test48000Mono) {
    123   TestAllTones(48000, 1);
    124   TestAmplitudes(48000, 1);
    125 }
    126 
    127 TEST_F(DtmfToneGeneratorTest, Test8000Stereo) {
    128   TestAllTones(8000, 2);
    129   TestAmplitudes(8000, 2);
    130 }
    131 
    132 TEST_F(DtmfToneGeneratorTest, Test16000Stereo) {
    133   TestAllTones(16000, 2);
    134   TestAmplitudes(16000, 2);
    135 }
    136 
    137 TEST_F(DtmfToneGeneratorTest, Test32000Stereo) {
    138   TestAllTones(32000, 2);
    139   TestAmplitudes(32000, 2);
    140 }
    141 
    142 TEST_F(DtmfToneGeneratorTest, Test48000Stereo) {
    143   TestAllTones(48000, 2);
    144   TestAmplitudes(48000, 2);
    145 }
    146 
    147 TEST(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   // NULL pointer to destination.
    175   EXPECT_EQ(DtmfToneGenerator::kParameterError,
    176             tone_gen.Generate(kNumSamples, NULL));
    177 }
    178 
    179 }  // namespace webrtc
    180