DevMidi.cpp
gehe zur Dokumentation dieser Datei
00001 
00026 // ------------------------------------------------------------------
00027 // Mutabor 3, 1998, R.Kraufle
00028 // MidiPort Klassen
00029 // ------------------------------------------------------------------
00030 
00031 #include "DevMidi.h"
00032 #include "Execute.h"
00033 #include "GrafKern.h"
00034 #include "MidiKern.h"
00035 
00036 // OutMidiPort ------------------------------------------------------
00037 
00038 //static long freq ;
00039 
00040 /* berechnet die Tonigkeit einer Taste bzgl. tonsystem */
00041 #define GET_INDEX(taste,tonsystem)                \
00042  ((int)( (taste)-( (tonsystem)->anker % (tonsystem)->breite )) \
00043                           % (tonsystem)->breite )
00044 
00045 
00046 // berechnet die 'Oktavlage' einer taste bzgl. tonsystem
00047 #define GET_ABSTAND(taste,tonsystem) \
00048      ( (int)((taste)-( (tonsystem)->anker % (tonsystem)->breite ))  \
00049            / (tonsystem)->breite -((int) (tonsystem)->anker         \
00050            / (tonsystem)->breite ))
00051 
00052 // berechnet die Frequenz in Midi-Form
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 /* 12.Wurzel 2 */
00061 //#define LONG_TO_HERTZ( x ) (440.0*pow(ZWZ,((((double)x)/16777216.0l))-69))
00062 //#define LONG_TO_CENT( x ) ( ((double)x)/167772.13l  )
00063 
00064 #ifdef RTMIDI
00065 #include "RtMidi.h"
00066 
00067 extern RtMidiOut *rtmidiout;
00068 
00069 extern RtMidiIn *rtmidiin;
00070 
00071 #endif
00072 
00073 // Midi-Ausgabe
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 // Zugriffe
00105 //#define zugriff  ((unsigned char*) &freq)
00106 //#define zgf  ((unsigned char*) &pb)
00107 
00108 // Pitch
00109 /* zugriff: 00000000111111112222222233333333
00110 22222222000000 + 111111
00111 
00112 zugriff: 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 |
00113         16 17 18 19 20 21 22 23 | 24 25 26 27 28 29 30 31
00114 zugriff[2] << 6 =  0  0  0  0  0  0 16 17 18 19 20 21 22 23
00115 zugriff[1] >> 2 = 10 11 12 13 14 15
00116 pb            = ( 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ) / bending_range;
00117 zgf0 >> 1 =          11 12 13 14 16 16 17
00118 zgf1 +64 =                                18 19 20 21 22 23 "1"
00119 pb & 0xff >> 1  =    11 12 13 14 15 16 17
00120 (pb>>8+0x4000)&0x7f00 =                   18 19 20 21 22 23 "1"
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 //      int pb = ( (((int)zugriff[2])<<6) + (zugriff[1]>>2) ) / bending_range; 
00131 //      MIDI_OUT3(0xE0+i, zgf[0] >> 1 , 64+zgf[1])
00132 
00133 // Sound
00134 #define MIDI_SOUND(i, sound) \
00135   if ( sound != -1 ) MIDI_OUT2(0xC0+i, sound)
00136 
00137 // ID errechnen
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; // alle nicht benutzt
00222 
00223 #ifdef RTMIDI
00224         // RtMidiIn constructor
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); // pitch auf 0
00245                 MIDI_OUT3(0xB0+i, 122, 0);  // local off
00246                 MIDI_OUT3(0xB0+i, 125, 0);  // omni on
00247                 MIDI_OUT3(0xB0+i, 127, 0);  // poly on
00248         }
00249 
00250         return true;
00251 }
00252 
00253 void OutMidiPort::Close()
00254 
00255 {
00256         DEBUGLOG (other, _T(""));
00257         // alle liegenden Tˆne ausschalten
00258 
00259         for (int i = 0; i < 16; i++)
00260                 if ( KeyDir[i] >= 16 )  // benutzt
00261                         MIDI_OUT3(0x80+i, ton_auf_kanal[i].key, 64);
00262 
00263         /*  for (int i = 0; i < 16; i++)
00264                  MidiOut3(176+i, 122, 1);  // local on */
00265         // Device schlieflen
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         // testen, ob nicht belegte Taste
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 )  // keinen freien gefunden
00315         {
00316                 // "mittelste Taste weglassen"
00317                 int AM = 0; // arithmetisches Mittel der Tasten
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                 // Ton auf Kanal free ausschalten
00332                 MIDI_OUT3(0x80+free, ton_auf_kanal[free].key, 64);
00333 
00334                 // evtl. Sustain ausschalten
00335                 if ( Cd[free].Sustain )
00336                         MIDI_OUT3(0xB0+free, 64, 0);
00337 
00338                 // KeyDir umsortieren
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         // freier Kanal = free
00351 
00352         // evtl. Sustain ausschalten
00353         if ( Cd[free].Sustain ) {
00354                 MIDI_OUT3(0xB0+free, 64, 0);
00355                 Cd[free].Sustain = 0;
00356         }
00357 
00358         // Sound testen
00359         if ( (s = cd->Sound) != Cd[free].Sound ) {
00360                 MIDI_SOUND(free, s);
00361                 Cd[free].Sound = s;
00362         }
00363 
00364         // Bank testen
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         // Pitch testen
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 ) //3 ?? notwendig?
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 // ???     ton_auf_kanal[i].id=0;
00411                                 MIDI_OUT3(0x80+i, ton_auf_kanal[i].key, velo);
00412                                 // KeyDir umsortieren
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                         // hier kann ein evtl. grˆflerer bending_range genutzt werden, um
00447                         // Ton aus und einschalten zu vermeiden
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                         // evtl. Ton ausschalten
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                         // Spezialbending (grofler Range)
00474                         Cd[i].Pitch = Delta;
00475 
00476                         Delta /= bending_range;
00477                         Delta = Delta >> 11;
00478                         Delta +=  0x40 << 7; // we have to add here as Delta can be negative
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                         //      MIDI_OUT3(0xE0+i, ((BYTE*)&Delta)[1] >> 1, (((BYTE*)&Delta)[2]));
00482                         MIDI_OUT3(0xE0+i, Delta & 0x7f, (Delta >> 7) & 0x7f );
00483 
00484                         // evtl. Ton einschalten
00485                         if ( SwitchTone )
00486                                 MIDI_OUT3(0x90+i, ton_auf_kanal[i].key, 64);  //3 velo speichern ??
00487                 }
00488 }
00489 
00490 void OutMidiPort::Sustain(char on, int channel)
00491 {
00492         DEBUGLOG (other, _T(""));
00493         DWORD chan = channel; // Midi has unsigned channels
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 //void Gis(GisToken *token, char turn) {};
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);  // All notes off */
00553                 MIDI_OUT3(0xB0+i, 7, 127);  // main volume
00554                 // sound piano
00555                 MIDI_OUT2(0xC0+i, 0);
00556                 // Merker aufr‰umen
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; // alle nicht benutzt
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 // InMidiPort -------------------------------------------------------
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         //  CurrentTimeStamp = dwParam2;
00598 
00599         if ( wMsg != MIM_DATA || dwParam1 % 256 > 240 ) return;
00600 
00601         // Daten in Midi-Automat
00602         ((InMidiPort*)dwInstance)->Proceed(dwParam1);
00603 }
00604 
00605 #endif
00606 
00607 // InMidiPort -------------------------------------------------------
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 /*#define MIDICODE(i)                           \
00752   (((BYTE*)(&midiCode))[i])
00753 */
00754 // f¸r bestimmte Route Codeverarbeitung
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: // Note On
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: // Note Off
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: // Programm Change
00791                 Cd[MidiChannel].Sound = (midiCode >> 8) & 0xff;
00792 
00793                 break;
00794 
00795         case 0xB0: // Control Change
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 ) // BankSelectMSB
00806                 {
00807                         Cd[MidiChannel].BankSelectMSB = data;
00808                         break;
00809                 } else if ( control == 32 ) // BankSelectLSB
00810                 {
00811                         Cd[MidiChannel].BankSelectLSB =data;
00812                         break;
00813                 }
00814         }
00815         case 0xA0:
00816 
00817         case 0xD0: // Key Pressure, Controler, Channel Pressure
00818                 //3 ??
00819                 break;
00820         }
00821 
00822         // Midianalyse
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 // Routen testen und jenachdem entsprechend Codeverarbeitung
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 

Erzeugt am Sun Aug 21 2011 10:51:53 für Mutabor von doxygen 1.7.4