/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "modules/webaudio/AudioBuffer.h"

#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
#include "modules/webaudio/AudioBufferOptions.h"
#include "modules/webaudio/BaseAudioContext.h"
#include "platform/audio/AudioBus.h"
#include "platform/audio/AudioFileReader.h"
#include "platform/audio/AudioUtilities.h"
#include "wtf/typed_arrays/Float32Array.h"

namespace blink {

AudioBuffer* AudioBuffer::create(unsigned numberOfChannels,
                                 size_t numberOfFrames,
                                 float sampleRate) {
  if (!AudioUtilities::isValidAudioBufferSampleRate(sampleRate) ||
      numberOfChannels > BaseAudioContext::maxNumberOfChannels() ||
      !numberOfChannels || !numberOfFrames)
    return nullptr;

  AudioBuffer* buffer =
      new AudioBuffer(numberOfChannels, numberOfFrames, sampleRate);

  if (!buffer->createdSuccessfully(numberOfChannels))
    return nullptr;
  return buffer;
}

AudioBuffer* AudioBuffer::create(unsigned numberOfChannels,
                                 size_t numberOfFrames,
                                 float sampleRate,
                                 ExceptionState& exceptionState) {
  if (!numberOfChannels ||
      numberOfChannels > BaseAudioContext::maxNumberOfChannels()) {
    exceptionState.throwDOMException(
        NotSupportedError, ExceptionMessages::indexOutsideRange(
                               "number of channels", numberOfChannels, 1u,
                               ExceptionMessages::InclusiveBound,
                               BaseAudioContext::maxNumberOfChannels(),
                               ExceptionMessages::InclusiveBound));
    return nullptr;
  }

  if (!AudioUtilities::isValidAudioBufferSampleRate(sampleRate)) {
    exceptionState.throwDOMException(
        NotSupportedError, ExceptionMessages::indexOutsideRange(
                               "sample rate", sampleRate,
                               AudioUtilities::minAudioBufferSampleRate(),
                               ExceptionMessages::InclusiveBound,
                               AudioUtilities::maxAudioBufferSampleRate(),
                               ExceptionMessages::InclusiveBound));
    return nullptr;
  }

  if (!numberOfFrames) {
    exceptionState.throwDOMException(
        NotSupportedError,
        ExceptionMessages::indexExceedsMinimumBound(
            "number of frames", numberOfFrames, static_cast<size_t>(0)));
    return nullptr;
  }

  AudioBuffer* audioBuffer =
      create(numberOfChannels, numberOfFrames, sampleRate);

  if (!audioBuffer) {
    exceptionState.throwDOMException(
        NotSupportedError, "createBuffer(" + String::number(numberOfChannels) +
                               ", " + String::number(numberOfFrames) + ", " +
                               String::number(sampleRate) + ") failed.");
  }

  return audioBuffer;
}

AudioBuffer* AudioBuffer::create(BaseAudioContext* context,
                                 const AudioBufferOptions& options,
                                 ExceptionState& exceptionState) {
  unsigned numberOfChannels;
  size_t numberOfFrames;
  float sampleRate;

  if (!options.hasNumberOfChannels()) {
    exceptionState.throwDOMException(
        NotFoundError, "AudioBufferOptions: numberOfChannels is required.");
    return nullptr;
  }

  if (!options.hasLength()) {
    exceptionState.throwDOMException(NotFoundError,
                                     "AudioBufferOptions: length is required.");
    return nullptr;
  }

  numberOfChannels = options.numberOfChannels();
  numberOfFrames = options.length();

  if (options.hasSampleRate())
    sampleRate = options.sampleRate();
  else
    sampleRate = context->sampleRate();

  return create(numberOfChannels, numberOfFrames, sampleRate, exceptionState);
}

AudioBuffer* AudioBuffer::createFromAudioFileData(const void* data,
                                                  size_t dataSize,
                                                  bool mixToMono,
                                                  float sampleRate) {
  RefPtr<AudioBus> bus =
      createBusFromInMemoryAudioFile(data, dataSize, mixToMono, sampleRate);
  if (bus) {
    AudioBuffer* buffer = new AudioBuffer(bus.get());
    if (buffer->createdSuccessfully(bus->numberOfChannels()))
      return buffer;
  }

  return nullptr;
}

AudioBuffer* AudioBuffer::createFromAudioBus(AudioBus* bus) {
  if (!bus)
    return nullptr;
  AudioBuffer* buffer = new AudioBuffer(bus);
  if (buffer->createdSuccessfully(bus->numberOfChannels()))
    return buffer;
  return nullptr;
}

bool AudioBuffer::createdSuccessfully(unsigned desiredNumberOfChannels) const {
  return numberOfChannels() == desiredNumberOfChannels;
}

DOMFloat32Array* AudioBuffer::createFloat32ArrayOrNull(size_t length) {
  RefPtr<WTF::Float32Array> bufferView =
      WTF::Float32Array::createOrNull(length);
  if (!bufferView)
    return nullptr;
  return DOMFloat32Array::create(bufferView.release());
}

AudioBuffer::AudioBuffer(unsigned numberOfChannels,
                         size_t numberOfFrames,
                         float sampleRate)
    : m_sampleRate(sampleRate), m_length(numberOfFrames) {
  m_channels.reserveCapacity(numberOfChannels);

  for (unsigned i = 0; i < numberOfChannels; ++i) {
    DOMFloat32Array* channelDataArray = createFloat32ArrayOrNull(m_length);
    // If the channel data array could not be created, just return. The caller
    // will need to check that the desired number of channels were created.
    if (!channelDataArray)
      return;

    channelDataArray->setNeuterable(false);
    m_channels.append(channelDataArray);
  }
}

AudioBuffer::AudioBuffer(AudioBus* bus)
    : m_sampleRate(bus->sampleRate()), m_length(bus->length()) {
  // Copy audio data from the bus to the Float32Arrays we manage.
  unsigned numberOfChannels = bus->numberOfChannels();
  m_channels.reserveCapacity(numberOfChannels);
  for (unsigned i = 0; i < numberOfChannels; ++i) {
    DOMFloat32Array* channelDataArray = createFloat32ArrayOrNull(m_length);
    // If the channel data array could not be created, just return. The caller
    // will need to check that the desired number of channels were created.
    if (!channelDataArray)
      return;

    channelDataArray->setNeuterable(false);
    const float* src = bus->channel(i)->data();
    float* dst = channelDataArray->data();
    memmove(dst, src, m_length * sizeof(*dst));
    m_channels.append(channelDataArray);
  }
}

DOMFloat32Array* AudioBuffer::getChannelData(unsigned channelIndex,
                                             ExceptionState& exceptionState) {
  if (channelIndex >= m_channels.size()) {
    exceptionState.throwDOMException(
        IndexSizeError, "channel index (" + String::number(channelIndex) +
                            ") exceeds number of channels (" +
                            String::number(m_channels.size()) + ")");
    return nullptr;
  }

  return getChannelData(channelIndex);
}

DOMFloat32Array* AudioBuffer::getChannelData(unsigned channelIndex) {
  if (channelIndex >= m_channels.size())
    return nullptr;

  return m_channels[channelIndex].get();
}

void AudioBuffer::copyFromChannel(DOMFloat32Array* destination,
                                  long channelNumber,
                                  ExceptionState& exceptionState) {
  return copyFromChannel(destination, channelNumber, 0, exceptionState);
}

void AudioBuffer::copyFromChannel(DOMFloat32Array* destination,
                                  long channelNumber,
                                  unsigned long startInChannel,
                                  ExceptionState& exceptionState) {
  if (channelNumber < 0 ||
      channelNumber >= static_cast<long>(m_channels.size())) {
    exceptionState.throwDOMException(
        IndexSizeError, ExceptionMessages::indexOutsideRange(
                            "channelNumber", channelNumber, 0L,
                            ExceptionMessages::InclusiveBound,
                            static_cast<long>(m_channels.size() - 1),
                            ExceptionMessages::InclusiveBound));
    return;
  }

  DOMFloat32Array* channelData = m_channels[channelNumber].get();

  if (startInChannel >= channelData->length()) {
    exceptionState.throwDOMException(
        IndexSizeError, ExceptionMessages::indexOutsideRange(
                            "startInChannel", startInChannel, 0UL,
                            ExceptionMessages::InclusiveBound,
                            static_cast<unsigned long>(channelData->length()),
                            ExceptionMessages::ExclusiveBound));

    return;
  }

  unsigned count = channelData->length() - startInChannel;
  count = std::min(destination->length(), count);

  const float* src = channelData->data();
  float* dst = destination->data();

  DCHECK(src);
  DCHECK(dst);

  memcpy(dst, src + startInChannel, count * sizeof(*src));
}

void AudioBuffer::copyToChannel(DOMFloat32Array* source,
                                long channelNumber,
                                ExceptionState& exceptionState) {
  return copyToChannel(source, channelNumber, 0, exceptionState);
}

void AudioBuffer::copyToChannel(DOMFloat32Array* source,
                                long channelNumber,
                                unsigned long startInChannel,
                                ExceptionState& exceptionState) {
  if (channelNumber < 0 ||
      channelNumber >= static_cast<long>(m_channels.size())) {
    exceptionState.throwDOMException(
        IndexSizeError, ExceptionMessages::indexOutsideRange(
                            "channelNumber", channelNumber, 0L,
                            ExceptionMessages::InclusiveBound,
                            static_cast<long>(m_channels.size() - 1),
                            ExceptionMessages::InclusiveBound));
    return;
  }

  DOMFloat32Array* channelData = m_channels[channelNumber].get();

  if (startInChannel >= channelData->length()) {
    exceptionState.throwDOMException(
        IndexSizeError, ExceptionMessages::indexOutsideRange(
                            "startInChannel", startInChannel, 0UL,
                            ExceptionMessages::InclusiveBound,
                            static_cast<unsigned long>(channelData->length()),
                            ExceptionMessages::ExclusiveBound));

    return;
  }

  unsigned count = channelData->length() - startInChannel;
  count = std::min(source->length(), count);

  const float* src = source->data();
  float* dst = channelData->data();

  DCHECK(src);
  DCHECK(dst);

  memcpy(dst + startInChannel, src, count * sizeof(*dst));
}

void AudioBuffer::zero() {
  for (unsigned i = 0; i < m_channels.size(); ++i) {
    if (DOMFloat32Array* array = getChannelData(i)) {
      float* data = array->data();
      memset(data, 0, length() * sizeof(*data));
    }
  }
}

}  // namespace blink
