// 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 "media/base/audio_bus.h"

#include <stddef.h>
#include <stdint.h>

#include <limits>
#include <utility>

#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
#include "media/base/audio_parameters.h"
#include "media/base/audio_sample_types.h"
#include "media/base/limits.h"
#include "media/base/vector_math.h"

namespace media {

static bool IsAligned(void* ptr) {
  return (reinterpret_cast<uintptr_t>(ptr) &
          (AudioBus::kChannelAlignment - 1)) == 0U;
}

// In order to guarantee that the memory block for each channel starts at an
// aligned address when splitting a contiguous block of memory into one block
// per channel, we may have to make these blocks larger than otherwise needed.
// We do this by allocating space for potentially more frames than requested.
// This method returns the required size for the contiguous memory block
// in bytes and outputs the adjusted number of frames via |out_aligned_frames|.
static int CalculateMemorySizeInternal(int channels,
                                       int frames,
                                       int* out_aligned_frames) {
  // Since our internal sample format is float, we can guarantee the alignment
  // by making the number of frames an integer multiple of
  // AudioBus::kChannelAlignment / sizeof(float).
  int aligned_frames =
      ((frames * sizeof(float) + AudioBus::kChannelAlignment - 1) &
       ~(AudioBus::kChannelAlignment - 1)) / sizeof(float);

  if (out_aligned_frames)
    *out_aligned_frames = aligned_frames;

  return sizeof(float) * channels * aligned_frames;
}

static void ValidateConfig(int channels, int frames) {
  CHECK_GT(frames, 0);
  CHECK_GT(channels, 0);
  CHECK_LE(channels, static_cast<int>(limits::kMaxChannels));
}

void AudioBus::CheckOverflow(int start_frame, int frames, int total_frames) {
  CHECK_GE(start_frame, 0);
  CHECK_GE(frames, 0);
  CHECK_GT(total_frames, 0);
  int sum = start_frame + frames;
  CHECK_LE(sum, total_frames);
  CHECK_GE(sum, 0);
}

AudioBus::AudioBus(int channels, int frames)
    : frames_(frames),
      can_set_channel_data_(false) {
  ValidateConfig(channels, frames_);

  int aligned_frames = 0;
  int size = CalculateMemorySizeInternal(channels, frames, &aligned_frames);

  data_.reset(static_cast<float*>(base::AlignedAlloc(
      size, AudioBus::kChannelAlignment)));

  BuildChannelData(channels, aligned_frames, data_.get());
}

AudioBus::AudioBus(int channels, int frames, float* data)
    : frames_(frames),
      can_set_channel_data_(false) {
  // Since |data| may have come from an external source, ensure it's valid.
  CHECK(data);
  ValidateConfig(channels, frames_);

  int aligned_frames = 0;
  CalculateMemorySizeInternal(channels, frames, &aligned_frames);

  BuildChannelData(channels, aligned_frames, data);
}

AudioBus::AudioBus(int frames, const std::vector<float*>& channel_data)
    : channel_data_(channel_data),
      frames_(frames),
      can_set_channel_data_(false) {
  ValidateConfig(
      base::checked_cast<int>(channel_data_.size()), frames_);

  // Sanity check wrapped vector for alignment and channel count.
  for (size_t i = 0; i < channel_data_.size(); ++i)
    DCHECK(IsAligned(channel_data_[i]));
}

AudioBus::AudioBus(int channels)
    : channel_data_(channels),
      frames_(0),
      can_set_channel_data_(true) {
  CHECK_GT(channels, 0);
  for (size_t i = 0; i < channel_data_.size(); ++i)
    channel_data_[i] = NULL;
}

AudioBus::~AudioBus() = default;

std::unique_ptr<AudioBus> AudioBus::Create(int channels, int frames) {
  return base::WrapUnique(new AudioBus(channels, frames));
}

std::unique_ptr<AudioBus> AudioBus::Create(const AudioParameters& params) {
  return base::WrapUnique(
      new AudioBus(params.channels(), params.frames_per_buffer()));
}

std::unique_ptr<AudioBus> AudioBus::CreateWrapper(int channels) {
  return base::WrapUnique(new AudioBus(channels));
}

std::unique_ptr<AudioBus> AudioBus::WrapVector(
    int frames,
    const std::vector<float*>& channel_data) {
  return base::WrapUnique(new AudioBus(frames, channel_data));
}

std::unique_ptr<AudioBus> AudioBus::WrapMemory(int channels,
                                               int frames,
                                               void* data) {
  // |data| must be aligned by AudioBus::kChannelAlignment.
  CHECK(IsAligned(data));
  return base::WrapUnique(
      new AudioBus(channels, frames, static_cast<float*>(data)));
}

std::unique_ptr<AudioBus> AudioBus::WrapMemory(const AudioParameters& params,
                                               void* data) {
  // |data| must be aligned by AudioBus::kChannelAlignment.
  CHECK(IsAligned(data));
  return base::WrapUnique(new AudioBus(params.channels(),
                                       params.frames_per_buffer(),
                                       static_cast<float*>(data)));
}

std::unique_ptr<const AudioBus> AudioBus::WrapReadOnlyMemory(
    const AudioParameters& params,
    const void* data) {
  // Note: const_cast is generally dangerous but is used in this case since
  // AudioBus accomodates both read-only and read/write use cases. A const
  // AudioBus object is returned to ensure noone accidentally writes to the
  // read-only data.
  return WrapMemory(params, const_cast<void*>(data));
}

void AudioBus::SetChannelData(int channel, float* data) {
  CHECK(can_set_channel_data_);
  CHECK(data);
  CHECK_GE(channel, 0);
  CHECK_LT(static_cast<size_t>(channel), channel_data_.size());
  DCHECK(IsAligned(data));
  channel_data_[channel] = data;
}

void AudioBus::set_frames(int frames) {
  CHECK(can_set_channel_data_);
  ValidateConfig(static_cast<int>(channel_data_.size()), frames);
  frames_ = frames;
}

size_t AudioBus::GetBitstreamDataSize() const {
  DCHECK(is_bitstream_format_);
  return bitstream_data_size_;
}

void AudioBus::SetBitstreamDataSize(size_t data_size) {
  DCHECK(is_bitstream_format_);
  bitstream_data_size_ = data_size;
}

int AudioBus::GetBitstreamFrames() const {
  DCHECK(is_bitstream_format_);
  return bitstream_frames_;
}

void AudioBus::SetBitstreamFrames(int frames) {
  DCHECK(is_bitstream_format_);
  bitstream_frames_ = frames;
}

void AudioBus::ZeroFramesPartial(int start_frame, int frames) {
  CheckOverflow(start_frame, frames, frames_);

  if (frames <= 0)
    return;

  if (is_bitstream_format_) {
    // No need to clean unused region for bitstream formats.
    if (start_frame >= bitstream_frames_)
      return;

    // Cannot clean partial frames.
    DCHECK_EQ(start_frame, 0);
    DCHECK(frames >= bitstream_frames_);

    // For compressed bitstream, zeroed buffer is not valid and would be
    // discarded immediately. It is faster and makes more sense to reset
    // |bitstream_data_size_| and |is_bitstream_format_| so that the buffer
    // contains no data instead of zeroed data.
    SetBitstreamDataSize(0);
    SetBitstreamFrames(0);
    return;
  }

  for (size_t i = 0; i < channel_data_.size(); ++i) {
    memset(channel_data_[i] + start_frame, 0,
           frames * sizeof(*channel_data_[i]));
  }
}

void AudioBus::ZeroFrames(int frames) {
  ZeroFramesPartial(0, frames);
}

void AudioBus::Zero() {
  ZeroFrames(frames_);
}

bool AudioBus::AreFramesZero() const {
  DCHECK(!is_bitstream_format_);
  for (size_t i = 0; i < channel_data_.size(); ++i) {
    for (int j = 0; j < frames_; ++j) {
      if (channel_data_[i][j])
        return false;
    }
  }
  return true;
}

int AudioBus::CalculateMemorySize(const AudioParameters& params) {
  return CalculateMemorySizeInternal(
      params.channels(), params.frames_per_buffer(), NULL);
}

int AudioBus::CalculateMemorySize(int channels, int frames) {
  return CalculateMemorySizeInternal(channels, frames, NULL);
}

void AudioBus::BuildChannelData(int channels, int aligned_frames, float* data) {
  DCHECK(!is_bitstream_format_);
  DCHECK(IsAligned(data));
  DCHECK_EQ(channel_data_.size(), 0U);
  // Initialize |channel_data_| with pointers into |data|.
  channel_data_.reserve(channels);
  for (int i = 0; i < channels; ++i)
    channel_data_.push_back(data + i * aligned_frames);
}

// Forwards to non-deprecated version.
void AudioBus::FromInterleaved(const void* source,
                               int frames,
                               int bytes_per_sample) {
  DCHECK(!is_bitstream_format_);
  switch (bytes_per_sample) {
    case 1:
      FromInterleaved<UnsignedInt8SampleTypeTraits>(
          reinterpret_cast<const uint8_t*>(source), frames);
      break;
    case 2:
      FromInterleaved<SignedInt16SampleTypeTraits>(
          reinterpret_cast<const int16_t*>(source), frames);
      break;
    case 4:
      FromInterleaved<SignedInt32SampleTypeTraits>(
          reinterpret_cast<const int32_t*>(source), frames);
      break;
    default:
      NOTREACHED() << "Unsupported bytes per sample encountered: "
                   << bytes_per_sample;
      ZeroFrames(frames);
  }
}

// Forwards to non-deprecated version.
void AudioBus::FromInterleavedPartial(const void* source,
                                      int start_frame,
                                      int frames,
                                      int bytes_per_sample) {
  DCHECK(!is_bitstream_format_);
  switch (bytes_per_sample) {
    case 1:
      FromInterleavedPartial<UnsignedInt8SampleTypeTraits>(
          reinterpret_cast<const uint8_t*>(source), start_frame, frames);
      break;
    case 2:
      FromInterleavedPartial<SignedInt16SampleTypeTraits>(
          reinterpret_cast<const int16_t*>(source), start_frame, frames);
      break;
    case 4:
      FromInterleavedPartial<SignedInt32SampleTypeTraits>(
          reinterpret_cast<const int32_t*>(source), start_frame, frames);
      break;
    default:
      NOTREACHED() << "Unsupported bytes per sample encountered: "
                   << bytes_per_sample;
      ZeroFramesPartial(start_frame, frames);
  }
}

// Forwards to non-deprecated version.
void AudioBus::ToInterleaved(int frames,
                             int bytes_per_sample,
                             void* dest) const {
  DCHECK(!is_bitstream_format_);
  switch (bytes_per_sample) {
    case 1:
      ToInterleaved<UnsignedInt8SampleTypeTraits>(
          frames, reinterpret_cast<uint8_t*>(dest));
      break;
    case 2:
      ToInterleaved<SignedInt16SampleTypeTraits>(
          frames, reinterpret_cast<int16_t*>(dest));
      break;
    case 4:
      ToInterleaved<SignedInt32SampleTypeTraits>(
          frames, reinterpret_cast<int32_t*>(dest));
      break;
    default:
      NOTREACHED() << "Unsupported bytes per sample encountered: "
                   << bytes_per_sample;
  }
}

// Forwards to non-deprecated version.
void AudioBus::ToInterleavedPartial(int start_frame,
                                    int frames,
                                    int bytes_per_sample,
                                    void* dest) const {
  DCHECK(!is_bitstream_format_);
  switch (bytes_per_sample) {
    case 1:
      ToInterleavedPartial<UnsignedInt8SampleTypeTraits>(
          start_frame, frames, reinterpret_cast<uint8_t*>(dest));
      break;
    case 2:
      ToInterleavedPartial<SignedInt16SampleTypeTraits>(
          start_frame, frames, reinterpret_cast<int16_t*>(dest));
      break;
    case 4:
      ToInterleavedPartial<SignedInt32SampleTypeTraits>(
          start_frame, frames, reinterpret_cast<int32_t*>(dest));
      break;
    default:
      NOTREACHED() << "Unsupported bytes per sample encountered: "
                   << bytes_per_sample;
  }
}

void AudioBus::CopyTo(AudioBus* dest) const {
  dest->set_is_bitstream_format(is_bitstream_format());
  if (is_bitstream_format()) {
    dest->SetBitstreamDataSize(GetBitstreamDataSize());
    dest->SetBitstreamFrames(GetBitstreamFrames());
    memcpy(dest->channel(0), channel(0), GetBitstreamDataSize());
    return;
  }

  CopyPartialFramesTo(0, frames(), 0, dest);
}

void AudioBus::CopyPartialFramesTo(int source_start_frame,
                                   int frame_count,
                                   int dest_start_frame,
                                   AudioBus* dest) const {
  DCHECK(!is_bitstream_format_);
  CHECK_EQ(channels(), dest->channels());
  CHECK_LE(source_start_frame + frame_count, frames());
  CHECK_LE(dest_start_frame + frame_count, dest->frames());

  // Since we don't know if the other AudioBus is wrapped or not (and we don't
  // want to care), just copy using the public channel() accessors.
  for (int i = 0; i < channels(); ++i) {
    memcpy(dest->channel(i) + dest_start_frame,
           channel(i) + source_start_frame,
           sizeof(*channel(i)) * frame_count);
  }
}

void AudioBus::Scale(float volume) {
  DCHECK(!is_bitstream_format_);
  if (volume > 0 && volume != 1) {
    for (int i = 0; i < channels(); ++i)
      vector_math::FMUL(channel(i), volume, frames(), channel(i));
  } else if (volume == 0) {
    Zero();
  }
}

void AudioBus::SwapChannels(int a, int b) {
  DCHECK(!is_bitstream_format_);
  DCHECK(a < channels() && a >= 0);
  DCHECK(b < channels() && b >= 0);
  DCHECK_NE(a, b);
  std::swap(channel_data_[a], channel_data_[b]);
}

}  // namespace media
