OpenShot Audio Library | OpenShotAudio  0.6.0
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 
23 namespace juce
24 {
25 
26 
27 
28 AudioChannelSet::AudioChannelSet (uint32 c) : channels (static_cast<int64> (c))
29 {
30 }
31 
32 AudioChannelSet::AudioChannelSet (const std::initializer_list<ChannelType>& c)
33 {
34  for (auto channel : c)
35  addChannel (channel);
36 }
37 
38 bool AudioChannelSet::operator== (const AudioChannelSet& other) const noexcept { return channels == other.channels; }
39 bool AudioChannelSet::operator!= (const AudioChannelSet& other) const noexcept { return channels != other.channels; }
40 bool AudioChannelSet::operator< (const AudioChannelSet& other) const noexcept { return channels < other.channels; }
41 
42 String 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 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 
156 String AudioChannelSet::getAbbreviatedChannelTypeName (AudioChannelSet::ChannelType type)
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 
270 AudioChannelSet::ChannelType AudioChannelSet::getChannelTypeFromAbbreviation (const String& abbr)
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 
380 String AudioChannelSet::getSpeakerArrangementAsString() const
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 
395 AudioChannelSet AudioChannelSet::fromAbbreviatedString (const String& str)
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 
410 String AudioChannelSet::getDescription() const
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 
474 bool AudioChannelSet::isDiscreteLayout() const noexcept
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 
483 int AudioChannelSet::size() const noexcept
484 {
485  return channels.countNumberOfSetBits();
486 }
487 
488 AudioChannelSet::ChannelType AudioChannelSet::getTypeOfChannel (int index) const noexcept
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 
498 int AudioChannelSet::getChannelIndexForType (AudioChannelSet::ChannelType type) const noexcept
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 
513 Array<AudioChannelSet::ChannelType> AudioChannelSet::getChannelTypes() const
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 
523 void AudioChannelSet::addChannel (ChannelType newChannel)
524 {
525  const int bit = static_cast<int> (newChannel);
526  jassert (bit >= 0 && bit < 1024);
527  channels.setBit (bit);
528 }
529 
530 void AudioChannelSet::removeChannel (ChannelType newChannel)
531 {
532  const int bit = static_cast<int> (newChannel);
533  jassert (bit >= 0 && bit < 1024);
534  channels.clearBit (bit);
535 }
536 
537 AudioChannelSet AudioChannelSet::disabled() { return {}; }
538 AudioChannelSet AudioChannelSet::mono() { return AudioChannelSet ({ centre }); }
539 AudioChannelSet AudioChannelSet::stereo() { return AudioChannelSet ({ left, right }); }
540 AudioChannelSet AudioChannelSet::createLCR() { return AudioChannelSet ({ left, right, centre }); }
541 AudioChannelSet AudioChannelSet::createLRS() { return AudioChannelSet ({ left, right, surround }); }
542 AudioChannelSet AudioChannelSet::createLCRS() { return AudioChannelSet ({ left, right, centre, surround }); }
543 AudioChannelSet AudioChannelSet::create5point0() { return AudioChannelSet ({ left, right, centre, leftSurround, rightSurround }); }
544 AudioChannelSet AudioChannelSet::create5point1() { return AudioChannelSet ({ left, right, centre, LFE, leftSurround, rightSurround }); }
545 AudioChannelSet AudioChannelSet::create6point0() { return AudioChannelSet ({ left, right, centre, leftSurround, rightSurround, centreSurround }); }
546 AudioChannelSet AudioChannelSet::create6point1() { return AudioChannelSet ({ left, right, centre, LFE, leftSurround, rightSurround, centreSurround }); }
547 AudioChannelSet AudioChannelSet::create6point0Music() { return AudioChannelSet ({ left, right, leftSurround, rightSurround, leftSurroundSide, rightSurroundSide }); }
548 AudioChannelSet AudioChannelSet::create6point1Music() { return AudioChannelSet ({ left, right, LFE, leftSurround, rightSurround, leftSurroundSide, rightSurroundSide }); }
549 AudioChannelSet AudioChannelSet::create7point0() { return AudioChannelSet ({ left, right, centre, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear }); }
550 AudioChannelSet AudioChannelSet::create7point0SDDS() { return AudioChannelSet ({ left, right, centre, leftSurround, rightSurround, leftCentre, rightCentre }); }
551 AudioChannelSet AudioChannelSet::create7point1() { return AudioChannelSet ({ left, right, centre, LFE, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear }); }
552 AudioChannelSet AudioChannelSet::create7point1SDDS() { return AudioChannelSet ({ left, right, centre, LFE, leftSurround, rightSurround, leftCentre, rightCentre }); }
553 AudioChannelSet AudioChannelSet::quadraphonic() { return AudioChannelSet ({ left, right, leftSurround, rightSurround }); }
554 AudioChannelSet AudioChannelSet::pentagonal() { return AudioChannelSet ({ left, right, centre, leftSurroundRear, rightSurroundRear }); }
555 AudioChannelSet AudioChannelSet::hexagonal() { return AudioChannelSet ({ left, right, centre, centreSurround, leftSurroundRear, rightSurroundRear }); }
556 AudioChannelSet AudioChannelSet::octagonal() { return AudioChannelSet ({ left, right, centre, leftSurround, rightSurround, centreSurround, wideLeft, wideRight }); }
557 AudioChannelSet AudioChannelSet::create5point0point2() { return AudioChannelSet ({ left, right, centre, leftSurround, rightSurround, topSideLeft, topSideRight }); }
558 AudioChannelSet AudioChannelSet::create5point1point2() { return AudioChannelSet ({ left, right, centre, LFE, leftSurround, rightSurround, topSideLeft, topSideRight }); }
559 AudioChannelSet AudioChannelSet::create5point0point4() { return AudioChannelSet ({ left, right, centre, leftSurround, rightSurround, topFrontLeft, topFrontRight, topRearLeft, topRearRight }); }
560 AudioChannelSet AudioChannelSet::create5point1point4() { return AudioChannelSet ({ left, right, centre, LFE, leftSurround, rightSurround, topFrontLeft, topFrontRight, topRearLeft, topRearRight }); }
561 AudioChannelSet AudioChannelSet::create7point0point2() { return AudioChannelSet ({ left, right, centre, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, topSideLeft, topSideRight }); }
562 AudioChannelSet AudioChannelSet::create7point1point2() { return AudioChannelSet ({ left, right, centre, LFE, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, topSideLeft, topSideRight }); }
563 AudioChannelSet AudioChannelSet::create7point0point4() { return AudioChannelSet ({ left, right, centre, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, topFrontLeft, topFrontRight, topRearLeft, topRearRight }); }
564 AudioChannelSet AudioChannelSet::create7point1point4() { return AudioChannelSet ({ left, right, centre, LFE, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, topFrontLeft, topFrontRight, topRearLeft, topRearRight }); }
565 AudioChannelSet AudioChannelSet::create7point0point6() { return AudioChannelSet ({ left, right, centre, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, topFrontLeft, topFrontRight, topSideLeft, topSideRight, topRearLeft, topRearRight }); }
566 AudioChannelSet AudioChannelSet::create7point1point6() { return AudioChannelSet ({ left, right, centre, LFE, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, topFrontLeft, topFrontRight, topSideLeft, topSideRight, topRearLeft, topRearRight }); }
567 AudioChannelSet AudioChannelSet::create9point0point4() { return AudioChannelSet ({ left, right, centre, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, wideLeft, wideRight, topFrontLeft, topFrontRight, topRearLeft, topRearRight }); }
568 AudioChannelSet AudioChannelSet::create9point1point4() { return AudioChannelSet ({ left, right, centre, LFE, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, wideLeft, wideRight, topFrontLeft, topFrontRight, topRearLeft, topRearRight }); }
569 AudioChannelSet AudioChannelSet::create9point0point6() { return AudioChannelSet ({ left, right, centre, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, wideLeft, wideRight, topFrontLeft, topFrontRight, topSideLeft, topSideRight, topRearLeft, topRearRight }); }
570 AudioChannelSet AudioChannelSet::create9point1point6() { return AudioChannelSet ({ left, right, centre, LFE, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, wideLeft, wideRight, topFrontLeft, topFrontRight, topSideLeft, topSideRight, topRearLeft, topRearRight }); }
571 
572 AudioChannelSet AudioChannelSet::ambisonic (int order)
573 {
574  jassert (isPositiveAndBelow (order, 8));
575 
576  static constexpr std::pair<int, int> continuousRanges[] { { ambisonicACN0, ambisonicACN3 },
577  { ambisonicACN4, ambisonicACN35 },
578  { ambisonicACN36, ambisonicACN63 } };
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 
599 int AudioChannelSet::getAmbisonicOrder() const
600 {
601  auto ambisonicOrder = getAmbisonicOrderForNumChannels (size());
602 
603  if (ambisonicOrder >= 0)
604  return (*this == ambisonic (ambisonicOrder) ? ambisonicOrder : -1);
605 
606  return -1;
607 }
608 
609 AudioChannelSet AudioChannelSet::discreteChannels (int numChannels)
610 {
611  AudioChannelSet s;
612  s.channels.setRange (discreteChannel0, numChannels, true);
613  return s;
614 }
615 
616 AudioChannelSet AudioChannelSet::canonicalChannelSet (int numChannels)
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 
630 AudioChannelSet AudioChannelSet::namedChannelSet (int numChannels)
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 
644 Array<AudioChannelSet> AudioChannelSet::channelSetsWithNumberOfChannels (int numChannels)
645 {
646  Array<AudioChannelSet> retval;
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:
661  return { AudioChannelSet::createLCR(),
662  AudioChannelSet::createLRS() };
663  case 4:
664  return { AudioChannelSet::quadraphonic(),
665  AudioChannelSet::createLCRS() };
666  case 5:
667  return { AudioChannelSet::create5point0(),
668  AudioChannelSet::pentagonal() };
669  case 6:
670  return { AudioChannelSet::create5point1(),
671  AudioChannelSet::create6point0(),
672  AudioChannelSet::create6point0Music(),
673  AudioChannelSet::hexagonal() };
674  case 7:
675  return { AudioChannelSet::create7point0(),
676  AudioChannelSet::create7point0SDDS(),
677  AudioChannelSet::create6point1(),
678  AudioChannelSet::create6point1Music() };
679  case 8:
680  return { AudioChannelSet::create7point1(),
681  AudioChannelSet::create7point1SDDS(),
682  AudioChannelSet::octagonal(),
683  AudioChannelSet::create5point1point2() };
684  case 9:
685  return { AudioChannelSet::create7point0point2() };
686  case 10:
687  return { AudioChannelSet::create5point1point4(),
688  AudioChannelSet::create7point1point2() };
689  case 11:
690  return { AudioChannelSet::create7point0point4() };
691  case 12:
692  return { AudioChannelSet::create7point1point4() };
693  case 14:
694  return { AudioChannelSet::create7point1point6() };
695  case 16:
696  return { AudioChannelSet::create9point1point6() };
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 
710 AudioChannelSet JUCE_CALLTYPE AudioChannelSet::channelSetWithChannels (const Array<ChannelType>& channelArray)
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 //==============================================================================
725 AudioChannelSet JUCE_CALLTYPE AudioChannelSet::fromWaveChannelMask (int32 dwChannelMask)
726 {
727  return AudioChannelSet (static_cast<uint32> ((dwChannelMask & ((1 << 18) - 1)) << 1));
728 }
729 
730 int32 AudioChannelSet::getWaveChannelMask() const noexcept
731 {
732  if (channels.getHighestBit() > topRearRight)
733  return -1;
734 
735  return (channels.toInteger() >> 1);
736 }
737 
738 //==============================================================================
739 int 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 
753 class AudioChannelSetUnitTest final : public UnitTest
754 {
755 public:
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  {
771  auto channelSets = AudioChannelSet::channelSetsWithNumberOfChannels (ch);
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)
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 
810 private:
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 
836  return AudioChannelSet::channelSetWithChannels (channels);
837  }
838 };
839 
840 static 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 Array< AudioChannelSet > JUCE_CALLTYPE channelSetsWithNumberOfChannels(int numChannels)
void addChannel(ChannelType newChannelType)
static AudioChannelSet JUCE_CALLTYPE channelSetWithChannels(const Array< ChannelType > &)
static AudioChannelSet JUCE_CALLTYPE ambisonic(int order=1)
BigInteger & setRange(int startBit, int numBits, bool shouldBeSet)
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
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