winamp/Src/external_dependencies/openmpt-trunk/soundlib/ModSample.h
2024-09-24 14:54:57 +02:00

175 lines
6.5 KiB
C++

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