/*
 *  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.
 */

#include <stdio.h>
#include <string.h>

#include <math.h>

#include "webrtc/common_types.h"
#include "webrtc/modules/audio_coding/main/test/SpatialAudio.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/system_wrappers/interface/trace.h"
#include "webrtc/test/testsupport/fileutils.h"

namespace webrtc {

#define NUM_PANN_COEFFS 10

SpatialAudio::SpatialAudio(int testMode)
    : _acmLeft(AudioCodingModule::Create(1)),
      _acmRight(AudioCodingModule::Create(2)),
      _acmReceiver(AudioCodingModule::Create(3)),
      _testMode(testMode) {
}

SpatialAudio::~SpatialAudio() {
  delete _channel;
  _inFile.Close();
  _outFile.Close();
}

int16_t SpatialAudio::Setup() {
  _channel = new Channel;

  // Register callback for the sender side.
  CHECK_ERROR(_acmLeft->RegisterTransportCallback(_channel));
  CHECK_ERROR(_acmRight->RegisterTransportCallback(_channel));
  // Register the receiver ACM in channel
  _channel->RegisterReceiverACM(_acmReceiver.get());

  uint16_t sampFreqHz = 32000;

  const std::string file_name = webrtc::test::ResourcePath(
      "audio_coding/testfile32kHz", "pcm");
  _inFile.Open(file_name, sampFreqHz, "rb", false);

  std::string output_file = webrtc::test::OutputPath()
      + "out_spatial_autotest.pcm";
  if (_testMode == 1) {
    output_file = webrtc::test::OutputPath() + "testspatial_out.pcm";
    printf("\n");
    printf("Enter the output file [%s]: ", output_file.c_str());
    PCMFile::ChooseFile(&output_file, MAX_FILE_NAME_LENGTH_BYTE, &sampFreqHz);
  } else {
    output_file = webrtc::test::OutputPath() + "testspatial_out.pcm";
  }
  _outFile.Open(output_file, sampFreqHz, "wb", false);
  _outFile.SaveStereo(true);

  // Register all available codes as receiving codecs.
  CodecInst codecInst;
  int status;
  uint8_t num_encoders = _acmReceiver->NumberOfCodecs();
  // Register all available codes as receiving codecs once more.
  for (uint8_t n = 0; n < num_encoders; n++) {
    status = _acmReceiver->Codec(n, &codecInst);
    if (status < 0) {
      printf("Error in Codec(), no matching codec found");
    }
    status = _acmReceiver->RegisterReceiveCodec(codecInst);
    if (status < 0) {
      printf("Error in RegisterReceiveCodec() for payload type %d",
             codecInst.pltype);
    }
  }

  return 0;
}

void SpatialAudio::Perform() {
  if (_testMode == 0) {
    printf("Running SpatialAudio Test");
    WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceAudioCoding, -1,
                 "---------- SpatialAudio ----------");
  }

  Setup();

  CodecInst codecInst;
  _acmLeft->Codec((uint8_t) 1, &codecInst);
  CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst));
  EncodeDecode();

  int16_t pannCntr = 0;

  double leftPanning[NUM_PANN_COEFFS] = { 1.00, 0.95, 0.90, 0.85, 0.80, 0.75,
      0.70, 0.60, 0.55, 0.50 };
  double rightPanning[NUM_PANN_COEFFS] = { 0.50, 0.55, 0.60, 0.70, 0.75, 0.80,
      0.85, 0.90, 0.95, 1.00 };

  while ((pannCntr + 1) < NUM_PANN_COEFFS) {
    _acmLeft->Codec((uint8_t) 0, &codecInst);
    codecInst.pacsize = 480;
    CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst));
    CHECK_ERROR(_acmRight->RegisterSendCodec(codecInst));

    EncodeDecode(leftPanning[pannCntr], rightPanning[pannCntr]);
    pannCntr++;

    // Change codec
    _acmLeft->Codec((uint8_t) 3, &codecInst);
    codecInst.pacsize = 320;
    CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst));
    CHECK_ERROR(_acmRight->RegisterSendCodec(codecInst));

    EncodeDecode(leftPanning[pannCntr], rightPanning[pannCntr]);
    pannCntr++;
    if (_testMode == 0) {
      printf(".");
    }
  }

  _acmLeft->Codec((uint8_t) 4, &codecInst);
  CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst));
  EncodeDecode();

  _acmLeft->Codec((uint8_t) 0, &codecInst);
  codecInst.pacsize = 480;
  CHECK_ERROR(_acmLeft->RegisterSendCodec(codecInst));
  CHECK_ERROR(_acmRight->RegisterSendCodec(codecInst));
  pannCntr = NUM_PANN_COEFFS - 1;
  while (pannCntr >= 0) {
    EncodeDecode(leftPanning[pannCntr], rightPanning[pannCntr]);
    pannCntr--;
    if (_testMode == 0) {
      printf(".");
    }
  }
  if (_testMode == 0) {
    printf("Done!\n");
  }
}

void SpatialAudio::EncodeDecode(const double leftPanning,
                                const double rightPanning) {
  AudioFrame audioFrame;
  int32_t outFileSampFreq = _outFile.SamplingFrequency();

  const double rightToLeftRatio = rightPanning / leftPanning;

  _channel->SetIsStereo(true);

  while (!_inFile.EndOfFile()) {
    _inFile.Read10MsData(audioFrame);
    for (int n = 0; n < audioFrame.samples_per_channel_; n++) {
      audioFrame.data_[n] = (int16_t) floor(
          audioFrame.data_[n] * leftPanning + 0.5);
    }
    CHECK_ERROR(_acmLeft->Add10MsData(audioFrame));

    for (int n = 0; n < audioFrame.samples_per_channel_; n++) {
      audioFrame.data_[n] = (int16_t) floor(
          audioFrame.data_[n] * rightToLeftRatio + 0.5);
    }
    CHECK_ERROR(_acmRight->Add10MsData(audioFrame));

    CHECK_ERROR(_acmReceiver->PlayoutData10Ms(outFileSampFreq, &audioFrame));
    _outFile.Write10MsData(audioFrame);
  }
  _inFile.Rewind();
}

void SpatialAudio::EncodeDecode() {
  AudioFrame audioFrame;
  int32_t outFileSampFreq = _outFile.SamplingFrequency();

  _channel->SetIsStereo(false);

  while (!_inFile.EndOfFile()) {
    _inFile.Read10MsData(audioFrame);
    CHECK_ERROR(_acmLeft->Add10MsData(audioFrame));

    CHECK_ERROR(_acmReceiver->PlayoutData10Ms(outFileSampFreq, &audioFrame));
    _outFile.Write10MsData(audioFrame);
  }
  _inFile.Rewind();
}

}  // namespace webrtc
