OpenShot Audio Library | OpenShotAudio: juce_AudioChannelSet.cpp Source File

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
28 AudioChannelSet::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
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
730int32 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
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 {
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)
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
836 return AudioChannelSet::channelSetWithChannels (channels);
837 }
838};
839
840static AudioChannelSetUnitTest audioChannelSetUnitTest;
841
842#endif
843
844} // namespace juce
juce::Array
Definition juce_Array.h:56
juce::Array::addArray
void addArray(const Type *elementsToAdd, int numElementsToAdd)
Definition juce_Array.h:583
juce::Array::add
void add(const ElementType &newElement)
Definition juce_Array.h:418
juce::AudioChannelSet
Definition juce_AudioChannelSet.h:47
juce::AudioChannelSet::AudioChannelSet
AudioChannelSet()=default
juce::AudioChannelSet::channelSetsWithNumberOfChannels
static Array< AudioChannelSet > JUCE_CALLTYPE channelSetsWithNumberOfChannels(int numChannels)
Definition juce_AudioChannelSet.cpp:644
juce::AudioChannelSet::ChannelType
ChannelType
Definition juce_AudioChannelSet.h:353
juce::AudioChannelSet::ambisonicACN25
@ ambisonicACN25
Definition juce_AudioChannelSet.h:426
juce::AudioChannelSet::ambisonicACN13
@ ambisonicACN13
Definition juce_AudioChannelSet.h:410
juce::AudioChannelSet::ambisonicACN8
@ ambisonicACN8
Definition juce_AudioChannelSet.h:403
juce::AudioChannelSet::ambisonicACN4
@ ambisonicACN4
Definition juce_AudioChannelSet.h:399
juce::AudioChannelSet::ambisonicACN15
@ ambisonicACN15
Definition juce_AudioChannelSet.h:412
juce::AudioChannelSet::ambisonicACN18
@ ambisonicACN18
Definition juce_AudioChannelSet.h:417
juce::AudioChannelSet::ambisonicACN27
@ ambisonicACN27
Definition juce_AudioChannelSet.h:428
juce::AudioChannelSet::ambisonicACN22
@ ambisonicACN22
Definition juce_AudioChannelSet.h:421
juce::AudioChannelSet::ambisonicACN24
@ ambisonicACN24
Definition juce_AudioChannelSet.h:423
juce::AudioChannelSet::ambisonicACN1
@ ambisonicACN1
Definition juce_AudioChannelSet.h:394
juce::AudioChannelSet::ambisonicACN29
@ ambisonicACN29
Definition juce_AudioChannelSet.h:430
juce::AudioChannelSet::ambisonicACN3
@ ambisonicACN3
Definition juce_AudioChannelSet.h:396
juce::AudioChannelSet::ambisonicACN31
@ ambisonicACN31
Definition juce_AudioChannelSet.h:432
juce::AudioChannelSet::ambisonicACN6
@ ambisonicACN6
Definition juce_AudioChannelSet.h:401
juce::AudioChannelSet::ambisonicACN35
@ ambisonicACN35
Definition juce_AudioChannelSet.h:436
juce::AudioChannelSet::ambisonicACN20
@ ambisonicACN20
Definition juce_AudioChannelSet.h:419
juce::AudioChannelSet::ambisonicACN16
@ ambisonicACN16
Definition juce_AudioChannelSet.h:415
juce::AudioChannelSet::ambisonicACN0
@ ambisonicACN0
Definition juce_AudioChannelSet.h:393
juce::AudioChannelSet::ambisonicACN11
@ ambisonicACN11
Definition juce_AudioChannelSet.h:408
juce::AudioChannelSet::ambisonicACN33
@ ambisonicACN33
Definition juce_AudioChannelSet.h:434
juce::AudioChannelSet::ambisonicACN9
@ ambisonicACN9
Definition juce_AudioChannelSet.h:406
juce::AudioChannelSet::addChannel
void addChannel(ChannelType newChannelType)
Definition juce_AudioChannelSet.cpp:523
juce::AudioChannelSet::channelSetWithChannels
static AudioChannelSet JUCE_CALLTYPE channelSetWithChannels(const Array< ChannelType > &)
Definition juce_AudioChannelSet.cpp:710
juce::AudioChannelSet::ambisonic
static AudioChannelSet JUCE_CALLTYPE ambisonic(int order=1)
Definition juce_AudioChannelSet.cpp:572
juce::BigInteger::setRange
BigInteger & setRange(int startBit, int numBits, bool shouldBeSet)
Definition juce_BigInteger.cpp:333
juce::StringArray
Definition juce_StringArray.h:35
juce::StringArray::joinIntoString
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
Definition juce_StringArray.cpp:289
juce::StringArray::add
void add(String stringToAdd)
Definition juce_StringArray.cpp:136
juce::String
Definition juce_String.h:53
juce::String::length
int length() const noexcept
Definition juce_String.cpp:511
juce::String::getIntValue
int getIntValue() const noexcept
Definition juce_String.cpp:1871
juce::UnitTest
Definition juce_UnitTest.h:70
juce::UnitTest::beginTest
void beginTest(const String &testName)
Definition juce_UnitTest.cpp:89
juce::UnitTest::expect
void expect(bool testResult, const String &failureMessage=String())
Definition juce_UnitTest.cpp:97
juce::UnitTest::runTest
virtual void runTest()=0