diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/soundlib/ModSample.h | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/soundlib/ModSample.h')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/soundlib/ModSample.h | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/soundlib/ModSample.h b/Src/external_dependencies/openmpt-trunk/soundlib/ModSample.h new file mode 100644 index 00000000..07a2e1f4 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/soundlib/ModSample.h @@ -0,0 +1,175 @@ +/* + * ModSample.h + * ----------- + * Purpose: Module Sample header class and helpers + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#pragma once + +#include "openmpt/all/BuildSettings.hpp" + +OPENMPT_NAMESPACE_BEGIN + +class CSoundFile; + +// Sample Struct +struct ModSample +{ + SmpLength nLength; // In frames + SmpLength nLoopStart, nLoopEnd; // Ditto + SmpLength nSustainStart, nSustainEnd; // Ditto + union + { + void *pSample; // Pointer to sample data + int8 *pSample8; // Pointer to 8-bit sample data + int16 *pSample16; // Pointer to 16-bit sample data + } pData; + uint32 nC5Speed; // Frequency of middle-C, in Hz (for IT/S3M/MPTM) + uint16 nPan; // Default sample panning (if pan flag is set), 0...256 + uint16 nVolume; // Default volume, 0...256 (ignored if uFlags[SMP_NODEFAULTVOLUME] is set) + uint16 nGlobalVol; // Global volume (sample volume is multiplied by this), 0...64 + SampleFlags uFlags; // Sample flags (see ChannelFlags enum) + int8 RelativeTone; // Relative note to middle c (for MOD/XM) + int8 nFineTune; // Finetune period (for MOD/XM), -128...127, unit is 1/128th of a semitone + VibratoType nVibType; // Auto vibrato type + uint8 nVibSweep; // Auto vibrato sweep (i.e. how long it takes until the vibrato effect reaches its full depth) + uint8 nVibDepth; // Auto vibrato depth + uint8 nVibRate; // Auto vibrato rate (speed) + uint8 rootNote; // For multisample import + + //char name[MAX_SAMPLENAME]; // Maybe it would be nicer to have sample names here, but that would require some refactoring. + mpt::charbuf<MAX_SAMPLEFILENAME> filename; + std::string GetFilename() const { return filename; } + + union + { + std::array<SmpLength, 9> cues; + OPLPatch adlib; + }; + + ModSample(MODTYPE type = MOD_TYPE_NONE) + { + pData.pSample = nullptr; + Initialize(type); + } + + bool HasSampleData() const noexcept + { + MPT_ASSERT(!pData.pSample || (pData.pSample && nLength > 0)); // having sample pointer implies non-zero sample length + return pData.pSample != nullptr && nLength != 0; + } + + MPT_FORCEINLINE const void *samplev() const noexcept + { + return pData.pSample; + } + MPT_FORCEINLINE void *samplev() noexcept + { + return pData.pSample; + } + MPT_FORCEINLINE const std::byte *sampleb() const noexcept + { + return mpt::void_cast<const std::byte*>(pData.pSample); + } + MPT_FORCEINLINE std::byte *sampleb() noexcept + { + return mpt::void_cast<std::byte*>(pData.pSample); + } + MPT_FORCEINLINE const int8 *sample8() const noexcept + { + MPT_ASSERT(GetElementarySampleSize() == sizeof(int8)); + return pData.pSample8; + } + MPT_FORCEINLINE int8 *sample8() noexcept + { + MPT_ASSERT(GetElementarySampleSize() == sizeof(int8)); + return pData.pSample8; + } + MPT_FORCEINLINE const int16 *sample16() const noexcept + { + MPT_ASSERT(GetElementarySampleSize() == sizeof(int16)); + return pData.pSample16; + } + MPT_FORCEINLINE int16 *sample16() noexcept + { + MPT_ASSERT(GetElementarySampleSize() == sizeof(int16)); + return pData.pSample16; + } + + // Return the size of one (elementary) sample in bytes. + uint8 GetElementarySampleSize() const noexcept { return (uFlags & CHN_16BIT) ? 2 : 1; } + + // Return the number of channels in the sample. + uint8 GetNumChannels() const noexcept { return (uFlags & CHN_STEREO) ? 2 : 1; } + + // Return the number of bytes per frame (Channels * Elementary Sample Size) + uint8 GetBytesPerSample() const noexcept { return GetElementarySampleSize() * GetNumChannels(); } + + // Return the size which pSample is at least. + SmpLength GetSampleSizeInBytes() const noexcept { return nLength * GetBytesPerSample(); } + + // Returns sample rate of the sample. The argument is needed because + // the sample rate is obtained differently for different module types. + uint32 GetSampleRate(const MODTYPE type) const; + + // Translate sample properties between two given formats. + void Convert(MODTYPE fromType, MODTYPE toType); + + // Initialize sample slot with default values. + void Initialize(MODTYPE type = MOD_TYPE_NONE); + + // Copies sample data from another sample slot and ensures that the 16-bit/stereo flags are set accordingly. + bool CopyWaveform(const ModSample &smpFrom); + + // Allocate sample based on a ModSample's properties. + // Returns number of bytes allocated, 0 on failure. + size_t AllocateSample(); + // Allocate sample memory. On sucess, a pointer to the silenced sample buffer is returned. On failure, nullptr is returned. + static void *AllocateSample(SmpLength numFrames, size_t bytesPerSample); + // Compute sample buffer size in bytes, including any overhead introduced by pre-computed loops and such. Returns 0 if sample is too big. + static size_t GetRealSampleBufferSize(SmpLength numSamples, size_t bytesPerSample); + + void FreeSample(); + static void FreeSample(void *samplePtr); + + // Set loop points and update loop wrap-around buffer + void SetLoop(SmpLength start, SmpLength end, bool enable, bool pingpong, CSoundFile &sndFile); + // Set sustain loop points and update loop wrap-around buffer + void SetSustainLoop(SmpLength start, SmpLength end, bool enable, bool pingpong, CSoundFile &sndFile); + // Update loop wrap-around buffer + void PrecomputeLoops(CSoundFile &sndFile, bool updateChannels = true); + + constexpr bool HasLoop() const noexcept { return uFlags[CHN_LOOP] && nLoopEnd > nLoopStart; } + constexpr bool HasSustainLoop() const noexcept { return uFlags[CHN_SUSTAINLOOP] && nSustainEnd > nSustainStart; } + constexpr bool HasPingPongLoop() const noexcept { return uFlags.test_all(CHN_LOOP | CHN_PINGPONGLOOP) && nLoopEnd > nLoopStart; } + constexpr bool HasPingPongSustainLoop() const noexcept { return uFlags.test_all(CHN_SUSTAINLOOP | CHN_PINGPONGSUSTAIN) && nSustainEnd > nSustainStart; } + + // Remove loop points if they're invalid. + void SanitizeLoops(); + + // Transpose <-> Frequency conversions + static uint32 TransposeToFrequency(int transpose, int finetune = 0); + void TransposeToFrequency(); + static std::pair<int8, int8> FrequencyToTranspose(uint32 freq); + void FrequencyToTranspose(); + + // Transpose the sample by amount specified in octaves (i.e. amount=1 transposes one octave up) + void Transpose(double amount); + + // Check if the sample has any valid cue points + bool HasAnyCuePoints() const; + // Check if the sample's cue points are the default cue point set. + bool HasCustomCuePoints() const; + void SetDefaultCuePoints(); + // Set cue points so that they are suitable for regular offset command extension + void Set16BitCuePoints(); + void RemoveAllCuePoints(); + + void SetAdlib(bool enable, OPLPatch patch = OPLPatch{{}}); +}; + +OPENMPT_NAMESPACE_END |