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) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MSVC++ requires this to be set before any other includes to get M_SQRT1_2. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _USE_MATH_DEFINES 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cmath> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "media/audio/audio_parameters.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/audio_bus.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/channel_mixer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Number of frames to test with. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum { kFrames = 16 }; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test all possible layout conversions can be constructed and mixed. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(ChannelMixerTest, ConstructAllPossibleLayouts) { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ChannelLayout input_layout = CHANNEL_LAYOUT_MONO; 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) input_layout <= CHANNEL_LAYOUT_MAX; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_layout = static_cast<ChannelLayout>(input_layout + 1)) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ChannelLayout output_layout = CHANNEL_LAYOUT_MONO; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_layout < CHANNEL_LAYOUT_STEREO_DOWNMIX; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_layout = static_cast<ChannelLayout>(output_layout + 1)) { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // DISCRETE can't be tested here based on the current approach. 3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC is not mixable. 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (input_layout == CHANNEL_LAYOUT_DISCRETE || 3223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) input_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC || 3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) output_layout == CHANNEL_LAYOUT_DISCRETE || 3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) output_layout == CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SCOPED_TRACE(base::StringPrintf( 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Input Layout: %d, Output Layout: %d", input_layout, output_layout)); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelMixer mixer(input_layout, output_layout); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioBus> input_bus = AudioBus::Create( 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelLayoutToChannelCount(input_layout), kFrames); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioBus> output_bus = AudioBus::Create( 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelLayoutToChannelCount(output_layout), kFrames); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int ch = 0; ch < input_bus->channels(); ++ch) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::fill(input_bus->channel(ch), input_bus->channel(ch) + kFrames, 1); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mixer.Transform(input_bus.get(), output_bus.get()); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ChannelMixerTestData { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelMixerTestData(ChannelLayout input_layout, ChannelLayout output_layout, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float* channel_values, int num_channel_values, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float scale) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : input_layout(input_layout), 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_layout(output_layout), 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_values(channel_values), 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_channel_values(num_channel_values), 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scale(scale) { 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) input_channels = ChannelLayoutToChannelCount(input_layout); 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output_channels = ChannelLayoutToChannelCount(output_layout); 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ChannelMixerTestData(ChannelLayout input_layout, int input_channels, 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ChannelLayout output_layout, int output_channels, 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) float* channel_values, int num_channel_values) 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : input_layout(input_layout), 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) input_channels(input_channels), 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output_layout(output_layout), 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output_channels(output_channels), 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) channel_values(channel_values), 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) num_channel_values(num_channel_values), 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scale(1.0f) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string DebugString() const { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return base::StringPrintf( 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Input Layout: %d, Output Layout %d, Scale: %f", input_layout, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_layout, scale); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelLayout input_layout; 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int input_channels; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelLayout output_layout; 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int output_channels; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float* channel_values; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_channel_values; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float scale; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::ostream& operator<<(std::ostream& os, const ChannelMixerTestData& data) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return os << data.DebugString(); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChannelMixerTest : public testing::TestWithParam<ChannelMixerTestData> {}; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verify channels are mixed and scaled correctly. The test only works if all 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// output channels have the same value. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(ChannelMixerTest, Mixing) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelLayout input_layout = GetParam().input_layout; 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int input_channels = GetParam().input_channels; 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<AudioBus> input_bus = AudioBus::Create(input_channels, kFrames); 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AudioParameters input_audio(AudioParameters::AUDIO_PCM_LINEAR, 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) input_layout, 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) input_layout == CHANNEL_LAYOUT_DISCRETE ? 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) input_channels : 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ChannelLayoutToChannelCount(input_layout), 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AudioParameters::kAudioCDSampleRate, 16, 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kFrames, 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters::NO_EFFECTS); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ChannelLayout output_layout = GetParam().output_layout; 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int output_channels = GetParam().output_channels; 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<AudioBus> output_bus = AudioBus::Create(output_channels, kFrames); 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AudioParameters output_audio(AudioParameters::AUDIO_PCM_LINEAR, 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output_layout, 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) output_layout == CHANNEL_LAYOUT_DISCRETE ? 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci output_channels : 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ChannelLayoutToChannelCount(output_layout), 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) AudioParameters::kAudioCDSampleRate, 16, 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kFrames, 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AudioParameters::NO_EFFECTS); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const float* channel_values = GetParam().channel_values; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(input_bus->channels(), GetParam().num_channel_values); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float expected_value = 0; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float scale = GetParam().scale; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int ch = 0; ch < input_bus->channels(); ++ch) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::fill(input_bus->channel(ch), input_bus->channel(ch) + kFrames, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_values[ch]); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expected_value += channel_values[ch] * scale; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ChannelMixer mixer(input_audio, output_audio); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mixer.Transform(input_bus.get(), output_bus.get()); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Validate the output channel 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (input_layout != CHANNEL_LAYOUT_DISCRETE) { 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int ch = 0; ch < output_bus->channels(); ++ch) { 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int frame = 0; frame < output_bus->frames(); ++frame) { 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_FLOAT_EQ(output_bus->channel(ch)[frame], expected_value); 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Processing discrete mixing. If there is a matching input channel, 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // then the output channel should be set. If no input channel, 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // output channel should be 0 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int ch = 0; ch < output_bus->channels(); ++ch) { 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) expected_value = (ch < input_channels) ? channel_values[ch] : 0; 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int frame = 0; frame < output_bus->frames(); ++frame) { 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_FLOAT_EQ(output_bus->channel(ch)[frame], expected_value); 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static float kStereoToMonoValues[] = { 0.5f, 0.75f }; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static float kMonoToStereoValues[] = { 0.5f }; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Zero the center channel since it will be mixed at scale 1 vs M_SQRT1_2. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static float kFiveOneToMonoValues[] = { 0.1f, 0.2f, 0.0f, 0.4f, 0.5f, 0.6f }; 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static float kFiveDiscreteValues[] = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f }; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Run through basic sanity tests for some common conversions. 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(ChannelMixerTest, ChannelMixerTest, testing::Values( 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelMixerTestData(CHANNEL_LAYOUT_STEREO, CHANNEL_LAYOUT_MONO, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kStereoToMonoValues, arraysize(kStereoToMonoValues), 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0.5f), 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelMixerTestData(CHANNEL_LAYOUT_MONO, CHANNEL_LAYOUT_STEREO, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMonoToStereoValues, arraysize(kMonoToStereoValues), 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1.0f), 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChannelMixerTestData(CHANNEL_LAYOUT_5_1, CHANNEL_LAYOUT_MONO, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFiveOneToMonoValues, arraysize(kFiveOneToMonoValues), 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static_cast<float>(M_SQRT1_2)), 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ChannelMixerTestData(CHANNEL_LAYOUT_DISCRETE, 2, 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHANNEL_LAYOUT_DISCRETE, 2, 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kStereoToMonoValues, arraysize(kStereoToMonoValues)), 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ChannelMixerTestData(CHANNEL_LAYOUT_DISCRETE, 2, 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHANNEL_LAYOUT_DISCRETE, 5, 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kStereoToMonoValues, arraysize(kStereoToMonoValues)), 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ChannelMixerTestData(CHANNEL_LAYOUT_DISCRETE, 5, 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CHANNEL_LAYOUT_DISCRETE, 2, 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kFiveDiscreteValues, arraysize(kFiveDiscreteValues)) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace media 189