OpenShot Library | libopenshot-audio  0.1.9
juce_CoreAudioFormat.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  By using JUCE, you agree to the terms of both the JUCE 5 End-User License
11  Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
12  27th April 2017).
13 
14  End User License Agreement: www.juce.com/juce-5-licence
15  Privacy Policy: www.juce.com/juce-5-privacy-policy
16 
17  Or: You may also use this code under the terms of the GPL v3 (see
18  www.gnu.org/licenses).
19 
20  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22  DISCLAIMED.
23 
24  ==============================================================================
25 */
26 
27 #if JUCE_MAC || JUCE_IOS
28 
29 #include "../../juce_audio_basics/native/juce_mac_CoreAudioLayouts.h"
30 
31 namespace juce
32 {
33 
34 //==============================================================================
35 namespace
36 {
37  const char* const coreAudioFormatName = "CoreAudio supported file";
38 
39  StringArray findFileExtensionsForCoreAudioCodecs()
40  {
41  StringArray extensionsArray;
42  CFArrayRef extensions = nullptr;
43  UInt32 sizeOfArray = sizeof (extensions);
44 
45  if (AudioFileGetGlobalInfo (kAudioFileGlobalInfo_AllExtensions, 0, nullptr, &sizeOfArray, &extensions) == noErr)
46  {
47  auto numValues = CFArrayGetCount (extensions);
48 
49  for (CFIndex i = 0; i < numValues; ++i)
50  extensionsArray.add ("." + String::fromCFString ((CFStringRef) CFArrayGetValueAtIndex (extensions, i)));
51 
52  CFRelease (extensions);
53  }
54 
55  return extensionsArray;
56  }
57 }
58 
59 //==============================================================================
60 const char* const CoreAudioFormat::midiDataBase64 = "midiDataBase64";
61 const char* const CoreAudioFormat::tempo = "tempo";
62 const char* const CoreAudioFormat::timeSig = "time signature";
63 const char* const CoreAudioFormat::keySig = "key signature";
64 
65 //==============================================================================
67 {
68  static uint32 chunkName (const char* const name) noexcept { return ByteOrder::bigEndianInt (name); }
69 
70  //==============================================================================
71  struct FileHeader
72  {
73  FileHeader (InputStream& input)
74  {
75  fileType = (uint32) input.readIntBigEndian();
76  fileVersion = (uint16) input.readShortBigEndian();
77  fileFlags = (uint16) input.readShortBigEndian();
78  }
79 
80  uint32 fileType;
81  uint16 fileVersion;
82  uint16 fileFlags;
83  };
84 
85  //==============================================================================
86  struct ChunkHeader
87  {
88  ChunkHeader (InputStream& input)
89  {
90  chunkType = (uint32) input.readIntBigEndian();
91  chunkSize = (int64) input.readInt64BigEndian();
92  }
93 
94  uint32 chunkType;
95  int64 chunkSize;
96  };
97 
98  //==============================================================================
100  {
102  {
103  sampleRate = input.readDoubleBigEndian();
104  formatID = (uint32) input.readIntBigEndian();
105  formatFlags = (uint32) input.readIntBigEndian();
106  bytesPerPacket = (uint32) input.readIntBigEndian();
107  framesPerPacket = (uint32) input.readIntBigEndian();
108  channelsPerFrame = (uint32) input.readIntBigEndian();
109  bitsPerChannel = (uint32) input.readIntBigEndian();
110  }
111 
112  double sampleRate;
113  uint32 formatID;
114  uint32 formatFlags;
115  uint32 bytesPerPacket;
116  uint32 framesPerPacket;
117  uint32 channelsPerFrame;
118  uint32 bitsPerChannel;
119  };
120 
121  //==============================================================================
122  static StringPairArray parseUserDefinedChunk (InputStream& input, int64 size)
123  {
124  StringPairArray infoStrings;
125  auto originalPosition = input.getPosition();
126 
127  uint8 uuid[16];
128  input.read (uuid, sizeof (uuid));
129 
130  if (memcmp (uuid, "\x29\x81\x92\x73\xB5\xBF\x4A\xEF\xB7\x8D\x62\xD1\xEF\x90\xBB\x2C", 16) == 0)
131  {
132  auto numEntries = (uint32) input.readIntBigEndian();
133 
134  for (uint32 i = 0; i < numEntries && input.getPosition() < originalPosition + size; ++i)
135  {
136  String keyName = input.readString();
137  infoStrings.set (keyName, input.readString());
138  }
139  }
140 
141  input.setPosition (originalPosition + size);
142  return infoStrings;
143  }
144 
145  //==============================================================================
146  static StringPairArray parseMidiChunk (InputStream& input, int64 size)
147  {
148  auto originalPosition = input.getPosition();
149 
150  MemoryBlock midiBlock;
151  input.readIntoMemoryBlock (midiBlock, (ssize_t) size);
152  MemoryInputStream midiInputStream (midiBlock, false);
153 
154  StringPairArray midiMetadata;
155  MidiFile midiFile;
156 
157  if (midiFile.readFrom (midiInputStream))
158  {
159  midiMetadata.set (CoreAudioFormat::midiDataBase64, midiBlock.toBase64Encoding());
160 
161  findTempoEvents (midiFile, midiMetadata);
162  findTimeSigEvents (midiFile, midiMetadata);
163  findKeySigEvents (midiFile, midiMetadata);
164  }
165 
166  input.setPosition (originalPosition + size);
167  return midiMetadata;
168  }
169 
170  static void findTempoEvents (MidiFile& midiFile, StringPairArray& midiMetadata)
171  {
172  MidiMessageSequence tempoEvents;
173  midiFile.findAllTempoEvents (tempoEvents);
174 
175  auto numTempoEvents = tempoEvents.getNumEvents();
176  MemoryOutputStream tempoSequence;
177 
178  for (int i = 0; i < numTempoEvents; ++i)
179  {
180  auto tempo = getTempoFromTempoMetaEvent (tempoEvents.getEventPointer (i));
181 
182  if (tempo > 0.0)
183  {
184  if (i == 0)
185  midiMetadata.set (CoreAudioFormat::tempo, String (tempo));
186 
187  if (numTempoEvents > 1)
188  tempoSequence << String (tempo) << ',' << tempoEvents.getEventTime (i) << ';';
189  }
190  }
191 
192  if (tempoSequence.getDataSize() > 0)
193  midiMetadata.set ("tempo sequence", tempoSequence.toUTF8());
194  }
195 
196  static double getTempoFromTempoMetaEvent (MidiMessageSequence::MidiEventHolder* holder)
197  {
198  if (holder != nullptr)
199  {
200  auto& midiMessage = holder->message;
201 
202  if (midiMessage.isTempoMetaEvent())
203  {
204  auto tempoSecondsPerQuarterNote = midiMessage.getTempoSecondsPerQuarterNote();
205 
206  if (tempoSecondsPerQuarterNote > 0.0)
207  return 60.0 / tempoSecondsPerQuarterNote;
208  }
209  }
210 
211  return 0.0;
212  }
213 
214  static void findTimeSigEvents (MidiFile& midiFile, StringPairArray& midiMetadata)
215  {
216  MidiMessageSequence timeSigEvents;
217  midiFile.findAllTimeSigEvents (timeSigEvents);
218  auto numTimeSigEvents = timeSigEvents.getNumEvents();
219 
220  MemoryOutputStream timeSigSequence;
221 
222  for (int i = 0; i < numTimeSigEvents; ++i)
223  {
224  int numerator, denominator;
225  timeSigEvents.getEventPointer(i)->message.getTimeSignatureInfo (numerator, denominator);
226 
227  String timeSigString;
228  timeSigString << numerator << '/' << denominator;
229 
230  if (i == 0)
231  midiMetadata.set (CoreAudioFormat::timeSig, timeSigString);
232 
233  if (numTimeSigEvents > 1)
234  timeSigSequence << timeSigString << ',' << timeSigEvents.getEventTime (i) << ';';
235  }
236 
237  if (timeSigSequence.getDataSize() > 0)
238  midiMetadata.set ("time signature sequence", timeSigSequence.toUTF8());
239  }
240 
241  static void findKeySigEvents (MidiFile& midiFile, StringPairArray& midiMetadata)
242  {
243  MidiMessageSequence keySigEvents;
244  midiFile.findAllKeySigEvents (keySigEvents);
245  auto numKeySigEvents = keySigEvents.getNumEvents();
246 
247  MemoryOutputStream keySigSequence;
248 
249  for (int i = 0; i < numKeySigEvents; ++i)
250  {
251  auto& message (keySigEvents.getEventPointer (i)->message);
252  auto key = jlimit (0, 14, message.getKeySignatureNumberOfSharpsOrFlats() + 7);
253  bool isMajor = message.isKeySignatureMajorKey();
254 
255  static const char* majorKeys[] = { "Cb", "Gb", "Db", "Ab", "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "C#" };
256  static const char* minorKeys[] = { "Ab", "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "C#", "G#", "D#", "A#" };
257 
258  String keySigString (isMajor ? majorKeys[key]
259  : minorKeys[key]);
260 
261  if (! isMajor)
262  keySigString << 'm';
263 
264  if (i == 0)
265  midiMetadata.set (CoreAudioFormat::keySig, keySigString);
266 
267  if (numKeySigEvents > 1)
268  keySigSequence << keySigString << ',' << keySigEvents.getEventTime (i) << ';';
269  }
270 
271  if (keySigSequence.getDataSize() > 0)
272  midiMetadata.set ("key signature sequence", keySigSequence.toUTF8());
273  }
274 
275  //==============================================================================
276  static StringPairArray parseInformationChunk (InputStream& input)
277  {
278  StringPairArray infoStrings;
279  auto numEntries = (uint32) input.readIntBigEndian();
280 
281  for (uint32 i = 0; i < numEntries; ++i)
282  infoStrings.set (input.readString(), input.readString());
283 
284  return infoStrings;
285  }
286 
287  //==============================================================================
288  static bool read (InputStream& input, StringPairArray& metadataValues)
289  {
290  auto originalPos = input.getPosition();
291 
292  const FileHeader cafFileHeader (input);
293  const bool isCafFile = cafFileHeader.fileType == chunkName ("caff");
294 
295  if (isCafFile)
296  {
297  while (! input.isExhausted())
298  {
299  const ChunkHeader chunkHeader (input);
300 
301  if (chunkHeader.chunkType == chunkName ("desc"))
302  {
303  AudioDescriptionChunk audioDescriptionChunk (input);
304  }
305  else if (chunkHeader.chunkType == chunkName ("uuid"))
306  {
307  metadataValues.addArray (parseUserDefinedChunk (input, chunkHeader.chunkSize));
308  }
309  else if (chunkHeader.chunkType == chunkName ("data"))
310  {
311  // -1 signifies an unknown data size so the data has to be at the
312  // end of the file so we must have finished the header
313 
314  if (chunkHeader.chunkSize == -1)
315  break;
316 
317  input.setPosition (input.getPosition() + chunkHeader.chunkSize);
318  }
319  else if (chunkHeader.chunkType == chunkName ("midi"))
320  {
321  metadataValues.addArray (parseMidiChunk (input, chunkHeader.chunkSize));
322  }
323  else if (chunkHeader.chunkType == chunkName ("info"))
324  {
325  metadataValues.addArray (parseInformationChunk (input));
326  }
327  else
328  {
329  // we aren't decoding this chunk yet so just skip over it
330  input.setPosition (input.getPosition() + chunkHeader.chunkSize);
331  }
332  }
333  }
334 
335  input.setPosition (originalPos);
336 
337  return isCafFile;
338  }
339 };
340 
341 //==============================================================================
343 {
344 public:
345  CoreAudioReader (InputStream* inp) : AudioFormatReader (inp, coreAudioFormatName)
346  {
347  usesFloatingPointData = true;
348  bitsPerSample = 32;
349 
350  if (input != nullptr)
351  CoreAudioFormatMetatdata::read (*input, metadataValues);
352 
353  auto status = AudioFileOpenWithCallbacks (this,
354  &readCallback,
355  nullptr, // write needs to be null to avoid permisisions errors
356  &getSizeCallback,
357  nullptr, // setSize needs to be null to avoid permisisions errors
358  0, // AudioFileTypeID inFileTypeHint
359  &audioFileID);
360  if (status == noErr)
361  {
362  status = ExtAudioFileWrapAudioFileID (audioFileID, false, &audioFileRef);
363 
364  if (status == noErr)
365  {
366  AudioStreamBasicDescription sourceAudioFormat;
367  UInt32 audioStreamBasicDescriptionSize = sizeof (AudioStreamBasicDescription);
368  ExtAudioFileGetProperty (audioFileRef,
369  kExtAudioFileProperty_FileDataFormat,
370  &audioStreamBasicDescriptionSize,
371  &sourceAudioFormat);
372 
373  numChannels = sourceAudioFormat.mChannelsPerFrame;
374  sampleRate = sourceAudioFormat.mSampleRate;
375 
376  UInt32 sizeOfLengthProperty = sizeof (int64);
377  ExtAudioFileGetProperty (audioFileRef,
378  kExtAudioFileProperty_FileLengthFrames,
379  &sizeOfLengthProperty,
380  &lengthInSamples);
381 
383  bool hasLayout = false;
384  UInt32 sizeOfLayout = 0, isWritable = 0;
385 
386  status = AudioFileGetPropertyInfo (audioFileID, kAudioFilePropertyChannelLayout, &sizeOfLayout, &isWritable);
387 
388  if (status == noErr && sizeOfLayout >= (sizeof (AudioChannelLayout) - sizeof (AudioChannelDescription)))
389  {
390  caLayout.malloc (1, static_cast<size_t> (sizeOfLayout));
391 
392  status = AudioFileGetProperty (audioFileID, kAudioFilePropertyChannelLayout,
393  &sizeOfLayout, caLayout.get());
394 
395  if (status == noErr)
396  {
397  auto fileLayout = CoreAudioLayouts::fromCoreAudio (*caLayout.get());
398 
399  if (fileLayout.size() == static_cast<int> (numChannels))
400  {
401  hasLayout = true;
402  channelSet = fileLayout;
403  }
404  }
405  }
406 
407  destinationAudioFormat.mSampleRate = sampleRate;
408  destinationAudioFormat.mFormatID = kAudioFormatLinearPCM;
409  destinationAudioFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsNonInterleaved | kAudioFormatFlagsNativeEndian;
410  destinationAudioFormat.mBitsPerChannel = sizeof (float) * 8;
411  destinationAudioFormat.mChannelsPerFrame = numChannels;
412  destinationAudioFormat.mBytesPerFrame = sizeof (float);
413  destinationAudioFormat.mFramesPerPacket = 1;
414  destinationAudioFormat.mBytesPerPacket = destinationAudioFormat.mFramesPerPacket * destinationAudioFormat.mBytesPerFrame;
415 
416  status = ExtAudioFileSetProperty (audioFileRef,
417  kExtAudioFileProperty_ClientDataFormat,
418  sizeof (AudioStreamBasicDescription),
419  &destinationAudioFormat);
420  if (status == noErr)
421  {
422  bufferList.malloc (1, sizeof (AudioBufferList) + numChannels * sizeof (::AudioBuffer));
423  bufferList->mNumberBuffers = numChannels;
424  channelMap.malloc (numChannels);
425 
426  if (hasLayout && caLayout != nullptr)
427  {
428  auto caOrder = CoreAudioLayouts::getCoreAudioLayoutChannels (*caLayout);
429 
430  for (int i = 0; i < static_cast<int> (numChannels); ++i)
431  {
432  auto idx = channelSet.getChannelIndexForType (caOrder.getReference (i));
433  jassert (isPositiveAndBelow (idx, static_cast<int> (numChannels)));
434 
435  channelMap[i] = idx;
436  }
437  }
438  else
439  {
440  for (int i = 0; i < static_cast<int> (numChannels); ++i)
441  channelMap[i] = i;
442  }
443 
444  ok = true;
445  }
446  }
447  }
448  }
449 
450  ~CoreAudioReader() override
451  {
452  ExtAudioFileDispose (audioFileRef);
453  AudioFileClose (audioFileID);
454  }
455 
456  //==============================================================================
457  bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
458  int64 startSampleInFile, int numSamples) override
459  {
460  clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,
461  startSampleInFile, numSamples, lengthInSamples);
462 
463  if (numSamples <= 0)
464  return true;
465 
466  if (lastReadPosition != startSampleInFile)
467  {
468  OSStatus status = ExtAudioFileSeek (audioFileRef, startSampleInFile);
469  if (status != noErr)
470  return false;
471 
472  lastReadPosition = startSampleInFile;
473  }
474 
475  while (numSamples > 0)
476  {
477  auto numThisTime = jmin (8192, numSamples);
478  auto numBytes = sizeof (float) * (size_t) numThisTime;
479 
480  audioDataBlock.ensureSize (numBytes * numChannels, false);
481  auto* data = static_cast<float*> (audioDataBlock.getData());
482 
483  for (int j = (int) numChannels; --j >= 0;)
484  {
485  bufferList->mBuffers[j].mNumberChannels = 1;
486  bufferList->mBuffers[j].mDataByteSize = (UInt32) numBytes;
487  bufferList->mBuffers[j].mData = data;
488  data += numThisTime;
489  }
490 
491  auto numFramesToRead = (UInt32) numThisTime;
492  auto status = ExtAudioFileRead (audioFileRef, &numFramesToRead, bufferList);
493 
494  if (status != noErr)
495  return false;
496 
497  for (int i = numDestChannels; --i >= 0;)
498  {
499  auto* dest = destSamples[(i < (int) numChannels ? channelMap[i] : i)];
500 
501  if (dest != nullptr)
502  {
503  if (i < (int) numChannels)
504  memcpy (dest + startOffsetInDestBuffer, bufferList->mBuffers[i].mData, numBytes);
505  else
506  zeromem (dest + startOffsetInDestBuffer, numBytes);
507  }
508  }
509 
510  startOffsetInDestBuffer += numThisTime;
511  numSamples -= numThisTime;
512  lastReadPosition += numThisTime;
513  }
514 
515  return true;
516  }
517 
519  {
520  if (channelSet.size() == static_cast<int> (numChannels))
521  return channelSet;
522 
524  }
525 
526  bool ok = false;
527 
528 private:
529  AudioFileID audioFileID;
530  ExtAudioFileRef audioFileRef;
531  AudioChannelSet channelSet;
532  AudioStreamBasicDescription destinationAudioFormat;
533  MemoryBlock audioDataBlock;
534  HeapBlock<AudioBufferList> bufferList;
535  int64 lastReadPosition = 0;
536  HeapBlock<int> channelMap;
537 
538  static SInt64 getSizeCallback (void* inClientData)
539  {
540  return static_cast<CoreAudioReader*> (inClientData)->input->getTotalLength();
541  }
542 
543  static OSStatus readCallback (void* inClientData, SInt64 inPosition, UInt32 requestCount,
544  void* buffer, UInt32* actualCount)
545  {
546  auto* reader = static_cast<CoreAudioReader*> (inClientData);
547  reader->input->setPosition (inPosition);
548  *actualCount = (UInt32) reader->input->read (buffer, (int) requestCount);
549  return noErr;
550  }
551 
552  JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreAudioReader)
553 };
554 
555 //==============================================================================
557  : AudioFormat (coreAudioFormatName, findFileExtensionsForCoreAudioCodecs())
558 {
559 }
560 
562 
565 
566 bool CoreAudioFormat::canDoStereo() { return true; }
567 bool CoreAudioFormat::canDoMono() { return true; }
568 
569 //==============================================================================
571  bool deleteStreamIfOpeningFails)
572 {
573  std::unique_ptr<CoreAudioReader> r (new CoreAudioReader (sourceStream));
574 
575  if (r->ok)
576  return r.release();
577 
578  if (! deleteStreamIfOpeningFails)
579  r->input = nullptr;
580 
581  return nullptr;
582 }
583 
585  double /*sampleRateToUse*/,
586  unsigned int /*numberOfChannels*/,
587  int /*bitsPerSample*/,
588  const StringPairArray& /*metadataValues*/,
589  int /*qualityOptionIndex*/)
590 {
591  jassertfalse; // not yet implemented!
592  return nullptr;
593 }
594 
595 //==============================================================================
596 // Unit tests for Core Audio layout conversions
597 //==============================================================================
598 #if JUCE_UNIT_TESTS
599 
600 #define DEFINE_CHANNEL_LAYOUT_DFL_ENTRY(x) CoreAudioChannelLayoutTag { x, #x, AudioChannelSet() }
601 #define DEFINE_CHANNEL_LAYOUT_TAG_ENTRY(x, y) CoreAudioChannelLayoutTag { x, #x, y }
602 
603 class CoreAudioLayoutsUnitTest : public UnitTest
604 {
605 public:
606  CoreAudioLayoutsUnitTest() : UnitTest ("Core Audio Layout <-> JUCE channel layout conversion", "Audio") {}
607 
608  // some ambisonic tags which are not explicitely defined
609  enum
610  {
611  kAudioChannelLayoutTag_HOA_ACN_SN3D_0Order = (190U<<16) | 1,
612  kAudioChannelLayoutTag_HOA_ACN_SN3D_1Order = (190U<<16) | 4,
613  kAudioChannelLayoutTag_HOA_ACN_SN3D_2Order = (190U<<16) | 9,
614  kAudioChannelLayoutTag_HOA_ACN_SN3D_3Order = (190U<<16) | 16,
615  kAudioChannelLayoutTag_HOA_ACN_SN3D_4Order = (190U<<16) | 25,
616  kAudioChannelLayoutTag_HOA_ACN_SN3D_5Order = (190U<<16) | 36
617  };
618 
619  void runTest() override
620  {
621  auto& knownTags = getAllKnownLayoutTags();
622 
623  {
624  // Check that all known tags defined in CoreAudio SDK version 10.12.4 are known to JUCE
625  // Include all defined tags even if there are duplicates as Apple will sometimes change
626  // definitions
627  beginTest ("All CA tags handled");
628 
629  for (auto tagEntry : knownTags)
630  {
631  auto labels = CoreAudioLayouts::fromCoreAudio (tagEntry.tag);
632 
633  expect (! labels.isDiscreteLayout(), "Tag \"" + String (tagEntry.name) + "\" is not handled by JUCE");
634  }
635  }
636 
637  {
638  beginTest ("Number of speakers");
639 
640  for (auto tagEntry : knownTags)
641  {
642  auto labels = CoreAudioLayouts::getSpeakerLayoutForCoreAudioTag (tagEntry.tag);
643 
644  expect (labels.size() == (tagEntry.tag & 0xffff), "Tag \"" + String (tagEntry.name) + "\" has incorrect channel count");
645  }
646  }
647 
648  {
649  beginTest ("No duplicate speaker");
650 
651  for (auto tagEntry : knownTags)
652  {
653  auto labels = CoreAudioLayouts::getSpeakerLayoutForCoreAudioTag (tagEntry.tag);
654  labels.sort();
655 
656  for (int i = 0; i < (labels.size() - 1); ++i)
657  expect (labels.getReference (i) != labels.getReference (i + 1),
658  "Tag \"" + String (tagEntry.name) + "\" has the same speaker twice");
659  }
660  }
661 
662  {
663  beginTest ("CA speaker list and juce layouts are consistent");
664 
665  for (auto tagEntry : knownTags)
666  expect (AudioChannelSet::channelSetWithChannels (CoreAudioLayouts::getSpeakerLayoutForCoreAudioTag (tagEntry.tag))
667  == CoreAudioLayouts::fromCoreAudio (tagEntry.tag),
668  "Tag \"" + String (tagEntry.name) + "\" is not converted consistently by JUCE");
669  }
670 
671  {
672  beginTest ("AudioChannelSet documentation is correct");
673 
674  for (auto tagEntry : knownTags)
675  {
676  if (tagEntry.equivalentChannelSet.isDisabled())
677  continue;
678 
679  expect (CoreAudioLayouts::fromCoreAudio (tagEntry.tag) == tagEntry.equivalentChannelSet,
680  "Documentation for tag \"" + String (tagEntry.name) + "\" is incorrect");
681  }
682  }
683 
684  {
685  beginTest ("CA tag reverse conversion");
686 
687  for (auto tagEntry : knownTags)
688  {
689  if (tagEntry.equivalentChannelSet.isDisabled())
690  continue;
691 
692  expect (CoreAudioLayouts::toCoreAudio (tagEntry.equivalentChannelSet) == tagEntry.tag,
693  "Incorrect reverse conversion for tag \"" + String (tagEntry.name) + "\"");
694  }
695  }
696  }
697 
698 private:
699  struct CoreAudioChannelLayoutTag
700  {
701  AudioChannelLayoutTag tag;
702  const char* name;
703  AudioChannelSet equivalentChannelSet; /* referred to this in the AudioChannelSet documentation */
704  };
705 
706  //==============================================================================
707  const Array<CoreAudioChannelLayoutTag>& getAllKnownLayoutTags() const
708  {
709  static CoreAudioChannelLayoutTag tags[] = {
710  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_Mono, AudioChannelSet::mono()),
711  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_Stereo, AudioChannelSet::stereo()),
712  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_StereoHeadphones),
713  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MatrixStereo),
714  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MidSide),
715  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_XY),
716  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_Binaural),
717  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_Ambisonic_B_Format),
718  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_Quadraphonic, AudioChannelSet::quadraphonic()),
719  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_Pentagonal, AudioChannelSet::pentagonal()),
720  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_Hexagonal, AudioChannelSet::hexagonal()),
721  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_Octagonal, AudioChannelSet::octagonal()),
722  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_Cube),
723  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_1_0),
724  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_2_0),
725  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_3_0_A, AudioChannelSet::createLCR()),
726  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_3_0_B),
727  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_4_0_A, AudioChannelSet::createLCRS()),
728  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_4_0_B),
729  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_5_0_A, AudioChannelSet::create5point0()),
730  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_5_0_B),
731  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_5_0_C),
732  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_5_0_D),
733  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_5_1_A, AudioChannelSet::create5point1()),
734  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_5_1_B),
735  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_5_1_C),
736  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_5_1_D),
737  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_6_1_A, AudioChannelSet::create6point1()),
738  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_7_1_A, AudioChannelSet::create7point1SDDS()),
739  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_7_1_B),
740  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_7_1_C, AudioChannelSet::create7point1()),
741  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_Emagic_Default_7_1),
742  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_SMPTE_DTV),
743  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_1_0),
744  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_2_0),
745  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_ITU_2_1, AudioChannelSet::createLRS()),
746  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_2_2),
747  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_3_0),
748  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_3_1),
749  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_3_2),
750  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_3_2_1),
751  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_3_4_1),
752  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_0),
753  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_1),
754  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_2),
755  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_3),
756  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_4),
757  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_5),
758  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_6),
759  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_7),
760  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_8),
761  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_9),
762  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_10),
763  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_11),
764  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_12),
765  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_13),
766  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_14),
767  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_15),
768  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_16),
769  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_17),
770  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_18),
771  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_19),
772  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_20),
773  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_4),
774  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_5),
775  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_6),
776  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_8),
777  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_5_0),
778  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_AudioUnit_6_0, AudioChannelSet::create6point0()),
779  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_AudioUnit_7_0, AudioChannelSet::create7point0()),
780  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_AudioUnit_7_0_Front, AudioChannelSet::create7point0SDDS()),
781  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_5_1),
782  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_6_1),
783  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_7_1),
784  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_7_1_Front),
785  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_3_0),
786  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_Quadraphonic),
787  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_4_0),
788  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_5_0),
789  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_5_1),
790  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_6_0),
791  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_6_1),
792  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_7_0),
793  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_7_1),
794  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_7_1_B),
795  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_7_1_C),
796  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_Octagonal),
797  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_TMH_10_2_std),
798  // DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_TMH_10_2_full), no indication on how to handle this tag
799  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AC3_1_0_1),
800  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AC3_3_0),
801  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AC3_3_1),
802  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AC3_3_0_1),
803  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AC3_2_1_1),
804  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AC3_3_1_1),
805  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC_6_0_A),
806  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC_7_0_A),
807  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_6_1_A),
808  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_6_1_B),
809  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_6_1_C),
810  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_A),
811  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_B),
812  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_C),
813  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_D),
814  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_E),
815  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_F),
816  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_G),
817  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_H),
818  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_3_1),
819  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_4_1),
820  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_DTS_6_0_A, AudioChannelSet::create6point0Music()),
821  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_6_0_B),
822  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_6_0_C),
823  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_DTS_6_1_A, AudioChannelSet::create6point1Music()),
824  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_6_1_B),
825  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_6_1_C),
826  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_7_0),
827  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_7_1),
828  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_8_0_A),
829  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_8_0_B),
830  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_8_1_A),
831  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_8_1_B),
832  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_6_1_D),
833  DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_6_1_D),
834  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_HOA_ACN_SN3D_0Order, AudioChannelSet::ambisonic (0)),
835  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_HOA_ACN_SN3D_1Order, AudioChannelSet::ambisonic (1)),
836  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_HOA_ACN_SN3D_2Order, AudioChannelSet::ambisonic (2)),
837  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_HOA_ACN_SN3D_3Order, AudioChannelSet::ambisonic (3)),
838  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_HOA_ACN_SN3D_4Order, AudioChannelSet::ambisonic (4)),
839  DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_HOA_ACN_SN3D_5Order, AudioChannelSet::ambisonic (5))
840  };
841  static Array<CoreAudioChannelLayoutTag> knownTags (tags, sizeof (tags) / sizeof (CoreAudioChannelLayoutTag));
842 
843  return knownTags;
844  }
845 };
846 
847 static CoreAudioLayoutsUnitTest coreAudioLayoutsUnitTest;
848 
849 #endif
850 
851 } // namespace juce
852 
853 #endif
static AudioChannelSet JUCE_CALLTYPE create6point1()
Creates a set for a 6.1 Cine surround setup (left, right, centre, leftSurround, rightSurround, centreSurround, LFE).
void getTimeSignatureInfo(int &numerator, int &denominator) const noexcept
Returns the time-signature values from a time-signature meta-event.
AudioFormatReader * createReaderFor(InputStream *, bool deleteStreamIfOpeningFails) override
Tries to create an object that can read from a stream containing audio data in this format...
Represents a set of audio channel types.
static AudioChannelSet JUCE_CALLTYPE create6point1Music()
Creates a set for a 6.0 Music surround setup (left, right, leftSurround, rightSurround, leftSurroundSide, rightSurroundSide, LFE).
void findAllTempoEvents(MidiMessageSequence &tempoChangeEvents) const
Makes a list of all the tempo-change meta-events from all tracks in the midi file.
Reads/writes standard midi format files.
Definition: juce_MidiFile.h:45
static AudioChannelSet JUCE_CALLTYPE pentagonal()
Creates a set for pentagonal surround setup (left, right, centre, leftSurroundRear, rightSurroundRear).
void malloc(SizeType newNumElements, size_t elementSize=sizeof(ElementType))
Allocates a specified amount of memory.
virtual int readIntBigEndian()
Reads four bytes from the stream as a big-endian 32-bit value.
virtual int64 readInt64BigEndian()
Reads eight bytes from the stream as a big-endian 64-bit value.
static AudioChannelSet JUCE_CALLTYPE create6point0Music()
Creates a set for a 6.0 Music surround setup (left, right, leftSurround, rightSurround, leftSurroundSide, rightSurroundSide).
static AudioChannelSet JUCE_CALLTYPE create7point1SDDS()
Creates a set for a 7.1 surround setup (left, right, centre, leftSurround, rightSurround, leftCentre, rightCentre, LFE).
The base class for streams that read data.
bool readFrom(InputStream &sourceStream, bool createMatchingNoteOffs=true)
Reads a midi file format stream.
Very simple container class to hold a pointer to some data on the heap.
static const char *const keySig
Metadata property name used when reading a caf file time signature information.
static JUCE_CONSTEXPR uint32 bigEndianInt(const void *bytes) noexcept
Turns 4 bytes into a big-endian integer.
InputStream * input
The input stream, for use by subclasses.
static AudioChannelSet JUCE_CALLTYPE channelSetWithChannels(const Array< ChannelType > &)
Creates a channel set for a list of channel types.
virtual String readString()
Reads a zero-terminated UTF-8 string from the stream.
The JUCE String class!
Definition: juce_String.h:42
~CoreAudioFormat() override
Destructor.
virtual short readShortBigEndian()
Reads two bytes from the stream as a little-endian 16-bit value.
MidiEventHolder * getEventPointer(int index) const noexcept
Returns a pointer to one of the events.
ElementType * get() const noexcept
Returns a raw pointer to the allocated data.
virtual int64 getPosition()=0
Returns the offset of the next byte that will be read from the stream.
static AudioChannelSet JUCE_CALLTYPE createLCRS()
Creates a set containing an LCRS set (left, right, centre, surround).
virtual bool isExhausted()=0
Returns true if the stream has no more data to read.
static AudioChannelSet JUCE_CALLTYPE ambisonic(int order=1)
Creates a set for ACN, SN3D normalised ambisonic surround setups with a given order.
This is a base class for classes that perform a unit test.
Definition: juce_UnitTest.h:73
static AudioChannelSet JUCE_CALLTYPE mono()
Creates a one-channel mono set (centre).
static AudioChannelSet JUCE_CALLTYPE create7point0SDDS()
Creates a set for a SDDS 7.0 surround setup (left, right, centre, leftSurround, rightSurround, leftCentre, rightCentre).
A multi-channel buffer containing floating point audio samples.
bool readSamples(int **destSamples, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples) override
Subclasses must implement this method to perform the low-level read operation.
AudioChannelSet getChannelLayout() override
Get the channel layout of the audio stream.
CoreAudioFormat()
Creates a format object.
Array< int > getPossibleBitDepths() override
Returns a set of bit depths that the format can read and write.
static AudioChannelSet JUCE_CALLTYPE create5point1()
Creates a set for a 5.1 surround setup (left, right, centre, leftSurround, rightSurround, LFE).
static AudioChannelSet JUCE_CALLTYPE create5point0()
Creates a set for a 5.0 surround setup (left, right, centre, leftSurround, rightSurround).
Subclasses of AudioFormat are used to read and write different audio file formats.
MidiMessage message
The message itself, whose timestamp is used to specify the event&#39;s time.
The base class for streams that write data to some kind of destination.
AudioFormatWriter * createWriterFor(OutputStream *, double sampleRateToUse, unsigned int numberOfChannels, int bitsPerSample, const StringPairArray &metadataValues, int qualityOptionIndex) override
Tries to create an object that can write to a stream with this audio format.
Array< int > getPossibleSampleRates() override
Returns a set of sample rates that the format can read and write.
static AudioChannelSet JUCE_CALLTYPE create7point1()
Creates a set for a DTS 7.1 surround setup (left, right, centre, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear, LFE).
bool canDoMono() override
Returns true if the format can do 1-channel audio.
static String fromCFString(CFStringRef cfString)
OSX ONLY - Creates a String from an OSX CFString.
size_t getDataSize() const noexcept
Returns the number of bytes of data that have been written to the stream.
static AudioChannelSet JUCE_CALLTYPE createLRS()
Creates a set containing an LRS set (left, right, surround).
void set(const String &key, const String &value)
Adds or amends a key/value pair.
virtual size_t readIntoMemoryBlock(MemoryBlock &destBlock, ssize_t maxNumBytesToRead=-1)
Reads from the stream and appends the data to a MemoryBlock.
static AudioChannelSet JUCE_CALLTYPE createLCR()
Creates a set containing an LCR set (left, right, centre).
static AudioChannelSet JUCE_CALLTYPE create6point0()
Creates a set for a 6.0 Cine surround setup (left, right, centre, leftSurround, rightSurround, centreSurround).
Writes samples to an audio file stream.
virtual double readDoubleBigEndian()
Reads eight bytes as a 64-bit floating point value.
static const char *const tempo
Metadata property name used when reading a caf file with tempo information.
static AudioChannelSet JUCE_CALLTYPE stereo()
Creates a set containing a stereo set (left, right).
A sequence of timestamped midi messages.
Structure used to hold midi events in the sequence.
static AudioChannelSet JUCE_CALLTYPE octagonal()
Creates a set for octagonal surround setup (left, right, leftSurround, rightSurround, centre, centreSurround, wideLeft, wideRight).
static const char *const timeSig
Metadata property name used when reading a caf file time signature information.
static AudioChannelSet JUCE_CALLTYPE create7point0()
Creates a set for a DTS 7.0 surround setup (left, right, centre, leftSurroundSide, rightSurroundSide, leftSurroundRear, rightSurroundRear).
void findAllTimeSigEvents(MidiMessageSequence &timeSigEvents) const
Makes a list of all the time-signature meta-events from all tracks in the midi file.
static AudioChannelSet JUCE_CALLTYPE hexagonal()
Creates a set for hexagonal surround setup (left, right, leftSurroundRear, rightSurroundRear, centre, surroundCentre).
A container for holding a set of strings which are keyed by another string.
void addArray(const StringPairArray &other)
Adds the items from another array to this one.
Reads samples from an audio file stream.
static AudioChannelSet JUCE_CALLTYPE quadraphonic()
Creates a set for quadraphonic surround setup (left, right, leftSurround, rightSurround) ...
String toUTF8() const
Returns a String created from the (UTF8) data that has been written to the stream.
Writes data to an internal memory buffer, which grows as required.
virtual int read(void *destBuffer, int maxBytesToRead)=0
Reads some data from the stream into a memory buffer.
virtual AudioChannelSet getChannelLayout()
Get the channel layout of the audio stream.
static const char *const midiDataBase64
Metadata property name used when reading a caf file with a MIDI chunk.
void findAllKeySigEvents(MidiMessageSequence &keySigEvents) const
Makes a list of all the time-signature meta-events from all tracks in the midi file.
A class to hold a resizable block of raw data.
double getTempoSecondsPerQuarterNote() const noexcept
Calculates the seconds-per-quarter-note from a tempo meta-event.
int getNumEvents() const noexcept
Returns the number of events in the sequence.
double getEventTime(int index) const noexcept
Returns the timestamp of the event at a given index.
Allows a block of data to be accessed as a stream.
virtual bool setPosition(int64 newPosition)=0
Tries to move the current read position of the stream.
String toBase64Encoding() const
Returns a string of characters in a JUCE-specific text encoding that represents the binary contents o...
bool canDoStereo() override
Returns true if the format can do 2-channel audio.