ModSample.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * ModSample.h
  3. * -----------
  4. * Purpose: Module Sample header class and helpers
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. OPENMPT_NAMESPACE_BEGIN
  12. class CSoundFile;
  13. // Sample Struct
  14. struct ModSample
  15. {
  16. SmpLength nLength; // In frames
  17. SmpLength nLoopStart, nLoopEnd; // Ditto
  18. SmpLength nSustainStart, nSustainEnd; // Ditto
  19. union
  20. {
  21. void *pSample; // Pointer to sample data
  22. int8 *pSample8; // Pointer to 8-bit sample data
  23. int16 *pSample16; // Pointer to 16-bit sample data
  24. } pData;
  25. uint32 nC5Speed; // Frequency of middle-C, in Hz (for IT/S3M/MPTM)
  26. uint16 nPan; // Default sample panning (if pan flag is set), 0...256
  27. uint16 nVolume; // Default volume, 0...256 (ignored if uFlags[SMP_NODEFAULTVOLUME] is set)
  28. uint16 nGlobalVol; // Global volume (sample volume is multiplied by this), 0...64
  29. SampleFlags uFlags; // Sample flags (see ChannelFlags enum)
  30. int8 RelativeTone; // Relative note to middle c (for MOD/XM)
  31. int8 nFineTune; // Finetune period (for MOD/XM), -128...127, unit is 1/128th of a semitone
  32. VibratoType nVibType; // Auto vibrato type
  33. uint8 nVibSweep; // Auto vibrato sweep (i.e. how long it takes until the vibrato effect reaches its full depth)
  34. uint8 nVibDepth; // Auto vibrato depth
  35. uint8 nVibRate; // Auto vibrato rate (speed)
  36. uint8 rootNote; // For multisample import
  37. //char name[MAX_SAMPLENAME]; // Maybe it would be nicer to have sample names here, but that would require some refactoring.
  38. mpt::charbuf<MAX_SAMPLEFILENAME> filename;
  39. std::string GetFilename() const { return filename; }
  40. union
  41. {
  42. std::array<SmpLength, 9> cues;
  43. OPLPatch adlib;
  44. };
  45. ModSample(MODTYPE type = MOD_TYPE_NONE)
  46. {
  47. pData.pSample = nullptr;
  48. Initialize(type);
  49. }
  50. bool HasSampleData() const noexcept
  51. {
  52. MPT_ASSERT(!pData.pSample || (pData.pSample && nLength > 0)); // having sample pointer implies non-zero sample length
  53. return pData.pSample != nullptr && nLength != 0;
  54. }
  55. MPT_FORCEINLINE const void *samplev() const noexcept
  56. {
  57. return pData.pSample;
  58. }
  59. MPT_FORCEINLINE void *samplev() noexcept
  60. {
  61. return pData.pSample;
  62. }
  63. MPT_FORCEINLINE const std::byte *sampleb() const noexcept
  64. {
  65. return mpt::void_cast<const std::byte*>(pData.pSample);
  66. }
  67. MPT_FORCEINLINE std::byte *sampleb() noexcept
  68. {
  69. return mpt::void_cast<std::byte*>(pData.pSample);
  70. }
  71. MPT_FORCEINLINE const int8 *sample8() const noexcept
  72. {
  73. MPT_ASSERT(GetElementarySampleSize() == sizeof(int8));
  74. return pData.pSample8;
  75. }
  76. MPT_FORCEINLINE int8 *sample8() noexcept
  77. {
  78. MPT_ASSERT(GetElementarySampleSize() == sizeof(int8));
  79. return pData.pSample8;
  80. }
  81. MPT_FORCEINLINE const int16 *sample16() const noexcept
  82. {
  83. MPT_ASSERT(GetElementarySampleSize() == sizeof(int16));
  84. return pData.pSample16;
  85. }
  86. MPT_FORCEINLINE int16 *sample16() noexcept
  87. {
  88. MPT_ASSERT(GetElementarySampleSize() == sizeof(int16));
  89. return pData.pSample16;
  90. }
  91. // Return the size of one (elementary) sample in bytes.
  92. uint8 GetElementarySampleSize() const noexcept { return (uFlags & CHN_16BIT) ? 2 : 1; }
  93. // Return the number of channels in the sample.
  94. uint8 GetNumChannels() const noexcept { return (uFlags & CHN_STEREO) ? 2 : 1; }
  95. // Return the number of bytes per frame (Channels * Elementary Sample Size)
  96. uint8 GetBytesPerSample() const noexcept { return GetElementarySampleSize() * GetNumChannels(); }
  97. // Return the size which pSample is at least.
  98. SmpLength GetSampleSizeInBytes() const noexcept { return nLength * GetBytesPerSample(); }
  99. // Returns sample rate of the sample. The argument is needed because
  100. // the sample rate is obtained differently for different module types.
  101. uint32 GetSampleRate(const MODTYPE type) const;
  102. // Translate sample properties between two given formats.
  103. void Convert(MODTYPE fromType, MODTYPE toType);
  104. // Initialize sample slot with default values.
  105. void Initialize(MODTYPE type = MOD_TYPE_NONE);
  106. // Copies sample data from another sample slot and ensures that the 16-bit/stereo flags are set accordingly.
  107. bool CopyWaveform(const ModSample &smpFrom);
  108. // Allocate sample based on a ModSample's properties.
  109. // Returns number of bytes allocated, 0 on failure.
  110. size_t AllocateSample();
  111. // Allocate sample memory. On sucess, a pointer to the silenced sample buffer is returned. On failure, nullptr is returned.
  112. static void *AllocateSample(SmpLength numFrames, size_t bytesPerSample);
  113. // Compute sample buffer size in bytes, including any overhead introduced by pre-computed loops and such. Returns 0 if sample is too big.
  114. static size_t GetRealSampleBufferSize(SmpLength numSamples, size_t bytesPerSample);
  115. void FreeSample();
  116. static void FreeSample(void *samplePtr);
  117. // Set loop points and update loop wrap-around buffer
  118. void SetLoop(SmpLength start, SmpLength end, bool enable, bool pingpong, CSoundFile &sndFile);
  119. // Set sustain loop points and update loop wrap-around buffer
  120. void SetSustainLoop(SmpLength start, SmpLength end, bool enable, bool pingpong, CSoundFile &sndFile);
  121. // Update loop wrap-around buffer
  122. void PrecomputeLoops(CSoundFile &sndFile, bool updateChannels = true);
  123. constexpr bool HasLoop() const noexcept { return uFlags[CHN_LOOP] && nLoopEnd > nLoopStart; }
  124. constexpr bool HasSustainLoop() const noexcept { return uFlags[CHN_SUSTAINLOOP] && nSustainEnd > nSustainStart; }
  125. constexpr bool HasPingPongLoop() const noexcept { return uFlags.test_all(CHN_LOOP | CHN_PINGPONGLOOP) && nLoopEnd > nLoopStart; }
  126. constexpr bool HasPingPongSustainLoop() const noexcept { return uFlags.test_all(CHN_SUSTAINLOOP | CHN_PINGPONGSUSTAIN) && nSustainEnd > nSustainStart; }
  127. // Remove loop points if they're invalid.
  128. void SanitizeLoops();
  129. // Transpose <-> Frequency conversions
  130. static uint32 TransposeToFrequency(int transpose, int finetune = 0);
  131. void TransposeToFrequency();
  132. static std::pair<int8, int8> FrequencyToTranspose(uint32 freq);
  133. void FrequencyToTranspose();
  134. // Transpose the sample by amount specified in octaves (i.e. amount=1 transposes one octave up)
  135. void Transpose(double amount);
  136. // Check if the sample has any valid cue points
  137. bool HasAnyCuePoints() const;
  138. // Check if the sample's cue points are the default cue point set.
  139. bool HasCustomCuePoints() const;
  140. void SetDefaultCuePoints();
  141. // Set cue points so that they are suitable for regular offset command extension
  142. void Set16BitCuePoints();
  143. void RemoveAllCuePoints();
  144. void SetAdlib(bool enable, OPLPatch patch = OPLPatch{{}});
  145. };
  146. OPENMPT_NAMESPACE_END