OpenShot Audio Library | OpenShotAudio 0.3.2
Loading...
Searching...
No Matches
juce_AudioChannelSet.cpp
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
27
28AudioChannelSet::AudioChannelSet (uint32 c) : channels (static_cast<int64> (c))
29{
30}
31
32AudioChannelSet::AudioChannelSet (const Array<ChannelType>& c)
33{
34 for (auto channel : c)
35 addChannel (channel);
36}
37
38bool AudioChannelSet::operator== (const AudioChannelSet& other) const noexcept { return channels == other.channels; }
39bool AudioChannelSet::operator!= (const AudioChannelSet& other) const noexcept { return channels != other.channels; }
40bool AudioChannelSet::operator< (const AudioChannelSet& other) const noexcept { return channels < other.channels; }
41
42String AudioChannelSet::getChannelTypeName (AudioChannelSet::ChannelType type)
43{
44 if (type >= discreteChannel0)
45 return "Discrete " + String (type - discreteChannel0 + 1);
46
47 switch (type)
48 {
49 case left: return NEEDS_TRANS("Left");
50 case right: return NEEDS_TRANS("Right");
51 case centre: return NEEDS_TRANS("Centre");
52 case LFE: return NEEDS_TRANS("LFE");
53 case leftSurround: return NEEDS_TRANS("Left Surround");
54 case rightSurround: return NEEDS_TRANS("Right Surround");
55 case leftCentre: return NEEDS_TRANS("Left Centre");
56 case rightCentre: return NEEDS_TRANS("Right Centre");
57 case centreSurround: return NEEDS_TRANS("Centre Surround");
58 case leftSurroundRear: return NEEDS_TRANS("Left Surround Rear");
59 case rightSurroundRear: return NEEDS_TRANS("Right Surround Rear");
60 case topMiddle: return NEEDS_TRANS("Top Middle");
61 case topFrontLeft: return NEEDS_TRANS("Top Front Left");
62 case topFrontCentre: return NEEDS_TRANS("Top Front Centre");
63 case topFrontRight: return NEEDS_TRANS("Top Front Right");
64 case topRearLeft: return NEEDS_TRANS("Top Rear Left");
65 case topRearCentre: return NEEDS_TRANS("Top Rear Centre");
66 case topRearRight: return NEEDS_TRANS("Top Rear Right");
67 case wideLeft: return NEEDS_TRANS("Wide Left");
68 case wideRight: return NEEDS_TRANS("Wide Right");
69 case LFE2: return NEEDS_TRANS("LFE 2");
70 case leftSurroundSide: return NEEDS_TRANS("Left Surround Side");
71 case rightSurroundSide: return NEEDS_TRANS("Right Surround Side");
72 case ambisonicW: return NEEDS_TRANS("Ambisonic W");
73 case ambisonicX: return NEEDS_TRANS("Ambisonic X");
74 case ambisonicY: return NEEDS_TRANS("Ambisonic Y");
75 case ambisonicZ: return NEEDS_TRANS("Ambisonic Z");
76 case topSideLeft: return NEEDS_TRANS("Top Side Left");
77 case topSideRight: return NEEDS_TRANS("Top Side Right");
78 case ambisonicACN4: return NEEDS_TRANS("Ambisonic 4");
79 case ambisonicACN5: return NEEDS_TRANS("Ambisonic 5");
80 case ambisonicACN6: return NEEDS_TRANS("Ambisonic 6");
81 case ambisonicACN7: return NEEDS_TRANS("Ambisonic 7");
82 case ambisonicACN8: return NEEDS_TRANS("Ambisonic 8");
83 case ambisonicACN9: return NEEDS_TRANS("Ambisonic 9");
84 case ambisonicACN10: return NEEDS_TRANS("Ambisonic 10");
85 case ambisonicACN11: return NEEDS_TRANS("Ambisonic 11");
86 case ambisonicACN12: return NEEDS_TRANS("Ambisonic 12");
87 case ambisonicACN13: return NEEDS_TRANS("Ambisonic 13");
88 case ambisonicACN14: return NEEDS_TRANS("Ambisonic 14");
89 case ambisonicACN15: return NEEDS_TRANS("Ambisonic 15");
90 case bottomFrontLeft: return NEEDS_TRANS("Bottom Front Left");
91 case bottomFrontCentre: return NEEDS_TRANS("Bottom Front Centre");
92 case bottomFrontRight: return NEEDS_TRANS("Bottom Front Right");
93 case bottomSideLeft: return NEEDS_TRANS("Bottom Side Left");
94 case bottomSideRight: return NEEDS_TRANS("Bottom Side Right");
95 case bottomRearLeft: return NEEDS_TRANS("Bottom Rear Left");
96 case bottomRearCentre: return NEEDS_TRANS("Bottom Rear Centre");
97 case bottomRearRight: return NEEDS_TRANS("Bottom Rear Right");
98 case discreteChannel0: return NEEDS_TRANS("Discrete channel");
99 default: break;
100 }
101
102 return "Unknown";
103}
104
105String AudioChannelSet::getAbbreviatedChannelTypeName (AudioChannelSet::ChannelType type)
106{
107 if (type >= discreteChannel0)
108 return String (type - discreteChannel0 + 1);
109
110 switch (type)
111 {
112 case left: return "L";
113 case right: return "R";
114 case centre: return "C";
115 case LFE: return "Lfe";
116 case leftSurround: return "Ls";
117 case rightSurround: return "Rs";
118 case leftCentre: return "Lc";
119 case rightCentre: return "Rc";
120 case centreSurround: return "Cs";
121 case leftSurroundRear: return "Lrs";
122 case rightSurroundRear: return "Rrs";
123 case topMiddle: return "Tm";
124 case topFrontLeft: return "Tfl";
125 case topFrontCentre: return "Tfc";
126 case topFrontRight: return "Tfr";
127 case topRearLeft: return "Trl";
128 case topRearCentre: return "Trc";
129 case topRearRight: return "Trr";
130 case wideLeft: return "Wl";
131 case wideRight: return "Wr";
132 case LFE2: return "Lfe2";
133 case leftSurroundSide: return "Lss";
134 case rightSurroundSide: return "Rss";
135 case ambisonicACN0: return "ACN0";
136 case ambisonicACN1: return "ACN1";
137 case ambisonicACN2: return "ACN2";
138 case ambisonicACN3: return "ACN3";
139 case ambisonicACN4: return "ACN4";
140 case ambisonicACN5: return "ACN5";
141 case ambisonicACN6: return "ACN6";
142 case ambisonicACN7: return "ACN7";
143 case ambisonicACN8: return "ACN8";
144 case ambisonicACN9: return "ACN9";
145 case ambisonicACN10: return "ACN10";
146 case ambisonicACN11: return "ACN11";
147 case ambisonicACN12: return "ACN12";
148 case ambisonicACN13: return "ACN13";
149 case ambisonicACN14: return "ACN14";
150 case ambisonicACN15: return "ACN15";
151 case topSideLeft: return "Tsl";
152 case topSideRight: return "Tsr";
153 case bottomFrontLeft: return "Bfl";
154 case bottomFrontCentre: return "Bfc";
155 case bottomFrontRight: return "Bfr";
156 case bottomSideLeft: return "Bsl";
157 case bottomSideRight: return "Bsr";
158 case bottomRearLeft: return "Brl";
159 case bottomRearCentre: return "Brc";
160 case bottomRearRight: return "Brr";
161 default: break;
162 }
163
164 if (type >= ambisonicACN4 && type <= ambisonicACN35)
165 return "ACN" + String (type - ambisonicACN4 + 4);
166
167 return {};
168}
169
170AudioChannelSet::ChannelType AudioChannelSet::getChannelTypeFromAbbreviation (const String& abbr)
171{
172 if (abbr.length() > 0 && (abbr[0] >= '0' && abbr[0] <= '9'))
173 return static_cast<AudioChannelSet::ChannelType> (static_cast<int> (discreteChannel0)
174 + abbr.getIntValue() - 1);
175
176 if (abbr == "L") return left;
177 if (abbr == "R") return right;
178 if (abbr == "C") return centre;
179 if (abbr == "Lfe") return LFE;
180 if (abbr == "Ls") return leftSurround;
181 if (abbr == "Rs") return rightSurround;
182 if (abbr == "Lc") return leftCentre;
183 if (abbr == "Rc") return rightCentre;
184 if (abbr == "Cs") return centreSurround;
185 if (abbr == "Lrs") return leftSurroundRear;
186 if (abbr == "Rrs") return rightSurroundRear;
187 if (abbr == "Tm") return topMiddle;
188 if (abbr == "Tfl") return topFrontLeft;
189 if (abbr == "Tfc") return topFrontCentre;
190 if (abbr == "Tfr") return topFrontRight;
191 if (abbr == "Trl") return topRearLeft;
192 if (abbr == "Trc") return topRearCentre;
193 if (abbr == "Trr") return topRearRight;
194 if (abbr == "Wl") return wideLeft;
195 if (abbr == "Wr") return wideRight;
196 if (abbr == "Lfe2") return LFE2;
197 if (abbr == "Lss") return leftSurroundSide;
198 if (abbr == "Rss") return rightSurroundSide;
199 if (abbr == "W") return ambisonicW;
200 if (abbr == "X") return ambisonicX;
201 if (abbr == "Y") return ambisonicY;
202 if (abbr == "Z") return ambisonicZ;
203 if (abbr == "ACN0") return ambisonicACN0;
204 if (abbr == "ACN1") return ambisonicACN1;
205 if (abbr == "ACN2") return ambisonicACN2;
206 if (abbr == "ACN3") return ambisonicACN3;
207 if (abbr == "ACN4") return ambisonicACN4;
208 if (abbr == "ACN5") return ambisonicACN5;
209 if (abbr == "ACN6") return ambisonicACN6;
210 if (abbr == "ACN7") return ambisonicACN7;
211 if (abbr == "ACN8") return ambisonicACN8;
212 if (abbr == "ACN9") return ambisonicACN9;
213 if (abbr == "ACN10") return ambisonicACN10;
214 if (abbr == "ACN11") return ambisonicACN11;
215 if (abbr == "ACN12") return ambisonicACN12;
216 if (abbr == "ACN13") return ambisonicACN13;
217 if (abbr == "ACN14") return ambisonicACN14;
218 if (abbr == "ACN15") return ambisonicACN15;
219 if (abbr == "Tsl") return topSideLeft;
220 if (abbr == "Tsr") return topSideRight;
221 if (abbr == "Bfl") return bottomFrontLeft;
222 if (abbr == "Bfc") return bottomFrontCentre;
223 if (abbr == "Bfr") return bottomFrontRight;
224 if (abbr == "Bsl") return bottomSideLeft;
225 if (abbr == "Bsr") return bottomSideRight;
226 if (abbr == "Brl") return bottomRearLeft;
227 if (abbr == "Brc") return bottomRearCentre;
228 if (abbr == "Brr") return bottomRearRight;
229 return unknown;
230}
231
232String AudioChannelSet::getSpeakerArrangementAsString() const
233{
235
236 for (auto& speaker : getChannelTypes())
237 {
238 auto name = getAbbreviatedChannelTypeName (speaker);
239
240 if (name.isNotEmpty())
241 speakerTypes.add (name);
242 }
243
244 return speakerTypes.joinIntoString (" ");
245}
246
247AudioChannelSet AudioChannelSet::fromAbbreviatedString (const String& str)
248{
249 AudioChannelSet set;
250
251 for (auto& abbr : StringArray::fromTokens (str, true))
252 {
253 auto type = getChannelTypeFromAbbreviation (abbr);
254
255 if (type != unknown)
256 set.addChannel (type);
257 }
258
259 return set;
260}
261
262String AudioChannelSet::getDescription() const
263{
264 if (isDiscreteLayout()) return "Discrete #" + String (size());
265 if (*this == disabled()) return "Disabled";
266 if (*this == mono()) return "Mono";
267 if (*this == stereo()) return "Stereo";
268
269 if (*this == createLCR()) return "LCR";
270 if (*this == createLRS()) return "LRS";
271 if (*this == createLCRS()) return "LCRS";
272
273 if (*this == create5point0()) return "5.0 Surround";
274 if (*this == create5point1()) return "5.1 Surround";
275 if (*this == create6point0()) return "6.0 Surround";
276 if (*this == create6point1()) return "6.1 Surround";
277 if (*this == create6point0Music()) return "6.0 (Music) Surround";
278 if (*this == create6point1Music()) return "6.1 (Music) Surround";
279 if (*this == create7point0()) return "7.0 Surround";
280 if (*this == create7point1()) return "7.1 Surround";
281 if (*this == create7point0SDDS()) return "7.0 Surround SDDS";
282 if (*this == create7point1SDDS()) return "7.1 Surround SDDS";
283 if (*this == create7point0point2()) return "7.0.2 Surround";
284 if (*this == create7point1point2()) return "7.1.2 Surround";
285
286 if (*this == quadraphonic()) return "Quadraphonic";
287 if (*this == pentagonal()) return "Pentagonal";
288 if (*this == hexagonal()) return "Hexagonal";
289 if (*this == octagonal()) return "Octagonal";
290
291 // ambisonics
292 {
293 auto order = getAmbisonicOrder();
294
295 if (order >= 0)
296 {
298
299 switch (order)
300 {
301 case 1: suffix = "st"; break;
302 case 2: suffix = "nd"; break;
303 case 3: suffix = "rd"; break;
304 default: suffix = "th"; break;
305 }
306
307 return String (order) + suffix + " Order Ambisonics";
308 }
309 }
310
311 return "Unknown";
312}
313
314bool AudioChannelSet::isDiscreteLayout() const noexcept
315{
316 for (auto& speaker : getChannelTypes())
317 if (speaker <= ambisonicACN35)
318 return false;
319
320 return true;
321}
322
323int AudioChannelSet::size() const noexcept
324{
325 return channels.countNumberOfSetBits();
326}
327
328AudioChannelSet::ChannelType AudioChannelSet::getTypeOfChannel (int index) const noexcept
329{
330 int bit = channels.findNextSetBit(0);
331
332 for (int i = 0; i < index && bit >= 0; ++i)
333 bit = channels.findNextSetBit (bit + 1);
334
335 return static_cast<ChannelType> (bit);
336}
337
338int AudioChannelSet::getChannelIndexForType (AudioChannelSet::ChannelType type) const noexcept
339{
340 int idx = 0;
341
342 for (int bit = channels.findNextSetBit (0); bit >= 0; bit = channels.findNextSetBit (bit + 1))
343 {
344 if (static_cast<ChannelType> (bit) == type)
345 return idx;
346
347 idx++;
348 }
349
350 return -1;
351}
352
353Array<AudioChannelSet::ChannelType> AudioChannelSet::getChannelTypes() const
354{
355 Array<ChannelType> result;
356
357 for (int bit = channels.findNextSetBit(0); bit >= 0; bit = channels.findNextSetBit (bit + 1))
358 result.add (static_cast<ChannelType> (bit));
359
360 return result;
361}
362
363void AudioChannelSet::addChannel (ChannelType newChannel)
364{
365 const int bit = static_cast<int> (newChannel);
366 jassert (bit >= 0 && bit < 1024);
367 channels.setBit (bit);
368}
369
370void AudioChannelSet::removeChannel (ChannelType newChannel)
371{
372 const int bit = static_cast<int> (newChannel);
373 jassert (bit >= 0 && bit < 1024);
374 channels.clearBit (bit);
375}
376
377AudioChannelSet AudioChannelSet::disabled() { return {}; }
378AudioChannelSet AudioChannelSet::mono() { return AudioChannelSet (1u << centre); }
379AudioChannelSet AudioChannelSet::stereo() { return AudioChannelSet ((1u << left) | (1u << right)); }
380AudioChannelSet AudioChannelSet::createLCR() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre)); }
381AudioChannelSet AudioChannelSet::createLRS() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << surround)); }
382AudioChannelSet AudioChannelSet::createLCRS() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << surround)); }
383AudioChannelSet AudioChannelSet::create5point0() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurround) | (1u << rightSurround)); }
384AudioChannelSet AudioChannelSet::create5point1() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << LFE) | (1u << leftSurround) | (1u << rightSurround)); }
385AudioChannelSet AudioChannelSet::create6point0() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurround) | (1u << rightSurround) | (1u << centreSurround)); }
386AudioChannelSet AudioChannelSet::create6point1() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << LFE) | (1u << leftSurround) | (1u << rightSurround) | (1u << centreSurround)); }
387AudioChannelSet AudioChannelSet::create6point0Music() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << leftSurround) | (1u << rightSurround) | (1u << leftSurroundSide) | (1u << rightSurroundSide)); }
388AudioChannelSet AudioChannelSet::create6point1Music() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << LFE) | (1u << leftSurround) | (1u << rightSurround) | (1u << leftSurroundSide) | (1u << rightSurroundSide)); }
389AudioChannelSet AudioChannelSet::create7point0() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurroundSide) | (1u << rightSurroundSide) | (1u << leftSurroundRear) | (1u << rightSurroundRear)); }
390AudioChannelSet AudioChannelSet::create7point0SDDS() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurround) | (1u << rightSurround) | (1u << leftCentre) | (1u << rightCentre)); }
391AudioChannelSet AudioChannelSet::create7point1() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << LFE) | (1u << leftSurroundSide) | (1u << rightSurroundSide) | (1u << leftSurroundRear) | (1u << rightSurroundRear)); }
392AudioChannelSet AudioChannelSet::create7point1SDDS() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << LFE) | (1u << leftSurround) | (1u << rightSurround) | (1u << leftCentre) | (1u << rightCentre)); }
393AudioChannelSet AudioChannelSet::quadraphonic() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << leftSurround) | (1u << rightSurround)); }
394AudioChannelSet AudioChannelSet::pentagonal() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurroundRear) | (1u << rightSurroundRear)); }
395AudioChannelSet AudioChannelSet::hexagonal() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << centreSurround) | (1u << leftSurroundRear) | (1u << rightSurroundRear)); }
396AudioChannelSet AudioChannelSet::octagonal() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurround) | (1u << rightSurround) | (1u << centreSurround) | (1u << wideLeft) | (1u << wideRight)); }
397AudioChannelSet AudioChannelSet::create7point0point2() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << leftSurroundSide) | (1u << rightSurroundSide) | (1u << leftSurroundRear) | (1u << rightSurroundRear) | (1u << topSideLeft) | (1u << topSideRight)); }
398AudioChannelSet AudioChannelSet::create7point1point2() { return AudioChannelSet ((1u << left) | (1u << right) | (1u << centre) | (1u << LFE) | (1u << leftSurroundSide) | (1u << rightSurroundSide) | (1u << leftSurroundRear) | (1u << rightSurroundRear) | (1u << topSideLeft) | (1u << topSideRight)); }
399
400AudioChannelSet AudioChannelSet::ambisonic (int order)
401{
402 jassert (isPositiveAndBelow (order, 6));
403
404 if (order == 0)
405 return AudioChannelSet ((uint32) (1 << ambisonicACN0));
406
407 AudioChannelSet set ((1u << ambisonicACN0) | (1u << ambisonicACN1) | (1u << ambisonicACN2) | (1u << ambisonicACN3));
408
409 auto numAmbisonicChannels = (order + 1) * (order + 1);
410 set.channels.setRange (ambisonicACN4, numAmbisonicChannels - 4, true);
411
412 return set;
413}
414
415int AudioChannelSet::getAmbisonicOrder() const
416{
417 auto ambisonicOrder = getAmbisonicOrderForNumChannels (size());
418
419 if (ambisonicOrder >= 0)
420 return (*this == ambisonic (ambisonicOrder) ? ambisonicOrder : -1);
421
422 return -1;
423}
424
425AudioChannelSet AudioChannelSet::discreteChannels (int numChannels)
426{
428 s.channels.setRange (discreteChannel0, numChannels, true);
429 return s;
430}
431
432AudioChannelSet AudioChannelSet::canonicalChannelSet (int numChannels)
433{
434 if (numChannels == 1) return AudioChannelSet::mono();
435 if (numChannels == 2) return AudioChannelSet::stereo();
436 if (numChannels == 3) return AudioChannelSet::createLCR();
437 if (numChannels == 4) return AudioChannelSet::quadraphonic();
438 if (numChannels == 5) return AudioChannelSet::create5point0();
439 if (numChannels == 6) return AudioChannelSet::create5point1();
440 if (numChannels == 7) return AudioChannelSet::create7point0();
441 if (numChannels == 8) return AudioChannelSet::create7point1();
442
443 return discreteChannels (numChannels);
444}
445
446AudioChannelSet AudioChannelSet::namedChannelSet (int numChannels)
447{
448 if (numChannels == 1) return AudioChannelSet::mono();
449 if (numChannels == 2) return AudioChannelSet::stereo();
450 if (numChannels == 3) return AudioChannelSet::createLCR();
451 if (numChannels == 4) return AudioChannelSet::quadraphonic();
452 if (numChannels == 5) return AudioChannelSet::create5point0();
453 if (numChannels == 6) return AudioChannelSet::create5point1();
454 if (numChannels == 7) return AudioChannelSet::create7point0();
455 if (numChannels == 8) return AudioChannelSet::create7point1();
456
457 return {};
458}
459
460Array<AudioChannelSet> AudioChannelSet::channelSetsWithNumberOfChannels (int numChannels)
461{
463
464 if (numChannels != 0)
465 {
466 retval.add (AudioChannelSet::discreteChannels (numChannels));
467
468 if (numChannels == 1)
469 {
470 retval.add (AudioChannelSet::mono());
471 }
472 else if (numChannels == 2)
473 {
474 retval.add (AudioChannelSet::stereo());
475 }
476 else if (numChannels == 3)
477 {
478 retval.add (AudioChannelSet::createLCR());
479 retval.add (AudioChannelSet::createLRS());
480 }
481 else if (numChannels == 4)
482 {
483 retval.add (AudioChannelSet::quadraphonic());
484 retval.add (AudioChannelSet::createLCRS());
485 }
486 else if (numChannels == 5)
487 {
488 retval.add (AudioChannelSet::create5point0());
489 retval.add (AudioChannelSet::pentagonal());
490 }
491 else if (numChannels == 6)
492 {
493 retval.add (AudioChannelSet::create5point1());
494 retval.add (AudioChannelSet::create6point0());
495 retval.add (AudioChannelSet::create6point0Music());
496 retval.add (AudioChannelSet::hexagonal());
497 }
498 else if (numChannels == 7)
499 {
500 retval.add (AudioChannelSet::create7point0());
501 retval.add (AudioChannelSet::create7point0SDDS());
502 retval.add (AudioChannelSet::create6point1());
503 retval.add (AudioChannelSet::create6point1Music());
504 }
505 else if (numChannels == 8)
506 {
507 retval.add (AudioChannelSet::create7point1());
508 retval.add (AudioChannelSet::create7point1SDDS());
509 retval.add (AudioChannelSet::octagonal());
510 }
511
512 auto order = getAmbisonicOrderForNumChannels (numChannels);
513 if (order >= 0)
514 retval.add (AudioChannelSet::ambisonic (order));
515 }
516
517 return retval;
518}
519
520AudioChannelSet JUCE_CALLTYPE AudioChannelSet::channelSetWithChannels (const Array<ChannelType>& channelArray)
521{
522 AudioChannelSet set;
523
524 for (auto ch : channelArray)
525 {
526 jassert (! set.channels[static_cast<int> (ch)]);
527
528 set.addChannel (ch);
529 }
530
531 return set;
532}
533
534//==============================================================================
535AudioChannelSet JUCE_CALLTYPE AudioChannelSet::fromWaveChannelMask (int32 dwChannelMask)
536{
537 return AudioChannelSet (static_cast<uint32> ((dwChannelMask & ((1 << 18) - 1)) << 1));
538}
539
540int32 AudioChannelSet::getWaveChannelMask() const noexcept
541{
542 if (channels.getHighestBit() > topRearRight)
543 return -1;
544
545 return (channels.toInteger() >> 1);
546}
547
548//==============================================================================
549int JUCE_CALLTYPE AudioChannelSet::getAmbisonicOrderForNumChannels (int numChannels)
550{
551 auto sqrtMinusOne = std::sqrt (static_cast<float> (numChannels)) - 1.0f;
552 auto ambisonicOrder = jmax (0, static_cast<int> (std::floor (sqrtMinusOne)));
553
554 if (ambisonicOrder > 5)
555 return -1;
556
557 return (static_cast<float> (ambisonicOrder) == sqrtMinusOne ? ambisonicOrder : -1);
558}
559
560
561//==============================================================================
562//==============================================================================
563#if JUCE_UNIT_TESTS
564
565class AudioChannelSetUnitTest : public UnitTest
566{
567public:
568 AudioChannelSetUnitTest()
569 : UnitTest ("AudioChannelSetUnitTest", UnitTestCategories::audio)
570 {}
571
572 void runTest() override
573 {
574 auto max = AudioChannelSet::maxChannelsOfNamedLayout;
575
576 beginTest ("maxChannelsOfNamedLayout is non-discrete");
577 expect (AudioChannelSet::channelSetsWithNumberOfChannels (max).size() >= 2);
578
579 beginTest ("channelSetsWithNumberOfChannels returns correct speaker count");
580 {
581 for (auto ch = 1; ch <= max; ++ch)
582 {
583 auto channelSets = AudioChannelSet::channelSetsWithNumberOfChannels (ch);
584
585 for (auto set : channelSets)
586 expect (set.size() == ch);
587 }
588 }
589
590 beginTest ("Ambisonics");
591 {
592 uint64 mask = 0;
593
594 mask |= (1ull << AudioChannelSet::ambisonicACN0);
595 checkAmbisonic (mask, 0, "0th Order Ambisonics");
596
597 mask |= (1ull << AudioChannelSet::ambisonicACN1) | (1ull << AudioChannelSet::ambisonicACN2) | (1ull << AudioChannelSet::ambisonicACN3);
598 checkAmbisonic (mask, 1, "1st Order Ambisonics");
599
600 mask |= (1ull << AudioChannelSet::ambisonicACN4) | (1ull << AudioChannelSet::ambisonicACN5) | (1ull << AudioChannelSet::ambisonicACN6)
601 | (1ull << AudioChannelSet::ambisonicACN7) | (1ull << AudioChannelSet::ambisonicACN8);
602 checkAmbisonic (mask, 2, "2nd Order Ambisonics");
603
604 mask |= (1ull << AudioChannelSet::ambisonicACN9) | (1ull << AudioChannelSet::ambisonicACN10) | (1ull << AudioChannelSet::ambisonicACN11)
605 | (1ull << AudioChannelSet::ambisonicACN12) | (1ull << AudioChannelSet::ambisonicACN13) | (1ull << AudioChannelSet::ambisonicACN14)
606 | (1ull << AudioChannelSet::ambisonicACN15);
607 checkAmbisonic (mask, 3, "3rd Order Ambisonics");
608
609 mask |= (1ull << AudioChannelSet::ambisonicACN16) | (1ull << AudioChannelSet::ambisonicACN17) | (1ull << AudioChannelSet::ambisonicACN18)
610 | (1ull << AudioChannelSet::ambisonicACN19) | (1ull << AudioChannelSet::ambisonicACN20) | (1ull << AudioChannelSet::ambisonicACN21)
611 | (1ull << AudioChannelSet::ambisonicACN22) | (1ull << AudioChannelSet::ambisonicACN23) | (1ull << AudioChannelSet::ambisonicACN24);
612 checkAmbisonic (mask, 4, "4th Order Ambisonics");
613
614 mask |= (1ull << AudioChannelSet::ambisonicACN25) | (1ull << AudioChannelSet::ambisonicACN26) | (1ull << AudioChannelSet::ambisonicACN27)
615 | (1ull << AudioChannelSet::ambisonicACN28) | (1ull << AudioChannelSet::ambisonicACN29) | (1ull << AudioChannelSet::ambisonicACN30)
616 | (1ull << AudioChannelSet::ambisonicACN31) | (1ull << AudioChannelSet::ambisonicACN32) | (1ull << AudioChannelSet::ambisonicACN33)
617 | (1ull << AudioChannelSet::ambisonicACN34) | (1ull << AudioChannelSet::ambisonicACN35);
618 checkAmbisonic (mask, 5, "5th Order Ambisonics");
619 }
620 }
621
622private:
623 void checkAmbisonic (uint64 mask, int order, const char* layoutName)
624 {
625 auto expected = AudioChannelSet::ambisonic (order);
626 auto numChannels = expected.size();
627
628 expect (numChannels == BigInteger ((int64) mask).countNumberOfSetBits());
629 expect (channelSetFromMask (mask) == expected);
630
631 expect (order == expected.getAmbisonicOrder());
632 expect (expected.getDescription() == layoutName);
633
634 auto layouts = AudioChannelSet::channelSetsWithNumberOfChannels (numChannels);
635 expect (layouts.contains (expected));
636
637 for (auto layout : layouts)
638 expect (layout.getAmbisonicOrder() == (layout == expected ? order : -1));
639 }
640
641 static AudioChannelSet channelSetFromMask (uint64 mask)
642 {
643 Array<AudioChannelSet::ChannelType> channels;
644 for (int bit = 0; bit <= 62; ++bit)
645 if ((mask & (1ull << bit)) != 0)
646 channels.add (static_cast<AudioChannelSet::ChannelType> (bit));
647
648 return AudioChannelSet::channelSetWithChannels (channels);
649 }
650};
651
652static AudioChannelSetUnitTest audioChannelSetUnitTest;
653
654#endif
655
656} // namespace juce
int size() const noexcept
Definition juce_Array.h:215
void add(const ElementType &newElement)
Definition juce_Array.h:418
void addChannel(ChannelType newChannelType)
void setRange(int startBit, int numBits, bool shouldBeSet)