00001
00026
00027
00028
00029
00030
00031 #include "DevMidi.h"
00032 #include "Execute.h"
00033 #include "GrafKern.h"
00034 #include "MidiKern.h"
00035
00036
00037
00038
00039
00040
00041 #define GET_INDEX(taste,tonsystem) \
00042 ((int)( (taste)-( (tonsystem)->anker % (tonsystem)->breite )) \
00043 % (tonsystem)->breite )
00044
00045
00046
00047 #define GET_ABSTAND(taste,tonsystem) \
00048 ( (int)((taste)-( (tonsystem)->anker % (tonsystem)->breite )) \
00049 / (tonsystem)->breite -((int) (tonsystem)->anker \
00050 / (tonsystem)->breite ))
00051
00052
00053 #define GET_FREQ(taste,tonsystem) \
00054 ( ( (tonsystem)->ton[GET_INDEX(taste,(tonsystem))]==0) ? \
00055 (long) 0 : \
00056 (long)( (tonsystem)->periode * \
00057 GET_ABSTAND(taste,(tonsystem)) + \
00058 (tonsystem)->ton[GET_INDEX(taste,(tonsystem))]))
00059
00060 #define ZWZ 1.059463094
00061
00062
00063
00064 #ifdef RTMIDI
00065 #include "RtMidi.h"
00066
00067 extern RtMidiOut *rtmidiout;
00068
00069 extern RtMidiIn *rtmidiin;
00070
00071 #endif
00072
00073
00074 #ifdef RTMIDI
00075 #define MIDI_OUT3(code1, code2, code3) \
00076 { std::vector<unsigned char> message; \
00077 message.push_back(code1); \
00078 message.push_back(code2); \
00079 message.push_back(code3); \
00080 DEBUGLOG2(midiio,_T("MIDI OUT %x %x %x"), \
00081 code1,code2,code3); \
00082 hMidiOut->sendMessage(&message); }
00083
00084 #define MIDI_OUT2(code1, code2) \
00085 { std::vector<unsigned char> message; \
00086 message.push_back(code1); \
00087 message.push_back(code2); \
00088 DEBUGLOG2(midiio,_T("MIDI OUT %x %x"), \
00089 code1,code2); \
00090 hMidiOut->sendMessage(&message); }
00091 #else
00092 #define MIDI_OUT3(code1, code2, code3) \
00093 midiOutShortMsg(hMidiOut, \
00094 ((DWORD) (code3) << 16) + \
00095 ((DWORD) (code2) << 8) + \
00096 ((DWORD) (code1)))
00097
00098 #define MIDI_OUT2(code1, code2) \
00099 midiOutShortMsg(hMidiOut, \
00100 ((DWORD) (code2) << 8) + \
00101 ((DWORD) (code1)))
00102 #endif
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 #define MIDI_PITCH(i,freq) \
00124 { unsigned int pb = ( ((freq & 0xffffff) / bending_range) >> 11) ; \
00125 DEBUGLOG2(midiio,_T("MIDI_PITCH(%x/%d,%x/%d) = %x/%d (%x/%d, %x/%d, %x/%d)"), \
00126 i,i,freq,freq,pb,pb,0xE0 + i,0xE0 + i, pb & 0x7f, pb & 0x7f, (0x40 + (pb >> 7) ) & 0x7f, \
00127 (0x40 + (pb >> 7) ) & 0x7f ); \
00128 MIDI_OUT3 (0xE0 + i, pb & 0x7f, (0x40 + (pb >> 7) ) & 0x7f) }
00129
00130
00131
00132
00133
00134 #define MIDI_SOUND(i, sound) \
00135 if ( sound != -1 ) MIDI_OUT2(0xC0+i, sound)
00136
00137
00138 #define MAKE_ID(route, box, taste, channel) \
00139 ((((DWORD)channel) << 24) + (((DWORD)route->GetId()&0xff) << 16) + ((DWORD)box << 8) + taste)
00140
00141
00143
00145 void OutMidiPort::Save (tree_storage & config)
00146 {
00147 config.Write(_T("Device Id"),DevId);
00148 config.Write(_T("Device Name"),Name);
00149 config.Write(_T("Bending Range"),bending_range);
00150 }
00151
00153
00158 void OutMidiPort::Save (tree_storage & config, const Route * route)
00159 {
00160 wxASSERT(route);
00161 config.Write(_T("Avoid Drum Channel"), route->ONoDrum);
00162 config.Write(_T("Channel Range From"), route->OFrom);
00163 config.Write(_T("Channel Range To"), route->OTo);
00164 }
00165
00166
00168
00170 void OutMidiPort::Load (tree_storage & config)
00171 {
00172 DevId = config.Read(_T("Device Id"),0);
00173 Name = config.Read(_T("Device Name"), rtmidiout->getPortCount()?
00174 muT(rtmidiout->getPortName(0).c_str()):wxString(_("Unknown")));
00175 bending_range = config.Read(_T("Bending Range"),2);
00176 }
00177
00179
00184 void OutMidiPort::Load (tree_storage & config, Route * route)
00185 {
00186 wxASSERT(route);
00187 route->ONoDrum = config.Read(_T("Avoid Drum Channel"), true);
00188 int oldfrom, oldto;
00189 oldfrom = route->OFrom = config.Read(_T("Channel Range From"), GetMinChannel());
00190 oldto = route->OTo = config.Read(_T("Channel Range To"), GetMaxChannel());
00191 bool correct = true;
00192 if (route->OFrom < GetMinChannel()) {
00193 correct = false;
00194 route->OFrom = GetMinChannel();
00195 }
00196 if (route->OTo > GetMaxChannel()) {
00197 correct = false;
00198 route->OTo = GetMaxChannel();
00199 }
00200 if (!correct)
00201 wxMessageBox(wxString::Format(_("The Channel range %d--%d of the MIDI output device %s must be inside %d--%d. The current route had to be corrected."),
00202 oldfrom,oldto,GetName().c_str(),GetMinChannel(),GetMaxChannel()),
00203 _("Warning loading route"),wxICON_EXCLAMATION);
00204 }
00205
00206
00207 bool OutMidiPort::Open()
00208 {
00209 DEBUGLOG (other, _T(""));
00210 int i;
00211
00212 for (i = 0; i < 16; i++) {
00213 Cd[i].Reset();
00214 ton_auf_kanal[i].taste = 0;
00215 ton_auf_kanal[i].id = 0;
00216 }
00217
00218 nKeyOn = 0;
00219
00220 for (i = 0; i < 16; i++)
00221 KeyDir[i] = (char)i;
00222
00223 #ifdef RTMIDI
00224
00225 try {
00226 hMidiOut = new RtMidiOut();
00227 } catch (RtError &error) {
00228 LAUFZEIT_ERROR0(_("Can not open ouput Midi devices."));
00229 return false;
00230 }
00231
00232 try {
00233 hMidiOut->openPort(DevId);
00234 } catch (RtError &error) {
00235 LAUFZEIT_ERROR2(_("Can not open output Midi device nr. %d (%s)"), DevId, (GetName().c_str()));
00236 return false;
00237 }
00238
00239 #else
00240 midiOutOpen(&hMidiOut, DevId, NULL, NULL, NULL);
00241
00242 #endif
00243 for (i = 0; i < 16; i++) {
00244 MIDI_OUT3(0xE0+i, 0x00, 0x40);
00245 MIDI_OUT3(0xB0+i, 122, 0);
00246 MIDI_OUT3(0xB0+i, 125, 0);
00247 MIDI_OUT3(0xB0+i, 127, 0);
00248 }
00249
00250 return true;
00251 }
00252
00253 void OutMidiPort::Close()
00254
00255 {
00256 DEBUGLOG (other, _T(""));
00257
00258
00259 for (int i = 0; i < 16; i++)
00260 if ( KeyDir[i] >= 16 )
00261 MIDI_OUT3(0x80+i, ton_auf_kanal[i].key, 64);
00262
00263
00264
00265
00266 #ifdef RTMIDI
00267 hMidiOut->closePort();
00268
00269 delete hMidiOut;
00270
00271 #else
00272 midiOutClose(hMidiOut);
00273
00274 #endif
00275 }
00276
00277 void OutMidiPort::NoteOn(int box, int taste, int velo, Route *r, int channel, ChannelData *cd)
00278 {
00279 DEBUGLOG (other, _T("box %d, key %d, velo %d, channel %d"),
00280 box, taste, velo, channel);
00281 int free = 16, freeSus = r->OTo, freeV = 64, freeSusV = 64, s;
00282 DWORD p;
00283 long freq;
00284
00285 if ( box == -2 ) {
00286 freq = ((long)taste) << 24;
00287 box = 255;
00288 } else
00289 freq = GET_FREQ (taste, mut_box[box].tonesystem);
00290
00291
00292 if ( !freq )
00293 return;
00294
00295 for ( int j = r->OFrom; j <= r->OTo; j++ )
00296 if ( j != DRUMCHANNEL || !r->ONoDrum ) {
00297 if ( Cd[j].Sustain ) {
00298 if ( KeyDir[j] < freeSusV ) {
00299 freeSus = j;
00300 freeSusV = KeyDir[j];
00301 }
00302 } else {
00303 if ( KeyDir[j] < freeV ) {
00304 free = j;
00305 freeV = KeyDir[j];
00306 }
00307 }
00308 }
00309 if ( freeV >= 16 ) {
00310 free = freeSus;
00311 freeV = freeSusV;
00312 }
00313
00314 if ( freeV >= 16 )
00315 {
00316
00317 int AM = 0;
00318 int j;
00319
00320 for (j = r->OFrom; j <= r->OTo; j++)
00321 if ( j != DRUMCHANNEL || !r->ONoDrum )
00322 AM += ton_auf_kanal[j].taste;
00323
00324 AM /= r->OTo + 1 - r->OFrom;
00325
00326 for ( j = r->OFrom; j <= r->OTo; j++ )
00327 if ( j != DRUMCHANNEL || !r->ONoDrum )
00328 if ( abs(AM - ton_auf_kanal[j].taste) < abs(AM - ton_auf_kanal[free].taste) )
00329 free = j;
00330
00331
00332 MIDI_OUT3(0x80+free, ton_auf_kanal[free].key, 64);
00333
00334
00335 if ( Cd[free].Sustain )
00336 MIDI_OUT3(0xB0+free, 64, 0);
00337
00338
00339 BYTE oldKeyDir = KeyDir[free];
00340
00341 for (int k = 0; k < 16; k++)
00342 if ( KeyDir[k] > oldKeyDir ) KeyDir[k]--;
00343
00344 KeyDir[free] = (char)(15+nKeyOn);
00345 } else {
00346 nKeyOn++;
00347 KeyDir[free] = (char)(15 + nKeyOn);
00348 }
00349
00350
00351
00352
00353 if ( Cd[free].Sustain ) {
00354 MIDI_OUT3(0xB0+free, 64, 0);
00355 Cd[free].Sustain = 0;
00356 }
00357
00358
00359 if ( (s = cd->Sound) != Cd[free].Sound ) {
00360 MIDI_SOUND(free, s);
00361 Cd[free].Sound = s;
00362 }
00363
00364
00365 if ( (s = cd->BankSelectMSB) != Cd[free].BankSelectMSB && s != -1 ) {
00366 MIDI_OUT3(0xB0+free, 0, (BYTE) s);
00367 Cd[free].BankSelectMSB = s;
00368 }
00369
00370 if ( (s = cd->BankSelectLSB) != Cd[free].BankSelectLSB && s != -1 ) {
00371 MIDI_OUT3(0xB0+free, 32, (BYTE) s);
00372 Cd[free].BankSelectLSB = s;
00373 }
00374
00375
00376 if ( (long)(p = (freq & 0xFFFFFF)) != Cd[free].Pitch ) {
00377 MIDI_PITCH(free, freq);
00378 Cd[free].Pitch = p;
00379 }
00380
00381 ton_auf_kanal[free].key = (freq >> 24) & 0x7f;
00382
00383 ton_auf_kanal[free].taste = taste;
00384 ton_auf_kanal[free].id = MAKE_ID(r, box, taste, channel);
00385 MIDI_OUT3(0x90+free, ton_auf_kanal[free].key, velo);
00386
00387 if ( cd->Sustain ) {
00388 MIDI_OUT3(0xB0+free, 64, cd->Sustain);
00389 Cd[free].Sustain = cd->Sustain;
00390 }
00391 };
00392
00393 void OutMidiPort::NoteOff(int box, int taste, int velo, Route *r, int channel)
00394 {
00395 DEBUGLOG (midiio, _T("box %d, key %d, velo %d, channel %d"),
00396 box, taste, velo, channel);
00397
00398 if ( box == -2 )
00399 box = MAX_BOX+1;
00400
00401 DWORD id = MAKE_ID(r, box, taste, channel);
00402
00403 if ( !velo )
00404 velo = 64;
00405
00406 for (int i = r->OFrom; i <= r->OTo; i++)
00407 if ( i != DRUMCHANNEL || !r->ONoDrum )
00408 if ( KeyDir[i] >= 16 && ton_auf_kanal[i].id == id ) {
00409 ton_auf_kanal[i].taste=0;
00410
00411 MIDI_OUT3(0x80+i, ton_auf_kanal[i].key, velo);
00412
00413 int oldKeyDir = KeyDir[i];
00414
00415 for (int k = 0; k < 16; k++)
00416 if ( KeyDir[k] > oldKeyDir || KeyDir[k] < 16) KeyDir[k]--;
00417
00418 nKeyOn--;
00419
00420 KeyDir[i] = 15;
00421 }
00422 }
00423
00424 inline long LongAbs(long x)
00425 {
00426 return (x < 0)? -x : x;
00427 }
00428
00429 void OutMidiPort::NotesCorrect(int box)
00430 {
00431 DEBUGLOG (midiio, _T(""));
00432
00433 for (int i = 0; i < 16; i++)
00434 if ( (KeyDir[i] >= 16 && ton_auf_kanal[i].id) || Cd[i].Sustain ) {
00435 int Box = (ton_auf_kanal[i].id >> 8) & 0xFF;
00436
00437 if ( Box != box )
00438 break;
00439
00440 DEBUGLOG(midiio,_T("old(hex/dec): channel = %01x/%d, Taste = %02x/%d, key = %02x/%d, pitch = %06x/%d"),
00441 i,i,ton_auf_kanal[i].taste,ton_auf_kanal[i].taste,
00442 ton_auf_kanal[i].key,ton_auf_kanal[i].key,Cd[i].Pitch,Cd[i].Pitch);
00443
00444 long freq = GET_FREQ(ton_auf_kanal[i].taste, mut_box[Box].tonesystem);
00445
00446
00447
00448 if ( ton_auf_kanal[i].key == ((freq >> 24) & 0x7f) &&
00449 Cd[i].Pitch == ((long)freq & 0xFFFFFF) )
00450 continue;
00451
00452
00453 long Delta = freq - ((long)ton_auf_kanal[i].key << 24);
00454
00455 bool SwitchTone = (LongAbs(Delta) >= ((long)bending_range << 24));
00456
00457
00458 if ( SwitchTone ) {
00459 if ( Cd[i].Sustain ) {
00460 MIDI_OUT3(0xB0+i, 64, 0);
00461 Cd[i].Sustain = 0;
00462
00463 if ( KeyDir[i] < 16 )
00464 continue;
00465 }
00466
00467 MIDI_OUT3(0x80+i, ton_auf_kanal[i].key, 0x7F);
00468 ton_auf_kanal[i].key = (freq >> 24) & 0x7F;
00469 Delta = freq - ((long)ton_auf_kanal[i].key << 24);
00470 } else if ( Delta == Cd[i].Pitch )
00471 continue;
00472
00473
00474 Cd[i].Pitch = Delta;
00475
00476 Delta /= bending_range;
00477 Delta = Delta >> 11;
00478 Delta += 0x40 << 7;
00479 DEBUGLOG(midiio,_T("new freq = %08x/%d, Pitch= %06x/%d, Delta = %06x/%d, i=%d"),
00480 freq, freq, Cd[i].Pitch, Cd[i].Pitch, Delta, Delta, i);
00481
00482 MIDI_OUT3(0xE0+i, Delta & 0x7f, (Delta >> 7) & 0x7f );
00483
00484
00485 if ( SwitchTone )
00486 MIDI_OUT3(0x90+i, ton_auf_kanal[i].key, 64);
00487 }
00488 }
00489
00490 void OutMidiPort::Sustain(char on, int channel)
00491 {
00492 DEBUGLOG (other, _T(""));
00493 DWORD chan = channel;
00494
00495 for (int i = 0; i < 16; i++)
00496 if ( ton_auf_kanal[i].id && (ton_auf_kanal[i].id >> 24) == chan ) {
00497 MIDI_OUT3(0xB0+i, 64, on);
00498 Cd[i].Sustain = on;
00499 }
00500 }
00501
00502 int OutMidiPort::GetChannel(int taste)
00503 {
00504 DEBUGLOG (other, _T(""));
00505
00506 for (int i = 0; i < 16; i++)
00507 if ( ton_auf_kanal[i].id && (ton_auf_kanal[i].taste == taste) )
00508 return i;
00509
00510 return -1;
00511 }
00512
00513
00514
00515 #ifdef RTMIDI
00516 void OutMidiPort::MidiOut(DWORD data, char n)
00517 {
00518 std::vector<unsigned char> message;
00519
00520 while ( n-- ) {
00521 DEBUGLOG (other, _T("sending byte %x"), data & 0xff);
00522 message.push_back(data & 0xFF);
00523 data >>= 8;
00524 }
00525
00526 hMidiOut->sendMessage(&message);
00527 }
00528
00529 #else
00530 void OutMidiPort::MidiOut(DWORD data, char n)
00531 {
00532 DEBUGLOG (other, _T("without RtMidi"));
00533 midiOutShortMsg(hMidiOut, data);
00534 }
00535
00536 #endif
00537
00538 void OutMidiPort::Quite(Route *r)
00539 {
00540 DEBUGLOG (other, _T(""));
00541
00542 for (int i = 0; i < 16; i++)
00543 if ( (char)((ton_auf_kanal[i].id >> 16) & 0x0FF) == r->GetId() )
00544 NoteOff(r->Box, ton_auf_kanal[i].id % 256, 64, r, ton_auf_kanal[i].id >> 24);
00545 }
00546
00547 void OutMidiPort::Panic()
00548 {
00549 DEBUGLOG (other, _T(""));
00550
00551 for (int i = 0; i < 16; i++) {
00552 MIDI_OUT3(176+i, 123, 0);
00553 MIDI_OUT3(0xB0+i, 7, 127);
00554
00555 MIDI_OUT2(0xC0+i, 0);
00556
00557 ton_auf_kanal[i].taste=0;
00558 ton_auf_kanal[i].id=0;
00559 Cd[i].Sound = 0;
00560 Cd[i].Sustain = 0;
00561 KeyDir[i] = i;
00562 }
00563
00564 nKeyOn = 0;
00565 }
00566
00567 void OutMidiPort::ReadData(wxConfigBase * config)
00568 {
00569 bending_range = config->Read(_("Bending_Range"),
00570 (long)bending_range);
00571 }
00572
00573 void OutMidiPort::WriteData(wxConfigBase * config)
00574 {
00575 config->Write(_("Bending_Range"), (long)bending_range);
00576 }
00577
00578
00579
00580
00581 #ifdef RTMIDI
00582
00583 void mycallback( double deltatime, std::vector< unsigned char > *message, void *userData )
00584 {
00585 DWORD data = 0;
00586
00587 for (int i = message->size()-1; i >= 0; i--)
00588 data = ((data << 8) | ((unsigned char)(*message)[i]));
00589
00590 ((InMidiPort*)userData)->Proceed(data);
00591 }
00592
00593 #else
00594
00595 void CALLBACK _export MidiInPortFunc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
00596 {
00597
00598
00599 if ( wMsg != MIM_DATA || dwParam1 % 256 > 240 ) return;
00600
00601
00602 ((InMidiPort*)dwInstance)->Proceed(dwParam1);
00603 }
00604
00605 #endif
00606
00607
00609
00611 void InMidiPort::Save (tree_storage & config)
00612 {
00613 config.Write(_T("Device Id"), DevId);
00614 config.Write(_T("Device Name"), Name);
00615 }
00616
00618
00623 void InMidiPort::Save (tree_storage & config, const Route * route)
00624 {
00625 config.Write(_T("Filter Type"), route->Type);
00626 switch(route->Type) {
00627 case RTchannel:
00628 config.Write(_T("Channel From"), route->IFrom);
00629 config.Write(_T("Channel To"), route->ITo);
00630 break;
00631 case RTstaff:
00632 config.Write(_T("Key From"), route->IFrom);
00633 config.Write(_T("Key To"), route->ITo);
00634 break;
00635 case RTelse:
00636 case RTall:
00637 break;
00638 }
00639 }
00640
00641
00643
00645 void InMidiPort::Load (tree_storage & config)
00646 {
00647 DevId = config.Read(_T("Device Id"), 0);
00648 Name = config.Read(_T("Device Name"),
00649 rtmidiout->getPortCount()?
00650 muT(rtmidiout->getPortName(0).c_str()):wxString(_("Unknown")));
00651 }
00652
00654
00659 void InMidiPort::Load (tree_storage & config, Route * route)
00660 {
00661 route->Type = (RouteType) config.Read(_T("Filter Type"), (int) RTchannel);
00662 switch(route->Type) {
00663 case RTchannel:
00664 {
00665 int oldfrom, oldto;
00666 oldfrom = route->IFrom = config.Read(_T("Channel From"), GetMinChannel());
00667 oldto = route->ITo = config.Read(_T("Channel To"), GetMaxChannel());
00668 bool correct = true;
00669 if (route->IFrom < GetMinChannel()) {
00670 correct = false;
00671 route->IFrom = GetMinChannel();
00672 }
00673 if (route->ITo > GetMaxChannel()) {
00674 correct = false;
00675 route->ITo = GetMaxChannel();
00676 }
00677 if (!correct)
00678 wxMessageBox(wxString::Format(_("The Channel range %d--%d of the MIDI input device %s must be inside %d--%d. The current route had to be corrected."),
00679 oldfrom,oldto,GetName().c_str(),GetMinChannel(),GetMaxChannel()),
00680 _("Warning loading route"),wxICON_EXCLAMATION);
00681 break;
00682 }
00683 case RTstaff:
00684 {
00685 int oldfrom, oldto;
00686 route->IFrom = oldfrom = config.Read(_T("Key From"), GetMinKey());
00687 route->ITo = oldto = config.Read(_T("Key To"), GetMaxKey());
00688 bool correct = true;
00689 if (route->IFrom < GetMinKey()) {
00690 correct = false;
00691 route->IFrom = GetMinKey();
00692 }
00693 if (route->ITo > GetMaxKey()) {
00694 correct = false;
00695 route->ITo = GetMaxKey();
00696 }
00697 if (!correct)
00698 wxMessageBox(wxString::Format(_("The Channel range %d--%d of the MIDI input device must be inside %d--%d. The current route had to be corrected."),
00699 oldfrom,oldto, GetName().c_str(),GetMinKey(), GetMaxKey()),
00700 _("Warning loading route"),wxICON_EXCLAMATION);
00701 break;
00702 }
00703 case RTelse:
00704 case RTall:
00705 break;
00706 }
00707 }
00708
00709 bool InMidiPort::Open()
00710 {
00711 for (int i = 0; i < 16; i++)
00712 Cd[i].Reset();
00713
00714 #ifdef RTMIDI
00715 try {
00716 hMidiIn = new RtMidiIn();
00717 } catch (RtError &error) {
00718 LAUFZEIT_ERROR0(_("Can not open Midi input devices."));
00719 return false;
00720 }
00721
00722 try {
00723 hMidiIn->openPort(DevId);
00724 } catch (RtError &error) {
00725 LAUFZEIT_ERROR2(_("Can not open Midi input device no. %d (%s)."), DevId, (GetName().c_str()));
00726 return false;
00727 }
00728
00729 hMidiIn->setCallback(mycallback, this);
00730
00731 #else
00732 midiInOpen(&hMidiIn, DevId, (DWORD)MidiInPortFunc, (DWORD)this, CALLBACK_FUNCTION);
00733 midiInStart(hMidiIn);
00734 #endif
00735 return true;
00736 }
00737
00738 void InMidiPort::Close()
00739 {
00740 #ifdef RTMIDI
00741 hMidiIn->closePort();
00742 delete hMidiIn;
00743 #else
00744 midiInStop(hMidiIn);
00745 midiInReset(hMidiIn);
00746 midiInClose(hMidiIn);
00747 #endif
00748 Quite();
00749 };
00750
00751
00752
00753
00754
00755 void InMidiPort::ProceedRoute(DWORD midiCode, Route *route)
00756 {
00757 #ifdef DEBUG
00758 if (midiCode != 0xf8)
00759 DEBUGLOG(midiio,_T("midiCode = %x"), midiCode);
00760 #endif
00761 int Box = route->Box;
00762 BYTE MidiChannel = midiCode & 0x0F;
00763 BYTE MidiStatus = midiCode & 0xF0;
00764
00765 switch ( MidiStatus ) {
00766
00767 case 0x90:
00768 if ( (midiCode & 0x7f0000) > 0 ) {
00769 if ( route->Active )
00770 AddKey(Box, (midiCode >> 8) & 0xff, route->GetId());
00771
00772 if ( route->GetOutDevice() )
00773 route->GetOutDevice()->NoteOn(Box,
00774 (midiCode >> 8) & 0xff,
00775 (midiCode >> 16) & 0xff,
00776 route, MidiChannel, &Cd[MidiChannel]);
00777
00778 break;
00779 }
00780
00781 case 0x80:
00782 if ( route->Active )
00783 DeleteKey(Box,(midiCode >> 8) & 0xff, route->GetId());
00784
00785 if ( route->GetOutDevice() )
00786 route->GetOutDevice()->NoteOff(Box, (midiCode >> 8) & 0xff, (midiCode >> 16) & 0xff, route, MidiChannel);
00787
00788 break;
00789
00790 case 0xC0:
00791 Cd[MidiChannel].Sound = (midiCode >> 8) & 0xff;
00792
00793 break;
00794
00795 case 0xB0:
00796 { int control = (midiCode >> 8) & 0xff;
00797 int data = (midiCode >> 16) & 0xff;
00798 if ( control == 64 ) {
00799 Cd[MidiChannel].Sustain = data;
00800
00801 if ( route->GetOutDevice() )
00802 route->GetOutDevice()->Sustain(Cd[MidiChannel].Sustain, MidiChannel);
00803
00804 break;
00805 } else if ( control == 0 )
00806 {
00807 Cd[MidiChannel].BankSelectMSB = data;
00808 break;
00809 } else if ( control == 32 )
00810 {
00811 Cd[MidiChannel].BankSelectLSB =data;
00812 break;
00813 }
00814 }
00815 case 0xA0:
00816
00817 case 0xD0:
00818
00819 break;
00820 }
00821
00822
00823 int lMidiCode[8] = {
00824 3, 3, 3, 3, 2, 2, 3, 1
00825 };
00826
00827 if ( Box >= 0 && route->Active )
00828 for (int i = 0; i < lMidiCode[MidiStatus >> 5]; i++) {
00829 MidiAnalysis(Box,midiCode & 0xff);
00830 midiCode >>= 8;
00831 }
00832 }
00833
00834
00835 void InMidiPort::Proceed(DWORD midiCode)
00836 {
00837 char DidOut = 0;
00838
00839 for (Route *R = GetRoutes(); R; R = R->GetNext())
00840 switch ( R->Type ) {
00841
00842 case RTchannel:
00843 if ( R->Check(midiCode & 0x0F) ) {
00844 ProceedRoute(midiCode, R);
00845 DidOut = 1;
00846 }
00847
00848 break;
00849
00850 case RTstaff:
00851 if ( ((midiCode & 0xF0) != 0x80 && (midiCode & 0xF0) != 0x90) || R->Check((midiCode >> 8) & 0xFF) ) {
00852 ProceedRoute(midiCode, R);
00853 DidOut = 1;
00854 }
00855
00856 break;
00857
00858 case RTelse:
00859 if ( DidOut )
00860 break;
00861
00862 case RTall:
00863 ProceedRoute(midiCode, R);
00864 }
00865
00866 FLUSH_UPDATE_UI;
00867 }
00868
00869 #ifdef RTMIDI
00870 #include <string>
00871
00872 using namespace std;
00873 #include "RtMidi.h"
00874 RtMidiOut *rtmidiout;
00875 RtMidiIn *rtmidiin;
00876 #endif
00877
00878 void MidiInit()
00879 {
00880 #ifdef RTMIDI
00881
00882 try {
00883 rtmidiout = new RtMidiOut();
00884 } catch (RtError &error) {
00885 error.printMessage();
00886 abort();
00887 }
00888
00889 try {
00890 rtmidiin = new RtMidiIn();
00891 } catch (RtError &error) {
00892 error.printMessage();
00893 abort();
00894 }
00895
00896 #endif
00897 }
00898
00899 void MidiUninit()
00900 {
00901 delete rtmidiin;
00902 delete rtmidiout;
00903 }
00904