/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// Unit tests for DtmfToneGenerator class.

#include "webrtc/modules/audio_coding/neteq4/dtmf_tone_generator.h"

#include <math.h>

#include "gtest/gtest.h"
#include "webrtc/modules/audio_coding/neteq4/audio_multi_vector.h"

namespace webrtc {

TEST(DtmfToneGenerator, CreateAndDestroy) {
  DtmfToneGenerator* tone_gen = new DtmfToneGenerator();
  delete tone_gen;
}

TEST(DtmfToneGenerator, TestErrors) {
  DtmfToneGenerator tone_gen;
  const int kNumSamples = 10;
  AudioMultiVector signal(1);  // One channel.

  // Try to generate tones without initializing.
  EXPECT_EQ(DtmfToneGenerator::kNotInitialized,
            tone_gen.Generate(kNumSamples, &signal));

  const int fs = 16000;       // Valid sample rate.
  const int event = 7;        // Valid event.
  const int attenuation = 0;  // Valid attenuation.
  // Initialize with invalid event -1.
  EXPECT_EQ(DtmfToneGenerator::kParameterError,
            tone_gen.Init(fs, -1, attenuation));
  // Initialize with invalid event 16.
  EXPECT_EQ(DtmfToneGenerator::kParameterError,
            tone_gen.Init(fs, 16, attenuation));
  // Initialize with invalid attenuation -1.
  EXPECT_EQ(DtmfToneGenerator::kParameterError, tone_gen.Init(fs, event, -1));
  // Initialize with invalid attenuation 37.
  EXPECT_EQ(DtmfToneGenerator::kParameterError, tone_gen.Init(fs, event, 37));
  EXPECT_FALSE(tone_gen.initialized());  // Should still be uninitialized.

  // Initialize with valid parameters.
  ASSERT_EQ(0, tone_gen.Init(fs, event, attenuation));
  EXPECT_TRUE(tone_gen.initialized());
  // Negative number of samples.
  EXPECT_EQ(DtmfToneGenerator::kParameterError, tone_gen.Generate(-1, &signal));
  // NULL pointer to destination.
  EXPECT_EQ(DtmfToneGenerator::kParameterError,
            tone_gen.Generate(kNumSamples, NULL));
}

TEST(DtmfToneGenerator, TestTones) {
  DtmfToneGenerator tone_gen;
  const int kAttenuation = 0;
  const int kNumSamples = 10;
  AudioMultiVector signal(1);  // One channel.

  // Low and high frequencies for events 0 through 15.
  const double low_freq_hz[] = { 941.0, 697.0, 697.0, 697.0, 770.0, 770.0,
      770.0, 852.0, 852.0, 852.0, 941.0, 941.0, 697.0, 770.0, 852.0, 941.0 };
  const double hi_freq_hz[] = { 1336.0, 1209.0, 1336.0, 1477.0, 1209.0, 1336.0,
      1477.0, 1209.0, 1336.0, 1477.0, 1209.0, 1477.0, 1633.0, 1633.0, 1633.0,
      1633.0 };
  const double attenuate_3dB = 23171.0 / 32768;  // 3 dB attenuation.
  const double base_attenuation = 16141.0 / 16384.0;  // This is the attenuation
                                                      // applied to all cases.
  const int fs_vec[] = { 8000, 16000, 32000, 48000 };
  for (int f = 0; f < 4; ++f) {
    int fs = fs_vec[f];
    for (int event = 0; event <= 15; ++event) {
      std::ostringstream ss;
      ss << "Checking event " << event << " at sample rate " << fs;
      SCOPED_TRACE(ss.str());
      ASSERT_EQ(0, tone_gen.Init(fs, event, kAttenuation));
      EXPECT_TRUE(tone_gen.initialized());
      EXPECT_EQ(kNumSamples, tone_gen.Generate(kNumSamples, &signal));

      double f1 = low_freq_hz[event];
      double f2 = hi_freq_hz[event];
      const double pi = 3.14159265358979323846;

      for (int n = 0; n < kNumSamples; ++n) {
        double x = attenuate_3dB * sin(2.0 * pi * f1 / fs * (-n - 1))
            + sin(2.0 * pi * f2 / fs * (-n - 1));
        x *= base_attenuation;
        x = ldexp(x, 14);  // Scale to Q14.
        static const int kChannel = 0;
        EXPECT_NEAR(x, static_cast<double>(signal[kChannel][n]), 25);
      }

      tone_gen.Reset();
      EXPECT_FALSE(tone_gen.initialized());
    }
  }
}

TEST(DtmfToneGenerator, TestAmplitudes) {
  DtmfToneGenerator tone_gen;
  const int kNumSamples = 10;
  AudioMultiVector signal(1);  // One channel.
  AudioMultiVector ref_signal(1);  // One channel.

  const int fs_vec[] = { 8000, 16000, 32000, 48000 };
  const int event_vec[] = { 0, 4, 9, 13 };  // Test a few events.
  for (int f = 0; f < 4; ++f) {
    int fs = fs_vec[f];
    int event = event_vec[f];
    // Create full-scale reference.
    ASSERT_EQ(0, tone_gen.Init(fs, event, 0));  // 0 attenuation.
    EXPECT_EQ(kNumSamples, tone_gen.Generate(kNumSamples, &ref_signal));
    // Test every 5 steps (to save time).
    for (int attenuation = 1; attenuation <= 36; attenuation += 5) {
      std::ostringstream ss;
      ss << "Checking event " << event << " at sample rate " << fs;
      ss << "; attenuation " << attenuation;
      SCOPED_TRACE(ss.str());
      ASSERT_EQ(0, tone_gen.Init(fs, event, attenuation));
      EXPECT_EQ(kNumSamples, tone_gen.Generate(kNumSamples, &signal));
      for (int n = 0; n < kNumSamples; ++n) {
        double attenuation_factor =
            pow(10, -static_cast<double>(attenuation)/20);
        // Verify that the attenuation is correct.
        static const int kChannel = 0;
        EXPECT_NEAR(attenuation_factor * ref_signal[kChannel][n],
                    signal[kChannel][n], 2);
      }

      tone_gen.Reset();
    }
  }
}

}  // namespace webrtc
