30static const char*
const wavFormatName =
"WAV file";
43 const String& originatorRef,
46 const String& codingHistory)
158namespace WavFileHelpers
161 JUCE_CONSTEXPR
inline size_t roundUpSize (
size_t sz)
noexcept {
return (sz + 3) & ~3u; }
164 #pragma pack (push, 1)
169 char description[256];
171 char originatorRef[32];
172 char originationDate[10];
173 char originationTime[8];
179 char codingHistory[1];
219 if (
b->description[0] != 0
220 ||
b->originator[0] != 0
221 ||
b->originationDate[0] != 0
222 ||
b->originationTime[0] != 0
223 ||
b->codingHistory[0] != 0
273 template <
typename NameType>
286 setValue (values,
"Manufacturer", manufacturer);
287 setValue (values,
"Product", product);
288 setValue (values,
"SamplePeriod", samplePeriod);
289 setValue (values,
"MidiUnityNote", midiUnityNote);
290 setValue (values,
"MidiPitchFraction", midiPitchFraction);
291 setValue (values,
"SmpteFormat", smpteFormat);
292 setValue (values,
"SmpteOffset", smpteOffset);
293 setValue (values,
"NumSampleLoops", numSampleLoops);
294 setValue (values,
"SamplerData", samplerData);
296 for (
int i = 0; i < (
int) numSampleLoops; ++i)
298 if ((uint8*) (loops + (i + 1)) > ((uint8*)
this) +
totalSize)
301 setValue (values, i,
"Identifier", loops[i].identifier);
302 setValue (values, i,
"Type", loops[i].type);
303 setValue (values, i,
"Start", loops[i].start);
304 setValue (values, i,
"End", loops[i].end);
305 setValue (values, i,
"Fraction", loops[i].fraction);
306 setValue (values, i,
"PlayCount", loops[i].playCount);
310 template <
typename NameType>
311 static uint32 getValue (
const StringPairArray& values, NameType name,
const char* def)
316 static uint32 getValue (
const StringPairArray& values,
int prefix,
const char* name,
const char* def)
318 return getValue (values,
"Loop" + String (prefix) + name, def);
321 static MemoryBlock createFrom (
const StringPairArray& values)
324 auto numLoops = jmin (64, values.getValue (
"NumSampleLoops",
"0").getIntValue());
326 data.setSize (roundUpSize (
sizeof (SMPLChunk) + (
size_t) (jmax (0, numLoops - 1)) *
sizeof (SampleLoop)),
true);
328 auto s =
static_cast<SMPLChunk*
> (data.getData());
330 s->manufacturer = getValue (values,
"Manufacturer",
"0");
331 s->product = getValue (values,
"Product",
"0");
332 s->samplePeriod = getValue (values,
"SamplePeriod",
"0");
333 s->midiUnityNote = getValue (values,
"MidiUnityNote",
"60");
334 s->midiPitchFraction = getValue (values,
"MidiPitchFraction",
"0");
335 s->smpteFormat = getValue (values,
"SmpteFormat",
"0");
336 s->smpteOffset = getValue (values,
"SmpteOffset",
"0");
338 s->samplerData = getValue (values,
"SamplerData",
"0");
340 for (
int i = 0; i < numLoops; ++i)
342 auto& loop = s->loops[i];
343 loop.identifier = getValue (values, i,
"Identifier",
"0");
344 loop.type = getValue (values, i,
"Type",
"0");
345 loop.start = getValue (values, i,
"Start",
"0");
346 loop.end = getValue (values, i,
"End",
"0");
347 loop.fraction = getValue (values, i,
"Fraction",
"0");
348 loop.playCount = getValue (values, i,
"PlayCount",
"0");
373 setValue (values,
"MidiUnityNote", baseNote);
374 setValue (values,
"Detune", detune);
375 setValue (values,
"Gain", gain);
376 setValue (values,
"LowNote", lowNote);
377 setValue (values,
"HighNote", highNote);
378 setValue (values,
"LowVelocity", lowVelocity);
379 setValue (values,
"HighVelocity", highVelocity);
392 if (keys.contains (
"LowNote",
true) && keys.contains (
"HighNote",
true))
397 inst->baseNote = getValue (values,
"MidiUnityNote",
"60");
398 inst->detune = getValue (values,
"Detune",
"0");
399 inst->gain = getValue (values,
"Gain",
"0");
400 inst->lowNote = getValue (values,
"LowNote",
"0");
401 inst->highNote = getValue (values,
"HighNote",
"127");
402 inst->lowVelocity = getValue (values,
"LowVelocity",
"1");
403 inst->highVelocity = getValue (values,
"HighVelocity",
"127");
435 for (
int i = 0; i < (
int) numCues; ++i)
440 setValue (values, i,
"Identifier", cues[i].identifier);
441 setValue (values, i,
"Order", cues[i].order);
442 setValue (values, i,
"ChunkID", cues[i].chunkID);
443 setValue (values, i,
"ChunkStart", cues[i].chunkStart);
444 setValue (values, i,
"BlockStart", cues[i].blockStart);
445 setValue (values, i,
"Offset", cues[i].offset);
449 static MemoryBlock createFrom (
const StringPairArray& values)
452 const int numCues = values.getValue (
"NumCuePoints",
"0").getIntValue();
456 data.setSize (roundUpSize (
sizeof (CueChunk) + (
size_t) (numCues - 1) *
sizeof (Cue)),
true);
458 auto c =
static_cast<CueChunk*
> (data.getData());
462 const String dataChunkID (chunkName (
"data"));
466 Array<uint32> identifiers;
469 for (
int i = 0; i < numCues; ++i)
471 auto prefix =
"Cue" + String (i);
472 auto identifier = (uint32) values.getValue (prefix +
"Identifier",
"0").getIntValue();
475 jassert (! identifiers.contains (identifier));
476 identifiers.add (identifier);
479 auto order = values.getValue (prefix +
"Order", String (nextOrder)).getIntValue();
480 nextOrder = jmax (nextOrder, order) + 1;
482 auto& cue = c->cues[i];
500 static int getValue (
const StringPairArray& values,
const String& name)
502 return values.getValue (name,
"0").getIntValue();
505 static int getValue (
const StringPairArray& values,
const String& prefix,
const char* name)
507 return getValue (values, prefix + name);
510 static void appendLabelOrNoteChunk (
const StringPairArray& values,
const String& prefix,
511 const int chunkType, MemoryOutputStream& out)
513 auto label = values.getValue (prefix +
"Text", prefix);
514 auto labelLength = (int) label.getNumBytesAsUTF8() + 1;
515 auto chunkLength = 4 + labelLength + (labelLength & 1);
517 out.writeInt (chunkType);
518 out.writeInt (chunkLength);
519 out.writeInt (getValue (values, prefix,
"Identifier"));
520 out.write (label.toUTF8(), (size_t) labelLength);
522 if ((out.getDataSize() & 1) != 0)
526 static void appendExtraChunk (
const StringPairArray& values,
const String& prefix, MemoryOutputStream& out)
528 auto text = values.getValue (prefix +
"Text", prefix);
530 auto textLength = (int) text.getNumBytesAsUTF8() + 1;
531 auto chunkLength = textLength + 20 + (textLength & 1);
533 out.writeInt (chunkName (
"ltxt"));
534 out.writeInt (chunkLength);
535 out.writeInt (getValue (values, prefix,
"Identifier"));
536 out.writeInt (getValue (values, prefix,
"SampleLength"));
537 out.writeInt (getValue (values, prefix,
"Purpose"));
538 out.writeShort ((
short) getValue (values, prefix,
"Country"));
539 out.writeShort ((
short) getValue (values, prefix,
"Language"));
540 out.writeShort ((
short) getValue (values, prefix,
"Dialect"));
541 out.writeShort ((
short) getValue (values, prefix,
"CodePage"));
542 out.write (text.toUTF8(), (size_t) textLength);
544 if ((out.getDataSize() & 1) != 0)
548 static MemoryBlock createFrom (
const StringPairArray& values)
550 auto numCueLabels = getValue (values,
"NumCueLabels");
551 auto numCueNotes = getValue (values,
"NumCueNotes");
552 auto numCueRegions = getValue (values,
"NumCueRegions");
554 MemoryOutputStream out;
556 if (numCueLabels + numCueNotes + numCueRegions > 0)
558 out.writeInt (chunkName (
"adtl"));
560 for (
int i = 0; i < numCueLabels; ++i)
561 appendLabelOrNoteChunk (values,
"CueLabel" + String (i), chunkName (
"labl"), out);
563 for (
int i = 0; i < numCueNotes; ++i)
564 appendLabelOrNoteChunk (values,
"CueNote" + String (i), chunkName (
"note"), out);
566 for (
int i = 0; i < numCueRegions; ++i)
567 appendExtraChunk (values,
"CueRegion" + String (i), out);
570 return out.getMemoryBlock();
576 namespace ListInfoChunk
578 static const char*
const types[] =
663 static bool isMatchingTypeIgnoringCase (
const int value,
const char*
const name)
noexcept
665 for (
int i = 0; i < 4; ++i)
686 for (
auto& type : types)
688 if (isMatchingTypeIgnoringCase (
infoType, type))
693 (
int)
mb.getSize()));
715 if ((
out.getDataSize() & 1) != 0)
724 out.writeInt (chunkName (
"INFO"));
727 for (
auto& type : types)
728 if (writeValue (values,
out, type))
742 input.
read (
this, (
int) jmin (
sizeof (*
this), length));
768 return AcidChunk (values).toMemoryBlock();
771 MemoryBlock toMemoryBlock()
const
773 return (flags != 0 || rootNote != 0 || numBeats != 0 || meterDenominator != 0 || meterNumerator != 0)
774 ? MemoryBlock (
this,
sizeof (*
this)) : MemoryBlock();
777 void addToMetadata (StringPairArray& values)
const
794 void setBoolFlag (StringPairArray& values,
const char* name, uint32 mask)
const
799 static uint32 getFlagIfPresent (
const StringPairArray& values,
const char* name, uint32 flag)
804 static float swapFloatByteOrder (
const float x)
noexcept
806 #ifdef JUCE_BIG_ENDIAN
807 union { uint32 asInt;
float asFloat; } n;
821 uint16 meterDenominator;
822 uint16 meterNumerator;
839 if ((
out.getDataSize() & 1) != 0)
843 return out.getMemoryBlock();
852 if (
auto xml = parseXML (source))
854 if (
xml->hasTagName (
"ebucore:ebuCoreMain"))
856 if (
auto xml2 =
xml->getChildByName (
"ebucore:coreMetadata"))
858 if (
auto xml3 =
xml2->getChildByName (
"ebucore:identifier"))
860 if (
auto xml4 =
xml3->getChildByName (
"dc:identifier"))
862 auto ISRCCode =
xml4->getAllSubText().fromFirstOccurrenceOf (
"ISRC:",
false,
true);
873 static MemoryBlock createFrom (
const StringPairArray& values)
876 MemoryOutputStream xml;
878 if (ISRC.isNotEmpty())
880 xml <<
"<ebucore:ebuCoreMain xmlns:dc=\" http://purl.org/dc/elements/1.1/\" "
881 "xmlns:ebucore=\"urn:ebu:metadata-schema:ebuCore_2012\">"
882 "<ebucore:coreMetadata>"
883 "<ebucore:identifier typeLabel=\"GUID\" "
884 "typeDefinition=\"Globally Unique Identifier\" "
885 "formatLabel=\"ISRC\" "
886 "formatDefinition=\"International Standard Recording Code\" "
887 "formatLink=\"http://www.ebu.ch/metadata/cs/ebu_IdentifierTypeCodeCS.xml#3.7\">"
888 "<dc:identifier>ISRC:" << ISRC <<
"</dc:identifier>"
889 "</ebucore:identifier>"
890 "</ebucore:coreMetadata>"
891 "</ebucore:ebuCoreMain>";
893 xml.writeRepeatedByte (0, xml.getDataSize());
896 return xml.getMemoryBlock();
913 static const ExtensibleWavSubFormat pcmFormat = { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
914 static const ExtensibleWavSubFormat IEEEFloatFormat = { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
915 static const ExtensibleWavSubFormat ambisonicFormat = { 0x00000001, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 } };
939 using namespace WavFileHelpers;
987 if (chunkType == chunkName (
"fmt "))
1011 else if (format == 0xfffe)
1036 else if (format == 0x674f
1041 || format == 0x6771)
1043 isSubformatOggVorbis =
true;
1048 else if (format != 1)
1053 else if (chunkType == chunkName (
"data"))
1056 dataLength = length;
1059 lengthInSamples = (bytesPerFrame > 0) ? (dataLength / bytesPerFrame) : 0;
1061 else if (chunkType == chunkName (
"bext"))
1067 bwav.calloc (jmax ((
size_t) length + 1,
sizeof (BWAVChunk)), 1);
1071 else if (chunkType == chunkName (
"smpl"))
1074 smpl.calloc (jmax ((
size_t) length + 1,
sizeof (SMPLChunk)), 1);
1078 else if (chunkType == chunkName (
"inst") || chunkType == chunkName (
"INST"))
1081 inst.calloc (jmax ((
size_t) length + 1,
sizeof (InstChunk)), 1);
1085 else if (chunkType == chunkName (
"cue "))
1088 cue.calloc (jmax ((
size_t) length + 1,
sizeof (CueChunk)), 1);
1092 else if (chunkType == chunkName (
"axml"))
1098 else if (chunkType == chunkName (
"LIST"))
1161 else if (chunkType == chunkName (
"acid"))
1165 else if (chunkType == chunkName (
"Trkn"))
1193 if (numSamples <= 0)
1198 while (numSamples > 0)
1235 default: jassertfalse;
break;
1243 return channelLayout;
1245 return WavFileHelpers::canonicalWavChannelSet (
static_cast<int> (
numChannels));
1274 return wavFileChannelLayout;
1277 int64 bwavChunkStart = 0, bwavSize = 0;
1278 int64 dataChunkStart = 0, dataLength = 0;
1279 int bytesPerFrame = 0;
1280 bool isRF64 =
false;
1281 bool isSubformatOggVorbis =
false;
1283 AudioChannelSet channelLayout;
1286 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WavAudioFormatReader)
1298 using namespace WavFileHelpers;
1300 if (metadataValues.
size() > 0)
1305 jassert (metadataValues.
getValue (
"MetaDataSource",
"None") !=
"AIFF");
1307 bwavChunk = BWAVChunk::createFrom (metadataValues);
1308 axmlChunk = AXMLChunk::createFrom (metadataValues);
1309 smplChunk = SMPLChunk::createFrom (metadataValues);
1310 instChunk = InstChunk::createFrom (metadataValues);
1311 cueChunk = CueChunk ::createFrom (metadataValues);
1312 listChunk = ListChunk::createFrom (metadataValues);
1313 listInfoChunk = ListInfoChunk::createFrom (metadataValues);
1314 acidChunk = AcidChunk::createFrom (metadataValues);
1315 trckChunk = TracktionChunk::createFrom (metadataValues);
1318 headerPosition =
out->getPosition();
1328 bool write (
const int** data,
int numSamples)
override
1330 jassert (numSamples >= 0);
1331 jassert (data !=
nullptr && *data !=
nullptr);
1345 default: jassertfalse;
break;
1358 bytesWritten +=
bytes;
1359 lengthInSamples += (
uint64) numSamples;
1378 MemoryBlock tempBlock, bwavChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk, listInfoChunk, acidChunk, trckChunk;
1379 uint64 lengthInSamples = 0, bytesWritten = 0;
1380 int64 headerPosition = 0;
1381 bool writeFailed =
false;
1385 if ((bytesWritten & 1) != 0)
1388 using namespace WavFileHelpers;
1399 uint64 audioDataSize = bytesPerFrame * lengthInSamples;
1400 auto channelMask = getChannelMaskFromChannelLayout (
channelLayout);
1402 const bool isRF64 = (bytesWritten >= 0x100000000LL);
1403 const bool isWaveFmtEx = isRF64 || (channelMask != 0);
1405 int64 riffChunkSize = (int64) (4 + 8 + 40
1406 + 8 + audioDataSize + (audioDataSize & 1)
1407 + chunkSize (bwavChunk)
1408 + chunkSize (axmlChunk)
1409 + chunkSize (smplChunk)
1410 + chunkSize (instChunk)
1411 + chunkSize (cueChunk)
1412 + chunkSize (listChunk)
1413 + chunkSize (listInfoChunk)
1414 + chunkSize (acidChunk)
1415 + chunkSize (trckChunk)
1418 riffChunkSize += (riffChunkSize & 1);
1421 writeChunkHeader (chunkName (
"RF64"), -1);
1423 writeChunkHeader (chunkName (
"RIFF"), (
int) riffChunkSize);
1429 #if ! JUCE_WAV_DO_NOT_PAD_HEADER_SIZE
1440 writeChunkHeader (chunkName (
"JUNK"), 28 + (isWaveFmtEx? 0 : 24));
1446 #if JUCE_WAV_DO_NOT_PAD_HEADER_SIZE
1451 writeChunkHeader (chunkName (
"ds64"), 28);
1459 writeChunkHeader (chunkName (
"fmt "), 40);
1464 writeChunkHeader (chunkName (
"fmt "), 16);
1481 const ExtensibleWavSubFormat& subFormat =
bitsPerSample < 32 ? pcmFormat : IEEEFloatFormat;
1486 output->
write (subFormat.data4, sizeof (subFormat.data4));
1489 writeChunk (bwavChunk, chunkName (
"bext"));
1490 writeChunk (axmlChunk, chunkName (
"axml"));
1491 writeChunk (smplChunk, chunkName (
"smpl"));
1492 writeChunk (instChunk, chunkName (
"inst"), 7);
1493 writeChunk (cueChunk, chunkName (
"cue "));
1494 writeChunk (listChunk, chunkName (
"LIST"));
1495 writeChunk (listInfoChunk, chunkName (
"LIST"));
1496 writeChunk (acidChunk, chunkName (
"acid"));
1497 writeChunk (trckChunk, chunkName (
"Trkn"));
1499 writeChunkHeader (chunkName (
"data"), isRF64 ? -1 : (int) (lengthInSamples * bytesPerFrame));
1504 static size_t chunkSize (
const MemoryBlock& data)
noexcept {
return data.getSize() > 0 ? (8 + data.getSize()) : 0; }
1506 void writeChunkHeader (
int chunkType,
int size)
const
1512 void writeChunk (
const MemoryBlock& data,
int chunkType,
int size = 0)
const
1514 if (data.getSize() > 0)
1516 writeChunkHeader (chunkType, size != 0 ? size : (int) data.getSize());
1521 static int getChannelMaskFromChannelLayout (
const AudioChannelSet&
channelLayout)
1532 auto wavChannelMask = 0;
1534 for (
auto channel : channels)
1536 int wavChannelBit =
static_cast<int> (channel) - 1;
1537 jassert (wavChannelBit >= 0 && wavChannelBit <= 31);
1539 wavChannelMask |= (1 << wavChannelBit);
1542 return wavChannelMask;
1545 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WavAudioFormatWriter)
1554 reader.dataLength, reader.bytesPerFrame)
1584 zeromem (result,
sizeof (
float) * (
size_t)
num);
1588 auto dest = &result;
1599 default: jassertfalse;
break;
1609 jassert (numSamples <= 0);
1625 default: jassertfalse;
break;
1630 template <
typename SampleType>
1637 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryMappedWavReader)
1646 return { 8000, 11025, 12000, 16000, 22050, 32000, 44100,
1647 48000, 88200, 96000, 176400, 192000, 352800, 384000 };
1652 return { 8, 16, 24, 32 };
1678 #if JUCE_USE_OGGVORBIS
1679 if (r->isSubformatOggVorbis)
1686 if (r->sampleRate > 0 && r->numChannels > 0 && r->bytesPerFrame > 0 && r->bitsPerSample <= 32)
1714 unsigned int numChannels,
int bitsPerSample,
1717 return createWriterFor (
out, sampleRate, WavFileHelpers::canonicalWavChannelSet (
static_cast<int> (numChannels)),
1730 (
unsigned int) bitsPerSample, metadataValues);
1735namespace WavFileHelpers
1737 static bool slowCopyWavFileWithNewMetadata (
const File& file,
const StringPairArray& metadata)
1742 std::unique_ptr<AudioFormatReader> reader (
wav.createReaderFor (file.
createInputStream(),
true));
1744 if (reader !=
nullptr)
1746 std::unique_ptr<OutputStream>
outStream (
tempFile.getFile().createOutputStream());
1754 if (writer !=
nullptr)
1758 bool ok = writer->writeFromAudioReader (*reader, 0, -1);
1762 return ok &&
tempFile.overwriteTargetFileWithTemporary();
1773 using namespace WavFileHelpers;
1777 if (reader !=
nullptr)
1779 auto bwavPos = reader->bwavChunkStart;
1780 auto bwavSize = reader->bwavSize;
1787 if (
chunk.getSize() <= (
size_t) bwavSize)
1819 void runTest()
override
1821 beginTest (
"Setting up metadata");
1830 for (
int i = numElementsInArray (WavFileHelpers::ListInfoChunk::types); --i >= 0;)
1831 metadataValues.set (WavFileHelpers::ListInfoChunk::types[i],
1832 WavFileHelpers::ListInfoChunk::types[i]);
1834 if (metadataValues.size() > 0)
1835 metadataValues.set (
"MetaDataSource",
"WAV");
1839 WavAudioFormat format;
1843 beginTest (
"Creating a basic wave writer");
1845 std::unique_ptr<AudioFormatWriter> writer (format.createWriterFor (
new MemoryOutputStream (
memoryBlock,
false),
1847 32, metadataValues, 0));
1848 expect (writer !=
nullptr);
1853 beginTest (
"Writing audio data to the basic wave writer");
1858 beginTest (
"Creating a basic wave reader");
1860 std::unique_ptr<AudioFormatReader> reader (format.createReaderFor (
new MemoryInputStream (
memoryBlock,
false),
false));
1861 expect (reader !=
nullptr);
1862 expect (reader->
metadataValues == metadataValues,
"Somehow, the metadata is different!");
1877 m.set (
"Manufacturer",
"0");
1878 m.set (
"Product",
"0");
1879 m.set (
"SamplePeriod",
"0");
1880 m.set (
"MidiUnityNote",
"60");
1881 m.set (
"MidiPitchFraction",
"0");
1882 m.set (
"SmpteFormat",
"0");
1883 m.set (
"SmpteOffset",
"0");
1884 m.set (
"NumSampleLoops",
"0");
1885 m.set (
"SamplerData",
"0");
1893static const WaveAudioFormatTests waveAudioFormatTests;
Holds a resizable array of primitive or copy-by-value objects.
bool isEmpty() const noexcept
Returns true if the array is empty, false otherwise.
int size() const noexcept
Returns the current number of elements in the array.
Array()=default
Creates an empty array.
void set(int indexToChange, ParameterType newValue)
Replaces an element with a new value.
Represents a set of audio channel types.
static AudioChannelSet JUCE_CALLTYPE quadraphonic()
Creates a set for quadraphonic surround setup (left, right, leftSurround, rightSurround)
static AudioChannelSet JUCE_CALLTYPE create5point0()
Creates a set for a 5.0 surround setup (left, right, centre, leftSurround, rightSurround).
int size() const noexcept
Returns the number of channels in the set.
bool isDiscreteLayout() const noexcept
Returns if this is a channel layout made-up of discrete channels.
static AudioChannelSet JUCE_CALLTYPE mono()
Creates a one-channel mono set (centre).
static AudioChannelSet JUCE_CALLTYPE stereo()
Creates a set containing a stereo set (left, right).
ChannelType
Represents different audio channel types.
@ topRearRight
Top Rear Right channel.
@ discreteChannel0
Non-typed individual channels are indexed upwards from this value.
static AudioChannelSet JUCE_CALLTYPE create5point1()
Creates a set for a 5.1 surround setup (left, right, centre, leftSurround, rightSurround,...
static AudioChannelSet JUCE_CALLTYPE create7point0SDDS()
Creates a set for a SDDS 7.0 surround setup (left, right, centre, leftSurround, rightSurround,...
static AudioChannelSet JUCE_CALLTYPE create7point1SDDS()
Creates a set for a 7.1 surround setup (left, right, centre, leftSurround, rightSurround,...
static AudioChannelSet JUCE_CALLTYPE canonicalChannelSet(int numChannels)
Create a canonical channel set for a given number of channels.
static AudioChannelSet JUCE_CALLTYPE discreteChannels(int numChannels)
Creates a set of untyped discrete channels.
static AudioChannelSet JUCE_CALLTYPE createLCR()
Creates a set containing an LCR set (left, right, centre).
Array< ChannelType > getChannelTypes() const
Returns an array of all the types in this channel set.
An arbitrarily large integer class.
static JUCE_CONSTEXPR uint16 swap(uint16 value) noexcept
Swaps the upper and lower bytes of a 16-bit integer.
static Type swapIfBigEndian(Type value) noexcept
Swaps the byte order of a signed or unsigned integer if the CPU is big-endian.
static JUCE_CONSTEXPR uint32 littleEndianInt(const void *bytes) noexcept
Turns 4 bytes into a little-endian integer.
static juce_wchar toUpperCase(juce_wchar character) noexcept
Converts a character to upper-case.
An output stream that writes into a local file.
Represents a local file or directory.
FileInputStream * createInputStream() const
Creates a stream to read from this file.
A class to hold a resizable block of raw data.
void ensureSize(const size_t minimumSize, bool initialiseNewSpaceToZero=false)
Increases the block's size only if it's smaller than a given size.
void setSize(const size_t newSize, bool initialiseNewSpaceToZero=false)
Resizes the memory block.
void fillWith(uint8 valueToUse) noexcept
Fills the entire memory block with a repeated byte value.
void * getData() const noexcept
Returns a void pointer to the data.
void readMaxLevels(int64 startSampleInFile, int64 numSamples, Range< float > *results, int numChannelsToRead) override
Finds the highest and lowest sample levels from a section of the audio stream.
void getSample(int64 sample, float *result) const noexcept override
Returns the samples for all channels at a given sample position.
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.
Writes data to an internal memory buffer, which grows as required.
The base class for streams that write data to some kind of destination.
virtual bool write(const void *dataToWrite, size_t numberOfBytes)=0
Writes a block of data to the stream.
virtual bool writeRepeatedByte(uint8 byte, size_t numTimesToRepeat)
Writes a byte to the output stream a given number of times.
virtual int64 getPosition()=0
Returns the stream's current position.
virtual bool writeByte(char byte)
Writes a single byte to the stream.
virtual bool writeShort(short value)
Writes a 16-bit integer to the stream in a little-endian byte order.
virtual bool writeInt64(int64 value)
Writes a 64-bit integer to the stream in a little-endian byte order.
virtual bool setPosition(int64 newPosition)=0
Tries to move the stream's output position.
virtual bool writeInt(int value)
Writes a 32-bit integer to the stream in a little-endian byte order.
JUCE_CONSTEXPR bool contains(const ValueType position) const noexcept
Returns true if the given position lies inside this range.
A container for holding a set of strings which are keyed by another string.
String getValue(StringRef, const String &defaultReturnValue) const
Finds the value corresponding to a key string.
bool containsKey(StringRef key) const noexcept
Returns true if the given key exists.
void set(const String &key, const String &value)
Adds or amends a key/value pair.
int size() const noexcept
Returns the number of strings in the array.
const StringArray & getAllKeys() const noexcept
Returns a list of all keys in the array.
static String createStringFromData(const void *data, int size)
Creates a string from data in an unknown format.
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
Creates a String from a UTF-8 encoded buffer.
int getIntValue() const noexcept
Reads the value of the string as a decimal number (up to 32 bits in size).
Manages a temporary file, which will be deleted when this object is deleted.
Holds an absolute date and time.
static Time JUCE_CALLTYPE getCurrentTime() noexcept
Returns a Time object that is set to the current system time.
This is a base class for classes that perform a unit test.
AcidChunk(InputStream &input, size_t length)
Reads an acid RIFF chunk from a stream positioned just after the size byte.