// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cobalt/media/base/audio_fifo.h"

#include "base/logging.h"

namespace media {

// Given current position in the FIFO, the maximum number of elements in the
// FIFO and the size of the input; this method provides two output results:
// |size| and |wrap_size|. These two results can then be utilized for memcopy
// operations to and from the FIFO.
// Under "normal" circumstances, |size| will be equal to |in_size| and
// |wrap_size| will be zero. This case corresponding to the non-wrapping case
// where we have not yet reached the "edge" of the FIFO. If |pos| + |in_size|
// exceeds the total size of the FIFO, we must wrap around and start reusing
// a part the allocated memory. The size of this part is given by |wrap_size|.
static void GetSizes(int pos, int max_size, int in_size, int* size,
                     int* wrap_size) {
  if (pos + in_size > max_size) {
    // Wrapping is required => derive size of each segment.
    *size = max_size - pos;
    *wrap_size = in_size - *size;
  } else {
    // Wrapping is not required.
    *size = in_size;
    *wrap_size = 0;
  }
}

// Updates the read/write position with |step| modulo the maximum number of
// elements in the FIFO to ensure that the position counters wraps around at
// the endpoint.
static int UpdatePos(int pos, int step, int max_size) {
  return ((pos + step) % max_size);
}

AudioFifo::AudioFifo(int channels, int frames)
    : audio_bus_(AudioBus::Create(channels, frames)),
      max_frames_(frames),
      frames_pushed_(0),
      frames_consumed_(0),
      read_pos_(0),
      write_pos_(0) {}

AudioFifo::~AudioFifo() {}

int AudioFifo::frames() const {
  int delta = frames_pushed_ - frames_consumed_;
  return delta;
}

void AudioFifo::Push(const AudioBus* source) {
  DCHECK(source);
  DCHECK_EQ(source->channels(), audio_bus_->channels());

  // Ensure that there is space for the new data in the FIFO.
  const int source_size = source->frames();
  CHECK_LE(source_size + frames(), max_frames_);

  // Figure out if wrapping is needed and if so what segment sizes we need
  // when adding the new audio bus content to the FIFO.
  int append_size = 0;
  int wrap_size = 0;
  GetSizes(write_pos_, max_frames(), source_size, &append_size, &wrap_size);

  // Copy all channels from the source to the FIFO. Wrap around if needed.
  for (int ch = 0; ch < source->channels(); ++ch) {
    float* dest = audio_bus_->channel(ch);
    const float* src = source->channel(ch);

    // Append part of (or the complete) source to the FIFO.
    memcpy(&dest[write_pos_], &src[0], append_size * sizeof(src[0]));
    if (wrap_size > 0) {
      // Wrapping is needed: copy remaining part from the source to the FIFO.
      memcpy(&dest[0], &src[append_size], wrap_size * sizeof(src[0]));
    }
  }

  frames_pushed_ += source_size;
  DCHECK_LE(frames(), max_frames());
  write_pos_ = UpdatePos(write_pos_, source_size, max_frames());
}

void AudioFifo::Consume(AudioBus* destination, int start_frame,
                        int frames_to_consume) {
  DCHECK(destination);
  DCHECK_EQ(destination->channels(), audio_bus_->channels());

  // It is not possible to ask for more data than what is available in the FIFO.
  CHECK_LE(frames_to_consume, frames());

  // A copy from the FIFO to |destination| will only be performed if the
  // allocated memory in |destination| is sufficient.
  CHECK_LE(frames_to_consume + start_frame, destination->frames());

  // Figure out if wrapping is needed and if so what segment sizes we need
  // when removing audio bus content from the FIFO.
  int consume_size = 0;
  int wrap_size = 0;
  GetSizes(read_pos_, max_frames(), frames_to_consume, &consume_size,
           &wrap_size);

  // For all channels, remove the requested amount of data from the FIFO
  // and copy the content to the destination. Wrap around if needed.
  for (int ch = 0; ch < destination->channels(); ++ch) {
    float* dest = destination->channel(ch);
    const float* src = audio_bus_->channel(ch);

    // Copy a selected part of the FIFO to the destination.
    memcpy(&dest[start_frame], &src[read_pos_], consume_size * sizeof(src[0]));
    if (wrap_size > 0) {
      // Wrapping is needed: copy remaining part to the destination.
      memcpy(&dest[consume_size + start_frame], &src[0],
             wrap_size * sizeof(src[0]));
    }
  }

  frames_consumed_ += frames_to_consume;
  read_pos_ = UpdatePos(read_pos_, frames_to_consume, max_frames());
}

void AudioFifo::Clear() {
  frames_pushed_ = 0;
  frames_consumed_ = 0;
  read_pos_ = 0;
  write_pos_ = 0;
}

}  // namespace media
