1 /*
2  * DLSBank.cpp
3  * -----------
4  * Purpose: Sound bank loading.
5  * Notes  : Supported sound bank types: DLS (including embedded DLS in MSS & RMI), SF2, SF3 / SF4 (modified SF2 with compressed samples)
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 
11 
12 #include "stdafx.h"
13 #include "Sndfile.h"
14 #ifdef MODPLUG_TRACKER
15 #include "../mptrack/Mptrack.h"
16 #include "../common/mptFileIO.h"
17 #endif
18 #include "Dlsbank.h"
19 #include "Loaders.h"
20 #include "SampleCopy.h"
21 #include "../common/mptStringBuffer.h"
22 #include "../common/FileReader.h"
23 #include "openmpt/base/Endian.hpp"
24 #include "SampleIO.h"
25 #include "mpt/io/base.hpp"
26 #include "mpt/io/io.hpp"
27 #include "mpt/io/io_stdstream.hpp"
28 
29 OPENMPT_NAMESPACE_BEGIN
30 
31 #ifdef MODPLUG_TRACKER
32 
33 #ifdef MPT_ALL_LOGGING
34 #define DLSBANK_LOG
35 #define DLSINSTR_LOG
36 #endif
37 
38 #define F_RGN_OPTION_SELFNONEXCLUSIVE	0x0001
39 
40 // Region Flags
41 enum RegionFlags
42 {
43 	DLSREGION_KEYGROUPMASK     = 0x0F,
44 	DLSREGION_OVERRIDEWSMP     = 0x10,
45 	DLSREGION_PINGPONGLOOP     = 0x20,
46 	DLSREGION_SAMPLELOOP       = 0x40,
47 	DLSREGION_SELFNONEXCLUSIVE = 0x80,
48 	DLSREGION_SUSTAINLOOP      = 0x100,
49 };
50 
51 ///////////////////////////////////////////////////////////////////////////
52 // Articulation connection graph definitions
53 
54 enum ConnectionSource : uint16
55 {
56 	// Generic Sources
57 	CONN_SRC_NONE              = 0x0000,
58 	CONN_SRC_LFO               = 0x0001,
59 	CONN_SRC_KEYONVELOCITY     = 0x0002,
60 	CONN_SRC_KEYNUMBER         = 0x0003,
61 	CONN_SRC_EG1               = 0x0004,
62 	CONN_SRC_EG2               = 0x0005,
63 	CONN_SRC_PITCHWHEEL        = 0x0006,
64 
65 	CONN_SRC_POLYPRESSURE      = 0x0007,
66 	CONN_SRC_CHANNELPRESSURE   = 0x0008,
67 	CONN_SRC_VIBRATO           = 0x0009,
68 
69 	// Midi Controllers 0-127
70 	CONN_SRC_CC1               = 0x0081,
71 	CONN_SRC_CC7               = 0x0087,
72 	CONN_SRC_CC10              = 0x008a,
73 	CONN_SRC_CC11              = 0x008b,
74 
75 	CONN_SRC_CC91              = 0x00db,
76 	CONN_SRC_CC93              = 0x00dd,
77 
78 	CONN_SRC_RPN0              = 0x0100,
79 	CONN_SRC_RPN1              = 0x0101,
80 	CONN_SRC_RPN2              = 0x0102,
81 };
82 
83 enum ConnectionDestination : uint16
84 {
85 	// Generic Destinations
86 	CONN_DST_NONE              = 0x0000,
87 	CONN_DST_ATTENUATION       = 0x0001,
88 	CONN_DST_RESERVED          = 0x0002,
89 	CONN_DST_PITCH             = 0x0003,
90 	CONN_DST_PAN               = 0x0004,
91 
92 	// LFO Destinations
93 	CONN_DST_LFO_FREQUENCY     = 0x0104,
94 	CONN_DST_LFO_STARTDELAY    = 0x0105,
95 
96 	CONN_DST_KEYNUMBER         = 0x0005,
97 
98 	// EG1 Destinations
99 	CONN_DST_EG1_ATTACKTIME    = 0x0206,
100 	CONN_DST_EG1_DECAYTIME     = 0x0207,
101 	CONN_DST_EG1_RESERVED      = 0x0208,
102 	CONN_DST_EG1_RELEASETIME   = 0x0209,
103 	CONN_DST_EG1_SUSTAINLEVEL  = 0x020a,
104 
105 	CONN_DST_EG1_DELAYTIME     = 0x020b,
106 	CONN_DST_EG1_HOLDTIME      = 0x020c,
107 	CONN_DST_EG1_SHUTDOWNTIME  = 0x020d,
108 
109 	// EG2 Destinations
110 	CONN_DST_EG2_ATTACKTIME    = 0x030a,
111 	CONN_DST_EG2_DECAYTIME     = 0x030b,
112 	CONN_DST_EG2_RESERVED      = 0x030c,
113 	CONN_DST_EG2_RELEASETIME   = 0x030d,
114 	CONN_DST_EG2_SUSTAINLEVEL  = 0x030e,
115 
116 	CONN_DST_EG2_DELAYTIME     = 0x030f,
117 	CONN_DST_EG2_HOLDTIME      = 0x0310,
118 
119 	CONN_TRN_NONE              = 0x0000,
120 	CONN_TRN_CONCAVE           = 0x0001,
121 };
122 
123 
124 //////////////////////////////////////////////////////////
125 // Supported DLS1 Articulations
126 
127 // [4-bit transform][12-bit dest][8-bit control][8-bit source] = 32-bit ID
DLSArt(uint8 src,uint8 ctl,uint16 dst)128 constexpr uint32 DLSArt(uint8 src, uint8 ctl, uint16 dst)
129 {
130 	return (dst << 16u) | (ctl << 8u) | src;
131 }
132 
133 enum DLSArt : uint32
134 {
135 	// Vibrato / Tremolo
136 	ART_LFO_FREQUENCY   = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_LFO_FREQUENCY),
137 	ART_LFO_STARTDELAY  = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_LFO_STARTDELAY),
138 	ART_LFO_ATTENUATION = DLSArt(CONN_SRC_LFO,  CONN_SRC_NONE, CONN_DST_ATTENUATION),
139 	ART_LFO_PITCH       = DLSArt(CONN_SRC_LFO,  CONN_SRC_NONE, CONN_DST_PITCH),
140 	ART_LFO_MODWTOATTN  = DLSArt(CONN_SRC_LFO,  CONN_SRC_CC1,  CONN_DST_ATTENUATION),
141 	ART_LFO_MODWTOPITCH = DLSArt(CONN_SRC_LFO,  CONN_SRC_CC1,  CONN_DST_PITCH),
142 
143 	// Volume Envelope
144 	ART_VOL_EG_ATTACKTIME   = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_ATTACKTIME),
145 	ART_VOL_EG_DECAYTIME    = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_DECAYTIME),
146 	ART_VOL_EG_SUSTAINLEVEL = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_SUSTAINLEVEL),
147 	ART_VOL_EG_RELEASETIME  = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_RELEASETIME),
148 	ART_VOL_EG_DELAYTIME    = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_DELAYTIME),
149 	ART_VOL_EG_HOLDTIME     = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_HOLDTIME),
150 	ART_VOL_EG_SHUTDOWNTIME = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_SHUTDOWNTIME),
151 	ART_VOL_EG_VELTOATTACK  = DLSArt(CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_EG1_ATTACKTIME),
152 	ART_VOL_EG_KEYTODECAY   = DLSArt(CONN_SRC_KEYNUMBER,     CONN_SRC_NONE, CONN_DST_EG1_DECAYTIME),
153 
154 	// Pitch Envelope
155 	ART_PITCH_EG_ATTACKTIME   = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_ATTACKTIME),
156 	ART_PITCH_EG_DECAYTIME    = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_DECAYTIME),
157 	ART_PITCH_EG_SUSTAINLEVEL = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_SUSTAINLEVEL),
158 	ART_PITCH_EG_RELEASETIME  = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_RELEASETIME),
159 	ART_PITCH_EG_VELTOATTACK  = DLSArt(CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_EG2_ATTACKTIME),
160 	ART_PITCH_EG_KEYTODECAY   = DLSArt(CONN_SRC_KEYNUMBER,     CONN_SRC_NONE, CONN_DST_EG2_DECAYTIME),
161 
162 	// Default Pan
163 	ART_DEFAULTPAN = DLSArt(CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_PAN),
164 };
165 
166 //////////////////////////////////////////////////////////
167 // DLS IFF Chunk IDs
168 
169 enum IFFChunkID : uint32
170 {
171 	// Standard IFF chunks IDs
172 	IFFID_FORM = MagicLE("FORM"),
173 	IFFID_RIFF = MagicLE("RIFF"),
174 	IFFID_LIST = MagicLE("LIST"),
175 	IFFID_INFO = MagicLE("INFO"),
176 
177 	// IFF Info fields
178 	IFFID_ICOP = MagicLE("ICOP"),
179 	IFFID_INAM = MagicLE("INAM"),
180 	IFFID_ICMT = MagicLE("ICMT"),
181 	IFFID_IENG = MagicLE("IENG"),
182 	IFFID_ISFT = MagicLE("ISFT"),
183 	IFFID_ISBJ = MagicLE("ISBJ"),
184 
185 	// Wave IFF chunks IDs
186 	IFFID_wave = MagicLE("wave"),
187 	IFFID_wsmp = MagicLE("wsmp"),
188 
189 	IFFID_XDLS = MagicLE("XDLS"),
190 	IFFID_DLS  = MagicLE("DLS "),
191 	IFFID_MLS  = MagicLE("MLS "),
192 	IFFID_RMID = MagicLE("RMID"),
193 	IFFID_colh = MagicLE("colh"),
194 	IFFID_ins  = MagicLE("ins "),
195 	IFFID_insh = MagicLE("insh"),
196 	IFFID_ptbl = MagicLE("ptbl"),
197 	IFFID_wvpl = MagicLE("wvpl"),
198 	IFFID_rgn  = MagicLE("rgn "),
199 	IFFID_rgn2 = MagicLE("rgn2"),
200 	IFFID_rgnh = MagicLE("rgnh"),
201 	IFFID_wlnk = MagicLE("wlnk"),
202 	IFFID_art1 = MagicLE("art1"),
203 	IFFID_art2 = MagicLE("art2"),
204 };
205 
206 //////////////////////////////////////////////////////////
207 // DLS Structures definitions
208 
209 struct IFFCHUNK
210 {
211 	uint32le id;
212 	uint32le len;
213 };
214 
215 MPT_BINARY_STRUCT(IFFCHUNK, 8)
216 
217 struct RIFFChunkID
218 {
219 	uint32le id_RIFF;
220 	uint32le riff_len;
221 	uint32le id_DLS;
222 };
223 
224 MPT_BINARY_STRUCT(RIFFChunkID, 12)
225 
226 struct LISTChunk
227 {
228 	uint32le id;
229 	uint32le len;
230 	uint32le listid;
231 };
232 
233 MPT_BINARY_STRUCT(LISTChunk, 12)
234 
235 struct DLSRgnRange
236 {
237 	uint16le usLow;
238 	uint16le usHigh;
239 };
240 
241 MPT_BINARY_STRUCT(DLSRgnRange, 4)
242 
243 struct VERSChunk
244 {
245 	uint32le id;
246 	uint32le len;
247 	uint16le version[4];
248 };
249 
250 MPT_BINARY_STRUCT(VERSChunk, 16)
251 
252 struct PTBLChunk
253 {
254 	uint32le cbSize;
255 	uint32le cCues;
256 };
257 
258 MPT_BINARY_STRUCT(PTBLChunk, 8)
259 
260 struct INSHChunk
261 {
262 	uint32le cRegions;
263 	uint32le ulBank;
264 	uint32le ulInstrument;
265 };
266 
267 MPT_BINARY_STRUCT(INSHChunk, 12)
268 
269 struct RGNHChunk
270 {
271 	DLSRgnRange RangeKey;
272 	DLSRgnRange RangeVelocity;
273 	uint16le fusOptions;
274 	uint16le usKeyGroup;
275 };
276 
277 MPT_BINARY_STRUCT(RGNHChunk, 12)
278 
279 struct WLNKChunk
280 {
281 	uint16le fusOptions;
282 	uint16le usPhaseGroup;
283 	uint32le ulChannel;
284 	uint32le ulTableIndex;
285 };
286 
287 MPT_BINARY_STRUCT(WLNKChunk, 12)
288 
289 struct ART1Chunk
290 {
291 	uint32le cbSize;
292 	uint32le cConnectionBlocks;
293 };
294 
295 MPT_BINARY_STRUCT(ART1Chunk, 8)
296 
297 struct ConnectionBlock
298 {
299 	uint16le usSource;
300 	uint16le usControl;
301 	uint16le usDestination;
302 	uint16le usTransform;
303 	int32le  lScale;
304 };
305 
306 MPT_BINARY_STRUCT(ConnectionBlock, 12)
307 
308 struct WSMPChunk
309 {
310 	uint32le cbSize;
311 	uint16le usUnityNote;
312 	int16le  sFineTune;
313 	int32le  lAttenuation;
314 	uint32le fulOptions;
315 	uint32le cSampleLoops;
316 };
317 
318 MPT_BINARY_STRUCT(WSMPChunk, 20)
319 
320 struct WSMPSampleLoop
321 {
322 	uint32le cbSize;
323 	uint32le ulLoopType;
324 	uint32le ulLoopStart;
325 	uint32le ulLoopLength;
326 
327 };
328 
329 MPT_BINARY_STRUCT(WSMPSampleLoop, 16)
330 
331 
332 /////////////////////////////////////////////////////////////////////
333 // SF2 IFF Chunk IDs
334 
335 enum SF2ChunkID : uint32
336 {
337 	IFFID_ifil = MagicLE("ifil"),
338 	IFFID_sfbk = MagicLE("sfbk"),
339 	IFFID_sfpk = MagicLE("sfpk"),  // SF2Pack compressed soundfont
340 	IFFID_sdta = MagicLE("sdta"),
341 	IFFID_pdta = MagicLE("pdta"),
342 	IFFID_phdr = MagicLE("phdr"),
343 	IFFID_pbag = MagicLE("pbag"),
344 	IFFID_pgen = MagicLE("pgen"),
345 	IFFID_inst = MagicLE("inst"),
346 	IFFID_ibag = MagicLE("ibag"),
347 	IFFID_igen = MagicLE("igen"),
348 	IFFID_shdr = MagicLE("shdr"),
349 };
350 
351 ///////////////////////////////////////////
352 // SF2 Generators IDs
353 
354 enum SF2Generators : uint16
355 {
356 	SF2_GEN_START_LOOP_FINE		= 2,
357 	SF2_GEN_END_LOOP_FINE		= 3,
358 	SF2_GEN_MODENVTOFILTERFC	= 11,
359 	SF2_GEN_PAN					= 17,
360 	SF2_GEN_DECAYMODENV			= 28,
361 	SF2_GEN_ATTACKVOLENV		= 34,
362 	SF2_GEN_HOLDVOLENV			= 34,
363 	SF2_GEN_DECAYVOLENV			= 36,
364 	SF2_GEN_SUSTAINVOLENV		= 37,
365 	SF2_GEN_RELEASEVOLENV		= 38,
366 	SF2_GEN_INSTRUMENT			= 41,
367 	SF2_GEN_KEYRANGE			= 43,
368 	SF2_GEN_START_LOOP_COARSE	= 45,
369 	SF2_GEN_ATTENUATION			= 48,
370 	SF2_GEN_END_LOOP_COARSE		= 50,
371 	SF2_GEN_COARSETUNE			= 51,
372 	SF2_GEN_FINETUNE			= 52,
373 	SF2_GEN_SAMPLEID			= 53,
374 	SF2_GEN_SAMPLEMODES			= 54,
375 	SF2_GEN_SCALE_TUNING		= 56,
376 	SF2_GEN_KEYGROUP			= 57,
377 	SF2_GEN_UNITYNOTE			= 58,
378 };
379 
380 /////////////////////////////////////////////////////////////////////
381 // SF2 Structures Definitions
382 
383 struct SFPresetHeader
384 {
385 	char     achPresetName[20];
386 	uint16le wPreset;
387 	uint16le wBank;
388 	uint16le wPresetBagNdx;
389 	uint32le dwLibrary;
390 	uint32le dwGenre;
391 	uint32le dwMorphology;
392 };
393 
394 MPT_BINARY_STRUCT(SFPresetHeader, 38)
395 
396 struct SFPresetBag
397 {
398 	uint16le wGenNdx;
399 	uint16le wModNdx;
400 };
401 
402 MPT_BINARY_STRUCT(SFPresetBag, 4)
403 
404 struct SFGenList
405 {
406 	uint16le sfGenOper;
407 	uint16le genAmount;
408 };
409 
410 MPT_BINARY_STRUCT(SFGenList, 4)
411 
412 struct SFInst
413 {
414 	char     achInstName[20];
415 	uint16le wInstBagNdx;
416 };
417 
418 MPT_BINARY_STRUCT(SFInst, 22)
419 
420 struct SFInstBag
421 {
422 	uint16le wGenNdx;
423 	uint16le wModNdx;
424 };
425 
426 MPT_BINARY_STRUCT(SFInstBag, 4)
427 
428 struct SFInstGenList
429 {
430 	uint16le sfGenOper;
431 	uint16le genAmount;
432 };
433 
434 MPT_BINARY_STRUCT(SFInstGenList, 4)
435 
436 struct SFSample
437 {
438 	char     achSampleName[20];
439 	uint32le dwStart;
440 	uint32le dwEnd;
441 	uint32le dwStartloop;
442 	uint32le dwEndloop;
443 	uint32le dwSampleRate;
444 	uint8le  byOriginalPitch;
445 	int8le   chPitchCorrection;
446 	uint16le wSampleLink;
447 	uint16le sfSampleType;
448 };
449 
450 MPT_BINARY_STRUCT(SFSample, 46)
451 
452 // End of structures definitions
453 /////////////////////////////////////////////////////////////////////
454 
455 
456 struct SF2LoaderInfo
457 {
458 	FileReader presetBags;
459 	FileReader presetGens;
460 	FileReader insts;
461 	FileReader instBags;
462 	FileReader instGens;
463 };
464 
465 
466 /////////////////////////////////////////////////////////////////////
467 // Unit conversion
468 
DLSSustainLevelToLinear(int32 sustain)469 static uint8 DLSSustainLevelToLinear(int32 sustain)
470 {
471 	// 0.1% units
472 	if(sustain >= 0)
473 	{
474 		int32 l = sustain / (1000 * 512);
475 		if(l >= 0 && l <= 128)
476 			return static_cast<uint8>(l);
477 	}
478 	return 128;
479 }
480 
481 
SF2SustainLevelToLinear(int32 sustain)482 static uint8 SF2SustainLevelToLinear(int32 sustain)
483 {
484 	// 0.1% units
485 	int32 l = 128 * (1000 - Clamp(sustain, 0, 1000)) / 1000;
486 	return static_cast<uint8>(l);
487 }
488 
489 
DLS32BitTimeCentsToMilliseconds(int32 lTimeCents)490 int32 CDLSBank::DLS32BitTimeCentsToMilliseconds(int32 lTimeCents)
491 {
492 	// tc = log2(time[secs]) * 1200*65536
493 	// time[secs] = 2^(tc/(1200*65536))
494 	if ((uint32)lTimeCents == 0x80000000) return 0;
495 	double fmsecs = 1000.0 * std::pow(2.0, ((double)lTimeCents)/(1200.0*65536.0));
496 	if (fmsecs < -32767) return -32767;
497 	if (fmsecs > 32767) return 32767;
498 	return (int32)fmsecs;
499 }
500 
501 
502 // 0dB = 0x10000
DLS32BitRelativeGainToLinear(int32 lCentibels)503 int32 CDLSBank::DLS32BitRelativeGainToLinear(int32 lCentibels)
504 {
505 	// v = 10^(cb/(200*65536)) * V
506 	return (int32)(65536.0 * std::pow(10.0, ((double)lCentibels)/(200*65536.0)) );
507 }
508 
509 
DLS32BitRelativeLinearToGain(int32 lGain)510 int32 CDLSBank::DLS32BitRelativeLinearToGain(int32 lGain)
511 {
512 	// cb = log10(v/V) * 200 * 65536
513 	if (lGain <= 0) return -960 * 65536;
514 	return (int32)(200 * 65536.0 * std::log10(((double)lGain) / 65536.0));
515 }
516 
517 
DLSMidiVolumeToLinear(uint32 nMidiVolume)518 int32 CDLSBank::DLSMidiVolumeToLinear(uint32 nMidiVolume)
519 {
520 	return (nMidiVolume * nMidiVolume << 16) / (127*127);
521 }
522 
523 
524 /////////////////////////////////////////////////////////////////////
525 // Implementation
526 
CDLSBank()527 CDLSBank::CDLSBank()
528 {
529 	m_nMaxWaveLink = 0;
530 	m_nType = SOUNDBANK_TYPE_INVALID;
531 }
532 
533 
IsDLSBank(const mpt::PathString & filename)534 bool CDLSBank::IsDLSBank(const mpt::PathString &filename)
535 {
536 	RIFFChunkID riff;
537 	if(filename.empty()) return false;
538 	mpt::ifstream f(filename, std::ios::binary);
539 	if(!f)
540 	{
541 		return false;
542 	}
543 	MemsetZero(riff);
544 	mpt::IO::Read(f, riff);
545 	// Check for embedded DLS sections
546 	if(riff.id_RIFF == IFFID_FORM)
547 	{
548 		// Miles Sound System
549 		do
550 		{
551 			uint32 len = mpt::bit_cast<uint32be>(riff.riff_len);
552 			if (len <= 4) break;
553 			if (riff.id_DLS == IFFID_XDLS)
554 			{
555 				mpt::IO::Read(f, riff);
556 				break;
557 			}
558 			if((len % 2u) != 0)
559 				len++;
560 			if (!mpt::IO::SeekRelative(f, len-4)) break;
561 		} while (mpt::IO::Read(f, riff));
562 	} else if(riff.id_RIFF == IFFID_RIFF && riff.id_DLS == IFFID_RMID)
563 	{
564 		for (;;)
565 		{
566 			if(!mpt::IO::Read(f, riff))
567 				break;
568 			if (riff.id_DLS == IFFID_DLS)
569 				break; // found it
570 			int len = riff.riff_len;
571 			if((len % 2u) != 0)
572 				len++;
573 			if ((len <= 4) || !mpt::IO::SeekRelative(f, len-4)) break;
574 		}
575 	}
576 	return ((riff.id_RIFF == IFFID_RIFF)
577 		&& ((riff.id_DLS == IFFID_DLS) || (riff.id_DLS == IFFID_MLS) || (riff.id_DLS == IFFID_sfbk))
578 		&& (riff.riff_len >= 256));
579 }
580 
581 
582 ///////////////////////////////////////////////////////////////
583 // Find an instrument based on the given parameters
584 
FindInstrument(bool isDrum,uint32 bank,uint32 program,uint32 key,uint32 * pInsNo) const585 const DLSINSTRUMENT *CDLSBank::FindInstrument(bool isDrum, uint32 bank, uint32 program, uint32 key, uint32 *pInsNo) const
586 {
587 	// This helps finding the "more correct" instrument if we search for an instrument in any bank, and the higher-bank instruments appear first in the file
588 	// Fixes issues when loading GeneralUser GS into OpenMPT's MIDI library.
589 	std::vector<std::reference_wrapper<const DLSINSTRUMENT>> sortedInstr{m_Instruments.begin(), m_Instruments.end()};
590 	if(bank >= 0x4000 || program >= 0x80)
591 	{
592 		std::sort(sortedInstr.begin(), sortedInstr.end(), [](const DLSINSTRUMENT &l, const DLSINSTRUMENT &r)
593 				{ return std::tie(l.ulBank, l.ulInstrument) < std::tie(r.ulBank, r.ulInstrument); });
594 	}
595 
596 	for(const DLSINSTRUMENT &dlsIns : sortedInstr)
597 	{
598 		uint32 insbank = ((dlsIns.ulBank & 0x7F00) >> 1) | (dlsIns.ulBank & 0x7F);
599 		if((bank >= 0x4000) || (insbank == bank))
600 		{
601 			if(isDrum && (dlsIns.ulBank & F_INSTRUMENT_DRUMS))
602 			{
603 				if((program >= 0x80) || (program == (dlsIns.ulInstrument & 0x7F)))
604 				{
605 					for(const auto &region : dlsIns.Regions)
606 					{
607 						if(region.IsDummy())
608 							continue;
609 
610 						if((!key || key >= 0x80)
611 						   || (key >= region.uKeyMin && key <= region.uKeyMax))
612 						{
613 							if(pInsNo)
614 								*pInsNo = static_cast<uint32>(std::distance(m_Instruments.data(), &dlsIns));
615 							// cppcheck false-positive
616 							// cppcheck-suppress returnDanglingLifetime
617 							return &dlsIns;
618 						}
619 					}
620 				}
621 			} else if(!isDrum && !(dlsIns.ulBank & F_INSTRUMENT_DRUMS))
622 			{
623 				if((program >= 0x80) || (program == (dlsIns.ulInstrument & 0x7F)))
624 				{
625 					if(pInsNo)
626 						*pInsNo = static_cast<uint32>(std::distance(m_Instruments.data(), &dlsIns));
627 					// cppcheck false-positive
628 					// cppcheck-suppress returnDanglingLifetime
629 					return &dlsIns;
630 				}
631 			}
632 		}
633 	}
634 
635 	return nullptr;
636 }
637 
638 
FindAndExtract(CSoundFile & sndFile,const INSTRUMENTINDEX ins,const bool isDrum) const639 bool CDLSBank::FindAndExtract(CSoundFile &sndFile, const INSTRUMENTINDEX ins, const bool isDrum) const
640 {
641 	ModInstrument *pIns = sndFile.Instruments[ins];
642 	if(pIns == nullptr)
643 		return false;
644 
645 	uint32 dlsIns = 0, drumRgn = 0;
646 	const uint32 program = (pIns->nMidiProgram != 0) ? pIns->nMidiProgram - 1 : 0;
647 	const uint32 key = isDrum ? (pIns->nMidiDrumKey & 0x7F) : 0xFF;
648 	if(FindInstrument(isDrum, (pIns->wMidiBank - 1) & 0x3FFF, program, key, &dlsIns)
649 		|| FindInstrument(isDrum, 0xFFFF, isDrum ? 0xFF : program, key, &dlsIns))
650 	{
651 		if(key < 0x80) drumRgn = GetRegionFromKey(dlsIns, key);
652 		if(ExtractInstrument(sndFile, ins, dlsIns, drumRgn))
653 		{
654 			pIns = sndFile.Instruments[ins]; // Reset pointer because ExtractInstrument may delete the previous value.
655 			if((key >= 24) && (key < 24 + std::size(szMidiPercussionNames)))
656 			{
657 				pIns->name = szMidiPercussionNames[key - 24];
658 			}
659 			return true;
660 		}
661 	}
662 	return false;
663 }
664 
665 
666 ///////////////////////////////////////////////////////////////
667 // Update DLS instrument definition from an IFF chunk
668 
UpdateInstrumentDefinition(DLSINSTRUMENT * pDlsIns,FileReader chunk)669 bool CDLSBank::UpdateInstrumentDefinition(DLSINSTRUMENT *pDlsIns, FileReader chunk)
670 {
671 	IFFCHUNK header;
672 	chunk.ReadStruct(header);
673 	if(!header.len || !chunk.CanRead(header.len))
674 		return false;
675 	if(header.id == IFFID_LIST)
676 	{
677 		uint32 listid = chunk.ReadUint32LE();
678 		while(chunk.CanRead(sizeof(IFFCHUNK)))
679 		{
680 			IFFCHUNK subHeader;
681 			chunk.ReadStruct(subHeader);
682 			chunk.SkipBack(sizeof(IFFCHUNK));
683 			FileReader subData = chunk.ReadChunk(subHeader.len + sizeof(IFFCHUNK));
684 			if(subHeader.len & 1)
685 			{
686 				chunk.Skip(1);
687 			}
688 			UpdateInstrumentDefinition(pDlsIns, subData);
689 		}
690 		switch(listid)
691 		{
692 		case IFFID_rgn:		// Level 1 region
693 		case IFFID_rgn2:	// Level 2 region
694 			pDlsIns->Regions.push_back({});
695 			break;
696 		}
697 	} else
698 	{
699 		switch(header.id)
700 		{
701 		case IFFID_insh:
702 		{
703 			INSHChunk insh;
704 			chunk.ReadStruct(insh);
705 			pDlsIns->ulBank = insh.ulBank;
706 			pDlsIns->ulInstrument = insh.ulInstrument;
707 			//Log("%3d regions, bank 0x%04X instrument %3d\n", insh.cRegions, pDlsIns->ulBank, pDlsIns->ulInstrument);
708 			break;
709 		}
710 
711 		case IFFID_rgnh:
712 			if(!pDlsIns->Regions.empty())
713 			{
714 				RGNHChunk rgnh;
715 				chunk.ReadStruct(rgnh);
716 				DLSREGION &region = pDlsIns->Regions.back();
717 				region.uKeyMin = (uint8)rgnh.RangeKey.usLow;
718 				region.uKeyMax = (uint8)rgnh.RangeKey.usHigh;
719 				region.fuOptions = (uint8)(rgnh.usKeyGroup & DLSREGION_KEYGROUPMASK);
720 				if(rgnh.fusOptions & F_RGN_OPTION_SELFNONEXCLUSIVE)
721 					region.fuOptions |= DLSREGION_SELFNONEXCLUSIVE;
722 				//Log("  Region %d: fusOptions=0x%02X usKeyGroup=0x%04X ", pDlsIns->nRegions, rgnh.fusOptions, rgnh.usKeyGroup);
723 				//Log("KeyRange[%3d,%3d] ", rgnh.RangeKey.usLow, rgnh.RangeKey.usHigh);
724 			}
725 			break;
726 
727 		case IFFID_wlnk:
728 			if (!pDlsIns->Regions.empty())
729 			{
730 				WLNKChunk wlnk;
731 				chunk.ReadStruct(wlnk);
732 				DLSREGION &region = pDlsIns->Regions.back();
733 				region.nWaveLink = (uint16)wlnk.ulTableIndex;
734 				if((region.nWaveLink < Util::MaxValueOfType(region.nWaveLink)) && (region.nWaveLink >= m_nMaxWaveLink))
735 					m_nMaxWaveLink = region.nWaveLink + 1;
736 				//Log("  WaveLink %d: fusOptions=0x%02X usPhaseGroup=0x%04X ", pDlsIns->nRegions, wlnk.fusOptions, wlnk.usPhaseGroup);
737 				//Log("ulChannel=%d ulTableIndex=%4d\n", wlnk.ulChannel, wlnk.ulTableIndex);
738 			}
739 			break;
740 
741 		case IFFID_wsmp:
742 			if(!pDlsIns->Regions.empty())
743 			{
744 				DLSREGION &region = pDlsIns->Regions.back();
745 				WSMPChunk wsmp;
746 				chunk.ReadStruct(wsmp);
747 				region.fuOptions |= DLSREGION_OVERRIDEWSMP;
748 				region.uUnityNote = (uint8)wsmp.usUnityNote;
749 				region.sFineTune = wsmp.sFineTune;
750 				int32 lVolume = DLS32BitRelativeGainToLinear(wsmp.lAttenuation) / 256;
751 				if (lVolume > 256) lVolume = 256;
752 				if (lVolume < 4) lVolume = 4;
753 				region.usVolume = (uint16)lVolume;
754 				//Log("  WaveSample %d: usUnityNote=%2d sFineTune=%3d ", pDlsEnv->nRegions, p->usUnityNote, p->sFineTune);
755 				//Log("fulOptions=0x%04X loops=%d\n", p->fulOptions, p->cSampleLoops);
756 				if((wsmp.cSampleLoops) && (wsmp.cbSize + sizeof(WSMPSampleLoop) <= header.len))
757 				{
758 					WSMPSampleLoop loop;
759 					chunk.Seek(sizeof(IFFCHUNK) + wsmp.cbSize);
760 					chunk.ReadStruct(loop);
761 					//Log("looptype=%2d loopstart=%5d loopend=%5d\n", ploop->ulLoopType, ploop->ulLoopStart, ploop->ulLoopLength);
762 					if(loop.ulLoopLength > 3)
763 					{
764 						region.fuOptions |= DLSREGION_SAMPLELOOP;
765 						//if(loop.ulLoopType) region.fuOptions |= DLSREGION_PINGPONGLOOP;
766 						region.ulLoopStart = loop.ulLoopStart;
767 						region.ulLoopEnd = loop.ulLoopStart + loop.ulLoopLength;
768 					}
769 				}
770 			}
771 			break;
772 
773 		case IFFID_art1:
774 		case IFFID_art2:
775 			{
776 				ART1Chunk art1;
777 				chunk.ReadStruct(art1);
778 				if(!(pDlsIns->ulBank & F_INSTRUMENT_DRUMS))
779 				{
780 					pDlsIns->nMelodicEnv = static_cast<uint32>(m_Envelopes.size() + 1);
781 				}
782 				if(art1.cbSize + art1.cConnectionBlocks * sizeof(ConnectionBlock) > header.len)
783 					break;
784 				DLSENVELOPE dlsEnv;
785 				MemsetZero(dlsEnv);
786 				dlsEnv.nDefPan = 128;
787 				dlsEnv.nVolSustainLevel = 128;
788 				//Log("  art1 (%3d bytes): cbSize=%d cConnectionBlocks=%d\n", p->len, p->cbSize, p->cConnectionBlocks);
789 				chunk.Seek(sizeof(IFFCHUNK) + art1.cbSize);
790 				for (uint32 iblk = 0; iblk < art1.cConnectionBlocks; iblk++)
791 				{
792 					ConnectionBlock blk;
793 					chunk.ReadStruct(blk);
794 					// [4-bit transform][12-bit dest][8-bit control][8-bit source] = 32-bit ID
795 					uint32 dwArticulation = blk.usTransform;
796 					dwArticulation = (dwArticulation << 12) | (blk.usDestination & 0x0FFF);
797 					dwArticulation = (dwArticulation << 8) | (blk.usControl & 0x00FF);
798 					dwArticulation = (dwArticulation << 8) | (blk.usSource & 0x00FF);
799 					switch(dwArticulation)
800 					{
801 					case ART_DEFAULTPAN:
802 						{
803 							int32 pan = 128 + blk.lScale / (65536000/128);
804 							dlsEnv.nDefPan = mpt::saturate_cast<uint8>(pan);
805 						}
806 						break;
807 
808 					case ART_VOL_EG_ATTACKTIME:
809 						// 32-bit time cents units. range = [0s, 20s]
810 						dlsEnv.wVolAttack = 0;
811 						if(blk.lScale > -0x40000000)
812 						{
813 							int32 l = blk.lScale - 78743200; // maximum velocity
814 							if (l > 0) l = 0;
815 							int32 attacktime = DLS32BitTimeCentsToMilliseconds(l);
816 							if (attacktime < 0) attacktime = 0;
817 							if (attacktime > 20000) attacktime = 20000;
818 							if (attacktime >= 20) dlsEnv.wVolAttack = (uint16)(attacktime / 20);
819 							//Log("%3d: Envelope Attack Time set to %d (%d time cents)\n", (uint32)(dlsEnv.ulInstrument & 0x7F)|((dlsEnv.ulBank >> 16) & 0x8000), attacktime, pblk->lScale);
820 						}
821 						break;
822 
823 					case ART_VOL_EG_DECAYTIME:
824 						// 32-bit time cents units. range = [0s, 20s]
825 						dlsEnv.wVolDecay = 0;
826 						if(blk.lScale > -0x40000000)
827 						{
828 							int32 decaytime = DLS32BitTimeCentsToMilliseconds(blk.lScale);
829 							if (decaytime > 20000) decaytime = 20000;
830 							if (decaytime >= 20) dlsEnv.wVolDecay = (uint16)(decaytime / 20);
831 							//Log("%3d: Envelope Decay Time set to %d (%d time cents)\n", (uint32)(dlsEnv.ulInstrument & 0x7F)|((dlsEnv.ulBank >> 16) & 0x8000), decaytime, pblk->lScale);
832 						}
833 						break;
834 
835 					case ART_VOL_EG_RELEASETIME:
836 						// 32-bit time cents units. range = [0s, 20s]
837 						dlsEnv.wVolRelease = 0;
838 						if(blk.lScale > -0x40000000)
839 						{
840 							int32 releasetime = DLS32BitTimeCentsToMilliseconds(blk.lScale);
841 							if (releasetime > 20000) releasetime = 20000;
842 							if (releasetime >= 20) dlsEnv.wVolRelease = (uint16)(releasetime / 20);
843 							//Log("%3d: Envelope Release Time set to %d (%d time cents)\n", (uint32)(dlsEnv.ulInstrument & 0x7F)|((dlsEnv.ulBank >> 16) & 0x8000), dlsEnv.wVolRelease, pblk->lScale);
844 						}
845 						break;
846 
847 					case ART_VOL_EG_SUSTAINLEVEL:
848 						// 0.1% units
849 						if(blk.lScale >= 0)
850 						{
851 							dlsEnv.nVolSustainLevel = DLSSustainLevelToLinear(blk.lScale);
852 						}
853 						break;
854 
855 					//default:
856 					//	Log("    Articulation = 0x%08X value=%d\n", dwArticulation, blk.lScale);
857 					}
858 				}
859 				m_Envelopes.push_back(dlsEnv);
860 			}
861 			break;
862 
863 		case IFFID_INAM:
864 			chunk.ReadString<mpt::String::spacePadded>(pDlsIns->szName, header.len);
865 			break;
866 	#if 0
867 		default:
868 			{
869 				char sid[5];
870 				memcpy(sid, &header.id, 4);
871 				sid[4] = 0;
872 				Log("    \"%s\": %d bytes\n", (uint32)sid, header.len.get());
873 			}
874 	#endif
875 		}
876 	}
877 	return true;
878 }
879 
880 ///////////////////////////////////////////////////////////////
881 // Converts SF2 chunks to DLS
882 
UpdateSF2PresetData(SF2LoaderInfo & sf2info,const IFFCHUNK & header,FileReader & chunk)883 bool CDLSBank::UpdateSF2PresetData(SF2LoaderInfo &sf2info, const IFFCHUNK &header, FileReader &chunk)
884 {
885 	if (!chunk.IsValid()) return false;
886 	switch(header.id)
887 	{
888 	case IFFID_phdr:
889 		if(m_Instruments.empty())
890 		{
891 			uint32 numIns = static_cast<uint32>(chunk.GetLength() / sizeof(SFPresetHeader));
892 			if(numIns <= 1)
893 				break;
894 			// The terminal sfPresetHeader record should never be accessed, and exists only to provide a terminal wPresetBagNdx with which to determine the number of zones in the last preset.
895 			numIns--;
896 			m_Instruments.resize(numIns);
897 
898 		#ifdef DLSBANK_LOG
899 			MPT_LOG_GLOBAL(LogDebug, "DLSBank", MPT_UFORMAT("phdr: {} instruments")(m_Instruments.size()));
900 		#endif
901 			SFPresetHeader psfh;
902 			chunk.ReadStruct(psfh);
903 			for(auto &dlsIns : m_Instruments)
904 			{
905 				mpt::String::WriteAutoBuf(dlsIns.szName) = mpt::String::ReadAutoBuf(psfh.achPresetName);
906 				dlsIns.ulInstrument = psfh.wPreset & 0x7F;
907 				dlsIns.ulBank = (psfh.wBank >= 128) ? F_INSTRUMENT_DRUMS : (psfh.wBank << 8);
908 				dlsIns.wPresetBagNdx = psfh.wPresetBagNdx;
909 				dlsIns.wPresetBagNum = 1;
910 				chunk.ReadStruct(psfh);
911 				if (psfh.wPresetBagNdx > dlsIns.wPresetBagNdx) dlsIns.wPresetBagNum = static_cast<uint16>(psfh.wPresetBagNdx - dlsIns.wPresetBagNdx);
912 			}
913 		}
914 		break;
915 
916 	case IFFID_pbag:
917 		if(!m_Instruments.empty() && chunk.CanRead(sizeof(SFPresetBag)))
918 		{
919 			sf2info.presetBags = chunk.GetChunk(chunk.BytesLeft());
920 		}
921 	#ifdef DLSINSTR_LOG
922 		else MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", U_("pbag: no instruments!"));
923 	#endif
924 		break;
925 
926 	case IFFID_pgen:
927 		if(!m_Instruments.empty() && chunk.CanRead(sizeof(SFGenList)))
928 		{
929 			sf2info.presetGens = chunk.GetChunk(chunk.BytesLeft());
930 		}
931 	#ifdef DLSINSTR_LOG
932 		else MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", U_("pgen: no instruments!"));
933 	#endif
934 		break;
935 
936 	case IFFID_inst:
937 		if(!m_Instruments.empty() && chunk.CanRead(sizeof(SFInst)))
938 		{
939 			sf2info.insts = chunk.GetChunk(chunk.BytesLeft());
940 		}
941 		break;
942 
943 	case IFFID_ibag:
944 		if(!m_Instruments.empty() && chunk.CanRead(sizeof(SFInstBag)))
945 		{
946 			sf2info.instBags = chunk.GetChunk(chunk.BytesLeft());
947 		}
948 		break;
949 
950 	case IFFID_igen:
951 		if(!m_Instruments.empty() && chunk.CanRead(sizeof(SFInstGenList)))
952 		{
953 			sf2info.instGens = chunk.GetChunk(chunk.BytesLeft());
954 		}
955 		break;
956 
957 	case IFFID_shdr:
958 		if (m_SamplesEx.empty())
959 		{
960 			uint32 numSmp = static_cast<uint32>(chunk.GetLength() / sizeof(SFSample));
961 			if (numSmp < 1) break;
962 			m_SamplesEx.resize(numSmp);
963 			m_WaveForms.resize(numSmp);
964 			#ifdef DLSINSTR_LOG
965 				MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", MPT_UFORMAT("shdr: {} samples")(m_SamplesEx.size()));
966 			#endif
967 
968 			for (uint32 i = 0; i < numSmp; i++)
969 			{
970 				SFSample p;
971 				chunk.ReadStruct(p);
972 				DLSSAMPLEEX &dlsSmp = m_SamplesEx[i];
973 				mpt::String::WriteAutoBuf(dlsSmp.szName) = mpt::String::ReadAutoBuf(p.achSampleName);
974 				dlsSmp.dwLen = 0;
975 				dlsSmp.dwSampleRate = p.dwSampleRate;
976 				dlsSmp.byOriginalPitch = p.byOriginalPitch;
977 				dlsSmp.chPitchCorrection = static_cast<int8>(Util::muldivr(p.chPitchCorrection, 128, 100));
978 				// cognitone's sf2convert tool doesn't set the correct sample flags (0x01 / 0x02 instead of 0x10/ 0x20).
979 				// For SF3, we ignore this and go by https://github.com/FluidSynth/fluidsynth/wiki/SoundFont3Format instead
980 				// As cognitone's tool is the only tool writing SF4 files, we always assume compressed samples with SF4 files if bits 0/1 are set.
981 				uint16 sampleType = p.sfSampleType;
982 				if(m_sf2version >= 0x4'0000 && m_sf2version <= 0x4'FFFF && (sampleType & 0x03))
983 					sampleType = (sampleType & 0xFFFC) | 0x10;
984 
985 				dlsSmp.compressed = (sampleType & 0x10);
986 				if(((sampleType & 0x7FCF) <= 4) && (p.dwEnd >= p.dwStart + 4))
987 				{
988 					m_WaveForms[i] = p.dwStart;
989 					dlsSmp.dwLen = (p.dwEnd - p.dwStart);
990 					if(!dlsSmp.compressed)
991 					{
992 						m_WaveForms[i] *= 2;
993 						dlsSmp.dwLen *= 2;
994 						if((p.dwEndloop > p.dwStartloop + 7) && (p.dwStartloop >= p.dwStart))
995 						{
996 							dlsSmp.dwStartloop = p.dwStartloop - p.dwStart;
997 							dlsSmp.dwEndloop = p.dwEndloop - p.dwStart;
998 						}
999 					} else
1000 					{
1001 						if(p.dwEndloop > p.dwStartloop + 7)
1002 						{
1003 							dlsSmp.dwStartloop = p.dwStartloop;
1004 							dlsSmp.dwEndloop = p.dwEndloop;
1005 						}
1006 					}
1007 				}
1008 			}
1009 		}
1010 		break;
1011 
1012 	#ifdef DLSINSTR_LOG
1013 	default:
1014 		{
1015 			char sdbg[5];
1016 			memcpy(sdbg, &header.id, 4);
1017 			sdbg[4] = 0;
1018 			MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", MPT_UFORMAT("Unsupported SF2 chunk: {} ({} bytes)")(mpt::ToUnicode(mpt::Charset::ASCII, mpt::String::ReadAutoBuf(sdbg)), header.len.get()));
1019 		}
1020 	#endif
1021 	}
1022 	return true;
1023 }
1024 
1025 
SF2TimeToDLS(int16 amount)1026 static int16 SF2TimeToDLS(int16 amount)
1027 {
1028 	int32 time = CDLSBank::DLS32BitTimeCentsToMilliseconds(static_cast<int32>(amount) << 16);
1029 	return static_cast<int16>(Clamp(time, 20, 20000) / 20);
1030 }
1031 
1032 
1033 // Convert all instruments to the DLS format
ConvertSF2ToDLS(SF2LoaderInfo & sf2info)1034 bool CDLSBank::ConvertSF2ToDLS(SF2LoaderInfo &sf2info)
1035 {
1036 	if (m_Instruments.empty() || m_SamplesEx.empty())
1037 		return false;
1038 
1039 	const uint32 numInsts = static_cast<uint32>(sf2info.insts.GetLength() / sizeof(SFInst));
1040 	const uint32 numInstBags = static_cast<uint32>(sf2info.instBags.GetLength() / sizeof(SFInstBag));
1041 
1042 	std::vector<std::pair<uint16, uint16>> instruments;  // instrument, key range
1043 	std::vector<SFGenList> generators;
1044 	std::vector<SFInstGenList> instrGenerators;
1045 	for(auto &dlsIns : m_Instruments)
1046 	{
1047 		instruments.clear();
1048 		DLSENVELOPE dlsEnv;
1049 		int32 instrAttenuation = 0;
1050 		// Default Envelope Values
1051 		dlsEnv.wVolAttack = 0;
1052 		dlsEnv.wVolDecay = 0;
1053 		dlsEnv.wVolRelease = 0;
1054 		dlsEnv.nVolSustainLevel = 128;
1055 		dlsEnv.nDefPan = 128;
1056 		// Load Preset Bags
1057 		sf2info.presetBags.Seek(dlsIns.wPresetBagNdx * sizeof(SFPresetBag));
1058 		for(uint32 ipbagcnt = 0; ipbagcnt < dlsIns.wPresetBagNum; ipbagcnt++)
1059 		{
1060 			// Load generators for each preset bag
1061 			SFPresetBag bag[2];
1062 			if(!sf2info.presetBags.ReadArray(bag))
1063 				break;
1064 			sf2info.presetBags.SkipBack(sizeof(SFPresetBag));
1065 
1066 			sf2info.presetGens.Seek(bag[0].wGenNdx * sizeof(SFGenList));
1067 			uint16 keyRange = 0xFFFF;
1068 			if(!sf2info.presetGens.ReadVector(generators, bag[1].wGenNdx - bag[0].wGenNdx))
1069 				continue;
1070 			for(const auto &gen : generators)
1071 			{
1072 				switch(gen.sfGenOper)
1073 				{
1074 				case SF2_GEN_ATTACKVOLENV:
1075 					dlsEnv.wVolAttack = SF2TimeToDLS(gen.genAmount);
1076 					break;
1077 				case SF2_GEN_DECAYVOLENV:
1078 					dlsEnv.wVolDecay = SF2TimeToDLS(gen.genAmount);
1079 					break;
1080 				case SF2_GEN_SUSTAINVOLENV:
1081 					// 0.1% units
1082 					if(gen.genAmount >= 0)
1083 					{
1084 						dlsEnv.nVolSustainLevel = SF2SustainLevelToLinear(gen.genAmount);
1085 					}
1086 					break;
1087 				case SF2_GEN_RELEASEVOLENV:
1088 					dlsEnv.wVolRelease = SF2TimeToDLS(gen.genAmount);
1089 					break;
1090 				case SF2_GEN_INSTRUMENT:
1091 					if(const auto instr = std::make_pair(gen.genAmount.get(), keyRange); !mpt::contains(instruments, instr))
1092 						instruments.push_back(instr);
1093 					keyRange = 0xFFFF;
1094 					break;
1095 				case SF2_GEN_KEYRANGE:
1096 					keyRange = gen.genAmount;
1097 					break;
1098 				case SF2_GEN_ATTENUATION:
1099 					instrAttenuation = -static_cast<int16>(gen.genAmount);
1100 					break;
1101 #if 0
1102 				default:
1103 					Log("Ins %3d: bag %3d gen %3d: ", nIns, ipbagndx, ipgenndx);
1104 					Log("genoper=%d amount=0x%04X ", gen.sfGenOper, gen.genAmount);
1105 					Log((pSmp->ulBank & F_INSTRUMENT_DRUMS) ? "(drum)\n" : "\n");
1106 #endif
1107 				}
1108 			}
1109 		}
1110 		// Envelope
1111 		if (!(dlsIns.ulBank & F_INSTRUMENT_DRUMS))
1112 		{
1113 			m_Envelopes.push_back(dlsEnv);
1114 			dlsIns.nMelodicEnv = static_cast<uint32>(m_Envelopes.size());
1115 		}
1116 		// Load Instrument Bags
1117 		dlsIns.Regions.clear();
1118 		for(const auto [nInstrNdx, keyRange] : instruments)
1119 		{
1120 			if(nInstrNdx >= numInsts)
1121 				continue;
1122 			sf2info.insts.Seek(nInstrNdx * sizeof(SFInst));
1123 			SFInst insts[2];
1124 			sf2info.insts.ReadArray(insts);
1125 			const uint32 numRegions = insts[1].wInstBagNdx - insts[0].wInstBagNdx;
1126 			dlsIns.Regions.reserve(dlsIns.Regions.size() + numRegions);
1127 			//Log("\nIns %3d, %2d regions:\n", nIns, pSmp->nRegions);
1128 			DLSREGION globalZone{};
1129 			globalZone.uUnityNote = 0xFF;  // 0xFF means undefined -> use sample root note
1130 			globalZone.tuning = 100;
1131 			globalZone.sFineTune = 0;
1132 			globalZone.nWaveLink = Util::MaxValueOfType(globalZone.nWaveLink);
1133 			if(keyRange != 0xFFFF)
1134 			{
1135 				globalZone.uKeyMin = static_cast<uint8>(keyRange & 0xFF);
1136 				globalZone.uKeyMax = static_cast<uint8>(keyRange >> 8);
1137 				if(globalZone.uKeyMin > globalZone.uKeyMax)
1138 					std::swap(globalZone.uKeyMin, globalZone.uKeyMax);
1139 			} else
1140 			{
1141 				globalZone.uKeyMin = 0;
1142 				globalZone.uKeyMax = 127;
1143 			}
1144 			for(uint32 nRgn = 0; nRgn < numRegions; nRgn++)
1145 			{
1146 				uint32 ibagcnt = insts[0].wInstBagNdx + nRgn;
1147 				if(ibagcnt >= numInstBags)
1148 					break;
1149 				// Create a new envelope for drums
1150 				DLSENVELOPE *pDlsEnv = &dlsEnv;
1151 				if(!(dlsIns.ulBank & F_INSTRUMENT_DRUMS) && dlsIns.nMelodicEnv > 0 && dlsIns.nMelodicEnv <= m_Envelopes.size())
1152 				{
1153 					pDlsEnv = &m_Envelopes[dlsIns.nMelodicEnv - 1];
1154 				}
1155 
1156 				DLSREGION rgn = globalZone;
1157 
1158 				// Region Default Values
1159 				int32 regionAttn = 0;
1160 				// Load Generators
1161 				sf2info.instBags.Seek(ibagcnt * sizeof(SFInstBag));
1162 				SFInstBag bags[2];
1163 				sf2info.instBags.ReadArray(bags);
1164 				sf2info.instGens.Seek(bags[0].wGenNdx * sizeof(SFInstGenList));
1165 				uint16 lastOp = SF2_GEN_SAMPLEID;
1166 				int32 loopStart = 0, loopEnd = 0;
1167 				if(!sf2info.instGens.ReadVector(instrGenerators, bags[1].wGenNdx - bags[0].wGenNdx))
1168 					break;
1169 				for(const auto &gen : instrGenerators)
1170 				{
1171 					uint16 value = gen.genAmount;
1172 					lastOp = gen.sfGenOper;
1173 
1174 					switch(gen.sfGenOper)
1175 					{
1176 					case SF2_GEN_KEYRANGE:
1177 						{
1178 							uint8 keyMin = static_cast<uint8>(value & 0xFF);
1179 							uint8 keyMax = static_cast<uint8>(value >> 8);
1180 							if(keyMin > keyMax)
1181 								std::swap(keyMin, keyMax);
1182 							rgn.uKeyMin = std::max(rgn.uKeyMin, keyMin);
1183 							rgn.uKeyMax = std::min(rgn.uKeyMax, keyMax);
1184 							// There was no overlap between instrument region and preset region - skip it
1185 							if(rgn.uKeyMin > rgn.uKeyMax)
1186 								rgn.uKeyMin = rgn.uKeyMax = 0xFF;
1187 						}
1188 						break;
1189 					case SF2_GEN_UNITYNOTE:
1190 						if (value < 128) rgn.uUnityNote = (uint8)value;
1191 						break;
1192 					case SF2_GEN_ATTACKVOLENV:
1193 						pDlsEnv->wVolAttack = SF2TimeToDLS(gen.genAmount);
1194 						break;
1195 					case SF2_GEN_DECAYVOLENV:
1196 						pDlsEnv->wVolDecay = SF2TimeToDLS(gen.genAmount);
1197 						break;
1198 					case SF2_GEN_SUSTAINVOLENV:
1199 						// 0.1% units
1200 						if(gen.genAmount >= 0)
1201 						{
1202 							pDlsEnv->nVolSustainLevel = SF2SustainLevelToLinear(gen.genAmount);
1203 						}
1204 						break;
1205 					case SF2_GEN_RELEASEVOLENV:
1206 						pDlsEnv->wVolRelease = SF2TimeToDLS(gen.genAmount);
1207 						break;
1208 					case SF2_GEN_PAN:
1209 						{
1210 							int32 pan = static_cast<int16>(value);
1211 							pan = std::clamp(Util::muldivr(pan + 500, 256, 1000), 0, 256);
1212 							rgn.panning = static_cast<int16>(pan);
1213 							pDlsEnv->nDefPan = mpt::saturate_cast<uint8>(pan);
1214 						}
1215 						break;
1216 					case SF2_GEN_ATTENUATION:
1217 						regionAttn = -static_cast<int16>(value);
1218 						break;
1219 					case SF2_GEN_SAMPLEID:
1220 						if (value < m_SamplesEx.size())
1221 						{
1222 							rgn.nWaveLink = value;
1223 							rgn.ulLoopStart = mpt::saturate_cast<uint32>(m_SamplesEx[value].dwStartloop + loopStart);
1224 							rgn.ulLoopEnd = mpt::saturate_cast<uint32>(m_SamplesEx[value].dwEndloop + loopEnd);
1225 						}
1226 						break;
1227 					case SF2_GEN_SAMPLEMODES:
1228 						value &= 3;
1229 						rgn.fuOptions &= uint16(~(DLSREGION_SAMPLELOOP|DLSREGION_PINGPONGLOOP|DLSREGION_SUSTAINLOOP));
1230 						if(value == 1)
1231 							rgn.fuOptions |= DLSREGION_SAMPLELOOP;
1232 						else if(value == 2)
1233 							rgn.fuOptions |= DLSREGION_SAMPLELOOP | DLSREGION_PINGPONGLOOP;
1234 						else if(value == 3)
1235 							rgn.fuOptions |= DLSREGION_SAMPLELOOP | DLSREGION_SUSTAINLOOP;
1236 						rgn.fuOptions |= DLSREGION_OVERRIDEWSMP;
1237 						break;
1238 					case SF2_GEN_KEYGROUP:
1239 						rgn.fuOptions |= (value & DLSREGION_KEYGROUPMASK);
1240 						break;
1241 					case SF2_GEN_COARSETUNE:
1242 						rgn.sFineTune += static_cast<int16>(value) * 128;
1243 						break;
1244 					case SF2_GEN_FINETUNE:
1245 						rgn.sFineTune += static_cast<int16>(Util::muldiv(static_cast<int8>(value), 128, 100));
1246 						break;
1247 					case SF2_GEN_SCALE_TUNING:
1248 						rgn.tuning = mpt::saturate_cast<uint8>(value);
1249 						break;
1250 					case SF2_GEN_START_LOOP_FINE:
1251 						loopStart += static_cast<int16>(value);
1252 						break;
1253 					case SF2_GEN_END_LOOP_FINE:
1254 						loopEnd += static_cast<int16>(value);
1255 						break;
1256 					case SF2_GEN_START_LOOP_COARSE:
1257 						loopStart += static_cast<int16>(value) * 32768;
1258 						break;
1259 					case SF2_GEN_END_LOOP_COARSE:
1260 						loopEnd += static_cast<int16>(value) * 32768;
1261 						break;
1262 					//default:
1263 					//	Log("    gen=%d value=%04X\n", pgen->sfGenOper, pgen->genAmount);
1264 					}
1265 				}
1266 				int32 linearVol = DLS32BitRelativeGainToLinear(((instrAttenuation + regionAttn) * 65536) / 10) / 256;
1267 				Limit(linearVol, 16, 256);
1268 				rgn.usVolume = static_cast<uint16>(linearVol);
1269 
1270 				if(lastOp != SF2_GEN_SAMPLEID && nRgn == 0)
1271 					globalZone = rgn;
1272 				else if(!rgn.IsDummy())
1273 					dlsIns.Regions.push_back(rgn);
1274 				//Log("\n");
1275 			}
1276 		}
1277 	}
1278 	return true;
1279 }
1280 
1281 
1282 ///////////////////////////////////////////////////////////////
1283 // Open: opens a DLS bank
1284 
Open(const mpt::PathString & filename)1285 bool CDLSBank::Open(const mpt::PathString &filename)
1286 {
1287 	if(filename.empty()) return false;
1288 	m_szFileName = filename;
1289 	InputFile f(filename, SettingCacheCompleteFileBeforeLoading());
1290 	if(!f.IsValid()) return false;
1291 	return Open(GetFileReader(f));
1292 }
1293 
1294 
Open(FileReader file)1295 bool CDLSBank::Open(FileReader file)
1296 {
1297 	uint32 nInsDef;
1298 
1299 	if(file.GetOptionalFileName())
1300 		m_szFileName = file.GetOptionalFileName().value();
1301 
1302 	file.Rewind();
1303 	size_t dwMemLength = file.GetLength();
1304 	size_t dwMemPos = 0;
1305 	if(!file.CanRead(256))
1306 	{
1307 		return false;
1308 	}
1309 
1310 	RIFFChunkID riff;
1311 	file.ReadStruct(riff);
1312 	// Check DLS sections embedded in RMI midi files
1313 	if(riff.id_RIFF == IFFID_RIFF && riff.id_DLS == IFFID_RMID)
1314 	{
1315 		while(file.ReadStruct(riff))
1316 		{
1317 			if(riff.id_RIFF == IFFID_RIFF && riff.id_DLS == IFFID_DLS)
1318 			{
1319 				file.SkipBack(sizeof(riff));
1320 				break;
1321 			}
1322 			uint32 len = riff.riff_len;
1323 			if((len % 2u) != 0)
1324 				len++;
1325 			file.SkipBack(4);
1326 			file.Skip(len);
1327 		}
1328 	}
1329 
1330 	// Check XDLS sections embedded in big endian IFF files (Miles Sound System)
1331 	if (riff.id_RIFF == IFFID_FORM)
1332 	{
1333 		do
1334 		{
1335 			if(riff.id_DLS == IFFID_XDLS)
1336 			{
1337 				file.ReadStruct(riff);
1338 				break;
1339 			}
1340 			uint32 len = mpt::bit_cast<uint32be>(riff.riff_len);
1341 			if((len % 2u) != 0)
1342 				len++;
1343 			file.SkipBack(4);
1344 			file.Skip(len);
1345 		} while(file.ReadStruct(riff));
1346 	}
1347 	if (riff.id_RIFF != IFFID_RIFF
1348 		|| (riff.id_DLS != IFFID_DLS && riff.id_DLS != IFFID_MLS && riff.id_DLS != IFFID_sfbk)
1349 		|| !file.CanRead(riff.riff_len - 4))
1350 	{
1351 	#ifdef DLSBANK_LOG
1352 		MPT_LOG_GLOBAL(LogDebug, "DLSBANK", U_("Invalid DLS bank!"));
1353 	#endif
1354 		return false;
1355 	}
1356 	SF2LoaderInfo sf2info;
1357 	m_nType = (riff.id_DLS == IFFID_sfbk) ? SOUNDBANK_TYPE_SF2 : SOUNDBANK_TYPE_DLS;
1358 	m_dwWavePoolOffset = 0;
1359 	m_sf2version = 0;
1360 	m_Instruments.clear();
1361 	m_WaveForms.clear();
1362 	m_Envelopes.clear();
1363 	nInsDef = 0;
1364 	if (dwMemLength > 8 + riff.riff_len + dwMemPos) dwMemLength = 8 + riff.riff_len + dwMemPos;
1365 	bool applyPaddingToSampleChunk = true;
1366 	while(file.CanRead(sizeof(IFFCHUNK)))
1367 	{
1368 		IFFCHUNK chunkHeader;
1369 		file.ReadStruct(chunkHeader);
1370 		dwMemPos = file.GetPosition();
1371 		FileReader chunk = file.ReadChunk(chunkHeader.len);
1372 
1373 		bool applyPadding = (chunkHeader.len % 2u) != 0;
1374 
1375 		if(!chunk.LengthIsAtLeast(chunkHeader.len))
1376 			break;
1377 
1378 		switch(chunkHeader.id)
1379 		{
1380 		// DLS 1.0: Instruments Collection Header
1381 		case IFFID_colh:
1382 		#ifdef DLSBANK_LOG
1383 			MPT_LOG_GLOBAL(LogDebug, "DLSBANK", MPT_UFORMAT("colh ({} bytes)")(chunkHeader.len.get()));
1384 		#endif
1385 			if (m_Instruments.empty())
1386 			{
1387 				m_Instruments.resize(chunk.ReadUint32LE());
1388 			#ifdef DLSBANK_LOG
1389 				MPT_LOG_GLOBAL(LogDebug, "DLSBANK", MPT_UFORMAT("  {} instruments")(m_Instruments.size()));
1390 			#endif
1391 			}
1392 			break;
1393 
1394 		// DLS 1.0: Instruments Pointers Table
1395 		case IFFID_ptbl:
1396 		#ifdef DLSBANK_LOG
1397 			MPT_LOG_GLOBAL(LogDebug, "DLSBANK", MPT_UFORMAT("ptbl ({} bytes)")(chunkHeader.len.get()));
1398 		#endif
1399 			if (m_WaveForms.empty())
1400 			{
1401 				PTBLChunk ptbl;
1402 				chunk.ReadStruct(ptbl);
1403 				chunk.Skip(ptbl.cbSize - 8);
1404 				uint32 cues = std::min(ptbl.cCues.get(), mpt::saturate_cast<uint32>(chunk.BytesLeft() / sizeof(uint32)));
1405 				m_WaveForms.reserve(cues);
1406 				for(uint32 i = 0; i < cues; i++)
1407 				{
1408 					m_WaveForms.push_back(chunk.ReadUint32LE());
1409 				}
1410 			#ifdef DLSBANK_LOG
1411 				MPT_LOG_GLOBAL(LogDebug, "DLSBANK", MPT_UFORMAT("  {} waveforms")(m_WaveForms.size()));
1412 			#endif
1413 			}
1414 			break;
1415 
1416 		// DLS 1.0: LIST section
1417 		case IFFID_LIST:
1418 		#ifdef DLSBANK_LOG
1419 			MPT_LOG_GLOBAL(LogDebug, "DLSBANK", U_("LIST"));
1420 		#endif
1421 			{
1422 				uint32 listid = chunk.ReadUint32LE();
1423 				if (((listid == IFFID_wvpl) && (m_nType & SOUNDBANK_TYPE_DLS))
1424 				 || ((listid == IFFID_sdta) && (m_nType & SOUNDBANK_TYPE_SF2)))
1425 				{
1426 					m_dwWavePoolOffset = dwMemPos + 4;
1427 				#ifdef DLSBANK_LOG
1428 					MPT_LOG_GLOBAL(LogDebug, "DLSBANK", MPT_UFORMAT("Wave Pool offset: {}")(m_dwWavePoolOffset));
1429 				#endif
1430 					if(!applyPaddingToSampleChunk)
1431 						applyPadding = false;
1432 					break;
1433 				}
1434 
1435 				while (chunk.CanRead(12))
1436 				{
1437 					IFFCHUNK listHeader;
1438 					chunk.ReadStruct(listHeader);
1439 
1440 					if(!chunk.CanRead(listHeader.len))
1441 						break;
1442 
1443 					FileReader subData = chunk.GetChunkAt(chunk.GetPosition() - sizeof(IFFCHUNK), listHeader.len + 8);
1444 					FileReader listChunk = chunk.ReadChunk(listHeader.len);
1445 					if(listHeader.len % 2u)
1446 						chunk.Skip(1);
1447 					// DLS Instrument Headers
1448 					if (listHeader.id == IFFID_LIST && (m_nType & SOUNDBANK_TYPE_DLS))
1449 					{
1450 						uint32 subID = listChunk.ReadUint32LE();
1451 						if ((subID == IFFID_ins) && (nInsDef < m_Instruments.size()))
1452 						{
1453 							DLSINSTRUMENT &dlsIns = m_Instruments[nInsDef];
1454 							//Log("Instrument %d:\n", nInsDef);
1455 							dlsIns.Regions.push_back({});
1456 							UpdateInstrumentDefinition(&dlsIns, subData);
1457 							nInsDef++;
1458 						}
1459 					} else
1460 					// DLS/SF2 Bank Information
1461 					if (listid == IFFID_INFO && listHeader.len)
1462 					{
1463 						switch(listHeader.id)
1464 						{
1465 						case IFFID_ifil:
1466 							m_sf2version = listChunk.ReadUint16LE() << 16;
1467 							m_sf2version |= listChunk.ReadUint16LE();
1468 							if(m_sf2version >= 0x3'0000 && m_sf2version <= 0x4'FFFF)
1469 							{
1470 								// "SF3" / "SF4" with compressed samples. The padding of the sample chunk is now optional (probably because it was simply forgotten to be added)
1471 								applyPaddingToSampleChunk = false;
1472 							}
1473 							listChunk.Skip(2);
1474 							break;
1475 						case IFFID_INAM:
1476 							listChunk.ReadString<mpt::String::maybeNullTerminated>(m_BankInfo.szBankName, listChunk.BytesLeft());
1477 							break;
1478 						case IFFID_IENG:
1479 							listChunk.ReadString<mpt::String::maybeNullTerminated>(m_BankInfo.szEngineer, listChunk.BytesLeft());
1480 							break;
1481 						case IFFID_ICOP:
1482 							listChunk.ReadString<mpt::String::maybeNullTerminated>(m_BankInfo.szCopyRight, listChunk.BytesLeft());
1483 							break;
1484 						case IFFID_ICMT:
1485 							listChunk.ReadString<mpt::String::maybeNullTerminated>(m_BankInfo.szComments, listChunk.BytesLeft());
1486 							break;
1487 						case IFFID_ISFT:
1488 							listChunk.ReadString<mpt::String::maybeNullTerminated>(m_BankInfo.szSoftware, listChunk.BytesLeft());
1489 							break;
1490 						case IFFID_ISBJ:
1491 							listChunk.ReadString<mpt::String::maybeNullTerminated>(m_BankInfo.szDescription, listChunk.BytesLeft());
1492 							break;
1493 						}
1494 					} else
1495 					if ((listid == IFFID_pdta) && (m_nType & SOUNDBANK_TYPE_SF2))
1496 					{
1497 						UpdateSF2PresetData(sf2info, listHeader, listChunk);
1498 					}
1499 				}
1500 			}
1501 			break;
1502 
1503 		#ifdef DLSBANK_LOG
1504 		default:
1505 			{
1506 				char sdbg[5];
1507 				memcpy(sdbg, &chunkHeader.id, 4);
1508 				sdbg[4] = 0;
1509 				MPT_LOG_GLOBAL(LogDebug, "DLSBANK", MPT_UFORMAT("Unsupported chunk: {} ({} bytes)")(mpt::ToUnicode(mpt::Charset::ASCII, mpt::String::ReadAutoBuf(sdbg)), chunkHeader.len.get()));
1510 			}
1511 			break;
1512 		#endif
1513 		}
1514 
1515 		if(applyPadding)
1516 			file.Skip(1);
1517 	}
1518 	// Build the ptbl is not present in file
1519 	if ((m_WaveForms.empty()) && (m_dwWavePoolOffset) && (m_nType & SOUNDBANK_TYPE_DLS) && (m_nMaxWaveLink > 0))
1520 	{
1521 	#ifdef DLSBANK_LOG
1522 		MPT_LOG_GLOBAL(LogDebug, "DLSBANK", MPT_UFORMAT("ptbl not present: building table ({} wavelinks)...")(m_nMaxWaveLink));
1523 	#endif
1524 		m_WaveForms.reserve(m_nMaxWaveLink);
1525 		file.Seek(m_dwWavePoolOffset);
1526 		while(m_WaveForms.size() < m_nMaxWaveLink && file.CanRead(sizeof(IFFCHUNK)))
1527 		{
1528 			IFFCHUNK chunk;
1529 			file.ReadStruct(chunk);
1530 			if (chunk.id == IFFID_LIST)
1531 				m_WaveForms.push_back(file.GetPosition() - m_dwWavePoolOffset - sizeof(IFFCHUNK));
1532 			file.Skip(chunk.len);
1533 		}
1534 #ifdef DLSBANK_LOG
1535 		MPT_LOG_GLOBAL(LogDebug, "DLSBANK", MPT_UFORMAT("Found {} waveforms")(m_WaveForms.size()));
1536 #endif
1537 	}
1538 	// Convert the SF2 data to DLS
1539 	if ((m_nType & SOUNDBANK_TYPE_SF2) && !m_SamplesEx.empty() && !m_Instruments.empty())
1540 	{
1541 		ConvertSF2ToDLS(sf2info);
1542 	}
1543 #ifdef DLSBANK_LOG
1544 	MPT_LOG_GLOBAL(LogDebug, "DLSBANK", U_("DLS bank closed"));
1545 #endif
1546 	return true;
1547 }
1548 
1549 ////////////////////////////////////////////////////////////////////////////////////////
1550 // Extracts the Waveforms from a DLS/SF2 bank
1551 
GetRegionFromKey(uint32 nIns,uint32 nKey) const1552 uint32 CDLSBank::GetRegionFromKey(uint32 nIns, uint32 nKey) const
1553 {
1554 	if(nIns >= m_Instruments.size())
1555 		return 0;
1556 	const DLSINSTRUMENT &dlsIns = m_Instruments[nIns];
1557 	for(uint32 rgn = 0; rgn < static_cast<uint32>(dlsIns.Regions.size()); rgn++)
1558 	{
1559 		const auto &region = dlsIns.Regions[rgn];
1560 		if(nKey < region.uKeyMin || nKey > region.uKeyMax)
1561 			continue;
1562 		if(region.nWaveLink == Util::MaxValueOfType(region.nWaveLink))
1563 			continue;
1564 		return rgn;
1565 	}
1566 	return 0;
1567 }
1568 
1569 
ExtractWaveForm(uint32 nIns,uint32 nRgn,std::vector<uint8> & waveData,uint32 & length) const1570 bool CDLSBank::ExtractWaveForm(uint32 nIns, uint32 nRgn, std::vector<uint8> &waveData, uint32 &length) const
1571 {
1572 	waveData.clear();
1573 	length = 0;
1574 
1575 	if (nIns >= m_Instruments.size() || !m_dwWavePoolOffset)
1576 	{
1577 	#ifdef DLSBANK_LOG
1578 		MPT_LOG_GLOBAL(LogDebug, "DLSBANK", MPT_UFORMAT("ExtractWaveForm({}) failed: m_Instruments.size()={} m_dwWavePoolOffset={} m_WaveForms.size()={}")(nIns, m_Instruments.size(), m_dwWavePoolOffset, m_WaveForms.size()));
1579 	#endif
1580 		return false;
1581 	}
1582 	const DLSINSTRUMENT &dlsIns = m_Instruments[nIns];
1583 	if(nRgn >= dlsIns.Regions.size())
1584 	{
1585 	#ifdef DLSBANK_LOG
1586 		MPT_LOG_GLOBAL(LogDebug, "DLSBANK", MPT_UFORMAT("invalid waveform region: nIns={} nRgn={} pSmp->nRegions={}")(nIns, nRgn, dlsIns.nRegions));
1587 	#endif
1588 		return false;
1589 	}
1590 	uint32 nWaveLink = dlsIns.Regions[nRgn].nWaveLink;
1591 	if(nWaveLink >= m_WaveForms.size())
1592 	{
1593 	#ifdef DLSBANK_LOG
1594 		MPT_LOG_GLOBAL(LogDebug, "DLSBANK", MPT_UFORMAT("Invalid wavelink id: nWaveLink={} nWaveForms={}")(nWaveLink, m_WaveForms.size()));
1595 	#endif
1596 		return false;
1597 	}
1598 
1599 	mpt::ifstream f(m_szFileName, std::ios::binary);
1600 	if(!f)
1601 	{
1602 		return false;
1603 	}
1604 
1605 	mpt::IO::Offset sampleOffset = mpt::saturate_cast<mpt::IO::Offset>(m_WaveForms[nWaveLink] + m_dwWavePoolOffset);
1606 	if(mpt::IO::SeekAbsolute(f, sampleOffset))
1607 	{
1608 		if (m_nType & SOUNDBANK_TYPE_SF2)
1609 		{
1610 			if (m_SamplesEx[nWaveLink].dwLen)
1611 			{
1612 				if (mpt::IO::SeekRelative(f, 8))
1613 				{
1614 					length = m_SamplesEx[nWaveLink].dwLen;
1615 					try
1616 					{
1617 						waveData.assign(length + 8, 0);
1618 						mpt::IO::ReadRaw(f, waveData.data(), length);
1619 					} catch(mpt::out_of_memory e)
1620 					{
1621 						mpt::delete_out_of_memory(e);
1622 					}
1623 				}
1624 			}
1625 		} else
1626 		{
1627 			LISTChunk chunk;
1628 			if(mpt::IO::Read(f, chunk))
1629 			{
1630 				if((chunk.id == IFFID_LIST) && (chunk.listid == IFFID_wave) && (chunk.len > 4))
1631 				{
1632 					length = chunk.len + 8;
1633 					try
1634 					{
1635 						waveData.assign(chunk.len + sizeof(IFFCHUNK), 0);
1636 						memcpy(waveData.data(), &chunk, sizeof(chunk));
1637 						mpt::IO::ReadRaw(f, &waveData[sizeof(chunk)], length - sizeof(chunk));
1638 					} catch(mpt::out_of_memory e)
1639 					{
1640 						mpt::delete_out_of_memory(e);
1641 					}
1642 				}
1643 			}
1644 		}
1645 	}
1646 	return !waveData.empty();
1647 }
1648 
1649 
ExtractSample(CSoundFile & sndFile,SAMPLEINDEX nSample,uint32 nIns,uint32 nRgn,int transpose) const1650 bool CDLSBank::ExtractSample(CSoundFile &sndFile, SAMPLEINDEX nSample, uint32 nIns, uint32 nRgn, int transpose) const
1651 {
1652 	std::vector<uint8> pWaveForm;
1653 	uint32 dwLen = 0;
1654 	bool ok, hasWaveform;
1655 
1656 	if(nIns >= m_Instruments.size())
1657 		return false;
1658 	const DLSINSTRUMENT &dlsIns = m_Instruments[nIns];
1659 	if(nRgn >= dlsIns.Regions.size())
1660 		return false;
1661 	if(!ExtractWaveForm(nIns, nRgn, pWaveForm, dwLen))
1662 		return false;
1663 	if(dwLen < 16)
1664 		return false;
1665 	ok = false;
1666 
1667 	FileReader wsmpChunk;
1668 	if (m_nType & SOUNDBANK_TYPE_SF2)
1669 	{
1670 		sndFile.DestroySample(nSample);
1671 		uint32 nWaveLink = dlsIns.Regions[nRgn].nWaveLink;
1672 		ModSample &sample = sndFile.GetSample(nSample);
1673 		if (sndFile.m_nSamples < nSample) sndFile.m_nSamples = nSample;
1674 		if (nWaveLink < m_SamplesEx.size())
1675 		{
1676 			const DLSSAMPLEEX &p = m_SamplesEx[nWaveLink];
1677 		#ifdef DLSINSTR_LOG
1678 			MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", MPT_UFORMAT("  SF2 WaveLink #{}: {}Hz")(nWaveLink, p.dwSampleRate));
1679 		#endif
1680 			sample.Initialize();
1681 
1682 			FileReader chunk{mpt::as_span(pWaveForm.data(), dwLen)};
1683 			if(!p.compressed || !sndFile.ReadSampleFromFile(nSample, chunk, false, false))
1684 			{
1685 				sample.nLength = dwLen / 2;
1686 				SampleIO(
1687 					SampleIO::_16bit,
1688 					SampleIO::mono,
1689 					SampleIO::littleEndian,
1690 					SampleIO::signedPCM)
1691 					.ReadSample(sample, chunk);
1692 			}
1693 			sample.nLoopStart = dlsIns.Regions[nRgn].ulLoopStart;
1694 			sample.nLoopEnd = dlsIns.Regions[nRgn].ulLoopEnd;
1695 			sample.nC5Speed = p.dwSampleRate;
1696 			sample.RelativeTone = p.byOriginalPitch;
1697 			sample.nFineTune = p.chPitchCorrection;
1698 			if(p.szName[0])
1699 				sndFile.m_szNames[nSample] = mpt::String::ReadAutoBuf(p.szName);
1700 			else if(dlsIns.szName[0])
1701 				sndFile.m_szNames[nSample] = mpt::String::ReadAutoBuf(dlsIns.szName);
1702 		}
1703 		hasWaveform = sample.HasSampleData();
1704 	} else
1705 	{
1706 		FileReader file(mpt::as_span(pWaveForm.data(), dwLen));
1707 		hasWaveform = sndFile.ReadWAVSample(nSample, file, false, &wsmpChunk);
1708 		if(dlsIns.szName[0])
1709 			sndFile.m_szNames[nSample] = mpt::String::ReadAutoBuf(dlsIns.szName);
1710 	}
1711 	if (hasWaveform)
1712 	{
1713 		ModSample &sample = sndFile.GetSample(nSample);
1714 		const DLSREGION &rgn = dlsIns.Regions[nRgn];
1715 		sample.uFlags.reset(CHN_LOOP | CHN_PINGPONGLOOP | CHN_SUSTAINLOOP | CHN_PINGPONGSUSTAIN);
1716 		if (rgn.fuOptions & DLSREGION_SAMPLELOOP) sample.uFlags.set(CHN_LOOP);
1717 		if (rgn.fuOptions & DLSREGION_SUSTAINLOOP) sample.uFlags.set(CHN_SUSTAINLOOP);
1718 		if (rgn.fuOptions & DLSREGION_PINGPONGLOOP) sample.uFlags.set(CHN_PINGPONGLOOP);
1719 		if (sample.uFlags[CHN_LOOP | CHN_SUSTAINLOOP])
1720 		{
1721 			if (rgn.ulLoopEnd > rgn.ulLoopStart)
1722 			{
1723 				if (sample.uFlags[CHN_SUSTAINLOOP])
1724 				{
1725 					sample.nSustainStart = rgn.ulLoopStart;
1726 					sample.nSustainEnd = rgn.ulLoopEnd;
1727 				} else
1728 				{
1729 					sample.nLoopStart = rgn.ulLoopStart;
1730 					sample.nLoopEnd = rgn.ulLoopEnd;
1731 				}
1732 			} else
1733 			{
1734 				sample.uFlags.reset(CHN_LOOP|CHN_SUSTAINLOOP);
1735 			}
1736 		}
1737 		// WSMP chunk
1738 		{
1739 			uint32 usUnityNote = rgn.uUnityNote;
1740 			int sFineTune = rgn.sFineTune;
1741 			int lVolume = rgn.usVolume;
1742 
1743 			WSMPChunk wsmp;
1744 			if(!(rgn.fuOptions & DLSREGION_OVERRIDEWSMP) && wsmpChunk.IsValid() && wsmpChunk.Skip(sizeof(IFFCHUNK)) && wsmpChunk.ReadStructPartial(wsmp))
1745 			{
1746 				usUnityNote = wsmp.usUnityNote;
1747 				sFineTune = wsmp.sFineTune;
1748 				lVolume = DLS32BitRelativeGainToLinear(wsmp.lAttenuation) / 256;
1749 				if(wsmp.cSampleLoops)
1750 				{
1751 					WSMPSampleLoop loop;
1752 					wsmpChunk.Seek(sizeof(IFFCHUNK) + wsmp.cbSize);
1753 					wsmpChunk.ReadStruct(loop);
1754 					if(loop.ulLoopLength > 3)
1755 					{
1756 						sample.uFlags.set(CHN_LOOP);
1757 						//if (loop.ulLoopType) sample.uFlags |= CHN_PINGPONGLOOP;
1758 						sample.nLoopStart = loop.ulLoopStart;
1759 						sample.nLoopEnd = loop.ulLoopStart + loop.ulLoopLength;
1760 					}
1761 				}
1762 			} else if (m_nType & SOUNDBANK_TYPE_SF2)
1763 			{
1764 				usUnityNote = (usUnityNote < 0x80) ? usUnityNote : sample.RelativeTone;
1765 				sFineTune += sample.nFineTune;
1766 			}
1767 		#ifdef DLSINSTR_LOG
1768 			MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", MPT_UFORMAT("WSMP: usUnityNote={}.{}, {}Hz (transp={})")(usUnityNote, sFineTune, sample.nC5Speed, transpose));
1769 		#endif
1770 			if (usUnityNote > 0x7F) usUnityNote = 60;
1771 			int steps = (60 + transpose - usUnityNote) * 128 + sFineTune;
1772 			sample.Transpose(steps * (1.0 / (12.0 * 128.0)));
1773 			sample.RelativeTone = 0;
1774 
1775 			Limit(lVolume, 16, 256);
1776 			sample.nGlobalVol = (uint8)(lVolume / 4);	// 0-64
1777 		}
1778 		sample.nPan = GetPanning(nIns, nRgn);
1779 
1780 		sample.Convert(MOD_TYPE_IT, sndFile.GetType());
1781 		sample.PrecomputeLoops(sndFile, false);
1782 		ok = true;
1783 	}
1784 	return ok;
1785 }
1786 
1787 
ScaleEnvelope(uint32 time,float tempoScale)1788 static uint16 ScaleEnvelope(uint32 time, float tempoScale)
1789 {
1790 	return std::max(mpt::saturate_round<uint16>(time * tempoScale), uint16(1));
1791 }
1792 
1793 
ExtractInstrument(CSoundFile & sndFile,INSTRUMENTINDEX nInstr,uint32 nIns,uint32 nDrumRgn) const1794 bool CDLSBank::ExtractInstrument(CSoundFile &sndFile, INSTRUMENTINDEX nInstr, uint32 nIns, uint32 nDrumRgn) const
1795 {
1796 	uint32 minRegion, maxRegion, nEnv;
1797 
1798 	if (nIns >= m_Instruments.size())
1799 		return false;
1800 	const DLSINSTRUMENT &dlsIns = m_Instruments[nIns];
1801 	const bool isDrum = (dlsIns.ulBank & F_INSTRUMENT_DRUMS) && nDrumRgn != uint32_max;
1802 	if(isDrum)
1803 	{
1804 		if(nDrumRgn >= dlsIns.Regions.size())
1805 			return false;
1806 		minRegion = nDrumRgn;
1807 		maxRegion = nDrumRgn + 1;
1808 		nEnv = dlsIns.Regions[nDrumRgn].uPercEnv;
1809 	} else
1810 	{
1811 		if(dlsIns.Regions.empty())
1812 			return false;
1813 		minRegion = 0;
1814 		maxRegion = static_cast<uint32>(dlsIns.Regions.size());
1815 		nEnv = dlsIns.nMelodicEnv;
1816 	}
1817 #ifdef DLSINSTR_LOG
1818 	MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", MPT_UFORMAT("DLS Instrument #{}: {}")(nIns, mpt::ToUnicode(mpt::Charset::ASCII, mpt::String::ReadAutoBuf(dlsIns.szName))));
1819 	MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", MPT_UFORMAT("  Bank=0x{} Instrument=0x{}")(mpt::ufmt::HEX0<4>(dlsIns.ulBank), mpt::ufmt::HEX0<4>(dlsIns.ulInstrument)));
1820 	MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", MPT_UFORMAT("  {} regions, nMelodicEnv={}")(dlsIns.Regions.size(), dlsIns.nMelodicEnv));
1821 	for (uint32 iDbg=0; iDbg<dlsIns.Regions.size(); iDbg++)
1822 	{
1823 		const DLSREGION *prgn = &dlsIns.Regions[iDbg];
1824 		MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", MPT_UFORMAT(" Region {}:")(iDbg));
1825 		MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", MPT_UFORMAT("  WaveLink = {} (loop [{}, {}])")(prgn->nWaveLink, prgn->ulLoopStart, prgn->ulLoopEnd));
1826 		MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", MPT_UFORMAT("  Key Range: [{}, {}]")(prgn->uKeyMin, prgn->uKeyMax));
1827 		MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", MPT_UFORMAT("  fuOptions = 0x{}")(mpt::ufmt::HEX0<4>(prgn->fuOptions)));
1828 		MPT_LOG_GLOBAL(LogDebug, "DLSINSTR", MPT_UFORMAT("  usVolume = {}, Unity Note = {}")(prgn->usVolume, prgn->uUnityNote));
1829 	}
1830 #endif
1831 
1832 	ModInstrument *pIns = new (std::nothrow) ModInstrument();
1833 	if(pIns == nullptr)
1834 	{
1835 		return false;
1836 	}
1837 
1838 	if(sndFile.Instruments[nInstr])
1839 	{
1840 		sndFile.DestroyInstrument(nInstr, deleteAssociatedSamples);
1841 	}
1842 	// Initializes Instrument
1843 	if(isDrum)
1844 	{
1845 		uint32 key = dlsIns.Regions[nDrumRgn].uKeyMin;
1846 		if((key >= 24) && (key <= 84))
1847 		{
1848 			std::string s = szMidiPercussionNames[key-24];
1849 			if(!mpt::String::ReadAutoBuf(dlsIns.szName).empty())
1850 			{
1851 				s += MPT_AFORMAT(" ({})")(mpt::trim_right<std::string>(mpt::String::ReadAutoBuf(dlsIns.szName)));
1852 			}
1853 			pIns->name = s;
1854 		} else
1855 		{
1856 			pIns->name = mpt::String::ReadAutoBuf(dlsIns.szName);
1857 		}
1858 	} else
1859 	{
1860 		pIns->name = mpt::String::ReadAutoBuf(dlsIns.szName);
1861 	}
1862 	int transpose = 0;
1863 	if(isDrum)
1864 	{
1865 		for(uint32 iNoteMap = 0; iNoteMap < NOTE_MAX; iNoteMap++)
1866 		{
1867 			if(sndFile.GetType() & (MOD_TYPE_IT | MOD_TYPE_MID | MOD_TYPE_MPT))
1868 			{
1869 				// Format has instrument note mapping
1870 				if(dlsIns.Regions[nDrumRgn].tuning == 0)
1871 					pIns->NoteMap[iNoteMap] = NOTE_MIDDLEC;
1872 				else if (iNoteMap < dlsIns.Regions[nDrumRgn].uKeyMin)
1873 					pIns->NoteMap[iNoteMap] = (uint8)(dlsIns.Regions[nDrumRgn].uKeyMin + NOTE_MIN);
1874 				else if(iNoteMap > dlsIns.Regions[nDrumRgn].uKeyMax)
1875 					pIns->NoteMap[iNoteMap] = (uint8)(dlsIns.Regions[nDrumRgn].uKeyMax + NOTE_MIN);
1876 			} else
1877 			{
1878 				if(iNoteMap == dlsIns.Regions[nDrumRgn].uKeyMin)
1879 				{
1880 					transpose = (dlsIns.Regions[nDrumRgn].uKeyMin + (dlsIns.Regions[nDrumRgn].uKeyMax - dlsIns.Regions[nDrumRgn].uKeyMin) / 2) - 60;
1881 				}
1882 			}
1883 		}
1884 	}
1885 	pIns->nFadeOut = 1024;
1886 	pIns->nMidiProgram = (uint8)(dlsIns.ulInstrument & 0x7F) + 1;
1887 	pIns->nMidiChannel = (uint8)(isDrum ? 10 : 0);
1888 	pIns->wMidiBank = (uint16)(((dlsIns.ulBank & 0x7F00) >> 1) | (dlsIns.ulBank & 0x7F));
1889 	pIns->nNNA = NewNoteAction::NoteOff;
1890 	pIns->nDCT = DuplicateCheckType::Note;
1891 	pIns->nDNA = DuplicateNoteAction::NoteFade;
1892 	sndFile.Instruments[nInstr] = pIns;
1893 	uint32 nLoadedSmp = 0;
1894 	SAMPLEINDEX nextSample = 0;
1895 	// Extract Samples
1896 	std::vector<SAMPLEINDEX> RgnToSmp(dlsIns.Regions.size());
1897 	std::set<uint16> extractedSamples;
1898 	for(uint32 nRgn = minRegion; nRgn < maxRegion; nRgn++)
1899 	{
1900 		bool duplicateRegion = false;
1901 		SAMPLEINDEX nSmp = 0;
1902 		const DLSREGION &rgn = dlsIns.Regions[nRgn];
1903 		if(rgn.IsDummy())
1904 			continue;
1905 		// Elimitate Duplicate Regions
1906 		uint32 dupRegion;
1907 		for(dupRegion = minRegion; dupRegion < nRgn; dupRegion++)
1908 		{
1909 			const DLSREGION &rgn2 = dlsIns.Regions[dupRegion];
1910 			if(RgnToSmp[dupRegion] == 0 || rgn2.IsDummy())
1911 				continue;
1912 			// No need to extract the same sample data twice
1913 			const bool sameSample = (rgn2.nWaveLink == rgn.nWaveLink) && (rgn2.ulLoopEnd == rgn.ulLoopEnd) && (rgn2.ulLoopStart == rgn.ulLoopStart) && extractedSamples.count(rgn.nWaveLink);
1914 			// Candidate for stereo sample creation
1915 			const bool sameKeyRange = (rgn2.uKeyMin == rgn.uKeyMin) && (rgn2.uKeyMax == rgn.uKeyMax);
1916 			if(sameSample || sameKeyRange)
1917 			{
1918 				duplicateRegion = true;
1919 				if(!sameKeyRange)
1920 					nSmp = RgnToSmp[dupRegion];
1921 				break;
1922 			}
1923 		}
1924 		// Create a new sample
1925 		if (!duplicateRegion)
1926 		{
1927 			uint32 nmaxsmp = (m_nType & MOD_TYPE_XM) ? 16 : (NOTE_MAX - NOTE_MIN + 1);
1928 			if (nLoadedSmp >= nmaxsmp)
1929 			{
1930 				nSmp = RgnToSmp[nRgn - 1];
1931 			} else
1932 			{
1933 				nextSample = sndFile.GetNextFreeSample(nInstr, nextSample + 1);
1934 				if (nextSample == SAMPLEINDEX_INVALID) break;
1935 				if (nextSample > sndFile.GetNumSamples()) sndFile.m_nSamples = nextSample;
1936 				nSmp = nextSample;
1937 				nLoadedSmp++;
1938 			}
1939 		}
1940 
1941 		RgnToSmp[nRgn] = nSmp;
1942 		// Map all notes to the right sample
1943 		if(nSmp)
1944 		{
1945 			for(uint8 key = 0; key < NOTE_MAX; key++)
1946 			{
1947 				if(isDrum || (key >= rgn.uKeyMin && key <= rgn.uKeyMax))
1948 				{
1949 					pIns->Keyboard[key] = nSmp;
1950 				}
1951 			}
1952 			// Load the sample
1953 			if(!duplicateRegion || !sndFile.GetSample(nSmp).HasSampleData())
1954 			{
1955 				ExtractSample(sndFile, nSmp, nIns, nRgn, transpose);
1956 				extractedSamples.insert(rgn.nWaveLink);
1957 			}
1958 		} else if(duplicateRegion && sndFile.GetSample(RgnToSmp[dupRegion]).GetNumChannels() == 1)
1959 		{
1960 			// Try to combine stereo samples
1961 			const uint16 pan1 = GetPanning(nIns, nRgn), pan2 = GetPanning(nIns, dupRegion);
1962 			if((pan1 < 16 && pan2 >= 240) || (pan2 < 16 && pan1 >= 240))
1963 			{
1964 				ModSample &sample = sndFile.GetSample(RgnToSmp[dupRegion]);
1965 				ModSample sampleCopy = sample;
1966 				sampleCopy.pData.pSample = nullptr;
1967 				sampleCopy.uFlags.set(CHN_16BIT | CHN_STEREO);
1968 				if(!sampleCopy.AllocateSample())
1969 					continue;
1970 
1971 				const uint8 offsetOrig = (pan1 < pan2) ? 1 : 0;
1972 				const uint8 offsetNew = (pan1 < pan2) ? 0 : 1;
1973 
1974 				std::vector<uint8> pWaveForm;
1975 				uint32 dwLen = 0;
1976 				if(!ExtractWaveForm(nIns, nRgn, pWaveForm, dwLen))
1977 					continue;
1978 				extractedSamples.insert(rgn.nWaveLink);
1979 
1980 				// First copy over original channel
1981 				auto pDest = sampleCopy.sample16() + offsetOrig;
1982 				if(sample.uFlags[CHN_16BIT])
1983 					CopySample<SC::ConversionChain<SC::Convert<int16, int16>, SC::DecodeIdentity<int16>>>(pDest, sample.nLength, 2, sample.sample16(), sample.GetSampleSizeInBytes(), 1);
1984 				else
1985 					CopySample<SC::ConversionChain<SC::Convert<int16, int8>, SC::DecodeIdentity<int8>>>(pDest, sample.nLength, 2, sample.sample8(), sample.GetSampleSizeInBytes(), 1);
1986 				sample.FreeSample();
1987 
1988 				// Now read the other channel
1989 				if(m_SamplesEx[m_Instruments[nIns].Regions[nRgn].nWaveLink].compressed)
1990 				{
1991 					FileReader file{mpt::as_span(pWaveForm)};
1992 					if(sndFile.ReadSampleFromFile(nSmp, file, false, false))
1993 					{
1994 						pDest = sampleCopy.sample16() + offsetNew;
1995 						const SmpLength copyLength = std::min(sample.nLength, sampleCopy.nLength);
1996 						if(sample.uFlags[CHN_16BIT])
1997 							CopySample<SC::ConversionChain<SC::Convert<int16, int16>, SC::DecodeIdentity<int16>>>(pDest, copyLength, 2, sample.sample16(), sample.GetSampleSizeInBytes(), sample.GetNumChannels());
1998 						else
1999 							CopySample<SC::ConversionChain<SC::Convert<int16, int8>, SC::DecodeIdentity<int8>>>(pDest, copyLength, 2, sample.sample8(), sample.GetSampleSizeInBytes(), sample.GetNumChannels());
2000 					}
2001 				} else
2002 				{
2003 					SmpLength len = std::min(dwLen / 2u, sampleCopy.nLength);
2004 					const int16 *src = reinterpret_cast<int16 *>(pWaveForm.data());
2005 					int16 *dst = sampleCopy.sample16() + offsetNew;
2006 					CopySample<SC::ConversionChain<SC::Convert<int16, int16>, SC::DecodeIdentity<int16>>>(dst, len, 2, src, pWaveForm.size(), 1);
2007 				}
2008 				sample.FreeSample();
2009 				sample = sampleCopy;
2010 			}
2011 		}
2012 	}
2013 
2014 	float tempoScale = 1.0f;
2015 	if(sndFile.m_nTempoMode == TempoMode::Modern)
2016 	{
2017 		uint32 ticksPerBeat = sndFile.m_nDefaultRowsPerBeat * sndFile.m_nDefaultSpeed;
2018 		if(ticksPerBeat != 0)
2019 			tempoScale = ticksPerBeat / 24.0f;
2020 	}
2021 
2022 	// Initializes Envelope
2023 	if ((nEnv) && (nEnv <= m_Envelopes.size()))
2024 	{
2025 		const DLSENVELOPE &part = m_Envelopes[nEnv - 1];
2026 		// Volume Envelope
2027 		if ((part.wVolAttack) || (part.wVolDecay < 20*50) || (part.nVolSustainLevel) || (part.wVolRelease < 20*50))
2028 		{
2029 			pIns->VolEnv.dwFlags.set(ENV_ENABLED);
2030 			// Delay section
2031 			// -> DLS level 2
2032 			// Attack section
2033 			pIns->VolEnv.clear();
2034 			if (part.wVolAttack)
2035 			{
2036 				pIns->VolEnv.push_back(0, (uint8)(ENVELOPE_MAX / (part.wVolAttack / 2 + 2) + 8)); // /-----
2037 				pIns->VolEnv.push_back(ScaleEnvelope(part.wVolAttack, tempoScale), ENVELOPE_MAX); // |
2038 			} else
2039 			{
2040 				pIns->VolEnv.push_back(0, ENVELOPE_MAX);
2041 			}
2042 			// Hold section
2043 			// -> DLS Level 2
2044 			// Sustain Level
2045 			if (part.nVolSustainLevel > 0)
2046 			{
2047 				if (part.nVolSustainLevel < 128)
2048 				{
2049 					uint16 lStartTime = pIns->VolEnv.back().tick;
2050 					int32 lSusLevel = - DLS32BitRelativeLinearToGain(part.nVolSustainLevel << 9) / 65536;
2051 					int32 lDecayTime = 1;
2052 					if (lSusLevel > 0)
2053 					{
2054 						lDecayTime = (lSusLevel * (int32)part.wVolDecay) / 960;
2055 						for (uint32 i=0; i<7; i++)
2056 						{
2057 							int32 lFactor = 128 - (1 << i);
2058 							if (lFactor <= part.nVolSustainLevel) break;
2059 							int32 lev = - DLS32BitRelativeLinearToGain(lFactor << 9) / 65536;
2060 							if (lev > 0)
2061 							{
2062 								int32 ltime = (lev * (int32)part.wVolDecay) / 960;
2063 								if ((ltime > 1) && (ltime < lDecayTime))
2064 								{
2065 									uint16 tick = lStartTime + ScaleEnvelope(ltime, tempoScale);
2066 									if(tick > pIns->VolEnv.back().tick)
2067 									{
2068 										pIns->VolEnv.push_back(tick, (uint8)(lFactor / 2));
2069 									}
2070 								}
2071 							}
2072 						}
2073 					}
2074 
2075 					uint16 decayEnd = lStartTime + ScaleEnvelope(lDecayTime, tempoScale);
2076 					if (decayEnd > pIns->VolEnv.back().tick)
2077 					{
2078 						pIns->VolEnv.push_back(decayEnd, (uint8)((part.nVolSustainLevel+1) / 2));
2079 					}
2080 				}
2081 				pIns->VolEnv.dwFlags.set(ENV_SUSTAIN);
2082 			} else
2083 			{
2084 				pIns->VolEnv.dwFlags.set(ENV_SUSTAIN);
2085 				pIns->VolEnv.push_back(pIns->VolEnv.back().tick + 1u, pIns->VolEnv.back().value);
2086 			}
2087 			pIns->VolEnv.nSustainStart = pIns->VolEnv.nSustainEnd = (uint8)(pIns->VolEnv.size() - 1);
2088 			// Release section
2089 			if ((part.wVolRelease) && (pIns->VolEnv.back().value > 1))
2090 			{
2091 				int32 lReleaseTime = part.wVolRelease;
2092 				uint16 lStartTime = pIns->VolEnv.back().tick;
2093 				int32 lStartFactor = pIns->VolEnv.back().value;
2094 				int32 lSusLevel = - DLS32BitRelativeLinearToGain(lStartFactor << 10) / 65536;
2095 				int32 lDecayEndTime = (lReleaseTime * lSusLevel) / 960;
2096 				lReleaseTime -= lDecayEndTime;
2097 				if(pIns->VolEnv.nSustainEnd > 0)
2098 					pIns->VolEnv.nReleaseNode = pIns->VolEnv.nSustainEnd;
2099 				for (uint32 i=0; i<5; i++)
2100 				{
2101 					int32 lFactor = 1 + ((lStartFactor * 3) >> (i+2));
2102 					if ((lFactor <= 1) || (lFactor >= lStartFactor)) continue;
2103 					int32 lev = - DLS32BitRelativeLinearToGain(lFactor << 10) / 65536;
2104 					if (lev > 0)
2105 					{
2106 						int32 ltime = (((int32)part.wVolRelease * lev) / 960) - lDecayEndTime;
2107 						if ((ltime > 1) && (ltime < lReleaseTime))
2108 						{
2109 							uint16 tick = lStartTime + ScaleEnvelope(ltime, tempoScale);
2110 							if(tick > pIns->VolEnv.back().tick)
2111 							{
2112 								pIns->VolEnv.push_back(tick, (uint8)lFactor);
2113 							}
2114 						}
2115 					}
2116 				}
2117 				if (lReleaseTime < 1) lReleaseTime = 1;
2118 				auto releaseTicks = ScaleEnvelope(lReleaseTime, tempoScale);
2119 				pIns->VolEnv.push_back(lStartTime + releaseTicks, ENVELOPE_MIN);
2120 				if(releaseTicks > 0)
2121 				{
2122 					pIns->nFadeOut = 32768 / releaseTicks;
2123 				}
2124 			} else
2125 			{
2126 				pIns->VolEnv.push_back(pIns->VolEnv.back().tick + 1u, ENVELOPE_MIN);
2127 			}
2128 		}
2129 	}
2130 	if(isDrum)
2131 	{
2132 		// Create a default envelope for drums
2133 		pIns->VolEnv.dwFlags.reset(ENV_SUSTAIN);
2134 		if(!pIns->VolEnv.dwFlags[ENV_ENABLED])
2135 		{
2136 			pIns->VolEnv.dwFlags.set(ENV_ENABLED);
2137 			pIns->VolEnv.resize(4);
2138 			pIns->VolEnv[0] = EnvelopeNode(0, ENVELOPE_MAX);
2139 			pIns->VolEnv[1] = EnvelopeNode(ScaleEnvelope(5, tempoScale), ENVELOPE_MAX);
2140 			pIns->VolEnv[2] = EnvelopeNode(pIns->VolEnv[1].tick * 2u, ENVELOPE_MID);
2141 			pIns->VolEnv[3] = EnvelopeNode(pIns->VolEnv[2].tick * 2u, ENVELOPE_MIN);	// 1 second max. for drums
2142 		}
2143 	}
2144 	pIns->Sanitize(MOD_TYPE_MPT);
2145 	pIns->Convert(MOD_TYPE_MPT, sndFile.GetType());
2146 	return true;
2147 }
2148 
2149 
GetRegionName(uint32 nIns,uint32 nRgn) const2150 const char *CDLSBank::GetRegionName(uint32 nIns, uint32 nRgn) const
2151 {
2152 	if(nIns >= m_Instruments.size())
2153 		return nullptr;
2154 	const DLSINSTRUMENT &dlsIns = m_Instruments[nIns];
2155 	if(nRgn >= dlsIns.Regions.size())
2156 		return nullptr;
2157 
2158 	if (m_nType & SOUNDBANK_TYPE_SF2)
2159 	{
2160 		uint32 nWaveLink = dlsIns.Regions[nRgn].nWaveLink;
2161 		if (nWaveLink < m_SamplesEx.size())
2162 		{
2163 			return m_SamplesEx[nWaveLink].szName;
2164 		}
2165 	}
2166 	return nullptr;
2167 }
2168 
2169 
GetPanning(uint32 ins,uint32 region) const2170 uint16 CDLSBank::GetPanning(uint32 ins, uint32 region) const
2171 {
2172 	const DLSINSTRUMENT &dlsIns = m_Instruments[ins];
2173 	if(region >= std::size(dlsIns.Regions))
2174 		return 128;
2175 	const DLSREGION &rgn = dlsIns.Regions[region];
2176 	if(rgn.panning >= 0)
2177 		return static_cast<uint16>(rgn.panning);
2178 
2179 	if(dlsIns.ulBank & F_INSTRUMENT_DRUMS)
2180 	{
2181 		if(rgn.uPercEnv > 0 && rgn.uPercEnv <= m_Envelopes.size())
2182 		{
2183 			return m_Envelopes[rgn.uPercEnv - 1].nDefPan;
2184 		}
2185 	} else
2186 	{
2187 		if(dlsIns.nMelodicEnv > 0 && dlsIns.nMelodicEnv <= m_Envelopes.size())
2188 		{
2189 			return m_Envelopes[dlsIns.nMelodicEnv - 1].nDefPan;
2190 		}
2191 	}
2192 	return 128;
2193 }
2194 
2195 
2196 #else // !MODPLUG_TRACKER
2197 
2198 MPT_MSVC_WORKAROUND_LNK4221(Dlsbank)
2199 
2200 #endif // MODPLUG_TRACKER
2201 
2202 
2203 OPENMPT_NAMESPACE_END
2204