diff options
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/soundlib/SampleIO.h')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/soundlib/SampleIO.h | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/soundlib/SampleIO.h b/Src/external_dependencies/openmpt-trunk/soundlib/SampleIO.h new file mode 100644 index 00000000..416a6035 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/soundlib/SampleIO.h @@ -0,0 +1,256 @@ +/* + * SampleIO.h + * ---------- + * Purpose: Central code for reading and writing samples. Create your SampleIO object and have a go at the ReadSample and WriteSample functions! + * Notes : Not all combinations of possible sample format combinations are implemented, especially for WriteSample. + * Using the existing generic sample conversion functors in SampleFormatConverters.h, it should be quite easy to extend the code, though. + * Authors: Olivier Lapicque + * OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#pragma once + +#include "openmpt/all/BuildSettings.hpp" + + +#include "../common/FileReaderFwd.h" + + +OPENMPT_NAMESPACE_BEGIN + + +struct ModSample; + +// Sample import / export formats +class SampleIO +{ +public: + // Bits per sample + enum Bitdepth : uint8 + { + _8bit = 8, + _16bit = 16, + _24bit = 24, + _32bit = 32, + _64bit = 64, + }; + + // Number of channels + channel format + enum Channels : uint8 + { + mono = 1, + stereoInterleaved, // LRLRLR... + stereoSplit, // LLL...RRR... + }; + + // Sample byte order + enum Endianness : uint8 + { + littleEndian = 0, + bigEndian = 1, + }; + + // Sample encoding + enum Encoding : uint8 + { + signedPCM = 0, // Integer PCM, signed + unsignedPCM, // Integer PCM, unsigned + deltaPCM, // Integer PCM, delta-encoded + floatPCM, // Floating point PCM + IT214, // Impulse Tracker 2.14 compressed + IT215, // Impulse Tracker 2.15 compressed + AMS, // AMS / Velvet Studio packed + DMF, // DMF Huffman compression + MDL, // MDL Huffman compression + PTM8Dto16, // PTM 8-Bit delta value -> 16-Bit sample + ADPCM, // 4-Bit ADPCM-packed + MT2, // MadTracker 2 stereo delta encoding + floatPCM15, // Floating point PCM with 2^15 full scale + floatPCM23, // Floating point PCM with 2^23 full scale + floatPCMnormalize, // Floating point PCM and data will be normalized while reading + signedPCMnormalize, // Integer PCM and data will be normalized while reading + uLaw, // 8-to-16 bit G.711 u-law compression + aLaw, // 8-to-16 bit G.711 a-law compression + }; + +protected: + Bitdepth m_bitdepth; + Channels m_channels; + Endianness m_endianness; + Encoding m_encoding; + +public: + constexpr SampleIO(Bitdepth bits = _8bit, Channels channels = mono, Endianness endianness = littleEndian, Encoding encoding = signedPCM) + : m_bitdepth(bits), m_channels(channels), m_endianness(endianness), m_encoding(encoding) + { } + + bool operator== (const SampleIO &other) const + { + return memcmp(this, &other, sizeof(*this)) == 0; + } + + bool operator!= (const SampleIO &other) const + { + return memcmp(this, &other, sizeof(*this)) != 0; + } + + void operator|= (Bitdepth bits) + { + m_bitdepth = bits; + } + + void operator|= (Channels channels) + { + m_channels = channels; + } + + void operator|= (Endianness endianness) + { + m_endianness = endianness; + } + + void operator|= (Encoding encoding) + { + m_encoding = encoding; + } + + void MayNormalize() + { + if(GetBitDepth() >= 24) + { + if(GetEncoding() == SampleIO::signedPCM) + { + m_encoding = SampleIO::signedPCMnormalize; + } else if(GetEncoding() == SampleIO::floatPCM) + { + m_encoding = SampleIO::floatPCMnormalize; + } + } + } + + // Return 0 in case of variable-length encoded samples. + MPT_CONSTEXPRINLINE uint8 GetEncodedBitsPerSample() const + { + switch(GetEncoding()) + { + case signedPCM: // Integer PCM, signed + case unsignedPCM: //Integer PCM, unsigned + case deltaPCM: // Integer PCM, delta-encoded + case floatPCM: // Floating point PCM + case MT2: // MadTracker 2 stereo delta encoding + case floatPCM15: // Floating point PCM with 2^15 full scale + case floatPCM23: // Floating point PCM with 2^23 full scale + case floatPCMnormalize: // Floating point PCM and data will be normalized while reading + case signedPCMnormalize: // Integer PCM and data will be normalized while reading + return GetBitDepth(); + + case IT214: // Impulse Tracker 2.14 compressed + case IT215: // Impulse Tracker 2.15 compressed + case AMS: // AMS / Velvet Studio packed + case DMF: // DMF Huffman compression + case MDL: // MDL Huffman compression + return 0; // variable-length compressed + + case PTM8Dto16: // PTM 8-Bit delta value -> 16-Bit sample + return 16; + case ADPCM: // 4-Bit ADPCM-packed + return 4; + case uLaw: // G.711 u-law + return 8; + case aLaw: // G.711 a-law + return 8; + + default: + return 0; + } + } + + // Return the static header size additional to the raw encoded sample data. + MPT_CONSTEXPRINLINE std::size_t GetEncodedHeaderSize() const + { + switch(GetEncoding()) + { + case ADPCM: + return 16; + default: + return 0; + } + } + + // Returns true if the encoded size cannot be calculated apriori from the encoding format and the sample length. + MPT_CONSTEXPRINLINE bool IsVariableLengthEncoded() const + { + return GetEncodedBitsPerSample() == 0; + } + + // Returns true if the decoder for a given format uses FileReader interface and thus do not need to call GetPinnedView() + MPT_CONSTEXPRINLINE bool UsesFileReaderForDecoding() const + { + switch(GetEncoding()) + { + case IT214: + case IT215: + case AMS: + case DMF: + case MDL: + return true; + default: + return false; + } + } + + // Get bits per sample + constexpr uint8 GetBitDepth() const + { + return static_cast<uint8>(m_bitdepth); + } + // Get channel layout + constexpr Channels GetChannelFormat() const + { + return m_channels; + } + // Get number of channels + constexpr uint8 GetNumChannels() const + { + return GetChannelFormat() == mono ? 1u : 2u; + } + // Get sample byte order + constexpr Endianness GetEndianness() const + { + return m_endianness; + } + // Get sample format / encoding + constexpr Encoding GetEncoding() const + { + return m_encoding; + } + + // Returns the encoded size of the sample. In case of variable-length encoding returns 0. + std::size_t CalculateEncodedSize(SmpLength length) const + { + if(IsVariableLengthEncoded()) + { + return 0; + } + uint8 bps = GetEncodedBitsPerSample(); + if(bps % 8u != 0) + { + MPT_ASSERT(GetEncoding() == ADPCM && bps == 4); + return GetEncodedHeaderSize() + (((length + 1) / 2) * GetNumChannels()); // round up + } + return GetEncodedHeaderSize() + (length * (bps / 8) * GetNumChannels()); + } + + // Read a sample from memory + size_t ReadSample(ModSample &sample, FileReader &file) const; + +#ifndef MODPLUG_NO_FILESAVE + // Write a sample to file + size_t WriteSample(std::ostream &f, const ModSample &sample, SmpLength maxSamples = 0) const; +#endif // MODPLUG_NO_FILESAVE +}; + + +OPENMPT_NAMESPACE_END |