You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

333 lines
21KB

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