/*
 *  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 "webrtc/modules/audio_coding/neteq/comfort_noise.h"

#include <assert.h>

#include "webrtc/base/logging.h"
#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
#include "webrtc/modules/audio_coding/codecs/cng/webrtc_cng.h"
#include "webrtc/modules/audio_coding/neteq/decoder_database.h"
#include "webrtc/modules/audio_coding/neteq/dsp_helper.h"
#include "webrtc/modules/audio_coding/neteq/sync_buffer.h"

namespace webrtc {

void ComfortNoise::Reset() {
  first_call_ = true;
  internal_error_code_ = 0;
}

int ComfortNoise::UpdateParameters(Packet* packet) {
  assert(packet);  // Existence is verified by caller.
  // Get comfort noise decoder.
  AudioDecoder* cng_decoder = decoder_database_->GetDecoder(
      packet->header.payloadType);
  if (!cng_decoder) {
    delete [] packet->payload;
    delete packet;
    return kUnknownPayloadType;
  }
  decoder_database_->SetActiveCngDecoder(packet->header.payloadType);
  CNG_dec_inst* cng_inst = cng_decoder->CngDecoderInstance();
  int16_t ret = WebRtcCng_UpdateSid(cng_inst,
                                    packet->payload,
                                    packet->payload_length);
  delete [] packet->payload;
  delete packet;
  if (ret < 0) {
    internal_error_code_ = WebRtcCng_GetErrorCodeDec(cng_inst);
    LOG(LS_ERROR) << "WebRtcCng_UpdateSid produced " << internal_error_code_;
    return kInternalError;
  }
  return kOK;
}

int ComfortNoise::Generate(size_t requested_length,
                           AudioMultiVector* output) {
  // TODO(hlundin): Change to an enumerator and skip assert.
  assert(fs_hz_ == 8000 || fs_hz_ == 16000 || fs_hz_ ==  32000 ||
         fs_hz_ == 48000);
  // Not adapted for multi-channel yet.
  if (output->Channels() != 1) {
    LOG(LS_ERROR) << "No multi-channel support";
    return kMultiChannelNotSupported;
  }

  size_t number_of_samples = requested_length;
  int16_t new_period = 0;
  if (first_call_) {
    // Generate noise and overlap slightly with old data.
    number_of_samples = requested_length + overlap_length_;
    new_period = 1;
  }
  output->AssertSize(number_of_samples);
  // Get the decoder from the database.
  AudioDecoder* cng_decoder = decoder_database_->GetActiveCngDecoder();
  if (!cng_decoder) {
    LOG(LS_ERROR) << "Unknwown payload type";
    return kUnknownPayloadType;
  }
  CNG_dec_inst* cng_inst = cng_decoder->CngDecoderInstance();
  // The expression &(*output)[0][0] is a pointer to the first element in
  // the first channel.
  if (WebRtcCng_Generate(cng_inst, &(*output)[0][0], number_of_samples,
                         new_period) < 0) {
    // Error returned.
    output->Zeros(requested_length);
    internal_error_code_ = WebRtcCng_GetErrorCodeDec(cng_inst);
    LOG(LS_ERROR) << "WebRtcCng_Generate produced " << internal_error_code_;
    return kInternalError;
  }

  if (first_call_) {
    // Set tapering window parameters. Values are in Q15.
    int16_t muting_window;  // Mixing factor for overlap data.
    int16_t muting_window_increment;  // Mixing factor increment (negative).
    int16_t unmuting_window;  // Mixing factor for comfort noise.
    int16_t unmuting_window_increment;  // Mixing factor increment.
    if (fs_hz_ == 8000) {
      muting_window = DspHelper::kMuteFactorStart8kHz;
      muting_window_increment = DspHelper::kMuteFactorIncrement8kHz;
      unmuting_window = DspHelper::kUnmuteFactorStart8kHz;
      unmuting_window_increment = DspHelper::kUnmuteFactorIncrement8kHz;
    } else if (fs_hz_ == 16000) {
      muting_window = DspHelper::kMuteFactorStart16kHz;
      muting_window_increment = DspHelper::kMuteFactorIncrement16kHz;
      unmuting_window = DspHelper::kUnmuteFactorStart16kHz;
      unmuting_window_increment = DspHelper::kUnmuteFactorIncrement16kHz;
    } else if (fs_hz_ == 32000) {
      muting_window = DspHelper::kMuteFactorStart32kHz;
      muting_window_increment = DspHelper::kMuteFactorIncrement32kHz;
      unmuting_window = DspHelper::kUnmuteFactorStart32kHz;
      unmuting_window_increment = DspHelper::kUnmuteFactorIncrement32kHz;
    } else {  // fs_hz_ == 48000
      muting_window = DspHelper::kMuteFactorStart48kHz;
      muting_window_increment = DspHelper::kMuteFactorIncrement48kHz;
      unmuting_window = DspHelper::kUnmuteFactorStart48kHz;
      unmuting_window_increment = DspHelper::kUnmuteFactorIncrement48kHz;
    }

    // Do overlap-add between new vector and overlap.
    size_t start_ix = sync_buffer_->Size() - overlap_length_;
    for (size_t i = 0; i < overlap_length_; i++) {
      /* overlapVec[i] = WinMute * overlapVec[i] + WinUnMute * outData[i] */
      // The expression (*output)[0][i] is the i-th element in the first
      // channel.
      (*sync_buffer_)[0][start_ix + i] =
          (((*sync_buffer_)[0][start_ix + i] * muting_window) +
              ((*output)[0][i] * unmuting_window) + 16384) >> 15;
      muting_window += muting_window_increment;
      unmuting_window += unmuting_window_increment;
    }
    // Remove |overlap_length_| samples from the front of |output| since they
    // were mixed into |sync_buffer_| above.
    output->PopFront(overlap_length_);
  }
  first_call_ = false;
  return kOK;
}

}  // namespace webrtc
