blob: db5240a6308b29a9ff812b23ee10c4648cfba205 [file] [log] [blame]
/*
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "media/base/shell_audio_bus.h"
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
namespace media {
namespace testing {
namespace {
template <typename T>
bool VerifyValues(const T* data, size_t size, T value) {
for (size_t i = 0; i < size; ++i) {
if (data[i] != value) {
return false;
}
}
return true;
}
template <typename T>
void FillValues(T* data, size_t size, T value) {
for (size_t i = 0; i < size; ++i) {
data[i] = value;
}
}
void Scribble(uint8* data, size_t size) {
for (size_t i = 0; i < size; ++i) {
data[i] = static_cast<uint8>(i + 0x34);
}
}
bool VerifyScribble(const uint8* data, size_t size) {
for (size_t i = 0; i < size; ++i) {
if (data[i] != static_cast<uint8>(i + 0x34)) {
return false;
}
}
return true;
}
// This function only works with audio bus containing float32 samples.
bool IsSameChannel(const ShellAudioBus& audio_bus_1,
size_t channel_1,
const ShellAudioBus& audio_bus_2,
size_t channel_2) {
if (audio_bus_1.frames() != audio_bus_2.frames()) {
return false;
}
for (size_t frame = 0; frame < audio_bus_1.frames(); ++frame) {
if (fabsf(audio_bus_1.GetFloat32Sample(channel_1, frame) -
audio_bus_2.GetFloat32Sample(channel_2, frame)) > 0.001) {
return false;
}
}
return true;
}
// This class allocates buffer with extra guard bytes in the front and back of
// the buffer. It can be used to verify if the ShellAudioBus implementation
// writes any data out of boundary.
class GuardedBuffers {
public:
GuardedBuffers(size_t number_of_buffers, size_t bytes_per_buffer) {
std::vector<uint8> buffer(bytes_per_buffer + kGuardBytes * 2);
buffers_.resize(number_of_buffers, buffer);
ScribbleContent();
}
void ScribbleContent() {
for (size_t i = 0; i < buffers_.size(); ++i) {
Scribble(&buffers_[i][0], kGuardBytes);
Scribble(&buffers_[i][buffers_[i].size() - kGuardBytes], kGuardBytes);
Scribble(&buffers_[i][kGuardBytes], buffers_[i].size() - kGuardBytes * 2);
}
}
bool VerifyGuardBytes() const {
for (size_t i = 0; i < buffers_.size(); ++i) {
if (!VerifyScribble(&buffers_[i][0], kGuardBytes) ||
!VerifyScribble(&buffers_[i][buffers_[i].size() - kGuardBytes],
kGuardBytes)) {
return false;
}
}
return true;
}
template <typename T>
T* GetBuffer(size_t index) {
return reinterpret_cast<T*>(&buffers_.at(index)[kGuardBytes]);
}
private:
typedef std::vector<uint8> Buffer;
typedef std::vector<Buffer> Buffers;
static const size_t kGuardBytes = 256;
Buffers buffers_;
};
class ShellAudioBusTest : public ::testing::Test {
public:
typedef ShellAudioBus::SampleType SampleType;
typedef ShellAudioBus::StorageType StorageType;
~ShellAudioBusTest() {
// We do an extra call to VerifyGuardBytes() just in case if it was omitted
// in a test. It is still recommended to verify the integrity in individual
// tests so the failure message is more informational.
if (guarded_buffers_) {
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
}
template <typename T>
void CreateAudioBus(StorageType storage_type) {
// We do an extra call to VerifyGuardBytes() just in case if it was omitted
// in a test. It is still recommended to verify the integrity in individual
// tests so the failure message is more informational.
if (guarded_buffers_) {
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
if (storage_type == ShellAudioBus::kPlanar) {
guarded_buffers_.reset(
new GuardedBuffers(kChannels, sizeof(T) * kFrames));
std::vector<T*> samples;
for (size_t channel = 0; channel < kChannels; ++channel) {
samples.push_back(guarded_buffers_->GetBuffer<T>(channel));
}
audio_bus_.reset(new ShellAudioBus(kFrames, samples));
} else {
guarded_buffers_.reset(
new GuardedBuffers(1, sizeof(T) * kFrames * kChannels));
audio_bus_.reset(new ShellAudioBus(kChannels, kFrames,
guarded_buffers_->GetBuffer<T>(0)));
}
}
protected:
static const size_t kChannels;
static const size_t kFrames;
scoped_ptr<GuardedBuffers> guarded_buffers_;
scoped_ptr<ShellAudioBus> audio_bus_;
};
const size_t ShellAudioBusTest::kChannels = 3;
const size_t ShellAudioBusTest::kFrames = 809;
TEST_F(ShellAudioBusTest, ConstructorWithAllocation) {
ShellAudioBus audio_bus(kChannels, kFrames, ShellAudioBus::kFloat32,
ShellAudioBus::kPlanar);
EXPECT_EQ(audio_bus.channels(), kChannels);
EXPECT_EQ(audio_bus.frames(), kFrames);
for (size_t channel = 0; channel < audio_bus.channels(); ++channel) {
const uint8* samples = audio_bus.planar_data(channel);
EXPECT_EQ(reinterpret_cast<intptr_t>(samples) %
ShellAudioBus::kChannelAlignmentInBytes,
0);
}
}
TEST_F(ShellAudioBusTest, ConstructorWithoutAllocation) {
CreateAudioBus<float>(ShellAudioBus::kInterleaved);
EXPECT_EQ(audio_bus_->channels(), kChannels);
EXPECT_EQ(audio_bus_->frames(), kFrames);
const float* samples =
reinterpret_cast<const float*>(audio_bus_->interleaved_data());
EXPECT_EQ(samples, guarded_buffers_->GetBuffer<float>(0));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
CreateAudioBus<int16>(ShellAudioBus::kPlanar);
EXPECT_EQ(audio_bus_->channels(), kChannels);
EXPECT_EQ(audio_bus_->frames(), kFrames);
for (size_t channel = 0; channel < audio_bus_->channels(); ++channel) {
const int16* samples =
reinterpret_cast<const int16*>(audio_bus_->planar_data(channel));
EXPECT_EQ(samples, guarded_buffers_->GetBuffer<int16>(channel));
}
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
TEST_F(ShellAudioBusTest, GetSampleSizeInBytes) {
ShellAudioBus float_audio_bus(2, 4, ShellAudioBus::kFloat32,
ShellAudioBus::kPlanar);
EXPECT_EQ(float_audio_bus.GetSampleSizeInBytes(), sizeof(float));
ShellAudioBus int16_audio_bus(2, 4, ShellAudioBus::kInt16,
ShellAudioBus::kPlanar);
EXPECT_EQ(int16_audio_bus.GetSampleSizeInBytes(), sizeof(int16));
}
TEST_F(ShellAudioBusTest, GetSample) {
CreateAudioBus<float>(ShellAudioBus::kInterleaved);
// Mark the first sample of the first channel as 1.f.
guarded_buffers_->GetBuffer<float>(0)[0] = 1.f;
// Mark the last sample of the last channel as 1.f.
guarded_buffers_->GetBuffer<float>(0)[kFrames * kChannels - 1] = 1.f;
EXPECT_EQ(audio_bus_->GetFloat32Sample(0, 0), 1.f);
EXPECT_EQ(audio_bus_->GetFloat32Sample(kChannels - 1, kFrames - 1), 1.f);
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
CreateAudioBus<int16>(ShellAudioBus::kPlanar);
for (size_t channel = 0; channel < audio_bus_->channels(); ++channel) {
// Mark the first sample of the channel as 100.
guarded_buffers_->GetBuffer<int16>(channel)[0] = 100;
// Mark the last sample of the channel as 100.
guarded_buffers_->GetBuffer<int16>(channel)[kFrames - 1] = 100;
EXPECT_EQ(audio_bus_->GetInt16Sample(channel, 0), 100);
EXPECT_EQ(audio_bus_->GetInt16Sample(channel, kFrames - 1), 100);
}
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
TEST_F(ShellAudioBusTest, ZeroFrames) {
CreateAudioBus<float>(ShellAudioBus::kInterleaved);
Scribble(guarded_buffers_->GetBuffer<uint8>(0),
sizeof(float) * kFrames * kChannels);
audio_bus_->ZeroFrames(0, 0);
audio_bus_->ZeroFrames(kFrames, kFrames);
EXPECT_TRUE(VerifyScribble(guarded_buffers_->GetBuffer<uint8>(0),
sizeof(float) * kFrames * kChannels));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
// Mark the first sample of last channel and second sample of the first
// channel as 1.f.
guarded_buffers_->GetBuffer<float>(0)[kChannels - 1] = 1.f;
guarded_buffers_->GetBuffer<float>(0)[kChannels] = 1.f;
audio_bus_->ZeroFrames(0, 1);
EXPECT_EQ(guarded_buffers_->GetBuffer<float>(0)[kChannels - 1], 0.f);
EXPECT_EQ(guarded_buffers_->GetBuffer<float>(0)[kChannels], 1.f);
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
// Mark the first sample of last channel and second but last sample of the
// first channel as 1.f.
guarded_buffers_->GetBuffer<float>(0)[kChannels * (kFrames - 1)] = 1.f;
guarded_buffers_->GetBuffer<float>(0)[kChannels * (kFrames - 1) - 1] = 1.f;
audio_bus_->ZeroFrames(kFrames - 1, kFrames);
EXPECT_EQ(guarded_buffers_->GetBuffer<float>(0)[kChannels * (kFrames - 1)],
0.f);
EXPECT_EQ(
guarded_buffers_->GetBuffer<float>(0)[kChannels * (kFrames - 1) - 1],
1.f);
audio_bus_->ZeroFrames(1, kFrames - 1);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<float>(0),
kFrames * kChannels, 0.f));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
CreateAudioBus<int16>(ShellAudioBus::kPlanar);
for (size_t channel = 0; channel < audio_bus_->channels(); ++channel) {
// Mark the first two samples of the channel as 100.
guarded_buffers_->GetBuffer<int16>(channel)[0] = 100;
guarded_buffers_->GetBuffer<int16>(channel)[1] = 100;
audio_bus_->ZeroFrames(0, 1);
EXPECT_EQ(guarded_buffers_->GetBuffer<int16>(channel)[0], 0);
EXPECT_EQ(guarded_buffers_->GetBuffer<int16>(channel)[1], 100);
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
// Mark the last two samples of the channel as 100.
guarded_buffers_->GetBuffer<int16>(channel)[kFrames - 1] = 100;
guarded_buffers_->GetBuffer<int16>(channel)[kFrames - 2] = 100;
audio_bus_->ZeroFrames(kFrames - 1, kFrames);
EXPECT_EQ(guarded_buffers_->GetBuffer<int16>(channel)[kFrames - 1], 0);
EXPECT_EQ(guarded_buffers_->GetBuffer<int16>(channel)[kFrames - 2], 100);
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
audio_bus_->ZeroFrames(1, kFrames - 1);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<int16>(channel),
kFrames, static_cast<int16>(0)));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
}
TEST_F(ShellAudioBusTest, AssignWithSameSampleTypeAndStorageType) {
CreateAudioBus<float>(ShellAudioBus::kInterleaved);
FillValues(guarded_buffers_->GetBuffer<float>(0), kFrames * kChannels, 1.f);
{
ShellAudioBus source(kChannels, kFrames / 2, ShellAudioBus::kFloat32,
ShellAudioBus::kInterleaved);
source.ZeroAllFrames();
audio_bus_->Assign(source);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<float>(0),
kFrames / 2 * kChannels, 0.f));
EXPECT_TRUE(VerifyValues(
guarded_buffers_->GetBuffer<float>(0) + kFrames / 2 * kChannels,
(kFrames - kFrames / 2) * kChannels, 1.f));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
{
ShellAudioBus source(kChannels, kFrames, ShellAudioBus::kFloat32,
ShellAudioBus::kInterleaved);
source.ZeroAllFrames();
audio_bus_->Assign(source);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<float>(0),
kFrames * kChannels, 0.f));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
{
ShellAudioBus source(kChannels, kFrames * 2, ShellAudioBus::kFloat32,
ShellAudioBus::kInterleaved);
source.ZeroAllFrames();
audio_bus_->Assign(source);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<float>(0),
kFrames * kChannels, 0.f));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
CreateAudioBus<int16>(ShellAudioBus::kPlanar);
for (size_t channel = 0; channel < audio_bus_->channels(); ++channel) {
FillValues(guarded_buffers_->GetBuffer<int16>(channel), kFrames,
static_cast<int16>(100));
{
ShellAudioBus source(kChannels, kFrames / 2, ShellAudioBus::kInt16,
ShellAudioBus::kPlanar);
source.ZeroAllFrames();
audio_bus_->Assign(source);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<int16>(channel),
kFrames / 2, static_cast<int16>(0)));
EXPECT_TRUE(VerifyValues(
guarded_buffers_->GetBuffer<int16>(channel) + kFrames / 2,
kFrames - kFrames / 2, static_cast<int16>(100)));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
{
ShellAudioBus source(kChannels, kFrames, ShellAudioBus::kInt16,
ShellAudioBus::kPlanar);
source.ZeroAllFrames();
audio_bus_->Assign(source);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<int16>(channel),
kFrames, static_cast<int16>(0)));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
{
ShellAudioBus source(kChannels, kFrames * 2, ShellAudioBus::kInt16,
ShellAudioBus::kPlanar);
source.ZeroAllFrames();
audio_bus_->Assign(source);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<int16>(channel),
kFrames, static_cast<int16>(0)));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
}
}
TEST_F(ShellAudioBusTest, AssignWithDifferentSampleTypesAndStorageTypes) {
CreateAudioBus<float>(ShellAudioBus::kInterleaved);
FillValues(guarded_buffers_->GetBuffer<float>(0), kFrames * kChannels, 1.f);
{
ShellAudioBus source(kChannels, kFrames / 2, ShellAudioBus::kInt16,
ShellAudioBus::kPlanar);
source.ZeroAllFrames();
audio_bus_->Assign(source);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<float>(0),
kFrames / 2 * kChannels, 0.f));
EXPECT_TRUE(VerifyValues(
guarded_buffers_->GetBuffer<float>(0) + kFrames / 2 * kChannels,
(kFrames - kFrames / 2) * kChannels, 1.f));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
{
ShellAudioBus source(kChannels, kFrames, ShellAudioBus::kInt16,
ShellAudioBus::kPlanar);
source.ZeroAllFrames();
audio_bus_->Assign(source);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<float>(0),
kFrames * kChannels, 0.f));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
{
ShellAudioBus source(kChannels, kFrames * 2, ShellAudioBus::kInt16,
ShellAudioBus::kPlanar);
source.ZeroAllFrames();
audio_bus_->Assign(source);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<float>(0),
kFrames * kChannels, 0.f));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
CreateAudioBus<int16>(ShellAudioBus::kPlanar);
for (size_t channel = 0; channel < audio_bus_->channels(); ++channel) {
FillValues(guarded_buffers_->GetBuffer<int16>(channel), kFrames,
static_cast<int16>(100));
{
ShellAudioBus source(kChannels, kFrames / 2, ShellAudioBus::kFloat32,
ShellAudioBus::kInterleaved);
source.ZeroAllFrames();
audio_bus_->Assign(source);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<int16>(channel),
kFrames / 2, static_cast<int16>(0)));
EXPECT_TRUE(VerifyValues(
guarded_buffers_->GetBuffer<int16>(channel) + kFrames / 2,
kFrames - kFrames / 2, static_cast<int16>(100)));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
{
ShellAudioBus source(kChannels, kFrames, ShellAudioBus::kFloat32,
ShellAudioBus::kInterleaved);
source.ZeroAllFrames();
audio_bus_->Assign(source);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<int16>(channel),
kFrames, static_cast<int16>(0)));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
{
ShellAudioBus source(kChannels, kFrames * 2, ShellAudioBus::kFloat32,
ShellAudioBus::kInterleaved);
source.ZeroAllFrames();
audio_bus_->Assign(source);
EXPECT_TRUE(VerifyValues(guarded_buffers_->GetBuffer<int16>(channel),
kFrames, static_cast<int16>(0)));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
}
}
TEST_F(ShellAudioBusTest, AssignWithMatrix) {
CreateAudioBus<float>(ShellAudioBus::kInterleaved);
// Fill the 1st channel with incrementally positive samples, fill the 2nd
// channel with decrementally negative samples, and fill the 3rd channel with
// 0.
for (size_t channel = 0; channel < kChannels; ++channel) {
for (size_t frame = 0; frame < kFrames; ++frame) {
float sample = 0.f;
if (channel == 0) {
sample = static_cast<float>(frame) / static_cast<float>(kFrames);
} else if (channel == 1) {
sample = -static_cast<float>(frame) / static_cast<float>(kFrames);
}
guarded_buffers_->GetBuffer<float>(0)[frame * kChannels + channel] =
sample;
}
}
{
ShellAudioBus other(kChannels * 2, kFrames, ShellAudioBus::kFloat32,
ShellAudioBus::kPlanar);
const float kConversionMatrix[] = {
0.f, 1.f, 0.f, // dest channel 0 = source channel 1.
1.f, 0.f, 0.f, // dest channel 1 = source channel 0.
1.f, 1.f, 1.f, // dest channel 2 = sum of all source channels,
// effectively make it equal to source channel 2.
-1.f, 0.f, 0.f, // dest channel 3 = negative source channel 0,
// effectively make it equal to source channel 1.
0.f, -1.f, 0.f, // dest channel 4 = negative source channel 1,
// effectively make it equal to source channel 0.
2.f, 1.f, -1.f, // dest channel 5 = 2 * source channel 0 + source
// channel 2 - source channel 2, effectively make it
// equal to source channel 0.
};
std::vector<float> matrix(kConversionMatrix,
kConversionMatrix + arraysize(kConversionMatrix));
other.Assign(*audio_bus_, matrix);
EXPECT_TRUE(IsSameChannel(other, 0, *audio_bus_, 1));
EXPECT_TRUE(IsSameChannel(other, 1, *audio_bus_, 0));
EXPECT_TRUE(IsSameChannel(other, 2, *audio_bus_, 2));
EXPECT_TRUE(IsSameChannel(other, 3, *audio_bus_, 1));
EXPECT_TRUE(IsSameChannel(other, 4, *audio_bus_, 0));
EXPECT_TRUE(IsSameChannel(other, 5, *audio_bus_, 0));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
}
TEST_F(ShellAudioBusTest, MixWithoutMatrix) {
CreateAudioBus<float>(ShellAudioBus::kInterleaved);
// Fill the 1st channel with incrementally positive samples, fill the 2nd
// channel with decrementally negative samples, and fill the 3rd channel with
// 0.
for (size_t channel = 0; channel < kChannels; ++channel) {
for (size_t frame = 0; frame < kFrames; ++frame) {
float sample = 0.f;
if (channel == 0) {
sample = static_cast<float>(frame) / static_cast<float>(kFrames);
} else if (channel == 1) {
sample = -static_cast<float>(frame) / static_cast<float>(kFrames);
}
guarded_buffers_->GetBuffer<float>(0)[frame * kChannels + channel] =
sample;
}
}
{
ShellAudioBus other(kChannels, kFrames, ShellAudioBus::kFloat32,
ShellAudioBus::kPlanar);
other.Assign(*audio_bus_);
// By call Mix() here, we effectively multiplies every sample in |other| by
// 2.
other.Mix(*audio_bus_);
// Adjust the original audio bus by multiplying every sample by 2.
for (size_t channel = 0; channel < kChannels; ++channel) {
for (size_t frame = 0; frame < kFrames; ++frame) {
guarded_buffers_->GetBuffer<float>(0)[frame * kChannels + channel] *= 2;
}
}
EXPECT_TRUE(IsSameChannel(other, 0, *audio_bus_, 0));
EXPECT_TRUE(IsSameChannel(other, 1, *audio_bus_, 1));
EXPECT_TRUE(IsSameChannel(other, 2, *audio_bus_, 2));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
}
TEST_F(ShellAudioBusTest, MixWithMatrix) {
CreateAudioBus<float>(ShellAudioBus::kInterleaved);
// Fill the 1st channel with incrementally positive samples, fill the 2nd
// channel with decrementally negative samples, and fill the 3rd channel with
// 0.
for (size_t channel = 0; channel < kChannels; ++channel) {
for (size_t frame = 0; frame < kFrames; ++frame) {
float sample = 0.f;
if (channel == 0) {
sample = static_cast<float>(frame) / static_cast<float>(kFrames);
} else if (channel == 1) {
sample = -static_cast<float>(frame) / static_cast<float>(kFrames);
}
guarded_buffers_->GetBuffer<float>(0)[frame * kChannels + channel] =
sample;
}
}
{
ShellAudioBus other(kChannels * 2, kFrames, ShellAudioBus::kFloat32,
ShellAudioBus::kPlanar);
const float kConversionMatrix[] = {
0.f, 1.f, 0.f, // dest channel 0 = source channel 1.
1.f, 0.f, 0.f, // dest channel 1 = source channel 0.
1.f, 1.f, 1.f, // dest channel 2 = sum of all source channels,
// effectively make it equal to source channel 2.
-1.f, 0.f, 0.f, // dest channel 3 = negative source channel 0,
// effectively make it equal to source channel 1.
0.f, -1.f, 0.f, // dest channel 4 = negative source channel 1,
// effectively make it equal to source channel 0.
2.f, 1.f, -1.f, // dest channel 5 = 2 * source channel 0 + source
// channel 2 - source channel 2, effectively make it
// equal to source channel 0.
};
std::vector<float> matrix(kConversionMatrix,
kConversionMatrix + arraysize(kConversionMatrix));
other.Assign(*audio_bus_, matrix);
// By call Mix() here, we effectively multiplies every sample in |other| by
// 2.
other.Mix(*audio_bus_, matrix);
// Adjust the original audio bus by multiplying every sample by 2.
for (size_t channel = 0; channel < kChannels; ++channel) {
for (size_t frame = 0; frame < kFrames; ++frame) {
guarded_buffers_->GetBuffer<float>(0)[frame * kChannels + channel] *= 2;
}
}
EXPECT_TRUE(IsSameChannel(other, 0, *audio_bus_, 1));
EXPECT_TRUE(IsSameChannel(other, 1, *audio_bus_, 0));
EXPECT_TRUE(IsSameChannel(other, 2, *audio_bus_, 2));
EXPECT_TRUE(IsSameChannel(other, 3, *audio_bus_, 1));
EXPECT_TRUE(IsSameChannel(other, 4, *audio_bus_, 0));
EXPECT_TRUE(IsSameChannel(other, 5, *audio_bus_, 0));
EXPECT_TRUE(guarded_buffers_->VerifyGuardBytes());
}
}
} // namespace
} // namespace testing
} // namespace media