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 "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