/*
 *  Copyright (c) 2015 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.
 */

// MSVC++ requires this to be set before any other includes to get M_PI.
#define _USE_MATH_DEFINES

#include "webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.h"

#include <math.h>

#include "webrtc/test/gtest.h"
#include "webrtc/base/array_view.h"
#include "webrtc/modules/audio_processing/audio_buffer.h"
#include "webrtc/modules/audio_processing/test/audio_buffer_tools.h"
#include "webrtc/modules/audio_processing/test/bitexactness_tools.h"

namespace webrtc {
namespace {

const int kChunkSizeMs = 10;
const int kSampleRateHz = 16000;

SphericalPointf AzimuthToSphericalPoint(float azimuth_radians) {
  return SphericalPointf(azimuth_radians, 0.f, 1.f);
}

void Verify(NonlinearBeamformer* bf, float target_azimuth_radians) {
  EXPECT_TRUE(bf->IsInBeam(AzimuthToSphericalPoint(target_azimuth_radians)));
  EXPECT_TRUE(bf->IsInBeam(AzimuthToSphericalPoint(
      target_azimuth_radians - NonlinearBeamformer::kHalfBeamWidthRadians +
      0.001f)));
  EXPECT_TRUE(bf->IsInBeam(AzimuthToSphericalPoint(
      target_azimuth_radians + NonlinearBeamformer::kHalfBeamWidthRadians -
      0.001f)));
  EXPECT_FALSE(bf->IsInBeam(AzimuthToSphericalPoint(
      target_azimuth_radians - NonlinearBeamformer::kHalfBeamWidthRadians -
      0.001f)));
  EXPECT_FALSE(bf->IsInBeam(AzimuthToSphericalPoint(
      target_azimuth_radians + NonlinearBeamformer::kHalfBeamWidthRadians +
      0.001f)));
}

void AimAndVerify(NonlinearBeamformer* bf, float target_azimuth_radians) {
  bf->AimAt(AzimuthToSphericalPoint(target_azimuth_radians));
  Verify(bf, target_azimuth_radians);
}

// Bitexactness test code.
const size_t kNumFramesToProcess = 1000;

void ProcessOneFrame(int sample_rate_hz,
                     AudioBuffer* capture_audio_buffer,
                     NonlinearBeamformer* beamformer) {
  if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) {
    capture_audio_buffer->SplitIntoFrequencyBands();
  }

  beamformer->AnalyzeChunk(*capture_audio_buffer->split_data_f());
  capture_audio_buffer->set_num_channels(1);
  beamformer->PostFilter(capture_audio_buffer->split_data_f());

  if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) {
    capture_audio_buffer->MergeFrequencyBands();
  }
}

int BeamformerSampleRate(int sample_rate_hz) {
  return (sample_rate_hz > AudioProcessing::kSampleRate16kHz
              ? AudioProcessing::kSampleRate16kHz
              : sample_rate_hz);
}

void RunBitExactnessTest(int sample_rate_hz,
                         const std::vector<Point>& array_geometry,
                         const SphericalPointf& target_direction,
                         rtc::ArrayView<const float> output_reference) {
  NonlinearBeamformer beamformer(array_geometry, 1u, target_direction);
  beamformer.Initialize(AudioProcessing::kChunkSizeMs,
                        BeamformerSampleRate(sample_rate_hz));

  const StreamConfig capture_config(sample_rate_hz, array_geometry.size(),
                                    false);
  AudioBuffer capture_buffer(
      capture_config.num_frames(), capture_config.num_channels(),
      capture_config.num_frames(), capture_config.num_channels(),
      capture_config.num_frames());
  test::InputAudioFile capture_file(
      test::GetApmCaptureTestVectorFileName(sample_rate_hz));
  std::vector<float> capture_input(capture_config.num_frames() *
                                   capture_config.num_channels());
  for (size_t frame_no = 0u; frame_no < kNumFramesToProcess; ++frame_no) {
    ReadFloatSamplesFromStereoFile(capture_config.num_frames(),
                                   capture_config.num_channels(), &capture_file,
                                   capture_input);

    test::CopyVectorToAudioBuffer(capture_config, capture_input,
                                  &capture_buffer);

    ProcessOneFrame(sample_rate_hz, &capture_buffer, &beamformer);
  }

  // Extract and verify the test results.
  std::vector<float> capture_output;
  test::ExtractVectorFromAudioBuffer(capture_config, &capture_buffer,
                                     &capture_output);

  const float kElementErrorBound = 1.f / static_cast<float>(1 << 15);

  // Compare the output with the reference. Only the first values of the output
  // from last frame processed are compared in order not having to specify all
  // preceeding frames as testvectors. As the algorithm being tested has a
  // memory, testing only the last frame implicitly also tests the preceeding
  // frames.
  EXPECT_TRUE(test::VerifyDeinterleavedArray(
      capture_config.num_frames(), capture_config.num_channels(),
      output_reference, capture_output, kElementErrorBound));
}

