123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- /*
- * 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
|