#include "chromecast/media/audio/interleaved_channel_mixer.h"
#include "base/check_op.h"
#include "base/compiler_specific.h"
#include "media/base/channel_mixing_matrix.h"
namespace chromecast {
namespace media {
InterleavedChannelMixer::InterleavedChannelMixer(
::media::ChannelLayout input_layout,
int input_channel_count,
::media::ChannelLayout output_layout,
int output_channel_count,
int max_frames)
: input_layout_(input_layout),
input_channel_count_(input_channel_count),
output_layout_(output_layout),
output_channel_count_(output_channel_count),
max_frames_(max_frames) {
if (input_layout_ == output_layout_) {
return;
}
buffer_.resize(max_frames * output_channel_count_);
std::vector<std::vector<float>> matrix;
::media::ChannelMixingMatrix matrix_builder(
input_layout_, input_channel_count_, output_layout_,
output_channel_count_);
matrix_builder.CreateTransformationMatrix(&matrix);
transform_.reserve(input_channel_count_ * output_channel_count_);
for (const std::vector<float>& output_channel : matrix) {
transform_.insert(transform_.end(), output_channel.begin(),
output_channel.end());
}
}
InterleavedChannelMixer::~InterleavedChannelMixer() = default;
float* InterleavedChannelMixer::Transform(const float* input, int num_frames) {
if (input_layout_ == output_layout_) {
return const_cast<float*>(input);
}
DCHECK_LE(num_frames, max_frames_);
float* output = buffer_.data();
for (int f = 0; f < num_frames; ++f) {
float* t = transform_.data();
for (int out_c = 0; out_c < output_channel_count_; ++out_c) {
float result = 0;
for (int in_c = 0; in_c < input_channel_count_; ++in_c) {
result += *t * UNSAFE_TODO(input[in_c]);
UNSAFE_TODO(++t);
}
*output = result;
UNSAFE_TODO(++output);
}
UNSAFE_TODO(input += input_channel_count_);
}
return buffer_.data();
}
}
}