// TODO(peah): Add bitexactness tests for scenarios with more than 2 input
// channels.
std::vector<Point> CreateArrayGeometry(int variant) {
  std::vector<Point> array_geometry;
  switch (variant) {
    case 1:
      array_geometry.push_back(Point(-0.025f, 0.f, 0.f));
      array_geometry.push_back(Point(0.025f, 0.f, 0.f));
      break;
    case 2:
      array_geometry.push_back(Point(-0.035f, 0.f, 0.f));
      array_geometry.push_back(Point(0.035f, 0.f, 0.f));
      break;
    case 3:
      array_geometry.push_back(Point(-0.5f, 0.f, 0.f));
      array_geometry.push_back(Point(0.5f, 0.f, 0.f));
      break;
    default:
      RTC_CHECK(false);
  }
  return array_geometry;
}

const SphericalPointf TargetDirection1(0.4f * static_cast<float>(M_PI) / 2.f,
                                       0.f,
                                       1.f);
const SphericalPointf TargetDirection2(static_cast<float>(M_PI) / 2.f,
                                       1.f,
                                       2.f);

}  // namespace

TEST(NonlinearBeamformerTest, AimingModifiesBeam) {
  std::vector<Point> array_geometry;
  array_geometry.push_back(Point(-0.025f, 0.f, 0.f));
  array_geometry.push_back(Point(0.025f, 0.f, 0.f));
  NonlinearBeamformer bf(array_geometry, 1u);
  bf.Initialize(kChunkSizeMs, kSampleRateHz);
  // The default constructor parameter sets the target angle to PI / 2.
  Verify(&bf, static_cast<float>(M_PI) / 2.f);
  AimAndVerify(&bf, static_cast<float>(M_PI) / 3.f);
  AimAndVerify(&bf, 3.f * static_cast<float>(M_PI) / 4.f);
  AimAndVerify(&bf, static_cast<float>(M_PI) / 6.f);
  AimAndVerify(&bf, static_cast<float>(M_PI));
}

