From 1abb704ce0e22276efcd3954556b41453c70daf4 Mon Sep 17 00:00:00 2001 From: Oli Date: Tue, 5 Apr 2022 12:45:33 +0100 Subject: [PATCH] WavAudioFormat: Add ASWG metadata support --- .../codecs/juce_WavAudioFormat.cpp | 302 +++++++++++++++++- .../codecs/juce_WavAudioFormat.h | 88 +++++ 2 files changed, 389 insertions(+), 1 deletion(-) diff --git a/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp b/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp index d63f21c946..debe26f0ea 100644 --- a/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp +++ b/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp @@ -161,6 +161,91 @@ const char* const WavAudioFormat::riffInfoWatermarkURL = "IWMU"; const char* const WavAudioFormat::riffInfoWrittenBy = "IWRI"; const char* const WavAudioFormat::riffInfoYear = "YEAR"; +const char* const WavAudioFormat::aswgContentType = "contentType"; +const char* const WavAudioFormat::aswgProject = "project"; +const char* const WavAudioFormat::aswgOriginator = "originator"; +const char* const WavAudioFormat::aswgOriginatorStudio = "originatorStudio"; +const char* const WavAudioFormat::aswgNotes = "notes"; +const char* const WavAudioFormat::aswgSession = "session"; +const char* const WavAudioFormat::aswgState = "state"; +const char* const WavAudioFormat::aswgEditor = "editor"; +const char* const WavAudioFormat::aswgMixer = "mixer"; +const char* const WavAudioFormat::aswgFxChainName = "fxChainName"; +const char* const WavAudioFormat::aswgChannelConfig = "channelConfig"; +const char* const WavAudioFormat::aswgAmbisonicFormat = "ambisonicFormat"; +const char* const WavAudioFormat::aswgAmbisonicChnOrder = "ambisonicChnOrder"; +const char* const WavAudioFormat::aswgAmbisonicNorm = "ambisonicNorm"; +const char* const WavAudioFormat::aswgMicType = "micType"; +const char* const WavAudioFormat::aswgMicConfig = "micConfig"; +const char* const WavAudioFormat::aswgMicDistance = "micDistance"; +const char* const WavAudioFormat::aswgRecordingLoc = "recordingLoc"; +const char* const WavAudioFormat::aswgIsDesigned = "isDesigned"; +const char* const WavAudioFormat::aswgRecEngineer = "recEngineer"; +const char* const WavAudioFormat::aswgRecStudio = "recStudio"; +const char* const WavAudioFormat::aswgImpulseLocation = "impulseLocation"; +const char* const WavAudioFormat::aswgCategory = "category"; +const char* const WavAudioFormat::aswgSubCategory = "subCategory"; +const char* const WavAudioFormat::aswgCatId = "catId"; +const char* const WavAudioFormat::aswgUserCategory = "userCategory"; +const char* const WavAudioFormat::aswgUserData = "userData"; +const char* const WavAudioFormat::aswgVendorCategory = "vendorCategory"; +const char* const WavAudioFormat::aswgFxName = "fxName"; +const char* const WavAudioFormat::aswgLibrary = "library"; +const char* const WavAudioFormat::aswgCreatorId = "creatorId"; +const char* const WavAudioFormat::aswgSourceId = "sourceId"; +const char* const WavAudioFormat::aswgRmsPower = "rmsPower"; +const char* const WavAudioFormat::aswgLoudness = "loudness"; +const char* const WavAudioFormat::aswgLoudnessRange = "loudnessRange"; +const char* const WavAudioFormat::aswgMaxPeak = "maxPeak"; +const char* const WavAudioFormat::aswgSpecDensity = "specDensity"; +const char* const WavAudioFormat::aswgZeroCrossRate = "zeroCrossRate"; +const char* const WavAudioFormat::aswgPapr = "papr"; +const char* const WavAudioFormat::aswgText = "text"; +const char* const WavAudioFormat::aswgEfforts = "efforts"; +const char* const WavAudioFormat::aswgEffortType = "effortType"; +const char* const WavAudioFormat::aswgProjection = "projection"; +const char* const WavAudioFormat::aswgLanguage = "language"; +const char* const WavAudioFormat::aswgTimingRestriction = "timingRestriction"; +const char* const WavAudioFormat::aswgCharacterName = "characterName"; +const char* const WavAudioFormat::aswgCharacterGender = "characterGender"; +const char* const WavAudioFormat::aswgCharacterAge = "characterAge"; +const char* const WavAudioFormat::aswgCharacterRole = "characterRole"; +const char* const WavAudioFormat::aswgActorName = "actorName"; +const char* const WavAudioFormat::aswgActorGender = "actorGender"; +const char* const WavAudioFormat::aswgDirector = "director"; +const char* const WavAudioFormat::aswgDirection = "direction"; +const char* const WavAudioFormat::aswgFxUsed = "fxUsed"; +const char* const WavAudioFormat::aswgUsageRights = "usageRights"; +const char* const WavAudioFormat::aswgIsUnion = "isUnion"; +const char* const WavAudioFormat::aswgAccent = "accent"; +const char* const WavAudioFormat::aswgEmotion = "emotion"; +const char* const WavAudioFormat::aswgComposor = "composor"; +const char* const WavAudioFormat::aswgArtist = "artist"; +const char* const WavAudioFormat::aswgSongTitle = "songTitle"; +const char* const WavAudioFormat::aswgGenre = "genre"; +const char* const WavAudioFormat::aswgSubGenre = "subGenre"; +const char* const WavAudioFormat::aswgProducer = "producer"; +const char* const WavAudioFormat::aswgMusicSup = "musicSup"; +const char* const WavAudioFormat::aswgInstrument = "instrument"; +const char* const WavAudioFormat::aswgMusicPublisher = "musicPublisher"; +const char* const WavAudioFormat::aswgRightsOwner = "rightsOwner"; +const char* const WavAudioFormat::aswgIsSource = "isSource"; +const char* const WavAudioFormat::aswgIsLoop = "isLoop"; +const char* const WavAudioFormat::aswgIntensity = "intensity"; +const char* const WavAudioFormat::aswgIsFinal = "isFinal"; +const char* const WavAudioFormat::aswgOrderRef = "orderRef"; +const char* const WavAudioFormat::aswgIsOst = "isOst"; +const char* const WavAudioFormat::aswgIsCinematic = "isCinematic"; +const char* const WavAudioFormat::aswgIsLicensed = "isLicensed"; +const char* const WavAudioFormat::aswgIsDiegetic = "isDiegetic"; +const char* const WavAudioFormat::aswgMusicVersion = "musicVersion"; +const char* const WavAudioFormat::aswgIsrcId = "isrcId"; +const char* const WavAudioFormat::aswgTempo = "tempo"; +const char* const WavAudioFormat::aswgTimeSig = "timeSig"; +const char* const WavAudioFormat::aswgInKey = "inKey"; +const char* const WavAudioFormat::aswgBillingCode = "billingCode"; +const char* const WavAudioFormat::aswgVersion = "IXML_VERSION"; + const char* const WavAudioFormat::ISRC = "ISRC"; const char* const WavAudioFormat::internationalStandardRecordingCode = "international standard recording code"; const char* const WavAudioFormat::tracktionLoopInfo = "tracktion loop info"; @@ -856,6 +941,157 @@ namespace WavFileHelpers } }; + //============================================================================= + namespace IXMLChunk + { + static const std::unordered_set aswgMetadataKeys + { + WavAudioFormat::aswgContentType, + WavAudioFormat::aswgProject, + WavAudioFormat::aswgOriginator, + WavAudioFormat::aswgOriginatorStudio, + WavAudioFormat::aswgNotes, + WavAudioFormat::aswgSession, + WavAudioFormat::aswgState, + WavAudioFormat::aswgEditor, + WavAudioFormat::aswgMixer, + WavAudioFormat::aswgFxChainName, + WavAudioFormat::aswgChannelConfig, + WavAudioFormat::aswgAmbisonicFormat, + WavAudioFormat::aswgAmbisonicChnOrder, + WavAudioFormat::aswgAmbisonicNorm, + WavAudioFormat::aswgMicType, + WavAudioFormat::aswgMicConfig, + WavAudioFormat::aswgMicDistance, + WavAudioFormat::aswgRecordingLoc, + WavAudioFormat::aswgIsDesigned, + WavAudioFormat::aswgRecEngineer, + WavAudioFormat::aswgRecStudio, + WavAudioFormat::aswgImpulseLocation, + WavAudioFormat::aswgCategory, + WavAudioFormat::aswgSubCategory, + WavAudioFormat::aswgCatId, + WavAudioFormat::aswgUserCategory, + WavAudioFormat::aswgUserData, + WavAudioFormat::aswgVendorCategory, + WavAudioFormat::aswgFxName, + WavAudioFormat::aswgLibrary, + WavAudioFormat::aswgCreatorId, + WavAudioFormat::aswgSourceId, + WavAudioFormat::aswgRmsPower, + WavAudioFormat::aswgLoudness, + WavAudioFormat::aswgLoudnessRange, + WavAudioFormat::aswgMaxPeak, + WavAudioFormat::aswgSpecDensity, + WavAudioFormat::aswgZeroCrossRate, + WavAudioFormat::aswgPapr, + WavAudioFormat::aswgText, + WavAudioFormat::aswgEfforts, + WavAudioFormat::aswgEffortType, + WavAudioFormat::aswgProjection, + WavAudioFormat::aswgLanguage, + WavAudioFormat::aswgTimingRestriction, + WavAudioFormat::aswgCharacterName, + WavAudioFormat::aswgCharacterGender, + WavAudioFormat::aswgCharacterAge, + WavAudioFormat::aswgCharacterRole, + WavAudioFormat::aswgActorName, + WavAudioFormat::aswgActorGender, + WavAudioFormat::aswgDirector, + WavAudioFormat::aswgDirection, + WavAudioFormat::aswgFxUsed, + WavAudioFormat::aswgUsageRights, + WavAudioFormat::aswgIsUnion, + WavAudioFormat::aswgAccent, + WavAudioFormat::aswgEmotion, + WavAudioFormat::aswgComposor, + WavAudioFormat::aswgArtist, + WavAudioFormat::aswgSongTitle, + WavAudioFormat::aswgGenre, + WavAudioFormat::aswgSubGenre, + WavAudioFormat::aswgProducer, + WavAudioFormat::aswgMusicSup, + WavAudioFormat::aswgInstrument, + WavAudioFormat::aswgMusicPublisher, + WavAudioFormat::aswgRightsOwner, + WavAudioFormat::aswgIsSource, + WavAudioFormat::aswgIsLoop, + WavAudioFormat::aswgIntensity, + WavAudioFormat::aswgIsFinal, + WavAudioFormat::aswgOrderRef, + WavAudioFormat::aswgIsOst, + WavAudioFormat::aswgIsCinematic, + WavAudioFormat::aswgIsLicensed, + WavAudioFormat::aswgIsDiegetic, + WavAudioFormat::aswgMusicVersion, + WavAudioFormat::aswgIsrcId, + WavAudioFormat::aswgTempo, + WavAudioFormat::aswgTimeSig, + WavAudioFormat::aswgInKey, + WavAudioFormat::aswgBillingCode + }; + + static void addToMetadata (StringMap& destValues, const String& source) + { + if (auto xml = parseXML (source)) + { + if (xml->hasTagName ("BWFXML")) + { + if (const auto* entry = xml->getChildByName (WavAudioFormat::aswgVersion)) + destValues[WavAudioFormat::aswgVersion] = entry->getAllSubText(); + + if (const auto* aswgElement = xml->getChildByName ("ASWG")) + { + for (const auto* entry : aswgElement->getChildIterator()) + { + const auto& tag = entry->getTagName(); + + if (aswgMetadataKeys.find (tag) != aswgMetadataKeys.end()) + destValues[tag] = entry->getAllSubText(); + } + } + } + } + } + + static MemoryBlock createFrom (const StringMap& values) + { + auto createTextElement = [] (const StringRef& key, const StringRef& value) + { + auto* elem = new XmlElement (key); + elem->addTextElement (value); + return elem; + }; + + std::unique_ptr aswgElement; + + for (const auto& pair : values) + { + if (aswgMetadataKeys.find (pair.first) != aswgMetadataKeys.end()) + { + if (aswgElement == nullptr) + aswgElement = std::make_unique ("ASWG"); + + aswgElement->addChildElement (createTextElement (pair.first, pair.second)); + } + } + + MemoryOutputStream outputStream; + + if (aswgElement != nullptr) + { + XmlElement xml ("BWFXML"); + auto aswgVersion = getValueWithDefault (values, WavAudioFormat::aswgVersion, "3.01"); + xml.addChildElement (createTextElement (WavAudioFormat::aswgVersion, aswgVersion)); + xml.addChildElement (aswgElement.release()); + xml.writeTo (outputStream); + outputStream.writeRepeatedByte (0, outputStream.getDataSize()); + } + + return outputStream.getMemoryBlock(); + } + } + //============================================================================== namespace AXMLChunk { @@ -1136,6 +1372,12 @@ public: input->readIntoMemoryBlock (axml, (ssize_t) length); AXMLChunk::addToMetadata (dict, axml.toString()); } + else if (chunkType == chunkName ("iXML")) + { + MemoryBlock ixml; + input->readIntoMemoryBlock (ixml, (ssize_t) length); + IXMLChunk::addToMetadata (dict, ixml.toString()); + } else if (chunkType == chunkName ("LIST")) { auto subChunkType = input->readInt(); @@ -1350,6 +1592,7 @@ public: const auto map = toMap (metadataValues); bwavChunk = BWAVChunk::createFrom (map); + ixmlChunk = IXMLChunk::createFrom (map); axmlChunk = AXMLChunk::createFrom (map); smplChunk = SMPLChunk::createFrom (map); instChunk = InstChunk::createFrom (map); @@ -1420,7 +1663,7 @@ public: } private: - MemoryBlock tempBlock, bwavChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk, listInfoChunk, acidChunk, trckChunk; + MemoryBlock tempBlock, bwavChunk, ixmlChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk, listInfoChunk, acidChunk, trckChunk; uint64 lengthInSamples = 0, bytesWritten = 0; int64 headerPosition = 0; bool writeFailed = false; @@ -1450,6 +1693,7 @@ private: int64 riffChunkSize = (int64) (4 /* 'RIFF' */ + 8 + 40 /* WAVEFORMATEX */ + 8 + audioDataSize + (audioDataSize & 1) + chunkSize (bwavChunk) + + chunkSize (ixmlChunk) + chunkSize (axmlChunk) + chunkSize (smplChunk) + chunkSize (instChunk) @@ -1532,6 +1776,7 @@ private: } writeChunk (bwavChunk, chunkName ("bext")); + writeChunk (ixmlChunk, chunkName ("iXML")); writeChunk (axmlChunk, chunkName ("axml")); writeChunk (smplChunk, chunkName ("smpl")); writeChunk (instChunk, chunkName ("inst"), 7); @@ -1951,6 +2196,61 @@ struct WaveAudioFormatTests : public UnitTest expect (a[WavAudioFormat::riffInfoSource] == "source"); expect (a[WavAudioFormat::internationalStandardRecordingCode] == "UUVVVXXYYYYY"); } + + { + beginTest ("Files containing ASWG metadata read and write correctly"); + MemoryBlock block; + StringPairArray meta; + + for (const auto& key : WavFileHelpers::IXMLChunk::aswgMetadataKeys) + meta.set (key, "Test123&<>"); + + { + auto writer = rawToUniquePtr (WavAudioFormat().createWriterFor (new MemoryOutputStream (block, false), 48000, 1, 32, meta, 0)); + expect (writer != nullptr); + } + + expect ([&] + { + auto input = std::make_unique (block, false); + + while (! input->isExhausted()) + { + char chunkType[4] {}; + auto pos = input->getPosition(); + + input->read (chunkType, 4); + + if (memcmp (chunkType, "iXML", 4) == 0) + { + auto length = (uint32) input->readInt(); + + MemoryBlock xmlBlock; + input->readIntoMemoryBlock (xmlBlock, (ssize_t) length); + + return parseXML (xmlBlock.toString()) != nullptr; + } + + input->setPosition (pos + 1); + } + + return false; + }()); + + { + auto reader = rawToUniquePtr (WavAudioFormat().createReaderFor (new MemoryInputStream (block, false), true)); + expect (reader != nullptr); + + for (const auto& key : meta.getAllKeys()) + { + const auto oldValue = meta.getValue (key, "!"); + const auto newValue = reader->metadataValues.getValue (key, ""); + expectEquals (oldValue, newValue); + } + + expect (reader->metadataValues.getValue (WavAudioFormat::aswgVersion, "") == "3.01"); + } + } } private: diff --git a/modules/juce_audio_formats/codecs/juce_WavAudioFormat.h b/modules/juce_audio_formats/codecs/juce_WavAudioFormat.h index b021949436..ae09c8d70a 100644 --- a/modules/juce_audio_formats/codecs/juce_WavAudioFormat.h +++ b/modules/juce_audio_formats/codecs/juce_WavAudioFormat.h @@ -168,6 +168,94 @@ public: static const char* const riffInfoWrittenBy; /**< Metadata property name used in INFO chunks. */ static const char* const riffInfoYear; /**< Metadata property name used in INFO chunks. */ + //============================================================================== + // ASWG chunk properties: + + static const char* const aswgContentType; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgProject; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgOriginator; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgOriginatorStudio; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgNotes; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgSession; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgState; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgEditor; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgMixer; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgFxChainName; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgChannelConfig; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgAmbisonicFormat; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgAmbisonicChnOrder; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgAmbisonicNorm; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgMicType; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgMicConfig; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgMicDistance; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgRecordingLoc; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgIsDesigned; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgRecEngineer; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgRecStudio; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgImpulseLocation; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgCategory; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgSubCategory; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgCatId; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgUserCategory; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgUserData; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgVendorCategory; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgFxName; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgLibrary; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgCreatorId; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgSourceId; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgRmsPower; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgLoudness; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgLoudnessRange; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgMaxPeak; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgSpecDensity; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgZeroCrossRate; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgPapr; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgText; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgEfforts; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgEffortType; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgProjection; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgLanguage; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgTimingRestriction; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgCharacterName; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgCharacterGender; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgCharacterAge; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgCharacterRole; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgActorName; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgActorGender; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgDirector; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgDirection; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgFxUsed; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgUsageRights; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgIsUnion; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgAccent; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgEmotion; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgComposor; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgArtist; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgSongTitle; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgGenre; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgSubGenre; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgProducer; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgMusicSup; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgInstrument; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgMusicPublisher; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgRightsOwner; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgIsSource; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgIsLoop; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgIntensity; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgIsFinal; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgOrderRef; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgIsOst; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgIsCinematic; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgIsLicensed; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgIsDiegetic; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgMusicVersion; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgIsrcId; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgTempo; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgTimeSig; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgInKey; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgBillingCode; /**< Metadata property name used in ASWG/iXML chunks. */ + static const char* const aswgVersion; /**< Metadata property name used in ASWG/iXML chunks. */ + //============================================================================== /** Metadata property name used when reading an ISRC code from an AXML chunk. */ [[deprecated ("This string is identical to riffInfoSource, making it impossible to differentiate between the two")]]