1
0

Dlsbank.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * DLSBank.h
  3. * ---------
  4. * Purpose: Sound bank loading.
  5. * Notes : Supported sound bank types: DLS (including embedded DLS in MSS & RMI), SF2
  6. * Authors: Olivier Lapicque
  7. * OpenMPT Devs
  8. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  9. */
  10. #pragma once
  11. #include "openmpt/all/BuildSettings.hpp"
  12. OPENMPT_NAMESPACE_BEGIN
  13. class CSoundFile;
  14. OPENMPT_NAMESPACE_END
  15. #include "Snd_defs.h"
  16. OPENMPT_NAMESPACE_BEGIN
  17. #ifdef MODPLUG_TRACKER
  18. struct DLSREGION
  19. {
  20. uint32 ulLoopStart;
  21. uint32 ulLoopEnd;
  22. uint16 nWaveLink;
  23. uint16 uPercEnv;
  24. uint16 usVolume; // 0..256
  25. uint16 fuOptions; // flags + key group
  26. int16 sFineTune; // +128 = +1 semitone
  27. int16 panning = -1; // -1= unset (DLS), otherwise 0...256
  28. uint8 uKeyMin;
  29. uint8 uKeyMax;
  30. uint8 uUnityNote;
  31. uint8 tuning = 100;
  32. constexpr bool IsDummy() const noexcept { return uKeyMin == 0xFF || nWaveLink == Util::MaxValueOfType(nWaveLink); }
  33. };
  34. struct DLSENVELOPE
  35. {
  36. // Volume Envelope
  37. uint16 wVolAttack; // Attack Time: 0-1000, 1 = 20ms (1/50s) -> [0-20s]
  38. uint16 wVolDecay; // Decay Time: 0-1000, 1 = 20ms (1/50s) -> [0-20s]
  39. uint16 wVolRelease; // Release Time: 0-1000, 1 = 20ms (1/50s) -> [0-20s]
  40. uint8 nVolSustainLevel; // Sustain Level: 0-128, 128=100%
  41. uint8 nDefPan; // Default Pan
  42. };
  43. // Special Bank bits
  44. #define F_INSTRUMENT_DRUMS 0x80000000
  45. struct DLSINSTRUMENT
  46. {
  47. uint32 ulBank = 0, ulInstrument = 0;
  48. uint32 nMelodicEnv = 0;
  49. std::vector<DLSREGION> Regions;
  50. char szName[32];
  51. // SF2 stuff (DO NOT USE! -> used internally by the SF2 loader)
  52. uint16 wPresetBagNdx = 0, wPresetBagNum = 0;
  53. };
  54. struct DLSSAMPLEEX
  55. {
  56. char szName[20];
  57. uint32 dwLen;
  58. uint32 dwStartloop;
  59. uint32 dwEndloop;
  60. uint32 dwSampleRate;
  61. uint8 byOriginalPitch;
  62. int8 chPitchCorrection;
  63. bool compressed = false;
  64. };
  65. #define SOUNDBANK_TYPE_INVALID 0
  66. #define SOUNDBANK_TYPE_DLS 0x01
  67. #define SOUNDBANK_TYPE_SF2 0x02
  68. struct SOUNDBANKINFO
  69. {
  70. std::string szBankName,
  71. szCopyRight,
  72. szComments,
  73. szEngineer,
  74. szSoftware, // ISFT: Software
  75. szDescription; // ISBJ: Subject
  76. };
  77. struct IFFCHUNK;
  78. struct SF2LoaderInfo;
  79. class CDLSBank
  80. {
  81. protected:
  82. SOUNDBANKINFO m_BankInfo;
  83. mpt::PathString m_szFileName;
  84. size_t m_dwWavePoolOffset;
  85. uint32 m_nType;
  86. // DLS Information
  87. uint32 m_nMaxWaveLink;
  88. uint32 m_sf2version = 0;
  89. std::vector<size_t> m_WaveForms;
  90. std::vector<DLSINSTRUMENT> m_Instruments;
  91. std::vector<DLSSAMPLEEX> m_SamplesEx;
  92. std::vector<DLSENVELOPE> m_Envelopes;
  93. public:
  94. CDLSBank();
  95. bool operator==(const CDLSBank &other) const noexcept { return !mpt::PathString::CompareNoCase(m_szFileName, other.m_szFileName); }
  96. static bool IsDLSBank(const mpt::PathString &filename);
  97. static uint32 MakeMelodicCode(uint32 bank, uint32 instr) { return ((bank << 16) | (instr));}
  98. static uint32 MakeDrumCode(uint32 rgn, uint32 instr) { return (0x80000000 | (rgn << 16) | (instr));}
  99. public:
  100. bool Open(const mpt::PathString &filename);
  101. bool Open(FileReader file);
  102. mpt::PathString GetFileName() const { return m_szFileName; }
  103. uint32 GetBankType() const { return m_nType; }
  104. const SOUNDBANKINFO &GetBankInfo() const { return m_BankInfo; }
  105. public:
  106. uint32 GetNumInstruments() const { return static_cast<uint32>(m_Instruments.size()); }
  107. uint32 GetNumSamples() const { return static_cast<uint32>(m_WaveForms.size()); }
  108. const DLSINSTRUMENT *GetInstrument(uint32 iIns) const { return iIns < m_Instruments.size() ? &m_Instruments[iIns] : nullptr; }
  109. const DLSINSTRUMENT *FindInstrument(bool isDrum, uint32 bank = 0xFF, uint32 program = 0xFF, uint32 key = 0xFF, uint32 *pInsNo = nullptr) const;
  110. bool FindAndExtract(CSoundFile &sndFile, const INSTRUMENTINDEX ins, const bool isDrum) const;
  111. uint32 GetRegionFromKey(uint32 nIns, uint32 nKey) const;
  112. bool ExtractWaveForm(uint32 nIns, uint32 nRgn, std::vector<uint8> &waveData, uint32 &length) const;
  113. bool ExtractSample(CSoundFile &sndFile, SAMPLEINDEX nSample, uint32 nIns, uint32 nRgn, int transpose = 0) const;
  114. bool ExtractInstrument(CSoundFile &sndFile, INSTRUMENTINDEX nInstr, uint32 nIns, uint32 nDrumRgn) const;
  115. const char *GetRegionName(uint32 nIns, uint32 nRgn) const;
  116. uint16 GetPanning(uint32 ins, uint32 region) const;
  117. // Internal Loader Functions
  118. protected:
  119. bool UpdateInstrumentDefinition(DLSINSTRUMENT *pDlsIns, FileReader chunk);
  120. bool UpdateSF2PresetData(SF2LoaderInfo &sf2info, const IFFCHUNK &header, FileReader &chunk);
  121. bool ConvertSF2ToDLS(SF2LoaderInfo &sf2info);
  122. public:
  123. // DLS Unit conversion
  124. static int32 DLS32BitTimeCentsToMilliseconds(int32 lTimeCents);
  125. static int32 DLS32BitRelativeGainToLinear(int32 lCentibels); // 0dB = 0x10000
  126. static int32 DLS32BitRelativeLinearToGain(int32 lGain); // 0dB = 0x10000
  127. static int32 DLSMidiVolumeToLinear(uint32 nMidiVolume); // [0-127] -> [0-0x10000]
  128. };
  129. #endif // MODPLUG_TRACKER
  130. OPENMPT_NAMESPACE_END