OpenShot Audio Library | OpenShotAudio 0.3.2
juce_mac_CoreAudioLayouts.h
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26#if ! DOXYGEN && (JUCE_MAC || JUCE_IOS)
27
28struct CoreAudioLayouts
29{
30 //==============================================================================
31 enum
32 {
33 coreAudioHOASN3DLayoutTag = (190U<<16) | 0 // kAudioChannelLayoutTag_HOA_ACN_SN3D
34 };
35
36 //==============================================================================
41 static AudioChannelSet fromCoreAudio (const AudioChannelLayout& layout)
42 {
43 return AudioChannelSet::channelSetWithChannels (getCoreAudioLayoutChannels (layout));
44 }
45
50 static AudioChannelSet fromCoreAudio (AudioChannelLayoutTag layoutTag)
51 {
52 return AudioChannelSet::channelSetWithChannels (getSpeakerLayoutForCoreAudioTag (layoutTag));
53 }
54
59 static AudioChannelLayoutTag toCoreAudio (const AudioChannelSet& set)
60 {
61 if (set.getAmbisonicOrder() >= 0)
62 return coreAudioHOASN3DLayoutTag | static_cast<unsigned> (set.size());
63
64 for (auto* tbl = SpeakerLayoutTable::get(); tbl->tag != 0; ++tbl)
65 {
66 AudioChannelSet caSet;
67
68 for (int i = 0; i < numElementsInArray (tbl->channelTypes)
69 && tbl->channelTypes[i] != AudioChannelSet::unknown; ++i)
70 caSet.addChannel (tbl->channelTypes[i]);
71
72 if (caSet == set)
73 return tbl->tag;
74 }
75
76 return kAudioChannelLayoutTag_DiscreteInOrder | static_cast<AudioChannelLayoutTag> (set.size());
77 }
78
79 static const Array<AudioChannelLayoutTag>& getKnownCoreAudioTags()
80 {
81 static Array<AudioChannelLayoutTag> tags (createKnownCoreAudioTags());
82 return tags;
83 }
84
85 //==============================================================================
87 static Array<AudioChannelSet::ChannelType> getCoreAudioLayoutChannels (const AudioChannelLayout& layout)
88 {
89 switch (layout.mChannelLayoutTag & 0xffff0000)
90 {
91 case kAudioChannelLayoutTag_UseChannelBitmap:
92 return AudioChannelSet::fromWaveChannelMask (static_cast<int> (layout.mChannelBitmap)).getChannelTypes();
93 case kAudioChannelLayoutTag_UseChannelDescriptions:
94 {
95 Array<AudioChannelSet::ChannelType> channels;
96
97 for (UInt32 i = 0; i < layout.mNumberChannelDescriptions; ++i)
98 channels.addIfNotAlreadyThere (getChannelTypeFromAudioChannelLabel (layout.mChannelDescriptions[i].mChannelLabel));
99
100 // different speaker mappings may point to the same JUCE speaker so fill up
101 // this array with discrete channels
102 for (int j = 0; channels.size() < static_cast<int> (layout.mNumberChannelDescriptions); ++j)
103 channels.addIfNotAlreadyThere (static_cast<AudioChannelSet::ChannelType> (AudioChannelSet::discreteChannel0 + j));
104
105 return channels;
106 }
107 case kAudioChannelLayoutTag_DiscreteInOrder:
108 return AudioChannelSet::discreteChannels (static_cast<int> (layout.mChannelLayoutTag) & 0xffff).getChannelTypes();
109 default:
110 break;
111 }
112
113 return getSpeakerLayoutForCoreAudioTag (layout.mChannelLayoutTag);
114 }
115
116 static Array<AudioChannelSet::ChannelType> getSpeakerLayoutForCoreAudioTag (AudioChannelLayoutTag tag)
117 {
118 // You need to specify the full AudioChannelLayout when using
119 // the UseChannelBitmap and UseChannelDescriptions layout tag
120 jassert (tag != kAudioChannelLayoutTag_UseChannelBitmap && tag != kAudioChannelLayoutTag_UseChannelDescriptions);
121
122 Array<AudioChannelSet::ChannelType> speakers;
123
124 for (auto* tbl = SpeakerLayoutTable::get(); tbl->tag != 0; ++tbl)
125 {
126 if (tag == tbl->tag)
127 {
128 for (int i = 0; i < numElementsInArray (tbl->channelTypes)
129 && tbl->channelTypes[i] != AudioChannelSet::unknown; ++i)
130 speakers.add (tbl->channelTypes[i]);
131
132 return speakers;
133 }
134 }
135
136 auto numChannels = tag & 0xffff;
137 if (tag >= coreAudioHOASN3DLayoutTag && tag <= (coreAudioHOASN3DLayoutTag | 0xffff))
138 {
139 auto sqrtMinusOne = std::sqrt (static_cast<float> (numChannels)) - 1.0f;
140 auto ambisonicOrder = jmax (0, static_cast<int> (std::floor (sqrtMinusOne)));
141
142 if (static_cast<float> (ambisonicOrder) == sqrtMinusOne)
143 return AudioChannelSet::ambisonic (ambisonicOrder).getChannelTypes();
144 }
145
146 for (UInt32 i = 0; i < numChannels; ++i)
147 speakers.add (static_cast<AudioChannelSet::ChannelType> (AudioChannelSet::discreteChannel0 + i));
148
149 return speakers;
150 }
151
152private:
153 //==============================================================================
154 struct LayoutTagSpeakerList
155 {
156 AudioChannelLayoutTag tag;
157 AudioChannelSet::ChannelType channelTypes[16];
158 };
159
160 static Array<AudioChannelLayoutTag> createKnownCoreAudioTags()
161 {
162 Array<AudioChannelLayoutTag> tags;
163
164 for (auto* tbl = SpeakerLayoutTable::get(); tbl->tag != 0; ++tbl)
165 tags.addIfNotAlreadyThere (tbl->tag);
166
167 for (unsigned order = 0; order <= 5; ++order)
168 tags.addIfNotAlreadyThere (coreAudioHOASN3DLayoutTag | ((order + 1) * (order + 1)));
169
170 return tags;
171 }
172
173 //==============================================================================
174 // This list has been derived from https://pastebin.com/24dQ4BPJ
175 // Apple channel labels have been replaced by JUCE channel names
176 // This means that some layouts will be identical in JUCE but not in CoreAudio
177
178 // In Apple's official definition the following tags exist with the same speaker layout and order
179 // even when *not* represented in JUCE channels
180 // kAudioChannelLayoutTag_Binaural = kAudioChannelLayoutTag_Stereo
181 // kAudioChannelLayoutTag_MPEG_5_0_B = kAudioChannelLayoutTag_Pentagonal
182 // kAudioChannelLayoutTag_ITU_2_2 = kAudioChannelLayoutTag_Quadraphonic
183 // kAudioChannelLayoutTag_AudioUnit_6_0 = kAudioChannelLayoutTag_Hexagonal
184 struct SpeakerLayoutTable : AudioChannelSet // save us some typing
185 {
186 static LayoutTagSpeakerList* get() noexcept
187 {
188 static LayoutTagSpeakerList tbl[] = {
189 // list layouts for which there is a corresponding named AudioChannelSet first
190 { kAudioChannelLayoutTag_Mono, { centre } },
191 { kAudioChannelLayoutTag_Stereo, { left, right } },
192 { kAudioChannelLayoutTag_MPEG_3_0_A, { left, right, centre } },
193 { kAudioChannelLayoutTag_ITU_2_1, { left, right, centreSurround } },
194 { kAudioChannelLayoutTag_MPEG_4_0_A, { left, right, centre, centreSurround } },
195 { kAudioChannelLayoutTag_MPEG_5_0_A, { left, right, centre, leftSurround, rightSurround } },
196 { kAudioChannelLayoutTag_MPEG_5_1_A, { left, right, centre, LFE, leftSurround, rightSurround } },
197 { kAudioChannelLayoutTag_AudioUnit_6_0, { left, right, leftSurround, rightSurround, centre, centreSurround } },
198 { kAudioChannelLayoutTag_MPEG_6_1_A, { left, right, centre, LFE, leftSurround, rightSurround, centreSurround } },
199 { kAudioChannelLayoutTag_DTS_6_0_A, { leftSurroundSide, rightSurroundSide, left, right, leftSurround, rightSurround } },
200 { kAudioChannelLayoutTag_DTS_6_1_A, { leftSurroundSide, rightSurroundSide, left, right, leftSurround, rightSurround, LFE } },
201 { kAudioChannelLayoutTag_AudioUnit_7_0, { left, right, leftSurroundSide, rightSurroundSide, centre, leftSurroundRear, rightSurroundRear } },
202 { kAudioChannelLayoutTag_AudioUnit_7_0_Front, { left, right, leftSurround, rightSurround, centre, leftCentre, rightCentre } },
203 { kAudioChannelLayoutTag_MPEG_7_1_C, { left, right, centre, LFE, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear } },
204 { kAudioChannelLayoutTag_MPEG_7_1_A, { left, right, centre, LFE, leftSurround, rightSurround, leftCentre, rightCentre } },
205 { kAudioChannelLayoutTag_Ambisonic_B_Format, { ambisonicW, ambisonicX, ambisonicY, ambisonicZ } },
206 { kAudioChannelLayoutTag_Quadraphonic, { left, right, leftSurround, rightSurround } },
207 { kAudioChannelLayoutTag_Pentagonal, { left, right, leftSurroundRear, rightSurroundRear, centre } },
208 { kAudioChannelLayoutTag_Hexagonal, { left, right, leftSurroundRear, rightSurroundRear, centre, centreSurround } },
209 { kAudioChannelLayoutTag_Octagonal, { left, right, leftSurround, rightSurround, centre, centreSurround, wideLeft, wideRight } },
210
211 // more uncommon layouts
212 { kAudioChannelLayoutTag_StereoHeadphones, { left, right } },
213 { kAudioChannelLayoutTag_MatrixStereo, { left, right } },
214 { kAudioChannelLayoutTag_MidSide, { centre, discreteChannel0 } },
215 { kAudioChannelLayoutTag_XY, { ambisonicX, ambisonicY } },
216 { kAudioChannelLayoutTag_Binaural, { left, right } },
217 { kAudioChannelLayoutTag_Cube, { left, right, leftSurround, rightSurround, topFrontLeft, topFrontRight, topRearLeft, topRearRight } },
218 { kAudioChannelLayoutTag_MPEG_3_0_B, { centre, left, right } },
219 { kAudioChannelLayoutTag_MPEG_4_0_B, { centre, left, right, centreSurround } },
220 { kAudioChannelLayoutTag_MPEG_5_0_B, { left, right, leftSurround, rightSurround, centre } },
221 { kAudioChannelLayoutTag_MPEG_5_0_C, { left, centre, right, leftSurround, rightSurround } },
222 { kAudioChannelLayoutTag_MPEG_5_0_D, { centre, left, right, leftSurround, rightSurround } },
223 { kAudioChannelLayoutTag_MPEG_5_1_B, { left, right, leftSurround, rightSurround, centre, LFE } },
224 { kAudioChannelLayoutTag_MPEG_5_1_C, { left, centre, right, leftSurround, rightSurround, LFE } },
225 { kAudioChannelLayoutTag_MPEG_5_1_D, { centre, left, right, leftSurround, rightSurround, LFE } },
226 { kAudioChannelLayoutTag_MPEG_7_1_B, { centre, leftCentre, rightCentre, left, right, leftSurround, rightSurround, LFE } },
227 { kAudioChannelLayoutTag_Emagic_Default_7_1, { left, right, leftSurround, rightSurround, centre, LFE, leftCentre, rightCentre } },
228 { kAudioChannelLayoutTag_SMPTE_DTV, { left, right, centre, LFE, leftSurround, rightSurround, discreteChannel0 /* leftMatrixTotal */, (ChannelType) (discreteChannel0 + 1) /* rightMatrixTotal */} },
229 { kAudioChannelLayoutTag_ITU_2_2, { left, right, leftSurround, rightSurround } },
230 { kAudioChannelLayoutTag_DVD_4, { left, right, LFE } },
231 { kAudioChannelLayoutTag_DVD_5, { left, right, LFE, centreSurround } },
232 { kAudioChannelLayoutTag_DVD_6, { left, right, LFE, leftSurround, rightSurround } },
233 { kAudioChannelLayoutTag_DVD_10, { left, right, centre, LFE } },
234 { kAudioChannelLayoutTag_DVD_11, { left, right, centre, LFE, centreSurround } },
235 { kAudioChannelLayoutTag_DVD_18, { left, right, leftSurround, rightSurround, LFE } },
236 { kAudioChannelLayoutTag_AAC_6_0, { centre, left, right, leftSurround, rightSurround, centreSurround } },
237 { kAudioChannelLayoutTag_AAC_6_1, { centre, left, right, leftSurround, rightSurround, centreSurround, LFE } },
238 { kAudioChannelLayoutTag_AAC_7_0, { centre, left, right, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear } },
239 { kAudioChannelLayoutTag_AAC_7_1_B, { centre, left, right, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear, LFE } },
240 { kAudioChannelLayoutTag_AAC_7_1_C, { centre, left, right, leftSurround, rightSurround, LFE, topFrontLeft, topFrontRight } },
241 { kAudioChannelLayoutTag_AAC_Octagonal, { centre, left, right, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear, centreSurround } },
242 { kAudioChannelLayoutTag_TMH_10_2_std, { left, right, centre, topFrontCentre, leftSurroundSide, rightSurroundSide, leftSurround, rightSurround, topFrontLeft, topFrontRight, wideLeft, wideRight, topRearCentre, centreSurround, LFE, LFE2 } },
243 { kAudioChannelLayoutTag_AC3_1_0_1, { centre, LFE } },
244 { kAudioChannelLayoutTag_AC3_3_0, { left, centre, right } },
245 { kAudioChannelLayoutTag_AC3_3_1, { left, centre, right, centreSurround } },
246 { kAudioChannelLayoutTag_AC3_3_0_1, { left, centre, right, LFE } },
247 { kAudioChannelLayoutTag_AC3_2_1_1, { left, right, centreSurround, LFE } },
248 { kAudioChannelLayoutTag_AC3_3_1_1, { left, centre, right, centreSurround, LFE } },
249 { kAudioChannelLayoutTag_EAC_6_0_A, { left, centre, right, leftSurround, rightSurround, centreSurround } },
250 { kAudioChannelLayoutTag_EAC_7_0_A, { left, centre, right, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear } },
251 { kAudioChannelLayoutTag_EAC3_6_1_A, { left, centre, right, leftSurround, rightSurround, LFE, centreSurround } },
252 { kAudioChannelLayoutTag_EAC3_6_1_B, { left, centre, right, leftSurround, rightSurround, LFE, centreSurround } },
253 { kAudioChannelLayoutTag_EAC3_6_1_C, { left, centre, right, leftSurround, rightSurround, LFE, topFrontCentre } },
254 { kAudioChannelLayoutTag_EAC3_7_1_A, { left, centre, right, leftSurround, rightSurround, LFE, leftSurroundRear, rightSurroundRear } },
255 { kAudioChannelLayoutTag_EAC3_7_1_B, { left, centre, right, leftSurround, rightSurround, LFE, leftCentre, rightCentre } },
256 { kAudioChannelLayoutTag_EAC3_7_1_C, { left, centre, right, leftSurround, rightSurround, LFE, leftSurroundSide, rightSurroundSide } },
257 { kAudioChannelLayoutTag_EAC3_7_1_D, { left, centre, right, leftSurround, rightSurround, LFE, wideLeft, wideRight } },
258 { kAudioChannelLayoutTag_EAC3_7_1_E, { left, centre, right, leftSurround, rightSurround, LFE, topFrontLeft, topFrontRight } },
259 { kAudioChannelLayoutTag_EAC3_7_1_F, { left, centre, right, leftSurround, rightSurround, LFE, centreSurround, topMiddle } },
260 { kAudioChannelLayoutTag_EAC3_7_1_G, { left, centre, right, leftSurround, rightSurround, LFE, centreSurround, topFrontCentre } },
261 { kAudioChannelLayoutTag_EAC3_7_1_H, { left, centre, right, leftSurround, rightSurround, LFE, centreSurround, topFrontCentre } },
262 { kAudioChannelLayoutTag_DTS_3_1, { centre, left, right, LFE } },
263 { kAudioChannelLayoutTag_DTS_4_1, { centre, left, right, centreSurround, LFE } },
264 { kAudioChannelLayoutTag_DTS_6_0_B, { centre, left, right, leftSurroundRear, rightSurroundRear, centreSurround } },
265 { kAudioChannelLayoutTag_DTS_6_0_C, { centre, centreSurround, left, right, leftSurroundRear, rightSurroundRear } },
266 { kAudioChannelLayoutTag_DTS_6_1_B, { centre, left, right, leftSurroundRear, rightSurroundRear, centreSurround, LFE } },
267 { kAudioChannelLayoutTag_DTS_6_1_C, { centre, centreSurround, left, right, leftSurroundRear, rightSurroundRear, LFE } },
268 { kAudioChannelLayoutTag_DTS_6_1_D, { centre, left, right, leftSurround, rightSurround, LFE, centreSurround } },
269 { kAudioChannelLayoutTag_DTS_7_0, { leftCentre, centre, rightCentre, left, right, leftSurround, rightSurround } },
270 { kAudioChannelLayoutTag_DTS_7_1, { leftCentre, centre, rightCentre, left, right, leftSurround, rightSurround, LFE } },
271 { kAudioChannelLayoutTag_DTS_8_0_A, { leftCentre, rightCentre, left, right, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear } },
272 { kAudioChannelLayoutTag_DTS_8_0_B, { leftCentre, centre, rightCentre, left, right, leftSurround, centreSurround, rightSurround } },
273 { kAudioChannelLayoutTag_DTS_8_1_A, { leftCentre, rightCentre, left, right, leftSurround, rightSurround, leftSurroundRear, rightSurroundRear, LFE } },
274 { kAudioChannelLayoutTag_DTS_8_1_B, { leftCentre, centre, rightCentre, left, right, leftSurround, centreSurround, rightSurround, LFE } },
275 { 0, {} }
276 };
277
278 return tbl;
279 }
280 };
281
282 //==============================================================================
283 static AudioChannelSet::ChannelType getChannelTypeFromAudioChannelLabel (AudioChannelLabel label) noexcept
284 {
285 if (label >= kAudioChannelLabel_Discrete_0 && label <= kAudioChannelLabel_Discrete_65535)
286 {
287 const unsigned int discreteChannelNum = label - kAudioChannelLabel_Discrete_0;
288 return static_cast<AudioChannelSet::ChannelType> (AudioChannelSet::discreteChannel0 + discreteChannelNum);
289 }
290
291 switch (label)
292 {
293 case kAudioChannelLabel_Center:
294 case kAudioChannelLabel_Mono: return AudioChannelSet::centre;
295 case kAudioChannelLabel_Left:
296 case kAudioChannelLabel_HeadphonesLeft: return AudioChannelSet::left;
297 case kAudioChannelLabel_Right:
298 case kAudioChannelLabel_HeadphonesRight: return AudioChannelSet::right;
299 case kAudioChannelLabel_LFEScreen: return AudioChannelSet::LFE;
300 case kAudioChannelLabel_LeftSurround: return AudioChannelSet::leftSurround;
301 case kAudioChannelLabel_RightSurround: return AudioChannelSet::rightSurround;
302 case kAudioChannelLabel_LeftCenter: return AudioChannelSet::leftCentre;
303 case kAudioChannelLabel_RightCenter: return AudioChannelSet::rightCentre;
304 case kAudioChannelLabel_CenterSurround: return AudioChannelSet::surround;
305 case kAudioChannelLabel_LeftSurroundDirect: return AudioChannelSet::leftSurroundSide;
306 case kAudioChannelLabel_RightSurroundDirect: return AudioChannelSet::rightSurroundSide;
307 case kAudioChannelLabel_TopCenterSurround: return AudioChannelSet::topMiddle;
308 case kAudioChannelLabel_VerticalHeightLeft: return AudioChannelSet::topFrontLeft;
309 case kAudioChannelLabel_VerticalHeightRight: return AudioChannelSet::topFrontRight;
310 case kAudioChannelLabel_VerticalHeightCenter: return AudioChannelSet::topFrontCentre;
311 case kAudioChannelLabel_TopBackLeft: return AudioChannelSet::topRearLeft;
312 case kAudioChannelLabel_RearSurroundLeft: return AudioChannelSet::leftSurroundRear;
313 case kAudioChannelLabel_TopBackRight: return AudioChannelSet::topRearRight;
314 case kAudioChannelLabel_RearSurroundRight: return AudioChannelSet::rightSurroundRear;
315 case kAudioChannelLabel_TopBackCenter: return AudioChannelSet::topRearCentre;
316 case kAudioChannelLabel_LFE2: return AudioChannelSet::LFE2;
317 case kAudioChannelLabel_LeftWide: return AudioChannelSet::wideLeft;
318 case kAudioChannelLabel_RightWide: return AudioChannelSet::wideRight;
319 case kAudioChannelLabel_Ambisonic_W: return AudioChannelSet::ambisonicW;
320 case kAudioChannelLabel_Ambisonic_X: return AudioChannelSet::ambisonicX;
321 case kAudioChannelLabel_Ambisonic_Y: return AudioChannelSet::ambisonicY;
322 case kAudioChannelLabel_Ambisonic_Z: return AudioChannelSet::ambisonicZ;
323 default: return AudioChannelSet::unknown;
324 }
325 }
326};
327
328#endif
329
330} // namespace juce
static AudioChannelSet JUCE_CALLTYPE channelSetWithChannels(const Array< ChannelType > &)
static AudioChannelSet JUCE_CALLTYPE ambisonic(int order=1)
static AudioChannelSet JUCE_CALLTYPE discreteChannels(int numChannels)
static AudioChannelSet JUCE_CALLTYPE fromWaveChannelMask(int32 dwChannelMask)
Array< ChannelType > getChannelTypes() const