OpenShot Audio Library | OpenShotAudio  0.3.1
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 
23 namespace juce
24 {
25 
26 #if ! DOXYGEN && (JUCE_MAC || JUCE_IOS)
27 
28 struct 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 
152 private:
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 > &)
Array< ChannelType > getChannelTypes() const
static AudioChannelSet JUCE_CALLTYPE ambisonic(int order=1)
static AudioChannelSet JUCE_CALLTYPE discreteChannels(int numChannels)
static AudioChannelSet JUCE_CALLTYPE fromWaveChannelMask(int32 dwChannelMask)