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