TEST(NonlinearBeamformerTest, InterfAnglesTakeAmbiguityIntoAccount) {
  {
    // For linear arrays there is ambiguity.
    std::vector<Point> array_geometry;
    array_geometry.push_back(Point(-0.1f, 0.f, 0.f));
    array_geometry.push_back(Point(0.f, 0.f, 0.f));
    array_geometry.push_back(Point(0.2f, 0.f, 0.f));
    NonlinearBeamformer bf(array_geometry, 1u);
    bf.Initialize(kChunkSizeMs, kSampleRateHz);
    EXPECT_EQ(2u, bf.interf_angles_radians_.size());
    EXPECT_FLOAT_EQ(M_PI / 2.f - bf.away_radians_,
                    bf.interf_angles_radians_[0]);
    EXPECT_FLOAT_EQ(M_PI / 2.f + bf.away_radians_,
                    bf.interf_angles_radians_[1]);
    bf.AimAt(AzimuthToSphericalPoint(bf.away_radians_ / 2.f));
    EXPECT_EQ(2u, bf.interf_angles_radians_.size());
    EXPECT_FLOAT_EQ(M_PI - bf.away_radians_ / 2.f,
                    bf.interf_angles_radians_[0]);
    EXPECT_FLOAT_EQ(3.f * bf.away_radians_ / 2.f, bf.interf_angles_radians_[1]);
  }
  {
    // For planar arrays with normal in the xy-plane there is ambiguity.
    std::vector<Point> array_geometry;
    array_geometry.push_back(Point(-0.1f, 0.f, 0.f));
    array_geometry.push_back(Point(0.f, 0.f, 0.f));
    array_geometry.push_back(Point(0.2f, 0.f, 0.f));
    array_geometry.push_back(Point(0.1f, 0.f, 0.2f));
    array_geometry.push_back(Point(0.f, 0.f, -0.1f));
    NonlinearBeamformer bf(array_geometry, 1u);
    bf.Initialize(kChunkSizeMs, kSampleRateHz);
    EXPECT_EQ(2u, bf.interf_angles_radians_.size());
    EXPECT_FLOAT_EQ(M_PI / 2.f - bf.away_radians_,
                    bf.interf_angles_radians_[0]);
    EXPECT_FLOAT_EQ(M_PI / 2.f + bf.away_radians_,
                    bf.interf_angles_radians_[1]);
    bf.AimAt(AzimuthToSphericalPoint(bf.away_radians_ / 2.f));
    EXPECT_EQ(2u, bf.interf_angles_radians_.size());
    EXPECT_FLOAT_EQ(M_PI - bf.away_radians_ / 2.f,
                    bf.interf_angles_radians_[0]);
    EXPECT_FLOAT_EQ(3.f * bf.away_radians_ / 2.f, bf.interf_angles_radians_[1]);
  }
  {
    // For planar arrays with normal not in the xy-plane there is no ambiguity.
    std::vector<Point> array_geometry;
    array_geometry.push_back(Point(0.f, 0.f, 0.f));
    array_geometry.push_back(Point(0.2f, 0.f, 0.f));
    array_geometry.push_back(Point(0.f, 0.1f, -0.2f));
    NonlinearBeamformer bf(array_geometry, 1u);
    bf.Initialize(kChunkSizeMs, kSampleRateHz);
    EXPECT_EQ(2u, bf.interf_angles_radians_.size());
    EXPECT_FLOAT_EQ(M_PI / 2.f - bf.away_radians_,
                    bf.interf_angles_radians_[0]);
    EXPECT_FLOAT_EQ(M_PI / 2.f + bf.away_radians_,
                    bf.interf_angles_radians_[1]);
    bf.AimAt(AzimuthToSphericalPoint(bf.away_radians_ / 2.f));
    EXPECT_EQ(2u, bf.interf_angles_radians_.size());
    EXPECT_FLOAT_EQ(-bf.away_radians_ / 2.f, bf.interf_angles_radians_[0]);
    EXPECT_FLOAT_EQ(3.f * bf.away_radians_ / 2.f, bf.interf_angles_radians_[1]);
  }
  {
    // For arrays which are not linear or planar there is no ambiguity.
    std::vector<Point> array_geometry;
    array_geometry.push_back(Point(0.f, 0.f, 0.f));
    array_geometry.push_back(Point(0.1f, 0.f, 0.f));
    array_geometry.push_back(Point(0.f, 0.2f, 0.f));
    array_geometry.push_back(Point(0.f, 0.f, 0.3f));
    NonlinearBeamformer bf(array_geometry, 1u);
    bf.Initialize(kChunkSizeMs, kSampleRateHz);
    EXPECT_EQ(2u, bf.interf_angles_radians_.size());
    EXPECT_FLOAT_EQ(M_PI / 2.f - bf.away_radians_,
                    bf.interf_angles_radians_[0]);
    EXPECT_FLOAT_EQ(M_PI / 2.f + bf.away_radians_,
                    bf.interf_angles_radians_[1]);
    bf.AimAt(AzimuthToSphericalPoint(bf.away_radians_ / 2.f));
    EXPECT_EQ(2u, bf.interf_angles_radians_.size());
    EXPECT_FLOAT_EQ(-bf.away_radians_ / 2.f, bf.interf_angles_radians_[0]);
    EXPECT_FLOAT_EQ(3.f * bf.away_radians_ / 2.f, bf.interf_angles_radians_[1]);
  }
}

// TODO(peah): Investigate why the nonlinear_beamformer.cc causes a DCHECK in
// this setup.
TEST(BeamformerBitExactnessTest,
     DISABLED_Stereo8kHz_ArrayGeometry1_TargetDirection1) {
  const float kOutputReference[] = {0.001318f, -0.001091f, 0.000990f,
                                    0.001318f, -0.001091f, 0.000990f};

  RunBitExactnessTest(AudioProcessing::kSampleRate8kHz, CreateArrayGeometry(1),
                      TargetDirection1, kOutputReference);
}

TEST(BeamformerBitExactnessTest,
     Stereo16kHz_ArrayGeometry1_TargetDirection1) {
  const float kOutputReference[] = {-0.000077f, -0.000147f, -0.000138f,
                                    -0.000077f, -0.000147f, -0.000138f};

  RunBitExactnessTest(AudioProcessing::kSampleRate16kHz, CreateArrayGeometry(1),
                      TargetDirection1, kOutputReference);
}

TEST(BeamformerBitExactnessTest,
     Stereo32kHz_ArrayGeometry1_TargetDirection1) {
  const float kOutputReference[] = {-0.000061f, -0.000061f, -0.000061f,
                                    -0.000061f, -0.000061f, -0.000061f};

  RunBitExactnessTest(AudioProcessing::kSampleRate32kHz, CreateArrayGeometry(1),
                      TargetDirection1, kOutputReference);
}

