diff --git a/source/modules/water/audiocodecs/WavAudioFormat.cpp b/source/modules/water/audiocodecs/WavAudioFormat.cpp deleted file mode 100644 index 26305a609..000000000 --- a/source/modules/water/audiocodecs/WavAudioFormat.cpp +++ /dev/null @@ -1,976 +0,0 @@ -/* - ============================================================================== - - This file is part of the Water library. - Copyright (c) 2015 ROLI Ltd. - Copyright (C) 2018 Filipe Coelho - - Permission is granted to use this software under the terms of either: - a) the GPL v2 (or any later version) - b) the Affero GPL v3 - - Details of these licenses can be found at: www.gnu.org/licenses - - Water is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ============================================================================== -*/ - -#include "WavAudioFormat.h" - -#include "../audioformat/AudioFormatReader.h" -#include "../memory/ByteOrder.h" -#include "../memory/MemoryBlock.h" -#include "../streams/InputStream.h" -#include "../streams/MemoryOutputStream.h" -#include "../xml/XmlDocument.h" -#include "../xml/XmlElement.h" - -namespace water { - -static const char* const wavFormatName = "WAV file"; - -//============================================================================== -const char* const WavAudioFormat::bwavDescription = "bwav description"; -const char* const WavAudioFormat::bwavOriginator = "bwav originator"; -const char* const WavAudioFormat::bwavOriginatorRef = "bwav originator ref"; -const char* const WavAudioFormat::bwavOriginationDate = "bwav origination date"; -const char* const WavAudioFormat::bwavOriginationTime = "bwav origination time"; -const char* const WavAudioFormat::bwavTimeReference = "bwav time reference"; -const char* const WavAudioFormat::bwavCodingHistory = "bwav coding history"; - -#if 0 -StringPairArray WavAudioFormat::createBWAVMetadata (const String& description, - const String& originator, - const String& originatorRef, - Time date, - const int64 timeReferenceSamples, - const String& codingHistory) -{ - StringPairArray m; - - m.set (bwavDescription, description); - m.set (bwavOriginator, originator); - m.set (bwavOriginatorRef, originatorRef); - m.set (bwavOriginationDate, date.formatted ("%Y-%m-%d")); - m.set (bwavOriginationTime, date.formatted ("%H:%M:%S")); - m.set (bwavTimeReference, String (timeReferenceSamples)); - m.set (bwavCodingHistory, codingHistory); - - return m; -} -#endif - -const char* const WavAudioFormat::acidOneShot = "acid one shot"; -const char* const WavAudioFormat::acidRootSet = "acid root set"; -const char* const WavAudioFormat::acidStretch = "acid stretch"; -const char* const WavAudioFormat::acidDiskBased = "acid disk based"; -const char* const WavAudioFormat::acidizerFlag = "acidizer flag"; -const char* const WavAudioFormat::acidRootNote = "acid root note"; -const char* const WavAudioFormat::acidBeats = "acid beats"; -const char* const WavAudioFormat::acidDenominator = "acid denominator"; -const char* const WavAudioFormat::acidNumerator = "acid numerator"; -const char* const WavAudioFormat::acidTempo = "acid tempo"; - -const char* const WavAudioFormat::riffInfoArchivalLocation = "IARL"; -const char* const WavAudioFormat::riffInfoArtist = "IART"; -const char* const WavAudioFormat::riffInfoBaseURL = "IBSU"; -const char* const WavAudioFormat::riffInfoCinematographer = "ICNM"; -const char* const WavAudioFormat::riffInfoComment = "CMNT"; -const char* const WavAudioFormat::riffInfoComments = "COMM"; -const char* const WavAudioFormat::riffInfoCommissioned = "ICMS"; -const char* const WavAudioFormat::riffInfoCopyright = "ICOP"; -const char* const WavAudioFormat::riffInfoCostumeDesigner = "ICDS"; -const char* const WavAudioFormat::riffInfoCountry = "ICNT"; -const char* const WavAudioFormat::riffInfoCropped = "ICRP"; -const char* const WavAudioFormat::riffInfoDateCreated = "ICRD"; -const char* const WavAudioFormat::riffInfoDateTimeOriginal = "IDIT"; -const char* const WavAudioFormat::riffInfoDefaultAudioStream = "ICAS"; -const char* const WavAudioFormat::riffInfoDimension = "IDIM"; -const char* const WavAudioFormat::riffInfoDirectory = "DIRC"; -const char* const WavAudioFormat::riffInfoDistributedBy = "IDST"; -const char* const WavAudioFormat::riffInfoDotsPerInch = "IDPI"; -const char* const WavAudioFormat::riffInfoEditedBy = "IEDT"; -const char* const WavAudioFormat::riffInfoEighthLanguage = "IAS8"; -const char* const WavAudioFormat::riffInfoEncodedBy = "CODE"; -const char* const WavAudioFormat::riffInfoEndTimecode = "TCDO"; -const char* const WavAudioFormat::riffInfoEngineer = "IENG"; -const char* const WavAudioFormat::riffInfoFifthLanguage = "IAS5"; -const char* const WavAudioFormat::riffInfoFirstLanguage = "IAS1"; -const char* const WavAudioFormat::riffInfoFourthLanguage = "IAS4"; -const char* const WavAudioFormat::riffInfoGenre = "GENR"; -const char* const WavAudioFormat::riffInfoKeywords = "IKEY"; -const char* const WavAudioFormat::riffInfoLanguage = "LANG"; -const char* const WavAudioFormat::riffInfoLength = "TLEN"; -const char* const WavAudioFormat::riffInfoLightness = "ILGT"; -const char* const WavAudioFormat::riffInfoLocation = "LOCA"; -const char* const WavAudioFormat::riffInfoLogoIconURL = "ILIU"; -const char* const WavAudioFormat::riffInfoLogoURL = "ILGU"; -const char* const WavAudioFormat::riffInfoMedium = "IMED"; -const char* const WavAudioFormat::riffInfoMoreInfoBannerImage = "IMBI"; -const char* const WavAudioFormat::riffInfoMoreInfoBannerURL = "IMBU"; -const char* const WavAudioFormat::riffInfoMoreInfoText = "IMIT"; -const char* const WavAudioFormat::riffInfoMoreInfoURL = "IMIU"; -const char* const WavAudioFormat::riffInfoMusicBy = "IMUS"; -const char* const WavAudioFormat::riffInfoNinthLanguage = "IAS9"; -const char* const WavAudioFormat::riffInfoNumberOfParts = "PRT2"; -const char* const WavAudioFormat::riffInfoOrganisation = "TORG"; -const char* const WavAudioFormat::riffInfoPart = "PRT1"; -const char* const WavAudioFormat::riffInfoProducedBy = "IPRO"; -const char* const WavAudioFormat::riffInfoProductionDesigner = "IPDS"; -const char* const WavAudioFormat::riffInfoProductionStudio = "ISDT"; -const char* const WavAudioFormat::riffInfoRate = "RATE"; -const char* const WavAudioFormat::riffInfoRated = "AGES"; -const char* const WavAudioFormat::riffInfoRating = "IRTD"; -const char* const WavAudioFormat::riffInfoRippedBy = "IRIP"; -const char* const WavAudioFormat::riffInfoSecondaryGenre = "ISGN"; -const char* const WavAudioFormat::riffInfoSecondLanguage = "IAS2"; -const char* const WavAudioFormat::riffInfoSeventhLanguage = "IAS7"; -const char* const WavAudioFormat::riffInfoSharpness = "ISHP"; -const char* const WavAudioFormat::riffInfoSixthLanguage = "IAS6"; -const char* const WavAudioFormat::riffInfoSoftware = "ISFT"; -const char* const WavAudioFormat::riffInfoSoundSchemeTitle = "DISP"; -const char* const WavAudioFormat::riffInfoSource = "ISRC"; -const char* const WavAudioFormat::riffInfoSourceFrom = "ISRF"; -const char* const WavAudioFormat::riffInfoStarring_ISTR = "ISTR"; -const char* const WavAudioFormat::riffInfoStarring_STAR = "STAR"; -const char* const WavAudioFormat::riffInfoStartTimecode = "TCOD"; -const char* const WavAudioFormat::riffInfoStatistics = "STAT"; -const char* const WavAudioFormat::riffInfoSubject = "ISBJ"; -const char* const WavAudioFormat::riffInfoTapeName = "TAPE"; -const char* const WavAudioFormat::riffInfoTechnician = "ITCH"; -const char* const WavAudioFormat::riffInfoThirdLanguage = "IAS3"; -const char* const WavAudioFormat::riffInfoTimeCode = "ISMP"; -const char* const WavAudioFormat::riffInfoTitle = "INAM"; -const char* const WavAudioFormat::riffInfoTrackNumber = "TRCK"; -const char* const WavAudioFormat::riffInfoURL = "TURL"; -const char* const WavAudioFormat::riffInfoVegasVersionMajor = "VMAJ"; -const char* const WavAudioFormat::riffInfoVegasVersionMinor = "VMIN"; -const char* const WavAudioFormat::riffInfoVersion = "TVER"; -const char* const WavAudioFormat::riffInfoWatermarkURL = "IWMU"; -const char* const WavAudioFormat::riffInfoWrittenBy = "IWRI"; -const char* const WavAudioFormat::riffInfoYear = "YEAR"; - -const char* const WavAudioFormat::ISRC = "ISRC"; -const char* const WavAudioFormat::tracktionLoopInfo = "tracktion loop info"; - -//============================================================================== -namespace WavFileHelpers -{ - inline int chunkName (const char* const name) noexcept { return (int) ByteOrder::littleEndianInt (name); } - inline size_t roundUpSize (size_t sz) noexcept { return (sz + 3) & ~3u; } - - #if _MSVC_VER - #pragma pack (push, 1) - #endif - - struct BWAVChunk - { - char description [256]; - char originator [32]; - char originatorRef [32]; - char originationDate [10]; - char originationTime [8]; - uint32 timeRefLow; - uint32 timeRefHigh; - uint16 version; - uint8 umid[64]; - uint8 reserved[190]; - char codingHistory[1]; - - void copyTo (StringPairArray& values, const int totalSize) const - { - values.set (WavAudioFormat::bwavDescription, String::fromUTF8 (description, sizeof (description))); - values.set (WavAudioFormat::bwavOriginator, String::fromUTF8 (originator, sizeof (originator))); - values.set (WavAudioFormat::bwavOriginatorRef, String::fromUTF8 (originatorRef, sizeof (originatorRef))); - values.set (WavAudioFormat::bwavOriginationDate, String::fromUTF8 (originationDate, sizeof (originationDate))); - values.set (WavAudioFormat::bwavOriginationTime, String::fromUTF8 (originationTime, sizeof (originationTime))); - - const uint32 timeLow = ByteOrder::swapIfBigEndian (timeRefLow); - const uint32 timeHigh = ByteOrder::swapIfBigEndian (timeRefHigh); - const int64 time = (((int64) timeHigh) << 32) + timeLow; - - values.set (WavAudioFormat::bwavTimeReference, String (time)); - values.set (WavAudioFormat::bwavCodingHistory, - String::fromUTF8 (codingHistory, totalSize - (int) offsetof (BWAVChunk, codingHistory))); - } - - } WATER_PACKED; - - //============================================================================== - struct SMPLChunk - { - struct SampleLoop - { - uint32 identifier; - uint32 type; // these are different in AIFF and WAV - uint32 start; - uint32 end; - uint32 fraction; - uint32 playCount; - } WATER_PACKED; - - uint32 manufacturer; - uint32 product; - uint32 samplePeriod; - uint32 midiUnityNote; - uint32 midiPitchFraction; - uint32 smpteFormat; - uint32 smpteOffset; - uint32 numSampleLoops; - uint32 samplerData; - SampleLoop loops[1]; - - template - static void setValue (StringPairArray& values, NameType name, uint32 val) - { - values.set (name, String (ByteOrder::swapIfBigEndian (val))); - } - - static void setValue (StringPairArray& values, int prefix, const char* name, uint32 val) - { - setValue (values, "Loop" + String (prefix) + name, val); - } - - void copyTo (StringPairArray& values, const int totalSize) const - { - setValue (values, "Manufacturer", manufacturer); - setValue (values, "Product", product); - setValue (values, "SamplePeriod", samplePeriod); - setValue (values, "MidiUnityNote", midiUnityNote); - setValue (values, "MidiPitchFraction", midiPitchFraction); - setValue (values, "SmpteFormat", smpteFormat); - setValue (values, "SmpteOffset", smpteOffset); - setValue (values, "NumSampleLoops", numSampleLoops); - setValue (values, "SamplerData", samplerData); - - for (int i = 0; i < (int) numSampleLoops; ++i) - { - if ((uint8*) (loops + (i + 1)) > ((uint8*) this) + totalSize) - break; - - setValue (values, i, "Identifier", loops[i].identifier); - setValue (values, i, "Type", loops[i].type); - setValue (values, i, "Start", loops[i].start); - setValue (values, i, "End", loops[i].end); - setValue (values, i, "Fraction", loops[i].fraction); - setValue (values, i, "PlayCount", loops[i].playCount); - } - } - - template - static uint32 getValue (const StringPairArray& values, NameType name, const char* def) - { - return ByteOrder::swapIfBigEndian ((uint32) values.getValue (name, def).getIntValue()); - } - - static uint32 getValue (const StringPairArray& values, int prefix, const char* name, const char* def) - { - return getValue (values, "Loop" + String (prefix) + name, def); - } - - } WATER_PACKED; - - //============================================================================== - struct InstChunk - { - int8 baseNote; - int8 detune; - int8 gain; - int8 lowNote; - int8 highNote; - int8 lowVelocity; - int8 highVelocity; - - static void setValue (StringPairArray& values, const char* name, int val) - { - values.set (name, String (val)); - } - - void copyTo (StringPairArray& values) const - { - setValue (values, "MidiUnityNote", baseNote); - setValue (values, "Detune", detune); - setValue (values, "Gain", gain); - setValue (values, "LowNote", lowNote); - setValue (values, "HighNote", highNote); - setValue (values, "LowVelocity", lowVelocity); - setValue (values, "HighVelocity", highVelocity); - } - - static int8 getValue (const StringPairArray& values, const char* name, const char* def) - { - return (int8) values.getValue (name, def).getIntValue(); - } - - } WATER_PACKED; - - //============================================================================== - struct CueChunk - { - struct Cue - { - uint32 identifier; - uint32 order; - uint32 chunkID; - uint32 chunkStart; - uint32 blockStart; - uint32 offset; - } WATER_PACKED; - - uint32 numCues; - Cue cues[1]; - - static void setValue (StringPairArray& values, int prefix, const char* name, uint32 val) - { - values.set ("Cue" + String (prefix) + name, String (ByteOrder::swapIfBigEndian (val))); - } - - void copyTo (StringPairArray& values, const int totalSize) const - { - values.set ("NumCuePoints", String (ByteOrder::swapIfBigEndian (numCues))); - - for (int i = 0; i < (int) numCues; ++i) - { - if ((uint8*) (cues + (i + 1)) > ((uint8*) this) + totalSize) - break; - - setValue (values, i, "Identifier", cues[i].identifier); - setValue (values, i, "Order", cues[i].order); - setValue (values, i, "ChunkID", cues[i].chunkID); - setValue (values, i, "ChunkStart", cues[i].chunkStart); - setValue (values, i, "BlockStart", cues[i].blockStart); - setValue (values, i, "Offset", cues[i].offset); - } - } - - } WATER_PACKED; - - //============================================================================== - /** Reads a RIFF List Info chunk from a stream positioned just after the size byte. */ - namespace ListInfoChunk - { - static const char* const types[] = - { - WavAudioFormat::riffInfoArchivalLocation, - WavAudioFormat::riffInfoArtist, - WavAudioFormat::riffInfoBaseURL, - WavAudioFormat::riffInfoCinematographer, - WavAudioFormat::riffInfoComment, - WavAudioFormat::riffInfoComments, - WavAudioFormat::riffInfoCommissioned, - WavAudioFormat::riffInfoCopyright, - WavAudioFormat::riffInfoCostumeDesigner, - WavAudioFormat::riffInfoCountry, - WavAudioFormat::riffInfoCropped, - WavAudioFormat::riffInfoDateCreated, - WavAudioFormat::riffInfoDateTimeOriginal, - WavAudioFormat::riffInfoDefaultAudioStream, - WavAudioFormat::riffInfoDimension, - WavAudioFormat::riffInfoDirectory, - WavAudioFormat::riffInfoDistributedBy, - WavAudioFormat::riffInfoDotsPerInch, - WavAudioFormat::riffInfoEditedBy, - WavAudioFormat::riffInfoEighthLanguage, - WavAudioFormat::riffInfoEncodedBy, - WavAudioFormat::riffInfoEndTimecode, - WavAudioFormat::riffInfoEngineer, - WavAudioFormat::riffInfoFifthLanguage, - WavAudioFormat::riffInfoFirstLanguage, - WavAudioFormat::riffInfoFourthLanguage, - WavAudioFormat::riffInfoGenre, - WavAudioFormat::riffInfoKeywords, - WavAudioFormat::riffInfoLanguage, - WavAudioFormat::riffInfoLength, - WavAudioFormat::riffInfoLightness, - WavAudioFormat::riffInfoLocation, - WavAudioFormat::riffInfoLogoIconURL, - WavAudioFormat::riffInfoLogoURL, - WavAudioFormat::riffInfoMedium, - WavAudioFormat::riffInfoMoreInfoBannerImage, - WavAudioFormat::riffInfoMoreInfoBannerURL, - WavAudioFormat::riffInfoMoreInfoText, - WavAudioFormat::riffInfoMoreInfoURL, - WavAudioFormat::riffInfoMusicBy, - WavAudioFormat::riffInfoNinthLanguage, - WavAudioFormat::riffInfoNumberOfParts, - WavAudioFormat::riffInfoOrganisation, - WavAudioFormat::riffInfoPart, - WavAudioFormat::riffInfoProducedBy, - WavAudioFormat::riffInfoProductionDesigner, - WavAudioFormat::riffInfoProductionStudio, - WavAudioFormat::riffInfoRate, - WavAudioFormat::riffInfoRated, - WavAudioFormat::riffInfoRating, - WavAudioFormat::riffInfoRippedBy, - WavAudioFormat::riffInfoSecondaryGenre, - WavAudioFormat::riffInfoSecondLanguage, - WavAudioFormat::riffInfoSeventhLanguage, - WavAudioFormat::riffInfoSharpness, - WavAudioFormat::riffInfoSixthLanguage, - WavAudioFormat::riffInfoSoftware, - WavAudioFormat::riffInfoSoundSchemeTitle, - WavAudioFormat::riffInfoSource, - WavAudioFormat::riffInfoSourceFrom, - WavAudioFormat::riffInfoStarring_ISTR, - WavAudioFormat::riffInfoStarring_STAR, - WavAudioFormat::riffInfoStartTimecode, - WavAudioFormat::riffInfoStatistics, - WavAudioFormat::riffInfoSubject, - WavAudioFormat::riffInfoTapeName, - WavAudioFormat::riffInfoTechnician, - WavAudioFormat::riffInfoThirdLanguage, - WavAudioFormat::riffInfoTimeCode, - WavAudioFormat::riffInfoTitle, - WavAudioFormat::riffInfoTrackNumber, - WavAudioFormat::riffInfoURL, - WavAudioFormat::riffInfoVegasVersionMajor, - WavAudioFormat::riffInfoVegasVersionMinor, - WavAudioFormat::riffInfoVersion, - WavAudioFormat::riffInfoWatermarkURL, - WavAudioFormat::riffInfoWrittenBy, - WavAudioFormat::riffInfoYear - }; - - static bool isMatchingTypeIgnoringCase (const int value, const char* const name) noexcept - { - for (int i = 0; i < 4; ++i) - if ((uint32) name[i] != CharacterFunctions::toUpperCase ((uint32) ((value >> (i * 8)) & 0xff))) - return false; - - return true; - } - - static void addToMetadata (StringPairArray& values, InputStream& input, int64 chunkEnd) - { - while (input.getPosition() < chunkEnd) - { - const int infoType = input.readInt(); - - int64 infoLength = chunkEnd - input.getPosition(); - - if (infoLength > 0) - { - infoLength = jmin (infoLength, (int64) input.readInt()); - - if (infoLength <= 0) - return; - - for (int i = 0; i < numElementsInArray (types); ++i) - { - if (isMatchingTypeIgnoringCase (infoType, types[i])) - { - MemoryBlock mb; - input.readIntoMemoryBlock (mb, (ssize_t) infoLength); - values.set (types[i], String::createStringFromData ((const char*) mb.getData(), - (int) mb.getSize())); - break; - } - } - } - } - } - } - - //============================================================================== - struct AcidChunk - { - /** Reads an acid RIFF chunk from a stream positioned just after the size byte. */ - AcidChunk (InputStream& input, size_t length) - { - zerostruct (*this); - input.read (this, (int) jmin (sizeof (*this), length)); - } - - AcidChunk (const StringPairArray& values) - { - zerostruct (*this); - - flags = getFlagIfPresent (values, WavAudioFormat::acidOneShot, 0x01) - | getFlagIfPresent (values, WavAudioFormat::acidRootSet, 0x02) - | getFlagIfPresent (values, WavAudioFormat::acidStretch, 0x04) - | getFlagIfPresent (values, WavAudioFormat::acidDiskBased, 0x08) - | getFlagIfPresent (values, WavAudioFormat::acidizerFlag, 0x10); - - if (values[WavAudioFormat::acidRootSet].getIntValue() != 0) - rootNote = ByteOrder::swapIfBigEndian ((uint16) values[WavAudioFormat::acidRootNote].getIntValue()); - - numBeats = ByteOrder::swapIfBigEndian ((uint32) values[WavAudioFormat::acidBeats].getIntValue()); - meterDenominator = ByteOrder::swapIfBigEndian ((uint16) values[WavAudioFormat::acidDenominator].getIntValue()); - meterNumerator = ByteOrder::swapIfBigEndian ((uint16) values[WavAudioFormat::acidNumerator].getIntValue()); - - if (values.containsKey (WavAudioFormat::acidTempo)) - tempo = swapFloatByteOrder (values[WavAudioFormat::acidTempo].getFloatValue()); - } - - MemoryBlock toMemoryBlock() const - { - return (flags != 0 || rootNote != 0 || numBeats != 0 || meterDenominator != 0 || meterNumerator != 0) - ? MemoryBlock (this, sizeof (*this)) : MemoryBlock(); - } - - void addToMetadata (StringPairArray& values) const - { - setBoolFlag (values, WavAudioFormat::acidOneShot, 0x01); - setBoolFlag (values, WavAudioFormat::acidRootSet, 0x02); - setBoolFlag (values, WavAudioFormat::acidStretch, 0x04); - setBoolFlag (values, WavAudioFormat::acidDiskBased, 0x08); - setBoolFlag (values, WavAudioFormat::acidizerFlag, 0x10); - - if (flags & 0x02) // root note set - values.set (WavAudioFormat::acidRootNote, String (ByteOrder::swapIfBigEndian (rootNote))); - - values.set (WavAudioFormat::acidBeats, String (ByteOrder::swapIfBigEndian (numBeats))); - values.set (WavAudioFormat::acidDenominator, String (ByteOrder::swapIfBigEndian (meterDenominator))); - values.set (WavAudioFormat::acidNumerator, String (ByteOrder::swapIfBigEndian (meterNumerator))); - values.set (WavAudioFormat::acidTempo, String (swapFloatByteOrder (tempo))); - } - - void setBoolFlag (StringPairArray& values, const char* name, uint32 mask) const - { - values.set (name, (flags & ByteOrder::swapIfBigEndian (mask)) ? "1" : "0"); - } - - static uint32 getFlagIfPresent (const StringPairArray& values, const char* name, uint32 flag) - { - return values[name].getIntValue() != 0 ? ByteOrder::swapIfBigEndian (flag) : 0; - } - - static float swapFloatByteOrder (const float x) noexcept - { - #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ - union { uint32 asInt; float asFloat; } n; - n.asFloat = x; - n.asInt = ByteOrder::swap (n.asInt); - return n.asFloat; - #else - return x; - #endif - } - - uint32 flags; - uint16 rootNote; - uint16 reserved1; - float reserved2; - uint32 numBeats; - uint16 meterDenominator; - uint16 meterNumerator; - float tempo; - - } WATER_PACKED; - - //============================================================================== - namespace AXMLChunk - { - static void addToMetadata (StringPairArray& destValues, const String& source) - { - ScopedPointer xml (XmlDocument::parse (source)); - - if (xml != nullptr && xml->hasTagName ("ebucore:ebuCoreMain")) - { - if (XmlElement* xml2 = xml->getChildByName ("ebucore:coreMetadata")) - { - if (XmlElement* xml3 = xml2->getChildByName ("ebucore:identifier")) - { - if (XmlElement* xml4 = xml3->getChildByName ("dc:identifier")) - { - const String ISRCCode (xml4->getAllSubText().fromFirstOccurrenceOf ("ISRC:", false, true)); - - if (ISRCCode.isNotEmpty()) - destValues.set (WavAudioFormat::ISRC, ISRCCode); - } - } - } - } - } - }; - - //============================================================================== - struct ExtensibleWavSubFormat - { - uint32 data1; - uint16 data2; - uint16 data3; - uint8 data4[8]; - - bool operator== (const ExtensibleWavSubFormat& other) const noexcept { return memcmp (this, &other, sizeof (*this)) == 0; } - bool operator!= (const ExtensibleWavSubFormat& other) const noexcept { return ! operator== (other); } - - } WATER_PACKED; - - static const ExtensibleWavSubFormat pcmFormat = { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; - static const ExtensibleWavSubFormat IEEEFloatFormat = { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; - static const ExtensibleWavSubFormat ambisonicFormat = { 0x00000001, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 } }; - - struct DataSize64Chunk // chunk ID = 'ds64' if data size > 0xffffffff, 'JUNK' otherwise - { - uint32 riffSizeLow; // low 4 byte size of RF64 block - uint32 riffSizeHigh; // high 4 byte size of RF64 block - uint32 dataSizeLow; // low 4 byte size of data chunk - uint32 dataSizeHigh; // high 4 byte size of data chunk - uint32 sampleCountLow; // low 4 byte sample count of fact chunk - uint32 sampleCountHigh; // high 4 byte sample count of fact chunk - uint32 tableLength; // number of valid entries in array 'table' - } WATER_PACKED; - - #if _MSVC_VER - #pragma pack (pop) - #endif -} - -//============================================================================== -class WavAudioFormatReader : public AudioFormatReader -{ -public: - WavAudioFormatReader (InputStream* const in) - : AudioFormatReader (in, wavFormatName), - bwavChunkStart (0), - bwavSize (0), - dataLength (0), - isRF64 (false) - { - using namespace WavFileHelpers; - uint64 len = 0; - uint64 end = 0; - int cueNoteIndex = 0; - int cueLabelIndex = 0; - int cueRegionIndex = 0; - - const int firstChunkType = input->readInt(); - - if (firstChunkType == chunkName ("RF64")) - { - input->skipNextBytes (4); // size is -1 for RF64 - isRF64 = true; - } - else if (firstChunkType == chunkName ("RIFF")) - { - len = (uint64) (uint32) input->readInt(); - end = len + (uint64) input->getPosition(); - } - else - { - return; - } - - const int64 startOfRIFFChunk = input->getPosition(); - - if (input->readInt() == chunkName ("WAVE")) - { - if (isRF64 && input->readInt() == chunkName ("ds64")) - { - const uint32 length = (uint32) input->readInt(); - - if (length < 28) - return; - - const int64 chunkEnd = input->getPosition() + length + (length & 1); - len = (uint64) input->readInt64(); - end = len + (uint64) startOfRIFFChunk; - dataLength = input->readInt64(); - input->setPosition (chunkEnd); - } - - while ((uint64) input->getPosition() < end && ! input->isExhausted()) - { - const int chunkType = input->readInt(); - uint32 length = (uint32) input->readInt(); - const int64 chunkEnd = input->getPosition() + length + (length & 1); - - if (chunkType == chunkName ("fmt ")) - { - // read the format chunk - const unsigned short format = (unsigned short) input->readShort(); - numChannels = (unsigned int) input->readShort(); - sampleRate = input->readInt(); - const int bytesPerSec = input->readInt(); - input->skipNextBytes (2); - bitsPerSample = (unsigned int) (int) input->readShort(); - - if (bitsPerSample > 64) - { - bytesPerFrame = bytesPerSec / (int) sampleRate; - bitsPerSample = 8 * (unsigned int) bytesPerFrame / numChannels; - } - else - { - bytesPerFrame = numChannels * bitsPerSample / 8; - } - - if (format == 3) - { - usesFloatingPointData = true; - } - else if (format == 0xfffe /*WAVE_FORMAT_EXTENSIBLE*/) - { - if (length < 40) // too short - { - bytesPerFrame = 0; - } - else - { - input->skipNextBytes (4); // skip over size and bitsPerSample - metadataValues.set ("ChannelMask", String (input->readInt())); - - ExtensibleWavSubFormat subFormat; - subFormat.data1 = (uint32) input->readInt(); - subFormat.data2 = (uint16) input->readShort(); - subFormat.data3 = (uint16) input->readShort(); - input->read (subFormat.data4, sizeof (subFormat.data4)); - - if (subFormat == IEEEFloatFormat) - usesFloatingPointData = true; - else if (subFormat != pcmFormat && subFormat != ambisonicFormat) - bytesPerFrame = 0; - } - } - else if (format != 1) - { - bytesPerFrame = 0; - } - } - else if (chunkType == chunkName ("data")) - { - if (! isRF64) // data size is expected to be -1, actual data size is in ds64 chunk - dataLength = length; - - dataChunkStart = input->getPosition(); - lengthInSamples = (bytesPerFrame > 0) ? (dataLength / bytesPerFrame) : 0; - } - else if (chunkType == chunkName ("bext")) - { - bwavChunkStart = input->getPosition(); - bwavSize = length; - - HeapBlock bwav; - bwav.calloc (jmax ((size_t) length + 1, sizeof (BWAVChunk)), 1); - input->read (bwav, (int) length); - bwav->copyTo (metadataValues, (int) length); - } - else if (chunkType == chunkName ("smpl")) - { - HeapBlock smpl; - smpl.calloc (jmax ((size_t) length + 1, sizeof (SMPLChunk)), 1); - input->read (smpl, (int) length); - smpl->copyTo (metadataValues, (int) length); - } - else if (chunkType == chunkName ("inst") || chunkType == chunkName ("INST")) // need to check which... - { - HeapBlock inst; - inst.calloc (jmax ((size_t) length + 1, sizeof (InstChunk)), 1); - input->read (inst, (int) length); - inst->copyTo (metadataValues); - } - else if (chunkType == chunkName ("cue ")) - { - HeapBlock cue; - cue.calloc (jmax ((size_t) length + 1, sizeof (CueChunk)), 1); - input->read (cue, (int) length); - cue->copyTo (metadataValues, (int) length); - } - else if (chunkType == chunkName ("axml")) - { - MemoryBlock axml; - input->readIntoMemoryBlock (axml, (ssize_t) length); - AXMLChunk::addToMetadata (metadataValues, axml.toString()); - } - else if (chunkType == chunkName ("LIST")) - { - const int subChunkType = input->readInt(); - - if (subChunkType == chunkName ("info") || subChunkType == chunkName ("INFO")) - { - ListInfoChunk::addToMetadata (metadataValues, *input, chunkEnd); - } - else if (subChunkType == chunkName ("adtl")) - { - while (input->getPosition() < chunkEnd) - { - const int adtlChunkType = input->readInt(); - const uint32 adtlLength = (uint32) input->readInt(); - const int64 adtlChunkEnd = input->getPosition() + (adtlLength + (adtlLength & 1)); - - if (adtlChunkType == chunkName ("labl") || adtlChunkType == chunkName ("note")) - { - String prefix; - - if (adtlChunkType == chunkName ("labl")) - prefix << "CueLabel" << cueLabelIndex++; - else if (adtlChunkType == chunkName ("note")) - prefix << "CueNote" << cueNoteIndex++; - - const uint32 identifier = (uint32) input->readInt(); - const int stringLength = (int) adtlLength - 4; - - MemoryBlock textBlock; - input->readIntoMemoryBlock (textBlock, stringLength); - - metadataValues.set (prefix + "Identifier", String (identifier)); - metadataValues.set (prefix + "Text", textBlock.toString()); - } - else if (adtlChunkType == chunkName ("ltxt")) - { - const String prefix ("CueRegion" + String (cueRegionIndex++)); - const uint32 identifier = (uint32) input->readInt(); - const uint32 sampleLength = (uint32) input->readInt(); - const uint32 purpose = (uint32) input->readInt(); - const uint16 country = (uint16) input->readInt(); - const uint16 language = (uint16) input->readInt(); - const uint16 dialect = (uint16) input->readInt(); - const uint16 codePage = (uint16) input->readInt(); - const uint32 stringLength = adtlLength - 20; - - MemoryBlock textBlock; - input->readIntoMemoryBlock (textBlock, (int) stringLength); - - metadataValues.set (prefix + "Identifier", String (identifier)); - metadataValues.set (prefix + "SampleLength", String (sampleLength)); - metadataValues.set (prefix + "Purpose", String (purpose)); - metadataValues.set (prefix + "Country", String (country)); - metadataValues.set (prefix + "Language", String (language)); - metadataValues.set (prefix + "Dialect", String (dialect)); - metadataValues.set (prefix + "CodePage", String (codePage)); - metadataValues.set (prefix + "Text", textBlock.toString()); - } - - input->setPosition (adtlChunkEnd); - } - } - } - else if (chunkType == chunkName ("acid")) - { - AcidChunk (*input, length).addToMetadata (metadataValues); - } - else if (chunkType == chunkName ("Trkn")) - { - MemoryBlock tracktion; - input->readIntoMemoryBlock (tracktion, (ssize_t) length); - metadataValues.set (WavAudioFormat::tracktionLoopInfo, tracktion.toString()); - } - else if (chunkEnd <= input->getPosition()) - { - break; - } - - input->setPosition (chunkEnd); - } - } - - if (cueLabelIndex > 0) metadataValues.set ("NumCueLabels", String (cueLabelIndex)); - if (cueNoteIndex > 0) metadataValues.set ("NumCueNotes", String (cueNoteIndex)); - if (cueRegionIndex > 0) metadataValues.set ("NumCueRegions", String (cueRegionIndex)); - if (metadataValues.size() > 0) metadataValues.set ("MetaDataSource", "WAV"); - } - - //============================================================================== - bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, - int64 startSampleInFile, int numSamples) override - { - clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer, - startSampleInFile, numSamples, lengthInSamples); - - if (numSamples <= 0) - return true; - - input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame); - - while (numSamples > 0) - { - const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3) - char tempBuffer [tempBufSize]; - - const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples); - const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame); - - if (bytesRead < numThisTime * bytesPerFrame) - { - jassert (bytesRead >= 0); - zeromem (tempBuffer + bytesRead, (size_t) (numThisTime * bytesPerFrame - bytesRead)); - } - - copySampleData (bitsPerSample, usesFloatingPointData, - destSamples, startOffsetInDestBuffer, numDestChannels, - tempBuffer, (int) numChannels, numThisTime); - - startOffsetInDestBuffer += numThisTime; - numSamples -= numThisTime; - } - - return true; - } - - static void copySampleData (unsigned int bitsPerSample, const bool usesFloatingPointData, - int* const* destSamples, int startOffsetInDestBuffer, int numDestChannels, - const void* sourceData, int numChannels, int numSamples) noexcept - { - switch (bitsPerSample) - { - case 8: - ReadHelper::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numChannels, numSamples); - break; - case 16: - ReadHelper::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numChannels, numSamples); - break; - case 24: - ReadHelper::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numChannels, numSamples); - break; - case 32: - if (usesFloatingPointData) - ReadHelper::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numChannels, numSamples); - else - ReadHelper::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numChannels, numSamples); - break; - default: - jassertfalse; - break; - } - } - - int64 bwavChunkStart, bwavSize; - int64 dataChunkStart, dataLength; - int bytesPerFrame; - bool isRF64; - -private: - CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WavAudioFormatReader) -}; - -//============================================================================== -WavAudioFormat::WavAudioFormat() : AudioFormat (wavFormatName, ".wav .bwf") {} -WavAudioFormat::~WavAudioFormat() {} - -Array WavAudioFormat::getPossibleSampleRates() -{ - const int rates[] = { 8000, 11025, 12000, 16000, 22050, 32000, 44100, - 48000, 88200, 96000, 176400, 192000, 352800, 384000 }; - - return Array (rates, numElementsInArray (rates)); -} - -Array WavAudioFormat::getPossibleBitDepths() -{ - const int depths[] = { 8, 16, 24, 32 }; - - return Array (depths, numElementsInArray (depths)); -} - -bool WavAudioFormat::canDoStereo() { return true; } -bool WavAudioFormat::canDoMono() { return true; } - -AudioFormatReader* WavAudioFormat::createReaderFor (InputStream* sourceStream, - const bool deleteStreamIfOpeningFails) -{ - ScopedPointer r (new WavAudioFormatReader (sourceStream)); - - if (r->sampleRate > 0 && r->numChannels > 0 && r->bytesPerFrame > 0) - return r.release(); - - if (! deleteStreamIfOpeningFails) - r->input = nullptr; - - return nullptr; -} - -} diff --git a/source/modules/water/audiocodecs/WavAudioFormat.h b/source/modules/water/audiocodecs/WavAudioFormat.h deleted file mode 100644 index 5512ffd2a..000000000 --- a/source/modules/water/audiocodecs/WavAudioFormat.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - ============================================================================== - - This file is part of the Water library. - Copyright (c) 2015 ROLI Ltd. - Copyright (C) 2018 Filipe Coelho - - Permission is granted to use this software under the terms of either: - a) the GPL v2 (or any later version) - b) the Affero GPL v3 - - Details of these licenses can be found at: www.gnu.org/licenses - - Water is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ============================================================================== -*/ - -#ifndef WATER_WAV_AUDIOFORMAT_H_INCLUDED -#define WATER_WAV_AUDIOFORMAT_H_INCLUDED - -#include "../audioformat/AudioFormat.h" -#include "../containers/Array.h" - -#include "CarlaJuceUtils.hpp" - -namespace water { - -//============================================================================== -/** - Reads and Writes WAV format audio files. - - @see AudioFormat -*/ -class WavAudioFormat : public AudioFormat -{ -public: - //============================================================================== - /** Creates a format object. */ - WavAudioFormat(); - - /** Destructor. */ - ~WavAudioFormat(); - - //============================================================================== - // BWAV chunk properties: - - static const char* const bwavDescription; /**< Metadata property name used in BWAV chunks. */ - static const char* const bwavOriginator; /**< Metadata property name used in BWAV chunks. */ - static const char* const bwavOriginatorRef; /**< Metadata property name used in BWAV chunks. */ - static const char* const bwavOriginationDate; /**< Metadata property name used in BWAV chunks. The format should be: yyyy-mm-dd */ - static const char* const bwavOriginationTime; /**< Metadata property name used in BWAV chunks. The format should be: format is: hh-mm-ss */ - static const char* const bwavCodingHistory; /**< Metadata property name used in BWAV chunks. */ - - /** Metadata property name used in BWAV chunks. - This is the number of samples from the start of an edit that the - file is supposed to begin at. Seems like an obvious mistake to - only allow a file to occur in an edit once, but that's the way - it is.. - - @see AudioFormatReader::metadataValues, createWriterFor - */ - static const char* const bwavTimeReference; - -#if 0 - /** Utility function to fill out the appropriate metadata for a BWAV file. - - This just makes it easier than using the property names directly, and it - fills out the time and date in the right format. - */ - static StringPairArray createBWAVMetadata (const String& description, - const String& originator, - const String& originatorRef, - Time dateAndTime, - int64 timeReferenceSamples, - const String& codingHistory); -#endif - - //============================================================================== - // 'acid' chunk properties: - - static const char* const acidOneShot; /**< Metadata property name used in acid chunks. */ - static const char* const acidRootSet; /**< Metadata property name used in acid chunks. */ - static const char* const acidStretch; /**< Metadata property name used in acid chunks. */ - static const char* const acidDiskBased; /**< Metadata property name used in acid chunks. */ - static const char* const acidizerFlag; /**< Metadata property name used in acid chunks. */ - static const char* const acidRootNote; /**< Metadata property name used in acid chunks. */ - static const char* const acidBeats; /**< Metadata property name used in acid chunks. */ - static const char* const acidDenominator; /**< Metadata property name used in acid chunks. */ - static const char* const acidNumerator; /**< Metadata property name used in acid chunks. */ - static const char* const acidTempo; /**< Metadata property name used in acid chunks. */ - - //============================================================================== - // INFO chunk properties: - - static const char* const riffInfoArchivalLocation; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoArtist; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoBaseURL; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoCinematographer; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoComment; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoComments; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoCommissioned; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoCopyright; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoCostumeDesigner; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoCountry; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoCropped; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoDateCreated; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoDateTimeOriginal; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoDefaultAudioStream; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoDimension; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoDirectory; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoDistributedBy; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoDotsPerInch; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoEditedBy; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoEighthLanguage; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoEncodedBy; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoEndTimecode; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoEngineer; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoFifthLanguage; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoFirstLanguage; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoFourthLanguage; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoGenre; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoKeywords; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoLanguage; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoLength; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoLightness; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoLocation; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoLogoIconURL; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoLogoURL; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoMedium; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoMoreInfoBannerImage; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoMoreInfoBannerURL; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoMoreInfoText; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoMoreInfoURL; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoMusicBy; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoNinthLanguage; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoNumberOfParts; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoOrganisation; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoPart; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoProducedBy; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoProductionDesigner; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoProductionStudio; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoRate; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoRated; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoRating; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoRippedBy; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoSecondaryGenre; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoSecondLanguage; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoSeventhLanguage; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoSharpness; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoSixthLanguage; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoSoftware; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoSoundSchemeTitle; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoSource; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoSourceFrom; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoStarring_ISTR; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoStarring_STAR; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoStartTimecode; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoStatistics; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoSubject; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoTapeName; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoTechnician; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoThirdLanguage; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoTimeCode; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoTitle; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoTrackNumber; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoURL; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoVegasVersionMajor; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoVegasVersionMinor; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoVersion; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoWatermarkURL; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoWrittenBy; /**< Metadata property name used in INFO chunks. */ - static const char* const riffInfoYear; /**< Metadata property name used in INFO chunks. */ - - //============================================================================== - /** Metadata property name used when reading an ISRC code from an AXML chunk. */ - static const char* const ISRC; - - /** Metadata property name used when reading a WAV file with a Tracktion chunk. */ - static const char* const tracktionLoopInfo; - - //============================================================================== - Array getPossibleSampleRates() override; - Array getPossibleBitDepths() override; - bool canDoStereo() override; - bool canDoMono() override; - - //============================================================================== - AudioFormatReader* createReaderFor (InputStream* sourceStream, - bool deleteStreamIfOpeningFails) override; - -private: - CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WavAudioFormat) -}; - -} - -#endif // WATER_WAV_AUDIOFORMAT_H_INCLUDED diff --git a/source/modules/water/audioformat/AudioFormat.cpp b/source/modules/water/audioformat/AudioFormat.cpp deleted file mode 100644 index 6ac472c48..000000000 --- a/source/modules/water/audioformat/AudioFormat.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - ============================================================================== - - This file is part of the Water library. - Copyright (c) 2015 ROLI Ltd. - Copyright (C) 2018 Filipe Coelho - - Permission is granted to use this software under the terms of either: - a) the GPL v2 (or any later version) - b) the Affero GPL v3 - - Details of these licenses can be found at: www.gnu.org/licenses - - Water is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ============================================================================== -*/ - -#include "AudioFormat.h" -#include "../files/File.h" - -namespace water { - -AudioFormat::AudioFormat (String name, StringArray extensions) - : formatName (name), fileExtensions (extensions) -{ -} - -AudioFormat::AudioFormat (StringRef name, StringRef extensions) - : formatName (name.text), fileExtensions (StringArray::fromTokens (extensions, false)) -{ -} - -AudioFormat::~AudioFormat() -{ -} - -bool AudioFormat::canHandleFile (const File& f) -{ - for (int i = 0; i < fileExtensions.size(); ++i) - if (f.hasFileExtension (fileExtensions[i])) - return true; - - return false; -} - -const String& AudioFormat::getFormatName() const { return formatName; } -const StringArray& AudioFormat::getFileExtensions() const { return fileExtensions; } -bool AudioFormat::isCompressed() { return false; } -StringArray AudioFormat::getQualityOptions() { return StringArray(); } - -#if 0 -MemoryMappedAudioFormatReader* AudioFormat::createMemoryMappedReader (const File&) -{ - return nullptr; -} - -MemoryMappedAudioFormatReader* AudioFormat::createMemoryMappedReader (FileInputStream* fin) -{ - delete fin; - return nullptr; -} -#endif - -} diff --git a/source/modules/water/audioformat/AudioFormat.h b/source/modules/water/audioformat/AudioFormat.h deleted file mode 100644 index 07e6127b4..000000000 --- a/source/modules/water/audioformat/AudioFormat.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - ============================================================================== - - This file is part of the Water library. - Copyright (c) 2015 ROLI Ltd. - Copyright (C) 2018 Filipe Coelho - - Permission is granted to use this software under the terms of either: - a) the GPL v2 (or any later version) - b) the Affero GPL v3 - - Details of these licenses can be found at: www.gnu.org/licenses - - Water is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ============================================================================== -*/ - -#ifndef WATER_AUDIOFORMAT_H_INCLUDED -#define WATER_AUDIOFORMAT_H_INCLUDED - -#include "../text/StringArray.h" - -namespace water { - -//============================================================================== -/** - Subclasses of AudioFormat are used to read and write different audio - file formats. - - @see AudioFormatReader, AudioFormatWriter, WavAudioFormat, AiffAudioFormat -*/ -class AudioFormat -{ -public: - //============================================================================== - /** Destructor. */ - virtual ~AudioFormat(); - - //============================================================================== - /** Returns the name of this format. - e.g. "WAV file" or "AIFF file" - */ - const String& getFormatName() const; - - /** Returns all the file extensions that might apply to a file of this format. - - The first item will be the one that's preferred when creating a new file. - - So for a wav file this might just return ".wav"; for an AIFF file it might - return two items, ".aif" and ".aiff" - */ - const StringArray& getFileExtensions() const; - - //============================================================================== - /** Returns true if this the given file can be read by this format. - - Subclasses shouldn't do too much work here, just check the extension or - file type. The base class implementation just checks the file's extension - against one of the ones that was registered in the constructor. - */ - virtual bool canHandleFile (const File& fileToTest); - - /** Returns a set of sample rates that the format can read and write. */ - virtual Array getPossibleSampleRates() = 0; - - /** Returns a set of bit depths that the format can read and write. */ - virtual Array getPossibleBitDepths() = 0; - - /** Returns true if the format can do 2-channel audio. */ - virtual bool canDoStereo() = 0; - - /** Returns true if the format can do 1-channel audio. */ - virtual bool canDoMono() = 0; - - /** Returns true if the format uses compressed data. */ - virtual bool isCompressed(); - - /** Returns a list of different qualities that can be used when writing. - - Non-compressed formats will just return an empty array, but for something - like Ogg-Vorbis or MP3, it might return a list of bit-rates, etc. - - When calling createWriterFor(), an index from this array is passed in to - tell the format which option is required. - */ - virtual StringArray getQualityOptions(); - - //============================================================================== - /** Tries to create an object that can read from a stream containing audio - data in this format. - - The reader object that is returned can be used to read from the stream, and - should then be deleted by the caller. - - @param sourceStream the stream to read from - the AudioFormatReader object - that is returned will delete this stream when it no longer - needs it. - @param deleteStreamIfOpeningFails if no reader can be created, this determines whether this method - should delete the stream object that was passed-in. (If a valid - reader is returned, it will always be in charge of deleting the - stream, so this parameter is ignored) - @see AudioFormatReader - */ - virtual AudioFormatReader* createReaderFor (InputStream* sourceStream, - bool deleteStreamIfOpeningFails) = 0; - -protected: - /** Creates an AudioFormat object. - - @param formatName this sets the value that will be returned by getFormatName() - @param fileExtensions an array of file extensions - these will be returned by getFileExtensions() - */ - AudioFormat (String formatName, StringArray fileExtensions); - - /** Creates an AudioFormat object. - - @param formatName this sets the value that will be returned by getFormatName() - @param fileExtensions a whitespace-separated list of file extensions - these will - be returned by getFileExtensions() - */ - AudioFormat (StringRef formatName, StringRef fileExtensions); - -private: - //============================================================================== - String formatName; - StringArray fileExtensions; -}; - -} - -#endif // WATER_AUDIOFORMAT_H_INCLUDED diff --git a/source/modules/water/audioformat/AudioFormatManager.cpp b/source/modules/water/audioformat/AudioFormatManager.cpp deleted file mode 100644 index 47fbed74e..000000000 --- a/source/modules/water/audioformat/AudioFormatManager.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - ============================================================================== - - This file is part of the Water library. - Copyright (c) 2015 ROLI Ltd. - Copyright (C) 2018 Filipe Coelho - - Permission is granted to use this software under the terms of either: - a) the GPL v2 (or any later version) - b) the Affero GPL v3 - - Details of these licenses can be found at: www.gnu.org/licenses - - Water is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ============================================================================== -*/ - -#include "AudioFormatManager.h" - -#include "../audiocodecs/WavAudioFormat.h" -#include "../files/FileInputStream.h" - -namespace water { - -AudioFormatManager::AudioFormatManager() : defaultFormatIndex (0) {} -AudioFormatManager::~AudioFormatManager() {} - -//============================================================================== -void AudioFormatManager::registerFormat (AudioFormat* newFormat, const bool makeThisTheDefaultFormat) -{ - jassert (newFormat != nullptr); - - if (newFormat != nullptr) - { - #if DEBUG - for (int i = getNumKnownFormats(); --i >= 0;) - { - if (getKnownFormat (i)->getFormatName() == newFormat->getFormatName()) - { - jassertfalse; // trying to add the same format twice! - } - } - #endif - - if (makeThisTheDefaultFormat) - defaultFormatIndex = getNumKnownFormats(); - - knownFormats.add (newFormat); - } -} - -void AudioFormatManager::registerBasicFormats() -{ - registerFormat (new WavAudioFormat(), true); -#if 0 - registerFormat (new AiffAudioFormat(), false); -#endif - - #if WATER_USE_FLAC - registerFormat (new FlacAudioFormat(), false); - #endif - - #if WATER_USE_OGGVORBIS - registerFormat (new OggVorbisAudioFormat(), false); - #endif - - #if WATER_MAC || WATER_IOS - registerFormat (new CoreAudioFormat(), false); - #endif - - #if WATER_USE_MP3AUDIOFORMAT - registerFormat (new MP3AudioFormat(), false); - #endif - - #if WATER_USE_WINDOWS_MEDIA_FORMAT - registerFormat (new WindowsMediaAudioFormat(), false); - #endif -} - -void AudioFormatManager::clearFormats() -{ - knownFormats.clear(); - defaultFormatIndex = 0; -} - -int AudioFormatManager::getNumKnownFormats() const -{ - return knownFormats.size(); -} - -AudioFormat* AudioFormatManager::getKnownFormat (const int index) const -{ - return knownFormats [index]; -} - -AudioFormat* AudioFormatManager::getDefaultFormat() const -{ - return getKnownFormat (defaultFormatIndex); -} - -AudioFormat* AudioFormatManager::findFormatForFileExtension (const String& fileExtension) const -{ - if (! fileExtension.startsWithChar ('.')) - return findFormatForFileExtension ("." + fileExtension); - - for (int i = 0; i < getNumKnownFormats(); ++i) - if (getKnownFormat(i)->getFileExtensions().contains (fileExtension, true)) - return getKnownFormat(i); - - return nullptr; -} - -String AudioFormatManager::getWildcardForAllFormats() const -{ - StringArray extensions; - - for (int i = 0; i < getNumKnownFormats(); ++i) - extensions.addArray (getKnownFormat(i)->getFileExtensions()); - - extensions.trim(); - extensions.removeEmptyStrings(); - - for (int i = 0; i < extensions.size(); ++i) - extensions.set (i, (extensions[i].startsWithChar ('.') ? "*" : "*.") + extensions[i]); - - extensions.removeDuplicates (true); - return extensions.joinIntoString (";"); -} - -//============================================================================== -AudioFormatReader* AudioFormatManager::createReaderFor (const File& file) -{ - // you need to actually register some formats before the manager can - // use them to open a file! - jassert (getNumKnownFormats() > 0); - - for (int i = 0; i < getNumKnownFormats(); ++i) - { - AudioFormat* const af = getKnownFormat(i); - - if (af->canHandleFile (file)) - if (InputStream* const in = file.createInputStream()) - if (AudioFormatReader* const r = af->createReaderFor (in, true)) - return r; - } - - return nullptr; -} - -AudioFormatReader* AudioFormatManager::createReaderFor (InputStream* audioFileStream) -{ - // you need to actually register some formats before the manager can - // use them to open a file! - jassert (getNumKnownFormats() > 0); - - ScopedPointer in (audioFileStream); - - if (in != nullptr) - { - const int64 originalStreamPos = in->getPosition(); - - for (int i = 0; i < getNumKnownFormats(); ++i) - { - if (AudioFormatReader* const r = getKnownFormat(i)->createReaderFor (in, false)) - { - in.release(); - return r; - } - - in->setPosition (originalStreamPos); - - // the stream that is passed-in must be capable of being repositioned so - // that all the formats can have a go at opening it. - jassert (in->getPosition() == originalStreamPos); - } - } - - return nullptr; -} - -} diff --git a/source/modules/water/audioformat/AudioFormatManager.h b/source/modules/water/audioformat/AudioFormatManager.h deleted file mode 100644 index dbaa7db77..000000000 --- a/source/modules/water/audioformat/AudioFormatManager.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - ============================================================================== - - This file is part of the Water library. - Copyright (c) 2015 ROLI Ltd. - Copyright (C) 2018 Filipe Coelho - - Permission is granted to use this software under the terms of either: - a) the GPL v2 (or any later version) - b) the Affero GPL v3 - - Details of these licenses can be found at: www.gnu.org/licenses - - Water is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ============================================================================== -*/ - -#ifndef WATER_AUDIOFORMATMANAGER_H_INCLUDED -#define WATER_AUDIOFORMATMANAGER_H_INCLUDED - -#include "AudioFormat.h" -#include "../containers/OwnedArray.h" -#include "../text/String.h" - -#include "CarlaJuceUtils.hpp" - -namespace water { - -//============================================================================== -/** - A class for keeping a list of available audio formats, and for deciding which - one to use to open a given file. - - After creating an AudioFormatManager object, you should call registerFormat() - or registerBasicFormats() to give it a list of format types that it can use. - - @see AudioFormat -*/ -class AudioFormatManager -{ -public: - //============================================================================== - /** Creates an empty format manager. - - Before it'll be any use, you'll need to call registerFormat() with all the - formats you want it to be able to recognise. - */ - AudioFormatManager(); - - /** Destructor. */ - ~AudioFormatManager(); - - //============================================================================== - /** Adds a format to the manager's list of available file types. - - The object passed-in will be deleted by this object, so don't keep a pointer - to it! - - If makeThisTheDefaultFormat is true, then the getDefaultFormat() method will - return this one when called. - */ - void registerFormat (AudioFormat* newFormat, - bool makeThisTheDefaultFormat); - - /** Handy method to make it easy to register the formats that come with Water. - - Currently, this will add WAV and AIFF to the list. - */ - void registerBasicFormats(); - - /** Clears the list of known formats. */ - void clearFormats(); - - /** Returns the number of currently registered file formats. */ - int getNumKnownFormats() const; - - /** Returns one of the registered file formats. */ - AudioFormat* getKnownFormat (int index) const; - - /** Iterator access to the list of known formats. */ - AudioFormat** begin() const noexcept { return knownFormats.begin(); } - - /** Iterator access to the list of known formats. */ - AudioFormat** end() const noexcept { return knownFormats.end(); } - - /** Looks for which of the known formats is listed as being for a given file - extension. - - The extension may have a dot before it, so e.g. ".wav" or "wav" are both ok. - */ - AudioFormat* findFormatForFileExtension (const String& fileExtension) const; - - /** Returns the format which has been set as the default one. - - You can set a format as being the default when it is registered. It's useful - when you want to write to a file, because the best format may change between - platforms, e.g. AIFF is preferred on the Mac, WAV on Windows. - - If none has been set as the default, this method will just return the first - one in the list. - */ - AudioFormat* getDefaultFormat() const; - - /** Returns a set of wildcards for file-matching that contains the extensions for - all known formats. - - E.g. if might return "*.wav;*.aiff" if it just knows about wavs and aiffs. - */ - String getWildcardForAllFormats() const; - - //============================================================================== - /** Searches through the known formats to try to create a suitable reader for - this file. - - If none of the registered formats can open the file, it'll return 0. If it - returns a reader, it's the caller's responsibility to delete the reader. - */ - AudioFormatReader* createReaderFor (const File& audioFile); - - /** Searches through the known formats to try to create a suitable reader for - this stream. - - The stream object that is passed-in will be deleted by this method or by the - reader that is returned, so the caller should not keep any references to it. - - The stream that is passed-in must be capable of being repositioned so - that all the formats can have a go at opening it. - - If none of the registered formats can open the stream, it'll return nullptr. - If it returns a reader, it's the caller's responsibility to delete the reader. - */ - AudioFormatReader* createReaderFor (InputStream* audioFileStream); - -private: - //============================================================================== - OwnedArray knownFormats; - int defaultFormatIndex; - - CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioFormatManager) -}; - -} - -#endif // WATER_AUDIOFORMATMANAGER_H_INCLUDED diff --git a/source/modules/water/audioformat/AudioFormatReader.cpp b/source/modules/water/audioformat/AudioFormatReader.cpp deleted file mode 100644 index 53ac2a79e..000000000 --- a/source/modules/water/audioformat/AudioFormatReader.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - ============================================================================== - - This file is part of the Water library. - Copyright (c) 2015 ROLI Ltd. - Copyright (C) 2018 Filipe Coelho - - Permission is granted to use this software under the terms of either: - a) the GPL v2 (or any later version) - b) the Affero GPL v3 - - Details of these licenses can be found at: www.gnu.org/licenses - - Water is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ============================================================================== -*/ - -#include "AudioFormatReader.h" - -#include "../buffers/AudioSampleBuffer.h" -#include "../streams/InputStream.h" - -namespace water { - -AudioFormatReader::AudioFormatReader (InputStream* const in, const String& name) - : sampleRate (0), - bitsPerSample (0), - lengthInSamples (0), - numChannels (0), - usesFloatingPointData (false), - input (in), - formatName (name) -{ -} - -AudioFormatReader::~AudioFormatReader() -{ - delete input; -} - -bool AudioFormatReader::read (int* const* destSamples, - int numDestChannels, - int64 startSampleInSource, - int numSamplesToRead, - const bool fillLeftoverChannelsWithCopies) -{ - jassert (numDestChannels > 0); // you have to actually give this some channels to work with! - - const size_t originalNumSamplesToRead = (size_t) numSamplesToRead; - int startOffsetInDestBuffer = 0; - - if (startSampleInSource < 0) - { - const int silence = (int) jmin (-startSampleInSource, (int64) numSamplesToRead); - - for (int i = numDestChannels; --i >= 0;) - if (destSamples[i] != nullptr) - zeromem (destSamples[i], sizeof (int) * (size_t) silence); - - startOffsetInDestBuffer += silence; - numSamplesToRead -= silence; - startSampleInSource = 0; - } - - if (numSamplesToRead <= 0) - return true; - - if (! readSamples (const_cast (destSamples), - jmin ((int) numChannels, numDestChannels), startOffsetInDestBuffer, - startSampleInSource, numSamplesToRead)) - return false; - - if (numDestChannels > (int) numChannels) - { - if (fillLeftoverChannelsWithCopies) - { - int* lastFullChannel = destSamples[0]; - - for (int i = (int) numChannels; --i > 0;) - { - if (destSamples[i] != nullptr) - { - lastFullChannel = destSamples[i]; - break; - } - } - - if (lastFullChannel != nullptr) - for (int i = (int) numChannels; i < numDestChannels; ++i) - if (destSamples[i] != nullptr) - memcpy (destSamples[i], lastFullChannel, sizeof (int) * originalNumSamplesToRead); - } - else - { - for (int i = (int) numChannels; i < numDestChannels; ++i) - if (destSamples[i] != nullptr) - zeromem (destSamples[i], sizeof (int) * originalNumSamplesToRead); - } - } - - return true; -} - -static void readChannels (AudioFormatReader& reader, - int** const chans, AudioSampleBuffer* const buffer, - const int startSample, const int numSamples, - const int64 readerStartSample, const int numTargetChannels) -{ - for (int j = 0; j < numTargetChannels; ++j) - chans[j] = reinterpret_cast (buffer->getWritePointer (j, startSample)); - - chans[numTargetChannels] = nullptr; - reader.read (chans, numTargetChannels, readerStartSample, numSamples, true); -} - - #define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \ - for (int i = 0; i < num; ++i) normalOp; - -static void convertFixedToFloat (float* dest, const int* src, float multiplier, int num) noexcept -{ - for (int i = 0; i < num; ++i) - dest[i] = src[i] * multiplier; -} - -void AudioFormatReader::read (AudioSampleBuffer* buffer, - int startSample, - int numSamples, - int64 readerStartSample, - bool useReaderLeftChan, - bool useReaderRightChan) -{ - jassert (buffer != nullptr); - jassert (startSample >= 0 && startSample + numSamples <= buffer->getNumSamples()); - - if (numSamples > 0) - { - const int numTargetChannels = buffer->getNumChannels(); - - if (numTargetChannels <= 2) - { - int* const dest0 = reinterpret_cast (buffer->getWritePointer (0, startSample)); - int* const dest1 = reinterpret_cast (numTargetChannels > 1 ? buffer->getWritePointer (1, startSample) : nullptr); - int* chans[3]; - - if (useReaderLeftChan == useReaderRightChan) - { - chans[0] = dest0; - chans[1] = numChannels > 1 ? dest1 : nullptr; - } - else if (useReaderLeftChan || (numChannels == 1)) - { - chans[0] = dest0; - chans[1] = nullptr; - } - else if (useReaderRightChan) - { - chans[0] = nullptr; - chans[1] = dest0; - } - - chans[2] = nullptr; - read (chans, 2, readerStartSample, numSamples, true); - - // if the target's stereo and the source is mono, dupe the first channel.. - if (numTargetChannels > 1 && (chans[0] == nullptr || chans[1] == nullptr)) - memcpy (dest1, dest0, sizeof (float) * (size_t) numSamples); - } - else if (numTargetChannels <= 64) - { - int* chans[65]; - readChannels (*this, chans, buffer, startSample, numSamples, readerStartSample, numTargetChannels); - } - else - { - HeapBlock chans; - chans.malloc ((size_t) numTargetChannels + 1); - // FIXME, check malloc return - readChannels (*this, chans, buffer, startSample, numSamples, readerStartSample, numTargetChannels); - } - - if (! usesFloatingPointData) - for (int j = 0; j < numTargetChannels; ++j) - if (float* const d = buffer->getWritePointer (j, startSample)) - convertFixedToFloat (d, reinterpret_cast (d), 1.0f / 0x7fffffff, numSamples); - } -} - -} diff --git a/source/modules/water/audioformat/AudioFormatReader.h b/source/modules/water/audioformat/AudioFormatReader.h deleted file mode 100644 index 3d73252fe..000000000 --- a/source/modules/water/audioformat/AudioFormatReader.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - ============================================================================== - - This file is part of the Water library. - Copyright (c) 2015 ROLI Ltd. - Copyright (C) 2018 Filipe Coelho - - Permission is granted to use this software under the terms of either: - a) the GPL v2 (or any later version) - b) the Affero GPL v3 - - Details of these licenses can be found at: www.gnu.org/licenses - - Water is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - ============================================================================== -*/ - -#ifndef WATER_AUDIOFORMATREADER_H_INCLUDED -#define WATER_AUDIOFORMATREADER_H_INCLUDED - -#include "../buffers/AudioDataConverters.h" -#include "../text/StringPairArray.h" - -#include "CarlaJuceUtils.hpp" - -namespace water { - -//============================================================================== -/** - Reads samples from an audio file stream. - - A subclass that reads a specific type of audio format will be created by - an AudioFormat object. - - @see AudioFormat, AudioFormatWriter -*/ -class AudioFormatReader -{ -protected: - //============================================================================== - /** Creates an AudioFormatReader object. - - @param sourceStream the stream to read from - this will be deleted - by this object when it is no longer needed. (Some - specialised readers might not use this parameter and - can leave it as nullptr). - @param formatName the description that will be returned by the getFormatName() - method - */ - AudioFormatReader (InputStream* sourceStream, - const String& formatName); - -public: - /** Destructor. */ - virtual ~AudioFormatReader(); - - //============================================================================== - /** Returns a description of what type of format this is. - - E.g. "AIFF" - */ - const String& getFormatName() const noexcept { return formatName; } - - //============================================================================== - /** Reads samples from the stream. - - @param destSamples an array of buffers into which the sample data for each - channel will be written. - If the format is fixed-point, each channel will be written - as an array of 32-bit signed integers using the full - range -0x80000000 to 0x7fffffff, regardless of the source's - bit-depth. If it is a floating-point format, you should cast - the resulting array to a (float**) to get the values (in the - range -1.0 to 1.0 or beyond) - If the format is stereo, then destSamples[0] is the left channel - data, and destSamples[1] is the right channel. - The numDestChannels parameter indicates how many pointers this array - contains, but some of these pointers can be null if you don't want to - read data for some of the channels - @param numDestChannels the number of array elements in the destChannels array - @param startSampleInSource the position in the audio file or stream at which the samples - should be read, as a number of samples from the start of the - stream. It's ok for this to be beyond the start or end of the - available data - any samples that are out-of-range will be returned - as zeros. - @param numSamplesToRead the number of samples to read. If this is greater than the number - of samples that the file or stream contains. the result will be padded - with zeros - @param fillLeftoverChannelsWithCopies if true, this indicates that if there's no source data available - for some of the channels that you pass in, then they should be filled with - copies of valid source channels. - E.g. if you're reading a mono file and you pass 2 channels to this method, then - if fillLeftoverChannelsWithCopies is true, both destination channels will be filled - with the same data from the file's single channel. If fillLeftoverChannelsWithCopies - was false, then only the first channel would be filled with the file's contents, and - the second would be cleared. If there are many channels, e.g. you try to read 4 channels - from a stereo file, then the last 3 would all end up with copies of the same data. - @returns true if the operation succeeded, false if there was an error. Note - that reading sections of data beyond the extent of the stream isn't an - error - the reader should just return zeros for these regions - @see readMaxLevels - */ - bool read (int* const* destSamples, - int numDestChannels, - int64 startSampleInSource, - int numSamplesToRead, - bool fillLeftoverChannelsWithCopies); - - /** Fills a section of an AudioSampleBuffer from this reader. - - This will convert the reader's fixed- or floating-point data to - the buffer's floating-point format, and will try to intelligently - cope with mismatches between the number of channels in the reader - and the buffer. - */ - void read (AudioSampleBuffer* buffer, - int startSampleInDestBuffer, - int numSamples, - int64 readerStartSample, - bool useReaderLeftChan, - bool useReaderRightChan); - - //============================================================================== - /** The sample-rate of the stream. */ - double sampleRate; - - /** The number of bits per sample, e.g. 16, 24, 32. */ - unsigned int bitsPerSample; - - /** The total number of samples in the audio stream. */ - int64 lengthInSamples; - - /** The total number of channels in the audio stream. */ - unsigned int numChannels; - - /** Indicates whether the data is floating-point or fixed. */ - bool usesFloatingPointData; - - /** A set of metadata values that the reader has pulled out of the stream. - - Exactly what these values are depends on the format, so you can - check out the format implementation code to see what kind of stuff - they understand. - */ - StringPairArray metadataValues; - - /** The input stream, for use by subclasses. */ - InputStream* input; - - - //============================================================================== - /** Subclasses must implement this method to perform the low-level read operation. - - Callers should use read() instead of calling this directly. - - @param destSamples the array of destination buffers to fill. Some of these - pointers may be null - @param numDestChannels the number of items in the destSamples array. This - value is guaranteed not to be greater than the number of - channels that this reader object contains - @param startOffsetInDestBuffer the number of samples from the start of the - dest data at which to begin writing - @param startSampleInFile the number of samples into the source data at which - to begin reading. This value is guaranteed to be >= 0. - @param numSamples the number of samples to read - */ - virtual bool readSamples (int** destSamples, - int numDestChannels, - int startOffsetInDestBuffer, - int64 startSampleInFile, - int numSamples) = 0; - - -protected: - //============================================================================== - /** Used by AudioFormatReader subclasses to copy data to different formats. */ - template - struct ReadHelper - { - typedef AudioData::Pointer DestType; - typedef AudioData::Pointer SourceType; - - template - static void read (TargetType* const* destData, int destOffset, int numDestChannels, - const void* sourceData, int numSourceChannels, int numSamples) noexcept - { - for (int i = 0; i < numDestChannels; ++i) - { - if (void* targetChan = destData[i]) - { - DestType dest (targetChan); - dest += destOffset; - - if (i < numSourceChannels) - dest.convertSamples (SourceType (addBytesToPointer (sourceData, i * SourceType::getBytesPerSample()), numSourceChannels), numSamples); - else - dest.clearSamples (numSamples); - } - } - } - }; - - /** Used by AudioFormatReader subclasses to clear any parts of the data blocks that lie - beyond the end of their available length. - */ - static void clearSamplesBeyondAvailableLength (int** destSamples, int numDestChannels, - int startOffsetInDestBuffer, int64 startSampleInFile, - int& numSamples, int64 fileLengthInSamples) - { - jassert (destSamples != nullptr); - const int64 samplesAvailable = fileLengthInSamples - startSampleInFile; - - if (samplesAvailable < numSamples) - { - for (int i = numDestChannels; --i >= 0;) - if (destSamples[i] != nullptr) - zeromem (destSamples[i] + startOffsetInDestBuffer, sizeof (int) * (size_t) numSamples); - - numSamples = (int) samplesAvailable; - } - } - -private: - String formatName; - - CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioFormatReader) -}; - -} - -#endif // WATER_AUDIOFORMATREADER_H_INCLUDED diff --git a/source/modules/water/buffers/AudioDataConverters.cpp b/source/modules/water/buffers/AudioDataConverters.cpp deleted file mode 100644 index d4edc5633..000000000 --- a/source/modules/water/buffers/AudioDataConverters.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/* - ============================================================================== - - This file is part of the Water library. - Copyright (c) 2016 - ROLI Ltd. - Copyright (C) 2018 Filipe Coelho - - Permission is granted to use this software under the terms of the ISC license - http://www.isc.org/downloads/software-support-policy/isc-license/ - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD - TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, - OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - OF THIS SOFTWARE. - - ============================================================================== -*/ - -#include "AudioDataConverters.h" - -namespace water { - -void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) -{ - const double maxVal = (double) 0x7fff; - char* intData = static_cast (dest); - - if (dest != (void*) source || destBytesPerSample <= 4) - { - for (int i = 0; i < numSamples; ++i) - { - *(uint16*) intData = ByteOrder::swapIfBigEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - intData += destBytesPerSample; - } - } - else - { - intData += destBytesPerSample * numSamples; - - for (int i = numSamples; --i >= 0;) - { - intData -= destBytesPerSample; - *(uint16*) intData = ByteOrder::swapIfBigEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - } - } -} - -void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) -{ - const double maxVal = (double) 0x7fff; - char* intData = static_cast (dest); - - if (dest != (void*) source || destBytesPerSample <= 4) - { - for (int i = 0; i < numSamples; ++i) - { - *(uint16*) intData = ByteOrder::swapIfLittleEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - intData += destBytesPerSample; - } - } - else - { - intData += destBytesPerSample * numSamples; - - for (int i = numSamples; --i >= 0;) - { - intData -= destBytesPerSample; - *(uint16*) intData = ByteOrder::swapIfLittleEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - } - } -} - -void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) -{ - const double maxVal = (double) 0x7fffff; - char* intData = static_cast (dest); - - if (dest != (void*) source || destBytesPerSample <= 4) - { - for (int i = 0; i < numSamples; ++i) - { - ByteOrder::littleEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); - intData += destBytesPerSample; - } - } - else - { - intData += destBytesPerSample * numSamples; - - for (int i = numSamples; --i >= 0;) - { - intData -= destBytesPerSample; - ByteOrder::littleEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); - } - } -} - -void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) -{ - const double maxVal = (double) 0x7fffff; - char* intData = static_cast (dest); - - if (dest != (void*) source || destBytesPerSample <= 4) - { - for (int i = 0; i < numSamples; ++i) - { - ByteOrder::bigEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); - intData += destBytesPerSample; - } - } - else - { - intData += destBytesPerSample * numSamples; - - for (int i = numSamples; --i >= 0;) - { - intData -= destBytesPerSample; - ByteOrder::bigEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData); - } - } -} - -void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) -{ - const double maxVal = (double) 0x7fffffff; - char* intData = static_cast (dest); - - if (dest != (void*) source || destBytesPerSample <= 4) - { - for (int i = 0; i < numSamples; ++i) - { - *(uint32*)intData = ByteOrder::swapIfBigEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - intData += destBytesPerSample; - } - } - else - { - intData += destBytesPerSample * numSamples; - - for (int i = numSamples; --i >= 0;) - { - intData -= destBytesPerSample; - *(uint32*)intData = ByteOrder::swapIfBigEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - } - } -} - -void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) -{ - const double maxVal = (double) 0x7fffffff; - char* intData = static_cast (dest); - - if (dest != (void*) source || destBytesPerSample <= 4) - { - for (int i = 0; i < numSamples; ++i) - { - *(uint32*)intData = ByteOrder::swapIfLittleEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - intData += destBytesPerSample; - } - } - else - { - intData += destBytesPerSample * numSamples; - - for (int i = numSamples; --i >= 0;) - { - intData -= destBytesPerSample; - *(uint32*)intData = ByteOrder::swapIfLittleEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i]))); - } - } -} - -void AudioDataConverters::convertFloatToFloat32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) -{ - jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data! - - char* d = static_cast (dest); - - for (int i = 0; i < numSamples; ++i) - { - *(float*) d = source[i]; - - #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ - *(uint32*) d = ByteOrder::swap (*(uint32*) d); - #endif - - d += destBytesPerSample; - } -} - -void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) -{ - jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data! - - char* d = static_cast (dest); - - for (int i = 0; i < numSamples; ++i) - { - *(float*) d = source[i]; - - #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - *(uint32*) d = ByteOrder::swap (*(uint32*) d); - #endif - - d += destBytesPerSample; - } -} - -//============================================================================== -void AudioDataConverters::convertInt16LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) -{ - const float scale = 1.0f / 0x7fff; - const char* intData = static_cast (source); - - if (source != (void*) dest || srcBytesPerSample >= 4) - { - for (int i = 0; i < numSamples; ++i) - { - dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*(uint16*)intData); - intData += srcBytesPerSample; - } - } - else - { - intData += srcBytesPerSample * numSamples; - - for (int i = numSamples; --i >= 0;) - { - intData -= srcBytesPerSample; - dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*(uint16*)intData); - } - } -} - -void AudioDataConverters::convertInt16BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) -{ - const float scale = 1.0f / 0x7fff; - const char* intData = static_cast (source); - - if (source != (void*) dest || srcBytesPerSample >= 4) - { - for (int i = 0; i < numSamples; ++i) - { - dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*(uint16*)intData); - intData += srcBytesPerSample; - } - } - else - { - intData += srcBytesPerSample * numSamples; - - for (int i = numSamples; --i >= 0;) - { - intData -= srcBytesPerSample; - dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*(uint16*)intData); - } - } -} - -void AudioDataConverters::convertInt24LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) -{ - const float scale = 1.0f / 0x7fffff; - const char* intData = static_cast (source); - - if (source != (void*) dest || srcBytesPerSample >= 4) - { - for (int i = 0; i < numSamples; ++i) - { - dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData); - intData += srcBytesPerSample; - } - } - else - { - intData += srcBytesPerSample * numSamples; - - for (int i = numSamples; --i >= 0;) - { - intData -= srcBytesPerSample; - dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData); - } - } -} - -void AudioDataConverters::convertInt24BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) -{ - const float scale = 1.0f / 0x7fffff; - const char* intData = static_cast (source); - - if (source != (void*) dest || srcBytesPerSample >= 4) - { - for (int i = 0; i < numSamples; ++i) - { - dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData); - intData += srcBytesPerSample; - } - } - else - { - intData += srcBytesPerSample * numSamples; - - for (int i = numSamples; --i >= 0;) - { - intData -= srcBytesPerSample; - dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData); - } - } -} - -void AudioDataConverters::convertInt32LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) -{ - const float scale = 1.0f / 0x7fffffff; - const char* intData = static_cast (source); - - if (source != (void*) dest || srcBytesPerSample >= 4) - { - for (int i = 0; i < numSamples; ++i) - { - dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*(uint32*) intData); - intData += srcBytesPerSample; - } - } - else - { - intData += srcBytesPerSample * numSamples; - - for (int i = numSamples; --i >= 0;) - { - intData -= srcBytesPerSample; - dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*(uint32*) intData); - } - } -} - -void AudioDataConverters::convertInt32BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) -{ - const float scale = 1.0f / 0x7fffffff; - const char* intData = static_cast (source); - - if (source != (void*) dest || srcBytesPerSample >= 4) - { - for (int i = 0; i < numSamples; ++i) - { - dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*(uint32*) intData); - intData += srcBytesPerSample; - } - } - else - { - intData += srcBytesPerSample * numSamples; - - for (int i = numSamples; --i >= 0;) - { - intData -= srcBytesPerSample; - dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*(uint32*) intData); - } - } -} - -void AudioDataConverters::convertFloat32LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) -{ - const char* s = static_cast (source); - - for (int i = 0; i < numSamples; ++i) - { - dest[i] = *(float*)s; - - #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ - uint32* const d = (uint32*) (dest + i); - *d = ByteOrder::swap (*d); - #endif - - s += srcBytesPerSample; - } -} - -void AudioDataConverters::convertFloat32BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) -{ - const char* s = static_cast (source); - - for (int i = 0; i < numSamples; ++i) - { - dest[i] = *(float*)s; - - #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - uint32* const d = (uint32*) (dest + i); - *d = ByteOrder::swap (*d); - #endif - - s += srcBytesPerSample; - } -} - - -//============================================================================== -void AudioDataConverters::convertFloatToFormat (const DataFormat destFormat, - const float* const source, - void* const dest, - const int numSamples) -{ - switch (destFormat) - { - case int16LE: convertFloatToInt16LE (source, dest, numSamples); break; - case int16BE: convertFloatToInt16BE (source, dest, numSamples); break; - case int24LE: convertFloatToInt24LE (source, dest, numSamples); break; - case int24BE: convertFloatToInt24BE (source, dest, numSamples); break; - case int32LE: convertFloatToInt32LE (source, dest, numSamples); break; - case int32BE: convertFloatToInt32BE (source, dest, numSamples); break; - case float32LE: convertFloatToFloat32LE (source, dest, numSamples); break; - case float32BE: convertFloatToFloat32BE (source, dest, numSamples); break; - default: jassertfalse; break; - } -} - -void AudioDataConverters::convertFormatToFloat (const DataFormat sourceFormat, - const void* const source, - float* const dest, - const int numSamples) -{ - switch (sourceFormat) - { - case int16LE: convertInt16LEToFloat (source, dest, numSamples); break; - case int16BE: convertInt16BEToFloat (source, dest, numSamples); break; - case int24LE: convertInt24LEToFloat (source, dest, numSamples); break; - case int24BE: convertInt24BEToFloat (source, dest, numSamples); break; - case int32LE: convertInt32LEToFloat (source, dest, numSamples); break; - case int32BE: convertInt32BEToFloat (source, dest, numSamples); break; - case float32LE: convertFloat32LEToFloat (source, dest, numSamples); break; - case float32BE: convertFloat32BEToFloat (source, dest, numSamples); break; - default: jassertfalse; break; - } -} - -//============================================================================== -void AudioDataConverters::interleaveSamples (const float** const source, - float* const dest, - const int numSamples, - const int numChannels) -{ - for (int chan = 0; chan < numChannels; ++chan) - { - int i = chan; - const float* src = source [chan]; - - for (int j = 0; j < numSamples; ++j) - { - dest [i] = src [j]; - i += numChannels; - } - } -} - -void AudioDataConverters::deinterleaveSamples (const float* const source, - float** const dest, - const int numSamples, - const int numChannels) -{ - for (int chan = 0; chan < numChannels; ++chan) - { - int i = chan; - float* dst = dest [chan]; - - for (int j = 0; j < numSamples; ++j) - { - dst [j] = source [i]; - i += numChannels; - } - } -} - -} diff --git a/source/modules/water/buffers/AudioDataConverters.h b/source/modules/water/buffers/AudioDataConverters.h deleted file mode 100644 index 96195b6d4..000000000 --- a/source/modules/water/buffers/AudioDataConverters.h +++ /dev/null @@ -1,719 +0,0 @@ -/* - ============================================================================== - - This file is part of the Water library. - Copyright (c) 2016 ROLI Ltd. - Copyright (C) 2018 Filipe Coelho - - Permission is granted to use this software under the terms of the ISC license - http://www.isc.org/downloads/software-support-policy/isc-license/ - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD - TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, - OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - OF THIS SOFTWARE. - - ============================================================================== -*/ - -#ifndef WATER_AUDIODATACONVERTERS_H_INCLUDED -#define WATER_AUDIODATACONVERTERS_H_INCLUDED - -#include "../memory/ByteOrder.h" - -namespace water { - -//============================================================================== -/** - This class a container which holds all the classes pertaining to the AudioData::Pointer - audio sample format class. - - @see AudioData::Pointer. -*/ -class AudioData -{ -public: - //============================================================================== - // These types can be used as the SampleFormat template parameter for the AudioData::Pointer class. - - class Int8; /**< Used as a template parameter for AudioData::Pointer. Indicates an 8-bit integer packed data format. */ - class UInt8; /**< Used as a template parameter for AudioData::Pointer. Indicates an 8-bit unsigned integer packed data format. */ - class Int16; /**< Used as a template parameter for AudioData::Pointer. Indicates an 16-bit integer packed data format. */ - class Int24; /**< Used as a template parameter for AudioData::Pointer. Indicates an 24-bit integer packed data format. */ - class Int32; /**< Used as a template parameter for AudioData::Pointer. Indicates an 32-bit integer packed data format. */ - class Float32; /**< Used as a template parameter for AudioData::Pointer. Indicates an 32-bit float data format. */ - - //============================================================================== - // These types can be used as the Endianness template parameter for the AudioData::Pointer class. - - class BigEndian; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored in big-endian order. */ - class LittleEndian; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored in little-endian order. */ - class NativeEndian; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored in the CPU's native endianness. */ - - //============================================================================== - // These types can be used as the InterleavingType template parameter for the AudioData::Pointer class. - - class NonInterleaved; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored contiguously. */ - class Interleaved; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are interleaved with a number of other channels. */ - - //============================================================================== - // These types can be used as the Constness template parameter for the AudioData::Pointer class. - - class NonConst; /**< Used as a template parameter for AudioData::Pointer. Indicates that the pointer can be used for non-const data. */ - class Const; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples can only be used for const data.. */ - - #ifndef DOXYGEN - //============================================================================== - class BigEndian - { - public: - template static inline float getAsFloat (SampleFormatType& s) noexcept { return s.getAsFloatBE(); } - template static inline void setAsFloat (SampleFormatType& s, float newValue) noexcept { s.setAsFloatBE (newValue); } - template static inline int32 getAsInt32 (SampleFormatType& s) noexcept { return s.getAsInt32BE(); } - template static inline void setAsInt32 (SampleFormatType& s, int32 newValue) noexcept { s.setAsInt32BE (newValue); } - template static inline void copyFrom (DestType& dest, SourceType& source) noexcept { dest.copyFromBE (source); } - enum { isBigEndian = 1 }; - }; - - class LittleEndian - { - public: - template static inline float getAsFloat (SampleFormatType& s) noexcept { return s.getAsFloatLE(); } - template static inline void setAsFloat (SampleFormatType& s, float newValue) noexcept { s.setAsFloatLE (newValue); } - template static inline int32 getAsInt32 (SampleFormatType& s) noexcept { return s.getAsInt32LE(); } - template static inline void setAsInt32 (SampleFormatType& s, int32 newValue) noexcept { s.setAsInt32LE (newValue); } - template static inline void copyFrom (DestType& dest, SourceType& source) noexcept { dest.copyFromLE (source); } - enum { isBigEndian = 0 }; - }; - - #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ - class NativeEndian : public BigEndian {}; - #else - class NativeEndian : public LittleEndian {}; - #endif - - //============================================================================== - class Int8 - { - public: - inline Int8 (void* d) noexcept : data (static_cast (d)) {} - - inline void advance() noexcept { ++data; } - inline void skip (int numSamples) noexcept { data += numSamples; } - inline float getAsFloatLE() const noexcept { return (float) (*data * (1.0 / (1.0 + maxValue))); } - inline float getAsFloatBE() const noexcept { return getAsFloatLE(); } - inline void setAsFloatLE (float newValue) noexcept { *data = (int8) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))); } - inline void setAsFloatBE (float newValue) noexcept { setAsFloatLE (newValue); } - inline int32 getAsInt32LE() const noexcept { return (int) (*data << 24); } - inline int32 getAsInt32BE() const noexcept { return getAsInt32LE(); } - inline void setAsInt32LE (int newValue) noexcept { *data = (int8) (newValue >> 24); } - inline void setAsInt32BE (int newValue) noexcept { setAsInt32LE (newValue); } - inline void clear() noexcept { *data = 0; } - inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;} - template inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); } - template inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); } - inline void copyFromSameType (Int8& source) noexcept { *data = *source.data; } - - int8* data; - enum { bytesPerSample = 1, maxValue = 0x7f, resolution = (1 << 24), isFloat = 0 }; - }; - - class UInt8 - { - public: - inline UInt8 (void* d) noexcept : data (static_cast (d)) {} - - inline void advance() noexcept { ++data; } - inline void skip (int numSamples) noexcept { data += numSamples; } - inline float getAsFloatLE() const noexcept { return (float) ((*data - 128) * (1.0 / (1.0 + maxValue))); } - inline float getAsFloatBE() const noexcept { return getAsFloatLE(); } - inline void setAsFloatLE (float newValue) noexcept { *data = (uint8) jlimit (0, 255, 128 + roundToInt (newValue * (1.0 + maxValue))); } - inline void setAsFloatBE (float newValue) noexcept { setAsFloatLE (newValue); } - inline int32 getAsInt32LE() const noexcept { return (int) ((*data - 128) << 24); } - inline int32 getAsInt32BE() const noexcept { return getAsInt32LE(); } - inline void setAsInt32LE (int newValue) noexcept { *data = (uint8) (128 + (newValue >> 24)); } - inline void setAsInt32BE (int newValue) noexcept { setAsInt32LE (newValue); } - inline void clear() noexcept { *data = 128; } - inline void clearMultiple (int num) noexcept { memset (data, 128, (size_t) num) ;} - template inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); } - template inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); } - inline void copyFromSameType (UInt8& source) noexcept { *data = *source.data; } - - uint8* data; - enum { bytesPerSample = 1, maxValue = 0x7f, resolution = (1 << 24), isFloat = 0 }; - }; - - class Int16 - { - public: - inline Int16 (void* d) noexcept : data (static_cast (d)) {} - - inline void advance() noexcept { ++data; } - inline void skip (int numSamples) noexcept { data += numSamples; } - inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int16) ByteOrder::swapIfBigEndian (*data)); } - inline float getAsFloatBE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int16) ByteOrder::swapIfLittleEndian (*data)); } - inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint16) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue)))); } - inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint16) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue)))); } - inline int32 getAsInt32LE() const noexcept { return (int32) (ByteOrder::swapIfBigEndian ((uint16) *data) << 16); } - inline int32 getAsInt32BE() const noexcept { return (int32) (ByteOrder::swapIfLittleEndian ((uint16) *data) << 16); } - inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint16) (newValue >> 16)); } - inline void setAsInt32BE (int32 newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint16) (newValue >> 16)); } - inline void clear() noexcept { *data = 0; } - inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;} - template inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); } - template inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); } - inline void copyFromSameType (Int16& source) noexcept { *data = *source.data; } - - uint16* data; - enum { bytesPerSample = 2, maxValue = 0x7fff, resolution = (1 << 16), isFloat = 0 }; - }; - - class Int24 - { - public: - inline Int24 (void* d) noexcept : data (static_cast (d)) {} - - inline void advance() noexcept { data += 3; } - inline void skip (int numSamples) noexcept { data += 3 * numSamples; } - inline float getAsFloatLE() const noexcept { return (float) (ByteOrder::littleEndian24Bit (data) * (1.0 / (1.0 + maxValue))); } - inline float getAsFloatBE() const noexcept { return (float) (ByteOrder::bigEndian24Bit (data) * (1.0 / (1.0 + maxValue))); } - inline void setAsFloatLE (float newValue) noexcept { ByteOrder::littleEndian24BitToChars (jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))), data); } - inline void setAsFloatBE (float newValue) noexcept { ByteOrder::bigEndian24BitToChars (jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))), data); } - inline int32 getAsInt32LE() const noexcept { return (int32) ByteOrder::littleEndian24Bit (data) << 8; } - inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::bigEndian24Bit (data) << 8; } - inline void setAsInt32LE (int32 newValue) noexcept { ByteOrder::littleEndian24BitToChars (newValue >> 8, data); } - inline void setAsInt32BE (int32 newValue) noexcept { ByteOrder::bigEndian24BitToChars (newValue >> 8, data); } - inline void clear() noexcept { data[0] = 0; data[1] = 0; data[2] = 0; } - inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;} - template inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); } - template inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); } - inline void copyFromSameType (Int24& source) noexcept { data[0] = source.data[0]; data[1] = source.data[1]; data[2] = source.data[2]; } - - char* data; - enum { bytesPerSample = 3, maxValue = 0x7fffff, resolution = (1 << 8), isFloat = 0 }; - }; - - class Int32 - { - public: - inline Int32 (void* d) noexcept : data (static_cast (d)) {} - - inline void advance() noexcept { ++data; } - inline void skip (int numSamples) noexcept { data += numSamples; } - inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfBigEndian (*data)); } - inline float getAsFloatBE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfLittleEndian (*data)); } - inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } - inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } - inline int32 getAsInt32LE() const noexcept { return (int32) ByteOrder::swapIfBigEndian (*data); } - inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::swapIfLittleEndian (*data); } - inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) newValue); } - inline void setAsInt32BE (int32 newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) newValue); } - inline void clear() noexcept { *data = 0; } - inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;} - template inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); } - template inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); } - inline void copyFromSameType (Int32& source) noexcept { *data = *source.data; } - - uint32* data; - enum { bytesPerSample = 4, maxValue = 0x7fffffff, resolution = 1, isFloat = 0 }; - }; - - /** A 32-bit integer type, of which only the bottom 24 bits are used. */ - class Int24in32 : public Int32 - { - public: - inline Int24in32 (void* d) noexcept : Int32 (d) {} - - inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfBigEndian (*data)); } - inline float getAsFloatBE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfLittleEndian (*data)); } - inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } - inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); } - inline int32 getAsInt32LE() const noexcept { return (int32) ByteOrder::swapIfBigEndian (*data) << 8; } - inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::swapIfLittleEndian (*data) << 8; } - inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) newValue >> 8); } - inline void setAsInt32BE (int32 newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) newValue >> 8); } - template inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); } - template inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); } - inline void copyFromSameType (Int24in32& source) noexcept { *data = *source.data; } - - enum { bytesPerSample = 4, maxValue = 0x7fffff, resolution = (1 << 8), isFloat = 0 }; - }; - - class Float32 - { - public: - inline Float32 (void* d) noexcept : data (static_cast (d)) {} - - inline void advance() noexcept { ++data; } - inline void skip (int numSamples) noexcept { data += numSamples; } - #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ - inline float getAsFloatBE() const noexcept { return *data; } - inline void setAsFloatBE (float newValue) noexcept { *data = newValue; } - inline float getAsFloatLE() const noexcept { union { uint32 asInt; float asFloat; } n; n.asInt = ByteOrder::swap (*(uint32*) data); return n.asFloat; } - inline void setAsFloatLE (float newValue) noexcept { union { uint32 asInt; float asFloat; } n; n.asFloat = newValue; *(uint32*) data = ByteOrder::swap (n.asInt); } - #else - inline float getAsFloatLE() const noexcept { return *data; } - inline void setAsFloatLE (float newValue) noexcept { *data = newValue; } - inline float getAsFloatBE() const noexcept { union { uint32 asInt; float asFloat; } n; n.asInt = ByteOrder::swap (*(uint32*) data); return n.asFloat; } - inline void setAsFloatBE (float newValue) noexcept { union { uint32 asInt; float asFloat; } n; n.asFloat = newValue; *(uint32*) data = ByteOrder::swap (n.asInt); } - #endif - inline int32 getAsInt32LE() const noexcept { return (int32) roundToInt (jlimit (-1.0, 1.0, (double) getAsFloatLE()) * (double) maxValue); } - inline int32 getAsInt32BE() const noexcept { return (int32) roundToInt (jlimit (-1.0, 1.0, (double) getAsFloatBE()) * (double) maxValue); } - inline void setAsInt32LE (int32 newValue) noexcept { setAsFloatLE ((float) (newValue * (1.0 / (1.0 + maxValue)))); } - inline void setAsInt32BE (int32 newValue) noexcept { setAsFloatBE ((float) (newValue * (1.0 / (1.0 + maxValue)))); } - inline void clear() noexcept { *data = 0; } - inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;} - template inline void copyFromLE (SourceType& source) noexcept { setAsFloatLE (source.getAsFloat()); } - template inline void copyFromBE (SourceType& source) noexcept { setAsFloatBE (source.getAsFloat()); } - inline void copyFromSameType (Float32& source) noexcept { *data = *source.data; } - - float* data; - enum { bytesPerSample = 4, maxValue = 0x7fffffff, resolution = (1 << 8), isFloat = 1 }; - }; - - //============================================================================== - class NonInterleaved - { - public: - inline NonInterleaved() noexcept {} - inline NonInterleaved (const NonInterleaved&) noexcept {} - inline NonInterleaved (const int) noexcept {} - inline void copyFrom (const NonInterleaved&) noexcept {} - template inline void advanceData (SampleFormatType& s) noexcept { s.advance(); } - template inline void advanceDataBy (SampleFormatType& s, int numSamples) noexcept { s.skip (numSamples); } - template inline void clear (SampleFormatType& s, int numSamples) noexcept { s.clearMultiple (numSamples); } - template inline static int getNumBytesBetweenSamples (const SampleFormatType&) noexcept { return SampleFormatType::bytesPerSample; } - - enum { isInterleavedType = 0, numInterleavedChannels = 1 }; - }; - - class Interleaved - { - public: - inline Interleaved() noexcept : numInterleavedChannels (1) {} - inline Interleaved (const Interleaved& other) noexcept : numInterleavedChannels (other.numInterleavedChannels) {} - inline Interleaved (const int numInterleavedChans) noexcept : numInterleavedChannels (numInterleavedChans) {} - inline void copyFrom (const Interleaved& other) noexcept { numInterleavedChannels = other.numInterleavedChannels; } - template inline void advanceData (SampleFormatType& s) noexcept { s.skip (numInterleavedChannels); } - template inline void advanceDataBy (SampleFormatType& s, int numSamples) noexcept { s.skip (numInterleavedChannels * numSamples); } - template inline void clear (SampleFormatType& s, int numSamples) noexcept { while (--numSamples >= 0) { s.clear(); s.skip (numInterleavedChannels); } } - template inline int getNumBytesBetweenSamples (const SampleFormatType&) const noexcept { return numInterleavedChannels * SampleFormatType::bytesPerSample; } - int numInterleavedChannels; - enum { isInterleavedType = 1 }; - }; - - //============================================================================== - class NonConst - { - public: - typedef void VoidType; - static inline void* toVoidPtr (VoidType* v) noexcept { return v; } - enum { isConst = 0 }; - }; - - class Const - { - public: - typedef const void VoidType; - static inline void* toVoidPtr (VoidType* v) noexcept { return const_cast (v); } - enum { isConst = 1 }; - }; - #endif - - //============================================================================== - /** - A pointer to a block of audio data with a particular encoding. - - This object can be used to read and write from blocks of encoded audio samples. To create one, you specify - the audio format as a series of template parameters, e.g. - @code - // this creates a pointer for reading from a const array of 16-bit little-endian packed samples. - AudioData::Pointer pointer (someRawAudioData); - - // These methods read the sample that is being pointed to - float firstSampleAsFloat = pointer.getAsFloat(); - int32 firstSampleAsInt = pointer.getAsInt32(); - ++pointer; // moves the pointer to the next sample. - pointer += 3; // skips the next 3 samples. - @endcode - - The convertSamples() method lets you copy a range of samples from one format to another, automatically - converting its format. - - @see AudioData::Converter - */ - template - class Pointer : private InterleavingType // (inherited for EBCO) - { - public: - //============================================================================== - /** Creates a non-interleaved pointer from some raw data in the appropriate format. - This constructor is only used if you've specified the AudioData::NonInterleaved option - - for interleaved formats, use the constructor that also takes a number of channels. - */ - Pointer (typename Constness::VoidType* sourceData) noexcept - : data (Constness::toVoidPtr (sourceData)) - { - // If you're using interleaved data, call the other constructor! If you're using non-interleaved data, - // you should pass NonInterleaved as the template parameter for the interleaving type! - static_jassert (InterleavingType::isInterleavedType == 0); - } - - /** Creates a pointer from some raw data in the appropriate format with the specified number of interleaved channels. - For non-interleaved data, use the other constructor. - */ - Pointer (typename Constness::VoidType* sourceData, int numInterleaved) noexcept - : InterleavingType (numInterleaved), data (Constness::toVoidPtr (sourceData)) - { - } - - /** Creates a copy of another pointer. */ - Pointer (const Pointer& other) noexcept - : InterleavingType (other), data (other.data) - { - } - - Pointer& operator= (const Pointer& other) noexcept - { - InterleavingType::operator= (other); - data = other.data; - return *this; - } - - //============================================================================== - /** Returns the value of the first sample as a floating point value. - The value will be in the range -1.0 to 1.0 for integer formats. For floating point - formats, the value could be outside that range, although -1 to 1 is the standard range. - */ - inline float getAsFloat() const noexcept { return Endianness::getAsFloat (data); } - - /** Sets the value of the first sample as a floating point value. - - (This method can only be used if the AudioData::NonConst option was used). - The value should be in the range -1.0 to 1.0 - for integer formats, values outside that - range will be clipped. For floating point formats, any value passed in here will be - written directly, although -1 to 1 is the standard range. - */ - inline void setAsFloat (float newValue) noexcept - { - static_jassert (Constness::isConst == 0); // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead! - Endianness::setAsFloat (data, newValue); - } - - /** Returns the value of the first sample as a 32-bit integer. - The value returned will be in the range 0x80000000 to 0x7fffffff, and shorter values will be - shifted to fill this range (e.g. if you're reading from 24-bit data, the values will be shifted up - by 8 bits when returned here). If the source data is floating point, values beyond -1.0 to 1.0 will - be clipped so that -1.0 maps onto -0x7fffffff and 1.0 maps to 0x7fffffff. - */ - inline int32 getAsInt32() const noexcept { return Endianness::getAsInt32 (data); } - - /** Sets the value of the first sample as a 32-bit integer. - This will be mapped to the range of the format that is being written - see getAsInt32(). - */ - inline void setAsInt32 (int32 newValue) noexcept - { - static_jassert (Constness::isConst == 0); // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead! - Endianness::setAsInt32 (data, newValue); - } - - /** Moves the pointer along to the next sample. */ - inline Pointer& operator++() noexcept { advance(); return *this; } - - /** Moves the pointer back to the previous sample. */ - inline Pointer& operator--() noexcept { this->advanceDataBy (data, -1); return *this; } - - /** Adds a number of samples to the pointer's position. */ - Pointer& operator+= (int samplesToJump) noexcept { this->advanceDataBy (data, samplesToJump); return *this; } - - /** Writes a stream of samples into this pointer from another pointer. - This will copy the specified number of samples, converting between formats appropriately. - */ - void convertSamples (Pointer source, int numSamples) const noexcept - { - static_jassert (Constness::isConst == 0); // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead! - - for (Pointer dest (*this); --numSamples >= 0;) - { - dest.data.copyFromSameType (source.data); - dest.advance(); - source.advance(); - } - } - - /** Writes a stream of samples into this pointer from another pointer. - This will copy the specified number of samples, converting between formats appropriately. - */ - template - void convertSamples (OtherPointerType source, int numSamples) const noexcept - { - static_jassert (Constness::isConst == 0); // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead! - - Pointer dest (*this); - - if (source.getRawData() != getRawData() || source.getNumBytesBetweenSamples() >= getNumBytesBetweenSamples()) - { - while (--numSamples >= 0) - { - Endianness::copyFrom (dest.data, source); - dest.advance(); - ++source; - } - } - else // copy backwards if we're increasing the sample width.. - { - dest += numSamples; - source += numSamples; - - while (--numSamples >= 0) - Endianness::copyFrom ((--dest).data, --source); - } - } - - /** Sets a number of samples to zero. */ - void clearSamples (int numSamples) const noexcept - { - Pointer dest (*this); - dest.clear (dest.data, numSamples); - } - -#if 0 - /** Scans a block of data, returning the lowest and highest levels as floats */ - Range findMinAndMax (size_t numSamples) const noexcept - { - if (numSamples == 0) - return Range(); - - Pointer dest (*this); - - if (isFloatingPoint()) - { - float mn = dest.getAsFloat(); - dest.advance(); - float mx = mn; - - while (--numSamples > 0) - { - const float v = dest.getAsFloat(); - dest.advance(); - - if (mx < v) mx = v; - if (v < mn) mn = v; - } - - return Range (mn, mx); - } - - int32 mn = dest.getAsInt32(); - dest.advance(); - int32 mx = mn; - - while (--numSamples > 0) - { - const int v = dest.getAsInt32(); - dest.advance(); - - if (mx < v) mx = v; - if (v < mn) mn = v; - } - - return Range (mn * (float) (1.0 / (1.0 + Int32::maxValue)), - mx * (float) (1.0 / (1.0 + Int32::maxValue))); - } - - /** Scans a block of data, returning the lowest and highest levels as floats */ - void findMinAndMax (size_t numSamples, float& minValue, float& maxValue) const noexcept - { - Range r (findMinAndMax (numSamples)); - minValue = r.getStart(); - maxValue = r.getEnd(); - } -#endif - - /** Returns true if the pointer is using a floating-point format. */ - static bool isFloatingPoint() noexcept { return (bool) SampleFormat::isFloat; } - - /** Returns true if the format is big-endian. */ - static bool isBigEndian() noexcept { return (bool) Endianness::isBigEndian; } - - /** Returns the number of bytes in each sample (ignoring the number of interleaved channels). */ - static int getBytesPerSample() noexcept { return (int) SampleFormat::bytesPerSample; } - - /** Returns the number of interleaved channels in the format. */ - int getNumInterleavedChannels() const noexcept { return (int) this->numInterleavedChannels; } - - /** Returns the number of bytes between the start address of each sample. */ - int getNumBytesBetweenSamples() const noexcept { return InterleavingType::getNumBytesBetweenSamples (data); } - - /** Returns the accuracy of this format when represented as a 32-bit integer. - This is the smallest number above 0 that can be represented in the sample format, converted to - a 32-bit range. E,g. if the format is 8-bit, its resolution is 0x01000000; if the format is 24-bit, - its resolution is 0x100. - */ - static int get32BitResolution() noexcept { return (int) SampleFormat::resolution; } - - /** Returns a pointer to the underlying data. */ - const void* getRawData() const noexcept { return data.data; } - - private: - //============================================================================== - SampleFormat data; - - inline void advance() noexcept { this->advanceData (data); } - - Pointer operator++ (int); // private to force you to use the more efficient pre-increment! - Pointer operator-- (int); - }; - - //============================================================================== - /** A base class for objects that are used to convert between two different sample formats. - - The AudioData::ConverterInstance implements this base class and can be templated, so - you can create an instance that converts between two particular formats, and then - store this in the abstract base class. - - @see AudioData::ConverterInstance - */ - class Converter - { - public: - virtual ~Converter() {} - - /** Converts a sequence of samples from the converter's source format into the dest format. */ - virtual void convertSamples (void* destSamples, const void* sourceSamples, int numSamples) const = 0; - - /** Converts a sequence of samples from the converter's source format into the dest format. - This method takes sub-channel indexes, which can be used with interleaved formats in order to choose a - particular sub-channel of the data to be used. - */ - virtual void convertSamples (void* destSamples, int destSubChannel, - const void* sourceSamples, int sourceSubChannel, int numSamples) const = 0; - }; - - //============================================================================== - /** - A class that converts between two templated AudioData::Pointer types, and which - implements the AudioData::Converter interface. - - This can be used as a concrete instance of the AudioData::Converter abstract class. - - @see AudioData::Converter - */ - template - class ConverterInstance : public Converter - { - public: - ConverterInstance (int numSourceChannels = 1, int numDestChannels = 1) - : sourceChannels (numSourceChannels), destChannels (numDestChannels) - {} - - void convertSamples (void* dest, const void* source, int numSamples) const override - { - SourceSampleType s (source, sourceChannels); - DestSampleType d (dest, destChannels); - d.convertSamples (s, numSamples); - } - - void convertSamples (void* dest, int destSubChannel, - const void* source, int sourceSubChannel, int numSamples) const override - { - jassert (destSubChannel < destChannels && sourceSubChannel < sourceChannels); - - SourceSampleType s (addBytesToPointer (source, sourceSubChannel * SourceSampleType::getBytesPerSample()), sourceChannels); - DestSampleType d (addBytesToPointer (dest, destSubChannel * DestSampleType::getBytesPerSample()), destChannels); - d.convertSamples (s, numSamples); - } - - private: - const int sourceChannels, destChannels; - - CARLA_DECLARE_NON_COPY_CLASS (ConverterInstance) - }; -}; - - - -//============================================================================== -/** - A set of routines to convert buffers of 32-bit floating point data to and from - various integer formats. - - Note that these functions are deprecated - the AudioData class provides a much more - flexible set of conversion classes now. -*/ -class AudioDataConverters -{ -public: - //============================================================================== - static void convertFloatToInt16LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 2); - static void convertFloatToInt16BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 2); - - static void convertFloatToInt24LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 3); - static void convertFloatToInt24BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 3); - - static void convertFloatToInt32LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4); - static void convertFloatToInt32BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4); - - static void convertFloatToFloat32LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4); - static void convertFloatToFloat32BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4); - - //============================================================================== - static void convertInt16LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 2); - static void convertInt16BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 2); - - static void convertInt24LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 3); - static void convertInt24BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 3); - - static void convertInt32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4); - static void convertInt32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4); - - static void convertFloat32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4); - static void convertFloat32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4); - - //============================================================================== - enum DataFormat - { - int16LE, - int16BE, - int24LE, - int24BE, - int32LE, - int32BE, - float32LE, - float32BE, - }; - - static void convertFloatToFormat (DataFormat destFormat, - const float* source, void* dest, int numSamples); - - static void convertFormatToFloat (DataFormat sourceFormat, - const void* source, float* dest, int numSamples); - - //============================================================================== - static void interleaveSamples (const float** source, float* dest, - int numSamples, int numChannels); - - static void deinterleaveSamples (const float* source, float** dest, - int numSamples, int numChannels); - -private: - AudioDataConverters(); - CARLA_DECLARE_NON_COPY_CLASS (AudioDataConverters) -}; - -} - -#endif // WATER_AUDIODATACONVERTERS_H_INCLUDED diff --git a/source/modules/water/maths/BigInteger.cpp b/source/modules/water/maths/BigInteger.cpp index bf104c0f4..d3a8b925c 100644 --- a/source/modules/water/maths/BigInteger.cpp +++ b/source/modules/water/maths/BigInteger.cpp @@ -160,7 +160,7 @@ uint32* BigInteger::ensureSize (const size_t numVals) noexcept //============================================================================== bool BigInteger::operator[] (const int bit) const noexcept { - if (bit > highestBit || bit < 0) + if (bit < 0 || bit > highestBit) return false; if (const uint32* const values = getValues()) @@ -182,6 +182,9 @@ void BigInteger::clear() noexcept bool BigInteger::setBit (const int bit) noexcept { + if (bit < 0) + return false; + CARLA_SAFE_ASSERT_RETURN(bit >= 0, false); if (bit > highestBit) @@ -213,7 +216,8 @@ bool BigInteger::setBit (const int bit, const bool shouldBeSet) noexcept bool BigInteger::clearBit (const int bit) noexcept { - CARLA_SAFE_ASSERT_RETURN(bit <= highestBit && bit >= 0, false); + if (bit < 0 || bit > highestBit) + return false; uint32* const values = getValues(); CARLA_SAFE_ASSERT_RETURN(values != nullptr, false); diff --git a/source/modules/water/text/StringPairArray.cpp b/source/modules/water/text/StringPairArray.cpp deleted file mode 100644 index 4b216e4c8..000000000 --- a/source/modules/water/text/StringPairArray.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - ============================================================================== - - This file is part of the Water library. - Copyright (c) 2016 ROLI Ltd. - Copyright (C) 2018 Filipe Coelho - - Permission is granted to use this software under the terms of the ISC license - http://www.isc.org/downloads/software-support-policy/isc-license/ - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD - TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, - OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - OF THIS SOFTWARE. - - ============================================================================== -*/ - -#include "StringPairArray.h" - -namespace water { - -StringPairArray::StringPairArray (const bool ignoreCase_) - : ignoreCase (ignoreCase_) -{ -} - -StringPairArray::StringPairArray (const StringPairArray& other) - : keys (other.keys), - values (other.values), - ignoreCase (other.ignoreCase) -{ -} - -StringPairArray::~StringPairArray() -{ -} - -StringPairArray& StringPairArray::operator= (const StringPairArray& other) -{ - keys = other.keys; - values = other.values; - return *this; -} - -bool StringPairArray::operator== (const StringPairArray& other) const -{ - for (int i = keys.size(); --i >= 0;) - if (other [keys[i]] != values[i]) - return false; - - return true; -} - -bool StringPairArray::operator!= (const StringPairArray& other) const -{ - return ! operator== (other); -} - -const String& StringPairArray::operator[] (StringRef key) const -{ - return values [keys.indexOf (key, ignoreCase)]; -} - -String StringPairArray::getValue (StringRef key, const String& defaultReturnValue) const -{ - const int i = keys.indexOf (key, ignoreCase); - - if (i >= 0) - return values[i]; - - return defaultReturnValue; -} - -bool StringPairArray::containsKey (StringRef key) const noexcept -{ - return keys.contains (key); -} - -void StringPairArray::set (const String& key, const String& value) -{ - const int i = keys.indexOf (key, ignoreCase); - - if (i >= 0) - { - values.set (i, value); - } - else - { - keys.add (key); - values.add (value); - } -} - -void StringPairArray::addArray (const StringPairArray& other) -{ - for (int i = 0; i < other.size(); ++i) - set (other.keys[i], other.values[i]); -} - -void StringPairArray::clear() -{ - keys.clear(); - values.clear(); -} - -void StringPairArray::remove (StringRef key) -{ - remove (keys.indexOf (key, ignoreCase)); -} - -void StringPairArray::remove (const int index) -{ - keys.remove (index); - values.remove (index); -} - -void StringPairArray::setIgnoresCase (const bool shouldIgnoreCase) -{ - ignoreCase = shouldIgnoreCase; -} - -String StringPairArray::getDescription() const -{ - String s; - - for (int i = 0; i < keys.size(); ++i) - { - s << keys[i] << " = " << values[i]; - if (i < keys.size()) - s << ", "; - } - - return s; -} - -void StringPairArray::minimiseStorageOverheads() -{ - keys.minimiseStorageOverheads(); - values.minimiseStorageOverheads(); -} - -} diff --git a/source/modules/water/text/StringPairArray.h b/source/modules/water/text/StringPairArray.h deleted file mode 100644 index 4c4a64f1e..000000000 --- a/source/modules/water/text/StringPairArray.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - ============================================================================== - - This file is part of the Water library. - Copyright (c) 2016 ROLI Ltd. - Copyright (C) 2018 Filipe Coelho - - Permission is granted to use this software under the terms of the ISC license - http://www.isc.org/downloads/software-support-policy/isc-license/ - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD - TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, - OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - OF THIS SOFTWARE. - - ----------------------------------------------------------------------------- - - To release a closed-source product which uses other parts of JUCE not - licensed under the ISC terms, commercial licenses are available: visit - www.juce.com for more information. - - ============================================================================== -*/ - -#ifndef JUCE_STRINGPAIRARRAY_H_INCLUDED -#define JUCE_STRINGPAIRARRAY_H_INCLUDED - -#include "StringArray.h" -#include "StringRef.h" - -namespace water { - -//============================================================================== -/** - A container for holding a set of strings which are keyed by another string. - - @see StringArray -*/ -class StringPairArray -{ -public: - //============================================================================== - /** Creates an empty array */ - StringPairArray (bool ignoreCaseWhenComparingKeys = true); - - /** Creates a copy of another array */ - StringPairArray (const StringPairArray& other); - - /** Destructor. */ - ~StringPairArray(); - - /** Copies the contents of another string array into this one */ - StringPairArray& operator= (const StringPairArray& other); - - //============================================================================== - /** Compares two arrays. - Comparisons are case-sensitive. - @returns true only if the other array contains exactly the same strings with the same keys - */ - bool operator== (const StringPairArray& other) const; - - /** Compares two arrays. - Comparisons are case-sensitive. - @returns false if the other array contains exactly the same strings with the same keys - */ - bool operator!= (const StringPairArray& other) const; - - //============================================================================== - /** Finds the value corresponding to a key string. - - If no such key is found, this will just return an empty string. To check whether - a given key actually exists (because it might actually be paired with an empty string), use - the getAllKeys() method to obtain a list. - - Obviously the reference returned shouldn't be stored for later use, as the - string it refers to may disappear when the array changes. - - @see getValue - */ - const String& operator[] (StringRef key) const; - - /** Finds the value corresponding to a key string. - If no such key is found, this will just return the value provided as a default. - @see operator[] - */ - String getValue (StringRef, const String& defaultReturnValue) const; - - /** Returns true if the given key exists. */ - bool containsKey (StringRef key) const noexcept; - - /** Returns a list of all keys in the array. */ - const StringArray& getAllKeys() const noexcept { return keys; } - - /** Returns a list of all values in the array. */ - const StringArray& getAllValues() const noexcept { return values; } - - /** Returns the number of strings in the array */ - inline int size() const noexcept { return keys.size(); }; - - - //============================================================================== - /** Adds or amends a key/value pair. - If a value already exists with this key, its value will be overwritten, - otherwise the key/value pair will be added to the array. - */ - void set (const String& key, const String& value); - - /** Adds the items from another array to this one. - This is equivalent to using set() to add each of the pairs from the other array. - */ - void addArray (const StringPairArray& other); - - //============================================================================== - /** Removes all elements from the array. */ - void clear(); - - /** Removes a string from the array based on its key. - If the key isn't found, nothing will happen. - */ - void remove (StringRef key); - - /** Removes a string from the array based on its index. - If the index is out-of-range, no action will be taken. - */ - void remove (int index); - - //============================================================================== - /** Indicates whether to use a case-insensitive search when looking up a key string. - */ - void setIgnoresCase (bool shouldIgnoreCase); - - //============================================================================== - /** Returns a descriptive string containing the items. - This is handy for dumping the contents of an array. - */ - String getDescription() const; - - //============================================================================== - /** Reduces the amount of storage being used by the array. - - Arrays typically allocate slightly more storage than they need, and after - removing elements, they may have quite a lot of unused space allocated. - This method will reduce the amount of allocated storage to a minimum. - */ - void minimiseStorageOverheads(); - - -private: - //============================================================================== - StringArray keys, values; - bool ignoreCase; - - CARLA_LEAK_DETECTOR (StringPairArray) -}; - -} - -#endif // JUCE_STRINGPAIRARRAY_H_INCLUDED diff --git a/source/modules/water/water.cpp b/source/modules/water/water.cpp index 9c9907463..a7d10e12b 100644 --- a/source/modules/water/water.cpp +++ b/source/modules/water/water.cpp @@ -36,14 +36,6 @@ HINSTANCE water_getCurrentModuleInstanceHandle() noexcept } -#include "audiocodecs/WavAudioFormat.cpp" - -#include "audioformat/AudioFormat.cpp" -#include "audioformat/AudioFormatManager.cpp" -#include "audioformat/AudioFormatReader.cpp" - -#include "buffers/AudioDataConverters.cpp" - #include "containers/NamedValueSet.cpp" #include "containers/Variant.cpp" @@ -80,7 +72,6 @@ HINSTANCE water_getCurrentModuleInstanceHandle() noexcept #include "text/CharacterFunctions.cpp" #include "text/Identifier.cpp" #include "text/StringArray.cpp" -#include "text/StringPairArray.cpp" #include "text/StringPool.cpp" #include "text/String.cpp" diff --git a/source/modules/water/water.h b/source/modules/water/water.h index 182d58ae6..67bbc4877 100644 --- a/source/modules/water/water.h +++ b/source/modules/water/water.h @@ -84,8 +84,6 @@ namespace water { -class AudioFormatManager; -class AudioFormatReader; class AudioProcessor; class AudioSampleBuffer; class File;