31static auto toMap (
const StringPairArray& array)
35 for (
auto i = 0; i < array.size(); ++i)
36 result[array.getAllKeys()[i]] = array.getAllValues()[i];
41static auto getValueWithDefault (
const StringMap& m,
const String& key,
const String& fallback = {})
43 const auto iter = m.find (key);
44 return iter != m.cend() ? iter->second : fallback;
47static const char*
const wavFormatName =
"WAV file";
60 const String& originatorRef,
63 const String& codingHistory)
261namespace WavFileHelpers
264 constexpr inline size_t roundUpSize (
size_t sz)
noexcept {
return (
sz + 3) & ~3u; }
267 #pragma pack (push, 1)
272 char description[256];
274 char originatorRef[32];
275 char originationDate[10];
276 char originationTime[8];
282 char codingHistory[1];
284 void copyTo (
StringMap& values,
const int totalSize)
const
321 if (b->description[0] != 0
322 || b->originator[0] != 0
323 || b->originationDate[0] != 0
324 || b->originationTime[0] != 0
325 || b->codingHistory[0] != 0
375 template <
typename NameType>
383 setValue (values,
"Loop" +
String (prefix) + name,
val);
386 void copyTo (
StringMap& values,
const int totalSize)
const
388 setValue (values,
"Manufacturer", manufacturer);
389 setValue (values,
"Product", product);
390 setValue (values,
"SamplePeriod", samplePeriod);
391 setValue (values,
"MidiUnityNote", midiUnityNote);
392 setValue (values,
"MidiPitchFraction", midiPitchFraction);
393 setValue (values,
"SmpteFormat", smpteFormat);
394 setValue (values,
"SmpteOffset", smpteOffset);
395 setValue (values,
"NumSampleLoops", numSampleLoops);
396 setValue (values,
"SamplerData", samplerData);
398 for (
int i = 0; i < (
int) numSampleLoops; ++i)
400 if ((
uint8*) (loops + (i + 1)) > ((
uint8*)
this) + totalSize)
403 setValue (values, i,
"Identifier", loops[i].identifier);
404 setValue (values, i,
"Type", loops[i].type);
405 setValue (values, i,
"Start", loops[i].start);
406 setValue (values, i,
"End", loops[i].
end);
407 setValue (values, i,
"Fraction", loops[i].fraction);
408 setValue (values, i,
"PlayCount", loops[i].playCount);
412 template <
typename NameType>
418 static uint32 getValue (
const StringMap& values,
int prefix,
const char* name,
const char*
def)
420 return getValue (values,
"Loop" + String (prefix) + name,
def);
423 static MemoryBlock createFrom (
const StringMap& values)
426 auto numLoops =
jmin (64, getValueWithDefault (values,
"NumSampleLoops",
"0").getIntValue());
428 data.setSize (roundUpSize (
sizeof (SMPLChunk) + (
size_t) (
jmax (0,
numLoops - 1)) *
sizeof (SampleLoop)),
true);
430 auto s =
static_cast<SMPLChunk*
> (
data.getData());
432 s->manufacturer = getValue (values,
"Manufacturer",
"0");
433 s->product = getValue (values,
"Product",
"0");
434 s->samplePeriod = getValue (values,
"SamplePeriod",
"0");
435 s->midiUnityNote = getValue (values,
"MidiUnityNote",
"60");
436 s->midiPitchFraction = getValue (values,
"MidiPitchFraction",
"0");
437 s->smpteFormat = getValue (values,
"SmpteFormat",
"0");
438 s->smpteOffset = getValue (values,
"SmpteOffset",
"0");
440 s->samplerData = getValue (values,
"SamplerData",
"0");
444 auto&
loop = s->loops[i];
445 loop.identifier = getValue (values, i,
"Identifier",
"0");
446 loop.type = getValue (values, i,
"Type",
"0");
447 loop.start = getValue (values, i,
"Start",
"0");
448 loop.end = getValue (values, i,
"End",
"0");
449 loop.fraction = getValue (values, i,
"Fraction",
"0");
450 loop.playCount = getValue (values, i,
"PlayCount",
"0");
468 static void setValue (
StringMap& values,
const char* name,
int val)
475 setValue (values,
"MidiUnityNote", baseNote);
476 setValue (values,
"Detune", detune);
477 setValue (values,
"Gain", gain);
478 setValue (values,
"LowNote", lowNote);
479 setValue (values,
"HighNote", highNote);
480 setValue (values,
"LowVelocity", lowVelocity);
481 setValue (values,
"HighVelocity", highVelocity);
484 static int8 getValue (
const StringMap& values,
const char* name,
const char*
def)
486 return (
int8) getValueWithDefault (values, name,
def).getIntValue();
493 if ( values.
find (
"LowNote") != values.
cend()
494 && values.
find (
"HighNote") != values.
cend())
496 data.setSize (8,
true);
499 inst->baseNote = getValue (values,
"MidiUnityNote",
"60");
500 inst->detune = getValue (values,
"Detune",
"0");
501 inst->gain = getValue (values,
"Gain",
"0");
502 inst->lowNote = getValue (values,
"LowNote",
"0");
503 inst->highNote = getValue (values,
"HighNote",
"127");
504 inst->lowVelocity = getValue (values,
"LowVelocity",
"1");
505 inst->highVelocity = getValue (values,
"HighVelocity",
"127");
533 void copyTo (
StringMap& values,
const int totalSize)
const
537 for (
int i = 0; i < (
int) numCues; ++i)
539 if ((
uint8*) (cues + (i + 1)) > ((
uint8*)
this) + totalSize)
542 setValue (values, i,
"Identifier", cues[i].identifier);
543 setValue (values, i,
"Order", cues[i].order);
544 setValue (values, i,
"ChunkID", cues[i].chunkID);
545 setValue (values, i,
"ChunkStart", cues[i].chunkStart);
546 setValue (values, i,
"BlockStart", cues[i].blockStart);
547 setValue (values, i,
"Offset", cues[i].offset);
551 static MemoryBlock createFrom (
const StringMap& values)
554 const int numCues = getValueWithDefault (values,
"NumCuePoints",
"0").getIntValue();
558 data.setSize (roundUpSize (
sizeof (CueChunk) + (
size_t) (numCues - 1) *
sizeof (Cue)),
true);
560 auto c =
static_cast<CueChunk*
> (data.getData());
571 for (
int i = 0; i < numCues; ++i)
573 auto prefix =
"Cue" + String (i);
574 auto identifier = (
uint32) getValueWithDefault (values, prefix +
"Identifier",
"0").getIntValue();
581 auto order = getValueWithDefault (values, prefix +
"Order", String (
nextOrder)).getIntValue();
584 auto&
cue = c->cues[i];
602 static int getValue (
const StringMap& values,
const String& name)
604 return getValueWithDefault (values, name,
"0").getIntValue();
607 static int getValue (
const StringMap& values,
const String& prefix,
const char* name)
609 return getValue (values, prefix + name);
612 static void appendLabelOrNoteChunk (
const StringMap& values,
const String& prefix,
613 const int chunkType, MemoryOutputStream& out)
615 auto label = getValueWithDefault (values, prefix +
"Text", prefix);
621 out.writeInt (getValue (values, prefix,
"Identifier"));
624 if ((out.getDataSize() & 1) != 0)
628 static void appendExtraChunk (
const StringMap& values,
const String& prefix, MemoryOutputStream& out)
630 auto text = getValueWithDefault (values, prefix +
"Text", prefix);
635 out.writeInt (chunkName (
"ltxt"));
637 out.writeInt (getValue (values, prefix,
"Identifier"));
638 out.writeInt (getValue (values, prefix,
"SampleLength"));
639 out.writeInt (getValue (values, prefix,
"Purpose"));
640 out.writeShort ((
short) getValue (values, prefix,
"Country"));
641 out.writeShort ((
short) getValue (values, prefix,
"Language"));
642 out.writeShort ((
short) getValue (values, prefix,
"Dialect"));
643 out.writeShort ((
short) getValue (values, prefix,
"CodePage"));
646 if ((out.getDataSize() & 1) != 0)
650 static MemoryBlock createFrom (
const StringMap& values)
653 auto numCueNotes = getValue (values,
"NumCueNotes");
656 MemoryOutputStream out;
660 out.writeInt (chunkName (
"adtl"));
663 appendLabelOrNoteChunk (values,
"CueLabel" + String (i), chunkName (
"labl"), out);
666 appendLabelOrNoteChunk (values,
"CueNote" + String (i), chunkName (
"note"), out);
669 appendExtraChunk (values,
"CueRegion" + String (i), out);
672 return out.getMemoryBlock();
678 namespace ListInfoChunk
680 static const char*
const types[] =
765 static bool isMatchingTypeIgnoringCase (
const int value,
const char*
const name)
noexcept
767 for (
int i = 0; i < 4; ++i)
788 for (
auto& type : types)
790 if (isMatchingTypeIgnoringCase (
infoType, type))
805 auto value = getValueWithDefault (values,
paramName, {});
829 for (
auto& type : types)
830 if (writeValue (values, out, type))
844 input.
read (
this, (
int)
jmin (
sizeof (*
this), length));
866 if (iter != values.
cend())
867 tempo = swapFloatByteOrder (iter->second.getFloatValue());
872 return AcidChunk (values).toMemoryBlock();
875 MemoryBlock toMemoryBlock()
const
877 return (flags != 0 || rootNote != 0 || numBeats != 0 || meterDenominator != 0 || meterNumerator != 0)
878 ? MemoryBlock (
this,
sizeof (*
this)) : MemoryBlock();
881 void addToMetadata (StringMap& values)
const
898 void setBoolFlag (StringMap& values,
const char* name,
uint32 mask)
const
903 static uint32 getFlagIfPresent (
const StringMap& values,
const char* name,
uint32 flag)
908 static float swapFloatByteOrder (
const float x)
noexcept
910 #ifdef JUCE_BIG_ENDIAN
1045 if (xml->hasTagName (
"BWFXML"))
1050 if (
const auto*
aswgElement = xml->getChildByName (
"ASWG"))
1052 for (
const auto* entry :
aswgElement->getChildIterator())
1054 const auto& tag = entry->getTagName();
1056 if (aswgMetadataKeys.find (tag) != aswgMetadataKeys.end())
1064 static MemoryBlock createFrom (
const StringMap& values)
1066 auto createTextElement = [] (
const StringRef& key,
const StringRef& value)
1068 auto*
elem =
new XmlElement (key);
1069 elem->addTextElement (value);
1075 for (
const auto& pair : values)
1077 if (aswgMetadataKeys.find (pair.first) != aswgMetadataKeys.end())
1080 aswgElement = std::make_unique<XmlElement> (
"ASWG");
1082 aswgElement->addChildElement (createTextElement (pair.first, pair.second));
1090 XmlElement xml (
"BWFXML");
1105 static void addToMetadata (StringMap&
destValues,
const String& source)
1109 if (xml->hasTagName (
"ebucore:ebuCoreMain"))
1111 if (
auto xml2 = xml->getChildByName (
"ebucore:coreMetadata"))
1113 if (
auto xml3 =
xml2->getChildByName (
"ebucore:identifier"))
1115 if (
auto xml4 =
xml3->getChildByName (
"dc:identifier"))
1117 auto ISRCCode =
xml4->getAllSubText().fromFirstOccurrenceOf (
"ISRC:",
false,
true);
1133 static MemoryBlock createFrom (
const StringMap& values)
1137 auto ISRC = getValueWithDefault (values,
1141 MemoryOutputStream xml;
1143 if (ISRC.isNotEmpty())
1151 jassert (ISRC.length() == 12);
1153 xml <<
"<ebucore:ebuCoreMain xmlns:dc=\" http://purl.org/dc/elements/1.1/\" "
1154 "xmlns:ebucore=\"urn:ebu:metadata-schema:ebuCore_2012\">"
1155 "<ebucore:coreMetadata>"
1156 "<ebucore:identifier typeLabel=\"GUID\" "
1157 "typeDefinition=\"Globally Unique Identifier\" "
1158 "formatLabel=\"ISRC\" "
1159 "formatDefinition=\"International Standard Recording Code\" "
1160 "formatLink=\"http://www.ebu.ch/metadata/cs/ebu_IdentifierTypeCodeCS.xml#3.7\">"
1161 "<dc:identifier>ISRC:" << ISRC <<
"</dc:identifier>"
1162 "</ebucore:identifier>"
1163 "</ebucore:coreMetadata>"
1164 "</ebucore:ebuCoreMain>";
1166 xml.writeRepeatedByte (0, xml.getDataSize());
1169 return xml.getMemoryBlock();
1186 static const ExtensibleWavSubFormat pcmFormat = { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
1187 static const ExtensibleWavSubFormat IEEEFloatFormat = { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } };
1188 static const ExtensibleWavSubFormat ambisonicFormat = { 0x00000001, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 } };
1212 using namespace WavFileHelpers;
1288 else if (format == 0xfffe)
1313 else if (format == 0x674f
1318 || format == 0x6771)
1320 isSubformatOggVorbis =
true;
1325 else if (format != 1)
1330 else if (
chunkType == chunkName (
"data"))
1339 dataLength = length;
1343 lengthInSamples = (bytesPerFrame > 0) ? (dataLength / bytesPerFrame) : 0;
1345 else if (
chunkType == chunkName (
"bext"))
1355 else if (
chunkType == chunkName (
"smpl"))
1369 else if (
chunkType == chunkName (
"cue "))
1372 cue.
calloc (
jmax ((
size_t) length + 1,
sizeof (CueChunk)), 1);
1374 cue->copyTo (
dict, (
int) length);
1376 else if (
chunkType == chunkName (
"axml"))
1380 AXMLChunk::addToMetadata (
dict,
axml.toString());
1382 else if (
chunkType == chunkName (
"iXML"))
1386 IXMLChunk::addToMetadata (
dict,
ixml.toString());
1388 else if (
chunkType == chunkName (
"LIST"))
1394 ListInfoChunk::addToMetadata (
dict, *
input, chunkEnd);
1419 dict[prefix +
"Identifier"] =
String (identifier);
1437 dict[prefix +
"Identifier"] =
String (identifier);
1451 else if (
chunkType == chunkName (
"acid"))
1453 AcidChunk (*
input, length).addToMetadata (
dict);
1455 else if (
chunkType == chunkName (
"Trkn"))
1473 if (
dict.size() > 0)
dict[
"MetaDataSource"] =
"WAV";
1485 if (numSamples <= 0)
1490 while (numSamples > 0)
1501 zeromem (tempBuffer + bytesRead, (
size_t) (
numThisTime * bytesPerFrame - bytesRead));
1517 const void*
sourceData,
int numberOfChannels,
int numSamples)
noexcept
1535 return channelLayout;
1537 return WavFileHelpers::canonicalWavChannelSet (
static_cast<int> (
numChannels));
1569 int64 bwavChunkStart = 0, bwavSize = 0;
1570 int64 dataChunkStart = 0, dataLength = 0;
1571 int bytesPerFrame = 0;
1572 bool isRF64 =
false;
1573 bool isSubformatOggVorbis =
false;
1575 AudioChannelSet channelLayout;
1590 using namespace WavFileHelpers;
1592 if (metadataValues.
size() > 0)
1597 jassert (metadataValues.
getValue (
"MetaDataSource",
"None") !=
"AIFF");
1599 const auto map = toMap (metadataValues);
1601 bwavChunk = BWAVChunk::createFrom (map);
1602 ixmlChunk = IXMLChunk::createFrom (map);
1603 axmlChunk = AXMLChunk::createFrom (map);
1604 smplChunk = SMPLChunk::createFrom (map);
1605 instChunk = InstChunk::createFrom (map);
1606 cueChunk = CueChunk ::createFrom (map);
1607 listChunk = ListChunk::createFrom (map);
1608 listInfoChunk = ListInfoChunk::createFrom (map);
1609 acidChunk = AcidChunk::createFrom (map);
1610 trckChunk = TracktionChunk::createFrom (map);
1623 bool write (
const int** data,
int numSamples)
override
1626 jassert (data !=
nullptr && *data !=
nullptr);
1653 bytesWritten += bytes;
1654 lengthInSamples += (
uint64) numSamples;
1673 MemoryBlock tempBlock, bwavChunk, ixmlChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk, listInfoChunk, acidChunk, trckChunk;
1674 uint64 lengthInSamples = 0, bytesWritten = 0;
1675 int64 headerPosition = 0;
1676 bool writeFailed =
false;
1680 if ((bytesWritten & 1) != 0)
1683 using namespace WavFileHelpers;
1697 const bool isRF64 = (bytesWritten >= 0x100000000LL);
1702 + chunkSize (bwavChunk)
1703 + chunkSize (ixmlChunk)
1704 + chunkSize (axmlChunk)
1705 + chunkSize (smplChunk)
1706 + chunkSize (instChunk)
1707 + chunkSize (cueChunk)
1708 + chunkSize (listChunk)
1709 + chunkSize (listInfoChunk)
1710 + chunkSize (acidChunk)
1711 + chunkSize (trckChunk)
1717 writeChunkHeader (chunkName (
"RF64"), -1);
1725 #if ! JUCE_WAV_DO_NOT_PAD_HEADER_SIZE
1736 writeChunkHeader (chunkName (
"JUNK"), 28 + (
isWaveFmtEx? 0 : 24));
1742 #if JUCE_WAV_DO_NOT_PAD_HEADER_SIZE
1747 writeChunkHeader (chunkName (
"ds64"), 28);
1755 writeChunkHeader (chunkName (
"fmt "), 40);
1760 writeChunkHeader (chunkName (
"fmt "), 16);
1785 writeChunk (bwavChunk, chunkName (
"bext"));
1786 writeChunk (ixmlChunk, chunkName (
"iXML"));
1787 writeChunk (axmlChunk, chunkName (
"axml"));
1788 writeChunk (smplChunk, chunkName (
"smpl"));
1789 writeChunk (instChunk, chunkName (
"inst"), 7);
1790 writeChunk (cueChunk, chunkName (
"cue "));
1791 writeChunk (listChunk, chunkName (
"LIST"));
1792 writeChunk (listInfoChunk, chunkName (
"LIST"));
1793 writeChunk (acidChunk, chunkName (
"acid"));
1794 writeChunk (trckChunk, chunkName (
"Trkn"));
1796 writeChunkHeader (chunkName (
"data"), isRF64 ? -1 : (
int) (lengthInSamples * bytesPerFrame));
1801 static size_t chunkSize (
const MemoryBlock& data)
noexcept {
return data.isEmpty() ? 0 : (8 +
data.getSize()); }
1803 void writeChunkHeader (
int chunkType,
int size)
const
1809 void writeChunk (
const MemoryBlock& data,
int chunkType,
int size = 0)
const
1811 if (!
data.isEmpty())
1818 static int getChannelMaskFromChannelLayout (
const AudioChannelSet& layout)
1820 if (layout.isDiscreteLayout())
1828 auto channels = layout.getChannelTypes();
1831 for (
auto channel : channels)
1851 reader.dataLength, reader.bytesPerFrame)
1861 if (numSamples <= 0)
1880 if (map ==
nullptr || ! mappedSection.
contains (sample))
1884 zeromem (result, (
size_t) num *
sizeof (
float));
1888 auto dest = &result;
1932 template <
typename SampleType>
1948 return { 8000, 11025, 12000, 16000, 22050, 32000, 44100,
1949 48000, 88200, 96000, 176400, 192000, 352800, 384000 };
1954 return { 8, 16, 24, 32 };
1980 #if JUCE_USE_OGGVORBIS
1981 if (r->isSubformatOggVorbis)
1988 if (r->sampleRate > 0 && r->numChannels > 0 && r->bytesPerFrame > 0 && r->bitsPerSample <= 32)
2016 unsigned int numChannels,
int bitsPerSample,
2019 return createWriterFor (out, sampleRate, WavFileHelpers::canonicalWavChannelSet (
static_cast<int> (numChannels)),
2032 (
unsigned int) bitsPerSample, metadataValues);
2037namespace WavFileHelpers
2046 if (reader !=
nullptr)
2056 if (writer !=
nullptr)
2060 bool ok = writer->writeFromAudioReader (*reader, 0, -1);
2064 return ok &&
tempFile.overwriteTargetFileWithTemporary();
2075 using namespace WavFileHelpers;
2079 if (reader !=
nullptr)
2081 auto bwavPos = reader->bwavChunkStart;
2082 auto bwavSize = reader->bwavSize;
2089 if (
chunk.getSize() <= (
size_t) bwavSize)
2125 void runTest()
override
2127 beginTest (
"Setting up metadata");
2137 metadataValues[WavFileHelpers::ListInfoChunk::types[i]] = WavFileHelpers::ListInfoChunk::types[i];
2141 if (metadataValues.
size() > 0)
2142 metadataValues[
"MetaDataSource"] =
"WAV";
2147 WavAudioFormat format;
2154 beginTest (
"Metadata can be written and read");
2161 beginTest (
"Files containing a riff info source and an empty ISRC associate the source with the riffInfoSource key");
2162 StringPairArray meta;
2174 beginTest (
"Files containing a riff info source and no ISRC associate the source with both keys "
2175 "for backwards compatibility");
2176 StringPairArray meta;
2186 beginTest (
"Files containing an ISRC associate the value with the internationalStandardRecordingCode key "
2187 "and the riffInfoSource key for backwards compatibility");
2188 StringPairArray meta;
2199 beginTest (
"Files containing an ISRC and a riff info source associate the values with the appropriate keys");
2200 StringPairArray meta;
2211 beginTest (
"Files containing ASWG metadata read and write correctly");
2213 StringPairArray meta;
2215 for (
const auto& key : WavFileHelpers::IXMLChunk::aswgMetadataKeys)
2216 meta.set (key,
"Test123&<>");
2219 auto writer =
rawToUniquePtr (WavAudioFormat().createWriterFor (
new MemoryOutputStream (
block,
false), 48000, 1, 32, meta, 0));
2220 expect (writer !=
nullptr);
2225 auto input = std::make_unique<MemoryInputStream> (
block,
false);
2227 while (! input->isExhausted())
2230 auto pos = input->getPosition();
2236 auto length = (
uint32) input->readInt();
2239 input->readIntoMemoryBlock (
xmlBlock, (ssize_t) length);
2244 input->setPosition (pos + 1);
2251 auto reader =
rawToUniquePtr (WavAudioFormat().createReaderFor (
new MemoryInputStream (
block,
false),
true));
2252 expect (reader !=
nullptr);
2254 for (
const auto& key : meta.getAllKeys())
2256 const auto oldValue = meta.getValue (key,
"!");
2258 expectEquals (oldValue, newValue);
2267 MemoryBlock
writeToBlock (WavAudioFormat& format, StringPairArray meta)
2280 expect (writer !=
nullptr);
2291 expect (reader !=
nullptr);
2295 template <
typename Fn>
2298 for (
const auto& pattern :
patterns)
2300 const auto begin =
static_cast<const char*
> (
mb.getData());
2326 m[
"Manufacturer"] =
"0";
2328 m[
"SamplePeriod"] =
"0";
2329 m[
"MidiUnityNote"] =
"60";
2330 m[
"MidiPitchFraction"] =
"0";
2331 m[
"SmpteFormat"] =
"0";
2332 m[
"SmpteOffset"] =
"0";
2333 m[
"NumSampleLoops"] =
"0";
2334 m[
"SamplerData"] =
"0";
Holds a resizable array of primitive or copy-by-value objects.
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.
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).
An arbitrarily large integer class.
static constexpr uint32 littleEndianInt(const void *bytes) noexcept
Turns 4 bytes into a little-endian integer.
static 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_wchar toUpperCase(juce_wchar character) noexcept
Converts a character to upper-case.
An output stream that writes into a local file.
bool setPosition(int64) override
Tries to move the stream's output position.
bool openedOk() const noexcept
Returns true if the stream opened without problems.
Represents a local file or directory.
std::unique_ptr< FileInputStream > createInputStream() const
Creates a stream to read from this file.
Very simple container class to hold a pointer to some data on the heap.
void calloc(SizeType newNumElements, const size_t elementSize=sizeof(ElementType))
Allocates a specified amount of memory and clears it.
A class to hold a resizable block of raw data.
void * getData() noexcept
Returns a void pointer to the data.
void ensureSize(size_t minimumSize, bool initialiseNewSpaceToZero=false)
Increases the block's size only if it's smaller than a given size.
bool readSamples(int *const *destSamples, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples) override
Subclasses must implement this method to perform the low-level read operation.
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.
Writes data to an internal memory buffer, which grows as required.
size_t getDataSize() const noexcept
Returns the number of bytes of data that have been written to the stream.
bool write(const void *, size_t) override
Writes a block of data to the stream.
MemoryBlock getMemoryBlock() const
Returns a copy of the stream's data as a memory block.
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.
virtual bool writeString(const String &text)
Stores a string in the stream in a binary format.
A general-purpose range object, that simply represents any linear range with a start and end point.
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.
void set(const String &key, const String &value)
Adds or amends a key/value pair.
void addUnorderedMap(const std::unordered_map< String, String > &mapToAdd)
Adds the contents of an unordered map to this StringPairArray.
int size() const noexcept
Returns the number of strings 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.
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.
String formatted(const String &format) const
Converts this date/time to a string with a user-defined format.
This is a base class for classes that perform a unit test.
void zerostruct(Type &structure) noexcept
Overwrites a structure or object with zeros.
unsigned short uint16
A platform-independent 16-bit unsigned integer type.
wchar_t juce_wchar
A platform-independent 32-bit unicode character type.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
constexpr Type jmax(Type a, Type b)
Returns the larger of two values.
RangedDirectoryIterator end(const RangedDirectoryIterator &)
Returns a default-constructed sentinel value.
std::unique_ptr< XmlElement > parseXML(const String &textToParse)
Attempts to parse some XML text, returning a new XmlElement if it was valid.
signed char int8
A platform-independent 8-bit signed integer type.
unsigned long long uint64
A platform-independent 64-bit unsigned integer type.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
unsigned int uint32
A platform-independent 32-bit unsigned integer type.
unsigned char uint8
A platform-independent 8-bit unsigned integer type.
RangedDirectoryIterator begin(const RangedDirectoryIterator &it)
Returns the iterator that was passed in.
constexpr int numElementsInArray(Type(&)[N]) noexcept
Handy function for getting the number of elements in a simple const C array.
long long int64
A platform-independent 64-bit integer type.
std::unique_ptr< T > rawToUniquePtr(T *ptr)
Converts an owning raw pointer into a unique_ptr, deriving the type of the unique_ptr automatically.
void zeromem(void *memory, size_t numBytes) noexcept
Fills a block of memory with zeros.
AcidChunk(InputStream &input, size_t length)
Reads an acid RIFF chunk from a stream positioned just after the size byte.