// 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/channel_mixer.h"

#include <stddef.h>

#include "base/logging.h"
#include "media/base/audio_bus.h"
#include "media/base/audio_parameters.h"
#include "media/base/channel_mixing_matrix.h"
#include "media/base/vector_math.h"

namespace media {

ChannelMixer::ChannelMixer(ChannelLayout input_layout,
                           ChannelLayout output_layout) {
  Initialize(input_layout,
             ChannelLayoutToChannelCount(input_layout),
             output_layout,
             ChannelLayoutToChannelCount(output_layout));
}

ChannelMixer::ChannelMixer(
    const AudioParameters& input, const AudioParameters& output) {
  Initialize(input.channel_layout(),
             input.channels(),
             output.channel_layout(),
             output.channels());
}

void ChannelMixer::Initialize(
    ChannelLayout input_layout, int input_channels,
    ChannelLayout output_layout, int output_channels) {
  // Create the transformation matrix
  ChannelMixingMatrix matrix_builder(input_layout, input_channels,
                                     output_layout, output_channels);
  remapping_ = matrix_builder.CreateTransformationMatrix(&matrix_);
}

ChannelMixer::~ChannelMixer() = default;

void ChannelMixer::Transform(const AudioBus* input, AudioBus* output) {
  CHECK_EQ(input->frames(), output->frames());
  TransformPartial(input, input->frames(), output);
}

void ChannelMixer::TransformPartial(const AudioBus* input,
                                    int frame_count,
                                    AudioBus* output) {
  CHECK_EQ(matrix_.size(), static_cast<size_t>(output->channels()));
  CHECK_EQ(matrix_[0].size(), static_cast<size_t>(input->channels()));
  CHECK_LE(frame_count, input->frames());
  CHECK_LE(frame_count, output->frames());

  // Zero initialize |output| so we're accumulating from zero.
  output->ZeroFrames(frame_count);

  // If we're just remapping we can simply copy the correct input to output.
  if (remapping_) {
    for (int output_ch = 0; output_ch < output->channels(); ++output_ch) {
      for (int input_ch = 0; input_ch < input->channels(); ++input_ch) {
        float scale = matrix_[output_ch][input_ch];
        if (scale > 0) {
          DCHECK_EQ(scale, 1.0f);
          memcpy(output->channel(output_ch), input->channel(input_ch),
                 sizeof(*output->channel(output_ch)) * frame_count);
          break;
        }
      }
    }
    return;
  }

  for (int output_ch = 0; output_ch < output->channels(); ++output_ch) {
    for (int input_ch = 0; input_ch < input->channels(); ++input_ch) {
      float scale = matrix_[output_ch][input_ch];
      // Scale should always be positive.  Don't bother scaling by zero.
      DCHECK_GE(scale, 0);
      if (scale > 0) {
        vector_math::FMAC(input->channel(input_ch), scale, frame_count,
                          output->channel(output_ch));
      }
    }
  }
}

}  // namespace media
