Backed out changeset 06f41c22f3a6 (bug 1888460) for causing linux xpcshell failures...
[gecko.git] / dom / media / AudioConfig.h
blobe31aa55d2c82cc0d1672ae7a84638bd5f623c04f
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)
7 # define AudioLayout_h
9 # include <cstdint>
10 # include <initializer_list>
11 # include "mozilla/MathAlgorithms.h"
12 # include "nsTArray.h"
13 # include "cubeb/cubeb.h"
15 namespace mozilla {
17 class AudioConfig {
18 public:
19 // Channel definition is conveniently defined to be in the same order as
20 // WAVEFORMAT && SMPTE, even though this is unused for now.
21 enum Channel {
22 CHANNEL_INVALID = -1,
23 CHANNEL_FRONT_LEFT = 0,
24 CHANNEL_FRONT_RIGHT,
25 CHANNEL_FRONT_CENTER,
26 CHANNEL_LFE,
27 CHANNEL_BACK_LEFT,
28 CHANNEL_BACK_RIGHT,
29 CHANNEL_FRONT_LEFT_OF_CENTER,
30 CHANNEL_FRONT_RIGHT_OF_CENTER,
31 CHANNEL_BACK_CENTER,
32 CHANNEL_SIDE_LEFT,
33 CHANNEL_SIDE_RIGHT,
34 // From WAVEFORMAT definition.
35 CHANNEL_TOP_CENTER,
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
44 class ChannelLayout {
45 public:
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)
55 : ChannelLayout() {
56 if (aChannels == 0 || !aConfig) {
57 return;
59 mChannels.AppendElements(aConfig, aChannels);
60 UpdateChannelMap();
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;
152 // 3F2_LFE Alias
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;
171 // 3F4_LFE Alias
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);
199 private:
200 void UpdateChannelMap();
201 const Channel* DefaultLayoutForChannels(uint32_t aChannels) const;
202 CopyableAutoTArray<Channel, MAX_CHANNELS> mChannels;
203 ChannelMap mChannelMap;
204 bool mValid;
207 enum SampleFormat {
208 FORMAT_NONE = 0,
209 FORMAT_U8,
210 FORMAT_S16,
211 FORMAT_S24LSB,
212 FORMAT_S24,
213 FORMAT_S32,
214 FORMAT_FLT,
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,
222 uint32_t aRate,
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()) {
233 return mChannels;
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);
256 private:
257 // Channels configuration.
258 ChannelLayout mChannelLayout;
260 // Channel count.
261 uint32_t mChannels;
263 // Sample rate.
264 uint32_t mRate;
266 // Sample format.
267 SampleFormat mFormat;
269 bool mInterleaved;
272 } // namespace mozilla
274 #endif // AudioLayout_h