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