TEST(BeamformerBitExactnessTest,
     Stereo48kHz_ArrayGeometry1_TargetDirection1) {
  const float kOutputReference[] = {0.000450f, 0.000436f, 0.000433f,
                                    0.000450f, 0.000436f, 0.000433f};

  RunBitExactnessTest(AudioProcessing::kSampleRate48kHz, CreateArrayGeometry(1),
                      TargetDirection1, kOutputReference);
}

// TODO(peah): Investigate why the nonlinear_beamformer.cc causes a DCHECK in
// this setup.
TEST(BeamformerBitExactnessTest,
     DISABLED_Stereo8kHz_ArrayGeometry1_TargetDirection2) {
  const float kOutputReference[] = {0.001144f,  -0.001026f, 0.001074f,
                                    -0.016205f, -0.007324f, -0.015656f};

  RunBitExactnessTest(AudioProcessing::kSampleRate8kHz, CreateArrayGeometry(1),
                      TargetDirection2, kOutputReference);
}

TEST(BeamformerBitExactnessTest,
     Stereo16kHz_ArrayGeometry1_TargetDirection2) {
  const float kOutputReference[] = {0.000221f, -0.000249f, 0.000140f,
                                    0.000221f, -0.000249f, 0.000140f};

  RunBitExactnessTest(AudioProcessing::kSampleRate16kHz, CreateArrayGeometry(1),
                      TargetDirection2, kOutputReference);
}

TEST(BeamformerBitExactnessTest,
     Stereo32kHz_ArrayGeometry1_TargetDirection2) {
  const float kOutputReference[] = {0.000763f, -0.000336f, 0.000549f,
                                    0.000763f, -0.000336f, 0.000549f};

  RunBitExactnessTest(AudioProcessing::kSampleRate32kHz, CreateArrayGeometry(1),
                      TargetDirection2, kOutputReference);
}

TEST(BeamformerBitExactnessTest,
     Stereo48kHz_ArrayGeometry1_TargetDirection2) {
  const float kOutputReference[] = {-0.000004f, -0.000494f, 0.000255f,
                                    -0.000004f, -0.000494f, 0.000255f};

  RunBitExactnessTest(AudioProcessing::kSampleRate48kHz, CreateArrayGeometry(1),
                      TargetDirection2, kOutputReference);
}

TEST(BeamformerBitExactnessTest,
     Stereo8kHz_ArrayGeometry2_TargetDirection2) {
  const float kOutputReference[] = {-0.000914f, 0.002170f, -0.002382f,
                                    -0.000914f, 0.002170f, -0.002382f};

  RunBitExactnessTest(AudioProcessing::kSampleRate8kHz, CreateArrayGeometry(2),
                      TargetDirection2, kOutputReference);
}

TEST(BeamformerBitExactnessTest,
     Stereo16kHz_ArrayGeometry2_TargetDirection2) {
  const float kOutputReference[] = {0.000179f, -0.000179f, 0.000081f,
                                    0.000179f, -0.000179f, 0.000081f};

  RunBitExactnessTest(AudioProcessing::kSampleRate16kHz, CreateArrayGeometry(2),
                      TargetDirection2, kOutputReference);
}

TEST(BeamformerBitExactnessTest,
     Stereo32kHz_ArrayGeometry2_TargetDirection2) {
  const float kOutputReference[] = {0.000549f, -0.000214f, 0.000366f,
                                    0.000549f, -0.000214f, 0.000366f};

  RunBitExactnessTest(AudioProcessing::kSampleRate32kHz, CreateArrayGeometry(2),
                      TargetDirection2, kOutputReference);
}

TEST(BeamformerBitExactnessTest,
     Stereo48kHz_ArrayGeometry2_TargetDirection2) {
  const float kOutputReference[] = {0.000019f, -0.000310f, 0.000182f,
                                    0.000019f, -0.000310f, 0.000182f};

  RunBitExactnessTest(AudioProcessing::kSampleRate48kHz, CreateArrayGeometry(2),
                      TargetDirection2, kOutputReference);
}

// TODO(peah): Investigate why the nonlinear_beamformer.cc causes a DCHECK in
// this setup.
TEST(BeamformerBitExactnessTest,
     DISABLED_Stereo16kHz_ArrayGeometry3_TargetDirection1) {
  const float kOutputReference[] = {-0.000161f, 0.000171f, -0.000096f,
                                    0.001007f,  0.000427f, 0.000977f};

  RunBitExactnessTest(AudioProcessing::kSampleRate16kHz, CreateArrayGeometry(3),
                      TargetDirection1, kOutputReference);
}

}  // namespace webrtc
