LowLevelMidiDriver.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2003-2005  The Pentagram Team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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 // These are only used by thread
00040 #define LLMD_MSG_THREAD_INIT                    -1      
00041 #define LLMD_MSG_THREAD_INIT_FAILED             -2
00042 #define LLMD_MSG_THREAD_EXIT                    -3
00043 
00044 // If the time to wait is less than this then we yield instead of waiting on the condition variable
00045 // This must be great than or equal to 2
00046 #define LLMD_MINIMUM_YIELD_THRESHOLD 6
00047 
00048 //#define DO_SMP_TEST
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 // MT32 SysEx
00058 //
00059 static const uint32 sysex_data_start = 7;               // Data starts at byte 7
00060 static const uint32 sysex_max_data_size = 256;
00061 
00062 
00063 //
00064 // Percussion
00065 //
00066 
00067 static const uint32 rhythm_base = 0x030110;     // Note, these are 7 bit!
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 // Memory offset based on index in the table
00074 static inline uint32 rhythm_mem_offset(uint32 index_num) { 
00075         return index_num * 4; 
00076 }
00077 
00078 // Memory offset based on note key num
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 // Timbre Memory Consts
00087 //
00088 static const uint32 timbre_temp_base = 0x040000;
00089 static const uint32 timbre_unk_base = 0x060000;
00090 static const uint32 timbre_base = 0x080000;     // Note, these are 7 bit!
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 // Patch Temp Consts
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 // Patch Memory Consts
00104 //
00105 static const uint32 patch_base = 0x050000;              // Note, these are 7 bit!
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,              // timbre_group
00111         0,              // timbre_num
00112         24,             // key_shift
00113         50,             // fine_tune
00114         24,             // bender_range
00115         0,              // assign_mode
00116         1,              // reverb_switch
00117         0               // dummy
00118 };
00119 
00120 //
00121 // All Dev Reset
00122 //
00123 static const uint32 all_dev_reset_base = 0x7f0000;
00124 
00125 // Display  Consts
00126 //
00127 static const uint32 display_base = 0x200000;    // Note, these are 7 bit!
00128 static const uint32 display_mem_size = 0x14;    // Display is 20 ASCII characters (32-127)
00129 
00130 // Convert 14 Bit base address to real
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         // Just kill it
00150         if (initialized) 
00151         {
00152                 perr << "Warning: Destructing LowLevelMidiDriver and destroyMidiDriver() wasn't called!" << std::endl;
00153                 //destroyMidiDriver();
00154                 if (thread) SDL_KillThread(thread);
00155         }
00156         thread = 0;
00157 }
00158 
00159 //
00160 // MidiDriver API
00161 //
00162 
00163 int LowLevelMidiDriver::initMidiDriver(uint32 samp_rate, bool is_stereo)
00164 {
00165         // Destroy first before re-initing
00166         if (initialized) destroyMidiDriver();
00167 
00168         string s;
00169 
00170         // Reset the current stream states
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         // Zero the memory
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         // Special handling for if we were uploading a timbre
00253         // Wait till the timbres have finished being sent
00254         while (uploading_timbres) {
00255                 waitTillNoComMessages();
00256                 
00257                 lockComMessage();
00258                 bool isplaying = playing[3];
00259                 unlockComMessage();
00260 
00261                 // If sequence is still playing timbres are still loading
00262                 // so we need to wait and try it again
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 // Communications
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 // Thread Stuff
00420 //
00421 
00422 int LowLevelMidiDriver::initThreadedSynth()
00423 {
00424         // Create the thread
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                 // Wait 1 MS before trying again
00462                 if (peekComMessageType() != 0)
00463                 {
00464                         yield ();
00465                         SDL_Delay(1);
00466                 }
00467                 else break;
00468                 
00469                 count++;
00470         }
00471 
00472         // We waited a while and it still didn't terminate
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                 // Get rid of all the messages
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         // Open the device
00500         int code = open();
00501 
00502         lockComMessage();
00503         {
00504                 // Pop all the messages
00505                 while(!messages.empty()) messages.pop();
00506 
00507                 // If we have an error code, push it to the message queue then return
00508                 // else we are ok to go
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         // Increase the thread priority, IF possible
00521         increaseThreadPriority();
00522 
00523         // Execute the play loop
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                                 //printf("Yielding\n");
00551                                 yield();
00552                                 //printf("Finished Yielding\n");
00553                         }
00554                         else
00555                         {
00556                                 //printf("Messages in queue, not Yielding\n");
00557                         }
00558                 }
00559                 else
00560                 {
00561                         lockComMessage();
00562                                 if (messages.empty())
00563                                 {
00564                                         //printf("Waiting %i ms\n", time_till_next-2);
00565                                         SDL_CondWaitTimeout(cond, mutex,time_till_next-2);
00566                                         //printf("Finished Waiting\n");
00567                                 }
00568                                 else
00569                                 {
00570                                         //printf("Messages in queue, not waiting\n");
00571                                 }
00572                         unlockComMessage();
00573                 }
00574         }
00575 
00576         // Display messages          0123456789ABCDEF0123
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         // Close the device
00583         close();
00584 
00585         lockComMessage();
00586         {
00587                 // Pop all messages
00588                 while(!messages.empty()) messages.pop();
00589                 initialized = false;
00590         }
00591         unlockComMessage();
00592 
00593         return 0;
00594 }
00595 
00596 //
00597 // Software Synth Stuff
00598 //
00599 
00600 int LowLevelMidiDriver::initSoftwareSynth()
00601 {
00602         // Open the device
00603         int ret = open();
00604 
00605         // Uh oh, failed
00606         if (ret) return 1;
00607 
00608         // Now setup all our crap
00609         total_seconds = 0;
00610         samples_this_second = 0;
00611 
00612         // This value doesn't 'really' matter all that much
00613         // Smaller values are more accurate (more iterations)
00614 
00615         if (sample_rate == 11025)
00616                 samples_per_iteration = 49;                                     // exactly 225 times a second
00617         if (sample_rate == 22050)
00618                 samples_per_iteration = 98;                                     // exactly 225 times a second
00619         else if (sample_rate == 44100)
00620                 samples_per_iteration = 147;                            // exactly 300 times a second
00621         else 
00622         {
00623                 samples_per_iteration = sample_rate/480;        // Approx 480 times a second
00624 
00625                 // Try to see if it can be 240 times/second
00626                 if (!(samples_per_iteration&1)) samples_per_iteration>>=1;
00627                 // Try to see if it can be 120 times/second
00628                 if (!(samples_per_iteration&1)) samples_per_iteration>>=1;
00629         }
00630 
00631         return 0;
00632 }
00633 
00634 void LowLevelMidiDriver::destroySoftwareSynth()
00635 {
00636         // Will cause the synth to set it self uninitialized
00637         ComMessage message(LLMD_MSG_THREAD_EXIT);
00638         sendComMessage(message);
00639 
00640         // Wait till all pending commands have been executed
00641         waitTillNoComMessages();
00642 
00643         close();
00644 }
00645 
00646 void LowLevelMidiDriver::produceSamples(sint16 *samples, uint32 bytes)
00647 {
00648         // Hey, we're not supposed to be here
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         // Now, do the note playing iterations
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                 // Increment the timing counter(s)
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                 // Calc Xmidi Clock
00671                 xmidi_clock = (total_seconds*6000) + (samples_this_second*6000)/sample_rate;
00672 
00673                 // We care about the return code now
00674                 if (playSequences()) {
00675 
00676                         lockComMessage();
00677                         {
00678                                 // Pop all messages
00679                                 while(!messages.empty()) messages.pop();
00680                                 initialized = false;
00681                         }
00682                         unlockComMessage();
00683 
00684                         break;
00685                 }
00686 
00687                 // Produce the samples
00688                 lowLevelProduceSamples(samples, samples_to_produce);
00689 
00690                 // Increment the counters
00691                 samples += samples_to_produce*stereo_mult;
00692         num_samples -= samples_to_produce;
00693         }
00694 }
00695 
00696 //
00697 // Shared Stuff
00698 //
00699 
00700 bool LowLevelMidiDriver::playSequences ()
00701 {
00702         int i;
00703 
00704         // Play all notes, from all sequences
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         // Did we get issued a music command?
00726         lockComMessage();
00727         {
00728                 while (!messages.empty()) 
00729                 {
00730                         ComMessage message = messages.front();
00731 
00732                         // Quick Exit if we get a 'queue' and get an exit command
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                                         // Kill the previous stream
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                                                 // Allocate some channels
00819                                                 /*
00820                                                 for (i = 0; i < 16; i++)
00821                                                         if (mask & (1<<i)) allocateChannel(message.sequence, i);
00822                                                 */
00823                                         }
00824 
00825                                 }
00826                                 break;
00827 
00828                                 // Attempt to load first 64 timbres into memory
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                                 // Uh we have no idea what it is
00857                         default:
00858                                 break;
00859                         }
00860 
00861                         // Pop it
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;  // Strip the channel number
00874 
00875         // Controller handling
00876         if ((message & 0x00F0) == (MIDI_STATUS_CONTROLLER << 4))
00877         {
00878                 // Screw around with volume
00879                 if ((message & 0xFF00) == (7 << 8))
00880                 {
00881                         int vol = (message >> 16) & 0xFF;
00882                         message &= 0x00FFFF;
00883                         // Global volume
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                         //pout << "Bank change in seq: " << sequence_id << " Channel: " << log_chan << " Bank: " << ((message>>16)&0xFF) << std::endl;
00900                         mt32_bank_sel[sequence_id][log_chan] = (message>>16)&0xFF;
00901                         // Note, we will pass this onto the midi driver, because they (i.e. FMOpl) might want them)
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                         //pout << "Program in seq: " << sequence_id << " Channel: " << log_chan << " Bank: " << bank << " Patch: " << patch << std::endl;
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         // Ok, get the physical channel number from the logical.
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         // Ignore Metadata
00932         if (status == 0xFF) return;
00933 
00934         // Ignore what would appear to be invalid SysEx data
00935         if (!msg || !length) return;
00936 
00937         // When uploading timbres, we will not send certain data types
00938         if (uploading_timbres && length > 7)
00939         {
00940                 // make sure it's for MT32
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         // Just send it
00989 
00990         int ticks = SDL_GetTicks();
00991         if (next_sysex > ticks) SDL_Delay(next_sysex-ticks); // Wait till we think the buffer is empty
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         // Unprotect the channel
01011         if (!protect) 
01012         {
01013                 chan_locks[chan] = -1;
01014                 chan_map[sequence_id][chan] = -1;
01015         }
01016         // Protect the channel (if required)
01017         else if (chan_locks[chan] != -2)
01018         {
01019                 // First check to see if the channel has been locked by something
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                         // It has, so what we want to do is unlock the channel, then 
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                         // Release the previous lock
01037                         lockChannel(relock_sid, relock_log, false);
01038                 }
01039 
01040                 // Now protect the channel
01041                 chan_locks[chan] = -2;
01042                 chan_map[sequence_id][chan] = -3;
01043 
01044                 // And attempt to get the other a new channel to lock
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         // When locking, we want to get the highest chan number with the lowest 
01055         // number of notes playing, that aren't already locked and don't have
01056         // protection
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                         // Protected or locked
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                 // Oh no, no channel to lock!
01088                 if (phys == -1) return -1;
01089 
01090                 // Now tell everyone that they lost their channel
01091                 for (s = 0; s < LLMD_NUM_SEQ; s++)
01092                 {
01093                         // Make sure they are mapping defualt
01094                         if (sequences[s] && chan_map[s][phys] == -1) 
01095                         {
01096                                 sequences[s]->loseChannel(phys);
01097                                 chan_map[s][phys] = -2; // Can't use it
01098                         }
01099                 }
01100 
01101                 // We are losing our old logical channel too
01102                 if (phys != chan) sequences[sequence_id]->loseChannel(chan);
01103 
01104                 // Ok, got our channel
01105                 chan_map[sequence_id][chan] = phys;
01106                 chan_locks[phys] = sequence_id;
01107                 sequences[sequence_id]->gainChannel(chan);
01108         }
01109         // Unlock the channel
01110         else
01111         {
01112                 int phys = chan_map[sequence_id][chan];
01113 
01114                 // Not locked
01115                 if (phys < 0) return -1;
01116 
01117                 // First, we'll lose our logical channel
01118                 if (sequences[sequence_id]) 
01119                         sequences[sequence_id]->loseChannel(chan);
01120 
01121                 // Now unlock it
01122                 chan_map[sequence_id][chan] = -1;
01123                 chan_locks[phys] = -1;
01124 
01125                 // Gain our logical channel back
01126                 if (phys != chan && sequences[sequence_id]) 
01127                         sequences[sequence_id]->gainChannel(chan);
01128 
01129                 // Now let everyone gain their channel that we stole
01130                 for (int s = 0; s < LLMD_NUM_SEQ; s++)
01131                 {
01132                         // Make sure they are mapping defualt
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         // For each channel
01147         for (int c = 0; c < 16; c++)
01148         {
01149                 int phys = chan_map[sequence_id][c];
01150 
01151                 // Doesn't need anything done to it
01152                 if (phys != -3) continue;
01153 
01154                 // We are protecting
01155                 if (phys == -3)
01156                 {
01157                         protectChannel(sequence_id, c, false);
01158                 }
01159                 // We are locking
01160                 else
01161                 {
01162                         lockChannel(sequence_id, c, false);
01163                 }
01164         }
01165         return 0;
01166 }
01167 
01168 
01169 // Load Timbre Library
01170 void LowLevelMidiDriver::loadTimbreLibrary(IDataSource *ds, TimbreLibraryType type)
01171 {
01172         // Ensure all sequences are stopped
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         // Wait till all pending commands have been executed
01181         waitTillNoComMessages();
01182 
01183         // Lock!
01184         lockComMessage();
01185 
01186         // Kill all existing timbres and stuff
01187 
01188         // Free memory
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                 // Delete the bank
01195                 delete [] mt32_patch_banks[i];
01196                 delete [] mt32_timbre_banks[i];
01197 
01198                 delete mt32_rhythm_bank[i];
01199         }
01200 
01201         // Zero the memory
01202         std::memset(mt32_patch_banks,0,sizeof(mt32_patch_banks[0])*128);
01203 
01204         // Zero the memory
01205         std::memset(mt32_timbre_banks,0,sizeof(mt32_timbre_banks[0])*128);
01206 
01207         // Mask it out 
01208         std::memset(mt32_timbre_used,-1,sizeof(mt32_timbre_used[0])*64);
01209 
01210         // Zero the memory
01211         std::memset(mt32_bank_sel,0,sizeof(mt32_bank_sel[0])*LLMD_NUM_SEQ);
01212 
01213         // Zero the memory
01214         std::memset(mt32_patch_bank_sel,0,sizeof(mt32_patch_bank_sel[0])*128);
01215 
01216         // Zero
01217         std::memset(mt32_rhythm_bank,0,sizeof(mt32_rhythm_bank[0])*128);
01218 
01219         // Setup Default Patch library
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                 // Setup Patch Defaults 
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); // a bit of a hack, it just sets up a few sysex messages
01243         }
01244 
01245         // Finally unlock
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         // Play the SysEx data
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         // If we want to precache
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                                 // Allocate memory
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                                 // Setup Timbre defaults
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                                 // Read the timbre into the buffer
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                                 // Set the current patch bank to -1
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                                 // Set the current patch bank to -1
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 // If data is NULL, then it is assumed that sysex_buffer already contains the data
01404 // address_base is 7-bit, while address_offset is 8 bit!
01405 void LowLevelMidiDriver::sendMT32SystemMessage(uint32 address_base, uint16 address_offset, uint32 len, const void *data)
01406 {
01407         unsigned char sysex_buffer[512];
01408 
01409         // MT32 Sysex Header
01410         sysex_buffer[0] = 0x41;         // Roland SysEx ID
01411         sysex_buffer[1] = 0x10;         // Device ID (assume 0x10, Device 17)
01412         sysex_buffer[2] = 0x16;         // MT-32 Model ID
01413         sysex_buffer[3] = 0x12;         // DTI Command ID (set data)
01414 
01415         // 7-bit address
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         // Only copy if required
01422         if (data) std::memcpy (sysex_buffer+sysex_data_start, data, len);
01423 
01424         // Calc checksum
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         // Set checksum
01433         sysex_buffer[sysex_data_start+len] = checksum;
01434 
01435         // Terminator
01436         sysex_buffer[sysex_data_start+len+1] = 0xF7;
01437 
01438         // Just send it
01439 
01440         int ticks = SDL_GetTicks();
01441         if (next_sysex > ticks) SDL_Delay(next_sysex-ticks);    // Wait till we think the buffer is empty
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         // Invalid bank
01449         if (bank < -1 || bank > 127) {
01450                 perr << "LLMD: Invalid bank in setPatchBank" << std::endl;
01451                 return;
01452         }
01453         // Invalid Patch
01454         else if (patch < 0 || patch > 127) {
01455                 perr << "LLMD: Invalid patch in setPatchBank" << std::endl;
01456                 return;
01457         }
01458         // Bank doesn't exist
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         // Patch hasn't been loaded
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         // Custom bank?
01481         if (p.timbre_bank > 0) {
01482                 // If no timbre loaded, we do nothing!
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                 // Upload timbre if required
01489                 if(mt32_timbre_banks[p.timbre_bank][p.timbre_num]->index == -1) {
01490                         //pout << "LLMD: Need to upload timbre" << std::endl;
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                 // Upload failed so do nothing
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) { // Rhythm
01504                 p.timbre_bank = 3;
01505         } else if (patch <= 0x3f) {             // Bank 0
01506                 p.timbre_bank = 0;
01507         } else {                                                // Bank 1
01508                 p.timbre_bank = 1;
01509                 p.timbre_num = p.timbre_num&0x3f;
01510         }
01511 
01512         // Set the correct bank 
01513         mt32_patch_bank_sel[patch] = bank;
01514 
01515         // Upload the patch
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                 // If no timbre loaded, we do nothing!
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                 // Upload timbre if required
01535                 if(mt32_timbre_banks[2][timbre]->index == -1) {
01536                         //pout << "LLMD: Need to upload timbre" << std::endl;
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         // If no timbre loaded, we do nothing!
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         // Already uploaded
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                 // Timbre is unused, so we will use it
01573                 if (tbank == -1) {
01574                         lru_index = i;
01575                         break;
01576                 }
01577 
01578                 // Just make sure it exists
01579                 if (!mt32_timbre_banks[tbank] || !mt32_timbre_banks[tbank][tpatch])
01580                         continue;
01581 
01582                 // Protected so ignore
01583                 if (mt32_timbre_banks[tbank][tpatch]->protect) 
01584                         continue;
01585 
01586                 // Inuse so ignore
01587                 if (mt32_patch_bank_sel[tpatch] == bank) 
01588                         continue;
01589 
01590                 // Is it LRU??
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         // Unsetup the old timbre
01603         if (lru_bank != -1) mt32_timbre_banks[lru_bank][lru_patch]->index = -1;
01604 
01605         // Setup the New one
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         // Now send the SysEx message
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         // Read all the timbres
01626         for (i = 0; ds->getPos() < ds->getSize(); i++) {
01627                 // Seek to the entry
01628                 ds->seek(i*6);
01629 
01630                 uint32 patch = (uint8) ds->read1();
01631                 uint32 bank = (uint8) ds->read1();
01632 
01633                 // If we read both == 255 then we've read all of them
01634                 if (patch == 255 || bank == 255) {
01635                         //POUT ("Finished " << patch << ": ");
01636                         break;
01637                 }
01638 
01639                 // Get offset and seek to it
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                 //pout << name << ": " << i << " = " << bank << ":" << patch << " @ " << offset << std::endl;
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                 // Allocate memory
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                 // Setup Patch Defaults 
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                 // Setup Timbre defaults
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                 // Read the timbre into the buffer
01679                 ds->read(mt32_timbre_banks[bank][patch]->timbre,246);
01680         }
01681 }
01682 
01683 
01684 // Protection

Generated on Fri Jul 27 22:27:23 2007 for pentagram by  doxygen 1.4.7