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 #if !defined(AudioLayout_h)
10 # include <initializer_list>
11 # include "mozilla/MathAlgorithms.h"
12 # include "nsTArray.h"
13 # include "cubeb/cubeb.h"
19 // Channel definition is conveniently defined to be in the same order as
20 // WAVEFORMAT && SMPTE, even though this is unused for now.
23 CHANNEL_FRONT_LEFT
= 0,
29 CHANNEL_FRONT_LEFT_OF_CENTER
,
30 CHANNEL_FRONT_RIGHT_OF_CENTER
,
34 // From WAVEFORMAT definition.
36 CHANNEL_TOP_FRONT_LEFT
,
37 CHANNEL_TOP_FRONT_CENTER
,
38 CHANNEL_TOP_FRONT_RIGHT
,
39 CHANNEL_TOP_BACK_LEFT
,
40 CHANNEL_TOP_BACK_CENTER
,
41 CHANNEL_TOP_BACK_RIGHT
46 // The maximum number of channels a channel map can represent.
47 static constexpr uint32_t MAX_CHANNELS
= 32;
49 using ChannelMap
= uint32_t;
51 ChannelLayout() : mChannelMap(UNKNOWN_MAP
), mValid(false) {}
52 explicit ChannelLayout(uint32_t aChannels
)
53 : ChannelLayout(aChannels
, DefaultLayoutForChannels(aChannels
)) {}
54 ChannelLayout(uint32_t aChannels
, const Channel
* aConfig
)
56 if (aChannels
== 0 || !aConfig
) {
59 mChannels
.AppendElements(aConfig
, aChannels
);
62 explicit ChannelLayout(std::initializer_list
<Channel
> aChannelList
)
63 : ChannelLayout(aChannelList
.size(), aChannelList
.begin()) {}
64 bool operator==(const ChannelLayout
& aOther
) const {
65 return mChannels
== aOther
.mChannels
;
67 bool operator!=(const ChannelLayout
& aOther
) const {
68 return mChannels
!= aOther
.mChannels
;
70 const Channel
& operator[](uint32_t aIndex
) const {
71 MOZ_ASSERT(mChannels
.Length() > aIndex
);
72 return mChannels
[aIndex
];
74 uint32_t Count() const { return mChannels
.Length(); }
75 ChannelMap
Map() const;
77 // Calculate the mapping table from the current layout to aOther such that
78 // one can easily go from one layout to the other by doing:
79 // out[channel] = in[map[channel]].
80 // Returns true if the reordering is possible or false otherwise.
81 // If true, then aMap, if set, will be updated to contain the mapping table
82 // allowing conversion from the current layout to aOther.
83 // If aMap is empty, then MappingTable can be used to simply determine if
84 // the current layout can be easily reordered to aOther.
85 bool MappingTable(const ChannelLayout
& aOther
,
86 nsTArray
<uint8_t>* aMap
= nullptr) const;
87 bool IsValid() const { return mValid
; }
88 bool HasChannel(Channel aChannel
) const {
89 return mChannelMap
& (1 << aChannel
);
91 // Return the number of channels found in this ChannelMap.
92 static uint32_t Channels(ChannelMap aMap
) {
93 static_assert(sizeof(ChannelMap
) == sizeof(uint32_t),
94 "Must adjust ChannelMap type");
95 return CountPopulation32(aMap
);
98 static ChannelLayout
SMPTEDefault(const ChannelLayout
& aChannelLayout
);
99 static ChannelLayout
SMPTEDefault(ChannelMap aMap
);
100 // Convert a channel map to a human readable string for debugging purposes.
101 static nsCString
ChannelMapToString(const ChannelMap aChannelMap
);
103 static constexpr ChannelMap UNKNOWN_MAP
= 0;
105 // Common channel layout definitions.
106 static constexpr ChannelMap LMONO_MAP
= 1 << CHANNEL_FRONT_CENTER
;
107 static constexpr ChannelMap LMONO_LFE_MAP
=
108 1 << CHANNEL_FRONT_CENTER
| 1 << CHANNEL_LFE
;
109 static constexpr ChannelMap LSTEREO_MAP
=
110 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
;
111 static constexpr ChannelMap LSTEREO_LFE_MAP
=
112 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
| 1 << CHANNEL_LFE
;
113 static constexpr ChannelMap L3F_MAP
= 1 << CHANNEL_FRONT_LEFT
|
114 1 << CHANNEL_FRONT_RIGHT
|
115 1 << CHANNEL_FRONT_CENTER
;
116 static constexpr ChannelMap L3F_LFE_MAP
=
117 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
|
118 1 << CHANNEL_FRONT_CENTER
| 1 << CHANNEL_LFE
;
119 static constexpr ChannelMap L2F1_MAP
= 1 << CHANNEL_FRONT_LEFT
|
120 1 << CHANNEL_FRONT_RIGHT
|
121 1 << CHANNEL_BACK_CENTER
;
122 static constexpr ChannelMap L2F1_LFE_MAP
=
123 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
| 1 << CHANNEL_LFE
|
124 1 << CHANNEL_BACK_CENTER
;
125 static constexpr ChannelMap L3F1_MAP
=
126 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
|
127 1 << CHANNEL_FRONT_CENTER
| 1 << CHANNEL_BACK_CENTER
;
128 static constexpr ChannelMap LSURROUND_MAP
= L3F1_MAP
;
129 static constexpr ChannelMap L3F1_LFE_MAP
=
130 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
|
131 1 << CHANNEL_FRONT_CENTER
| 1 << CHANNEL_LFE
| 1 << CHANNEL_BACK_CENTER
;
132 static constexpr ChannelMap L2F2_MAP
=
133 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
|
134 1 << CHANNEL_SIDE_LEFT
| 1 << CHANNEL_SIDE_RIGHT
;
135 static constexpr ChannelMap L2F2_LFE_MAP
=
136 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
| 1 << CHANNEL_LFE
|
137 1 << CHANNEL_SIDE_LEFT
| 1 << CHANNEL_SIDE_RIGHT
;
138 static constexpr ChannelMap LQUAD_MAP
=
139 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
|
140 1 << CHANNEL_BACK_LEFT
| 1 << CHANNEL_BACK_RIGHT
;
141 static constexpr ChannelMap LQUAD_LFE_MAP
=
142 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
| 1 << CHANNEL_LFE
|
143 1 << CHANNEL_BACK_LEFT
| 1 << CHANNEL_BACK_RIGHT
;
144 static constexpr ChannelMap L3F2_MAP
=
145 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
|
146 1 << CHANNEL_FRONT_CENTER
| 1 << CHANNEL_SIDE_LEFT
|
147 1 << CHANNEL_SIDE_RIGHT
;
148 static constexpr ChannelMap L3F2_LFE_MAP
=
149 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
|
150 1 << CHANNEL_FRONT_CENTER
| 1 << CHANNEL_LFE
| 1 << CHANNEL_SIDE_LEFT
|
151 1 << CHANNEL_SIDE_RIGHT
;
153 static constexpr ChannelMap L5POINT1_SURROUND_MAP
= L3F2_LFE_MAP
;
154 static constexpr ChannelMap L3F2_BACK_MAP
=
155 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
|
156 1 << CHANNEL_FRONT_CENTER
| 1 << CHANNEL_BACK_LEFT
|
157 1 << CHANNEL_BACK_RIGHT
;
158 static constexpr ChannelMap L3F2_BACK_LFE_MAP
=
159 L3F2_BACK_MAP
| 1 << CHANNEL_LFE
;
160 static constexpr ChannelMap L3F3R_LFE_MAP
=
161 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
|
162 1 << CHANNEL_FRONT_CENTER
| 1 << CHANNEL_LFE
|
163 1 << CHANNEL_BACK_CENTER
| 1 << CHANNEL_SIDE_LEFT
|
164 1 << CHANNEL_SIDE_RIGHT
;
165 static ChannelLayout L3F4_LFE
;
166 static constexpr ChannelMap L3F4_LFE_MAP
=
167 1 << CHANNEL_FRONT_LEFT
| 1 << CHANNEL_FRONT_RIGHT
|
168 1 << CHANNEL_FRONT_CENTER
| 1 << CHANNEL_LFE
| 1 << CHANNEL_BACK_LEFT
|
169 1 << CHANNEL_BACK_RIGHT
| 1 << CHANNEL_SIDE_LEFT
|
170 1 << CHANNEL_SIDE_RIGHT
;
172 static ChannelLayout L7POINT1_SURROUND
;
173 static constexpr ChannelMap L7POINT1_SURROUND_MAP
= L3F4_LFE_MAP
;
175 // Statically check that we can static_cast a Gecko ChannelLayout to a
176 // cubeb_channel_layout.
177 static_assert(CUBEB_LAYOUT_UNDEFINED
== UNKNOWN_MAP
);
178 static_assert(CUBEB_LAYOUT_MONO
== LMONO_MAP
);
179 static_assert(CUBEB_LAYOUT_MONO_LFE
== LMONO_LFE_MAP
);
180 static_assert(CUBEB_LAYOUT_STEREO
== LSTEREO_MAP
);
181 static_assert(CUBEB_LAYOUT_STEREO_LFE
== LSTEREO_LFE_MAP
);
182 static_assert(CUBEB_LAYOUT_3F
== L3F_MAP
);
183 static_assert(CUBEB_LAYOUT_3F_LFE
== L3F_LFE_MAP
);
184 static_assert(CUBEB_LAYOUT_2F1
== L2F1_MAP
);
185 static_assert(CUBEB_LAYOUT_2F1_LFE
== L2F1_LFE_MAP
);
186 static_assert(CUBEB_LAYOUT_3F1
== L3F1_MAP
);
187 static_assert(CUBEB_LAYOUT_3F1_LFE
== L3F1_LFE_MAP
);
188 static_assert(CUBEB_LAYOUT_2F2
== L2F2_MAP
);
189 static_assert(CUBEB_LAYOUT_3F2_LFE
== L3F2_LFE_MAP
);
190 static_assert(CUBEB_LAYOUT_QUAD
== LQUAD_MAP
);
191 static_assert(CUBEB_LAYOUT_QUAD_LFE
== LQUAD_LFE_MAP
);
192 static_assert(CUBEB_LAYOUT_3F2
== L3F2_MAP
);
193 static_assert(CUBEB_LAYOUT_3F2_LFE
== L3F2_LFE_MAP
);
194 static_assert(CUBEB_LAYOUT_3F2_BACK
== L3F2_BACK_MAP
);
195 static_assert(CUBEB_LAYOUT_3F2_LFE_BACK
== L3F2_BACK_LFE_MAP
);
196 static_assert(CUBEB_LAYOUT_3F3R_LFE
== L3F3R_LFE_MAP
);
197 static_assert(CUBEB_LAYOUT_3F4_LFE
== L3F4_LFE_MAP
);
200 void UpdateChannelMap();
201 const Channel
* DefaultLayoutForChannels(uint32_t aChannels
) const;
202 CopyableAutoTArray
<Channel
, MAX_CHANNELS
> mChannels
;
203 ChannelMap mChannelMap
;
215 FORMAT_DEFAULT
= FORMAT_FLT
218 AudioConfig(const ChannelLayout
& aChannelLayout
, uint32_t aRate
,
219 AudioConfig::SampleFormat aFormat
= FORMAT_DEFAULT
,
220 bool aInterleaved
= true);
221 AudioConfig(const ChannelLayout
& aChannelLayout
, uint32_t aChannels
,
223 AudioConfig::SampleFormat aFormat
= FORMAT_DEFAULT
,
224 bool aInterleaved
= true);
225 // Will create a channel configuration from default SMPTE ordering.
226 AudioConfig(uint32_t aChannels
, uint32_t aRate
,
227 AudioConfig::SampleFormat aFormat
= FORMAT_DEFAULT
,
228 bool aInterleaved
= true);
230 const ChannelLayout
& Layout() const { return mChannelLayout
; }
231 uint32_t Channels() const {
232 if (!mChannelLayout
.IsValid()) {
235 return mChannelLayout
.Count();
237 uint32_t Rate() const { return mRate
; }
238 SampleFormat
Format() const { return mFormat
; }
239 bool Interleaved() const { return mInterleaved
; }
240 bool operator==(const AudioConfig
& aOther
) const {
241 return mChannelLayout
== aOther
.mChannelLayout
&& mRate
== aOther
.mRate
&&
242 mFormat
== aOther
.mFormat
&& mInterleaved
== aOther
.mInterleaved
;
244 bool operator!=(const AudioConfig
& aOther
) const {
245 return !(*this == aOther
);
248 bool IsValid() const {
249 return mChannelLayout
.IsValid() && Format() != FORMAT_NONE
&& Rate() > 0;
252 static const char* FormatToString(SampleFormat aFormat
);
253 static uint32_t SampleSize(SampleFormat aFormat
);
254 static uint32_t FormatToBits(SampleFormat aFormat
);
257 // Channels configuration.
258 ChannelLayout mChannelLayout
;
267 SampleFormat mFormat
;
272 } // namespace mozilla
274 #endif // AudioLayout_h