The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

779 lines
42KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. // This macro can be set if you need to override this internal name for some reason..
  18. #ifndef JUCE_STATE_DICTIONARY_KEY
  19. #define JUCE_STATE_DICTIONARY_KEY "jucePluginState"
  20. #endif
  21. struct AudioUnitHelpers
  22. {
  23. // maps a channel index into an AU format to an index of a juce format
  24. struct AUChannelStreamOrder
  25. {
  26. AudioChannelLayoutTag auLayoutTag;
  27. AudioChannelLabel speakerOrder[8];
  28. };
  29. static AUChannelStreamOrder auChannelStreamOrder[];
  30. static AudioChannelSet::ChannelType CoreAudioChannelLabelToJuceType (AudioChannelLabel label) noexcept
  31. {
  32. if (label >= kAudioChannelLabel_Discrete_0 && label <= kAudioChannelLabel_Discrete_65535)
  33. {
  34. const unsigned int discreteChannelNum = label - kAudioChannelLabel_Discrete_0;
  35. return static_cast<AudioChannelSet::ChannelType> (AudioChannelSet::discreteChannel0 + discreteChannelNum);
  36. }
  37. switch (label)
  38. {
  39. case kAudioChannelLabel_Center:
  40. case kAudioChannelLabel_Mono: return AudioChannelSet::centre;
  41. case kAudioChannelLabel_Left:
  42. case kAudioChannelLabel_HeadphonesLeft: return AudioChannelSet::left;
  43. case kAudioChannelLabel_Right:
  44. case kAudioChannelLabel_HeadphonesRight: return AudioChannelSet::right;
  45. case kAudioChannelLabel_LFEScreen: return AudioChannelSet::subbass;
  46. case kAudioChannelLabel_LeftSurround: return AudioChannelSet::leftSurround;
  47. case kAudioChannelLabel_RightSurround: return AudioChannelSet::rightSurround;
  48. case kAudioChannelLabel_LeftCenter: return AudioChannelSet::leftCentre;
  49. case kAudioChannelLabel_RightCenter: return AudioChannelSet::rightCentre;
  50. case kAudioChannelLabel_CenterSurround: return AudioChannelSet::surround;
  51. case kAudioChannelLabel_LeftSurroundDirect: return AudioChannelSet::leftSurroundDirect;
  52. case kAudioChannelLabel_RightSurroundDirect: return AudioChannelSet::rightSurroundDirect;
  53. case kAudioChannelLabel_TopCenterSurround: return AudioChannelSet::topMiddle;
  54. case kAudioChannelLabel_VerticalHeightLeft: return AudioChannelSet::topFrontLeft;
  55. case kAudioChannelLabel_VerticalHeightRight: return AudioChannelSet::topFrontRight;
  56. case kAudioChannelLabel_VerticalHeightCenter: return AudioChannelSet::topFrontCentre;
  57. case kAudioChannelLabel_TopBackLeft: return AudioChannelSet::topRearLeft;
  58. case kAudioChannelLabel_RearSurroundLeft: return AudioChannelSet::leftRearSurround;
  59. case kAudioChannelLabel_TopBackRight: return AudioChannelSet::topRearRight;
  60. case kAudioChannelLabel_RearSurroundRight: return AudioChannelSet::rightRearSurround;
  61. case kAudioChannelLabel_TopBackCenter: return AudioChannelSet::topRearCentre;
  62. case kAudioChannelLabel_LFE2: return AudioChannelSet::subbass2;
  63. case kAudioChannelLabel_LeftWide: return AudioChannelSet::wideLeft;
  64. case kAudioChannelLabel_RightWide: return AudioChannelSet::wideRight;
  65. case kAudioChannelLabel_Ambisonic_W: return AudioChannelSet::ambisonicW;
  66. case kAudioChannelLabel_Ambisonic_X: return AudioChannelSet::ambisonicX;
  67. case kAudioChannelLabel_Ambisonic_Y: return AudioChannelSet::ambisonicY;
  68. case kAudioChannelLabel_Ambisonic_Z: return AudioChannelSet::ambisonicZ;
  69. default: return AudioChannelSet::unknown;
  70. }
  71. }
  72. static AudioChannelLabel JuceChannelTypeToCoreAudioLabel (const AudioChannelSet::ChannelType& label) noexcept
  73. {
  74. if (label >= AudioChannelSet::discreteChannel0)
  75. {
  76. const unsigned int discreteChannelNum = label - AudioChannelSet::discreteChannel0;;
  77. return static_cast<AudioChannelLabel> (kAudioChannelLabel_Discrete_0 + discreteChannelNum);
  78. }
  79. switch (label)
  80. {
  81. case AudioChannelSet::centre: return kAudioChannelLabel_Center;
  82. case AudioChannelSet::left: return kAudioChannelLabel_Left;
  83. case AudioChannelSet::right: return kAudioChannelLabel_Right;
  84. case AudioChannelSet::subbass: return kAudioChannelLabel_LFEScreen;
  85. case AudioChannelSet::leftRearSurround: return kAudioChannelLabel_RearSurroundLeft;
  86. case AudioChannelSet::rightRearSurround: return kAudioChannelLabel_RearSurroundRight;
  87. case AudioChannelSet::leftCentre: return kAudioChannelLabel_LeftCenter;
  88. case AudioChannelSet::rightCentre: return kAudioChannelLabel_RightCenter;
  89. case AudioChannelSet::surround: return kAudioChannelLabel_CenterSurround;
  90. case AudioChannelSet::leftSurround: return kAudioChannelLabel_LeftSurround;
  91. case AudioChannelSet::rightSurround: return kAudioChannelLabel_RightSurround;
  92. case AudioChannelSet::topMiddle: return kAudioChannelLabel_TopCenterSurround;
  93. case AudioChannelSet::topFrontLeft: return kAudioChannelLabel_VerticalHeightLeft;
  94. case AudioChannelSet::topFrontRight: return kAudioChannelLabel_VerticalHeightRight;
  95. case AudioChannelSet::topFrontCentre: return kAudioChannelLabel_VerticalHeightCenter;
  96. case AudioChannelSet::topRearLeft: return kAudioChannelLabel_TopBackLeft;
  97. case AudioChannelSet::topRearRight: return kAudioChannelLabel_TopBackRight;
  98. case AudioChannelSet::topRearCentre: return kAudioChannelLabel_TopBackCenter;
  99. case AudioChannelSet::subbass2: return kAudioChannelLabel_LFE2;
  100. case AudioChannelSet::wideLeft: return kAudioChannelLabel_LeftWide;
  101. case AudioChannelSet::wideRight: return kAudioChannelLabel_RightWide;
  102. case AudioChannelSet::ambisonicW: return kAudioChannelLabel_Ambisonic_W;
  103. case AudioChannelSet::ambisonicX: return kAudioChannelLabel_Ambisonic_X;
  104. case AudioChannelSet::ambisonicY: return kAudioChannelLabel_Ambisonic_Y;
  105. case AudioChannelSet::ambisonicZ: return kAudioChannelLabel_Ambisonic_Z;
  106. case AudioChannelSet::leftSurroundDirect: return kAudioChannelLabel_LeftSurroundDirect;
  107. case AudioChannelSet::rightSurroundDirect: return kAudioChannelLabel_RightSurroundDirect;
  108. case AudioChannelSet::unknown: return kAudioChannelLabel_Unknown;
  109. case AudioChannelSet::discreteChannel0: return kAudioChannelLabel_Discrete_0;
  110. }
  111. return kAudioChannelLabel_Unknown;
  112. }
  113. static AudioChannelSet CoreAudioChannelBitmapToJuceType (UInt32 bitmap) noexcept
  114. {
  115. AudioChannelSet set;
  116. if ((bitmap & kAudioChannelBit_Left) != 0) set.addChannel (AudioChannelSet::left);
  117. if ((bitmap & kAudioChannelBit_Right) != 0) set.addChannel (AudioChannelSet::right);
  118. if ((bitmap & kAudioChannelBit_Center) != 0) set.addChannel (AudioChannelSet::centre);
  119. if ((bitmap & kAudioChannelBit_LFEScreen) != 0) set.addChannel (AudioChannelSet::subbass);
  120. if ((bitmap & kAudioChannelBit_LeftSurroundDirect) != 0) set.addChannel (AudioChannelSet::leftSurroundDirect);
  121. if ((bitmap & kAudioChannelBit_RightSurroundDirect) != 0) set.addChannel (AudioChannelSet::rightSurroundDirect);
  122. if ((bitmap & kAudioChannelBit_LeftCenter) != 0) set.addChannel (AudioChannelSet::leftCentre);
  123. if ((bitmap & kAudioChannelBit_RightCenter) != 0) set.addChannel (AudioChannelSet::rightCentre);
  124. if ((bitmap & kAudioChannelBit_CenterSurround) != 0) set.addChannel (AudioChannelSet::surround);
  125. if ((bitmap & kAudioChannelBit_LeftSurround) != 0) set.addChannel (AudioChannelSet::leftSurround);
  126. if ((bitmap & kAudioChannelBit_RightSurround) != 0) set.addChannel (AudioChannelSet::rightSurround);
  127. if ((bitmap & kAudioChannelBit_TopCenterSurround) != 0) set.addChannel (AudioChannelSet::topMiddle);
  128. if ((bitmap & kAudioChannelBit_VerticalHeightLeft) != 0) set.addChannel (AudioChannelSet::topFrontLeft);
  129. if ((bitmap & kAudioChannelBit_VerticalHeightCenter) != 0) set.addChannel (AudioChannelSet::topFrontCentre);
  130. if ((bitmap & kAudioChannelBit_VerticalHeightRight) != 0) set.addChannel (AudioChannelSet::topFrontRight);
  131. if ((bitmap & kAudioChannelBit_TopBackLeft) != 0) set.addChannel (AudioChannelSet::topRearLeft);
  132. if ((bitmap & kAudioChannelBit_TopBackCenter) != 0) set.addChannel (AudioChannelSet::topRearCentre);
  133. if ((bitmap & kAudioChannelBit_TopBackRight) != 0) set.addChannel (AudioChannelSet::topRearRight);
  134. return set;
  135. }
  136. static AudioChannelSet CoreAudioChannelLayoutToJuceType (const AudioChannelLayout& layout) noexcept
  137. {
  138. const AudioChannelLayoutTag tag = layout.mChannelLayoutTag;
  139. if (tag == kAudioChannelLayoutTag_UseChannelBitmap) return CoreAudioChannelBitmapToJuceType (layout.mChannelBitmap);
  140. if (tag == kAudioChannelLayoutTag_UseChannelDescriptions)
  141. {
  142. if (layout.mNumberChannelDescriptions <= 8)
  143. {
  144. // first try to convert the layout via the auChannelStreamOrder array
  145. int layoutIndex;
  146. for (layoutIndex = 0; auChannelStreamOrder[layoutIndex].auLayoutTag != 0; ++layoutIndex)
  147. {
  148. const AUChannelStreamOrder& streamOrder = auChannelStreamOrder[layoutIndex];
  149. int numChannels;
  150. for (numChannels = 0; numChannels < 8 && streamOrder.speakerOrder[numChannels] != 0;)
  151. ++numChannels;
  152. if (numChannels != (int) layout.mNumberChannelDescriptions)
  153. continue;
  154. int ch;
  155. for (ch = 0; ch < numChannels; ++ch)
  156. if (streamOrder.speakerOrder[ch] != layout.mChannelDescriptions[ch].mChannelLabel)
  157. break;
  158. // match!
  159. if (ch == numChannels)
  160. break;
  161. }
  162. if (auChannelStreamOrder[layoutIndex].auLayoutTag != 0)
  163. return CALayoutTagToChannelSet (auChannelStreamOrder[layoutIndex].auLayoutTag);
  164. }
  165. AudioChannelSet set;
  166. for (unsigned int i = 0; i < layout.mNumberChannelDescriptions; ++i)
  167. set.addChannel (CoreAudioChannelLabelToJuceType (layout.mChannelDescriptions[i].mChannelLabel));
  168. return set;
  169. }
  170. return CALayoutTagToChannelSet (tag);
  171. }
  172. static AudioChannelSet CALayoutTagToChannelSet (AudioChannelLayoutTag tag) noexcept
  173. {
  174. switch (tag)
  175. {
  176. case kAudioChannelLayoutTag_Unknown: return AudioChannelSet::disabled();
  177. case kAudioChannelLayoutTag_Mono: return AudioChannelSet::mono();
  178. case kAudioChannelLayoutTag_Stereo:
  179. case kAudioChannelLayoutTag_StereoHeadphones:
  180. case kAudioChannelLayoutTag_Binaural: return AudioChannelSet::stereo();
  181. case kAudioChannelLayoutTag_Quadraphonic: return AudioChannelSet::quadraphonic();
  182. case kAudioChannelLayoutTag_Pentagonal: return AudioChannelSet::pentagonal();
  183. case kAudioChannelLayoutTag_Hexagonal: return AudioChannelSet::hexagonal();
  184. case kAudioChannelLayoutTag_Octagonal: return AudioChannelSet::octagonal();
  185. case kAudioChannelLayoutTag_Ambisonic_B_Format: return AudioChannelSet::ambisonic();
  186. case kAudioChannelLayoutTag_AudioUnit_6_0: return AudioChannelSet::create6point0();
  187. case kAudioChannelLayoutTag_DTS_6_0_A: return AudioChannelSet::create6point0Music();
  188. case kAudioChannelLayoutTag_MPEG_6_1_A: return AudioChannelSet::create6point1();
  189. case kAudioChannelLayoutTag_MPEG_5_0_B: return AudioChannelSet::create5point0();
  190. case kAudioChannelLayoutTag_MPEG_5_1_A: return AudioChannelSet::create5point1();
  191. case kAudioChannelLayoutTag_DTS_7_1:
  192. case kAudioChannelLayoutTag_MPEG_7_1_C: return AudioChannelSet::create7point1();
  193. case kAudioChannelLayoutTag_AudioUnit_7_0: return AudioChannelSet::create7point0();
  194. case kAudioChannelLayoutTag_AudioUnit_7_0_Front: return AudioChannelSet::createFront7point0();
  195. case kAudioChannelLayoutTag_AudioUnit_7_1_Front: return AudioChannelSet::createFront7point1();
  196. case kAudioChannelLayoutTag_MPEG_3_0_A:
  197. case kAudioChannelLayoutTag_MPEG_3_0_B: return AudioChannelSet::createLCR();
  198. case kAudioChannelLayoutTag_MPEG_4_0_A:
  199. case kAudioChannelLayoutTag_MPEG_4_0_B: return AudioChannelSet::createLCRS();
  200. case kAudioChannelLayoutTag_ITU_2_1: return AudioChannelSet::createLRS();
  201. case kAudioChannelLayoutTag_EAC3_7_1_C: return AudioChannelSet::create7point1AC3();
  202. }
  203. if (int numChannels = static_cast<int> (tag) & 0xffff)
  204. return AudioChannelSet::discreteChannels (numChannels);
  205. // Bitmap and channel description array layout tags are currently unsupported :-(
  206. jassertfalse;
  207. return AudioChannelSet();
  208. }
  209. static AudioChannelLayoutTag ChannelSetToCALayoutTag (const AudioChannelSet& set) noexcept
  210. {
  211. if (set == AudioChannelSet::mono()) return kAudioChannelLayoutTag_Mono;
  212. if (set == AudioChannelSet::stereo()) return kAudioChannelLayoutTag_Stereo;
  213. if (set == AudioChannelSet::createLCR()) return kAudioChannelLayoutTag_MPEG_3_0_A;
  214. if (set == AudioChannelSet::createLRS()) return kAudioChannelLayoutTag_ITU_2_1;
  215. if (set == AudioChannelSet::createLCRS()) return kAudioChannelLayoutTag_MPEG_4_0_A;
  216. if (set == AudioChannelSet::quadraphonic()) return kAudioChannelLayoutTag_Quadraphonic;
  217. if (set == AudioChannelSet::pentagonal()) return kAudioChannelLayoutTag_Pentagonal;
  218. if (set == AudioChannelSet::hexagonal()) return kAudioChannelLayoutTag_Hexagonal;
  219. if (set == AudioChannelSet::octagonal()) return kAudioChannelLayoutTag_Octagonal;
  220. if (set == AudioChannelSet::ambisonic()) return kAudioChannelLayoutTag_Ambisonic_B_Format;
  221. if (set == AudioChannelSet::create5point0()) return kAudioChannelLayoutTag_MPEG_5_0_B;
  222. if (set == AudioChannelSet::create5point1()) return kAudioChannelLayoutTag_MPEG_5_1_A;
  223. if (set == AudioChannelSet::create6point0()) return kAudioChannelLayoutTag_AudioUnit_6_0;
  224. if (set == AudioChannelSet::create6point0Music()) return kAudioChannelLayoutTag_DTS_6_0_A;
  225. if (set == AudioChannelSet::create6point1()) return kAudioChannelLayoutTag_MPEG_6_1_A;
  226. if (set == AudioChannelSet::create7point0()) return kAudioChannelLayoutTag_AudioUnit_7_0;
  227. if (set == AudioChannelSet::create7point1()) return kAudioChannelLayoutTag_MPEG_7_1_C;
  228. if (set == AudioChannelSet::createFront7point0()) return kAudioChannelLayoutTag_AudioUnit_7_0_Front;
  229. if (set == AudioChannelSet::createFront7point1()) return kAudioChannelLayoutTag_AudioUnit_7_1_Front;
  230. if (set == AudioChannelSet::create7point1AC3()) return kAudioChannelLayoutTag_EAC3_7_1_C;
  231. if (set == AudioChannelSet::disabled()) return kAudioChannelLayoutTag_Unknown;
  232. return static_cast<AudioChannelLayoutTag> ((int) kAudioChannelLayoutTag_DiscreteInOrder | set.size());
  233. }
  234. static int auChannelIndexToJuce (int auIndex, const AudioChannelSet& channelSet)
  235. {
  236. if (auIndex >= 8) return auIndex;
  237. AudioChannelLayoutTag currentLayout = ChannelSetToCALayoutTag (channelSet);
  238. int layoutIndex;
  239. for (layoutIndex = 0; auChannelStreamOrder[layoutIndex].auLayoutTag != currentLayout; ++layoutIndex)
  240. if (auChannelStreamOrder[layoutIndex].auLayoutTag == 0) return auIndex;
  241. AudioChannelSet::ChannelType channelType
  242. = CoreAudioChannelLabelToJuceType (auChannelStreamOrder[layoutIndex].speakerOrder[auIndex]);
  243. // We need to map surround channels to rear surround channels for petagonal and hexagonal
  244. if (channelSet == AudioChannelSet::pentagonal() || channelSet == AudioChannelSet::hexagonal())
  245. {
  246. switch (channelType)
  247. {
  248. case AudioChannelSet::leftSurround:
  249. channelType = AudioChannelSet::leftRearSurround;
  250. break;
  251. case AudioChannelSet::rightSurround:
  252. channelType = AudioChannelSet::rightRearSurround;
  253. break;
  254. default:
  255. break;
  256. }
  257. }
  258. const int juceIndex = channelSet.getChannelTypes().indexOf (channelType);
  259. jassert (juceIndex >= 0);
  260. return juceIndex >= 0 ? juceIndex : auIndex;
  261. }
  262. static int juceChannelIndexToAu (int juceIndex, const AudioChannelSet& channelSet)
  263. {
  264. AudioChannelLayoutTag currentLayout = ChannelSetToCALayoutTag (channelSet);
  265. int layoutIndex;
  266. for (layoutIndex = 0; auChannelStreamOrder[layoutIndex].auLayoutTag != currentLayout; ++layoutIndex)
  267. {
  268. if (auChannelStreamOrder[layoutIndex].auLayoutTag == 0)
  269. {
  270. jassertfalse;
  271. return juceIndex;
  272. }
  273. }
  274. const AUChannelStreamOrder& channelOrder = auChannelStreamOrder[layoutIndex];
  275. AudioChannelSet::ChannelType channelType = channelSet.getTypeOfChannel (juceIndex);
  276. // We need to map rear surround channels to surround channels for petagonal and hexagonal
  277. if (channelSet == AudioChannelSet::pentagonal() || channelSet == AudioChannelSet::hexagonal())
  278. {
  279. switch (channelType)
  280. {
  281. case AudioChannelSet::leftRearSurround:
  282. channelType = AudioChannelSet::leftSurround;
  283. break;
  284. case AudioChannelSet::rightRearSurround:
  285. channelType = AudioChannelSet::rightSurround;
  286. break;
  287. default:
  288. break;
  289. }
  290. }
  291. for (int i = 0; i < 8 && channelOrder.speakerOrder[i] != 0; ++i)
  292. if (CoreAudioChannelLabelToJuceType (channelOrder.speakerOrder[i]) == channelType)
  293. return i;
  294. jassertfalse;
  295. return juceIndex;
  296. }
  297. class ChannelRemapper
  298. {
  299. public:
  300. ChannelRemapper (PluginBusUtilities& bUtils) : busUtils (bUtils), inputLayoutMap (nullptr), outputLayoutMap (nullptr) {}
  301. ~ChannelRemapper() {}
  302. void alloc()
  303. {
  304. const int numInputBuses = busUtils.getBusCount (true);
  305. const int numOutputBuses = busUtils.getBusCount (false);
  306. initializeChannelMapArray (true, numInputBuses);
  307. initializeChannelMapArray (false, numOutputBuses);
  308. for (int busIdx = 0; busIdx < numInputBuses; ++busIdx)
  309. fillLayoutChannelMaps (true, busIdx);
  310. for (int busIdx = 0; busIdx < numOutputBuses; ++busIdx)
  311. fillLayoutChannelMaps (false, busIdx);
  312. }
  313. void release()
  314. {
  315. inputLayoutMap = outputLayoutMap = nullptr;
  316. inputLayoutMapPtrStorage.free();
  317. outputLayoutMapPtrStorage.free();
  318. inputLayoutMapStorage.free();
  319. outputLayoutMapStorage.free();
  320. }
  321. inline const int* get (bool input, int bus) const noexcept { return (input ? inputLayoutMap : outputLayoutMap) [bus]; }
  322. private:
  323. //==============================================================================
  324. PluginBusUtilities& busUtils;
  325. HeapBlock<int*> inputLayoutMapPtrStorage, outputLayoutMapPtrStorage;
  326. HeapBlock<int> inputLayoutMapStorage, outputLayoutMapStorage;
  327. int** inputLayoutMap;
  328. int** outputLayoutMap;
  329. //==============================================================================
  330. void initializeChannelMapArray (bool isInput, const int numBuses)
  331. {
  332. HeapBlock<int*>& layoutMapPtrStorage = isInput ? inputLayoutMapPtrStorage : outputLayoutMapPtrStorage;
  333. HeapBlock<int>& layoutMapStorage = isInput ? inputLayoutMapStorage : outputLayoutMapStorage;
  334. int**& layoutMap = isInput ? inputLayoutMap : outputLayoutMap;
  335. const int totalInChannels = busUtils.findTotalNumChannels (true);
  336. const int totalOutChannels = busUtils.findTotalNumChannels (false);
  337. layoutMapPtrStorage.calloc (static_cast<size_t> (numBuses));
  338. layoutMapStorage.calloc (static_cast<size_t> (isInput ? totalInChannels : totalOutChannels));
  339. layoutMap = layoutMapPtrStorage. getData();
  340. int ch = 0;
  341. for (int busIdx = 0; busIdx < numBuses; ++busIdx)
  342. {
  343. layoutMap[busIdx] = layoutMapStorage.getData() + ch;
  344. ch += busUtils.getNumChannels (isInput, busIdx);
  345. }
  346. }
  347. void fillLayoutChannelMaps (bool isInput, int busNr)
  348. {
  349. int* layoutMap = (isInput ? inputLayoutMap : outputLayoutMap)[busNr];
  350. const AudioChannelSet& channelFormat = busUtils.getChannelSet (isInput, busNr);
  351. const int numChannels = channelFormat.size();
  352. for (int i = 0; i < numChannels; ++i)
  353. layoutMap[i] = AudioUnitHelpers::juceChannelIndexToAu (i, channelFormat);
  354. }
  355. };
  356. //==============================================================================
  357. class CoreAudioBufferList
  358. {
  359. public:
  360. CoreAudioBufferList() { reset(); }
  361. //==============================================================================
  362. void prepare (int inChannels, int outChannels, int maxFrames)
  363. {
  364. const int numChannels = jmax (inChannels, outChannels);
  365. scratch.setSize (numChannels, maxFrames);
  366. channels.calloc (static_cast<size_t> (numChannels));
  367. reset();
  368. }
  369. void release()
  370. {
  371. scratch.setSize (0, 0);
  372. channels.free();
  373. }
  374. void reset() noexcept
  375. {
  376. pushIdx = 0;
  377. popIdx = 0;
  378. zeromem (channels.getData(), sizeof(float*) * static_cast<size_t> (scratch.getNumChannels()));
  379. }
  380. //==============================================================================
  381. float* setBuffer (const int idx, float* ptr = nullptr) noexcept
  382. {
  383. jassert (idx < scratch.getNumChannels());
  384. return (channels [idx] = uniqueBuffer (idx, ptr));
  385. }
  386. //==============================================================================
  387. float* push() noexcept
  388. {
  389. jassert (pushIdx < scratch.getNumChannels());
  390. return channels [pushIdx++];
  391. }
  392. void push (AudioBufferList& bufferList, const int* channelMap) noexcept
  393. {
  394. jassert (pushIdx < scratch.getNumChannels());
  395. if (bufferList.mNumberBuffers > 0)
  396. {
  397. const UInt32 n = bufferList.mBuffers [0].mDataByteSize /
  398. (bufferList.mBuffers [0].mNumberChannels * sizeof (float));
  399. const bool isInterleaved = isAudioBufferInterleaved (bufferList);
  400. const int numChannels = static_cast<int> (isInterleaved ? bufferList.mBuffers [0].mNumberChannels
  401. : bufferList.mNumberBuffers);
  402. for (int ch = 0; ch < numChannels; ++ch)
  403. {
  404. float* data = push();
  405. int mappedChannel = channelMap [ch];
  406. if (isInterleaved || static_cast<float*> (bufferList.mBuffers [mappedChannel].mData) != data)
  407. copyAudioBuffer (bufferList, mappedChannel, n, data);
  408. }
  409. }
  410. }
  411. //==============================================================================
  412. float* pop() noexcept
  413. {
  414. jassert (popIdx < scratch.getNumChannels());
  415. return channels[popIdx++];
  416. }
  417. void pop (AudioBufferList& buffer, const int* channelMap) noexcept
  418. {
  419. if (buffer.mNumberBuffers > 0)
  420. {
  421. const UInt32 n = buffer.mBuffers [0].mDataByteSize / (buffer.mBuffers [0].mNumberChannels * sizeof (float));
  422. const bool isInterleaved = isAudioBufferInterleaved (buffer);
  423. const int numChannels = static_cast<int> (isInterleaved ? buffer.mBuffers [0].mNumberChannels : buffer.mNumberBuffers);
  424. for (int ch = 0; ch < numChannels; ++ch)
  425. {
  426. int mappedChannel = channelMap [ch];
  427. float* nextBuffer = pop();
  428. if (nextBuffer == buffer.mBuffers [mappedChannel].mData && ! isInterleaved)
  429. continue; // no copying necessary
  430. if (buffer.mBuffers [mappedChannel].mData == nullptr && ! isInterleaved)
  431. buffer.mBuffers [mappedChannel].mData = nextBuffer;
  432. else
  433. copyAudioBuffer (nextBuffer, mappedChannel, n, buffer);
  434. }
  435. }
  436. }
  437. //==============================================================================
  438. AudioSampleBuffer& getBuffer (UInt32 frames) noexcept
  439. {
  440. jassert (pushIdx == scratch.getNumChannels());
  441. #if JUCE_DEBUG
  442. for (int i = 0; i < pushIdx; ++i)
  443. jassert (channels [i] != nullptr);
  444. #endif
  445. mutableBuffer.setDataToReferTo (channels, pushIdx, static_cast<int> (frames));
  446. return mutableBuffer;
  447. }
  448. private:
  449. float* uniqueBuffer (int idx, float* buffer) noexcept
  450. {
  451. if (buffer == nullptr)
  452. return scratch.getWritePointer (idx);
  453. for (int ch = 0; ch < idx; ++ch)
  454. if (buffer == channels[ch])
  455. return scratch.getWritePointer (idx);
  456. return buffer;
  457. }
  458. //==============================================================================
  459. AudioSampleBuffer scratch;
  460. AudioSampleBuffer mutableBuffer;
  461. HeapBlock<float*> channels;
  462. int pushIdx, popIdx;
  463. };
  464. static bool isAudioBufferInterleaved (const AudioBufferList& audioBuffer) noexcept
  465. {
  466. return (audioBuffer.mNumberBuffers == 1 && audioBuffer.mBuffers[0].mNumberChannels > 1);
  467. }
  468. static void clearAudioBuffer (const AudioBufferList& audioBuffer) noexcept
  469. {
  470. for (unsigned int ch = 0; ch < audioBuffer.mNumberBuffers; ++ch)
  471. zeromem (audioBuffer.mBuffers[ch].mData, audioBuffer.mBuffers[ch].mDataByteSize);
  472. }
  473. static void copyAudioBuffer (const AudioBufferList& audioBuffer, const int channel, const UInt32 size, float* dst) noexcept
  474. {
  475. if (! isAudioBufferInterleaved (audioBuffer))
  476. {
  477. jassert (channel < static_cast<int> (audioBuffer.mNumberBuffers));
  478. jassert (audioBuffer.mBuffers[channel].mDataByteSize == (size * sizeof (float)));
  479. memcpy (dst, audioBuffer.mBuffers[channel].mData, size * sizeof (float));
  480. }
  481. else
  482. {
  483. const int numChannels = static_cast<int> (audioBuffer.mBuffers[0].mNumberChannels);
  484. const UInt32 n = static_cast<UInt32> (numChannels) * size;
  485. const float* src = static_cast<const float*> (audioBuffer.mBuffers[0].mData);
  486. jassert (channel < numChannels);
  487. jassert (audioBuffer.mBuffers[0].mDataByteSize == (n * sizeof (float)));
  488. for (const float* inData = src; inData < (src + n); inData += numChannels)
  489. *dst++ = inData[channel];
  490. }
  491. }
  492. static void copyAudioBuffer (const float *src, const int channel, const UInt32 size, AudioBufferList& audioBuffer) noexcept
  493. {
  494. if (! isAudioBufferInterleaved (audioBuffer))
  495. {
  496. jassert (channel < static_cast<int> (audioBuffer.mNumberBuffers));
  497. jassert (audioBuffer.mBuffers[channel].mDataByteSize == (size * sizeof (float)));
  498. memcpy (audioBuffer.mBuffers[channel].mData, src, size * sizeof (float));
  499. }
  500. else
  501. {
  502. const int numChannels = static_cast<int> (audioBuffer.mBuffers[0].mNumberChannels);
  503. const UInt32 n = static_cast<UInt32> (numChannels) * size;
  504. float* dst = static_cast<float*> (audioBuffer.mBuffers[0].mData);
  505. jassert (channel < numChannels);
  506. jassert (audioBuffer.mBuffers[0].mDataByteSize == (n * sizeof (float)));
  507. for (float* outData = dst; outData < (dst + n); outData += numChannels)
  508. outData[channel] = *src++;
  509. }
  510. }
  511. static Array<AUChannelInfo> getAUChannelInfo (PluginBusUtilities& busUtils)
  512. {
  513. Array<AUChannelInfo> channelInfo;
  514. AudioProcessor* juceFilter = &busUtils.processor;
  515. const AudioProcessor::AudioBusArrangement& arr = juceFilter->busArrangement;
  516. PluginBusUtilities::ScopedBusRestorer restorer (busUtils);
  517. const bool hasMainInputBus = (busUtils.getNumEnabledBuses (true) > 0);
  518. const bool hasMainOutputBus = (busUtils.getNumEnabledBuses (false) > 0);
  519. if ((! hasMainInputBus) && (! hasMainOutputBus))
  520. {
  521. // midi effect plug-in: no audio
  522. AUChannelInfo info;
  523. info.inChannels = 0;
  524. info.outChannels = 0;
  525. channelInfo.add (info);
  526. return channelInfo;
  527. }
  528. else
  529. {
  530. const uint32_t maxNumChanToCheckFor = 9;
  531. uint32_t defaultInputs = static_cast<uint32_t> (busUtils.getNumChannels (true, 0));
  532. uint32_t defaultOutputs = static_cast<uint32_t> (busUtils.getNumChannels (false, 0));
  533. uint32_t lastInputs = defaultInputs;
  534. uint32_t lastOutputs = defaultOutputs;
  535. SortedSet<uint32_t> supportedChannels;
  536. // add the current configuration
  537. if (lastInputs != 0 || lastOutputs != 0)
  538. supportedChannels.add ((lastInputs << 16) | lastOutputs);
  539. for (uint32_t inChanNum = hasMainInputBus ? 1 : 0; inChanNum <= (hasMainInputBus ? maxNumChanToCheckFor : 0); ++inChanNum)
  540. {
  541. const AudioChannelSet dfltInLayout = busUtils.getDefaultLayoutForChannelNumAndBus(true, 0, static_cast<int> (inChanNum));
  542. if (inChanNum != 0 && dfltInLayout.isDisabled())
  543. continue;
  544. for (uint32_t outChanNum = hasMainOutputBus ? 1 : 0; outChanNum <= (hasMainOutputBus ? maxNumChanToCheckFor : 0); ++outChanNum)
  545. {
  546. const AudioChannelSet dfltOutLayout = busUtils.getDefaultLayoutForChannelNumAndBus(false, 0, static_cast<int> (outChanNum));
  547. if (outChanNum != 0 && dfltOutLayout.isDisabled())
  548. continue;
  549. // get the number of channels again. This is only needed for some processors that change their configuration
  550. // even when they indicate that setPreferredBusArrangement failed.
  551. lastInputs = hasMainInputBus ? static_cast<uint32_t> (arr.inputBuses. getReference (0). channels.size()) : 0;
  552. lastOutputs = hasMainOutputBus ? static_cast<uint32_t> (arr.outputBuses.getReference (0). channels.size()) : 0;
  553. uint32_t channelConfiguration = (inChanNum << 16) | outChanNum;
  554. // did we already try this configuration?
  555. if (supportedChannels.contains (channelConfiguration)) continue;
  556. if (lastInputs != inChanNum && (! dfltInLayout.isDisabled()))
  557. {
  558. if (! juceFilter->setPreferredBusArrangement (true, 0, dfltInLayout)) continue;
  559. lastInputs = inChanNum;
  560. lastOutputs = hasMainOutputBus ? static_cast<uint32_t> (arr.outputBuses.getReference (0). channels.size()) : 0;
  561. supportedChannels.add ((lastInputs << 16) | lastOutputs);
  562. }
  563. if (lastOutputs != outChanNum && (! dfltOutLayout.isDisabled()))
  564. {
  565. if (! juceFilter->setPreferredBusArrangement (false, 0, dfltOutLayout)) continue;
  566. lastInputs = hasMainInputBus ? static_cast<uint32_t> (arr.inputBuses.getReference (0).channels.size()) : 0;
  567. lastOutputs = outChanNum;
  568. supportedChannels.add ((lastInputs << 16) | lastOutputs);
  569. }
  570. }
  571. }
  572. bool hasInOutMismatch = false;
  573. for (int i = 0; i < supportedChannels.size(); ++i)
  574. {
  575. const uint32_t numInputs = (supportedChannels[i] >> 16) & 0xffff;
  576. const uint32_t numOutputs = (supportedChannels[i] >> 0) & 0xffff;
  577. if (numInputs != numOutputs)
  578. {
  579. hasInOutMismatch = true;
  580. break;
  581. }
  582. }
  583. bool hasUnsupportedInput = ! hasMainOutputBus, hasUnsupportedOutput = ! hasMainInputBus;
  584. for (uint32_t inChanNum = hasMainInputBus ? 1 : 0; inChanNum <= (hasMainInputBus ? maxNumChanToCheckFor : 0); ++inChanNum)
  585. {
  586. uint32_t channelConfiguration = (inChanNum << 16) | (hasInOutMismatch ? defaultOutputs : inChanNum);
  587. if (! supportedChannels.contains (channelConfiguration))
  588. {
  589. hasUnsupportedInput = true;
  590. break;
  591. }
  592. }
  593. for (uint32_t outChanNum = hasMainOutputBus ? 1 : 0; outChanNum <= (hasMainOutputBus ? maxNumChanToCheckFor : 0); ++outChanNum)
  594. {
  595. uint32_t channelConfiguration = ((hasInOutMismatch ? defaultInputs : outChanNum) << 16) | outChanNum;
  596. if (! supportedChannels.contains (channelConfiguration))
  597. {
  598. hasUnsupportedOutput = true;
  599. break;
  600. }
  601. }
  602. for (int i = 0; i < supportedChannels.size(); ++i)
  603. {
  604. const int numInputs = (supportedChannels[i] >> 16) & 0xffff;
  605. const int numOutputs = (supportedChannels[i] >> 0) & 0xffff;
  606. AUChannelInfo info;
  607. // see here: https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/TheAudioUnit/TheAudioUnit.html
  608. info.inChannels = static_cast<SInt16> (hasMainInputBus ? (hasUnsupportedInput ? numInputs : (hasInOutMismatch && (! hasUnsupportedOutput) ? -2 : -1)) : 0);
  609. info.outChannels = static_cast<SInt16> (hasMainOutputBus ? (hasUnsupportedOutput ? numOutputs : (hasInOutMismatch && (! hasUnsupportedInput) ? -2 : -1)) : 0);
  610. if (info.inChannels == -2 && info.outChannels == -2)
  611. info.inChannels = -1;
  612. int j;
  613. for (j = 0; j < channelInfo.size(); ++j)
  614. if (channelInfo[j].inChannels == info.inChannels && channelInfo[j].outChannels == info.outChannels)
  615. break;
  616. if (j >= channelInfo.size())
  617. channelInfo.add (info);
  618. }
  619. }
  620. return channelInfo;
  621. }
  622. };
  623. AudioUnitHelpers::AUChannelStreamOrder AudioUnitHelpers::auChannelStreamOrder[] =
  624. {
  625. {kAudioChannelLayoutTag_Mono, {kAudioChannelLabel_Center, 0, 0, 0, 0, 0, 0, 0}},
  626. {kAudioChannelLayoutTag_Stereo, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, 0, 0, 0, 0, 0, 0}},
  627. {kAudioChannelLayoutTag_StereoHeadphones, {kAudioChannelLabel_HeadphonesLeft, kAudioChannelLabel_HeadphonesRight, 0, 0, 0, 0, 0, 0}},
  628. {kAudioChannelLayoutTag_Binaural, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, 0, 0, 0, 0, 0, 0}},
  629. {kAudioChannelLayoutTag_Quadraphonic, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, 0, 0, 0, 0}},
  630. {kAudioChannelLayoutTag_Pentagonal, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, kAudioChannelLabel_Center, 0, 0, 0}},
  631. {kAudioChannelLayoutTag_Hexagonal, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, kAudioChannelLabel_Center, kAudioChannelLabel_CenterSurround, 0, 0}},
  632. {kAudioChannelLayoutTag_Octagonal, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, kAudioChannelLabel_Center, kAudioChannelLabel_CenterSurround, kAudioChannelLabel_LeftWide, kAudioChannelLabel_RightWide}},
  633. {kAudioChannelLayoutTag_Ambisonic_B_Format, {kAudioChannelLabel_Ambisonic_W, kAudioChannelLabel_Ambisonic_X, kAudioChannelLabel_Ambisonic_Y, kAudioChannelLabel_Ambisonic_Z, 0, 0, 0, 0}},
  634. {kAudioChannelLayoutTag_MPEG_5_0_B, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, kAudioChannelLabel_Center, 0, 0, 0}},
  635. {kAudioChannelLayoutTag_MPEG_5_1_A, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_Center, kAudioChannelLabel_LFEScreen, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, 0, 0}},
  636. {kAudioChannelLayoutTag_AudioUnit_6_0, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, kAudioChannelLabel_Center, kAudioChannelLabel_CenterSurround, 0, 0}},
  637. {kAudioChannelLayoutTag_DTS_6_0_A, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, kAudioChannelLabel_RearSurroundLeft, kAudioChannelLabel_RearSurroundRight, 0, 0}},
  638. {kAudioChannelLayoutTag_MPEG_6_1_A, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_Center, kAudioChannelLabel_LFEScreen, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, kAudioChannelLabel_CenterSurround, 0}},
  639. {kAudioChannelLayoutTag_AudioUnit_7_0, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, kAudioChannelLabel_Center, kAudioChannelLabel_RearSurroundLeft, kAudioChannelLabel_RearSurroundRight, 0}},
  640. {kAudioChannelLayoutTag_MPEG_7_1_C, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_Center, kAudioChannelLabel_LFEScreen, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, kAudioChannelLabel_RearSurroundLeft, kAudioChannelLabel_RearSurroundRight}},
  641. {kAudioChannelLayoutTag_AudioUnit_7_0_Front,{kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, kAudioChannelLabel_Center, kAudioChannelLabel_LeftCenter, kAudioChannelLabel_RightCenter, 0}},
  642. {kAudioChannelLayoutTag_AudioUnit_7_1_Front,{kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_Center, kAudioChannelLabel_LFEScreen, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, kAudioChannelLabel_LeftCenter, kAudioChannelLabel_RightCenter}},
  643. {kAudioChannelLayoutTag_MPEG_3_0_A, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_Center, 0, 0, 0, 0, 0}},
  644. {kAudioChannelLayoutTag_MPEG_3_0_B, {kAudioChannelLabel_Center, kAudioChannelLabel_Left, kAudioChannelLabel_Right, 0, 0, 0, 0, 0}},
  645. {kAudioChannelLayoutTag_MPEG_4_0_A, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_Center, kAudioChannelLabel_CenterSurround, 0, 0, 0, 0}},
  646. {kAudioChannelLayoutTag_MPEG_4_0_B, {kAudioChannelLabel_Center, kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_CenterSurround, 0, 0, 0, 0}},
  647. {kAudioChannelLayoutTag_ITU_2_1, {kAudioChannelLabel_Left, kAudioChannelLabel_Right, kAudioChannelLabel_CenterSurround, 0, 0, 0, 0, 0}},
  648. {kAudioChannelLayoutTag_EAC3_7_1_C, {kAudioChannelLabel_Left, kAudioChannelLabel_Center, kAudioChannelLabel_Right, kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, kAudioChannelLabel_LFEScreen, kAudioChannelLabel_LeftSurroundDirect, kAudioChannelLabel_RightSurroundDirect}},
  649. {0, {0,0,0,0,0,0,0,0}}
  650. };