1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "AudioConfig.h"
13 using ChannelLayout
= AudioConfig::ChannelLayout
;
16 * AudioConfig::ChannelLayout
20 SMPTE channel layout (also known as wave order)
36 3F2-LFE L R C LFE LS RS
37 3F3R-LFE L R C LFE BC LS RS
38 3F4-LFE L R C LFE Rls Rrs LS RS
41 void AudioConfig::ChannelLayout::UpdateChannelMap() {
42 mValid
= mChannels
.Length() <= MAX_CHANNELS
;
43 mChannelMap
= UNKNOWN_MAP
;
46 mValid
= mChannelMap
> 0;
50 auto AudioConfig::ChannelLayout::Map() const -> ChannelMap
{
51 if (mChannelMap
!= UNKNOWN_MAP
) {
54 if (mChannels
.Length() > MAX_CHANNELS
) {
57 ChannelMap map
= UNKNOWN_MAP
;
58 for (size_t i
= 0; i
< mChannels
.Length(); i
++) {
59 if (uint32_t(mChannels
[i
]) > sizeof(ChannelMap
) * 8) {
62 ChannelMap mask
= 1 << mChannels
[i
];
63 if (mChannels
[i
] == CHANNEL_INVALID
|| (mChannelMap
& mask
)) {
64 // Invalid configuration.
72 const AudioConfig::Channel
*
73 AudioConfig::ChannelLayout::DefaultLayoutForChannels(uint32_t aChannels
) const {
77 static const Channel config
[] = {CHANNEL_FRONT_CENTER
};
82 static const Channel config
[] = {CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
};
87 static const Channel config
[] = {CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
88 CHANNEL_FRONT_CENTER
};
93 static const Channel config
[] = {CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
94 CHANNEL_BACK_LEFT
, CHANNEL_BACK_RIGHT
};
99 static const Channel config
[] = {CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
100 CHANNEL_FRONT_CENTER
, CHANNEL_SIDE_LEFT
,
106 static const Channel config
[] = {
107 CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
, CHANNEL_FRONT_CENTER
,
108 CHANNEL_LFE
, CHANNEL_SIDE_LEFT
, CHANNEL_SIDE_RIGHT
};
113 static const Channel config
[] = {
114 CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
, CHANNEL_FRONT_CENTER
,
115 CHANNEL_LFE
, CHANNEL_BACK_CENTER
, CHANNEL_SIDE_LEFT
,
121 static const Channel config
[] = {
122 CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
, CHANNEL_FRONT_CENTER
,
123 CHANNEL_LFE
, CHANNEL_BACK_LEFT
, CHANNEL_BACK_RIGHT
,
124 CHANNEL_SIDE_LEFT
, CHANNEL_SIDE_RIGHT
};
132 /* static */ AudioConfig::ChannelLayout
133 AudioConfig::ChannelLayout::SMPTEDefault(const ChannelLayout
& aChannelLayout
) {
134 if (!aChannelLayout
.IsValid()) {
135 return aChannelLayout
;
137 return SMPTEDefault(aChannelLayout
.Map());
141 ChannelLayout
AudioConfig::ChannelLayout::SMPTEDefault(ChannelMap aMap
) {
142 // First handle the most common cases.
145 return ChannelLayout
{CHANNEL_FRONT_CENTER
};
147 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
};
149 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
150 CHANNEL_FRONT_CENTER
};
152 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
153 CHANNEL_FRONT_CENTER
, CHANNEL_LFE
};
155 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
156 CHANNEL_BACK_CENTER
};
158 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
, CHANNEL_LFE
,
159 CHANNEL_BACK_CENTER
};
161 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
162 CHANNEL_FRONT_CENTER
, CHANNEL_BACK_CENTER
};
164 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
165 CHANNEL_FRONT_CENTER
, CHANNEL_LFE
,
166 CHANNEL_BACK_CENTER
};
168 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
169 CHANNEL_SIDE_LEFT
, CHANNEL_SIDE_RIGHT
};
171 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
, CHANNEL_LFE
,
172 CHANNEL_SIDE_LEFT
, CHANNEL_SIDE_RIGHT
};
174 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
175 CHANNEL_BACK_LEFT
, CHANNEL_BACK_RIGHT
};
177 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
, CHANNEL_LFE
,
178 CHANNEL_BACK_LEFT
, CHANNEL_BACK_RIGHT
};
180 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
181 CHANNEL_FRONT_CENTER
, CHANNEL_SIDE_LEFT
,
184 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
185 CHANNEL_FRONT_CENTER
, CHANNEL_LFE
,
186 CHANNEL_SIDE_LEFT
, CHANNEL_SIDE_RIGHT
};
188 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
189 CHANNEL_FRONT_CENTER
, CHANNEL_BACK_LEFT
,
191 case L3F2_BACK_LFE_MAP
:
192 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
193 CHANNEL_FRONT_CENTER
, CHANNEL_LFE
,
194 CHANNEL_BACK_LEFT
, CHANNEL_BACK_RIGHT
};
196 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
197 CHANNEL_FRONT_CENTER
, CHANNEL_LFE
,
198 CHANNEL_BACK_CENTER
, CHANNEL_SIDE_LEFT
,
201 return ChannelLayout
{CHANNEL_FRONT_LEFT
, CHANNEL_FRONT_RIGHT
,
202 CHANNEL_FRONT_CENTER
, CHANNEL_LFE
,
203 CHANNEL_BACK_LEFT
, CHANNEL_BACK_RIGHT
,
204 CHANNEL_SIDE_LEFT
, CHANNEL_SIDE_RIGHT
};
209 static_assert(MAX_CHANNELS
<= sizeof(ChannelMap
) * 8,
210 "Must be able to fit channels on bit mask");
211 AutoTArray
<Channel
, MAX_CHANNELS
> layout
;
212 uint32_t channels
= 0;
218 if (channels
> MAX_CHANNELS
) {
219 return ChannelLayout();
221 layout
.AppendElement(static_cast<Channel
>(i
));
226 return ChannelLayout(channels
, layout
.Elements());
229 nsCString
AudioConfig::ChannelLayout::ChannelMapToString(
230 const ChannelMap aChannelMap
) {
233 constexpr const std::array CHANNEL_NAME
= {"Front left",
239 "Front left of center",
240 "Front right of center",
252 rv
.AppendPrintf("0x%08x", aChannelMap
);
255 for (size_t i
= 0; i
< CHANNEL_NAME
.size(); i
++) {
256 if (aChannelMap
& (1 << i
)) {
261 rv
.Append(CHANNEL_NAME
[i
]);
269 bool AudioConfig::ChannelLayout::MappingTable(const ChannelLayout
& aOther
,
270 nsTArray
<uint8_t>* aMap
) const {
271 if (!IsValid() || !aOther
.IsValid() || Map() != aOther
.Map()) {
280 aMap
->SetLength(Count());
281 for (uint32_t i
= 0; i
< Count(); i
++) {
282 for (uint32_t j
= 0; j
< Count(); j
++) {
283 if (aOther
[j
] == mChannels
[i
]) {
293 * AudioConfig::ChannelConfig
296 /* static */ const char* AudioConfig::FormatToString(
297 AudioConfig::SampleFormat aFormat
) {
300 return "unsigned 8 bit";
302 return "signed 16 bit";
304 return "signed 24 bit MSB";
306 return "signed 24 bit LSB";
308 return "signed 32 bit";
310 return "32 bit floating point";
318 uint32_t AudioConfig::SampleSize(AudioConfig::SampleFormat aFormat
) {
339 uint32_t AudioConfig::FormatToBits(AudioConfig::SampleFormat aFormat
) {
360 AudioConfig::AudioConfig(const ChannelLayout
& aChannelLayout
, uint32_t aRate
,
361 AudioConfig::SampleFormat aFormat
, bool aInterleaved
)
362 : mChannelLayout(aChannelLayout
),
363 mChannels(aChannelLayout
.Count()),
366 mInterleaved(aInterleaved
) {}
368 AudioConfig::AudioConfig(const ChannelLayout
& aChannelLayout
,
369 uint32_t aChannels
, uint32_t aRate
,
370 AudioConfig::SampleFormat aFormat
, bool aInterleaved
)
371 : mChannelLayout(aChannelLayout
),
372 mChannels(aChannels
),
375 mInterleaved(aInterleaved
) {}
377 AudioConfig::AudioConfig(uint32_t aChannels
, uint32_t aRate
,
378 AudioConfig::SampleFormat aFormat
, bool aInterleaved
)
379 : mChannelLayout(aChannels
),
380 mChannels(aChannels
),
383 mInterleaved(aInterleaved
) {}
385 } // namespace mozilla