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 <cstring>
00021
00022 #ifndef PENTAGRAM_IN_EXULT
00023 #include "IDataSource.h"
00024 #endif
00025
00026 #include "LowLevelMidiDriver.h"
00027 #include "XMidiSequence.h"
00028 #include "XMidiFile.h"
00029 #include "XMidiEvent.h"
00030 #include "XMidiEventList.h"
00031
00032 #define LLMD_MSG_PLAY 1
00033 #define LLMD_MSG_FINISH 2
00034 #define LLMD_MSG_PAUSE 3
00035 #define LLMD_MSG_SET_VOLUME 4
00036 #define LLMD_MSG_SET_SPEED 5
00037 #define LLMD_MSG_PRECACHE_TIMBRES 6
00038
00039
00040 #define LLMD_MSG_THREAD_INIT -1
00041 #define LLMD_MSG_THREAD_INIT_FAILED -2
00042 #define LLMD_MSG_THREAD_EXIT -3
00043
00044
00045
00046 #define LLMD_MINIMUM_YIELD_THRESHOLD 6
00047
00048
00049
00050 #ifdef DO_SMP_TEST
00051 #define giveinfo() perr << __FILE__ << ":" << __LINE__ << std::endl; perr.flush();
00052 #else
00053 #define giveinfo()
00054 #endif
00055
00056
00057
00058
00059 static const uint32 sysex_data_start = 7;
00060 static const uint32 sysex_max_data_size = 256;
00061
00062
00063
00064
00065
00066
00067 static const uint32 rhythm_base = 0x030110;
00068 static const uint32 rhythm_mem_size = 4;
00069
00070 static const uint32 rhythm_first_note = 24;
00071 static const uint32 rhythm_num_notes = 64;
00072
00073
00074 static inline uint32 rhythm_mem_offset(uint32 index_num) {
00075 return index_num * 4;
00076 }
00077
00078
00079 static inline uint32 rhythm_mem_offset_note(uint32 rhythm_note_num) {
00080 return (rhythm_note_num-rhythm_first_note) * 4;
00081 }
00082
00083
00084
00085
00086
00087
00088 static const uint32 timbre_temp_base = 0x040000;
00089 static const uint32 timbre_unk_base = 0x060000;
00090 static const uint32 timbre_base = 0x080000;
00091 static const uint32 timbre_mem_size = 246;
00092 static inline uint32 timbre_mem_offset(uint32 timbre_num) { return timbre_num * 256; }
00093
00094
00095
00096
00097 static const uint32 patch_temp_base = 0x030000;
00098 static const uint32 patch_temp_size = 16;
00099 static inline uint32 patch_temp_offset(uint32 patch_num) { return patch_num * 16; }
00100
00101
00102
00103
00104
00105 static const uint32 patch_base = 0x050000;
00106 static const uint32 patch_mem_size = 8;
00107 static inline uint32 patch_mem_offset(uint32 patch_num) { return patch_num * 8; }
00108
00109 const LowLevelMidiDriver::MT32Patch LowLevelMidiDriver::mt32_patch_template = {
00110 0,
00111 0,
00112 24,
00113 50,
00114 24,
00115 0,
00116 1,
00117 0
00118 };
00119
00120
00121
00122
00123 static const uint32 all_dev_reset_base = 0x7f0000;
00124
00125
00126
00127 static const uint32 display_base = 0x200000;
00128 static const uint32 display_mem_size = 0x14;
00129
00130
00131 static inline int ConvBaseToActual(uint32 address_base)
00132 {
00133 return ((address_base>>2) & (0x7f<<14)) |
00134 ((address_base>>1) & (0x7f<<7)) |
00135 ((address_base>>0) & (0x7f<<0));
00136 }
00137
00138 using std::string;
00139 using std::endl;
00140
00141 LowLevelMidiDriver::LowLevelMidiDriver() :
00142 MidiDriver(), mutex(0), cbmutex(0),cond(0),
00143 global_volume(255), thread(0)
00144 {
00145 }
00146
00147 LowLevelMidiDriver::~LowLevelMidiDriver()
00148 {
00149
00150 if (initialized)
00151 {
00152 perr << "Warning: Destructing LowLevelMidiDriver and destroyMidiDriver() wasn't called!" << std::endl;
00153
00154 if (thread) SDL_KillThread(thread);
00155 }
00156 thread = 0;
00157 }
00158
00159
00160
00161
00162
00163 int LowLevelMidiDriver::initMidiDriver(uint32 samp_rate, bool is_stereo)
00164 {
00165
00166 if (initialized) destroyMidiDriver();
00167
00168 string s;
00169
00170
00171 std::memset(sequences, 0, sizeof (XMidiSequence*) * LLMD_NUM_SEQ);
00172 std::memset(chan_locks, -1, sizeof (sint32) * 16);
00173 std::memset(chan_map, -1, sizeof (sint32) * LLMD_NUM_SEQ * 16);
00174 for (int i = 0; i < LLMD_NUM_SEQ; i++) {
00175 playing[i] = false;
00176 callback_data[i] = -1;
00177 }
00178
00179 mutex = SDL_CreateMutex();
00180 cbmutex = SDL_CreateMutex();
00181 cond = SDL_CreateCond();
00182 thread = 0;
00183 sample_rate = samp_rate;
00184 stereo = is_stereo;
00185 uploading_timbres = false;
00186 next_sysex = 0;
00187
00188
00189 std::memset(mt32_patch_banks,0,sizeof(mt32_patch_banks[0])*128);
00190 std::memset(mt32_timbre_banks,0,sizeof(mt32_timbre_banks[0])*128);
00191 std::memset(mt32_timbre_used,-1,sizeof(mt32_timbre_used[0])*64);
00192 std::memset(mt32_bank_sel,0,sizeof(mt32_bank_sel[0])*LLMD_NUM_SEQ);
00193 std::memset(mt32_patch_bank_sel,0,sizeof(mt32_patch_bank_sel[0])*128);
00194 std::memset(mt32_rhythm_bank,0,sizeof(mt32_rhythm_bank[0])*128);
00195
00196 int code = 0;
00197
00198 if (isSampleProducer()) code = initSoftwareSynth();
00199 else code = initThreadedSynth();
00200
00201 if (code)
00202 {
00203 perr << "Failed to initialize midi player (code: " << code << ")" << endl;
00204 SDL_DestroyMutex(mutex);
00205 SDL_DestroyMutex(cbmutex);
00206 SDL_DestroyCond(cond);
00207 thread = 0;
00208 mutex = 0;
00209 cbmutex = 0;
00210 cond = 0;
00211 }
00212 else
00213 initialized = true;
00214
00215 return code;
00216 }
00217
00218 void LowLevelMidiDriver::destroyMidiDriver()
00219 {
00220 if (!initialized) return;
00221
00222 waitTillNoComMessages();
00223
00224 if (isSampleProducer()) destroySoftwareSynth();
00225 else destroyThreadedSynth();
00226
00227 initialized = false;
00228
00229 SDL_DestroyMutex(mutex);
00230 SDL_DestroyMutex(cbmutex);
00231 SDL_DestroyCond(cond);
00232 cbmutex = 0;
00233 mutex = 0;
00234 thread = 0;
00235 cond = 0;
00236
00237 giveinfo();
00238 }
00239
00240 int LowLevelMidiDriver::maxSequences()
00241 {
00242 return LLMD_NUM_SEQ;
00243 }
00244
00245 void LowLevelMidiDriver::startSequence(int seq_num, XMidiEventList *eventlist, bool repeat, int vol, int branch)
00246 {
00247 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return;
00248
00249 if (!initialized)
00250 return;
00251
00252
00253
00254 while (uploading_timbres) {
00255 waitTillNoComMessages();
00256
00257 lockComMessage();
00258 bool isplaying = playing[3];
00259 unlockComMessage();
00260
00261
00262
00263 if (isplaying) yield();
00264 else uploading_timbres = false;
00265 }
00266
00267 eventlist->incerementCounter();
00268
00269 ComMessage message(LLMD_MSG_PLAY);
00270 message.sequence = seq_num;
00271 message.data.play.list = eventlist;
00272 message.data.play.repeat = repeat;
00273 message.data.play.volume = vol;
00274 message.data.play.branch = branch;
00275
00276 sendComMessage(message);
00277 }
00278
00279 void LowLevelMidiDriver::finishSequence(int seq_num)
00280 {
00281 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return;
00282 if (!initialized) return;
00283 if (uploading_timbres) return;
00284
00285 ComMessage message(LLMD_MSG_FINISH);
00286 message.sequence = seq_num;
00287
00288 sendComMessage(message);
00289 }
00290
00291 void LowLevelMidiDriver::setSequenceVolume(int seq_num, int vol)
00292 {
00293 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return;
00294 if (vol < 0 || vol > 255) return;
00295 if (!initialized) return;
00296 if (uploading_timbres) return;
00297
00298 ComMessage message(LLMD_MSG_SET_VOLUME);
00299 message.sequence = seq_num;
00300 message.data.volume.level = vol;
00301
00302 sendComMessage(message);
00303 }
00304
00305 void LowLevelMidiDriver::setGlobalVolume(int vol)
00306 {
00307 if (vol < 0 || vol > 255) return;
00308 if (!initialized) return;
00309
00310 ComMessage message(LLMD_MSG_SET_VOLUME);
00311 message.sequence = -1;
00312 message.data.volume.level = vol;
00313
00314 sendComMessage(message);
00315 }
00316
00317 void LowLevelMidiDriver::setSequenceSpeed(int seq_num, int speed)
00318 {
00319 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return;
00320 if (speed < 0) return;
00321 if (!initialized) return;
00322 if (uploading_timbres) return;
00323
00324 ComMessage message(LLMD_MSG_SET_SPEED);
00325 message.sequence = seq_num;
00326 message.data.speed.percentage = speed;
00327
00328 sendComMessage(message);
00329 }
00330
00331 bool LowLevelMidiDriver::isSequencePlaying(int seq_num)
00332 {
00333 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return false;
00334 if (uploading_timbres) return false;
00335
00336 waitTillNoComMessages();
00337
00338 lockComMessage();
00339 bool ret = playing[seq_num];
00340 unlockComMessage();
00341
00342 return ret;
00343 }
00344
00345 void LowLevelMidiDriver::pauseSequence(int seq_num)
00346 {
00347 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return;
00348 if (!initialized) return;
00349 if (uploading_timbres) return;
00350
00351 ComMessage message(LLMD_MSG_PAUSE);
00352 message.sequence = seq_num;
00353 message.data.pause.paused = true;
00354
00355 sendComMessage(message);
00356 }
00357
00358 void LowLevelMidiDriver::unpauseSequence(int seq_num)
00359 {
00360 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return;
00361 if (!initialized) return;
00362 if (uploading_timbres) return;
00363
00364 ComMessage message(LLMD_MSG_PAUSE);
00365 message.sequence = seq_num;
00366 message.data.pause.paused = false;
00367
00368 sendComMessage(message);
00369 }
00370
00371 uint32 LowLevelMidiDriver::getSequenceCallbackData(int seq_num)
00372 {
00373 if (seq_num >= LLMD_NUM_SEQ || seq_num < 0) return 0;
00374
00375 SDL_mutexP(cbmutex);
00376 uint32 ret = callback_data[seq_num];
00377 SDL_mutexV(cbmutex);
00378
00379 return ret;
00380 }
00381
00382
00383
00384
00385
00386 sint32 LowLevelMidiDriver::peekComMessageType()
00387 {
00388 lockComMessage();
00389 sint32 ret = 0;
00390 if (messages.size()) ret = messages.front().type;
00391 unlockComMessage();
00392 return ret;
00393 }
00394
00395 void LowLevelMidiDriver::sendComMessage(ComMessage& message)
00396 {
00397 lockComMessage();
00398 messages.push(message);
00399 SDL_CondSignal(cond);
00400 unlockComMessage();
00401 }
00402
00403 void LowLevelMidiDriver::waitTillNoComMessages()
00404 {
00405 while (peekComMessageType()) yield ();
00406 }
00407
00408 void LowLevelMidiDriver::lockComMessage()
00409 {
00410 SDL_mutexP(mutex);
00411 }
00412
00413 void LowLevelMidiDriver::unlockComMessage()
00414 {
00415 SDL_mutexV(mutex);
00416 }
00417
00418
00419
00420
00421
00422 int LowLevelMidiDriver::initThreadedSynth()
00423 {
00424
00425 giveinfo();
00426
00427 ComMessage message(LLMD_MSG_THREAD_INIT);
00428 sendComMessage(message);
00429
00430 thread = SDL_CreateThread (threadMain_Static, static_cast<void*>(this));
00431
00432 while (peekComMessageType() == LLMD_MSG_THREAD_INIT)
00433 yield ();
00434
00435 int code = 0;
00436
00437 lockComMessage();
00438 {
00439 while (!messages.empty())
00440 {
00441 if (messages.front().type == LLMD_MSG_THREAD_INIT_FAILED)
00442 code = messages.front().data.init_failed.code;
00443 messages.pop();
00444 }
00445 }
00446 unlockComMessage();
00447
00448 return code;
00449 }
00450
00451 void LowLevelMidiDriver::destroyThreadedSynth()
00452 {
00453 ComMessage message(LLMD_MSG_THREAD_EXIT);
00454 sendComMessage(message);
00455
00456 int count = 0;
00457
00458 while (count < 400)
00459 {
00460 giveinfo();
00461
00462 if (peekComMessageType() != 0)
00463 {
00464 yield ();
00465 SDL_Delay(1);
00466 }
00467 else break;
00468
00469 count++;
00470 }
00471
00472
00473 if (count == 400 && peekComMessageType() != 0) {
00474 perr << "MidiPlayer Thread failed to stop in time. Killing it." << std::endl;
00475 SDL_KillThread (thread);
00476 }
00477
00478 lockComMessage();
00479 {
00480
00481 while (!messages.empty()) messages.pop();
00482 }
00483 unlockComMessage();
00484
00485 }
00486
00487 int LowLevelMidiDriver::threadMain_Static(void *data)
00488 {
00489 giveinfo();
00490 LowLevelMidiDriver *ptr=static_cast<LowLevelMidiDriver *>(data);
00491 giveinfo();
00492 return ptr->threadMain();
00493 }
00494
00495 int LowLevelMidiDriver::threadMain()
00496 {
00497 giveinfo();
00498
00499
00500 int code = open();
00501
00502 lockComMessage();
00503 {
00504
00505 while(!messages.empty()) messages.pop();
00506
00507
00508
00509 if (code)
00510 {
00511 ComMessage message(LLMD_MSG_THREAD_INIT_FAILED);
00512 message.data.init_failed.code = code;
00513 messages.push(message);
00514 }
00515 }
00516 unlockComMessage();
00517
00518 if (code) return code;
00519
00520
00521 increaseThreadPriority();
00522
00523
00524 for (;;)
00525 {
00526 xmidi_clock = SDL_GetTicks()*6;
00527 if (playSequences()) break;
00528
00529 sint32 time_till_next = 0x7FFFFFFF;
00530
00531 for (int i = 0; i < LLMD_NUM_SEQ; i++)
00532 {
00533 int seq = i;
00534
00535 if (sequences[seq])
00536 {
00537 sint32 ms = sequences[seq]->timeTillNext();
00538 if (ms < time_till_next) time_till_next = ms;
00539 }
00540 }
00541
00542 if (time_till_next <= LLMD_MINIMUM_YIELD_THRESHOLD)
00543 {
00544 bool wait = false;
00545 lockComMessage();
00546 if (messages.empty()) wait = true;
00547 unlockComMessage();
00548 if (wait)
00549 {
00550
00551 yield();
00552
00553 }
00554 else
00555 {
00556
00557 }
00558 }
00559 else
00560 {
00561 lockComMessage();
00562 if (messages.empty())
00563 {
00564
00565 SDL_CondWaitTimeout(cond, mutex,time_till_next-2);
00566
00567 }
00568 else
00569 {
00570
00571 }
00572 unlockComMessage();
00573 }
00574 }
00575
00576
00577 const char exit_display[] = "Poor Poor Avatar... ";
00578 sendMT32SystemMessage(display_base,0,display_mem_size,exit_display);
00579 sendMT32SystemMessage(all_dev_reset_base,0,1,exit_display);
00580 SDL_Delay(40);
00581
00582
00583 close();
00584
00585 lockComMessage();
00586 {
00587
00588 while(!messages.empty()) messages.pop();
00589 initialized = false;
00590 }
00591 unlockComMessage();
00592
00593 return 0;
00594 }
00595
00596
00597
00598
00599
00600 int LowLevelMidiDriver::initSoftwareSynth()
00601 {
00602
00603 int ret = open();
00604
00605
00606 if (ret) return 1;
00607
00608
00609 total_seconds = 0;
00610 samples_this_second = 0;
00611
00612
00613
00614
00615 if (sample_rate == 11025)
00616 samples_per_iteration = 49;
00617 if (sample_rate == 22050)
00618 samples_per_iteration = 98;
00619 else if (sample_rate == 44100)
00620 samples_per_iteration = 147;
00621 else
00622 {
00623 samples_per_iteration = sample_rate/480;
00624
00625
00626 if (!(samples_per_iteration&1)) samples_per_iteration>>=1;
00627
00628 if (!(samples_per_iteration&1)) samples_per_iteration>>=1;
00629 }
00630
00631 return 0;
00632 }
00633
00634 void LowLevelMidiDriver::destroySoftwareSynth()
00635 {
00636
00637 ComMessage message(LLMD_MSG_THREAD_EXIT);
00638 sendComMessage(message);
00639
00640
00641 waitTillNoComMessages();
00642
00643 close();
00644 }
00645
00646 void LowLevelMidiDriver::produceSamples(sint16 *samples, uint32 bytes)
00647 {
00648
00649 if (!initialized) return;
00650
00651 int stereo_mult = 1;
00652 if (stereo) stereo_mult = 2;
00653
00654 uint32 num_samples = bytes/(2*stereo_mult);
00655
00656
00657 while (num_samples > 0)
00658 {
00659 uint32 samples_to_produce = samples_per_iteration;
00660 if (samples_to_produce > num_samples) samples_to_produce = num_samples;
00661
00662
00663 samples_this_second += samples_to_produce;
00664 while (samples_this_second > sample_rate)
00665 {
00666 total_seconds++;
00667 samples_this_second -= sample_rate;
00668 }
00669
00670
00671 xmidi_clock = (total_seconds*6000) + (samples_this_second*6000)/sample_rate;
00672
00673
00674 if (playSequences()) {
00675
00676 lockComMessage();
00677 {
00678
00679 while(!messages.empty()) messages.pop();
00680 initialized = false;
00681 }
00682 unlockComMessage();
00683
00684 break;
00685 }
00686
00687
00688 lowLevelProduceSamples(samples, samples_to_produce);
00689
00690
00691 samples += samples_to_produce*stereo_mult;
00692 num_samples -= samples_to_produce;
00693 }
00694 }
00695
00696
00697
00698
00699
00700 bool LowLevelMidiDriver::playSequences ()
00701 {
00702 int i;
00703
00704
00705 for (i = 0; i < LLMD_NUM_SEQ; i++)
00706 {
00707 int seq = i;
00708
00709 while (sequences[seq] && !peekComMessageType())
00710 {
00711 sint32 pending_events = sequences[seq]->playEvent();
00712
00713 if (pending_events > 0) break;
00714 else if (pending_events == -1)
00715 {
00716 delete sequences[seq];
00717 sequences[seq] = 0;
00718 lockComMessage();
00719 playing[seq] = false;
00720 unlockComMessage();
00721 }
00722 }
00723 }
00724
00725
00726 lockComMessage();
00727 {
00728 while (!messages.empty())
00729 {
00730 ComMessage message = messages.front();
00731
00732
00733 if (messages.back().type == LLMD_MSG_THREAD_EXIT)
00734 message = messages.back();
00735
00736 switch (message.type)
00737 {
00738 case LLMD_MSG_FINISH:
00739 {
00740 delete sequences[message.sequence];
00741 sequences[message.sequence] = 0;
00742 playing[message.sequence] = false;
00743 callback_data[message.sequence] = -1;
00744 unlockAndUnprotectChannel(message.sequence);
00745 }
00746 break;
00747
00748 case LLMD_MSG_THREAD_EXIT:
00749 {
00750 for (i = 0; i < LLMD_NUM_SEQ; i++)
00751 {
00752 delete sequences[i];
00753 sequences[i] = 0;
00754 playing[i] = false;
00755 callback_data[i] = -1;
00756 unlockAndUnprotectChannel(i);
00757 }
00758 }
00759 unlockComMessage();
00760 return true;
00761
00762 case LLMD_MSG_SET_VOLUME:
00763 {
00764 if (message.sequence == -1)
00765 {
00766 global_volume = message.data.volume.level;
00767 for (i = 0; i < LLMD_NUM_SEQ; i++)
00768 if (sequences[i])
00769 sequences[i]->setVolume(sequences[i]->getVolume());
00770 }
00771 else if (sequences[message.sequence])
00772 sequences[message.sequence]->setVolume(message.data.volume.level);
00773 }
00774 break;
00775
00776 case LLMD_MSG_SET_SPEED:
00777 {
00778 if (sequences[message.sequence])
00779 sequences[message.sequence]->setSpeed(message.data.speed.percentage);
00780 }
00781 break;
00782
00783 case LLMD_MSG_PAUSE:
00784 {
00785 if (sequences[message.sequence])
00786 {
00787 if (!message.data.pause.paused) sequences[message.sequence]->unpause();
00788 else sequences[message.sequence]->pause();
00789 }
00790 }
00791 break;
00792
00793 case LLMD_MSG_PLAY:
00794 {
00795
00796 delete sequences[message.sequence];
00797 sequences[message.sequence] = 0;
00798 playing[message.sequence] = false;
00799 callback_data[message.sequence] = -1;
00800 unlockAndUnprotectChannel(message.sequence);
00801
00802 giveinfo();
00803
00804 if (message.data.play.list)
00805 {
00806 sequences[message.sequence] = new XMidiSequence(
00807 this,
00808 message.sequence,
00809 message.data.play.list,
00810 message.data.play.repeat,
00811 message.data.play.volume,
00812 message.data.play.branch);
00813
00814 playing[message.sequence] = true;
00815
00816 uint16 mask = sequences[message.sequence]->getChanMask();
00817
00818
00819
00820
00821
00822
00823 }
00824
00825 }
00826 break;
00827
00828
00829 case LLMD_MSG_PRECACHE_TIMBRES:
00830 {
00831 int count = 0;
00832
00833 for (int bank = 0; bank < 128; bank++)
00834 {
00835 if (mt32_timbre_banks[bank]) for (int timbre = 0; timbre < 128; timbre++)
00836 {
00837 if (mt32_timbre_banks[bank][timbre])
00838 {
00839 uploadTimbre(bank,timbre);
00840 count++;
00841
00842 if (count == 64) break;
00843 }
00844 }
00845 if (count == 64) break;
00846 }
00847
00848 if (mt32_patch_banks[0]) for (int patch = 0; patch < 128; patch++)
00849 {
00850 if (mt32_patch_banks[0][patch] && mt32_patch_banks[0][patch]->timbre_bank >= 2)
00851 setPatchBank(0,patch);
00852 }
00853 }
00854 break;
00855
00856
00857 default:
00858 break;
00859 }
00860
00861
00862 messages.pop();
00863 }
00864 }
00865 unlockComMessage();
00866
00867 return false;
00868 }
00869
00870 void LowLevelMidiDriver::sequenceSendEvent(uint16 sequence_id, uint32 message)
00871 {
00872 int log_chan = message & 0xF;
00873 message &= 0xFFFFFFF0;
00874
00875
00876 if ((message & 0x00F0) == (MIDI_STATUS_CONTROLLER << 4))
00877 {
00878
00879 if ((message & 0xFF00) == (7 << 8))
00880 {
00881 int vol = (message >> 16) & 0xFF;
00882 message &= 0x00FFFF;
00883
00884 vol = (vol * global_volume) / 0xFF;
00885 message |= vol << 16;
00886 }
00887 else if ((message & 0xFF00) == (XMIDI_CONTROLLER_CHAN_LOCK << 8))
00888 {
00889 lockChannel(sequence_id, log_chan, ((message>>16)&0xFF)>=64);
00890 return;
00891 }
00892 else if ((message & 0xFF00) == (XMIDI_CONTROLLER_CHAN_LOCK_PROT << 8))
00893 {
00894 protectChannel(sequence_id, log_chan, ((message>>16)&0xFF)>=64);
00895 return;
00896 }
00897 else if ((message & 0xFF00) == (XMIDI_CONTROLLER_BANK_CHANGE << 8))
00898 {
00899
00900 mt32_bank_sel[sequence_id][log_chan] = (message>>16)&0xFF;
00901
00902 }
00903 }
00904 else if ((message & 0x00F0) == (MIDI_STATUS_PROG_CHANGE << 4))
00905 {
00906 if (mt32_patch_banks[0])
00907 {
00908 int bank = mt32_bank_sel[sequence_id][log_chan];
00909 int patch = (message & 0xFF00)>>8;
00910
00911 if (bank != mt32_patch_bank_sel[patch]) setPatchBank(bank,patch);
00912 }
00913 }
00914 else if ((message & 0x00F0) == (MIDI_STATUS_NOTE_ON << 4) && log_chan == 0x9)
00915 {
00916 int temp = (message>>8)&0xFF;
00917 if (mt32_rhythm_bank[temp]) loadRhythmTemp(temp);
00918 }
00919
00920
00921 int phys_chan = chan_map[sequence_id][log_chan];
00922
00923 if (phys_chan == -2) return;
00924 else if (phys_chan < 0) phys_chan = log_chan;
00925
00926 send(message|phys_chan);
00927 }
00928
00929 void LowLevelMidiDriver::sequenceSendSysEx(uint16 sequence_id, uint8 status, const uint8 *msg, uint16 length)
00930 {
00931
00932 if (status == 0xFF) return;
00933
00934
00935 if (!msg || !length) return;
00936
00937
00938 if (uploading_timbres && length > 7)
00939 {
00940
00941
00942 if (msg[0] == 0x41 && msg[1] == 0x10 && msg[2] == 0x16 && msg[3] == 0x12)
00943 {
00944 uint32 actual_address = (msg[4]<<14) | (msg[5]<<7) | msg[6];
00945
00946 uint32 timbre_add_start = ConvBaseToActual(timbre_base);
00947 uint32 timbre_add_end = timbre_add_start + timbre_mem_offset(64);
00948 uint32 patch_add_start = ConvBaseToActual(patch_base);
00949 uint32 patch_add_end = patch_add_start + patch_mem_offset(128);
00950 uint32 rhythm_add_start = ConvBaseToActual(rhythm_base);
00951 uint32 rhythm_add_end = rhythm_add_start + rhythm_mem_offset(85);
00952 uint32 timbre_temp_add_start = ConvBaseToActual(timbre_temp_base);
00953 uint32 timbre_temp_add_end = timbre_temp_add_start + timbre_mem_offset(8);
00954 uint32 patch_temp_add_start = ConvBaseToActual(patch_temp_base);
00955 uint32 patch_temp_add_end = patch_temp_add_start + patch_temp_offset(8);
00956 uint32 timbre_unk_add_start = ConvBaseToActual(timbre_unk_base);
00957 uint32 timbre_unk_add_end = timbre_unk_add_start + timbre_mem_offset(128);
00958
00959 uint32 sysex_size = length-(4+3+1+1);
00960
00961 if (actual_address >= timbre_add_start && actual_address < timbre_add_end)
00962 {
00963 return;
00964 }
00965 if (actual_address >= timbre_temp_add_start && actual_address < timbre_temp_add_end)
00966 {
00967 return;
00968 }
00969 if (actual_address >= timbre_unk_add_start && actual_address < timbre_unk_add_end)
00970 {
00971 return;
00972 }
00973 if (actual_address >= patch_add_start && actual_address < patch_add_end)
00974 {
00975 return;
00976 }
00977 if (actual_address >= patch_temp_add_start && actual_address < patch_temp_add_end)
00978 {
00979 return;
00980 }
00981 if (actual_address >= rhythm_add_start && actual_address < rhythm_add_end)
00982 {
00983 return;
00984 }
00985 }
00986 }
00987
00988
00989
00990 int ticks = SDL_GetTicks();
00991 if (next_sysex > ticks) SDL_Delay(next_sysex-ticks);
00992 send_sysex(status,msg,length);
00993 next_sysex = SDL_GetTicks() + 40;
00994 }
00995
00996 uint32 LowLevelMidiDriver::getTickCount(uint16 sequence_id)
00997 {
00998 return xmidi_clock;
00999 }
01000
01001 void LowLevelMidiDriver::handleCallbackTrigger(uint16 sequence_id, uint8 data)
01002 {
01003 SDL_mutexP(cbmutex);
01004 callback_data[sequence_id] = data;
01005 SDL_mutexV(cbmutex);
01006 }
01007
01008 int LowLevelMidiDriver::protectChannel(uint16 sequence_id, int chan, bool protect)
01009 {
01010
01011 if (!protect)
01012 {
01013 chan_locks[chan] = -1;
01014 chan_map[sequence_id][chan] = -1;
01015 }
01016
01017 else if (chan_locks[chan] != -2)
01018 {
01019
01020 int relock_sid = -1;
01021 int relock_log = -1;
01022 if (chan_locks[chan] != -1)
01023 {
01024 relock_sid = chan_locks[chan];
01025
01026
01027 for (int c = 0; c < 16; c++)
01028 {
01029 if (chan_map[relock_sid][c] == chan)
01030 {
01031 relock_log = c;
01032 break;
01033 }
01034 }
01035
01036
01037 lockChannel(relock_sid, relock_log, false);
01038 }
01039
01040
01041 chan_locks[chan] = -2;
01042 chan_map[sequence_id][chan] = -3;
01043
01044
01045 if (relock_sid != -1)
01046 lockChannel(relock_sid, relock_log, true);
01047 }
01048
01049 return 0;
01050 }
01051
01052 int LowLevelMidiDriver::lockChannel(uint16 sequence_id, int chan, bool lock)
01053 {
01054
01055
01056
01057 if (lock)
01058 {
01059 int notes_on[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
01060 int s, c, phys;
01061
01062 for (s = 0; s < LLMD_NUM_SEQ; s++)
01063 {
01064 if (sequences[s]) for (c = 0; c < 16; c++)
01065 {
01066 phys = chan_map[s][c];
01067 if (phys == -1) phys = c;
01068 if (phys != -2)
01069 notes_on[phys] += sequences[s]->countNotesOn(c);
01070 }
01071 }
01072
01073 phys = -1;
01074 int prev_max = 128;
01075 for (c = 0; c < 16; c++)
01076 {
01077
01078 if (chan_locks[c] != -1) continue;
01079
01080 if (notes_on[c] <= prev_max)
01081 {
01082 prev_max = notes_on[c];
01083 phys = c;
01084 }
01085 }
01086
01087
01088 if (phys == -1) return -1;
01089
01090
01091 for (s = 0; s < LLMD_NUM_SEQ; s++)
01092 {
01093
01094 if (sequences[s] && chan_map[s][phys] == -1)
01095 {
01096 sequences[s]->loseChannel(phys);
01097 chan_map[s][phys] = -2;
01098 }
01099 }
01100
01101
01102 if (phys != chan) sequences[sequence_id]->loseChannel(chan);
01103
01104
01105 chan_map[sequence_id][chan] = phys;
01106 chan_locks[phys] = sequence_id;
01107 sequences[sequence_id]->gainChannel(chan);
01108 }
01109
01110 else
01111 {
01112 int phys = chan_map[sequence_id][chan];
01113
01114
01115 if (phys < 0) return -1;
01116
01117
01118 if (sequences[sequence_id])
01119 sequences[sequence_id]->loseChannel(chan);
01120
01121
01122 chan_map[sequence_id][chan] = -1;
01123 chan_locks[phys] = -1;
01124
01125
01126 if (phys != chan && sequences[sequence_id])
01127 sequences[sequence_id]->gainChannel(chan);
01128
01129
01130 for (int s = 0; s < LLMD_NUM_SEQ; s++)
01131 {
01132
01133 if (sequences[s] && chan_map[s][phys] == -2)
01134 {
01135 chan_map[s][phys] = -1;
01136 sequences[s]->gainChannel(phys);
01137 }
01138 }
01139 }
01140
01141 return 0;
01142 }
01143
01144 int LowLevelMidiDriver::unlockAndUnprotectChannel(uint16 sequence_id)
01145 {
01146
01147 for (int c = 0; c < 16; c++)
01148 {
01149 int phys = chan_map[sequence_id][c];
01150
01151
01152 if (phys != -3) continue;
01153
01154
01155 if (phys == -3)
01156 {
01157 protectChannel(sequence_id, c, false);
01158 }
01159
01160 else
01161 {
01162 lockChannel(sequence_id, c, false);
01163 }
01164 }
01165 return 0;
01166 }
01167
01168
01169
01170 void LowLevelMidiDriver::loadTimbreLibrary(IDataSource *ds, TimbreLibraryType type)
01171 {
01172
01173 uint32 i,j;
01174 for (i = 0 ; i < LLMD_NUM_SEQ; i++) {
01175 ComMessage message(LLMD_MSG_FINISH);
01176 message.sequence = i;
01177 sendComMessage(message);
01178 }
01179
01180
01181 waitTillNoComMessages();
01182
01183
01184 lockComMessage();
01185
01186
01187
01188
01189 for (i = 0; i < 128; i++) {
01190
01191 if (mt32_patch_banks[i]) for (j = 0; j < 128; j++) delete mt32_patch_banks[i][j];
01192 if (mt32_timbre_banks[i]) for (j = 0; j < 128; j++) delete mt32_timbre_banks[i][j];
01193
01194
01195 delete [] mt32_patch_banks[i];
01196 delete [] mt32_timbre_banks[i];
01197
01198 delete mt32_rhythm_bank[i];
01199 }
01200
01201
01202 std::memset(mt32_patch_banks,0,sizeof(mt32_patch_banks[0])*128);
01203
01204
01205 std::memset(mt32_timbre_banks,0,sizeof(mt32_timbre_banks[0])*128);
01206
01207
01208 std::memset(mt32_timbre_used,-1,sizeof(mt32_timbre_used[0])*64);
01209
01210
01211 std::memset(mt32_bank_sel,0,sizeof(mt32_bank_sel[0])*LLMD_NUM_SEQ);
01212
01213
01214 std::memset(mt32_patch_bank_sel,0,sizeof(mt32_patch_bank_sel[0])*128);
01215
01216
01217 std::memset(mt32_rhythm_bank,0,sizeof(mt32_rhythm_bank[0])*128);
01218
01219
01220 mt32_patch_banks[0] = new MT32Patch*[128];
01221 for (i = 0; i < 128; i++) {
01222 mt32_patch_banks[0][i] = new MT32Patch;
01223
01224
01225 *(mt32_patch_banks[0][i]) = mt32_patch_template;
01226 mt32_patch_banks[0][i]->timbre_bank = 0;
01227 mt32_patch_banks[0][i]->timbre_num = i;
01228 }
01229
01230 XMidiFile *xmidi = 0;
01231
01232 if (type == TIMBRE_LIBRARY_U7VOICE_MT)
01233 xmidi = new XMidiFile(ds,XMIDIFILE_HINT_U7VOICE_MT_FILE);
01234 else if (type == TIMBRE_LIBRARY_SYX_FILE)
01235 xmidi = new XMidiFile(ds,XMIDIFILE_HINT_SYX_FILE);
01236 else if (type == TIMBRE_LIBRARY_XMIDI_FILE)
01237 xmidi = new XMidiFile(ds,XMIDIFILE_HINT_SYSEX_IN_MID);
01238 else if (type == TIMBRE_LIBRARY_XMIDI_MT)
01239 {
01240 loadXMidiTimbreLibrary(ds);
01241 ds->seek(0);
01242 xmidi = new XMidiFile(ds,XMIDIFILE_HINT_XMIDI_MT_FILE);
01243 }
01244
01245
01246 unlockComMessage();
01247
01248 if (!xmidi) return;
01249
01250 XMidiEventList *eventlist = xmidi->GetEventList(0);
01251 if (!eventlist) return;
01252
01253 extractTimbreLibrary(eventlist);
01254
01255 uploading_timbres = true;
01256
01257
01258
01259 ComMessage message(LLMD_MSG_PLAY);
01260 message.sequence = 3;
01261 message.data.play.list = eventlist;
01262 message.data.play.repeat = false;
01263 message.data.play.volume = 255;
01264 message.data.play.branch = 0;
01265 sendComMessage(message);
01266
01267 if (type == TIMBRE_LIBRARY_XMIDI_FILE)
01268 {
01269 message.type = LLMD_MSG_SET_SPEED;
01270 message.sequence = 3;
01271 message.data.speed.percentage = 400;
01272 sendComMessage(message);
01273 }
01274
01275
01276 if (1) {
01277 waitTillNoComMessages();
01278
01279 bool is_playing = true;
01280
01281 do {
01282 lockComMessage();
01283 is_playing = playing[3];
01284 unlockComMessage();
01285
01286 if (is_playing) yield();
01287 } while (is_playing);
01288 uploading_timbres = false;
01289
01290 pout << "Precaching Timbres" << std::endl;
01291 ComMessage precache(LLMD_MSG_PRECACHE_TIMBRES);
01292 sendComMessage(precache);
01293 }
01294 }
01295
01296 void LowLevelMidiDriver::extractTimbreLibrary(XMidiEventList *eventlist)
01297 {
01298 for (XMidiEvent *event = eventlist->events; event; event = event->next)
01299 {
01300 if (event->status != 0xF0) continue;
01301
01302 uint16 length = event->ex.sysex_data.len;
01303 uint8 *msg = event->ex.sysex_data.buffer;
01304
01305 if (msg && length > 7 && msg[0] == 0x41 && msg[1] == 0x10 && msg[2] == 0x16 && msg[3] == 0x12)
01306 {
01307 uint32 actual_address = (msg[4]<<14) | (msg[5]<<7) | msg[6];
01308
01309 uint32 timbre_add_start = ConvBaseToActual(timbre_base);
01310 uint32 timbre_add_end = timbre_add_start + timbre_mem_offset(64);
01311 uint32 patch_add_start = ConvBaseToActual(patch_base);
01312 uint32 patch_add_end = patch_add_start + patch_mem_offset(128);
01313 uint32 rhythm_add_start = ConvBaseToActual(rhythm_base);
01314 uint32 rhythm_add_end = rhythm_add_start + rhythm_mem_offset(85);
01315
01316 uint32 sysex_size = length-(4+3+1+1);
01317 msg += 7;
01318
01319 if ((actual_address+sysex_size) >= timbre_add_start && actual_address < timbre_add_end)
01320 {
01321 uint32 start = actual_address;
01322 uint32 size = sysex_size;
01323 if (actual_address < timbre_add_start)
01324 {
01325 sysex_size -= timbre_add_start-actual_address;
01326 actual_address = timbre_add_start;
01327 }
01328 if ((start+size) > timbre_add_end) size = timbre_add_end-start;
01329 start -= timbre_add_start;
01330 start /= 256;
01331
01332
01333 if (!mt32_timbre_banks[2]) {
01334 mt32_timbre_banks[2] = new MT32Timbre*[128];
01335 std::memset(mt32_timbre_banks[2],0,sizeof(mt32_timbre_banks[2][0])*128);
01336 }
01337 if (!mt32_timbre_banks[2][start]) mt32_timbre_banks[2][start] = new MT32Timbre;
01338
01339
01340 mt32_timbre_banks[2][start]->time_uploaded = 0;
01341 mt32_timbre_banks[2][start]->index = -1;
01342 mt32_timbre_banks[2][start]->protect = false;
01343
01344
01345 std::memcpy(mt32_timbre_banks[2][start]->timbre,msg,246);
01346 }
01347 if ((actual_address+sysex_size) >= patch_add_start && actual_address < patch_add_end)
01348 {
01349 uint32 start = actual_address;
01350 uint32 size = sysex_size;
01351 if (actual_address < patch_add_start)
01352 {
01353 sysex_size -= patch_add_start-actual_address;
01354 actual_address = patch_add_start;
01355 }
01356 if ((start+size) > patch_add_end) size = patch_add_end-start;
01357 start -= patch_add_start;
01358 start /= 8;
01359 size /= 8;
01360
01361
01362 for (uint32 patch = start; patch < start+size; patch++, msg+=8)
01363 {
01364 mt32_patch_bank_sel[patch] = -1;
01365
01366 std::memcpy(mt32_patch_banks[0][patch],msg,8);
01367 if (mt32_patch_banks[0][patch]->timbre_bank == 1)
01368 {
01369 mt32_patch_banks[0][patch]->timbre_bank = 0;
01370 mt32_patch_banks[0][patch]->timbre_num += 0x40;
01371 }
01372 else if (mt32_patch_banks[0][patch]->timbre_bank == 3)
01373 {
01374 mt32_patch_banks[0][patch]->timbre_bank = -1;
01375 }
01376 }
01377 }
01378 if ((actual_address+sysex_size) >= rhythm_add_start && actual_address < rhythm_add_end)
01379 {
01380 uint32 start = actual_address;
01381 uint32 size = sysex_size;
01382 if (actual_address < rhythm_add_start)
01383 {
01384 sysex_size -= rhythm_add_start-actual_address;
01385 actual_address = rhythm_add_start;
01386 }
01387 if ((start+size) > rhythm_add_end) size = rhythm_add_end-start;
01388 start -= rhythm_add_start;
01389 start /= 4;
01390 size /= 4;
01391
01392
01393 for (uint32 temp = start; temp < start+size; temp++, msg+=4)
01394 {
01395 if (!mt32_rhythm_bank[temp]) mt32_rhythm_bank[temp] = new MT32Rhythm;
01396 std::memcpy(mt32_rhythm_bank[temp],msg,4);
01397 }
01398 }
01399 }
01400 }
01401 }
01402
01403
01404
01405 void LowLevelMidiDriver::sendMT32SystemMessage(uint32 address_base, uint16 address_offset, uint32 len, const void *data)
01406 {
01407 unsigned char sysex_buffer[512];
01408
01409
01410 sysex_buffer[0] = 0x41;
01411 sysex_buffer[1] = 0x10;
01412 sysex_buffer[2] = 0x16;
01413 sysex_buffer[3] = 0x12;
01414
01415
01416 uint32 actual_address = address_offset + ConvBaseToActual(address_base);
01417 sysex_buffer[4] = (actual_address>>14)&0x7F;
01418 sysex_buffer[5] = (actual_address>>7)&0x7F;
01419 sysex_buffer[6] = actual_address&0x7F;
01420
01421
01422 if (data) std::memcpy (sysex_buffer+sysex_data_start, data, len);
01423
01424
01425 char checksum = 0;
01426 for (uint32 j = 4; j < sysex_data_start+len; j++)
01427 checksum += sysex_buffer[j];
01428
01429 checksum = checksum & 0x7f;
01430 if (checksum) checksum = 0x80 - checksum;
01431
01432
01433 sysex_buffer[sysex_data_start+len] = checksum;
01434
01435
01436 sysex_buffer[sysex_data_start+len+1] = 0xF7;
01437
01438
01439
01440 int ticks = SDL_GetTicks();
01441 if (next_sysex > ticks) SDL_Delay(next_sysex-ticks);
01442 send_sysex(0xF0,sysex_buffer,sysex_data_start+len+2);
01443 next_sysex = SDL_GetTicks() + 40;
01444 }
01445
01446 void LowLevelMidiDriver::setPatchBank(int bank, int patch)
01447 {
01448
01449 if (bank < -1 || bank > 127) {
01450 perr << "LLMD: Invalid bank in setPatchBank" << std::endl;
01451 return;
01452 }
01453
01454 else if (patch < 0 || patch > 127) {
01455 perr << "LLMD: Invalid patch in setPatchBank" << std::endl;
01456 return;
01457 }
01458
01459 else if (bank != -1 && !mt32_patch_banks[bank]) {
01460 perr << "LLMD: Patch bank doesn't exist in setPatchBank" << std::endl;
01461 return;
01462 }
01463
01464 if (bank != -1 && !mt32_patch_banks[bank][patch]) {
01465 perr << "LLMD: Patch not loaded in setPatchBank" << std::endl;
01466 return;
01467 }
01468
01469 MT32Patch p;
01470
01471 if (bank == -1)
01472 {
01473 p = mt32_patch_template;
01474 p.timbre_bank = 0;
01475 p.timbre_num = patch;
01476 }
01477 else
01478 p = *(mt32_patch_banks[bank][patch]);
01479
01480
01481 if (p.timbre_bank > 0) {
01482
01483 if (!mt32_timbre_banks[p.timbre_bank] || !mt32_timbre_banks[p.timbre_bank][p.timbre_num]) {
01484 perr << "LLMD: Timbre not loaded in setPatchBank" << std::endl;
01485 return;
01486 }
01487
01488
01489 if(mt32_timbre_banks[p.timbre_bank][p.timbre_num]->index == -1) {
01490
01491 uploadTimbre(p.timbre_bank,p.timbre_num);
01492 }
01493
01494 p.timbre_num = mt32_timbre_banks[p.timbre_bank][p.timbre_num]->index;
01495 p.timbre_bank = 2;
01496
01497
01498 if (p.timbre_num == -1) {
01499 perr << "LLMD: Timbre failed to upload" << std::endl;
01500 return;
01501 }
01502 }
01503 else if (p.timbre_bank == -1) {
01504 p.timbre_bank = 3;
01505 } else if (patch <= 0x3f) {
01506 p.timbre_bank = 0;
01507 } else {
01508 p.timbre_bank = 1;
01509 p.timbre_num = p.timbre_num&0x3f;
01510 }
01511
01512
01513 mt32_patch_bank_sel[patch] = bank;
01514
01515
01516 pout << "LLMD: Uploading Patch for " << bank << ":" << patch << " using timbre " << (int) p.timbre_bank << ":" << (int) p.timbre_num << std::endl;
01517 sendMT32SystemMessage(patch_base,patch_mem_offset(patch),patch_mem_size, &p );
01518 }
01519
01520 void LowLevelMidiDriver::loadRhythmTemp(int temp)
01521 {
01522 if (!mt32_rhythm_bank[temp]) return;
01523
01524 int timbre = mt32_rhythm_bank[temp]->timbre;
01525
01526 if (timbre < 0x40) {
01527
01528
01529 if (!mt32_timbre_banks[2] || !mt32_timbre_banks[2][timbre]) {
01530 perr << "LLMD: Timbre not loaded in loadRhythmTemp" << std::endl;
01531 return;
01532 }
01533
01534
01535 if(mt32_timbre_banks[2][timbre]->index == -1) {
01536
01537 uploadTimbre(2,timbre);
01538 }
01539
01540 mt32_timbre_banks[2][timbre]->protect = true;
01541 mt32_rhythm_bank[temp]->timbre = mt32_timbre_banks[2][timbre]->index;
01542 }
01543
01544 pout << "LLMD: Uploading Rhythm Temp " << temp << " using timbre " << (int) mt32_rhythm_bank[temp]->timbre << std::endl;
01545 sendMT32SystemMessage(rhythm_base,rhythm_mem_offset(temp),rhythm_mem_size, mt32_rhythm_bank[temp] );
01546
01547 delete mt32_rhythm_bank[temp];
01548 mt32_rhythm_bank[temp] = 0;
01549 }
01550
01551 void LowLevelMidiDriver::uploadTimbre(int bank, int patch)
01552 {
01553
01554 if (!mt32_timbre_banks[bank] || !mt32_timbre_banks[bank][patch]) {
01555 perr << "LLMD: No bank loaded in uploadTimbre" << std::endl;
01556 return;
01557 }
01558
01559
01560 if (mt32_timbre_banks[bank][patch]->index != -1) {
01561 perr << "LLMD: Timbre already loaded in uploadTimbre" << std::endl;
01562 return;
01563 }
01564
01565 int lru_index = -1;
01566 uint32 lru_time = 0xFFFFFFFF;
01567
01568 for (int i = 0; i < 64; i++) {
01569 int tbank = mt32_timbre_used[i][0];
01570 int tpatch = mt32_timbre_used[i][1];
01571
01572
01573 if (tbank == -1) {
01574 lru_index = i;
01575 break;
01576 }
01577
01578
01579 if (!mt32_timbre_banks[tbank] || !mt32_timbre_banks[tbank][tpatch])
01580 continue;
01581
01582
01583 if (mt32_timbre_banks[tbank][tpatch]->protect)
01584 continue;
01585
01586
01587 if (mt32_patch_bank_sel[tpatch] == bank)
01588 continue;
01589
01590
01591 if (mt32_timbre_banks[tbank][tpatch]->time_uploaded < lru_time) {
01592 lru_index = i;
01593 lru_time = mt32_timbre_banks[tbank][tpatch]->time_uploaded;
01594 }
01595 }
01596
01597 if (lru_index == -1) return;
01598
01599 int lru_bank = mt32_timbre_used[lru_index][0];
01600 int lru_patch = mt32_timbre_used[lru_index][1];
01601
01602
01603 if (lru_bank != -1) mt32_timbre_banks[lru_bank][lru_patch]->index = -1;
01604
01605
01606 mt32_timbre_used[lru_index][0] = bank;
01607 mt32_timbre_used[lru_index][1] = patch;
01608
01609 mt32_timbre_banks[bank][patch]->index = lru_index;
01610 mt32_timbre_banks[bank][patch]->protect = false;
01611 mt32_timbre_banks[bank][patch]->time_uploaded = xmidi_clock;
01612
01613
01614 char name[11] = {0};
01615 std::memcpy (name,mt32_timbre_banks[bank][patch]->timbre,10);
01616
01617 pout << "LLMD: Uploading Custom Timbre `"<< name << "` from " << bank << ":" << patch << " into 2:" << lru_index << std::endl;
01618 sendMT32SystemMessage(timbre_base, timbre_mem_offset(lru_index), timbre_mem_size, mt32_timbre_banks[bank][patch]->timbre);
01619 }
01620
01621 void LowLevelMidiDriver::loadXMidiTimbreLibrary(IDataSource *ds)
01622 {
01623 uint32 i;
01624
01625
01626 for (i = 0; ds->getPos() < ds->getSize(); i++) {
01627
01628 ds->seek(i*6);
01629
01630 uint32 patch = (uint8) ds->read1();
01631 uint32 bank = (uint8) ds->read1();
01632
01633
01634 if (patch == 255 || bank == 255) {
01635
01636 break;
01637 }
01638
01639
01640 uint32 offset = ds->read4();
01641 ds->seek(offset);
01642
01643 uint16 size = ds->read2();
01644
01645 char name[11] = {0};
01646 ds->read(name,10);
01647
01648
01649 if (size != 0xF8) {
01650 pout << "LLMD: Patch " << i << " = " << bank << ":" << patch << " @ " << offset << ". Bad size:" << size << std::endl;
01651 }
01652
01653 ds->seek(offset+2);
01654
01655
01656 if (!mt32_timbre_banks[bank]) {
01657 mt32_timbre_banks[bank] = new MT32Timbre*[128];
01658 std::memset(mt32_timbre_banks[bank],0,sizeof(mt32_timbre_banks[bank][0])*128);
01659 }
01660 if (!mt32_timbre_banks[bank][patch]) mt32_timbre_banks[bank][patch] = new MT32Timbre;
01661
01662 if (!mt32_patch_banks[bank]) {
01663 mt32_patch_banks[bank] = new MT32Patch*[128];
01664 std::memset(mt32_patch_banks[bank],0,sizeof(mt32_patch_banks[bank][0])*128);
01665 }
01666 if (!mt32_patch_banks[bank][patch]) mt32_patch_banks[bank][patch] = new MT32Patch;
01667
01668
01669 *(mt32_patch_banks[bank][patch]) = mt32_patch_template;
01670 mt32_patch_banks[bank][patch]->timbre_bank = bank;
01671 mt32_patch_banks[bank][patch]->timbre_num = patch;
01672
01673
01674 mt32_timbre_banks[bank][patch]->time_uploaded = 0;
01675 mt32_timbre_banks[bank][patch]->index = -1;
01676 mt32_timbre_banks[bank][patch]->protect = false;
01677
01678
01679 ds->read(mt32_timbre_banks[bank][patch]->timbre,246);
01680 }
01681 }
01682
01683
01684