00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020 #include "XMidiFile.h"
00021 #include "XMidiEvent.h"
00022 #include "XMidiEventList.h"
00023 #include "XMidiNoteStack.h"
00024
00025 #ifdef PENTAGRAM_IN_EXULT
00026 #include "game.h"
00027 #include "databuf.h"
00028 #else
00029 #include "IDataSource.h"
00030 #include "ODataSource.h"
00031 #endif
00032
00033 #ifndef UNDER_CE
00034 using std::atof;
00035 using std::atoi;
00036 using std::memcmp;
00037 using std::memcpy;
00038 using std::memset;
00039 using std::size_t;
00040 #endif
00041 using std::string;
00042 using std::endl;
00043
00044 #ifndef UNDER_CE
00045 #define XMidiEvent__Malloc XMidiEvent::Malloc
00046 #define XMidiEvent__Calloc XMidiEvent::Calloc
00047 #else
00048
00049 template<class T>
00050 static inline T* XMidiEvent__Malloc(size_t num=1)
00051 {
00052 return static_cast<T*>(std::malloc(num));
00053 }
00054
00055 template<class T>
00056 static inline T* XMidiEvent__Calloc(size_t num=1,size_t sz=0)
00057 {
00058 if(!sz) sz=sizeof(T);
00059 return static_cast<T*>(std::calloc(num,sz));
00060 }
00061
00062 #endif
00063
00064
00065
00066
00067
00068
00069
00070 #define PATCH_VOL_PAN_BIAS 5
00071
00072
00073
00074
00075
00076
00077 const char XMidiFile::mt32asgm[128] = {
00078 0,
00079 1,
00080 2,
00081 4,
00082 4,
00083 5,
00084 5,
00085 3,
00086 16,
00087 17,
00088 18,
00089 16,
00090 19,
00091 19,
00092 19,
00093 21,
00094 6,
00095 6,
00096 6,
00097 7,
00098 7,
00099 7,
00100 8,
00101 8,
00102 62,
00103 63,
00104 62,
00105 63,
00106 38,
00107 39,
00108 38,
00109 39,
00110 88,
00111 90,
00112 52,
00113 92,
00114 97,
00115 99,
00116 14,
00117 54,
00118 98,
00119 96,
00120 68,
00121 95,
00122 81,
00123 87,
00124 112,
00125 80,
00126 48,
00127 48,
00128 44,
00129 45,
00130 40,
00131 40,
00132 42,
00133 42,
00134 43,
00135 46,
00136 46,
00137 24,
00138 25,
00139 26,
00140 27,
00141 104,
00142 32,
00143 32,
00144 33,
00145 34,
00146 36,
00147 37,
00148 35,
00149 35,
00150 73,
00151 73,
00152 72,
00153 72,
00154 74,
00155 75,
00156 64,
00157 65,
00158 66,
00159 67,
00160 71,
00161 71,
00162 68,
00163 69,
00164 70,
00165 22,
00166 56,
00167 56,
00168 57,
00169 57,
00170 60,
00171 60,
00172 58,
00173 61,
00174 61,
00175 11,
00176 11,
00177 99,
00178 112,
00179 9,
00180 14,
00181 13,
00182 12,
00183 107,
00184 111,
00185 77,
00186 78,
00187 78,
00188 76,
00189 76,
00190 47,
00191 117,
00192 116,
00193 118,
00194 118,
00195 116,
00196 115,
00197 119,
00198 115,
00199 112,
00200 55,
00201 124,
00202 123,
00203 94,
00204 98,
00205 121
00206 };
00207
00208
00209
00210 const char XMidiFile::mt32asgs[256] = {
00211 0, 0,
00212 1, 0,
00213 2, 0,
00214 4, 0,
00215 4, 0,
00216 5, 0,
00217 5, 0,
00218 3, 0,
00219 16, 0,
00220 17, 0,
00221 18, 0,
00222 16, 0,
00223 19, 0,
00224 19, 0,
00225 19, 0,
00226 21, 0,
00227 6, 0,
00228 6, 0,
00229 6, 0,
00230 7, 0,
00231 7, 0,
00232 7, 0,
00233 8, 0,
00234 8, 0,
00235 62, 0,
00236 63, 0,
00237 62, 0,
00238 63, 0,
00239 38, 0,
00240 39, 0,
00241 38, 0,
00242 39, 0,
00243 88, 0,
00244 90, 0,
00245 52, 0,
00246 92, 0,
00247 97, 0,
00248 99, 0,
00249 14, 0,
00250 54, 0,
00251 98, 0,
00252 96, 0,
00253 68, 0,
00254 95, 0,
00255 81, 0,
00256 87, 0,
00257 112, 0,
00258 80, 0,
00259 48, 0,
00260 48, 0,
00261 44, 0,
00262 45, 0,
00263 40, 0,
00264 40, 0,
00265 42, 0,
00266 42, 0,
00267 43, 0,
00268 46, 0,
00269 46, 0,
00270 24, 0,
00271 25, 0,
00272 26, 0,
00273 27, 0,
00274 104, 0,
00275 32, 0,
00276 32, 0,
00277 33, 0,
00278 34, 0,
00279 36, 0,
00280 37, 0,
00281 35, 0,
00282 35, 0,
00283 73, 0,
00284 73, 0,
00285 72, 0,
00286 72, 0,
00287 74, 0,
00288 75, 0,
00289 64, 0,
00290 65, 0,
00291 66, 0,
00292 67, 0,
00293 71, 0,
00294 71, 0,
00295 68, 0,
00296 69, 0,
00297 70, 0,
00298 22, 0,
00299 56, 0,
00300 56, 0,
00301 57, 0,
00302 57, 0,
00303 60, 0,
00304 60, 0,
00305 58, 0,
00306 61, 0,
00307 61, 0,
00308 11, 0,
00309 11, 0,
00310 99, 0,
00311 112, 0,
00312 9, 0,
00313 14, 0,
00314 13, 0,
00315 12, 0,
00316 107, 0,
00317 111, 0,
00318 77, 0,
00319 78, 0,
00320 78, 0,
00321 76, 0,
00322 76, 0,
00323 47, 0,
00324 117, 0,
00325 116, 0,
00326 118, 0,
00327 118, 0,
00328 116, 0,
00329 115, 0,
00330 119, 0,
00331 115, 0,
00332 112, 0,
00333 55, 0,
00334 124, 0,
00335 123, 0,
00336 94, 0,
00337 98, 0,
00338 121, 0
00339 };
00340
00341
00342 const char XMidiFile::gmasmt32[128] =
00343 {
00344 0x00, 0x01, 0x03, 0x07, 0x05, 0x06, 0x11, 0x15,
00345 0x16, 0x65, 0x65, 0x62, 0x68, 0x67, 0x66, 0x69,
00346
00347 0x0C, 0x09, 0x0A, 0x0D, 0x0E, 0x0F, 0x57, 0x0F,
00348 0x3B, 0x3C, 0x3B, 0x3E, 0x3D, 0x3B, 0x3E, 0x3E,
00349
00350 0x40, 0x43, 0x42, 0x47, 0x44, 0x45, 0x42 , 0x46,
00351 0x35, 0x34, 0x36, 0x38, 0x35, 0x33, 0x39 , 0x70,
00352
00353 0X30, 0x32, 0x30, 0x32, 0x22, 0x2A, 0x21, 0x7A,
00354 0X58, 0x5A, 0x5E, 0x59, 0x5C, 0x5F, 0x59, 0x5B,
00355
00356 0x4E, 0x4F, 0x50, 0x51, 0x54, 0x55, 0x56, 0x53,
00357 0x4B, 0x49, 0x4C, 0x4D, 0x6E, 0x6B, 0x6C, 0x48,
00358
00359 0x2F, 0x43, 0x4B, 0x33, 0x3D, 0x48, 0x34, 0x43,
00360 0x20, 0x21, 0x43, 0x22, 0x20, 0x20, 0x21, 0x21,
00361
00362 0x29, 0x24, 0x23, 0x25, 0x2D, 0x21, 0x2B, 0x20,
00363 0x3F, 0x69, 0x69, 0x69, 0x33, 0x51, 0x34, 0x51,
00364
00365 0x17, 0x67, 0x67, 0x71, 0x75, 0x71, 0x74, 0x77,
00366 0x7C, 0x78, 0x77, 0x7C, 0x7B, 0x78, 0x77, 0x72
00367 };
00368
00369
00370
00371
00372 static const uint32 sysex_data_start = 7;
00373 static const uint32 sysex_max_data_size = 256;
00374
00375
00376
00377
00378
00379
00380 static const uint32 rhythm_base = 0x030110;
00381 static const uint32 rhythm_mem_size = 4;
00382
00383 static const uint32 rhythm_first_note = 24;
00384 static const uint32 rhythm_num_notes = 64;
00385
00386
00387 static inline uint32 rhythm_mem_offset(uint32 index_num) {
00388 return index_num * 4;
00389 }
00390
00391
00392 static inline uint32 rhythm_mem_offset_note(uint32 rhythm_note_num) {
00393 return (rhythm_note_num-rhythm_first_note) * 4;
00394 }
00395
00396 struct RhythmSetupData {
00397 uint8 timbre;
00398 uint8 output_level;
00399 uint8 panpot;
00400 uint8 reverb_switch;
00401 };
00402
00403
00404
00405
00406
00407 static const uint32 timbre_base = 0x080000;
00408 static const uint32 timbre_mem_size = 246;
00409 static inline uint32 timbre_mem_offset(uint32 timbre_num) { return timbre_num * 256; }
00410
00411
00412
00413
00414
00415 static const uint32 patch_base = 0x050000;
00416 static const uint32 patch_mem_size = 8;
00417 static inline uint32 patch_mem_offset(uint32 patch_num) { return patch_num * 8; }
00418
00419 struct PatchMemData {
00420 uint8 timbre_group;
00421 uint8 timbre_num;
00422 uint8 key_shift;
00423 uint8 fine_tune;
00424 uint8 bender_range;
00425 uint8 assign_mode;
00426 uint8 reverb_switch;
00427 uint8 dummy;
00428 };
00429
00430 static const PatchMemData patch_template = {
00431 2,
00432 0,
00433 24,
00434 50,
00435 24,
00436 0,
00437 1,
00438 0
00439 };
00440
00441
00442
00443
00444
00445 static const uint32 system_base = 0x100000;
00446 static const uint32 system_mem_size = 0x17;
00447 #define system_mem_offset(setting) ((uintptr)(&((systemArea*)0)->setting))
00448
00449 struct systemArea {
00450 char masterTune;
00451 char reverbMode;
00452 char reverbTime;
00453 char reverbLevel;
00454 char reserveSettings[9];
00455 char chanAssign[9];
00456 char masterVol;
00457 };
00458
00459 static const char system_init_reverb[3] = { 0,3,2 };
00460 static const char system_part_chans[9] = { 1,2,3,4,5,6,7,8,9 };
00461 static const char system_part_rsv[9] = { 3,4,3,4,3,4,3,4,4 };
00462
00463
00464
00465
00466 static const uint32 display_base = 0x200000;
00467 static const uint32 display_mem_size = 0x14;
00468
00469
00470 #ifdef PENTAGRAM_IN_EXULT
00471 static const char display[] = " Uploading Timbres! ";
00472 static const char display_black_gate[] = "BG Uploading Timbres";
00473 static const char display_serpent_isle[] = "SI Uploading Timbres";
00474
00475 static const char display_beginning[] = "--==| Exult! |==--";
00476 static const char display_beginning_bg[] = " U7: The Black Gate ";
00477 static const char display_beginning_si[] = "U7: The Serpent Isle";
00478 #else
00479
00480 static const char display[] = " Uploading Timbres! ";
00481 static const char display_beginning[] = "--=| Pentagram! |=--";
00482 #endif
00483
00484
00485
00486
00487 static const uint32 all_dev_reset_base = 0x7f0000;
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 static uint8 U7PercussionNotes[] = {
00498 28, 33, 74, 76, 77, 78, 79, 80,
00499 81, 82, 83, 84, 85, 86, 87, 0
00500 };
00501
00502
00503 static RhythmSetupData U7PercussionData[] = {
00504 { 0, 0x5A, 0x07, 0 },
00505 { 6, 0x64, 0x07, 1 },
00506 { 1, 0x5A, 0x05, 0 },
00507 { 1, 0x5A, 0x06, 0 },
00508 { 1, 0x5A, 0x07, 0 },
00509 { 2, 0x64, 0x07, 1 },
00510 { 1, 0x5A, 0x08, 0 },
00511 { 5, 0x5A, 0x07, 1 },
00512 { 1, 0x5A, 0x09, 0 },
00513 { 3, 0x5F, 0x07, 1 },
00514 { 4, 0x64, 0x04, 1 },
00515 { 4, 0x64, 0x05, 1 },
00516 { 4, 0x64, 0x06, 1 },
00517 { 4, 0x64, 0x07, 1 },
00518 { 4, 0x64, 0x08, 1 }
00519 };
00520
00521
00522
00523
00524 XMidiFile::XMidiFile(IDataSource *source, int pconvert) : num_tracks(0),
00525 events(NULL), convert_type(pconvert),
00526 do_reverb(false), do_chorus(false)
00527 {
00528 std::memset(bank127,0,sizeof(bank127));
00529
00530 ExtractTracks (source);
00531
00532
00533 if (pconvert >= XMIDIFILE_HINT_U7VOICE_MT_FILE) InsertDisplayEvents();
00534 }
00535
00536 XMidiFile::~XMidiFile()
00537 {
00538 if (events)
00539 {
00540 for (int i=0; i < num_tracks; i++) {
00541 events[i]->decerementCounter();
00542 events[i] = NULL;
00543 }
00544
00545 XMidiEvent::Free(events);
00546 }
00547 }
00548
00549 XMidiEventList *XMidiFile::GetEventList (uint32 track)
00550 {
00551 if (!events)
00552 {
00553 perr << "No midi data in loaded." << endl;
00554 return 0;
00555 }
00556
00557 if (track >= num_tracks)
00558 {
00559 perr << "Can't retrieve MIDI data, track out of range" << endl;
00560 return 0;
00561 }
00562
00563 return events[track];
00564 }
00565
00566
00567 void XMidiFile::CreateNewEvent (int time)
00568 {
00569 if (!list)
00570 {
00571 list = current = XMidiEvent__Calloc<XMidiEvent>();
00572 if (time > 0)
00573 current->time = time;
00574 return;
00575 }
00576
00577 if (time < 0 || list->time > time)
00578 {
00579 XMidiEvent *event = XMidiEvent__Calloc<XMidiEvent>();
00580 event->next = list;
00581 list = current = event;
00582 return;
00583 }
00584
00585 if (!current || current->time > time)
00586 current = list;
00587
00588 while (current->next)
00589 {
00590 if (current->next->time > time)
00591 {
00592 XMidiEvent *event = XMidiEvent__Calloc<XMidiEvent>();
00593
00594 event->next = current->next;
00595 current->next = event;
00596 current = event;
00597 current->time = time;
00598 return;
00599 }
00600
00601 current = current->next;
00602 }
00603
00604 current->next = XMidiEvent__Calloc<XMidiEvent>();
00605 current = current->next;
00606 current->time = time;
00607 }
00608
00609
00610
00611
00612
00613
00614 int XMidiFile::GetVLQ (IDataSource *source, uint32 &quant)
00615 {
00616 int i;
00617 quant = 0;
00618 unsigned int data;
00619
00620 for (i = 0; i < 4; i++)
00621 {
00622 data = source->read1();
00623 quant <<= 7;
00624 quant |= data & 0x7F;
00625
00626 if (!(data & 0x80))
00627 {
00628 i++;
00629 break;
00630 }
00631
00632 }
00633 return i;
00634 }
00635
00636
00637
00638
00639
00640
00641 int XMidiFile::GetVLQ2 (IDataSource *source, uint32 &quant)
00642 {
00643 int i;
00644 quant = 0;
00645 int data = 0;
00646
00647 for (i = 0; i < 4; i++)
00648 {
00649 data = source->read1();
00650 if (data & 0x80)
00651 {
00652 source->skip(-1);
00653 break;
00654 }
00655 quant += data;
00656 }
00657 return i;
00658 }
00659
00660
00661
00662
00663
00664
00665
00666 void XMidiFile::ApplyFirstState(first_state &fs, int chan_mask)
00667 {
00668 for (int channel = 0; channel < 16; channel++)
00669 {
00670 XMidiEvent *patch = fs.patch[channel];
00671 XMidiEvent *vol = fs.vol[channel];
00672 XMidiEvent *pan = fs.pan[channel];
00673 XMidiEvent *bank = fs.bank[channel];
00674 XMidiEvent *reverb = NULL;
00675 XMidiEvent *chorus = NULL;
00676 XMidiEvent *temp;
00677
00678
00679 if (!patch || !(chan_mask & 1 << channel)) continue;
00680 #if 0
00681 std::cout << "Channel: " << channel+1 << std::endl;
00682 std::cout << "Patch: " << (unsigned int) patch->data[0] << " @ " << patch->time << std::endl;
00683 if (bank) std::cout << " Bank: " << (unsigned int) bank->data[1] << " @ " << bank->time << std::endl;
00684 if (vol) std::cout << " Vol: " << (unsigned int) vol->data[1] << " @ " << vol->time << std::endl;
00685 if (pan) std::cout << " Pan: " << ((signed int) pan->data[1])-64 << " @ " << pan->time << std::endl;
00686 std::cout << std::endl;
00687 #endif
00688
00689
00690 temp = patch;
00691 patch = XMidiEvent__Calloc<XMidiEvent>();
00692 patch->time = temp->time;
00693 patch->status = channel|(MIDI_STATUS_PROG_CHANGE << 4);
00694 patch->data[0] = temp->data[0];
00695
00696
00697 if (vol && (vol->time > patch->time+PATCH_VOL_PAN_BIAS || vol->time < patch->time-PATCH_VOL_PAN_BIAS))
00698 vol = NULL;
00699
00700 temp = vol;
00701 vol = XMidiEvent__Calloc<XMidiEvent>();
00702 vol->status = channel|(MIDI_STATUS_CONTROLLER << 4);
00703 vol->data[0] = 7;
00704
00705 if (!temp)
00706 {
00707
00708 if (convert_type) vol->data[1] = 90;
00709 else vol->data[1] = 90;
00710 }
00711 else
00712 vol->data[1] = temp->data[1];
00713
00714
00715
00716 if (bank && (bank->time > patch->time+PATCH_VOL_PAN_BIAS || bank->time < patch->time-PATCH_VOL_PAN_BIAS))
00717 bank = NULL;
00718
00719 temp = bank;
00720
00721 bank = XMidiEvent__Calloc<XMidiEvent>();
00722 bank->status = channel|(MIDI_STATUS_CONTROLLER << 4);
00723
00724 if (!temp)
00725 bank->data[1] = 0;
00726 else
00727 bank->data[1] = temp->data[1];
00728
00729
00730 if (pan && (pan->time > patch->time+PATCH_VOL_PAN_BIAS || pan->time < patch->time-PATCH_VOL_PAN_BIAS))
00731 pan = NULL;
00732
00733 temp = pan;
00734 pan = XMidiEvent__Calloc<XMidiEvent>();
00735 pan->status = channel|(MIDI_STATUS_CONTROLLER << 4);
00736 pan->data[0] = 10;
00737
00738 if (!temp)
00739 pan->data[1] = 64;
00740 else
00741 pan->data[1] = temp->data[1];
00742
00743 if (do_reverb)
00744 {
00745 reverb = XMidiEvent__Calloc<XMidiEvent>();
00746 reverb->status = channel|(MIDI_STATUS_CONTROLLER << 4);
00747 reverb->data[0] = 91;
00748 reverb->data[1] = reverb_value;
00749 }
00750
00751 if (do_chorus)
00752 {
00753 chorus = XMidiEvent__Calloc<XMidiEvent>();
00754 chorus->status = channel|(MIDI_STATUS_CONTROLLER << 4);
00755 chorus->data[0] = 93;
00756 chorus->data[1] = chorus_value;
00757 }
00758
00759 vol->time = 0;
00760 pan->time = 0;
00761 patch->time = 0;
00762 bank->time = 0;
00763
00764 if (do_reverb && do_chorus) reverb->next = chorus;
00765 else if (do_reverb) reverb->next = bank;
00766 if (do_chorus) chorus->next = bank;
00767 bank->next = vol;
00768 vol->next = pan;
00769 pan->next = patch;
00770
00771 patch->next = list;
00772 if (do_reverb) list = reverb;
00773 else if (do_chorus) list = chorus;
00774 else list = bank;
00775 }
00776 }
00777
00778 #ifndef BEOS
00779
00780 struct uint64 {
00781 uint32 low;
00782 uint32 high;
00783
00784 uint64() : low(0), high(0) { }
00785 uint64(uint32 i) : low(i), high(0) { }
00786 uint64(uint32 h, uint32 l) : low(l), high(h) { }
00787 uint64(const uint64 &i) : low(i.low), high(i.high) { }
00788
00789 inline void addlow(uint32 l) {
00790 uint32 mid = (low >> 16);
00791 low = (low & 0xFFFF) + (l & 0xFFFF);
00792 mid += (low >> 16) + (l >> 16);
00793 low = (low&0xFFFF) + (mid << 16);
00794 high += mid >> 16;
00795 }
00796
00797
00798
00799 inline uint64 & operator = (uint64 &o) {
00800 low = o.low;
00801 high = o.high;
00802 return *this;
00803 }
00804
00805 inline uint64 & operator += (uint64 &o) {
00806 addlow(o.low);
00807 high += o.high;
00808 return *this;
00809 }
00810
00811 inline uint64 operator + (uint64 &o) {
00812 uint64 n(*this);
00813 n.addlow(o.low);
00814 n.high += o.high;
00815 return n;
00816 }
00817
00818
00819
00820 inline uint64 & operator = (uint32 i) {
00821 low = i;
00822 high = 0;
00823 return *this;
00824 }
00825
00826 inline uint64 & operator += (uint32 i) {
00827 addlow(i);
00828 return *this;
00829 }
00830
00831 inline uint64 operator + (uint32 i) {
00832 uint64 n(*this);
00833 n.addlow(i);
00834 return n;
00835 }
00836
00837 inline uint64 & operator *= (uint32 i) {
00838
00839 uint32 h1 = i >> 16;
00840 uint32 h2 = low >> 16;
00841
00842
00843
00844 uint32 l1 = i & 0xFFFF;
00845 uint32 l2 = low & 0xFFFF;
00846 uint32 l3 = high & 0xFFFF;
00847
00848
00849 uint32 accum;
00850
00851
00852 low = l1*l2;
00853 high = 0;
00854
00855
00856 accum = h1*l2;
00857 addlow(accum<<16);
00858 high += accum>>16;
00859
00860
00861 accum = l1*h2;
00862 addlow(accum<<16);
00863 high += accum>>16;
00864
00865
00866 high += h1*h2;
00867
00868
00869 high += l1*l3;
00870
00871
00872 high += (h1*l3) << 16;
00873
00874
00875 high += (l1*l3) << 16;
00876
00877 return *this;
00878 }
00879
00880 inline uint64 operator * (uint32 i) {
00881 uint64 n(*this);
00882 return n*=i;
00883 }
00884
00885 inline uint64 & operator /= (uint32 div) {
00886
00887
00888 if (!high) {
00889 low /= div;
00890 return *this;
00891 }
00892
00893
00894 uint32 mod = high;
00895 uint32 l = low;
00896
00897
00898 uint32 shift = 32;
00899 low = 0;
00900
00901
00902
00903 if (mod >= div) {
00904 high = mod / div;
00905 mod %= div;
00906 }
00907 else high = 0;
00908
00909
00910 while (--shift) {
00911
00912 mod <<= 1;
00913 mod |= (l>>shift) & 1;
00914
00915
00916 if (mod >= div) {
00917 uint32 v = mod / div;
00918 mod %= div;
00919 addlow(v << shift);
00920 high += v >> (32 - shift);
00921 }
00922 }
00923
00924
00925
00926 mod <<= 1;
00927 mod |= l & 1;
00928
00929
00930 if (mod >= div) {
00931 uint32 v = mod / div;
00932 mod %= div;
00933 addlow(v << shift);
00934 }
00935
00936 return *this;
00937 }
00938
00939 inline uint64 operator / (uint32 i) {
00940 uint64 n(*this);
00941 return n/=i;
00942 }
00943
00944 inline uint64 & operator %= (uint32 div) {
00945
00946
00947 if (!high) {
00948 low %= div;
00949 return *this;
00950 }
00951
00952
00953 uint32 mod = high;
00954
00955
00956 uint32 shift = 32;
00957
00958 while (1) {
00959
00960
00961 if (mod >= div) mod %= div;
00962
00963 if (shift == 0) break;
00964
00965 mod <<= 1;
00966 shift--;
00967 mod |= (low>>shift) & 1;
00968 }
00969
00970 high = 0;
00971 low = mod;
00972
00973 return *this;
00974 }
00975
00976 inline uint64 operator % (uint32 i) {
00977 uint64 n(*this);
00978 return n%=i;
00979 }
00980
00981 inline operator uint32 ()
00982 {
00983 return low;
00984 }
00985
00986 void printx() {
00987 if (high) std::printf ("%X%08X", high, low);
00988 else printf ("%X", low);
00989 }
00990 };
00991 #endif
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001 void XMidiFile::AdjustTimings(uint32 ppqn)
01002 {
01003 uint32 tempo = 500000;
01004 uint32 time_prev = 0;
01005 uint32 hs_rem = 0;
01006 uint32 hs = 0;
01007
01008 ppqn *= 10000;
01009
01010
01011 XMidiNoteStack notes;
01012
01013 for (XMidiEvent *event = list; event; event = event->next) {
01014
01015
01016
01017
01018 uint64 aim = event->time - time_prev;
01019 aim *= tempo;
01020
01021 hs_rem += aim%ppqn;
01022 hs += aim/ppqn;
01023 hs += hs_rem/ppqn;
01024 hs_rem %= ppqn;
01025
01026 time_prev = event->time;
01027 event->time = (hs*6)/5 + (6*hs_rem)/(5*ppqn);
01028
01029
01030 if (event->status <= 0x9F) {
01031
01032
01033 if ((event->status>>4) == MIDI_STATUS_NOTE_ON && event->data[1])
01034 notes.Push(event);
01035 else {
01036 XMidiEvent *prev = notes.FindAndPop(event);
01037 if (prev) prev->ex.note_on.duration = event->time - prev->time;
01038 }
01039
01040 }
01041 else if (event->status == 0xFF && event->data[0] == 0x51) {
01042
01043 tempo = (event->ex.sysex_data.buffer[0] << 16) +
01044 (event->ex.sysex_data.buffer[1] << 8) +
01045 event->ex.sysex_data.buffer[2];
01046
01047 event->ex.sysex_data.buffer[0] = 0x07;
01048 event->ex.sysex_data.buffer[1] = 0xA1;
01049 event->ex.sysex_data.buffer[2] = 0x20;
01050 }
01051 }
01052
01053
01054 static const unsigned char tempo_buf[5] = { 0x51, 0x03, 0x07, 0xA1, 0x20 };
01055 IBufferDataSource ds(tempo_buf, 5);
01056 current = list;
01057 ConvertSystemMessage (0, 0xFF,&ds);
01058 }
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 int XMidiFile::ConvertEvent (const int time, const unsigned char status, IDataSource *source, const int size, first_state &fs)
01074 {
01075 int data;
01076
01077 data = source->read1();
01078
01079
01080
01081 if ((status >> 4) == 0xB && data == 0)
01082 {
01083 data = source->read1();
01084
01085 bank127[status&0xF] = false;
01086
01087 if (convert_type == XMIDIFILE_CONVERT_MT32_TO_GM
01088 || convert_type == XMIDIFILE_CONVERT_MT32_TO_GS
01089 || convert_type == XMIDIFILE_CONVERT_MT32_TO_GS127)
01090 return 2;
01091
01092 CreateNewEvent (time);
01093 current->status = status;
01094 current->data[0] = 0;
01095 current->data[1] = data;
01096
01097
01098 if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current;
01099
01100 if (convert_type == XMIDIFILE_CONVERT_GS127_TO_GS && data == 127)
01101 bank127[status&0xF] = true;
01102
01103 return 2;
01104 }
01105
01106
01107 if ((status >> 4) == 0xC && (status&0xF) != 9 && convert_type != XMIDIFILE_CONVERT_NOCONVERSION)
01108 {
01109 if (convert_type == XMIDIFILE_CONVERT_MT32_TO_GM)
01110 {
01111 data = mt32asgm[data];
01112 }
01113 else if (convert_type == XMIDIFILE_CONVERT_GM_TO_MT32)
01114 {
01115 data = gmasmt32[data];
01116 }
01117 else if ((convert_type == XMIDIFILE_CONVERT_GS127_TO_GS && bank127[status&0xF]) ||
01118 convert_type == XMIDIFILE_CONVERT_MT32_TO_GS)
01119 {
01120 CreateNewEvent (time);
01121 current->status = 0xB0 | (status&0xF);
01122 current->data[0] = 0;
01123 current->data[1] = mt32asgs[data*2+1];
01124
01125 data = mt32asgs[data*2];
01126
01127
01128 if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current;
01129 }
01130 else if (convert_type == XMIDIFILE_CONVERT_MT32_TO_GS127)
01131 {
01132 CreateNewEvent (time);
01133 current->status = 0xB0 | (status&0xF);
01134 current->data[0] = 0;
01135 current->data[1] = 127;
01136
01137
01138 if (!fs.bank[status&0xF] || fs.bank[status&0xF]->time > time) fs.bank[status&0xF] = current;
01139 }
01140 }
01141 else if ((status >> 4) == 0xC && (status&0xF) == 9 && convert_type != XMIDIFILE_CONVERT_NOCONVERSION)
01142 {
01143 return size;
01144 }
01145
01146 CreateNewEvent (time);
01147 current->status = status;
01148
01149 current->data[0] = data;
01150
01151
01152 if ((status >> 4) == 0xC) {
01153 if (!fs.patch[status&0xF] || fs.patch[status&0xF]->time > time)
01154 fs.patch[status&0xF] = current;
01155 }
01156
01157 else if ((status >> 4) == 0xB) {
01158
01159 if (current->data[0] == 7) {
01160 if (!fs.vol[status&0xF] || fs.vol[status&0xF]->time > time)
01161 fs.vol[status&0xF] = current;
01162 }
01163
01164 else if (current->data[0] == 10) {
01165 if (!fs.pan[status&0xF] || fs.pan[status&0xF]->time > time)
01166 fs.pan[status&0xF] = current;
01167 }
01168
01169 else if (current->data[0] == XMIDI_CONTROLLER_SEQ_BRANCH_INDEX) {
01170 current->ex.branch_index.next_branch = branches;
01171 branches = current;
01172 }
01173 }
01174
01175 if (size == 1)
01176 return 1;
01177
01178 current->data[1] = source->read1();
01179
01180
01181
01182
01183
01184 return 2;
01185 }
01186
01187 int XMidiFile::ConvertNote (const int time, const unsigned char status, IDataSource *source, const int size)
01188 {
01189 uint32 delta = 0;
01190 int data;
01191
01192 data = source->read1();
01193
01194 CreateNewEvent (time);
01195 current->status = status;
01196
01197 current->data[0] = data;
01198 current->data[1] = source->read1();
01199
01200
01201
01202
01203
01204 if (size == 2)
01205 return 2;
01206
01207
01208
01209
01210 int i = GetVLQ (source, delta);
01211
01212
01213 current->ex.note_on.duration = delta;
01214
01215
01216 XMidiEvent *prev = current;
01217
01218
01219 CreateNewEvent (time+delta);
01220
01221 current->status = status;
01222 current->data[0] = data;
01223 current->data[1] = 0;
01224
01225
01226 current = prev;
01227
01228 return i + 2;
01229 }
01230
01231
01232 int XMidiFile::ConvertSystemMessage (const int time, const unsigned char status, IDataSource *source)
01233 {
01234 int i=0;
01235
01236 CreateNewEvent (time);
01237 current->status = status;
01238
01239
01240 if (status == 0xFF)
01241 {
01242 current->data[0] = source->read1();
01243 i++;
01244 }
01245
01246 i += GetVLQ (source, current->ex.sysex_data.len);
01247
01248 if (!current->ex.sysex_data.len)
01249 {
01250 current->ex.sysex_data.buffer = NULL;
01251 return i;
01252 }
01253
01254 current->ex.sysex_data.buffer = XMidiEvent__Malloc<unsigned char>(current->ex.sysex_data.len);
01255
01256 source->read (reinterpret_cast<char *>(current->ex.sysex_data.buffer), current->ex.sysex_data.len);
01257
01258 return i+current->ex.sysex_data.len;
01259 }
01260
01261
01262
01263 int XMidiFile::CreateMT32SystemMessage(const int time, uint32 address_base, uint16 address_offset, uint32 len, const void *data, IDataSource *source)
01264 {
01265 CreateNewEvent (time);
01266
01267 current->status = 0xF0;
01268
01269
01270 current->ex.sysex_data.len = sysex_data_start+len+2;
01271 unsigned char *sysex_buffer = current->ex.sysex_data.buffer =
01272 XMidiEvent__Malloc<unsigned char>(current->ex.sysex_data.len);
01273
01274
01275 sysex_buffer[0] = 0x41;
01276 sysex_buffer[1] = 0x10;
01277 sysex_buffer[2] = 0x16;
01278 sysex_buffer[3] = 0x12;
01279
01280
01281 uint32 actual_address = address_offset;
01282 actual_address += (address_base>>2) & (0x7f<<14);
01283 actual_address += (address_base>>1) & (0x7f<<7);
01284 actual_address += (address_base>>0) & (0x7f<<0);
01285 sysex_buffer[4] = (actual_address>>14)&0x7F;
01286 sysex_buffer[5] = (actual_address>>7)&0x7F;
01287 sysex_buffer[6] = actual_address&0x7F;
01288
01289
01290 if (data) std::memcpy (sysex_buffer+sysex_data_start, data, len);
01291 else if (source) source->read(sysex_buffer+sysex_data_start,len);
01292
01293
01294 char checksum = 0;
01295 for (uint32 j = 4; j < sysex_data_start+len; j++)
01296 checksum += sysex_buffer[j];
01297
01298 checksum = checksum & 0x7f;
01299 if (checksum) checksum = 0x80 - checksum;
01300
01301
01302 sysex_buffer[sysex_data_start+len] = checksum;
01303
01304
01305 sysex_buffer[sysex_data_start+len+1] = 0xF7;
01306
01307 return sysex_data_start+len+2;
01308 }
01309
01310
01311 int XMidiFile::ConvertFiletoList (IDataSource *source, const bool is_xmi, first_state &fs)
01312 {
01313 int time = 0;
01314 uint32 data;
01315 int end = 0;
01316 uint32 status = 0;
01317 int play_size = 2;
01318 uint32 file_size = source->getSize();
01319 int retval = 0;
01320
01321 if (is_xmi) play_size = 3;
01322
01323 while (!end && source->getPos() < file_size)
01324 {
01325 if (!is_xmi)
01326 {
01327 GetVLQ (source, data);
01328 time += data;
01329
01330 data = source->read1();
01331
01332 if (data >= 0x80)
01333 {
01334 status = data;
01335 }
01336 else
01337 source->skip (-1);
01338 }
01339 else
01340 {
01341 GetVLQ2 (source, data);
01342 time += data;
01343
01344 status = source->read1();
01345 }
01346
01347 switch (status >> 4)
01348 {
01349 case MIDI_STATUS_NOTE_ON:
01350 retval |= 1 << (status & 0xF);
01351 ConvertNote (time, status, source, play_size);
01352 break;
01353
01354 case MIDI_STATUS_NOTE_OFF:
01355 ConvertNote (time, status, source, 2);
01356 break;
01357
01358
01359 case MIDI_STATUS_AFTERTOUCH:
01360 case MIDI_STATUS_CONTROLLER:
01361 case MIDI_STATUS_PITCH_WHEEL:
01362 ConvertEvent (time, status, source, 2, fs);
01363 break;
01364
01365
01366
01367 case MIDI_STATUS_PROG_CHANGE:
01368 case MIDI_STATUS_PRESSURE:
01369 ConvertEvent (time, status, source, 1, fs);
01370 break;
01371
01372
01373 case MIDI_STATUS_SYSEX:
01374 if (status == 0xFF)
01375 {
01376 int pos = source->getPos();
01377 uint32 data = source->read1();
01378
01379 if (data == 0x2F)
01380 end = 1;
01381 else if (data == 0x51 && is_xmi)
01382 {
01383 GetVLQ (source, data);
01384 source->skip(data);
01385 break;
01386 }
01387
01388 source->seek (pos);
01389 }
01390 ConvertSystemMessage (time, status, source);
01391 break;
01392
01393 default:
01394 break;
01395 }
01396
01397 }
01398
01399 return retval;
01400 }
01401
01402
01403 int XMidiFile::ExtractTracksFromXmi (IDataSource *source)
01404 {
01405 int num = 0;
01406 uint32 len = 0;
01407 char buf[32];
01408
01409 first_state fs;
01410
01411 while (source->getPos() < source->getSize() && num != num_tracks)
01412 {
01413
01414 source->read (buf, 4);
01415 len = source->read4high();
01416
01417
01418 if (!memcmp(buf,"FORM",4))
01419 {
01420 source->skip (4);
01421 source->read (buf, 4);
01422 len = source->read4high();
01423 }
01424
01425 if (memcmp(buf,"EVNT",4))
01426 {
01427 source->skip ((len+1)&~1);
01428 continue;
01429 }
01430
01431 list = NULL;
01432 branches = NULL;
01433 memset(&fs, 0, sizeof(fs));
01434
01435 int begin = source->getPos ();
01436
01437
01438 int chan_mask = ConvertFiletoList (source, true, fs);
01439
01440
01441
01442
01443
01444 static const unsigned char tempo_buf[5] = { 0x51, 0x03, 0x07, 0xA1, 0x20 };
01445 IBufferDataSource ds(tempo_buf, 5);
01446 current = list;
01447 ConvertSystemMessage (0, 0xFF,&ds);
01448
01449
01450 events[num]->events = list;
01451 events[num]->branches = branches;
01452 events[num]->chan_mask = chan_mask;
01453
01454
01455 num++;
01456
01457
01458 source->seek (begin + ((len+1)&~1));
01459 }
01460
01461
01462 return num;
01463 }
01464
01465 int XMidiFile::ExtractTracksFromMid (IDataSource *source, const uint32 ppqn, const int num_tracks, const bool type1)
01466 {
01467 int num = 0;
01468 uint32 len = 0;
01469 char buf[32];
01470 int chan_mask = 0;
01471
01472 first_state fs;
01473 memset(&fs, 0, sizeof(fs));
01474
01475 list = NULL;
01476 branches = NULL;
01477
01478 while (source->getPos() < source->getSize() && num != num_tracks)
01479 {
01480
01481 source->read (buf, 4);
01482 len = source->read4high();
01483
01484 if (memcmp(buf,"MTrk",4))
01485 {
01486 source->skip (len);
01487 continue;
01488 }
01489
01490 int begin = source->getPos ();
01491
01492
01493 chan_mask |= ConvertFiletoList (source, false, fs);
01494
01495 if (!type1) {
01496 ApplyFirstState(fs, chan_mask);
01497 AdjustTimings(ppqn);
01498 events[num]->events = list;
01499 events[num]->branches = branches;
01500 branches = NULL;
01501 list = NULL;
01502 memset(&fs, 0, sizeof(fs));
01503 chan_mask = 0;
01504 }
01505
01506
01507 num++;
01508 source->seek (begin+len);
01509 }
01510
01511 if (type1) {
01512 ApplyFirstState(fs, chan_mask);
01513 AdjustTimings(ppqn);
01514 events[0]->events = list;
01515 events[0]->branches = branches;
01516 return num == num_tracks ? 1 : 0;
01517 }
01518
01519
01520 return num;
01521 }
01522
01523 int XMidiFile::ExtractTracks (IDataSource *source)
01524 {
01525 uint32 i = 0;
01526 int start;
01527 uint32 len;
01528 uint32 chunk_len;
01529 int count;
01530 char buf[32];
01531
01532 int format_hint = convert_type;
01533
01534 if (convert_type >= XMIDIFILE_HINT_U7VOICE_MT_FILE)
01535 convert_type = XMIDIFILE_CONVERT_NOCONVERSION;
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569 do_reverb = false;
01570 do_chorus = false;
01571 reverb_value = 0;
01572 chorus_value = 0;
01573
01574
01575 source->read (buf, 4);
01576
01577
01578 if (!memcmp (buf, "FORM", 4))
01579 {
01580
01581 len = source->read4high();
01582
01583 start = source->getPos();
01584
01585
01586 source->read (buf, 4);
01587
01588
01589 if (!memcmp (buf, "XMID", 4))
01590 {
01591 perr << "Warning: XMidiFile doesn't have XDIR" << endl;
01592 num_tracks = 1;
01593
01594 }
01595 else if (memcmp (buf, "XDIR", 4))
01596 {
01597 perr << "Not a recognised XMID" << endl;
01598 return 0;
01599
01600 }
01601 else
01602 {
01603 num_tracks = 0;
01604
01605 for (i = 4; i < len; i++)
01606 {
01607
01608 source->read (buf, 4);
01609
01610
01611 chunk_len = source->read4high();
01612
01613
01614 i+=8;
01615
01616 if (memcmp (buf, "INFO", 4))
01617 {
01618
01619 source->skip((chunk_len+1)&~1);
01620 i+= (chunk_len+1)&~1;
01621 continue;
01622 }
01623
01624
01625 if (chunk_len < 2)
01626 break;
01627
01628 num_tracks = source->read2();
01629 break;
01630 }
01631
01632
01633 if (num_tracks == 0)
01634 {
01635 perr << "Not a valid XMID" << endl;
01636 return 0;
01637 }
01638
01639
01640
01641 source->seek (start+((len+1)&~1));
01642
01643
01644 source->read (buf, 4);
01645
01646
01647 if (memcmp (buf, "CAT ", 4))
01648 {
01649 perr << "Not a recognised XMID (" << buf[0] << buf[1] << buf[2] << buf[3] << ") should be (CAT )" << endl;
01650 return 0;
01651 }
01652
01653
01654 len = source->read4high();
01655
01656
01657 source->read (buf, 4);
01658
01659
01660 if (memcmp (buf, "XMID", 4))
01661 {
01662 perr << "Not a recognised XMID (" << buf[0] << buf[1] << buf[2] << buf[3] << ") should be (XMID)" << endl;
01663 return 0;
01664 }
01665
01666 }
01667
01668
01669
01670 events = XMidiEvent__Calloc<XMidiEventList*>(num_tracks);
01671
01672 for (i = 0; i < num_tracks; i++)
01673 events[i] = XMidiEvent__Calloc<XMidiEventList>();
01674
01675 count = ExtractTracksFromXmi (source);
01676
01677 if (count != num_tracks)
01678 {
01679 perr << "Error: unable to extract all (" << num_tracks << ") tracks specified from XMidiFile. Only ("<< count << ")" << endl;
01680
01681 int i = 0;
01682
01683 for (i = 0; i < num_tracks; i++) {
01684 events[i]->decerementCounter();
01685 events[i] = NULL;
01686 }
01687
01688
01689 XMidiEvent::Free (events);
01690
01691 return 0;
01692 }
01693
01694 return 1;
01695
01696 }
01697 else if (!memcmp (buf, "MThd", 4))
01698 {
01699
01700 len = source->read4high();
01701
01702 if (len < 6)
01703 {
01704 perr << "Not a valid MIDI" << endl;
01705 return 0;
01706 }
01707
01708 int type = source->read2high();
01709
01710 int actual_num = num_tracks = source->read2high();
01711
01712
01713 if (type == 1) num_tracks = 1;
01714
01715 events = XMidiEvent__Calloc<XMidiEventList*>(num_tracks);
01716 const uint32 ppqn = source->read2high();
01717
01718 for (i = 0; i < num_tracks; i++)
01719 events[i] = XMidiEvent__Calloc<XMidiEventList>();
01720
01721 count = ExtractTracksFromMid (source, ppqn, actual_num, type == 1);
01722
01723 if (count != num_tracks)
01724 {
01725 perr << "Error: unable to extract all (" << num_tracks << ") tracks specified from MIDI. Only ("<< count << ")" << endl;
01726
01727 for (i = 0; i < num_tracks; i++) {
01728 events[i]->decerementCounter();
01729 events[i] = NULL;
01730 }
01731
01732 XMidiEvent::Free (events);
01733
01734 return 0;
01735
01736 }
01737
01738 return 1;
01739
01740 }
01741 else if (!memcmp (buf, "RIFF", 4))
01742 {
01743
01744 len = source->read4();
01745
01746
01747 source->read (buf, 4);
01748
01749
01750 if (memcmp (buf, "RMID", 4))
01751 {
01752 perr << "Invalid RMID" << endl;
01753 return 0;
01754 }
01755
01756
01757
01758 for (i = 4; i < len; i++)
01759 {
01760
01761 source->read (buf, 4);
01762
01763 chunk_len = source->read4();
01764
01765 i+=8;
01766
01767 if (memcmp (buf, "data", 4))
01768 {
01769
01770 source->skip ((chunk_len+1)&~1);
01771 i+= (chunk_len+1)&~1;
01772 continue;
01773 }
01774
01775 return ExtractTracks (source);
01776
01777 }
01778
01779 perr << "Failed to find midi data in RIFF Midi" << endl;
01780 return 0;
01781 }
01782 else if (format_hint == XMIDIFILE_HINT_U7VOICE_MT_FILE)
01783 {
01784 return ExtractTracksFromU7V(source);
01785 }
01786 else if (format_hint == XMIDIFILE_HINT_XMIDI_MT_FILE)
01787 {
01788 return ExtractTracksFromXMIDIMT(source);
01789 }
01790
01791 return 0;
01792 }
01793
01794 int XMidiFile::ExtractTracksFromU7V (IDataSource *source)
01795 {
01796 uint32 i, j;
01797 int num = 0;
01798 uint32 len = 0;
01799 int time = 0;
01800 int time_inc = 32;
01801
01802
01803 first_state fs;
01804
01805 list = NULL;
01806 branches = NULL;
01807 memset(&fs, 0, sizeof(fs));
01808
01809
01810 int chan_mask = 0;
01811
01812 source->seek(0);
01813 uint32 num_timbres = source->read1();
01814 pout << num_timbres << " custom timbres..." << std::endl;
01815
01816 if (source->getSize() != 247*num_timbres+1) {
01817 perr << "File size didn't match timbre count. Wont convert." << std::endl;
01818 return 0;
01819 }
01820
01821
01822
01823
01824
01825 char one = 1;
01826 CreateMT32SystemMessage(time, all_dev_reset_base, 0, 1, &one);
01827 time += time_inc;
01828
01829
01830
01831 for (i = 0; i < num_timbres; i++)
01832 {
01833
01834
01835
01836 CreateMT32SystemMessage(time, timbre_base, timbre_mem_offset(i), timbre_mem_size, 0, source);
01837
01838
01839
01840
01841
01842
01843 PatchMemData patch_data = patch_template;
01844
01845
01846 patch_data.timbre_num = i;
01847
01848 CreateMT32SystemMessage(time,
01849 patch_base,
01850 patch_mem_offset(source->read1()-1),
01851 patch_mem_size,
01852 &patch_data );
01853
01854
01855 }
01856
01857
01858
01859
01860
01861 i = 0;
01862 while (U7PercussionNotes[i])
01863 {
01864
01865 for (j = i+1; U7PercussionNotes[j]; j++)
01866 {
01867
01868 if (U7PercussionNotes[j-1]+1 != U7PercussionNotes[j]) break;
01869 }
01870
01871 int count = j-i;
01872
01873 CreateMT32SystemMessage(time,
01874 rhythm_base,
01875 rhythm_mem_offset_note(U7PercussionNotes[i]),
01876 rhythm_mem_size*count,
01877 &U7PercussionData[i] );
01878
01879 time += time_inc;
01880 i+=count;
01881 }
01882
01883
01884
01885
01886
01887 char seventy = 70;
01888
01889 CreateMT32SystemMessage(time, system_base, system_mem_offset(masterVol), 1,&seventy);
01890 time += time_inc;
01891
01892
01893
01894
01895
01896 static const unsigned char tempo_buf[5] = { 0x51, 0x03, 0x07, 0xA1, 0x20 };
01897 IBufferDataSource ds(tempo_buf, 5);
01898 current = list;
01899 ConvertSystemMessage (0, 0xFF,&ds);
01900
01901 num_tracks=1;
01902 events = XMidiEvent__Calloc<XMidiEventList*>(1);
01903 events[0] = XMidiEvent__Calloc<XMidiEventList>();
01904 events[0]->events = list;
01905 events[0]->branches = branches;
01906 events[0]->chan_mask = chan_mask;
01907
01908
01909 num++;
01910
01911
01912 return num;
01913
01914 }
01915
01916 int XMidiFile::ExtractTracksFromXMIDIMT (IDataSource *source)
01917 {
01918 int num = 0;
01919 uint32 len = 0;
01920 int time = 0;
01921 int time_inc = 32;
01922
01923
01924 first_state fs;
01925
01926 list = NULL;
01927 branches = NULL;
01928 memset(&fs, 0, sizeof(fs));
01929
01930
01931 int chan_mask = 0;
01932
01933 source->seek(0);
01934
01935
01936
01937
01938
01939 char one = 1;
01940 CreateMT32SystemMessage(time, all_dev_reset_base, 0, 1, &one);
01941 time += time_inc;
01942
01943
01944 CreateMT32SystemMessage(time, system_base, system_mem_offset(chanAssign), 9, system_part_chans);
01945 time += time_inc;
01946
01947
01948 CreateMT32SystemMessage(time, system_base, system_mem_offset(reserveSettings), 9, system_part_rsv);
01949 time += time_inc;
01950
01951
01952 CreateMT32SystemMessage(time, system_base, 1, 3, system_init_reverb);
01953 time += time_inc;
01954
01955
01956 static const unsigned char tempo_buf[5] = { 0x51, 0x03, 0x07, 0xA1, 0x20 };
01957 IBufferDataSource ds(tempo_buf, 5);
01958 current = list;
01959 ConvertSystemMessage (0, 0xFF,&ds);
01960
01961 num_tracks=1;
01962 events = XMidiEvent__Calloc<XMidiEventList*>(1);
01963 events[0] = XMidiEvent__Calloc<XMidiEventList>();
01964 events[0]->events = list;
01965 events[0]->branches = branches;
01966 events[0]->chan_mask = chan_mask;
01967
01968
01969 num++;
01970
01971
01972 return num;
01973 }
01974
01975 void XMidiFile::InsertDisplayEvents()
01976 {
01977
01978 current = list = events[0]->events;
01979 while (current->next) current = current->next;
01980
01981
01982
01983
01984
01985
01986 const char *display = ::display;
01987 const char *display_beginning = ::display_beginning;
01988 #ifdef PENTAGRAM_IN_EXULT
01989 if (Game::get_game_type() == SERPENT_ISLE)
01990 {
01991 display = display_serpent_isle;
01992 display_beginning = display_beginning_si;
01993 }
01994 else if (Game::get_game_type() == BLACK_GATE)
01995 {
01996 display = display_black_gate;
01997 display_beginning = display_beginning_bg;
01998 }
01999 #endif
02000
02001 CreateMT32SystemMessage(current->time, display_base, 0, display_mem_size, display );
02002 CreateMT32SystemMessage(-1, display_base, 0, display_mem_size, display_beginning );
02003
02004 events[0]->events = list;
02005
02006 }