/src/mozilla-central/dom/media/AudioConfig.cpp
Line | Count | Source (jump to first uncovered line) |
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/. */ |
6 | | |
7 | | #include "AudioConfig.h" |
8 | | |
9 | | namespace mozilla { |
10 | | |
11 | | typedef AudioConfig::ChannelLayout ChannelLayout; |
12 | | |
13 | | /** |
14 | | * AudioConfig::ChannelLayout |
15 | | */ |
16 | | |
17 | | /* |
18 | | SMPTE channel layout (also known as wave order) |
19 | | DUAL-MONO L R |
20 | | DUAL-MONO-LFE L R LFE |
21 | | MONO M |
22 | | MONO-LFE M LFE |
23 | | STEREO L R |
24 | | STEREO-LFE L R LFE |
25 | | 3F L R C |
26 | | 3F-LFE L R C LFE |
27 | | 2F1 L R S |
28 | | 2F1-LFE L R LFE S |
29 | | 3F1 L R C S |
30 | | 3F1-LFE L R C LFE S |
31 | | 2F2 L R LS RS |
32 | | 2F2-LFE L R LFE LS RS |
33 | | 3F2 L R C LS RS |
34 | | 3F2-LFE L R C LFE LS RS |
35 | | 3F3R-LFE L R C LFE BC LS RS |
36 | | 3F4-LFE L R C LFE Rls Rrs LS RS |
37 | | */ |
38 | | |
39 | | void |
40 | | AudioConfig::ChannelLayout::UpdateChannelMap() |
41 | 0 | { |
42 | 0 | mValid = mChannels.Length() <= MAX_CHANNELS; |
43 | 0 | mChannelMap = UNKNOWN_MAP; |
44 | 0 | if (mValid) { |
45 | 0 | mChannelMap = Map(); |
46 | 0 | mValid = mChannelMap > 0; |
47 | 0 | } |
48 | 0 | } |
49 | | |
50 | | auto |
51 | | AudioConfig::ChannelLayout::Map() const -> ChannelMap |
52 | 0 | { |
53 | 0 | if (mChannelMap != UNKNOWN_MAP) { |
54 | 0 | return mChannelMap; |
55 | 0 | } |
56 | 0 | if (mChannels.Length() > MAX_CHANNELS) { |
57 | 0 | return UNKNOWN_MAP; |
58 | 0 | } |
59 | 0 | ChannelMap map = UNKNOWN_MAP; |
60 | 0 | for (size_t i = 0; i < mChannels.Length(); i++) { |
61 | 0 | if (uint32_t(mChannels[i]) > sizeof(ChannelMap) * 8) { |
62 | 0 | return UNKNOWN_MAP; |
63 | 0 | } |
64 | 0 | ChannelMap mask = 1 << mChannels[i]; |
65 | 0 | if (mChannels[i] == CHANNEL_INVALID || (mChannelMap & mask)) { |
66 | 0 | // Invalid configuration. |
67 | 0 | return UNKNOWN_MAP; |
68 | 0 | } |
69 | 0 | map |= mask; |
70 | 0 | } |
71 | 0 | return map; |
72 | 0 | } |
73 | | |
74 | | const AudioConfig::Channel* |
75 | | AudioConfig::ChannelLayout::DefaultLayoutForChannels(uint32_t aChannels) const |
76 | | { |
77 | | switch (aChannels) { |
78 | | case 1: // MONO |
79 | | { |
80 | | static const Channel config[] = { CHANNEL_FRONT_CENTER }; |
81 | | return config; |
82 | | } |
83 | | case 2: // STEREO |
84 | | { |
85 | | static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT }; |
86 | | return config; |
87 | | } |
88 | | case 3: // 3F |
89 | | { |
90 | | static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER }; |
91 | | return config; |
92 | | } |
93 | | case 4: // QUAD |
94 | | { |
95 | | static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT }; |
96 | | return config; |
97 | | } |
98 | | case 5: // 3F2 |
99 | | { |
100 | | static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT }; |
101 | | return config; |
102 | | } |
103 | | case 6: // 3F2-LFE |
104 | | { |
105 | | static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT }; |
106 | | return config; |
107 | | } |
108 | | case 7: // 3F3R-LFE |
109 | | { |
110 | | static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE, CHANNEL_BACK_CENTER, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT }; |
111 | | return config; |
112 | | } |
113 | | case 8: // 3F4-LFE |
114 | | { |
115 | | static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE, CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT }; |
116 | | return config; |
117 | | } |
118 | | default: |
119 | | return nullptr; |
120 | | } |
121 | | } |
122 | | |
123 | | /* static */ AudioConfig::ChannelLayout |
124 | | AudioConfig::ChannelLayout::SMPTEDefault( |
125 | | const ChannelLayout& aChannelLayout) |
126 | 0 | { |
127 | 0 | if (!aChannelLayout.IsValid()) { |
128 | 0 | return aChannelLayout; |
129 | 0 | } |
130 | 0 | return SMPTEDefault(aChannelLayout.Map()); |
131 | 0 | } |
132 | | |
133 | | /* static */ ChannelLayout |
134 | | AudioConfig::ChannelLayout::SMPTEDefault(ChannelMap aMap) |
135 | 0 | { |
136 | 0 | // First handle the most common cases. |
137 | 0 | switch (aMap) { |
138 | 0 | case LMONO_MAP: |
139 | 0 | return ChannelLayout{ CHANNEL_FRONT_CENTER }; |
140 | 0 | case LSTEREO_MAP: |
141 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT }; |
142 | 0 | case L3F_MAP: |
143 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, |
144 | 0 | CHANNEL_FRONT_RIGHT, |
145 | 0 | CHANNEL_FRONT_CENTER }; |
146 | 0 | case L3F_LFE_MAP: |
147 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, |
148 | 0 | CHANNEL_FRONT_RIGHT, |
149 | 0 | CHANNEL_FRONT_CENTER, |
150 | 0 | CHANNEL_LFE }; |
151 | 0 | case L2F1_MAP: |
152 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, |
153 | 0 | CHANNEL_FRONT_RIGHT, |
154 | 0 | CHANNEL_BACK_CENTER }; |
155 | 0 | case L2F1_LFE_MAP: |
156 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, |
157 | 0 | CHANNEL_FRONT_RIGHT, |
158 | 0 | CHANNEL_LFE, |
159 | 0 | CHANNEL_BACK_CENTER }; |
160 | 0 | case L3F1_MAP: |
161 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, |
162 | 0 | CHANNEL_FRONT_RIGHT, |
163 | 0 | CHANNEL_FRONT_CENTER, |
164 | 0 | CHANNEL_BACK_CENTER }; |
165 | 0 | case L3F1_LFE_MAP: |
166 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, |
167 | 0 | CHANNEL_FRONT_RIGHT, |
168 | 0 | CHANNEL_FRONT_CENTER, |
169 | 0 | CHANNEL_LFE, |
170 | 0 | CHANNEL_BACK_CENTER }; |
171 | 0 | case L2F2_MAP: |
172 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, |
173 | 0 | CHANNEL_FRONT_RIGHT, |
174 | 0 | CHANNEL_SIDE_LEFT, |
175 | 0 | CHANNEL_SIDE_RIGHT }; |
176 | 0 | case L2F2_LFE_MAP: |
177 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, |
178 | 0 | CHANNEL_FRONT_RIGHT, |
179 | 0 | CHANNEL_LFE, |
180 | 0 | CHANNEL_SIDE_LEFT, |
181 | 0 | CHANNEL_SIDE_RIGHT }; |
182 | 0 | case LQUAD_MAP: |
183 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, |
184 | 0 | CHANNEL_FRONT_RIGHT, |
185 | 0 | CHANNEL_BACK_LEFT, |
186 | 0 | CHANNEL_BACK_RIGHT }; |
187 | 0 | case LQUAD_LFE_MAP: |
188 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, |
189 | 0 | CHANNEL_FRONT_RIGHT, |
190 | 0 | CHANNEL_LFE, |
191 | 0 | CHANNEL_BACK_LEFT, |
192 | 0 | CHANNEL_BACK_RIGHT }; |
193 | 0 | case L3F2_MAP: |
194 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, |
195 | 0 | CHANNEL_FRONT_RIGHT, |
196 | 0 | CHANNEL_FRONT_CENTER, |
197 | 0 | CHANNEL_SIDE_LEFT, |
198 | 0 | CHANNEL_SIDE_RIGHT }; |
199 | 0 | case L3F2_LFE_MAP: |
200 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, |
201 | 0 | CHANNEL_FRONT_CENTER, CHANNEL_LFE, |
202 | 0 | CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT }; |
203 | 0 | case L3F2_BACK_MAP: |
204 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, |
205 | 0 | CHANNEL_FRONT_RIGHT, |
206 | 0 | CHANNEL_FRONT_CENTER, |
207 | 0 | CHANNEL_BACK_LEFT, |
208 | 0 | CHANNEL_BACK_RIGHT }; |
209 | 0 | case L3F2_BACK_LFE_MAP: |
210 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, |
211 | 0 | CHANNEL_FRONT_CENTER, CHANNEL_LFE, |
212 | 0 | CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT }; |
213 | 0 | case L3F3R_LFE_MAP: |
214 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, |
215 | 0 | CHANNEL_FRONT_CENTER, CHANNEL_LFE, |
216 | 0 | CHANNEL_BACK_CENTER, CHANNEL_SIDE_LEFT, |
217 | 0 | CHANNEL_SIDE_RIGHT }; |
218 | 0 | case L3F4_LFE_MAP: |
219 | 0 | return ChannelLayout{ CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, |
220 | 0 | CHANNEL_FRONT_CENTER, CHANNEL_LFE, |
221 | 0 | CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT, |
222 | 0 | CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT }; |
223 | 0 | default: |
224 | 0 | break; |
225 | 0 | } |
226 | 0 | |
227 | 0 | static_assert(MAX_CHANNELS <= sizeof(ChannelMap) * 8, |
228 | 0 | "Must be able to fit channels on bit mask"); |
229 | 0 | AutoTArray<Channel, MAX_CHANNELS> layout; |
230 | 0 | uint32_t channels = 0; |
231 | 0 |
|
232 | 0 | uint32_t i = 0; |
233 | 0 | while (aMap) { |
234 | 0 | if (aMap & 1) { |
235 | 0 | channels++; |
236 | 0 | if (channels > MAX_CHANNELS) { |
237 | 0 | return ChannelLayout(); |
238 | 0 | } |
239 | 0 | layout.AppendElement(static_cast<Channel>(i)); |
240 | 0 | } |
241 | 0 | aMap >>= 1; |
242 | 0 | i++; |
243 | 0 | } |
244 | 0 | return ChannelLayout(channels, layout.Elements()); |
245 | 0 | } |
246 | | |
247 | | bool |
248 | | AudioConfig::ChannelLayout::MappingTable(const ChannelLayout& aOther, |
249 | | nsTArray<uint8_t>* aMap) const |
250 | 0 | { |
251 | 0 | if (!IsValid() || !aOther.IsValid() || Map() != aOther.Map()) { |
252 | 0 | if (aMap) { |
253 | 0 | aMap->SetLength(0); |
254 | 0 | } |
255 | 0 | return false; |
256 | 0 | } |
257 | 0 | if (!aMap) { |
258 | 0 | return true; |
259 | 0 | } |
260 | 0 | aMap->SetLength(Count()); |
261 | 0 | for (uint32_t i = 0; i < Count(); i++) { |
262 | 0 | for (uint32_t j = 0; j < Count(); j++) { |
263 | 0 | if (aOther[j] == mChannels[i]) { |
264 | 0 | (*aMap)[j] = i; |
265 | 0 | break; |
266 | 0 | } |
267 | 0 | } |
268 | 0 | } |
269 | 0 | return true; |
270 | 0 | } |
271 | | |
272 | | /** |
273 | | * AudioConfig::ChannelConfig |
274 | | */ |
275 | | |
276 | | /* static */ const char* |
277 | | AudioConfig::FormatToString(AudioConfig::SampleFormat aFormat) |
278 | | { |
279 | | switch (aFormat) { |
280 | | case FORMAT_U8: return "unsigned 8 bit"; |
281 | | case FORMAT_S16: return "signed 16 bit"; |
282 | | case FORMAT_S24: return "signed 24 bit MSB"; |
283 | | case FORMAT_S24LSB: return "signed 24 bit LSB"; |
284 | | case FORMAT_S32: return "signed 32 bit"; |
285 | | case FORMAT_FLT: return "32 bit floating point"; |
286 | | case FORMAT_NONE: return "none"; |
287 | | default: return "unknown"; |
288 | | } |
289 | | } |
290 | | /* static */ uint32_t |
291 | | AudioConfig::SampleSize(AudioConfig::SampleFormat aFormat) |
292 | 0 | { |
293 | 0 | switch (aFormat) { |
294 | 0 | case FORMAT_U8: return 1; |
295 | 0 | case FORMAT_S16: return 2; |
296 | 0 | case FORMAT_S24: MOZ_FALLTHROUGH; |
297 | 0 | case FORMAT_S24LSB: MOZ_FALLTHROUGH; |
298 | 0 | case FORMAT_S32: MOZ_FALLTHROUGH; |
299 | 0 | case FORMAT_FLT: return 4; |
300 | 0 | case FORMAT_NONE: |
301 | 0 | default: return 0; |
302 | 0 | } |
303 | 0 | } |
304 | | |
305 | | /* static */ uint32_t |
306 | | AudioConfig::FormatToBits(AudioConfig::SampleFormat aFormat) |
307 | 0 | { |
308 | 0 | switch (aFormat) { |
309 | 0 | case FORMAT_U8: return 8; |
310 | 0 | case FORMAT_S16: return 16; |
311 | 0 | case FORMAT_S24LSB: MOZ_FALLTHROUGH; |
312 | 0 | case FORMAT_S24: return 24; |
313 | 0 | case FORMAT_S32: MOZ_FALLTHROUGH; |
314 | 0 | case FORMAT_FLT: return 32; |
315 | 0 | case FORMAT_NONE: MOZ_FALLTHROUGH; |
316 | 0 | default: return 0; |
317 | 0 | } |
318 | 0 | } |
319 | | |
320 | | AudioConfig::AudioConfig(const ChannelLayout& aChannelLayout, uint32_t aRate, |
321 | | AudioConfig::SampleFormat aFormat, bool aInterleaved) |
322 | | : mChannelLayout(aChannelLayout) |
323 | | , mChannels(aChannelLayout.Count()) |
324 | | , mRate(aRate) |
325 | | , mFormat(aFormat) |
326 | | , mInterleaved(aInterleaved) |
327 | 0 | { |
328 | 0 | } |
329 | | |
330 | | AudioConfig::AudioConfig(const ChannelLayout& aChannelLayout, |
331 | | uint32_t aChannels, |
332 | | uint32_t aRate, |
333 | | AudioConfig::SampleFormat aFormat, |
334 | | bool aInterleaved) |
335 | | : mChannelLayout(aChannelLayout) |
336 | | , mChannels(aChannels) |
337 | | , mRate(aRate) |
338 | | , mFormat(aFormat) |
339 | | , mInterleaved(aInterleaved) |
340 | 0 | { |
341 | 0 | } |
342 | | |
343 | | AudioConfig::AudioConfig(uint32_t aChannels, |
344 | | uint32_t aRate, |
345 | | AudioConfig::SampleFormat aFormat, |
346 | | bool aInterleaved) |
347 | | : mChannelLayout(aChannels) |
348 | | , mChannels(aChannels) |
349 | | , mRate(aRate) |
350 | | , mFormat(aFormat) |
351 | | , mInterleaved(aInterleaved) |
352 | 0 | { |
353 | 0 | } |
354 | | |
355 | | } // namespace mozilla |