15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "build/build_config.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_parameters.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/audio_bus.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/channel_layout.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/base/fake_audio_render_callback.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kChannels = 6;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_5_1;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use a buffer size which is intentionally not a multiple of kChannelAlignment.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kFrameCount = media::AudioBus::kChannelAlignment * 32 - 1;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSampleRate = 48000;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioBusTest : public testing::Test {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioBusTest() {}
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~AudioBusTest() {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < data_.size(); ++i)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AlignedFree(data_[i]);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validate parameters returned by AudioBus v.s. the constructed parameters.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void VerifyParams(AudioBus* bus) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kChannels, bus->channels());
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kFrameCount, bus->frames());
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void VerifyValue(const float data[], int size, float value) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < size; ++i)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_FLOAT_EQ(value, data[i]) << "i=" << i;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Verify values for each channel in |result| are within |epsilon| of
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // |expected|.  If |epsilon| exactly equals 0, uses FLOAT_EQ macro.
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void VerifyBusWithEpsilon(const AudioBus* result, const AudioBus* expected,
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            float epsilon) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(expected->channels(), result->channels());
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(expected->frames(), result->frames());
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int ch = 0; ch < result->channels(); ++ch) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int i = 0; i < result->frames(); ++i) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SCOPED_TRACE(base::StringPrintf("ch=%d, i=%d", ch, i));
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (epsilon == 0) {
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          ASSERT_FLOAT_EQ(expected->channel(ch)[i], result->channel(ch)[i]);
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        } else {
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          ASSERT_NEAR(expected->channel(ch)[i], result->channel(ch)[i],
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      epsilon);
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Verify values for each channel in |result| against |expected|.
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void VerifyBus(const AudioBus* result, const AudioBus* expected) {
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VerifyBusWithEpsilon(result, expected, 0);
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read and write to the full extent of the allocated channel data.  Also test
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the Zero() method and verify it does as advertised.  Also test data if data
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is 16-byte aligned as advertised (see kChannelAlignment in audio_bus.h).
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void VerifyChannelData(AudioBus* bus) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < bus->channels(); ++i) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          bus->channel(i)) & (AudioBus::kChannelAlignment - 1));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < bus->channels(); ++i)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VerifyValue(bus->channel(i), bus->frames(), i);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus->Zero();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < bus->channels(); ++i)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VerifyValue(bus->channel(i), bus->frames(), 0);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify copying to and from |bus1| and |bus2|.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CopyTest(AudioBus* bus1, AudioBus* bus2) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Fill |bus1| with dummy data.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < bus1->channels(); ++i)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::fill(bus1->channel(i), bus1->channel(i) + bus1->frames(), i);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify copy from |bus1| to |bus2|.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus2->Zero();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus1->CopyTo(bus2);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyBus(bus1, bus2);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verify copy from |bus2| to |bus1|.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus1->Zero();
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus2->CopyTo(bus1);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyBus(bus2, bus1);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<float*> data_;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AudioBusTest);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify basic Create(...) method works as advertised.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioBusTest, Create) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyParams(bus.get());
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyChannelData(bus.get());
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify Create(...) using AudioParameters works as advertised.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioBusTest, CreateUsingAudioParameters) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus = AudioBus::Create(AudioParameters(
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kFrameCount));
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyParams(bus.get());
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyChannelData(bus.get());
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify an AudioBus created via wrapping a vector works as advertised.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioBusTest, WrapVector) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_.reserve(kChannels);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kChannels; ++i) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_.push_back(static_cast<float*>(base::AlignedAlloc(
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment)));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus = AudioBus::WrapVector(kFrameCount, data_);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyParams(bus.get());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyChannelData(bus.get());
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify an AudioBus created via wrapping a memory block works as advertised.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioBusTest, WrapMemory) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioParameters params(
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kFrameCount);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int data_size = AudioBus::CalculateMemorySize(params);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data(static_cast<float*>(
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::AlignedAlloc(data_size, AudioBus::kChannelAlignment)));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill the memory with a test value we can check for after wrapping.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const float kTestValue = 3;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::fill(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.get(), data.get() + data_size / sizeof(*data.get()), kTestValue);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus = AudioBus::WrapMemory(params, data.get());
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the test value we filled prior to wrapping.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < bus->channels(); ++i)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyValue(bus->channel(i), bus->frames(), kTestValue);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyParams(bus.get());
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyChannelData(bus.get());
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the channel vectors lie within the provided memory block.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GE(bus->channel(0), data.get());
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(bus->channel(bus->channels() - 1) + bus->frames(),
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            data.get() + data_size / sizeof(*data.get()));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simulate a shared memory transfer and verify results.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioBusTest, CopyTo) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create one bus with AudioParameters and the other through direct values to
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // test for parity between the Create() functions.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AudioParameters params(
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate, 32,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kFrameCount);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus1 = AudioBus::Create(kChannels, kFrameCount);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus2 = AudioBus::Create(params);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("Created");
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CopyTest(bus1.get(), bus2.get());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("Wrapped Vector");
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Try a copy to an AudioBus wrapping a vector.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_.reserve(kChannels);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kChannels; ++i) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_.push_back(static_cast<float*>(base::AlignedAlloc(
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          sizeof(*data_[i]) * kFrameCount, AudioBus::kChannelAlignment)));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus2 = AudioBus::WrapVector(kFrameCount, data_);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CopyTest(bus1.get(), bus2.get());
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("Wrapped Memory");
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Try a copy to an AudioBus wrapping a memory block.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr_malloc<float, base::ScopedPtrAlignedFree> data(
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<float*>(base::AlignedAlloc(
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            AudioBus::CalculateMemorySize(params),
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            AudioBus::kChannelAlignment)));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus2 = AudioBus::WrapMemory(params, data.get());
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CopyTest(bus1.get(), bus2.get());
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify Zero() and ZeroFrames(...) utility methods work as advertised.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioBusTest, Zero) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill the bus with dummy data.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < bus->channels(); ++i)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Zero first half the frames of each channel.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->ZeroFrames(kFrameCount / 2);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < bus->channels(); ++i) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("First Half Zero");
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyValue(bus->channel(i), kFrameCount / 2, 0);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyValue(bus->channel(i) + kFrameCount / 2,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                kFrameCount - kFrameCount / 2, i + 1);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill the bus with dummy data.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < bus->channels(); ++i)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Zero the last half of the frames.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->ZeroFramesPartial(kFrameCount / 2, kFrameCount - kFrameCount / 2);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < bus->channels(); ++i) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("Last Half Zero");
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyValue(bus->channel(i) + kFrameCount / 2,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                kFrameCount - kFrameCount / 2, 0);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyValue(bus->channel(i), kFrameCount / 2, i + 1);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill the bus with dummy data.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < bus->channels(); ++i)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::fill(bus->channel(i), bus->channel(i) + bus->frames(), i + 1);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Zero all the frames of each channel.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->Zero();
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < bus->channels(); ++i) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("All Zero");
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyValue(bus->channel(i), bus->frames(), 0);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Each test vector represents two channels of data in the following arbitrary
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// layout: <min, zero, max, min, max / 2, min / 2, zero, max, zero, zero>.
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const int kTestVectorSize = 10;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const uint8 kTestVectorUint8[kTestVectorSize] = {
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    0, -kint8min, kuint8max, 0, kint8max / 2 + 128, kint8min / 2 + 128,
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    -kint8min, kuint8max, -kint8min, -kint8min };
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int16 kTestVectorInt16[kTestVectorSize] = {
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    kint16min, 0, kint16max, kint16min, kint16max / 2, kint16min / 2,
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    0, kint16max, 0, 0 };
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int32 kTestVectorInt32[kTestVectorSize] = {
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    kint32min, 0, kint32max, kint32min, kint32max / 2, kint32min / 2,
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    0, kint32max, 0, 0 };
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Expected results.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kTestVectorFrames = kTestVectorSize / 2;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const float kTestVectorResult[][kTestVectorFrames] = {
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { -1, 1, 0.5, 0, 0 }, { 0, -1, -0.5, 1, 0 }};
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kTestVectorChannels = arraysize(kTestVectorResult);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify FromInterleaved() deinterleaves audio in supported formats correctly.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioBusTest, FromInterleaved) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus = AudioBus::Create(
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kTestVectorChannels, kTestVectorFrames);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> expected = AudioBus::Create(
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kTestVectorChannels, kTestVectorFrames);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int ch = 0; ch < kTestVectorChannels; ++ch) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(expected->channel(ch), kTestVectorResult[ch],
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           kTestVectorFrames * sizeof(*expected->channel(ch)));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("uint8");
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus->Zero();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus->FromInterleaved(
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kTestVectorUint8, kTestVectorFrames, sizeof(*kTestVectorUint8));
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Biased uint8 calculations have poor precision, so the epsilon here is
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // slightly more permissive than int16 and int32 calculations.
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VerifyBusWithEpsilon(bus.get(), expected.get(), 1.0f / (kuint8max - 1));
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("int16");
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus->Zero();
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus->FromInterleaved(
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kTestVectorInt16, kTestVectorFrames, sizeof(*kTestVectorInt16));
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VerifyBusWithEpsilon(bus.get(), expected.get(), 1.0f / (kuint16max + 1.0f));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("int32");
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus->Zero();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus->FromInterleaved(
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kTestVectorInt32, kTestVectorFrames, sizeof(*kTestVectorInt32));
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VerifyBusWithEpsilon(bus.get(), expected.get(), 1.0f / (kuint32max + 1.0f));
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify FromInterleavedPartial() deinterleaves audio correctly.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioBusTest, FromInterleavedPartial) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only deinterleave the middle two frames in each channel.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kPartialStart = 1;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kPartialFrames = 2;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrames);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus = AudioBus::Create(
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kTestVectorChannels, kTestVectorFrames);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> expected = AudioBus::Create(
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kTestVectorChannels, kTestVectorFrames);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expected->Zero();
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int ch = 0; ch < kTestVectorChannels; ++ch) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(expected->channel(ch) + kPartialStart,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           kTestVectorResult[ch] + kPartialStart,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           kPartialFrames * sizeof(*expected->channel(ch)));
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->Zero();
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bus->FromInterleavedPartial(
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kTestVectorInt32 + kPartialStart * bus->channels(), kPartialStart,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kPartialFrames, sizeof(*kTestVectorInt32));
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyBus(bus.get(), expected.get());
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify ToInterleaved() interleaves audio in suported formats correctly.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(AudioBusTest, ToInterleaved) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<AudioBus> bus = AudioBus::Create(
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kTestVectorChannels, kTestVectorFrames);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill the bus with our test vector.
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (int ch = 0; ch < bus->channels(); ++ch) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(bus->channel(ch), kTestVectorResult[ch],
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           kTestVectorFrames * sizeof(*bus->channel(ch)));
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("uint8");
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8 test_array[arraysize(kTestVectorUint8)];
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorUint8), test_array);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(memcmp(
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        test_array, kTestVectorUint8, sizeof(kTestVectorUint8)), 0);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("int16");
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int16 test_array[arraysize(kTestVectorInt16)];
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt16), test_array);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(memcmp(
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        test_array, kTestVectorInt16, sizeof(kTestVectorInt16)), 0);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SCOPED_TRACE("int32");
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 test_array[arraysize(kTestVectorInt32)];
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bus->ToInterleaved(bus->frames(), sizeof(*kTestVectorInt32), test_array);
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Some compilers get better precision than others on the half-max test, so
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // let the test pass with an off by one check on the half-max.
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int32 fixed_test_array[arraysize(kTestVectorInt32)];
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    memcpy(fixed_test_array, kTestVectorInt32, sizeof(kTestVectorInt32));
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_EQ(fixed_test_array[4], kint32max / 2);
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    fixed_test_array[4]++;
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ASSERT_TRUE(
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       memcmp(test_array, kTestVectorInt32, sizeof(kTestVectorInt32)) == 0 ||
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       memcmp(test_array, fixed_test_array, sizeof(fixed_test_array)) == 0);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Verify ToInterleavedPartial() interleaves audio correctly.
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(AudioBusTest, ToInterleavedPartial) {
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only interleave the middle two frames in each channel.
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const int kPartialStart = 1;
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const int kPartialFrames = 2;
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_LE(kPartialStart + kPartialFrames, kTestVectorFrames);
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<AudioBus> expected = AudioBus::Create(
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kTestVectorChannels, kTestVectorFrames);
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int ch = 0; ch < kTestVectorChannels; ++ch) {
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    memcpy(expected->channel(ch), kTestVectorResult[ch],
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kTestVectorFrames * sizeof(*expected->channel(ch)));
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int16 test_array[arraysize(kTestVectorInt16)];
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expected->ToInterleavedPartial(
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kPartialStart, kPartialFrames, sizeof(*kTestVectorInt16), test_array);
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(memcmp(
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      test_array, kTestVectorInt16 + kPartialStart * kTestVectorChannels,
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kPartialFrames * sizeof(*kTestVectorInt16) * kTestVectorChannels), 0);
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(AudioBusTest, Scale) {
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<AudioBus> bus = AudioBus::Create(kChannels, kFrameCount);
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Fill the bus with dummy data.
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static const float kFillValue = 1;
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (int i = 0; i < bus->channels(); ++i)
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::fill(bus->channel(i), bus->channel(i) + bus->frames(), kFillValue);
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Adjust by an invalid volume and ensure volume is unchanged.
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bus->Scale(-1);
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (int i = 0; i < bus->channels(); ++i) {
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SCOPED_TRACE("Invalid Scale");
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VerifyValue(bus->channel(i), bus->frames(), kFillValue);
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Verify correct volume adjustment.
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  static const float kVolume = 0.5;
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bus->Scale(kVolume);
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (int i = 0; i < bus->channels(); ++i) {
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SCOPED_TRACE("Half Scale");
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VerifyValue(bus->channel(i), bus->frames(), kFillValue * kVolume);
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Verify zero volume case.
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bus->Scale(0);
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (int i = 0; i < bus->channels(); ++i) {
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SCOPED_TRACE("Zero Scale");
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VerifyValue(bus->channel(i), bus->frames(), 0);
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Benchmark the FromInterleaved() and ToInterleaved() methods.
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(AudioBusTest, DISABLED_InterleaveBench) {
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<AudioBus> bus = AudioBus::Create(2, 48000 * 120);
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int frame_size = bus->frames() * bus->channels();
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FakeAudioRenderCallback callback(0.2);
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Render(bus.get(), 0);
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  {
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SCOPED_TRACE("uint8");
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<uint8> interleaved(new uint8[frame_size]);
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const int byte_size = sizeof(*interleaved);
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::TimeTicks start = base::TimeTicks::HighResNow();
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bus->ToInterleaved(bus->frames(), byte_size, interleaved.get());
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    double total_time_ms =
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        (base::TimeTicks::HighResNow() - start).InMillisecondsF();
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    printf("ToInterleaved uint8 took %.2fms.\n", total_time_ms);
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    start = base::TimeTicks::HighResNow();
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bus->FromInterleaved(interleaved.get(), bus->frames(), byte_size);
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    total_time_ms = (base::TimeTicks::HighResNow() - start).InMillisecondsF();
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    printf("FromInterleaved uint8 took %.2fms.\n", total_time_ms);
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  {
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SCOPED_TRACE("int16");
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<int16> interleaved(new int16[frame_size]);
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const int byte_size = sizeof(*interleaved);
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::TimeTicks start = base::TimeTicks::HighResNow();
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bus->ToInterleaved(bus->frames(), byte_size, interleaved.get());
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    double total_time_ms =
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        (base::TimeTicks::HighResNow() - start).InMillisecondsF();
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    printf("ToInterleaved int16 took %.2fms.\n", total_time_ms);
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    start = base::TimeTicks::HighResNow();
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bus->FromInterleaved(interleaved.get(), bus->frames(), byte_size);
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    total_time_ms = (base::TimeTicks::HighResNow() - start).InMillisecondsF();
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    printf("FromInterleaved int16 took %.2fms.\n", total_time_ms);
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  {
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SCOPED_TRACE("int32");
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<int32> interleaved(new int32[frame_size]);
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const int byte_size = sizeof(*interleaved);
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::TimeTicks start = base::TimeTicks::HighResNow();
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bus->ToInterleaved(bus->frames(), byte_size, interleaved.get());
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    double total_time_ms =
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        (base::TimeTicks::HighResNow() - start).InMillisecondsF();
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    printf("ToInterleaved int32 took %.2fms.\n", total_time_ms);
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    start = base::TimeTicks::HighResNow();
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bus->FromInterleaved(interleaved.get(), bus->frames(), byte_size);
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    total_time_ms = (base::TimeTicks::HighResNow() - start).InMillisecondsF();
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    printf("FromInterleaved int32 took %.2fms.\n", total_time_ms);
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
473