1 /*
2 * Load_mid.cpp
3 * ------------
4 * Purpose: MIDI file loader
5 * Notes : (currently none)
6 * Authors: OpenMPT Devs
7 * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
8 */
9
10
11 #include "stdafx.h"
12 #include "Loaders.h"
13 #include "Dlsbank.h"
14 #include "MIDIEvents.h"
15 #ifdef MODPLUG_TRACKER
16 #include "../mptrack/TrackerSettings.h"
17 #include "../mptrack/Moddoc.h"
18 #include "../mptrack/Mptrack.h"
19 #include "../common/mptFileIO.h"
20 #endif // MODPLUG_TRACKER
21
22 OPENMPT_NAMESPACE_BEGIN
23
24 #if defined(MODPLUG_TRACKER) || defined(MPT_FUZZ_TRACKER)
25
26 #ifdef LIBOPENMPT_BUILD
DLSMidiVolumeToLinearCDLSBank27 struct CDLSBank { static int32 DLSMidiVolumeToLinear(uint32) { return 256; } };
28 #endif // LIBOPENMPT_BUILD
29
30 #define MIDI_DRUMCHANNEL 10
31
32 const char *szMidiGroupNames[17] =
33 {
34 "Piano",
35 "Chromatic Percussion",
36 "Organ",
37 "Guitar",
38 "Bass",
39 "Strings",
40 "Ensemble",
41 "Brass",
42 "Reed",
43 "Pipe",
44 "Synth Lead",
45 "Synth Pad",
46 "Synth Effects",
47 "Ethnic",
48 "Percussive",
49 "Sound Effects",
50 "Percussions"
51 };
52
53
54 const char *szMidiProgramNames[128] =
55 {
56 // 1-8: Piano
57 "Acoustic Grand Piano",
58 "Bright Acoustic Piano",
59 "Electric Grand Piano",
60 "Honky-tonk Piano",
61 "Electric Piano 1",
62 "Electric Piano 2",
63 "Harpsichord",
64 "Clavi",
65 // 9-16: Chromatic Percussion
66 "Celesta",
67 "Glockenspiel",
68 "Music Box",
69 "Vibraphone",
70 "Marimba",
71 "Xylophone",
72 "Tubular Bells",
73 "Dulcimer",
74 // 17-24: Organ
75 "Drawbar Organ",
76 "Percussive Organ",
77 "Rock Organ",
78 "Church Organ",
79 "Reed Organ",
80 "Accordion",
81 "Harmonica",
82 "Tango Accordion",
83 // 25-32: Guitar
84 "Acoustic Guitar (nylon)",
85 "Acoustic Guitar (steel)",
86 "Electric Guitar (jazz)",
87 "Electric Guitar (clean)",
88 "Electric Guitar (muted)",
89 "Overdriven Guitar",
90 "Distortion Guitar",
91 "Guitar harmonics",
92 // 33-40 Bass
93 "Acoustic Bass",
94 "Electric Bass (finger)",
95 "Electric Bass (pick)",
96 "Fretless Bass",
97 "Slap Bass 1",
98 "Slap Bass 2",
99 "Synth Bass 1",
100 "Synth Bass 2",
101 // 41-48 Strings
102 "Violin",
103 "Viola",
104 "Cello",
105 "Contrabass",
106 "Tremolo Strings",
107 "Pizzicato Strings",
108 "Orchestral Harp",
109 "Timpani",
110 // 49-56 Ensemble
111 "String Ensemble 1",
112 "String Ensemble 2",
113 "SynthStrings 1",
114 "SynthStrings 2",
115 "Choir Aahs",
116 "Voice Oohs",
117 "Synth Voice",
118 "Orchestra Hit",
119 // 57-64 Brass
120 "Trumpet",
121 "Trombone",
122 "Tuba",
123 "Muted Trumpet",
124 "French Horn",
125 "Brass Section",
126 "SynthBrass 1",
127 "SynthBrass 2",
128 // 65-72 Reed
129 "Soprano Sax",
130 "Alto Sax",
131 "Tenor Sax",
132 "Baritone Sax",
133 "Oboe",
134 "English Horn",
135 "Bassoon",
136 "Clarinet",
137 // 73-80 Pipe
138 "Piccolo",
139 "Flute",
140 "Recorder",
141 "Pan Flute",
142 "Blown Bottle",
143 "Shakuhachi",
144 "Whistle",
145 "Ocarina",
146 // 81-88 Synth Lead
147 "Lead 1 (square)",
148 "Lead 2 (sawtooth)",
149 "Lead 3 (calliope)",
150 "Lead 4 (chiff)",
151 "Lead 5 (charang)",
152 "Lead 6 (voice)",
153 "Lead 7 (fifths)",
154 "Lead 8 (bass + lead)",
155 // 89-96 Synth Pad
156 "Pad 1 (new age)",
157 "Pad 2 (warm)",
158 "Pad 3 (polysynth)",
159 "Pad 4 (choir)",
160 "Pad 5 (bowed)",
161 "Pad 6 (metallic)",
162 "Pad 7 (halo)",
163 "Pad 8 (sweep)",
164 // 97-104 Synth Effects
165 "FX 1 (rain)",
166 "FX 2 (soundtrack)",
167 "FX 3 (crystal)",
168 "FX 4 (atmosphere)",
169 "FX 5 (brightness)",
170 "FX 6 (goblins)",
171 "FX 7 (echoes)",
172 "FX 8 (sci-fi)",
173 // 105-112 Ethnic
174 "Sitar",
175 "Banjo",
176 "Shamisen",
177 "Koto",
178 "Kalimba",
179 "Bag pipe",
180 "Fiddle",
181 "Shanai",
182 // 113-120 Percussive
183 "Tinkle Bell",
184 "Agogo",
185 "Steel Drums",
186 "Woodblock",
187 "Taiko Drum",
188 "Melodic Tom",
189 "Synth Drum",
190 "Reverse Cymbal",
191 // 121-128 Sound Effects
192 "Guitar Fret Noise",
193 "Breath Noise",
194 "Seashore",
195 "Bird Tweet",
196 "Telephone Ring",
197 "Helicopter",
198 "Applause",
199 "Gunshot"
200 };
201
202
203 // Notes 25-85
204 const char *szMidiPercussionNames[61] =
205 {
206 "Seq Click",
207 "Brush Tap",
208 "Brush Swirl",
209 "Brush Slap",
210 "Brush Swirl W/Attack",
211 "Snare Roll",
212 "Castanet",
213 "Snare Lo",
214 "Sticks",
215 "Bass Drum Lo",
216 "Open Rim Shot",
217 "Acoustic Bass Drum",
218 "Bass Drum 1",
219 "Side Stick",
220 "Acoustic Snare",
221 "Hand Clap",
222 "Electric Snare",
223 "Low Floor Tom",
224 "Closed Hi-Hat",
225 "High Floor Tom",
226 "Pedal Hi-Hat",
227 "Low Tom",
228 "Open Hi-Hat",
229 "Low-Mid Tom",
230 "Hi Mid Tom",
231 "Crash Cymbal 1",
232 "High Tom",
233 "Ride Cymbal 1",
234 "Chinese Cymbal",
235 "Ride Bell",
236 "Tambourine",
237 "Splash Cymbal",
238 "Cowbell",
239 "Crash Cymbal 2",
240 "Vibraslap",
241 "Ride Cymbal 2",
242 "Hi Bongo",
243 "Low Bongo",
244 "Mute Hi Conga",
245 "Open Hi Conga",
246 "Low Conga",
247 "High Timbale",
248 "Low Timbale",
249 "High Agogo",
250 "Low Agogo",
251 "Cabasa",
252 "Maracas",
253 "Short Whistle",
254 "Long Whistle",
255 "Short Guiro",
256 "Long Guiro",
257 "Claves",
258 "Hi Wood Block",
259 "Low Wood Block",
260 "Mute Cuica",
261 "Open Cuica",
262 "Mute Triangle",
263 "Open Triangle",
264 "Shaker",
265 "Jingle Bell",
266 "Bell Tree",
267 };
268
269
270 ////////////////////////////////////////////////////////////////////////////////
271 // Maps a midi instrument - returns the instrument number in the file
MapMidiInstrument(uint8 program,uint16 bank,uint8 midiChannel,uint8 note,bool isXG,std::bitset<16> drumChns)272 uint32 CSoundFile::MapMidiInstrument(uint8 program, uint16 bank, uint8 midiChannel, uint8 note, bool isXG, std::bitset<16> drumChns)
273 {
274 ModInstrument *pIns;
275 program &= 0x7F;
276 bank &= 0x3FFF;
277 note &= 0x7F;
278
279 // In XG mode, extra drums are on banks with MSB 7F
280 const bool isDrum = drumChns[midiChannel - 1] || (bank >= 0x3F80 && isXG);
281
282 for (uint32 i = 1; i <= m_nInstruments; i++) if (Instruments[i])
283 {
284 ModInstrument *p = Instruments[i];
285 // Drum Kit?
286 if (isDrum)
287 {
288 if (note == p->nMidiDrumKey && bank + 1 == p->wMidiBank) return i;
289 } else
290 // Melodic Instrument
291 {
292 if (program + 1 == p->nMidiProgram && bank + 1 == p->wMidiBank && p->nMidiDrumKey == 0) return i;
293 }
294 }
295 if(!CanAddMoreInstruments() || !CanAddMoreSamples())
296 return 0;
297
298 pIns = AllocateInstrument(m_nInstruments + 1);
299 if(pIns == nullptr)
300 {
301 return 0;
302 }
303
304 m_nSamples++;
305 pIns->wMidiBank = bank + 1;
306 pIns->nMidiProgram = program + 1;
307 pIns->nFadeOut = 1024;
308 pIns->nNNA = NewNoteAction::NoteOff;
309 pIns->nDCT = isDrum ? DuplicateCheckType::Sample : DuplicateCheckType::Note;
310 pIns->nDNA = DuplicateNoteAction::NoteFade;
311 if(isDrum)
312 {
313 pIns->nMidiChannel = MIDI_DRUMCHANNEL;
314 pIns->nMidiDrumKey = note;
315 for(auto &key : pIns->NoteMap)
316 {
317 key = NOTE_MIDDLEC;
318 }
319 }
320 pIns->VolEnv.dwFlags.set(ENV_ENABLED);
321 if (!isDrum) pIns->VolEnv.dwFlags.set(ENV_SUSTAIN);
322 pIns->VolEnv.reserve(4);
323 pIns->VolEnv.push_back(EnvelopeNode(0, ENVELOPE_MAX));
324 pIns->VolEnv.push_back(EnvelopeNode(10, ENVELOPE_MAX));
325 pIns->VolEnv.push_back(EnvelopeNode(15, (ENVELOPE_MAX + ENVELOPE_MID) / 2));
326 pIns->VolEnv.push_back(EnvelopeNode(20, ENVELOPE_MIN));
327 pIns->VolEnv.nSustainStart = pIns->VolEnv.nSustainEnd = 1;
328 // Set GM program / drum name
329 if (!isDrum)
330 {
331 pIns->name = szMidiProgramNames[program];
332 } else
333 {
334 if (note >= 24 && note <= 84)
335 pIns->name = szMidiPercussionNames[note - 24];
336 else
337 pIns->name = "Percussions";
338 }
339 return m_nInstruments;
340 }
341
342
343 struct MThd
344 {
345 uint32be headerLength;
346 uint16be format; // 0 = single-track, 1 = multi-track, 2 = multi-song
347 uint16be numTracks; // Number of track chunks
348 uint16be division; // Delta timing value: positive = units/beat; negative = smpte compatible units
349 };
350
351 MPT_BINARY_STRUCT(MThd, 10)
352
353
354 using tick_t = uint32;
355
356 struct TrackState
357 {
358 FileReader track;
359 tick_t nextEvent = 0;
360 uint8 command = 0;
361 bool finished = false;
362 };
363
364 struct ModChannelState
365 {
366 static constexpr uint8 NOMIDI = 0xFF; // No MIDI channel assigned.
367
368 tick_t age = 0; // At which MIDI tick the channel was triggered
369 int32 porta = 0; // Current portamento position in extra-fine slide units (1/64th of a semitone)
370 uint8 vol = 100; // MIDI note volume (0...127)
371 uint8 pan = 128; // MIDI channel panning (0...256)
372 uint8 midiCh = NOMIDI; // MIDI channel that was last played on this channel
373 ModCommand::NOTE note = NOTE_NONE; // MIDI note that was last played on this channel
374 bool sustained = false; // If true, the note was already released by a note-off event, but sustain pedal CC is still active
375 };
376
377 struct MidiChannelState
378 {
379 int32 pitchbendMod = 0; // Pre-computed pitchbend in extra-fine slide units (1/64th of a semitone)
380 int16 pitchbend = MIDIEvents::pitchBendCentre; // 0...16383
381 uint16 bank = 0; // 0...16383
382 uint8 program = 0; // 0...127
383 // -- Controllers ---------------- function ---------- CC# --- range ---- init (midi) ---
384 uint8 pan = 128; // Channel Panning 10 [0-255] 128 (64)
385 uint8 expression = 128; // Channel Expression 11 0-128 128 (127)
386 uint8 volume = 80; // Channel Volume 7 0-128 80 (100)
387 uint16 rpn = 0x3FFF; // Currently selected RPN 100/101 n/a
388 uint8 pitchBendRange = 2; // Pitch Bend Range 2
389 int8 transpose = 0; // Channel transpose 0
390 bool monoMode = false; // Mono/Poly operation 126/127 n/a Poly
391 bool sustain = false; // Sustain pedal 64 on/off off
392
393 std::array<CHANNELINDEX, 128> noteOn; // Value != CHANNELINDEX_INVALID: Note is active and mapped to mod channel in value
394
MidiChannelStateMidiChannelState395 MidiChannelState()
396 {
397 noteOn.fill(CHANNELINDEX_INVALID);
398 }
399
SetPitchbendMidiChannelState400 void SetPitchbend(uint16 value)
401 {
402 pitchbend = value;
403 // Convert from arbitrary MIDI pitchbend to 64th of semitone
404 pitchbendMod = Util::muldiv(pitchbend - MIDIEvents::pitchBendCentre, pitchBendRange * 64, MIDIEvents::pitchBendCentre);
405 }
406
ResetAllControllersMidiChannelState407 void ResetAllControllers()
408 {
409 expression = 128;
410 pitchBendRange = 2;
411 SetPitchbend(MIDIEvents::pitchBendCentre);
412 transpose = 0;
413 rpn = 0x3FFF;
414 monoMode = false;
415 sustain = false;
416 // Should also reset modulation, pedals (40h-43h), aftertouch
417 }
418
SetRPNMidiChannelState419 void SetRPN(uint8 value)
420 {
421 switch(rpn)
422 {
423 case 0: // Pitch Bend Range
424 pitchBendRange = std::max(value, uint8(1));
425 SetPitchbend(pitchbend);
426 break;
427 case 2: // Coarse Tune
428 transpose = static_cast<int8>(value) - 64;
429 break;
430 }
431 }
432
SetRPNRelativeMidiChannelState433 void SetRPNRelative(int8 value)
434 {
435 switch(rpn)
436 {
437 case 0: // Pitch Bend Range
438 pitchBendRange = static_cast<uint8>(std::clamp(pitchBendRange + value, 1, 0x7F));
439 break;
440 case 2: // Coarse Tune
441 transpose = mpt::saturate_cast<int8>(transpose + value);
442 break;
443 }
444 }
445 };
446
447
FindUnusedChannel(uint8 midiCh,ModCommand::NOTE note,const std::vector<ModChannelState> & channels,bool monoMode,PatternRow patRow)448 static CHANNELINDEX FindUnusedChannel(uint8 midiCh, ModCommand::NOTE note, const std::vector<ModChannelState> &channels, bool monoMode, PatternRow patRow)
449 {
450 for(size_t i = 0; i < channels.size(); i++)
451 {
452 // Check if this note is already playing, or find any note of the same MIDI channel in case of mono mode
453 if(channels[i].midiCh == midiCh && (channels[i].note == note || (monoMode && channels[i].note != NOTE_NONE)))
454 {
455 return static_cast<CHANNELINDEX>(i);
456 }
457 }
458
459 CHANNELINDEX anyUnusedChannel = CHANNELINDEX_INVALID;
460 CHANNELINDEX anyFreeChannel = CHANNELINDEX_INVALID;
461
462 CHANNELINDEX oldsetMidiCh = CHANNELINDEX_INVALID;
463 tick_t oldestMidiChAge = std::numeric_limits<decltype(oldestMidiChAge)>::max();
464
465 CHANNELINDEX oldestAnyCh = 0;
466 tick_t oldestAnyChAge = std::numeric_limits<decltype(oldestAnyChAge)>::max();
467
468 for(size_t i = 0; i < channels.size(); i++)
469 {
470 if(channels[i].note == NOTE_NONE && !patRow[i].IsNote())
471 {
472 // Recycle channel previously used by the same MIDI channel
473 if(channels[i].midiCh == midiCh)
474 return static_cast<CHANNELINDEX>(i);
475 // If we cannot find a channel that was already used for the same MIDI channel, try a completely unused channel next
476 else if(channels[i].midiCh == ModChannelState::NOMIDI && anyUnusedChannel == CHANNELINDEX_INVALID)
477 anyUnusedChannel = static_cast<CHANNELINDEX>(i);
478 // And if that fails, try any channel that currently doesn't play a note.
479 if(anyFreeChannel == CHANNELINDEX_INVALID)
480 anyFreeChannel = static_cast<CHANNELINDEX>(i);
481 }
482
483 // If we can't find any free channels, look for the oldest channels
484 if(channels[i].midiCh == midiCh && channels[i].age < oldestMidiChAge)
485 {
486 // Oldest channel matching this MIDI channel
487 oldestMidiChAge = channels[i].age;
488 oldsetMidiCh = static_cast<CHANNELINDEX>(i);
489 } else if(channels[i].age < oldestAnyChAge)
490 {
491 // Any oldest channel
492 oldestAnyChAge = channels[i].age;
493 oldestAnyCh = static_cast<CHANNELINDEX>(i);
494 }
495 }
496 if(anyUnusedChannel != CHANNELINDEX_INVALID)
497 return anyUnusedChannel;
498 if(anyFreeChannel != CHANNELINDEX_INVALID)
499 return anyFreeChannel;
500 if(oldsetMidiCh != CHANNELINDEX_INVALID)
501 return oldsetMidiCh;
502 return oldestAnyCh;
503 }
504
505
MIDINoteOff(MidiChannelState & midiChn,std::vector<ModChannelState> & modChnStatus,uint8 note,uint8 delay,PatternRow patRow,std::bitset<16> drumChns)506 static void MIDINoteOff(MidiChannelState &midiChn, std::vector<ModChannelState> &modChnStatus, uint8 note, uint8 delay, PatternRow patRow, std::bitset<16> drumChns)
507 {
508 CHANNELINDEX chn = midiChn.noteOn[note];
509 if(chn == CHANNELINDEX_INVALID)
510 return;
511
512 if(midiChn.sustain)
513 {
514 // Turn this off later
515 modChnStatus[chn].sustained = true;
516 return;
517 }
518
519 uint8 midiCh = modChnStatus[chn].midiCh;
520 modChnStatus[chn].note = NOTE_NONE;
521 modChnStatus[chn].sustained = false;
522 midiChn.noteOn[note] = CHANNELINDEX_INVALID;
523 ModCommand &m = patRow[chn];
524 if(m.note == NOTE_NONE)
525 {
526 m.note = NOTE_KEYOFF;
527 if(delay != 0)
528 {
529 m.command = CMD_S3MCMDEX;
530 m.param = 0xD0 | delay;
531 }
532 } else if(m.IsNote() && !drumChns[midiCh])
533 {
534 // Only do note cuts for melodic instruments - they sound weird on drums which should fade out naturally.
535 if(m.command == CMD_S3MCMDEX && (m.param & 0xF0) == 0xD0)
536 {
537 // Already have a note delay
538 m.command = CMD_DELAYCUT;
539 m.param = (m.param << 4) | (delay - (m.param & 0x0F));
540 } else if(m.command == CMD_NONE || m.command == CMD_PANNING8)
541 {
542 m.command = CMD_S3MCMDEX;
543 m.param = 0xC0 | delay;
544 }
545 }
546 }
547
548
EnterMIDIVolume(ModCommand & m,ModChannelState & modChn,const MidiChannelState & midiChn)549 static void EnterMIDIVolume(ModCommand &m, ModChannelState &modChn, const MidiChannelState &midiChn)
550 {
551 m.volcmd = VOLCMD_VOLUME;
552
553 int32 vol = CDLSBank::DLSMidiVolumeToLinear(modChn.vol) >> 8;
554 vol = (vol * midiChn.volume * midiChn.expression) >> 13;
555 Limit(vol, 4, 256);
556 m.vol = static_cast<ModCommand::VOL>(vol / 4);
557 }
558
559
ProbeFileHeaderMID(MemoryFileReader file,const uint64 * pfilesize)560 CSoundFile::ProbeResult CSoundFile::ProbeFileHeaderMID(MemoryFileReader file, const uint64 *pfilesize)
561 {
562 MPT_UNREFERENCED_PARAMETER(pfilesize);
563 char magic[4];
564 file.ReadArray(magic);
565 if(!memcmp(magic, "MThd", 4))
566 return ProbeSuccess;
567
568 if(!memcmp(magic, "RIFF", 4) && file.Skip(4) && file.ReadMagic("RMID"))
569 return ProbeSuccess;
570
571 return ProbeFailure;
572 }
573
574
ReadMID(FileReader & file,ModLoadingFlags loadFlags)575 bool CSoundFile::ReadMID(FileReader &file, ModLoadingFlags loadFlags)
576 {
577 file.Rewind();
578
579 // Microsoft MIDI files
580 bool isRIFF = false;
581 if(file.ReadMagic("RIFF"))
582 {
583 file.Skip(4);
584 if(!file.ReadMagic("RMID"))
585 {
586 return false;
587 } else if(loadFlags == onlyVerifyHeader)
588 {
589 return true;
590 }
591 do
592 {
593 char id[4];
594 file.ReadArray(id);
595 uint32 length = file.ReadUint32LE();
596 if(memcmp(id, "data", 4))
597 {
598 file.Skip(length);
599 } else
600 {
601 isRIFF = true;
602 break;
603 }
604 } while(file.CanRead(8));
605 }
606
607 MThd fileHeader;
608 if(!file.ReadMagic("MThd")
609 || !file.ReadStruct(fileHeader)
610 || fileHeader.numTracks == 0
611 || fileHeader.headerLength < 6
612 || !file.Skip(fileHeader.headerLength - 6))
613 {
614 return false;
615 } else if(loadFlags == onlyVerifyHeader)
616 {
617 return true;
618 }
619
620 InitializeGlobals(MOD_TYPE_MID);
621 InitializeChannels();
622
623 #ifdef MODPLUG_TRACKER
624 const uint32 quantize = Clamp(TrackerSettings::Instance().midiImportQuantize.Get(), 4u, 256u);
625 const ROWINDEX patternLen = Clamp(TrackerSettings::Instance().midiImportPatternLen.Get(), ROWINDEX(1), MAX_PATTERN_ROWS);
626 const uint8 ticksPerRow = Clamp(TrackerSettings::Instance().midiImportTicks.Get(), uint8(2), uint8(16));
627 #else
628 const uint32 quantize = 32; // Must be 4 or higher
629 const ROWINDEX patternLen = 128;
630 const uint8 ticksPerRow = 16; // Must be in range 2...16
631 #endif
632 #ifdef MPT_FUZZ_TRACKER
633 // Avoid generating test cases that take overly long to evaluate
634 const ORDERINDEX MPT_MIDI_IMPORT_MAX_ORDERS = 64;
635 #else
636 const ORDERINDEX MPT_MIDI_IMPORT_MAX_ORDERS = MAX_ORDERS;
637 #endif
638
639 m_songArtist = U_("MIDI Conversion");
640 m_modFormat.formatName = U_("Standard MIDI File");
641 m_modFormat.type = isRIFF ? UL_("rmi") : UL_("mid");
642 m_modFormat.madeWithTracker = U_("Standard MIDI File");
643 m_modFormat.charset = mpt::Charset::ISO8859_1;
644
645 SetMixLevels(MixLevels::v1_17RC3);
646 m_nTempoMode = TempoMode::Modern;
647 m_SongFlags = SONG_LINEARSLIDES;
648 m_nDefaultTempo.Set(120);
649 m_nDefaultSpeed = ticksPerRow;
650 m_nChannels = MAX_BASECHANNELS;
651 m_nDefaultRowsPerBeat = quantize / 4;
652 m_nDefaultRowsPerMeasure = 4 * m_nDefaultRowsPerBeat;
653 m_nSamplePreAmp = m_nVSTiVolume = 32;
654 TEMPO tempo = m_nDefaultTempo;
655 uint16 ppqn = fileHeader.division;
656 if(ppqn & 0x8000)
657 {
658 // SMPTE compatible units (approximation)
659 int frames = 256 - (ppqn >> 8), subFrames = (ppqn & 0xFF);
660 ppqn = static_cast<uint16>(frames * subFrames / 2);
661 }
662 if(!ppqn)
663 ppqn = 96;
664 Order().clear();
665
666 MidiChannelState midiChnStatus[16];
667 const CHANNELINDEX tempoChannel = m_nChannels - 2, globalVolChannel = m_nChannels - 1;
668 const uint16 numTracks = fileHeader.numTracks;
669 std::vector<TrackState> tracks(numTracks);
670 std::vector<ModChannelState> modChnStatus(m_nChannels);
671 std::bitset<16> drumChns;
672 drumChns.set(MIDI_DRUMCHANNEL - 1);
673
674 tick_t timeShift = 0;
675 for(auto &track : tracks)
676 {
677 if(!file.ReadMagic("MTrk"))
678 return false;
679 track.track = file.ReadChunk(file.ReadUint32BE());
680 tick_t delta = 0;
681 track.track.ReadVarInt(delta);
682 // Work-around for some MID files that assume that negative deltas exist (they don't according to the standard)
683 if(delta > int32_max)
684 timeShift = std::max(static_cast<tick_t>(~delta + 1), timeShift);
685 track.nextEvent = delta;
686 }
687 if(timeShift != 0)
688 {
689 for(auto &track : tracks)
690 {
691 if(track.nextEvent > int32_max)
692 track.nextEvent = timeShift - static_cast<tick_t>(~track.nextEvent + 1);
693 else
694 track.nextEvent += timeShift;
695 }
696 }
697
698 uint16 finishedTracks = 0;
699 PATTERNINDEX emptyPattern = PATTERNINDEX_INVALID;
700 ORDERINDEX lastOrd = 0, loopEndOrd = ORDERINDEX_INVALID;
701 ROWINDEX lastRow = 0, loopEndRow = ROWINDEX_INVALID;
702 ROWINDEX restartRow = ROWINDEX_INVALID;
703 int8 masterTranspose = 0;
704 bool isXG = false;
705 bool isEMIDI = false;
706 bool isEMIDILoop = false;
707 const bool isType2 = (fileHeader.format == 2);
708
709 const auto ModPositionFromTick = [&](const tick_t tick, const tick_t offset = 0)
710 {
711 tick_t modTicks = Util::muldivr_unsigned(tick, quantize * ticksPerRow, ppqn * 4u) - offset;
712
713 ORDERINDEX ord = static_cast<ORDERINDEX>((modTicks / ticksPerRow) / patternLen);
714 ROWINDEX row = (modTicks / ticksPerRow) % patternLen;
715 uint8 delay = static_cast<uint8>(modTicks % ticksPerRow);
716
717 return std::make_tuple(ord, row, delay);
718 };
719
720 while(finishedTracks < numTracks)
721 {
722 uint16 t = 0;
723 tick_t tick = std::numeric_limits<decltype(tick)>::max();
724 for(uint16 track = 0; track < numTracks; track++)
725 {
726 if(!tracks[track].finished && tracks[track].nextEvent < tick)
727 {
728 tick = tracks[track].nextEvent;
729 t = track;
730 if(isType2)
731 break;
732 }
733 }
734 FileReader &track = tracks[t].track;
735
736 const auto [ord, row, delay] = ModPositionFromTick(tick);
737
738 if(ord >= Order().GetLength())
739 {
740 if(ord > MPT_MIDI_IMPORT_MAX_ORDERS)
741 break;
742 ORDERINDEX curSize = Order().GetLength();
743 // If we need to extend the order list by more than one pattern, this means that we
744 // will be filling in empty patterns. Just recycle one empty pattern for this job.
745 // We read events in chronological order, so it is never possible for the loader to
746 // "jump back" to one of those empty patterns and write into it.
747 if(ord > curSize && emptyPattern == PATTERNINDEX_INVALID)
748 {
749 if((emptyPattern = Patterns.InsertAny(patternLen)) == PATTERNINDEX_INVALID)
750 break;
751 }
752 Order().resize(ord + 1, emptyPattern);
753
754 if((Order()[ord] = Patterns.InsertAny(patternLen)) == PATTERNINDEX_INVALID)
755 break;
756 }
757
758 // Keep track of position of last event for resizing the last pattern
759 if(ord > lastOrd)
760 {
761 lastOrd = ord;
762 lastRow = row;
763 } else if(ord == lastOrd)
764 {
765 lastRow = std::max(lastRow, row);
766 }
767
768 PATTERNINDEX pat = Order()[ord];
769 PatternRow patRow = Patterns[pat].GetRow(row);
770
771 uint8 data1 = track.ReadUint8();
772 if(data1 == 0xFF)
773 {
774 // Meta events
775 data1 = track.ReadUint8();
776 size_t len = 0;
777 track.ReadVarInt(len);
778 FileReader chunk = track.ReadChunk(len);
779
780 switch(data1)
781 {
782 case 1: // Text
783 case 2: // Copyright
784 m_songMessage.Read(chunk, len, SongMessage::leAutodetect);
785 break;
786 case 3: // Track Name
787 if(len > 0)
788 {
789 std::string s;
790 chunk.ReadString<mpt::String::maybeNullTerminated>(s, len);
791 if(!m_songMessage.empty())
792 m_songMessage.append(1, SongMessage::InternalLineEnding);
793 m_songMessage += s;
794 if(m_songName.empty())
795 m_songName = s;
796 }
797 break;
798 case 4: // Instrument
799 case 5: // Lyric
800 break;
801 case 6: // Marker
802 case 7: // Cue point
803 {
804 std::string s;
805 chunk.ReadString<mpt::String::maybeNullTerminated>(s, len);
806 Patterns[pat].SetName(s);
807 if(!mpt::CompareNoCaseAscii(s, "loopStart"))
808 {
809 Order().SetRestartPos(ord);
810 restartRow = row;
811 } else if(!mpt::CompareNoCaseAscii(s, "loopEnd"))
812 {
813 std::tie(loopEndOrd, loopEndRow, std::ignore) = ModPositionFromTick(tick, 1);
814 }
815 }
816 break;
817 case 8: // Patch name
818 case 9: // Port name
819 break;
820 case 0x2F: // End Of Track
821 tracks[t].finished = true;
822 break;
823 case 0x51: // Tempo
824 {
825 uint32 tempoInt = chunk.ReadUint24BE();
826 if(tempoInt == 0)
827 break;
828 TEMPO newTempo(60000000.0 / tempoInt);
829 if(!tick)
830 {
831 m_nDefaultTempo = newTempo;
832 } else if(newTempo != tempo)
833 {
834 patRow[tempoChannel].command = CMD_TEMPO;
835 patRow[tempoChannel].param = mpt::saturate_round<ModCommand::PARAM>(std::max(32.0, newTempo.ToDouble()));
836 }
837 tempo = newTempo;
838 }
839 break;
840
841 default:
842 break;
843 }
844 } else
845 {
846 uint8 command = tracks[t].command;
847 if(data1 & 0x80)
848 {
849 // Command byte (if not present, use running status for channel messages)
850 command = data1;
851 if(data1 < 0xF0)
852 {
853 tracks[t].command = data1;
854 data1 = track.ReadUint8();
855 }
856 }
857 uint8 midiCh = command & 0x0F;
858
859 switch(command & 0xF0)
860 {
861 case 0x80: // Note Off
862 case 0x90: // Note On
863 {
864 data1 &= 0x7F;
865 ModCommand::NOTE note = static_cast<ModCommand::NOTE>(Clamp(data1 + NOTE_MIN, NOTE_MIN, NOTE_MAX));
866 uint8 data2 = track.ReadUint8();
867 if(data2 > 0 && (command & 0xF0) == 0x90)
868 {
869 // Note On
870 CHANNELINDEX chn = FindUnusedChannel(midiCh, note, modChnStatus, midiChnStatus[midiCh].monoMode, patRow);
871 if(chn != CHANNELINDEX_INVALID)
872 {
873 modChnStatus[chn].age = tick;
874 modChnStatus[chn].note = note;
875 modChnStatus[chn].midiCh = midiCh;
876 modChnStatus[chn].vol = data2;
877 modChnStatus[chn].sustained = false;
878 midiChnStatus[midiCh].noteOn[data1] = chn;
879 int32 pitchOffset = 0;
880 if(midiChnStatus[midiCh].pitchbendMod != 0)
881 {
882 pitchOffset = (midiChnStatus[midiCh].pitchbendMod + (midiChnStatus[midiCh].pitchbendMod > 0 ? 32 : -32)) / 64;
883 modChnStatus[chn].porta = pitchOffset * 64;
884 } else
885 {
886 modChnStatus[chn].porta = 0;
887 }
888 patRow[chn].note = static_cast<ModCommand::NOTE>(Clamp(note + pitchOffset + midiChnStatus[midiCh].transpose + masterTranspose, NOTE_MIN, NOTE_MAX));
889 patRow[chn].instr = mpt::saturate_cast<ModCommand::INSTR>(MapMidiInstrument(midiChnStatus[midiCh].program, midiChnStatus[midiCh].bank, midiCh + 1, data1, isXG, drumChns));
890 EnterMIDIVolume(patRow[chn], modChnStatus[chn], midiChnStatus[midiCh]);
891
892 if(patRow[chn].command == CMD_PORTAMENTODOWN || patRow[chn].command == CMD_PORTAMENTOUP)
893 {
894 patRow[chn].command = CMD_NONE;
895 }
896 if(delay != 0)
897 {
898 patRow[chn].command = CMD_S3MCMDEX;
899 patRow[chn].param = 0xD0 | delay;
900 }
901 if(modChnStatus[chn].pan != midiChnStatus[midiCh].pan && patRow[chn].command == CMD_NONE)
902 {
903 patRow[chn].command = CMD_PANNING8;
904 patRow[chn].param = midiChnStatus[midiCh].pan;
905 modChnStatus[chn].pan = midiChnStatus[midiCh].pan;
906 }
907 }
908 } else
909 {
910 // Note Off
911 MIDINoteOff(midiChnStatus[midiCh], modChnStatus, data1, delay, patRow, drumChns);
912 }
913 }
914 break;
915 case 0xA0: // Note Aftertouch
916 {
917 track.Skip(1);
918 }
919 break;
920 case 0xB0: // Controller
921 {
922 uint8 data2 = track.ReadUint8();
923 switch(data1)
924 {
925 case MIDIEvents::MIDICC_Panposition_Coarse:
926 midiChnStatus[midiCh].pan = data2 * 2u;
927 for(auto chn : midiChnStatus[midiCh].noteOn)
928 {
929 if(chn != CHANNELINDEX_INVALID && modChnStatus[chn].pan != midiChnStatus[midiCh].pan)
930 {
931 if(Patterns[pat].WriteEffect(EffectWriter(CMD_PANNING8, midiChnStatus[midiCh].pan).Channel(chn).Row(row)))
932 {
933 modChnStatus[chn].pan = midiChnStatus[midiCh].pan;
934 }
935 }
936 }
937 break;
938
939 case MIDIEvents::MIDICC_DataEntry_Coarse:
940 midiChnStatus[midiCh].SetRPN(data2);
941 break;
942
943 case MIDIEvents::MIDICC_Volume_Coarse:
944 midiChnStatus[midiCh].volume = (uint8)(CDLSBank::DLSMidiVolumeToLinear(data2) >> 9);
945 for(auto chn : midiChnStatus[midiCh].noteOn)
946 {
947 if(chn != CHANNELINDEX_INVALID)
948 {
949 EnterMIDIVolume(patRow[chn], modChnStatus[chn], midiChnStatus[midiCh]);
950 }
951 }
952 break;
953
954 case MIDIEvents::MIDICC_Expression_Coarse:
955 midiChnStatus[midiCh].expression = (uint8)(CDLSBank::DLSMidiVolumeToLinear(data2) >> 9);
956 for(auto chn : midiChnStatus[midiCh].noteOn)
957 {
958 if(chn != CHANNELINDEX_INVALID)
959 {
960 EnterMIDIVolume(patRow[chn], modChnStatus[chn], midiChnStatus[midiCh]);
961 }
962 }
963 break;
964
965 case MIDIEvents::MIDICC_BankSelect_Coarse:
966 midiChnStatus[midiCh].bank &= 0x7F;
967 midiChnStatus[midiCh].bank |= (data2 << 7);
968 break;
969
970 case MIDIEvents::MIDICC_BankSelect_Fine:
971 midiChnStatus[midiCh].bank &= (0x7F << 7);
972 midiChnStatus[midiCh].bank |= data2;
973 break;
974
975 case MIDIEvents::MIDICC_HoldPedal_OnOff:
976 midiChnStatus[midiCh].sustain = (data2 >= 0x40);
977 if(data2 < 0x40)
978 {
979 // Release notes that are still being held after note-off
980 for(const auto &chnState : modChnStatus)
981 {
982 if(chnState.midiCh == midiCh && chnState.sustained && chnState.note != NOTE_NONE)
983 {
984 MIDINoteOff(midiChnStatus[midiCh], modChnStatus, chnState.note - NOTE_MIN, delay, patRow, drumChns);
985 }
986 }
987 }
988 break;
989
990 case MIDIEvents::MIDICC_DataButtonincrement:
991 case MIDIEvents::MIDICC_DataButtondecrement:
992 midiChnStatus[midiCh].SetRPNRelative((data1 == MIDIEvents::MIDICC_DataButtonincrement) ? 1 : -1);
993 break;
994
995 case MIDIEvents::MIDICC_NonRegisteredParameter_Fine:
996 case MIDIEvents::MIDICC_NonRegisteredParameter_Coarse:
997 midiChnStatus[midiCh].rpn = 0x3FFF;
998 break;
999
1000 case MIDIEvents::MIDICC_RegisteredParameter_Fine:
1001 midiChnStatus[midiCh].rpn &= (0x7F << 7);
1002 midiChnStatus[midiCh].rpn |= data2;
1003 break;
1004 case MIDIEvents::MIDICC_RegisteredParameter_Coarse:
1005 midiChnStatus[midiCh].rpn &= 0x7F;
1006 midiChnStatus[midiCh].rpn |= (data2 << 7);
1007 break;
1008
1009 case 110:
1010 isEMIDI = true;
1011 break;
1012
1013 case 111:
1014 // Non-standard MIDI loop point. May conflict with Apogee EMIDI CCs (110/111), which is why we also check if CC 110 is ever used.
1015 if(data2 == 0 && !isEMIDI)
1016 {
1017 Order().SetRestartPos(ord);
1018 restartRow = row;
1019 }
1020 break;
1021
1022 case 118:
1023 // EMIDI Global Loop Start
1024 isEMIDI = true;
1025 isEMIDILoop = false;
1026 Order().SetRestartPos(ord);
1027 restartRow = row;
1028 break;
1029
1030 case 119:
1031 // EMIDI Global Loop End
1032 if(data2 == 0x7F)
1033 {
1034 isEMIDILoop = true;
1035 isEMIDI = true;
1036 std::tie(loopEndOrd, loopEndRow, std::ignore) = ModPositionFromTick(tick, 1);
1037 }
1038 break;
1039
1040 case MIDIEvents::MIDICC_AllControllersOff:
1041 midiChnStatus[midiCh].ResetAllControllers();
1042 break;
1043
1044 // Bn.78.00: All Sound Off (GS)
1045 // Bn.7B.00: All Notes Off (GM)
1046 case MIDIEvents::MIDICC_AllSoundOff:
1047 case MIDIEvents::MIDICC_AllNotesOff:
1048 // All Notes Off
1049 midiChnStatus[midiCh].sustain = false;
1050 for(uint8 note = 0; note < 128; note++)
1051 {
1052 MIDINoteOff(midiChnStatus[midiCh], modChnStatus, note, delay, patRow, drumChns);
1053 }
1054 break;
1055 case MIDIEvents::MIDICC_MonoOperation:
1056 if(data2 == 0)
1057 {
1058 midiChnStatus[midiCh].monoMode = true;
1059 }
1060 break;
1061 case MIDIEvents::MIDICC_PolyOperation:
1062 if(data2 == 0)
1063 {
1064 midiChnStatus[midiCh].monoMode = false;
1065 }
1066 break;
1067 }
1068 }
1069 break;
1070 case 0xC0: // Program Change
1071 midiChnStatus[midiCh].program = data1 & 0x7F;
1072 break;
1073 case 0xD0: // Channel aftertouch
1074 break;
1075 case 0xE0: // Pitch bend
1076 midiChnStatus[midiCh].SetPitchbend(data1 | (track.ReadUint8() << 7));
1077 break;
1078 case 0xF0: // General / Immediate
1079 switch(midiCh)
1080 {
1081 case MIDIEvents::sysExStart: // SysEx
1082 case MIDIEvents::sysExEnd: // SysEx (continued)
1083 {
1084 uint32 len;
1085 track.ReadVarInt(len);
1086 FileReader sysex = track.ReadChunk(len);
1087 if(midiCh == MIDIEvents::sysExEnd)
1088 break;
1089
1090 if(sysex.ReadMagic("\x7F\x7F\x04\x01"))
1091 {
1092 // Master volume
1093 uint8 volumeRaw[2];
1094 sysex.ReadArray(volumeRaw);
1095 uint16 globalVol = volumeRaw[0] | (volumeRaw[1] << 7);
1096 if(tick == 0)
1097 {
1098 m_nDefaultGlobalVolume = Util::muldivr_unsigned(globalVol, MAX_GLOBAL_VOLUME, 16383);
1099 } else
1100 {
1101 patRow[globalVolChannel].command = CMD_GLOBALVOLUME;
1102 patRow[globalVolChannel].param = static_cast<ModCommand::PARAM>(Util::muldivr_unsigned(globalVol, 128, 16383));
1103 }
1104 } else
1105 {
1106 uint8 xg[7];
1107 sysex.ReadArray(xg);
1108 if(!memcmp(xg, "\x43\x10\x4C\x00\x00\x7E\x00", 7))
1109 {
1110 // XG System On
1111 isXG = true;
1112 } else if(!memcmp(xg, "\x43\x10\x4C\x00\x00\x06", 6))
1113 {
1114 // XG Master Transpose
1115 masterTranspose = static_cast<int8>(xg[6]) - 64;
1116 } else if(!memcmp(xg, "\x41\x10\x42\x12\x40", 5) && (xg[5] & 0xF0) == 0x10 && xg[6] == 0x15)
1117 {
1118 // GS Drum Kit
1119 uint8 chn = xg[5] & 0x0F;
1120 if(chn == 0)
1121 chn = 9;
1122 else if(chn < 10)
1123 chn--;
1124 drumChns.set(chn, sysex.ReadUint8() != 0);
1125 }
1126 }
1127 }
1128 break;
1129 case MIDIEvents::sysQuarterFrame:
1130 track.Skip(1);
1131 break;
1132 case MIDIEvents::sysPositionPointer:
1133 track.Skip(2);
1134 break;
1135 case MIDIEvents::sysSongSelect:
1136 track.Skip(1);
1137 break;
1138 case MIDIEvents::sysTuneRequest:
1139 case MIDIEvents::sysMIDIClock:
1140 case MIDIEvents::sysMIDITick:
1141 case MIDIEvents::sysStart:
1142 case MIDIEvents::sysContinue:
1143 case MIDIEvents::sysStop:
1144 case MIDIEvents::sysActiveSense:
1145 case MIDIEvents::sysReset:
1146 break;
1147
1148 default:
1149 break;
1150 }
1151 break;
1152
1153 default:
1154 break;
1155 }
1156 }
1157
1158 // Pitch bend any channels that haven't reached their target yet
1159 // TODO: This is currently not called on any rows without events!
1160 for(size_t chn = 0; chn < modChnStatus.size(); chn++)
1161 {
1162 ModChannelState &chnState = modChnStatus[chn];
1163 ModCommand &m = patRow[chn];
1164 uint8 midiCh = chnState.midiCh;
1165 if(chnState.note == NOTE_NONE || m.command == CMD_S3MCMDEX || m.command == CMD_DELAYCUT || midiCh == ModChannelState::NOMIDI)
1166 continue;
1167
1168 int32 diff = midiChnStatus[midiCh].pitchbendMod - chnState.porta;
1169 if(diff == 0)
1170 continue;
1171
1172 if(m.command == CMD_PORTAMENTODOWN || m.command == CMD_PORTAMENTOUP)
1173 {
1174 // First, undo the effect of an existing portamento command
1175 int32 porta = 0;
1176 if(m.param < 0xE0)
1177 porta = m.param * 4 * (ticksPerRow - 1);
1178 else if(m.param < 0xF0)
1179 porta = (m.param & 0x0F);
1180 else
1181 porta = (m.param & 0x0F) * 4;
1182
1183 if(m.command == CMD_PORTAMENTODOWN)
1184 porta = -porta;
1185
1186 diff += porta;
1187 chnState.porta -= porta;
1188
1189 if(diff == 0)
1190 {
1191 m.command = CMD_NONE;
1192 continue;
1193 }
1194 }
1195
1196 m.command = static_cast<ModCommand::COMMAND>(diff < 0 ? CMD_PORTAMENTODOWN : CMD_PORTAMENTOUP);
1197 int32 absDiff = std::abs(diff);
1198 int32 realDiff = 0;
1199 if(absDiff < 16)
1200 {
1201 // Extra-fine slides can do this.
1202 m.param = 0xE0 | static_cast<uint8>(absDiff);
1203 realDiff = absDiff;
1204 } else if(absDiff < 64)
1205 {
1206 // Fine slides can do this.
1207 absDiff = std::min((absDiff + 3) / 4, 0x0F);
1208 m.param = 0xF0 | static_cast<uint8>(absDiff);
1209 realDiff = absDiff * 4;
1210 } else
1211 {
1212 // Need a normal slide.
1213 absDiff /= 4 * (ticksPerRow - 1);
1214 LimitMax(absDiff, 0xDF);
1215 m.param = static_cast<uint8>(absDiff);
1216 realDiff = absDiff * 4 * (ticksPerRow - 1);
1217 }
1218 chnState.porta += realDiff * mpt::signum(diff);
1219 }
1220
1221 tick_t delta = 0;
1222 if(track.ReadVarInt(delta) && track.CanRead(1))
1223 {
1224 tracks[t].nextEvent += delta;
1225 } else
1226 {
1227 finishedTracks++;
1228 tracks[t].nextEvent = Util::MaxValueOfType(delta);
1229 tracks[t].finished = true;
1230 // Add another sub-song for type-2 files
1231 if(isType2 && finishedTracks < numTracks)
1232 {
1233 if(Order.AddSequence() == SEQUENCEINDEX_INVALID)
1234 break;
1235 Order().clear();
1236 }
1237 }
1238 }
1239
1240 if(isEMIDILoop)
1241 isEMIDI = false;
1242
1243 if(isEMIDI)
1244 {
1245 Order().SetRestartPos(0);
1246 }
1247
1248 if(loopEndOrd == ORDERINDEX_INVALID)
1249 loopEndOrd = lastOrd;
1250 if(loopEndRow == ROWINDEX_INVALID)
1251 loopEndRow = lastRow;
1252
1253 if(Order().IsValidPat(loopEndOrd))
1254 {
1255 PATTERNINDEX lastPat = Order()[loopEndOrd];
1256 if(loopEndOrd == lastOrd)
1257 Patterns[lastPat].Resize(loopEndRow + 1);
1258 if(restartRow != ROWINDEX_INVALID && !isEMIDI)
1259 {
1260 Patterns[lastPat].WriteEffect(EffectWriter(CMD_PATTERNBREAK, mpt::saturate_cast<ModCommand::PARAM>(restartRow)).Row(loopEndRow));
1261 if(ORDERINDEX restartPos = Order().GetRestartPos(); loopEndOrd != lastOrd || restartPos <= std::numeric_limits<ModCommand::PARAM>::max())
1262 Patterns[lastPat].WriteEffect(EffectWriter(CMD_POSITIONJUMP, mpt::saturate_cast<ModCommand::PARAM>(restartPos)).Row(loopEndRow));
1263 }
1264 }
1265 Order.SetSequence(0);
1266
1267 std::vector<CHANNELINDEX> channels;
1268 channels.reserve(m_nChannels);
1269 for(CHANNELINDEX i = 0; i < m_nChannels; i++)
1270 {
1271 if(modChnStatus[i].midiCh != ModChannelState::NOMIDI
1272 #ifdef MODPLUG_TRACKER
1273 || (GetpModDoc() != nullptr && !GetpModDoc()->IsChannelUnused(i))
1274 #endif // MODPLUG_TRACKER
1275 )
1276 {
1277 channels.push_back(i);
1278 if(modChnStatus[i].midiCh != ModChannelState::NOMIDI)
1279 ChnSettings[i].szName = MPT_AFORMAT("MIDI Ch {}")(1 + modChnStatus[i].midiCh);
1280 else if(i == tempoChannel)
1281 ChnSettings[i].szName = "Tempo";
1282 else if(i == globalVolChannel)
1283 ChnSettings[i].szName = "Global Volume";
1284 }
1285 }
1286 if(channels.empty())
1287 return false;
1288
1289 #ifdef MODPLUG_TRACKER
1290 if(GetpModDoc() != nullptr)
1291 {
1292 // Keep MIDI channels in patterns neatly grouped
1293 std::sort(channels.begin(), channels.end(), [&modChnStatus] (CHANNELINDEX c1, CHANNELINDEX c2)
1294 {
1295 if(modChnStatus[c1].midiCh == modChnStatus[c2].midiCh)
1296 return c1 < c2;
1297 return modChnStatus[c1].midiCh < modChnStatus[c2].midiCh;
1298 });
1299 GetpModDoc()->ReArrangeChannels(channels, false);
1300 GetpModDoc()->m_ShowSavedialog = true;
1301 }
1302
1303 std::unique_ptr<CDLSBank> cachedBank, embeddedBank;
1304
1305 if(CDLSBank::IsDLSBank(file.GetOptionalFileName().value_or(P_(""))))
1306 {
1307 // Soundfont embedded in MIDI file
1308 embeddedBank = std::make_unique<CDLSBank>();
1309 embeddedBank->Open(file.GetOptionalFileName().value_or(P_("")));
1310 } else
1311 {
1312 // Soundfont with same name as MIDI file
1313 for(const auto &ext : { P_(".sf2"), P_(".sf3"), P_(".sf4"), P_(".sbk"), P_(".dls") })
1314 {
1315 mpt::PathString filename = file.GetOptionalFileName().value_or(P_("")).ReplaceExt(ext);
1316 if(filename.IsFile())
1317 {
1318 embeddedBank = std::make_unique<CDLSBank>();
1319 if(embeddedBank->Open(filename))
1320 break;
1321 }
1322 }
1323 }
1324 ChangeModTypeTo(MOD_TYPE_MPT);
1325 const MidiLibrary &midiLib = CTrackApp::GetMidiLibrary();
1326 mpt::PathString cachedBankName;
1327 // Load Instruments
1328 for (INSTRUMENTINDEX ins = 1; ins <= m_nInstruments; ins++) if (Instruments[ins])
1329 {
1330 ModInstrument *pIns = Instruments[ins];
1331 uint32 midiCode = 0;
1332 if(pIns->nMidiChannel == MIDI_DRUMCHANNEL)
1333 midiCode = 0x80 | (pIns->nMidiDrumKey & 0x7F);
1334 else if(pIns->nMidiProgram)
1335 midiCode = (pIns->nMidiProgram - 1) & 0x7F;
1336
1337 if(embeddedBank && embeddedBank->FindAndExtract(*this, ins, midiCode >= 0x80))
1338 {
1339 continue;
1340 }
1341
1342 const mpt::PathString &midiMapName = midiLib[midiCode];
1343 if(!midiMapName.empty())
1344 {
1345 // Load from DLS/SF2 Bank
1346 if(CDLSBank::IsDLSBank(midiMapName))
1347 {
1348 CDLSBank *dlsBank = nullptr;
1349 if(cachedBank != nullptr && !mpt::PathString::CompareNoCase(cachedBankName, midiMapName))
1350 {
1351 dlsBank = cachedBank.get();
1352 } else
1353 {
1354 cachedBank = std::make_unique<CDLSBank>();
1355 cachedBankName = midiMapName;
1356 if(cachedBank->Open(midiMapName)) dlsBank = cachedBank.get();
1357 }
1358 if(dlsBank)
1359 {
1360 dlsBank->FindAndExtract(*this, ins, midiCode >= 0x80);
1361 }
1362 } else
1363 {
1364 // Load from Instrument or Sample file
1365 InputFile f(midiMapName, SettingCacheCompleteFileBeforeLoading());
1366 if(f.IsValid())
1367 {
1368 FileReader insFile = GetFileReader(f);
1369 if(ReadInstrumentFromFile(ins, insFile, false))
1370 {
1371 mpt::PathString filename = midiMapName.GetFullFileName();
1372 pIns = Instruments[ins];
1373 if(!pIns->filename[0]) pIns->filename = filename.ToLocale();
1374 if(!pIns->name[0])
1375 {
1376 if(midiCode < 0x80)
1377 {
1378 pIns->name = szMidiProgramNames[midiCode];
1379 } else
1380 {
1381 uint32 key = midiCode & 0x7F;
1382 if((key >= 24) && (key < 24 + std::size(szMidiPercussionNames)))
1383 pIns->name = szMidiPercussionNames[key - 24];
1384 }
1385 }
1386 }
1387 }
1388 }
1389 }
1390 }
1391 #endif // MODPLUG_TRACKER
1392 return true;
1393 }
1394
1395
1396 #else // !MODPLUG_TRACKER && !MPT_FUZZ_TRACKER
1397
1398 bool CSoundFile::ReadMID(FileReader &/*file*/, ModLoadingFlags /*loadFlags*/)
1399 {
1400 return false;
1401 }
1402
1403 #endif
1404
1405 OPENMPT_NAMESPACE_END
1406