Bug 1890793: Assert CallArgs::newTarget is not gray. r=spidermonkey-reviewers,sfink...
[gecko.git] / dom / media / AudioConfig.cpp
blobb23d96f8fa4db35968c7bb84a427a43e66bca11c
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"
8 #include "nsString.h"
9 #include <array>
11 namespace mozilla {
13 using ChannelLayout = AudioConfig::ChannelLayout;
15 /**
16 * AudioConfig::ChannelLayout
20 SMPTE channel layout (also known as wave order)
21 DUAL-MONO L R
22 DUAL-MONO-LFE L R LFE
23 MONO M
24 MONO-LFE M LFE
25 STEREO L R
26 STEREO-LFE L R LFE
27 3F L R C
28 3F-LFE L R C LFE
29 2F1 L R S
30 2F1-LFE L R LFE S
31 3F1 L R C S
32 3F1-LFE L R C LFE S
33 2F2 L R LS RS
34 2F2-LFE L R LFE LS RS
35 3F2 L R C LS RS
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;
44 if (mValid) {
45 mChannelMap = Map();
46 mValid = mChannelMap > 0;
50 auto AudioConfig::ChannelLayout::Map() const -> ChannelMap {
51 if (mChannelMap != UNKNOWN_MAP) {
52 return mChannelMap;
54 if (mChannels.Length() > MAX_CHANNELS) {
55 return UNKNOWN_MAP;
57 ChannelMap map = UNKNOWN_MAP;
58 for (size_t i = 0; i < mChannels.Length(); i++) {
59 if (uint32_t(mChannels[i]) > sizeof(ChannelMap) * 8) {
60 return UNKNOWN_MAP;
62 ChannelMap mask = 1 << mChannels[i];
63 if (mChannels[i] == CHANNEL_INVALID || (mChannelMap & mask)) {
64 // Invalid configuration.
65 return UNKNOWN_MAP;
67 map |= mask;
69 return map;
72 const AudioConfig::Channel*
73 AudioConfig::ChannelLayout::DefaultLayoutForChannels(uint32_t aChannels) const {
74 switch (aChannels) {
75 case 1: // MONO
77 static const Channel config[] = {CHANNEL_FRONT_CENTER};
78 return config;
80 case 2: // STEREO
82 static const Channel config[] = {CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT};
83 return config;
85 case 3: // 3F
87 static const Channel config[] = {CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
88 CHANNEL_FRONT_CENTER};
89 return config;
91 case 4: // QUAD
93 static const Channel config[] = {CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
94 CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT};
95 return config;
97 case 5: // 3F2
99 static const Channel config[] = {CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
100 CHANNEL_FRONT_CENTER, CHANNEL_SIDE_LEFT,
101 CHANNEL_SIDE_RIGHT};
102 return config;
104 case 6: // 3F2-LFE
106 static const Channel config[] = {
107 CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER,
108 CHANNEL_LFE, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT};
109 return config;
111 case 7: // 3F3R-LFE
113 static const Channel config[] = {
114 CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER,
115 CHANNEL_LFE, CHANNEL_BACK_CENTER, CHANNEL_SIDE_LEFT,
116 CHANNEL_SIDE_RIGHT};
117 return config;
119 case 8: // 3F4-LFE
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};
125 return config;
127 default:
128 return nullptr;
132 /* static */ AudioConfig::ChannelLayout
133 AudioConfig::ChannelLayout::SMPTEDefault(const ChannelLayout& aChannelLayout) {
134 if (!aChannelLayout.IsValid()) {
135 return aChannelLayout;
137 return SMPTEDefault(aChannelLayout.Map());
140 /* static */
141 ChannelLayout AudioConfig::ChannelLayout::SMPTEDefault(ChannelMap aMap) {
142 // First handle the most common cases.
143 switch (aMap) {
144 case LMONO_MAP:
145 return ChannelLayout{CHANNEL_FRONT_CENTER};
146 case LSTEREO_MAP:
147 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT};
148 case L3F_MAP:
149 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
150 CHANNEL_FRONT_CENTER};
151 case L3F_LFE_MAP:
152 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
153 CHANNEL_FRONT_CENTER, CHANNEL_LFE};
154 case L2F1_MAP:
155 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
156 CHANNEL_BACK_CENTER};
157 case L2F1_LFE_MAP:
158 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_LFE,
159 CHANNEL_BACK_CENTER};
160 case L3F1_MAP:
161 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
162 CHANNEL_FRONT_CENTER, CHANNEL_BACK_CENTER};
163 case L3F1_LFE_MAP:
164 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
165 CHANNEL_FRONT_CENTER, CHANNEL_LFE,
166 CHANNEL_BACK_CENTER};
167 case L2F2_MAP:
168 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
169 CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT};
170 case L2F2_LFE_MAP:
171 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_LFE,
172 CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT};
173 case LQUAD_MAP:
174 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
175 CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT};
176 case LQUAD_LFE_MAP:
177 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_LFE,
178 CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT};
179 case L3F2_MAP:
180 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
181 CHANNEL_FRONT_CENTER, CHANNEL_SIDE_LEFT,
182 CHANNEL_SIDE_RIGHT};
183 case L3F2_LFE_MAP:
184 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
185 CHANNEL_FRONT_CENTER, CHANNEL_LFE,
186 CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT};
187 case L3F2_BACK_MAP:
188 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
189 CHANNEL_FRONT_CENTER, CHANNEL_BACK_LEFT,
190 CHANNEL_BACK_RIGHT};
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};
195 case L3F3R_LFE_MAP:
196 return ChannelLayout{CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT,
197 CHANNEL_FRONT_CENTER, CHANNEL_LFE,
198 CHANNEL_BACK_CENTER, CHANNEL_SIDE_LEFT,
199 CHANNEL_SIDE_RIGHT};
200 case L3F4_LFE_MAP:
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};
205 default:
206 break;
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;
214 uint32_t i = 0;
215 while (aMap) {
216 if (aMap & 1) {
217 channels++;
218 if (channels > MAX_CHANNELS) {
219 return ChannelLayout();
221 layout.AppendElement(static_cast<Channel>(i));
223 aMap >>= 1;
224 i++;
226 return ChannelLayout(channels, layout.Elements());
229 nsCString AudioConfig::ChannelLayout::ChannelMapToString(
230 const ChannelMap aChannelMap) {
231 nsCString rv;
233 constexpr const std::array CHANNEL_NAME = {"Front left",
234 "Front right",
235 "Front center",
236 "Low frequency",
237 "Back left",
238 "Back right",
239 "Front left of center",
240 "Front right of center",
241 "Back center",
242 "Side left",
243 "Side right",
244 "Top center",
245 "Top front left",
246 "Top front center",
247 "Top front right",
248 "Top back left",
249 "Top back center",
250 "Top back right"};
252 rv.AppendPrintf("0x%08x", aChannelMap);
253 rv.Append("[");
254 bool empty = true;
255 for (size_t i = 0; i < CHANNEL_NAME.size(); i++) {
256 if (aChannelMap & (1 << i)) {
257 if (!empty) {
258 rv.Append("|");
260 empty = false;
261 rv.Append(CHANNEL_NAME[i]);
264 rv.Append("]");
266 return rv;
269 bool AudioConfig::ChannelLayout::MappingTable(const ChannelLayout& aOther,
270 nsTArray<uint8_t>* aMap) const {
271 if (!IsValid() || !aOther.IsValid() || Map() != aOther.Map()) {
272 if (aMap) {
273 aMap->SetLength(0);
275 return false;
277 if (!aMap) {
278 return true;
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]) {
284 (*aMap)[j] = i;
285 break;
289 return true;
293 * AudioConfig::ChannelConfig
296 /* static */ const char* AudioConfig::FormatToString(
297 AudioConfig::SampleFormat aFormat) {
298 switch (aFormat) {
299 case FORMAT_U8:
300 return "unsigned 8 bit";
301 case FORMAT_S16:
302 return "signed 16 bit";
303 case FORMAT_S24:
304 return "signed 24 bit MSB";
305 case FORMAT_S24LSB:
306 return "signed 24 bit LSB";
307 case FORMAT_S32:
308 return "signed 32 bit";
309 case FORMAT_FLT:
310 return "32 bit floating point";
311 case FORMAT_NONE:
312 return "none";
313 default:
314 return "unknown";
317 /* static */
318 uint32_t AudioConfig::SampleSize(AudioConfig::SampleFormat aFormat) {
319 switch (aFormat) {
320 case FORMAT_U8:
321 return 1;
322 case FORMAT_S16:
323 return 2;
324 case FORMAT_S24:
325 [[fallthrough]];
326 case FORMAT_S24LSB:
327 [[fallthrough]];
328 case FORMAT_S32:
329 [[fallthrough]];
330 case FORMAT_FLT:
331 return 4;
332 case FORMAT_NONE:
333 default:
334 return 0;
338 /* static */
339 uint32_t AudioConfig::FormatToBits(AudioConfig::SampleFormat aFormat) {
340 switch (aFormat) {
341 case FORMAT_U8:
342 return 8;
343 case FORMAT_S16:
344 return 16;
345 case FORMAT_S24LSB:
346 [[fallthrough]];
347 case FORMAT_S24:
348 return 24;
349 case FORMAT_S32:
350 [[fallthrough]];
351 case FORMAT_FLT:
352 return 32;
353 case FORMAT_NONE:
354 [[fallthrough]];
355 default:
356 return 0;
360 AudioConfig::AudioConfig(const ChannelLayout& aChannelLayout, uint32_t aRate,
361 AudioConfig::SampleFormat aFormat, bool aInterleaved)
362 : mChannelLayout(aChannelLayout),
363 mChannels(aChannelLayout.Count()),
364 mRate(aRate),
365 mFormat(aFormat),
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),
373 mRate(aRate),
374 mFormat(aFormat),
375 mInterleaved(aInterleaved) {}
377 AudioConfig::AudioConfig(uint32_t aChannels, uint32_t aRate,
378 AudioConfig::SampleFormat aFormat, bool aInterleaved)
379 : mChannelLayout(aChannels),
380 mChannels(aChannels),
381 mRate(aRate),
382 mFormat(aFormat),
383 mInterleaved(aInterleaved) {}
385 } // namespace mozilla