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 ®ion : 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 ®ion = 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 ®ion = 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 ®ion = 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 ®ion = 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