OpenShot Audio Library | OpenShotAudio 0.4.0
 
Loading...
Searching...
No Matches
juce_AudioChannelSet.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
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 std::initializer_list<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
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 ambisonicACN16: return NEEDS_TRANS ("Ambisonic 16");
91 case ambisonicACN17: return NEEDS_TRANS ("Ambisonic 17");
92 case ambisonicACN18: return NEEDS_TRANS ("Ambisonic 18");
93 case ambisonicACN19: return NEEDS_TRANS ("Ambisonic 19");
94 case ambisonicACN20: return NEEDS_TRANS ("Ambisonic 20");
95 case ambisonicACN21: return NEEDS_TRANS ("Ambisonic 21");
96 case ambisonicACN22: return NEEDS_TRANS ("Ambisonic 22");
97 case ambisonicACN23: return NEEDS_TRANS ("Ambisonic 23");
98 case ambisonicACN24: return NEEDS_TRANS ("Ambisonic 24");
99 case ambisonicACN25: return NEEDS_TRANS ("Ambisonic 25");
100 case ambisonicACN26: return NEEDS_TRANS ("Ambisonic 26");
101 case ambisonicACN27: return NEEDS_TRANS ("Ambisonic 27");
102 case ambisonicACN28: return NEEDS_TRANS ("Ambisonic 28");
103 case ambisonicACN29: return NEEDS_TRANS ("Ambisonic 29");
104 case ambisonicACN30: return NEEDS_TRANS ("Ambisonic 30");
105 case ambisonicACN31: return NEEDS_TRANS ("Ambisonic 31");
106 case ambisonicACN32: return NEEDS_TRANS ("Ambisonic 32");
107 case ambisonicACN33: return NEEDS_TRANS ("Ambisonic 33");
108 case ambisonicACN34: return NEEDS_TRANS ("Ambisonic 34");
109 case ambisonicACN35: return NEEDS_TRANS ("Ambisonic 35");
110 case ambisonicACN36: return NEEDS_TRANS ("Ambisonic 36");
111 case ambisonicACN37: return NEEDS_TRANS ("Ambisonic 37");
112 case ambisonicACN38: return NEEDS_TRANS ("Ambisonic 38");
113 case ambisonicACN39: return NEEDS_TRANS ("Ambisonic 39");
114 case ambisonicACN40: return NEEDS_TRANS ("Ambisonic 40");
115 case ambisonicACN41: return NEEDS_TRANS ("Ambisonic 41");
116 case ambisonicACN42: return NEEDS_TRANS ("Ambisonic 42");
117 case ambisonicACN43: return NEEDS_TRANS ("Ambisonic 43");
118 case ambisonicACN44: return NEEDS_TRANS ("Ambisonic 44");
119 case ambisonicACN45: return NEEDS_TRANS ("Ambisonic 45");
120 case ambisonicACN46: return NEEDS_TRANS ("Ambisonic 46");
121 case ambisonicACN47: return NEEDS_TRANS ("Ambisonic 47");
122 case ambisonicACN48: return NEEDS_TRANS ("Ambisonic 48");
123 case ambisonicACN49: return NEEDS_TRANS ("Ambisonic 49");
124 case ambisonicACN50: return NEEDS_TRANS ("Ambisonic 50");
125 case ambisonicACN51: return NEEDS_TRANS ("Ambisonic 51");
126 case ambisonicACN52: return NEEDS_TRANS ("Ambisonic 52");
127 case ambisonicACN53: return NEEDS_TRANS ("Ambisonic 53");
128 case ambisonicACN54: return NEEDS_TRANS ("Ambisonic 54");
129 case ambisonicACN55: return NEEDS_TRANS ("Ambisonic 55");
130 case ambisonicACN56: return NEEDS_TRANS ("Ambisonic 56");
131 case ambisonicACN57: return NEEDS_TRANS ("Ambisonic 57");
132 case ambisonicACN58: return NEEDS_TRANS ("Ambisonic 58");
133 case ambisonicACN59: return NEEDS_TRANS ("Ambisonic 59");
134 case ambisonicACN60: return NEEDS_TRANS ("Ambisonic 60");
135 case ambisonicACN61: return NEEDS_TRANS ("Ambisonic 61");
136 case ambisonicACN62: return NEEDS_TRANS ("Ambisonic 62");
137 case ambisonicACN63: return NEEDS_TRANS ("Ambisonic 63");
138 case bottomFrontLeft: return NEEDS_TRANS ("Bottom Front Left");
139 case bottomFrontCentre: return NEEDS_TRANS ("Bottom Front Centre");
140 case bottomFrontRight: return NEEDS_TRANS ("Bottom Front Right");
141 case proximityLeft: return NEEDS_TRANS ("Proximity Left");
142 case proximityRight: return NEEDS_TRANS ("Proximity Right");
143 case bottomSideLeft: return NEEDS_TRANS ("Bottom Side Left");
144 case bottomSideRight: return NEEDS_TRANS ("Bottom Side Right");
145 case bottomRearLeft: return NEEDS_TRANS ("Bottom Rear Left");
146 case bottomRearCentre: return NEEDS_TRANS ("Bottom Rear Centre");
147 case bottomRearRight: return NEEDS_TRANS ("Bottom Rear Right");
148 case discreteChannel0:
149 case unknown:
150 default: break;
151 }
152
153 return "Unknown";
154}
155
157{
158 if (type >= discreteChannel0)
159 return String (type - discreteChannel0 + 1);
160
161 switch (type)
162 {
163 case left: return "L";
164 case right: return "R";
165 case centre: return "C";
166 case LFE: return "Lfe";
167 case leftSurround: return "Ls";
168 case rightSurround: return "Rs";
169 case leftCentre: return "Lc";
170 case rightCentre: return "Rc";
171 case centreSurround: return "Cs";
172 case leftSurroundRear: return "Lrs";
173 case rightSurroundRear: return "Rrs";
174 case topMiddle: return "Tm";
175 case topFrontLeft: return "Tfl";
176 case topFrontCentre: return "Tfc";
177 case topFrontRight: return "Tfr";
178 case topRearLeft: return "Trl";
179 case topRearCentre: return "Trc";
180 case topRearRight: return "Trr";
181 case wideLeft: return "Wl";
182 case wideRight: return "Wr";
183 case LFE2: return "Lfe2";
184 case leftSurroundSide: return "Lss";
185 case rightSurroundSide: return "Rss";
186 case ambisonicACN0: return "ACN0";
187 case ambisonicACN1: return "ACN1";
188 case ambisonicACN2: return "ACN2";
189 case ambisonicACN3: return "ACN3";
190 case ambisonicACN4: return "ACN4";
191 case ambisonicACN5: return "ACN5";
192 case ambisonicACN6: return "ACN6";
193 case ambisonicACN7: return "ACN7";
194 case ambisonicACN8: return "ACN8";
195 case ambisonicACN9: return "ACN9";
196 case ambisonicACN10: return "ACN10";
197 case ambisonicACN11: return "ACN11";
198 case ambisonicACN12: return "ACN12";
199 case ambisonicACN13: return "ACN13";
200 case ambisonicACN14: return "ACN14";
201 case ambisonicACN15: return "ACN15";
202 case ambisonicACN16: return "ACN16";
203 case ambisonicACN17: return "ACN17";
204 case ambisonicACN18: return "ACN18";
205 case ambisonicACN19: return "ACN19";
206 case ambisonicACN20: return "ACN20";
207 case ambisonicACN21: return "ACN21";
208 case ambisonicACN22: return "ACN22";
209 case ambisonicACN23: return "ACN23";
210 case ambisonicACN24: return "ACN24";
211 case ambisonicACN25: return "ACN25";
212 case ambisonicACN26: return "ACN26";
213 case ambisonicACN27: return "ACN27";
214 case ambisonicACN28: return "ACN28";
215 case ambisonicACN29: return "ACN29";
216 case ambisonicACN30: return "ACN30";
217 case ambisonicACN31: return "ACN31";
218 case ambisonicACN32: return "ACN32";
219 case ambisonicACN33: return "ACN33";
220 case ambisonicACN34: return "ACN34";
221 case ambisonicACN35: return "ACN35";
222 case ambisonicACN36: return "ACN36";
223 case ambisonicACN37: return "ACN37";
224 case ambisonicACN38: return "ACN38";
225 case ambisonicACN39: return "ACN39";
226 case ambisonicACN40: return "ACN40";
227 case ambisonicACN41: return "ACN41";
228 case ambisonicACN42: return "ACN42";
229 case ambisonicACN43: return "ACN43";
230 case ambisonicACN44: return "ACN44";
231 case ambisonicACN45: return "ACN45";
232 case ambisonicACN46: return "ACN46";
233 case ambisonicACN47: return "ACN47";
234 case ambisonicACN48: return "ACN48";
235 case ambisonicACN49: return "ACN49";
236 case ambisonicACN50: return "ACN50";
237 case ambisonicACN51: return "ACN51";
238 case ambisonicACN52: return "ACN52";
239 case ambisonicACN53: return "ACN53";
240 case ambisonicACN54: return "ACN54";
241 case ambisonicACN55: return "ACN55";
242 case ambisonicACN56: return "ACN56";
243 case ambisonicACN57: return "ACN57";
244 case ambisonicACN58: return "ACN58";
245 case ambisonicACN59: return "ACN59";
246 case ambisonicACN60: return "ACN60";
247 case ambisonicACN61: return "ACN61";
248 case ambisonicACN62: return "ACN62";
249 case ambisonicACN63: return "ACN63";
250 case topSideLeft: return "Tsl";
251 case topSideRight: return "Tsr";
252 case bottomFrontLeft: return "Bfl";
253 case bottomFrontCentre: return "Bfc";
254 case bottomFrontRight: return "Bfr";
255 case proximityLeft: return "Pl";
256 case proximityRight: return "Pr";
257 case bottomSideLeft: return "Bsl";
258 case bottomSideRight: return "Bsr";
259 case bottomRearLeft: return "Brl";
260 case bottomRearCentre: return "Brc";
261 case bottomRearRight: return "Brr";
262 case discreteChannel0:
263 case unknown:
264 default: break;
265 }
266
267 return {};
268}
269
271{
272 if (abbr.length() > 0 && (abbr[0] >= '0' && abbr[0] <= '9'))
273 return static_cast<AudioChannelSet::ChannelType> (static_cast<int> (discreteChannel0)
274 + abbr.getIntValue() - 1);
275
276 if (abbr == "L") return left;
277 if (abbr == "R") return right;
278 if (abbr == "C") return centre;
279 if (abbr == "Lfe") return LFE;
280 if (abbr == "Ls") return leftSurround;
281 if (abbr == "Rs") return rightSurround;
282 if (abbr == "Lc") return leftCentre;
283 if (abbr == "Rc") return rightCentre;
284 if (abbr == "Cs") return centreSurround;
285 if (abbr == "Lrs") return leftSurroundRear;
286 if (abbr == "Rrs") return rightSurroundRear;
287 if (abbr == "Tm") return topMiddle;
288 if (abbr == "Tfl") return topFrontLeft;
289 if (abbr == "Tfc") return topFrontCentre;
290 if (abbr == "Tfr") return topFrontRight;
291 if (abbr == "Trl") return topRearLeft;
292 if (abbr == "Trc") return topRearCentre;
293 if (abbr == "Trr") return topRearRight;
294 if (abbr == "Wl") return wideLeft;
295 if (abbr == "Wr") return wideRight;
296 if (abbr == "Lfe2") return LFE2;
297 if (abbr == "Lss") return leftSurroundSide;
298 if (abbr == "Rss") return rightSurroundSide;
299 if (abbr == "W") return ambisonicW;
300 if (abbr == "X") return ambisonicX;
301 if (abbr == "Y") return ambisonicY;
302 if (abbr == "Z") return ambisonicZ;
303 if (abbr == "ACN0") return ambisonicACN0;
304 if (abbr == "ACN1") return ambisonicACN1;
305 if (abbr == "ACN2") return ambisonicACN2;
306 if (abbr == "ACN3") return ambisonicACN3;
307 if (abbr == "ACN4") return ambisonicACN4;
308 if (abbr == "ACN5") return ambisonicACN5;
309 if (abbr == "ACN6") return ambisonicACN6;
310 if (abbr == "ACN7") return ambisonicACN7;
311 if (abbr == "ACN8") return ambisonicACN8;
312 if (abbr == "ACN9") return ambisonicACN9;
313 if (abbr == "ACN10") return ambisonicACN10;
314 if (abbr == "ACN11") return ambisonicACN11;
315 if (abbr == "ACN12") return ambisonicACN12;
316 if (abbr == "ACN13") return ambisonicACN13;
317 if (abbr == "ACN14") return ambisonicACN14;
318 if (abbr == "ACN15") return ambisonicACN15;
319 if (abbr == "ACN16") return ambisonicACN16;
320 if (abbr == "ACN17") return ambisonicACN17;
321 if (abbr == "ACN18") return ambisonicACN18;
322 if (abbr == "ACN19") return ambisonicACN19;
323 if (abbr == "ACN20") return ambisonicACN20;
324 if (abbr == "ACN21") return ambisonicACN21;
325 if (abbr == "ACN22") return ambisonicACN22;
326 if (abbr == "ACN23") return ambisonicACN23;
327 if (abbr == "ACN24") return ambisonicACN24;
328 if (abbr == "ACN25") return ambisonicACN25;
329 if (abbr == "ACN26") return ambisonicACN26;
330 if (abbr == "ACN27") return ambisonicACN27;
331 if (abbr == "ACN28") return ambisonicACN28;
332 if (abbr == "ACN29") return ambisonicACN29;
333 if (abbr == "ACN30") return ambisonicACN30;
334 if (abbr == "ACN31") return ambisonicACN31;
335 if (abbr == "ACN32") return ambisonicACN32;
336 if (abbr == "ACN33") return ambisonicACN33;
337 if (abbr == "ACN34") return ambisonicACN34;
338 if (abbr == "ACN35") return ambisonicACN35;
339 if (abbr == "ACN36") return ambisonicACN36;
340 if (abbr == "ACN37") return ambisonicACN37;
341 if (abbr == "ACN38") return ambisonicACN38;
342 if (abbr == "ACN39") return ambisonicACN39;
343 if (abbr == "ACN40") return ambisonicACN40;
344 if (abbr == "ACN41") return ambisonicACN41;
345 if (abbr == "ACN42") return ambisonicACN42;
346 if (abbr == "ACN43") return ambisonicACN43;
347 if (abbr == "ACN44") return ambisonicACN44;
348 if (abbr == "ACN45") return ambisonicACN45;
349 if (abbr == "ACN46") return ambisonicACN46;
350 if (abbr == "ACN47") return ambisonicACN47;
351 if (abbr == "ACN48") return ambisonicACN48;
352 if (abbr == "ACN49") return ambisonicACN49;
353 if (abbr == "ACN50") return ambisonicACN50;
354 if (abbr == "ACN51") return ambisonicACN51;
355 if (abbr == "ACN52") return ambisonicACN52;
356 if (abbr == "ACN53") return ambisonicACN53;
357 if (abbr == "ACN54") return ambisonicACN54;
358 if (abbr == "ACN55") return ambisonicACN55;
359 if (abbr == "ACN56") return ambisonicACN56;
360 if (abbr == "ACN57") return ambisonicACN57;
361 if (abbr == "ACN58") return ambisonicACN58;
362 if (abbr == "ACN59") return ambisonicACN59;
363 if (abbr == "ACN60") return ambisonicACN60;
364 if (abbr == "ACN61") return ambisonicACN61;
365 if (abbr == "ACN62") return ambisonicACN62;
366 if (abbr == "ACN63") return ambisonicACN63;
367 if (abbr == "Tsl") return topSideLeft;
368 if (abbr == "Tsr") return topSideRight;
369 if (abbr == "Bfl") return bottomFrontLeft;
370 if (abbr == "Bfc") return bottomFrontCentre;
371 if (abbr == "Bfr") return bottomFrontRight;
372 if (abbr == "Bsl") return bottomSideLeft;
373 if (abbr == "Bsr") return bottomSideRight;
374 if (abbr == "Brl") return bottomRearLeft;
375 if (abbr == "Brc") return bottomRearCentre;
376 if (abbr == "Brr") return bottomRearRight;
377 return unknown;
378}
379
381{
382 StringArray speakerTypes;
383
384 for (auto& speaker : getChannelTypes())
385 {
386 auto name = getAbbreviatedChannelTypeName (speaker);
387
388 if (name.isNotEmpty())
389 speakerTypes.add (name);
390 }
391
392 return speakerTypes.joinIntoString (" ");
393}
394
396{
397 AudioChannelSet set;
398
399 for (auto& abbr : StringArray::fromTokens (str, true))
400 {
401 auto type = getChannelTypeFromAbbreviation (abbr);
402
403 if (type != unknown)
404 set.addChannel (type);
405 }
406
407 return set;
408}
409
411{
412 if (isDiscreteLayout()) return "Discrete #" + String (size());
413 if (*this == disabled()) return "Disabled";
414 if (*this == mono()) return "Mono";
415 if (*this == stereo()) return "Stereo";
416
417 if (*this == createLCR()) return "LCR";
418 if (*this == createLRS()) return "LRS";
419 if (*this == createLCRS()) return "LCRS";
420
421 if (*this == create5point0()) return "5.0 Surround";
422 if (*this == create5point0point2()) return "5.0.2 Surround";
423 if (*this == create5point0point4()) return "5.0.4 Surround";
424 if (*this == create5point1()) return "5.1 Surround";
425 if (*this == create5point1point2()) return "5.1.2 Surround";
426 if (*this == create5point1point4()) return "5.1.4 Surround";
427 if (*this == create6point0()) return "6.0 Surround";
428 if (*this == create6point1()) return "6.1 Surround";
429 if (*this == create6point0Music()) return "6.0 (Music) Surround";
430 if (*this == create6point1Music()) return "6.1 (Music) Surround";
431 if (*this == create7point0()) return "7.0 Surround";
432 if (*this == create7point1()) return "7.1 Surround";
433 if (*this == create7point0SDDS()) return "7.0 Surround SDDS";
434 if (*this == create7point1SDDS()) return "7.1 Surround SDDS";
435 if (*this == create7point0point2()) return "7.0.2 Surround";
436 if (*this == create7point0point4()) return "7.0.4 Surround";
437 if (*this == create7point0point6()) return "7.0.6 Surround";
438 if (*this == create7point1point2()) return "7.1.2 Surround";
439 if (*this == create7point1point4()) return "7.1.4 Surround";
440 if (*this == create7point1point6()) return "7.1.6 Surround";
441 if (*this == create9point0point4()) return "9.0.4 Surround";
442 if (*this == create9point1point4()) return "9.1.4 Surround";
443 if (*this == create9point0point6()) return "9.0.6 Surround";
444 if (*this == create9point1point6()) return "9.1.6 Surround";
445
446 if (*this == quadraphonic()) return "Quadraphonic";
447 if (*this == pentagonal()) return "Pentagonal";
448 if (*this == hexagonal()) return "Hexagonal";
449 if (*this == octagonal()) return "Octagonal";
450
451 // ambisonics
452 {
453 auto order = getAmbisonicOrder();
454
455 if (order >= 0)
456 {
457 String suffix;
458
459 switch (order)
460 {
461 case 1: suffix = "st"; break;
462 case 2: suffix = "nd"; break;
463 case 3: suffix = "rd"; break;
464 default: suffix = "th"; break;
465 }
466
467 return String (order) + suffix + " Order Ambisonics";
468 }
469 }
470
471 return "Unknown";
472}
473
475{
476 const auto channelTypes = getChannelTypes();
477
478 return std::none_of (std::begin (channelTypes),
479 std::end (channelTypes),
480 [] (const auto& t) { return t < discreteChannel0; });
481}
482
483int AudioChannelSet::size() const noexcept
484{
485 return channels.countNumberOfSetBits();
486}
487
489{
490 int bit = channels.findNextSetBit (0);
491
492 for (int i = 0; i < index && bit >= 0; ++i)
493 bit = channels.findNextSetBit (bit + 1);
494
495 return static_cast<ChannelType> (bit);
496}
497
499{
500 int idx = 0;
501
502 for (int bit = channels.findNextSetBit (0); bit >= 0; bit = channels.findNextSetBit (bit + 1))
503 {
504 if (static_cast<ChannelType> (bit) == type)
505 return idx;
506
507 idx++;
508 }
509
510 return -1;
511}
512
514{
515 Array<ChannelType> result;
516
517 for (int bit = channels.findNextSetBit (0); bit >= 0; bit = channels.findNextSetBit (bit + 1))
518 result.add (static_cast<ChannelType> (bit));
519
520 return result;
521}
522
524{
525 const int bit = static_cast<int> (newChannel);
526 jassert (bit >= 0 && bit < 1024);
527 channels.setBit (bit);
528}
529
531{
532 const int bit = static_cast<int> (newChannel);
533 jassert (bit >= 0 && bit < 1024);
534 channels.clearBit (bit);
535}
536
571
573{
574 jassert (isPositiveAndBelow (order, 8));
575
576 static constexpr std::pair<int, int> continuousRanges[] { { ambisonicACN0, ambisonicACN3 },
579
580 AudioChannelSet set;
581
582 const auto setBits = [&set] (auto range, auto maxNumToSet)
583 {
584 const auto numToSet = std::min (maxNumToSet, range.second - range.first + 1);
585 set.channels.setRange (range.first, numToSet, true);
586 return numToSet;
587 };
588
589 const auto numAmbisonicChannels = square (order + 1);
590
591 for (int rangeIdx = 0, bitsSet = 0; bitsSet < numAmbisonicChannels; ++rangeIdx)
592 {
593 bitsSet += setBits (continuousRanges[rangeIdx], numAmbisonicChannels - bitsSet);
594 }
595
596 return set;
597}
598
600{
601 auto ambisonicOrder = getAmbisonicOrderForNumChannels (size());
602
603 if (ambisonicOrder >= 0)
604 return (*this == ambisonic (ambisonicOrder) ? ambisonicOrder : -1);
605
606 return -1;
607}
608
610{
612 s.channels.setRange (discreteChannel0, numChannels, true);
613 return s;
614}
615
617{
618 if (numChannels == 1) return AudioChannelSet::mono();
619 if (numChannels == 2) return AudioChannelSet::stereo();
620 if (numChannels == 3) return AudioChannelSet::createLCR();
621 if (numChannels == 4) return AudioChannelSet::quadraphonic();
622 if (numChannels == 5) return AudioChannelSet::create5point0();
623 if (numChannels == 6) return AudioChannelSet::create5point1();
624 if (numChannels == 7) return AudioChannelSet::create7point0();
625 if (numChannels == 8) return AudioChannelSet::create7point1();
626
627 return discreteChannels (numChannels);
628}
629
631{
632 if (numChannels == 1) return AudioChannelSet::mono();
633 if (numChannels == 2) return AudioChannelSet::stereo();
634 if (numChannels == 3) return AudioChannelSet::createLCR();
635 if (numChannels == 4) return AudioChannelSet::quadraphonic();
636 if (numChannels == 5) return AudioChannelSet::create5point0();
637 if (numChannels == 6) return AudioChannelSet::create5point1();
638 if (numChannels == 7) return AudioChannelSet::create7point0();
639 if (numChannels == 8) return AudioChannelSet::create7point1();
640
641 return {};
642}
643
645{
647
648 if (numChannels != 0)
649 {
650 retval.add (AudioChannelSet::discreteChannels (numChannels));
651
652 retval.addArray ([numChannels]() -> Array<AudioChannelSet>
653 {
654 switch (numChannels)
655 {
656 case 1:
657 return { AudioChannelSet::mono() };
658 case 2:
659 return { AudioChannelSet::stereo() };
660 case 3:
663 case 4:
666 case 5:
669 case 6:
674 case 7:
679 case 8:
684 case 9:
686 case 10:
689 case 11:
691 case 12:
693 case 14:
695 case 16:
697 }
698
699 return {};
700 }());
701
702 auto order = getAmbisonicOrderForNumChannels (numChannels);
703 if (order >= 0)
704 retval.add (AudioChannelSet::ambisonic (order));
705 }
706
707 return retval;
708}
709
711{
712 AudioChannelSet set;
713
714 for (auto ch : channelArray)
715 {
716 jassert (! set.channels[static_cast<int> (ch)]);
717
718 set.addChannel (ch);
719 }
720
721 return set;
722}
723
724//==============================================================================
725AudioChannelSet JUCE_CALLTYPE AudioChannelSet::fromWaveChannelMask (int32 dwChannelMask)
726{
727 return AudioChannelSet (static_cast<uint32> ((dwChannelMask & ((1 << 18) - 1)) << 1));
728}
729
731{
732 if (channels.getHighestBit() > topRearRight)
733 return -1;
734
735 return (channels.toInteger() >> 1);
736}
737
738//==============================================================================
739int AudioChannelSet::getAmbisonicOrderForNumChannels (int numChannels, int maxOrderToCheck)
740{
741 for (auto i = 0; i <= maxOrderToCheck; ++i)
742 if (numChannels == square (i + 1))
743 return i;
744
745 return -1;
746}
747
748
749//==============================================================================
750//==============================================================================
751#if JUCE_UNIT_TESTS
752
753class AudioChannelSetUnitTest final : public UnitTest
754{
755public:
756 AudioChannelSetUnitTest()
757 : UnitTest ("AudioChannelSetUnitTest", UnitTestCategories::audio)
758 {}
759
760 void runTest() override
761 {
762 auto max = AudioChannelSet::maxChannelsOfNamedLayout;
763
764 beginTest ("maxChannelsOfNamedLayout is non-discrete");
765 expect (AudioChannelSet::channelSetsWithNumberOfChannels (max).size() >= 2);
766
767 beginTest ("channelSetsWithNumberOfChannels returns correct speaker count");
768 {
769 for (auto ch = 1; ch <= max; ++ch)
770 {
772
773 for (auto set : channelSets)
774 expect (set.size() == ch);
775 }
776 }
777
778 beginTest ("Ambisonics");
779 {
780 uint64 mask = 0;
781
782 mask |= (1ull << AudioChannelSet::ambisonicACN0);
783 checkAmbisonic (mask, 0, "0th Order Ambisonics");
784
785 mask |= (1ull << AudioChannelSet::ambisonicACN1) | (1ull << AudioChannelSet::ambisonicACN2) | (1ull << AudioChannelSet::ambisonicACN3);
786 checkAmbisonic (mask, 1, "1st Order Ambisonics");
787
788 mask |= (1ull << AudioChannelSet::ambisonicACN4) | (1ull << AudioChannelSet::ambisonicACN5) | (1ull << AudioChannelSet::ambisonicACN6)
789 | (1ull << AudioChannelSet::ambisonicACN7) | (1ull << AudioChannelSet::ambisonicACN8);
790 checkAmbisonic (mask, 2, "2nd Order Ambisonics");
791
792 mask |= (1ull << AudioChannelSet::ambisonicACN9) | (1ull << AudioChannelSet::ambisonicACN10) | (1ull << AudioChannelSet::ambisonicACN11)
793 | (1ull << AudioChannelSet::ambisonicACN12) | (1ull << AudioChannelSet::ambisonicACN13) | (1ull << AudioChannelSet::ambisonicACN14)
794 | (1ull << AudioChannelSet::ambisonicACN15);
795 checkAmbisonic (mask, 3, "3rd Order Ambisonics");
796
797 mask |= (1ull << AudioChannelSet::ambisonicACN16) | (1ull << AudioChannelSet::ambisonicACN17) | (1ull << AudioChannelSet::ambisonicACN18)
798 | (1ull << AudioChannelSet::ambisonicACN19) | (1ull << AudioChannelSet::ambisonicACN20) | (1ull << AudioChannelSet::ambisonicACN21)
799 | (1ull << AudioChannelSet::ambisonicACN22) | (1ull << AudioChannelSet::ambisonicACN23) | (1ull << AudioChannelSet::ambisonicACN24);
800 checkAmbisonic (mask, 4, "4th Order Ambisonics");
801
802 mask |= (1ull << AudioChannelSet::ambisonicACN25) | (1ull << AudioChannelSet::ambisonicACN26) | (1ull << AudioChannelSet::ambisonicACN27)
803 | (1ull << AudioChannelSet::ambisonicACN28) | (1ull << AudioChannelSet::ambisonicACN29) | (1ull << AudioChannelSet::ambisonicACN30)
804 | (1ull << AudioChannelSet::ambisonicACN31) | (1ull << AudioChannelSet::ambisonicACN32) | (1ull << AudioChannelSet::ambisonicACN33)
805 | (1ull << AudioChannelSet::ambisonicACN34) | (1ull << AudioChannelSet::ambisonicACN35);
806 checkAmbisonic (mask, 5, "5th Order Ambisonics");
807 }
808 }
809
810private:
811 void checkAmbisonic (uint64 mask, int order, const char* layoutName)
812 {
813 auto expected = AudioChannelSet::ambisonic (order);
814 auto numChannels = expected.size();
815
816 expect (numChannels == BigInteger ((int64) mask).countNumberOfSetBits());
817 expect (channelSetFromMask (mask) == expected);
818
819 expect (order == expected.getAmbisonicOrder());
820 expect (expected.getDescription() == layoutName);
821
822 auto layouts = AudioChannelSet::channelSetsWithNumberOfChannels (numChannels);
823 expect (layouts.contains (expected));
824
825 for (auto layout : layouts)
826 expect (layout.getAmbisonicOrder() == (layout == expected ? order : -1));
827 }
828
829 static AudioChannelSet channelSetFromMask (uint64 mask)
830 {
831 Array<AudioChannelSet::ChannelType> channels;
832 for (int bit = 0; bit <= 62; ++bit)
833 if ((mask & (1ull << bit)) != 0)
834 channels.add (static_cast<AudioChannelSet::ChannelType> (bit));
835
837 }
838};
839
840static AudioChannelSetUnitTest audioChannelSetUnitTest;
841
842#endif
843
844} // namespace juce
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Definition juce_Array.h:583
void add(const ElementType &newElement)
Definition juce_Array.h:418
static AudioChannelSet JUCE_CALLTYPE create7point1()
static AudioChannelSet JUCE_CALLTYPE namedChannelSet(int numChannels)
static AudioChannelSet JUCE_CALLTYPE quadraphonic()
static AudioChannelSet JUCE_CALLTYPE create5point0point2()
static AudioChannelSet JUCE_CALLTYPE create5point0()
static ChannelType JUCE_CALLTYPE getChannelTypeFromAbbreviation(const String &abbreviation)
static AudioChannelSet JUCE_CALLTYPE create9point0point4()
static AudioChannelSet JUCE_CALLTYPE create6point0()
bool isDiscreteLayout() const noexcept
static AudioChannelSet JUCE_CALLTYPE create6point1Music()
static AudioChannelSet JUCE_CALLTYPE create5point0point4()
void removeChannel(ChannelType newChannelType)
static AudioChannelSet JUCE_CALLTYPE create5point1point4()
static AudioChannelSet JUCE_CALLTYPE disabled()
static AudioChannelSet JUCE_CALLTYPE hexagonal()
static AudioChannelSet fromAbbreviatedString(const String &set)
static AudioChannelSet JUCE_CALLTYPE mono()
static AudioChannelSet JUCE_CALLTYPE create7point0point4()
static AudioChannelSet JUCE_CALLTYPE createLRS()
static Array< AudioChannelSet > JUCE_CALLTYPE channelSetsWithNumberOfChannels(int numChannels)
static AudioChannelSet JUCE_CALLTYPE stereo()
static AudioChannelSet JUCE_CALLTYPE octagonal()
static AudioChannelSet JUCE_CALLTYPE create6point1()
static AudioChannelSet JUCE_CALLTYPE create9point1point4()
static AudioChannelSet JUCE_CALLTYPE create9point0point6()
void addChannel(ChannelType newChannelType)
static AudioChannelSet JUCE_CALLTYPE create5point1()
static AudioChannelSet JUCE_CALLTYPE create7point0SDDS()
static AudioChannelSet JUCE_CALLTYPE create5point1point2()
static int getAmbisonicOrderForNumChannels(int numChannels, int maxOrderToCheck=7)
ChannelType getTypeOfChannel(int channelIndex) const noexcept
static AudioChannelSet JUCE_CALLTYPE create9point1point6()
static AudioChannelSet JUCE_CALLTYPE create6point0Music()
static String JUCE_CALLTYPE getChannelTypeName(ChannelType)
static AudioChannelSet JUCE_CALLTYPE create7point0point2()
static AudioChannelSet JUCE_CALLTYPE create7point1SDDS()
String getSpeakerArrangementAsString() const
static AudioChannelSet JUCE_CALLTYPE create7point0()
static AudioChannelSet JUCE_CALLTYPE channelSetWithChannels(const Array< ChannelType > &)
static AudioChannelSet JUCE_CALLTYPE ambisonic(int order=1)
static AudioChannelSet JUCE_CALLTYPE createLCRS()
static AudioChannelSet JUCE_CALLTYPE create7point1point2()
static AudioChannelSet JUCE_CALLTYPE canonicalChannelSet(int numChannels)
static AudioChannelSet JUCE_CALLTYPE discreteChannels(int numChannels)
static AudioChannelSet JUCE_CALLTYPE create7point0point6()
static AudioChannelSet JUCE_CALLTYPE create7point1point6()
static AudioChannelSet JUCE_CALLTYPE createLCR()
static AudioChannelSet JUCE_CALLTYPE fromWaveChannelMask(int32 dwChannelMask)
static AudioChannelSet JUCE_CALLTYPE pentagonal()
int getChannelIndexForType(ChannelType type) const noexcept
static String JUCE_CALLTYPE getAbbreviatedChannelTypeName(ChannelType)
int32 getWaveChannelMask() const noexcept
static AudioChannelSet JUCE_CALLTYPE create7point1point4()
Array< ChannelType > getChannelTypes() const
BigInteger & setRange(int startBit, int numBits, bool shouldBeSet)
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
static StringArray fromTokens(StringRef stringToTokenise, bool preserveQuotedStrings)
void add(String stringToAdd)
int length() const noexcept
int getIntValue() const noexcept
void beginTest(const String &testName)
void expect(bool testResult, const String &failureMessage=String())
virtual void runTest()=0