29static const char*
const aiffFormatName =
"AIFF file";
42namespace AiffFileHelpers
47 #pragma pack (push, 1)
56 uint16 startIdentifier;
70 void copyTo (std::map<String, String>& values)
const
72 values.emplace (
"MidiUnityNote", String (baseNote));
73 values.emplace (
"Detune", String (detune));
75 values.emplace (
"LowNote", String (lowNote));
76 values.emplace (
"HighNote", String (highNote));
77 values.emplace (
"LowVelocity", String (lowVelocity));
78 values.emplace (
"HighVelocity", String (highVelocity));
82 values.emplace (
"NumSampleLoops", String (2));
91 static uint16 getValue16 (
const StringPairArray& values,
const char* name,
const char* def)
96 static int8 getValue8 (
const StringPairArray& values,
const char* name,
const char* def)
98 return (int8) values.getValue (name, def).getIntValue();
101 static void create (MemoryBlock& block,
const StringPairArray& values)
103 if (values.getAllKeys().contains (
"MidiUnityNote",
true))
105 block.setSize ((
sizeof (InstChunk) + 3) & ~(
size_t) 3,
true);
106 auto& inst = *
static_cast<InstChunk*
> (block.getData());
108 inst.baseNote = getValue8 (values,
"MidiUnityNote",
"60");
109 inst.detune = getValue8 (values,
"Detune",
"0");
110 inst.lowNote = getValue8 (values,
"LowNote",
"0");
111 inst.highNote = getValue8 (values,
"HighNote",
"127");
112 inst.lowVelocity = getValue8 (values,
"LowVelocity",
"1");
113 inst.highVelocity = getValue8 (values,
"HighVelocity",
"127");
114 inst.gain = (int16) getValue16 (values,
"Gain",
"0");
116 inst.sustainLoop.type = getValue16 (values,
"Loop0Type",
"0");
117 inst.sustainLoop.startIdentifier = getValue16 (values,
"Loop0StartIdentifier",
"0");
118 inst.sustainLoop.endIdentifier = getValue16 (values,
"Loop0EndIdentifier",
"0");
119 inst.releaseLoop.type = getValue16 (values,
"Loop1Type",
"0");
120 inst.releaseLoop.startIdentifier = getValue16 (values,
"Loop1StartIdentifier",
"0");
121 inst.releaseLoop.endIdentifier = getValue16 (values,
"Loop1EndIdentifier",
"0");
138 BASCChunk (InputStream& input)
142 flags = (uint32) input.readIntBigEndian();
143 numBeats = (uint32) input.readIntBigEndian();
144 rootNote = (uint16) input.readShortBigEndian();
145 key = (uint16) input.readShortBigEndian();
146 timeSigNum = (uint16) input.readShortBigEndian();
147 timeSigDen = (uint16) input.readShortBigEndian();
148 oneShot = (uint16) input.readShortBigEndian();
149 input.read (unknown,
sizeof (unknown));
152 void addToMetadata (std::map<String, String>& metadata)
const
154 const bool rootNoteSet = rootNote != 0;
166 const char* keyString =
nullptr;
170 case minor: keyString =
"minor";
break;
171 case major: keyString =
"major";
break;
172 case neither: keyString =
"neither";
break;
173 case both: keyString =
"both";
break;
177 if (keyString !=
nullptr)
181 void setBoolFlag (std::map<String, String>& values,
183 bool shouldBeSet)
const
185 values.emplace (name, shouldBeSet ?
"1" :
"0");
205 static bool isValidTag (
const char* d)
noexcept
212 static bool isAppleGenre (
const String& tag)
noexcept
214 static const char* appleGenres[] =
228 for (
int i = 0; i < numElementsInArray (appleGenres); ++i)
229 if (tag == appleGenres[i])
235 static String read (InputStream& input,
const uint32 length)
238 input.skipNextBytes (4);
239 input.readIntoMemoryBlock (mb, (ssize_t) length - 4);
241 StringArray tagsArray;
243 auto* data =
static_cast<const char*
> (mb.getData());
244 auto* dataEnd = data + mb.getSize();
246 while (data < dataEnd)
248 bool isGenre =
false;
250 if (isValidTag (data))
252 auto tag = String (CharPointer_UTF8 (data), CharPointer_UTF8 (dataEnd));
253 isGenre = isAppleGenre (tag);
257 data += isGenre ? 118 : 50;
259 if (data < dataEnd && data[0] == 0)
261 if (data + 52 < dataEnd && isValidTag (data + 50)) data += 50;
262 else if (data + 120 < dataEnd && isValidTag (data + 118)) data += 118;
263 else if (data + 170 < dataEnd && isValidTag (data + 168)) data += 168;
267 return tagsArray.joinIntoString (
";");
274 static bool metaDataContainsZeroIdentifiers (
const StringPairArray& values)
277 const String cueString (
"Cue");
278 const String noteString (
"CueNote");
279 const String identifierString (
"Identifier");
281 for (
auto& key : values.getAllKeys())
283 if (key.startsWith (noteString))
286 if (key.startsWith (cueString) && key.contains (identifierString))
287 if (values.getValue (key,
"-1").getIntValue() == 0)
294 static void create (MemoryBlock& block,
const StringPairArray& values)
296 auto numCues = values.getValue (
"NumCuePoints",
"0").getIntValue();
300 MemoryOutputStream out (block,
false);
301 out.writeShortBigEndian ((
short) numCues);
303 auto numCueLabels = values.getValue (
"NumCueLabels",
"0").getIntValue();
304 auto idOffset = metaDataContainsZeroIdentifiers (values) ? 1 : 0;
307 Array<int> identifiers;
310 for (
int i = 0; i < numCues; ++i)
312 auto prefixCue =
"Cue" + String (i);
313 auto identifier = idOffset + values.getValue (prefixCue +
"Identifier",
"1").getIntValue();
316 jassert (! identifiers.contains (identifier));
317 identifiers.add (identifier);
320 auto offset = values.getValue (prefixCue +
"Offset",
"0").getIntValue();
321 auto label =
"CueLabel" + String (i);
323 for (
int labelIndex = 0; labelIndex < numCueLabels; ++labelIndex)
325 auto prefixLabel =
"CueLabel" + String (labelIndex);
326 auto labelIdentifier = idOffset + values.getValue (prefixLabel +
"Identifier",
"1").getIntValue();
328 if (labelIdentifier == identifier)
330 label = values.getValue (prefixLabel +
"Text", label);
335 out.writeShortBigEndian ((
short) identifier);
336 out.writeIntBigEndian (offset);
338 auto labelLength = jmin ((
size_t) 254, label.getNumBytesAsUTF8());
339 out.writeByte (
static_cast<char> (labelLength + 1));
340 out.write (label.toUTF8(), labelLength);
343 if ((out.getDataSize() & 1) != 0)
353 static void create (MemoryBlock& block,
const StringPairArray& values)
355 auto numNotes = values.getValue (
"NumCueNotes",
"0").getIntValue();
359 MemoryOutputStream out (block,
false);
360 out.writeShortBigEndian ((
short) numNotes);
362 for (
int i = 0; i < numNotes; ++i)
364 auto prefix =
"CueNote" + String (i);
366 out.writeIntBigEndian (values.getValue (prefix +
"TimeStamp",
"0").getIntValue());
367 out.writeShortBigEndian ((
short) values.getValue (prefix +
"Identifier",
"0").getIntValue());
369 auto comment = values.getValue (prefix +
"Text", String());
370 auto commentLength = jmin (comment.getNumBytesAsUTF8(), (
size_t) 65534);
372 out.writeShortBigEndian (
static_cast<short> (commentLength + 1));
373 out.write (comment.toUTF8(), commentLength);
376 if ((out.getDataSize() & 1) != 0)
385class AiffAudioFormatReader final :
public AudioFormatReader
388 AiffAudioFormatReader (InputStream* in)
391 using namespace AiffFileHelpers;
393 std::map<String, String> metadataValuesMap;
404 if (input->readInt() == chunkName (
"FORM"))
406 auto len = input->readIntBigEndian();
407 auto end = input->getPosition() + len;
408 auto nextType = input->readInt();
410 if (nextType == chunkName (
"AIFF") || nextType == chunkName (
"AIFC"))
412 bool hasGotVer =
false;
413 bool hasGotData =
false;
414 bool hasGotType =
false;
416 while (input->getPosition() < end)
418 auto type = input->readInt();
419 auto length = (uint32) input->readIntBigEndian();
420 auto chunkEnd = input->getPosition() + length;
422 if (type == chunkName (
"FVER"))
425 auto ver = input->readIntBigEndian();
427 if (ver != 0 && ver != (
int) 0xa2805140)
430 else if (type == chunkName (
"COMM"))
434 numChannels = (
unsigned int) input->readShortBigEndian();
437 bytesPerFrame = (int) ((numChannels * bitsPerSample) >> 3);
439 unsigned char sampleRateBytes[10];
440 input->read (sampleRateBytes, 10);
441 const int byte0 = sampleRateBytes[0];
443 if ((byte0 & 0x80) != 0
444 || byte0 <= 0x3F || byte0 > 0x40
445 || (byte0 == 0x40 && sampleRateBytes[1] > 0x1C))
456 littleEndian =
false;
460 auto compType = input->readInt();
462 if (compType == chunkName (
"NONE") || compType == chunkName (
"twos"))
464 littleEndian =
false;
466 else if (compType == chunkName (
"sowt"))
470 else if (compType == chunkName (
"fl32") || compType == chunkName (
"FL32"))
472 littleEndian =
false;
482 else if (type == chunkName (
"SSND"))
486 auto offset = input->readIntBigEndian();
487 dataChunkStart = input->getPosition() + 4 + offset;
488 lengthInSamples = (bytesPerFrame > 0) ? jmin (lengthInSamples, ((int64) length) / (int64) bytesPerFrame) : 0;
490 else if (type == chunkName (
"MARK"))
492 auto numCues = (uint16) input->readShortBigEndian();
495 metadataValuesMap.emplace (
"NumCuePoints", String (numCues));
496 metadataValuesMap.emplace (
"NumCueLabels", String (numCues));
498 for (uint16 i = 0; i < numCues; ++i)
500 auto identifier = (uint16) input->readShortBigEndian();
501 auto offset = (uint32) input->readIntBigEndian();
502 auto stringLength = (uint8) input->readByte();
503 MemoryBlock textBlock;
504 input->readIntoMemoryBlock (textBlock, stringLength);
509 if ((stringLength & 1) == 0)
512 auto prefixCue =
"Cue" + String (i);
513 metadataValuesMap.emplace (prefixCue +
"Identifier", String (identifier));
514 metadataValuesMap.emplace (prefixCue +
"Offset", String (offset));
516 auto prefixLabel =
"CueLabel" + String (i);
517 metadataValuesMap.emplace (prefixLabel +
"Identifier", String (identifier));
518 metadataValuesMap.emplace (prefixLabel +
"Text", textBlock.toString());
521 else if (type == chunkName (
"COMT"))
523 auto numNotes = (uint16) input->readShortBigEndian();
524 metadataValuesMap.emplace (
"NumCueNotes", String (numNotes));
526 for (uint16 i = 0; i < numNotes; ++i)
528 auto timestamp = (uint32) input->readIntBigEndian();
529 auto identifier = (uint16) input->readShortBigEndian();
530 auto stringLength = (uint16) input->readShortBigEndian();
532 MemoryBlock textBlock;
533 input->readIntoMemoryBlock (textBlock, stringLength + (stringLength & 1));
535 auto prefix =
"CueNote" + String (i);
536 metadataValuesMap.emplace (prefix +
"TimeStamp", String (timestamp));
537 metadataValuesMap.emplace (prefix +
"Identifier", String (identifier));
538 metadataValuesMap.emplace (prefix +
"Text", textBlock.toString());
541 else if (type == chunkName (
"INST"))
543 HeapBlock<InstChunk> inst;
544 inst.calloc (jmax ((
size_t) length + 1,
sizeof (InstChunk)), 1);
545 input->read (inst, (
int) length);
546 inst->copyTo (metadataValuesMap);
548 else if (type == chunkName (
"basc"))
550 AiffFileHelpers::BASCChunk (*input).addToMetadata (metadataValuesMap);
552 else if (type == chunkName (
"cate"))
555 AiffFileHelpers::CATEChunk::read (*input, length));
557 else if ((hasGotVer && hasGotData && hasGotType)
558 || chunkEnd < input->getPosition()
559 || input->isExhausted())
564 input->setPosition (chunkEnd + (chunkEnd & 1));
569 if (metadataValuesMap.size() > 0)
570 metadataValuesMap.emplace (
"MetaDataSource",
"AIFF");
576 bool readSamples (
int*
const* destSamples,
int numDestChannels,
int startOffsetInDestBuffer,
577 int64 startSampleInFile,
int numSamples)
override
580 startSampleInFile, numSamples, lengthInSamples);
585 input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame);
587 while (numSamples > 0)
589 const int tempBufSize = 480 * 3 * 4;
590 char tempBuffer [tempBufSize];
592 const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples);
593 const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame);
595 if (bytesRead < numThisTime * bytesPerFrame)
597 jassert (bytesRead >= 0);
598 zeromem (tempBuffer + bytesRead, (
size_t) (numThisTime * bytesPerFrame - bytesRead));
602 copySampleData<AudioData::LittleEndian> (bitsPerSample, usesFloatingPointData,
603 destSamples, startOffsetInDestBuffer, numDestChannels,
604 tempBuffer, (
int) numChannels, numThisTime);
606 copySampleData<AudioData::BigEndian> (bitsPerSample, usesFloatingPointData,
607 destSamples, startOffsetInDestBuffer, numDestChannels,
608 tempBuffer, (
int) numChannels, numThisTime);
610 startOffsetInDestBuffer += numThisTime;
611 numSamples -= numThisTime;
617 template <
typename Endianness>
618 static void copySampleData (
unsigned int numBitsPerSample,
bool floatingPointData,
619 int*
const* destSamples,
int startOffsetInDestBuffer,
int numDestChannels,
620 const void* sourceData,
int numberOfChannels,
int numSamples)
noexcept
622 switch (numBitsPerSample)
624 case 8: ReadHelper<AudioData::Int32, AudioData::Int8, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numberOfChannels, numSamples);
break;
625 case 16: ReadHelper<AudioData::Int32, AudioData::Int16, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numberOfChannels, numSamples);
break;
626 case 24: ReadHelper<AudioData::Int32, AudioData::Int24, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numberOfChannels, numSamples);
break;
627 case 32:
if (floatingPointData) ReadHelper<AudioData::Float32, AudioData::Float32, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numberOfChannels, numSamples);
628 else ReadHelper<AudioData::Int32, AudioData::Int32, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numberOfChannels, numSamples);
630 default: jassertfalse;
break;
635 int64 dataChunkStart;
639 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AiffAudioFormatReader)
643class AiffAudioFormatWriter final :
public AudioFormatWriter
646 AiffAudioFormatWriter (OutputStream* out,
double rate,
647 unsigned int numChans,
unsigned int bits,
648 const StringPairArray& metadataValues)
651 using namespace AiffFileHelpers;
653 if (metadataValues.size() > 0)
658 jassert (metadataValues.getValue (
"MetaDataSource",
"None") !=
"WAV");
660 MarkChunk::create (markChunk, metadataValues);
661 COMTChunk::create (comtChunk, metadataValues);
662 InstChunk::create (instChunk, metadataValues);
665 headerPosition = out->getPosition();
669 ~AiffAudioFormatWriter()
override
671 if ((bytesWritten & 1) != 0)
678 bool write (
const int** data,
int numSamples)
override
680 jassert (numSamples >= 0);
681 jassert (data !=
nullptr && *data !=
nullptr);
686 auto bytes =
numChannels * (size_t) numSamples * bitsPerSample / 8;
687 tempBlock.ensureSize (bytes,
false);
689 switch (bitsPerSample)
691 case 8: WriteHelper<AudioData::Int8, AudioData::Int32, AudioData::BigEndian>::write (tempBlock.getData(), (
int) numChannels, data, numSamples);
break;
692 case 16: WriteHelper<AudioData::Int16, AudioData::Int32, AudioData::BigEndian>::write (tempBlock.getData(), (
int) numChannels, data, numSamples);
break;
693 case 24: WriteHelper<AudioData::Int24, AudioData::Int32, AudioData::BigEndian>::write (tempBlock.getData(), (
int) numChannels, data, numSamples);
break;
694 case 32: WriteHelper<AudioData::Int32, AudioData::Int32, AudioData::BigEndian>::write (tempBlock.getData(), (
int) numChannels, data, numSamples);
break;
695 default: jassertfalse;
break;
698 if (bytesWritten + bytes >= (
size_t) 0xfff00000
709 bytesWritten += bytes;
710 lengthInSamples += (uint64) numSamples;
715 MemoryBlock tempBlock, markChunk, comtChunk, instChunk;
716 uint64 lengthInSamples = 0, bytesWritten = 0;
717 int64 headerPosition = 0;
718 bool writeFailed =
false;
722 using namespace AiffFileHelpers;
728 jassert (couldSeekOk);
730 auto headerLen = (int) (54 + (markChunk.isEmpty() ? 0 : markChunk.getSize() + 8)
731 + (comtChunk.isEmpty() ? 0 : comtChunk.getSize() + 8)
732 + (instChunk.isEmpty() ? 0 : instChunk.getSize() + 8));
733 auto audioBytes = (int) (lengthInSamples * ((bitsPerSample * numChannels) / 8));
734 audioBytes += (audioBytes & 1);
745 uint8 sampleRateBytes[10] = {};
749 sampleRateBytes[0] = 0x3f;
750 sampleRateBytes[1] = 0xff;
751 sampleRateBytes[2] = 0x80;
755 int mask = 0x40000000;
756 sampleRateBytes[0] = 0x40;
758 if (sampleRate >= mask)
761 sampleRateBytes[1] = 0x1d;
765 int n = (int) sampleRate;
768 for (i = 0; i <= 32 ; ++i)
778 sampleRateBytes[1] = (uint8) (29 - i);
779 sampleRateBytes[2] = (uint8) ((n >> 24) & 0xff);
780 sampleRateBytes[3] = (uint8) ((n >> 16) & 0xff);
781 sampleRateBytes[4] = (uint8) ((n >> 8) & 0xff);
782 sampleRateBytes[5] = (uint8) (n & 0xff);
788 if (! markChunk.isEmpty())
795 if (! comtChunk.isEmpty())
802 if (! instChunk.isEmpty())
817 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AiffAudioFormatWriter)
821class MemoryMappedAiffReader final :
public MemoryMappedAudioFormatReader
824 MemoryMappedAiffReader (
const File& f,
const AiffAudioFormatReader& reader)
826 reader.bytesPerFrame * reader.lengthInSamples, reader.bytesPerFrame),
827 littleEndian (reader.littleEndian)
831 bool readSamples (
int*
const* destSamples,
int numDestChannels,
int startOffsetInDestBuffer,
832 int64 startSampleInFile,
int numSamples)
override
835 startSampleInFile, numSamples, lengthInSamples);
840 if (map ==
nullptr || ! mappedSection.
contains (Range<int64> (startSampleInFile, startSampleInFile + numSamples)))
847 AiffAudioFormatReader::copySampleData<AudioData::LittleEndian>
848 (bitsPerSample, usesFloatingPointData, destSamples, startOffsetInDestBuffer,
849 numDestChannels, sampleToPointer (startSampleInFile), (
int) numChannels, numSamples);
851 AiffAudioFormatReader::copySampleData<AudioData::BigEndian>
852 (bitsPerSample, usesFloatingPointData, destSamples, startOffsetInDestBuffer,
853 numDestChannels, sampleToPointer (startSampleInFile), (
int) numChannels, numSamples);
858 void getSample (int64 sample,
float* result)
const noexcept override
860 auto num = (int) numChannels;
862 if (map ==
nullptr || ! mappedSection.
contains (sample))
866 zeromem (result, (
size_t) num *
sizeof (
float));
870 float** dest = &result;
875 switch (bitsPerSample)
877 case 8: ReadHelper<AudioData::Float32, AudioData::UInt8, AudioData::LittleEndian>::read (dest, 0, 1, source, 1, num);
break;
878 case 16: ReadHelper<AudioData::Float32, AudioData::Int16, AudioData::LittleEndian>::read (dest, 0, 1, source, 1, num);
break;
879 case 24: ReadHelper<AudioData::Float32, AudioData::Int24, AudioData::LittleEndian>::read (dest, 0, 1, source, 1, num);
break;
880 case 32:
if (usesFloatingPointData) ReadHelper<AudioData::Float32, AudioData::Float32, AudioData::LittleEndian>::read (dest, 0, 1, source, 1, num);
881 else ReadHelper<AudioData::Float32, AudioData::Int32, AudioData::LittleEndian>::read (dest, 0, 1, source, 1, num);
883 default: jassertfalse;
break;
888 switch (bitsPerSample)
890 case 8: ReadHelper<AudioData::Float32, AudioData::UInt8, AudioData::BigEndian>::read (dest, 0, 1, source, 1, num);
break;
891 case 16: ReadHelper<AudioData::Float32, AudioData::Int16, AudioData::BigEndian>::read (dest, 0, 1, source, 1, num);
break;
892 case 24: ReadHelper<AudioData::Float32, AudioData::Int24, AudioData::BigEndian>::read (dest, 0, 1, source, 1, num);
break;
893 case 32:
if (usesFloatingPointData) ReadHelper<AudioData::Float32, AudioData::Float32, AudioData::BigEndian>::read (dest, 0, 1, source, 1, num);
894 else ReadHelper<AudioData::Float32, AudioData::Int32, AudioData::BigEndian>::read (dest, 0, 1, source, 1, num);
896 default: jassertfalse;
break;
901 void readMaxLevels (int64 startSampleInFile, int64 numSamples, Range<float>* results,
int numChannelsToRead)
override
903 numSamples = jmin (numSamples, lengthInSamples - startSampleInFile);
905 if (map ==
nullptr || numSamples <= 0 || ! mappedSection.
contains (Range<int64> (startSampleInFile, startSampleInFile + numSamples)))
907 jassert (numSamples <= 0);
909 for (
int i = 0; i < numChannelsToRead; ++i)
910 results[i] = Range<float>();
915 switch (bitsPerSample)
917 case 8: scanMinAndMax<AudioData::UInt8> (startSampleInFile, numSamples, results, numChannelsToRead);
break;
918 case 16: scanMinAndMax<AudioData::Int16> (startSampleInFile, numSamples, results, numChannelsToRead);
break;
919 case 24: scanMinAndMax<AudioData::Int24> (startSampleInFile, numSamples, results, numChannelsToRead);
break;
920 case 32:
if (usesFloatingPointData) scanMinAndMax<AudioData::Float32> (startSampleInFile, numSamples, results, numChannelsToRead);
921 else scanMinAndMax<AudioData::Int32> (startSampleInFile, numSamples, results, numChannelsToRead);
923 default: jassertfalse;
break;
930 const bool littleEndian;
932 template <
typename SampleType>
933 void scanMinAndMax (int64 startSampleInFile, int64 numSamples, Range<float>* results,
int numChannelsToRead)
const noexcept
935 for (
int i = 0; i < numChannelsToRead; ++i)
936 results[i] = scanMinAndMaxForChannel<SampleType> (i, startSampleInFile, numSamples);
939 template <
typename SampleType>
940 Range<float> scanMinAndMaxForChannel (
int channel, int64 startSampleInFile, int64 numSamples)
const noexcept
942 return littleEndian ? scanMinAndMaxInterleaved<SampleType, AudioData::LittleEndian> (channel, startSampleInFile, numSamples)
946 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryMappedAiffReader)
955 return { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000 };
960 return { 8, 16, 24 };
972 auto type = f.getMacOSType();
975 return type == 0x41494646 || type == 0x41494643
976 || type == 0x61696666 || type == 0x61696663 ;
982 std::unique_ptr<AiffAudioFormatReader> w (
new AiffAudioFormatReader (sourceStream));
984 if (w->sampleRate > 0 && w->numChannels > 0)
987 if (! deleteStreamIfOpeningFails)
1002 AiffAudioFormatReader reader (fin);
1004 if (reader.lengthInSamples > 0)
1005 return new MemoryMappedAiffReader (fin->
getFile(), reader);
1013 unsigned int numberOfChannels,
1019 return new AiffAudioFormatWriter (out, sampleRate, numberOfChannels,
1020 (
unsigned int) bitsPerSample, metadataValues);
static constexpr uint32 bigEndianInt(const void *bytes) noexcept
static constexpr uint32 littleEndianInt(const void *bytes) noexcept
static Type swapIfLittleEndian(Type value) noexcept
static constexpr uint16 bigEndianShort(const void *bytes) noexcept
static bool isLowerCase(juce_wchar character) noexcept
static bool isLetterOrDigit(char character) noexcept
static bool isUpperCase(juce_wchar character) noexcept
std::unique_ptr< FileInputStream > createInputStream() const
virtual bool write(const void *dataToWrite, size_t numberOfBytes)=0
virtual int64 getPosition()=0
virtual bool writeByte(char byte)
virtual bool writeIntBigEndian(int value)
virtual bool setPosition(int64 newPosition)=0
virtual bool writeShortBigEndian(short value)
virtual bool writeInt(int value)
constexpr bool contains(const ValueType position) const noexcept
String & getReference(int index) noexcept
const StringArray & getAllValues() const noexcept
void addMap(const std::map< String, String > &mapToAdd)
int size() const noexcept
const StringArray & getAllKeys() const noexcept