DevMidF.cpp
gehe zur Dokumentation dieser Datei
00001 
00089 // ------------------------------------------------------------------
00090 // Mutabor 3, 1998, R.Krauße
00091 // MIDI-File als Device
00092 // ------------------------------------------------------------------
00093 #include "Defs.h"
00094 #if defined(MUTWIN) && !defined(WX)
00095 #include <owl/pch.h>
00096 #endif
00097 
00098 #ifdef RTMIDI
00099 #  include "RtMidi.h"
00100 #else
00101 #ifndef H_MMSYSTEM
00102 //  #define WINVER 0x030a
00103 #include <mmsystem.h>
00104 #define H_MMSYSTEM
00105 #endif
00106 #endif
00107 
00108 #include "DevMidF.h"
00109 #include "Execute.h"
00110 #include "GrafKern.h"
00111 #include "Runtime.h"
00112 
00113 #include "wx/wfstream.h"
00114 
00115 
00116 /* berechnet die Tonigkeit einer Taste bzgl. tonsystem */
00117 #define GET_INDEX(taste,tonsystem)                \
00118  ((int)((taste)-( (tonsystem)->anker % (tonsystem)->breite )) \
00119                           % (tonsystem)->breite )
00120 
00121 
00122 // berechnet die 'Oktavlage' einer taste bzgl. tonsystem
00123 #define GET_ABSTAND(taste,tonsystem) \
00124      ( (int)((taste)-( (tonsystem)->anker % (tonsystem)->breite ))  \
00125            / (tonsystem)->breite -((int) (tonsystem)->anker         \
00126            / (tonsystem)->breite ))
00127 
00128 // berechnet die Frequenz in Midi-Form
00129 #define GET_FREQ(taste,tonsystem)  \
00130         ( ( (tonsystem)->ton[GET_INDEX(taste,(tonsystem))]==0) ?       \
00131           (long) 0 :                                       \
00132      (long)( (tonsystem)->periode *                   \
00133               GET_ABSTAND(taste,(tonsystem))  +                         \
00134                    (tonsystem)->ton[GET_INDEX(taste,(tonsystem))]))
00135 
00136 #define ZWZ 1.059463094 /* 12.Wurzel 2 */
00137 #define LONG_TO_HERTZ( x ) (440.0*pow(ZWZ,((((float)x)/(double)16777216.0))-69))
00138 #define LONG_TO_CENT( x ) ( ((float)x)/(double)167772.13  )
00139 
00140 // Midi-Ausgabe
00141 #define MIDI_OUT3(code1, code2, code3) \
00142   Tracks.MidiOut3(code1, code2, code3)
00143 
00144 #define MIDI_OUT2(code1, code2) \
00145   Tracks.MidiOut2(code1, code2)
00146 
00147 // Zugriffe
00148 #define zugriff  ((unsigned char*) &freq)
00149 #define zgf  ((unsigned char*) &pb)
00150 
00151 // Pitch
00152 #define MIDI_PITCH(i) \
00153         int pb = ( (((int)zugriff[2])<<6) + (zugriff[1]>>2) ) / bending_range; \
00154         MIDI_OUT3(0xE0+i, zgf[0] >> 1 , 64+(ton_auf_kanal[i].fine=(zgf[1])))
00155 
00156 // Sound
00157 #define MIDI_SOUND(i, sound) \
00158   if ( sound != -1 ) MIDI_OUT2(0xC0+i, sound)
00159 
00160 // ID errechnen
00161 #define MAKE_ID(route, box, taste, channel) \
00162  ((((DWORD)channel) << 24) + (((DWORD)route->GetId()) << 16) + ((DWORD)box << 8) + taste)
00163 
00164 #define NO_DELTA 0x7fffffffl //2147483647  // long max-Zahl
00165 
00166 int lMidiCode[8] = { 3, 3, 3, 3, 2, 2, 3, 1 };
00167 
00168 // Daten ¸bergeben für NoRealTime-Übersetzungen
00169 BYTE *pData;
00170 int nData;
00171 long NRT_Speed;
00172 
00173 DWORD ReadLength(mutIFstream &is)
00174 {
00175         BYTE a[4];
00176         mutReadStream(is,(char*)a, 4);
00177         return (((DWORD)a[0]) << 24) + (((DWORD)a[1]) << 16) +
00178                (((DWORD)a[2]) << 8) + ((DWORD)a[3]);
00179 }
00180 
00181 void WriteLength(mutOFstream &os, DWORD l)
00182 {
00183         mutPutC(os,(BYTE) ((l >> 24) & 0xFF));
00184         mutPutC(os,(BYTE) ((l >> 16) & 0xFF));
00185         mutPutC(os,(BYTE) ((l >> 8) & 0xFF));
00186         mutPutC(os,(BYTE) (l & 0xFF));
00187 }
00188 
00189 
00190 
00191 // Tracks -----------------------------------------------------------
00192 
00193 void Track::WriteDelta()
00194 {
00195         BYTE w[5];
00196         int i = 0;
00197         DWORD Delta = (unsigned int)CurrentTime - Time;
00198         Time = (unsigned int) CurrentTime;
00199         w[0] = Delta & 0x7F;
00200         Delta >>= 7;
00201 
00202         while ( Delta ) {
00203                 i++;
00204                 w[i] = 0x80 | (Delta & 0x7F);
00205                 Delta >>= 7;
00206         }
00207 
00208         for (;i>=0;i--)
00209                 Data->Add(w[i]);
00210 }
00211 
00212 void Track::Save(mutOFstream &os)
00213 {
00214         mutWriteStream(os,"MTrk",4);
00215         WriteLength(os, Data->GetItemsInContainer()+4);
00216 
00217         for (DWORD i = 0; i < Data->GetItemsInContainer(); i++)
00218                 mutPutC(os,(BYTE)(*Data)[i]);
00219 
00220         mutPutC(os,(BYTE)0x00);
00221 
00222         mutPutC(os,(BYTE)0xFF);
00223 
00224         mutPutC(os,(BYTE)0x2F);
00225 
00226         mutPutC(os,(BYTE)0x00);
00227 }
00228 
00229 // OutMidiFile ------------------------------------------------------
00230 
00232 
00234 void OutMidiFile::Save (tree_storage & config) 
00235 {
00236         config.Write(_T("Bending Range"),bending_range);
00237         config.Write(_T("File Name"),Name);
00238 }
00239 
00241 
00246 void OutMidiFile::Save (tree_storage & config, const Route * route)
00247 {
00248         wxASSERT(route);
00249         config.Write(_T("Avoid Drum Channel"), route->ONoDrum);
00250         config.Write(_T("Channel Range From"), route->OFrom);
00251         config.Write(_T("Channel Range To"), route->OTo);
00252 }
00253 
00254 
00256 
00258 void OutMidiFile::Load (tree_storage & config)
00259 {
00260         bending_range=config.Read(_T("Bending Range"), bending_range);
00261         Name = config.Read(_T("File Name"),mutEmptyString);
00262 }
00263 
00265 
00270 void OutMidiFile::Load (tree_storage & config, Route * route)
00271 {
00272         wxASSERT(route);
00273         route->ONoDrum = config.Read (_T("Avoid Drum Channel"), true);
00274         int oldfrom, oldto;
00275         oldfrom = route->OFrom = config.Read(_T("Channel From"), GetMinChannel());
00276         oldto = route->OTo = config.Read(_T("Channel To"), GetMaxChannel());
00277         bool correct = true;
00278         if (route->OFrom < GetMinChannel()) {
00279                 correct = false;
00280                 route->OFrom = GetMinChannel();
00281         }
00282         if (route->OTo > GetMaxChannel()) {
00283                 correct = false;
00284                 route->OTo = GetMaxChannel();
00285         }
00286         if (!correct)
00287                 wxMessageBox(wxString::Format(_("The Channel range %d--%d of the MIDI file %s must be inside %d--%d. The current route had to be corrected."),
00288                                               oldfrom,oldto,GetName().c_str(),GetMinChannel(),GetMaxChannel()),
00289                              _("Warning loading route"),wxICON_EXCLAMATION);
00290 }
00291 
00292 
00293 bool OutMidiFile::Open()
00294 {
00295         Tracks.Data->Flush();
00296         return true;
00297 }
00298 
00299 void OutMidiFile::Close()
00300 {
00301         // alle liegenden Tˆne ausschalten
00302 
00303         for (int i = 0; i < 16; i++)
00304                 if ( KeyDir[i] >= 16 )  // benutzt
00305                         MIDI_OUT3(0x80+i, ton_auf_kanal[i].key, 64);
00306 
00307         // Datei speichern
00308         mutOpenOFstream(os,Name);
00309 
00310         BYTE Header[41] =
00311                 { 'M', 'T', 'h', 'd', 0, 0, 0, 6, 0, 1, 0, 2, 1, 0x00,
00312                   'M', 'T', 'r', 'k', 0, 0, 0, 0x13, 0x00, 0xFF, 0x51, 0x03, 0x07, 0xD0, 0x00,
00313                   0x00, 0xFF, 0x58, 0x04, 0x04, 0x02, 0x18, 0x08, 0x00, 0xFF, 0x2F, 0x00 };
00314 
00315         if ( !RealTime ) {
00316                 Header[12] = ((WORD)(NRT_Speed >> 8)) & 0xFF;
00317                 Header[13] = ((WORD)(NRT_Speed)) & 0xFF;
00318         }
00319 
00320         mutWriteStream(os,Header, 41);
00321 
00322         Tracks.Save(os);
00323 }
00324 
00325 void OutMidiFile::NoteOn(int box, int taste, int velo, Route *r, int channel, ChannelData *cd)
00326 {
00327         int i = 0, s;
00328         DWORD p;
00329         unsigned long freq;
00330 
00331         if ( box == -2 ) {
00332                 freq = ((long)taste) << 24;
00333                 box = 255;
00334         } else
00335                 freq = GET_FREQ (taste, mut_box[box].tonesystem);
00336 
00337         // testen, ob nicht belegte Taste
00338         if ( !freq )
00339                 return;
00340 
00341         int help = r->OTo;
00342 
00343         i = r->OFrom; // "irgendein" Startwert im g¸ltigen Bereich
00344 
00345         if ( i == DRUMCHANNEL && r->ONoDrum && i < r->OTo )
00346                 i++;
00347 
00348         int j;
00349 
00350         for (j = r->OFrom; j <= r->OTo; j++ )
00351                 if ( j != DRUMCHANNEL || !r->ONoDrum )
00352                         if ( KeyDir[j] < KeyDir[i] )
00353                                 i = j;
00354 
00355         if ( KeyDir[i] >= 16 )  // keinen freien gefunden
00356         {
00357                 // "mittelste Taste weglassen"
00358                 int AM = 0; // arithmetisches Mittel der Tasten
00359 
00360                 for (REUSE(int) j =r->OFrom; j <= r->OTo; j++)
00361                         if ( j != DRUMCHANNEL || !r->ONoDrum )
00362                                 AM += ton_auf_kanal[j].taste;
00363 
00364                 AM /= help + 1 - r->OFrom;
00365 
00366                 for (REUSE(int) j = r->OFrom; j <= r->OTo; j++ )
00367                         if ( j != DRUMCHANNEL || !r->ONoDrum )
00368                                 if ( abs(AM - ton_auf_kanal[j].taste) < abs(AM - ton_auf_kanal[i].taste) )
00369                                         i = j;
00370 
00371                 // Ton auf Kanal i ausschalten
00372                 MIDI_OUT3(0x80+i, ton_auf_kanal[i].key, 64);
00373 
00374                 // KeyDir umsortieren
00375                 BYTE oldKeyDir = KeyDir[i];
00376 
00377                 for (int k = 0; k < 16; k++)
00378                         if ( KeyDir[k] > oldKeyDir ) KeyDir[k]--;
00379 
00380                 KeyDir[i] = 15+nKeyOn;
00381         } else {
00382                 nKeyOn++;
00383                 KeyDir[i] = 15 + nKeyOn;
00384         }
00385 
00386         // freier Kanal = i
00387 
00388         // Sound testen
00389         if ( (s = cd->Sound) != Cd[i].Sound ) {
00390                 MIDI_SOUND(i, s);
00391                 Cd[i].Sound = s;
00392         }
00393 
00394         // Bank testen
00395         if ( (s = cd->BankSelectMSB) != Cd[i].BankSelectMSB && s != -1 ) {
00396                 MIDI_OUT3(0xB0+i, 0, (BYTE) s);
00397                 Cd[i].BankSelectMSB = s;
00398         }
00399 
00400         if ( (s = cd->BankSelectLSB) != Cd[i].BankSelectLSB && s != -1 ) {
00401                 MIDI_OUT3(0xB0+i, 32, (BYTE) s);
00402                 Cd[i].BankSelectLSB = s;
00403         }
00404 
00405         // Pitch testen
00406         if ( (long) (p = freq & 0xFFFFFF) != Cd[i].Pitch ) {
00407                 MIDI_PITCH(i);
00408                 Cd[i].Pitch = p;
00409         }
00410 
00411         ton_auf_kanal[i].key = zugriff[3] & 0x7f;
00412 
00413         ton_auf_kanal[i].taste = taste;
00414         ton_auf_kanal[i].id = MAKE_ID(r, box, taste, channel);
00415         MIDI_OUT3(0x90+i, ton_auf_kanal[i].key, velo);
00416 }
00417 
00418 void OutMidiFile::NoteOff(int box, int taste, int velo, Route *r, int channel)
00419 {
00420         if ( box == -2 )
00421                 box = 255;
00422 
00423         DWORD id = MAKE_ID(r, box, taste, channel);
00424 
00425         if ( !velo ) //3 ?? notwendig?
00426                 velo = 64;
00427 
00428         for (int i = r->OFrom; i <= r->OTo; i++)
00429                 if ( i != DRUMCHANNEL || !r->ONoDrum )
00430                         if ( ton_auf_kanal[i].id == id ) {
00431                                 ton_auf_kanal[i].taste=0;
00432                                 ton_auf_kanal[i].id=0;
00433                                 MIDI_OUT3(0x80+i, ton_auf_kanal[i].key, velo);
00434                                 // KeyDir umsortieren
00435                                 int oldKeyDir = KeyDir[i];
00436 
00437                                 for (int k = 0; k < 16; k++)
00438                                         if ( KeyDir[k] > oldKeyDir || KeyDir[k] < 16) KeyDir[k]--;
00439 
00440                                 nKeyOn--;
00441 
00442                                 KeyDir[i] = 15;
00443                         }
00444 }
00445 
00446 inline long LongAbs(long x)
00447 {
00448         return (x < 0)? -x : x;
00449 }
00450 
00451 void OutMidiFile::NotesCorrect(int box)
00452 {
00453         for (int i = 0; i < 16; i++)
00454                 if ( KeyDir[i] >= 16 && ton_auf_kanal[i].id ) {
00455                         int Box = (ton_auf_kanal[i].id >> 8) & 0xFF;
00456 
00457                         if ( Box != box )
00458                                 break;
00459 
00460                         long freq = GET_FREQ(ton_auf_kanal[i].taste, mut_box[box].tonesystem);
00461 
00462                         // hier kann ein evtl. grˆflerer bending_range genutzt werden, um
00463                         // Ton aus und einschalten zu vermeiden
00464                         if ( ton_auf_kanal[i].key == (zugriff[3] & 0x7f) &&
00465                                         Cd[i].Pitch == (freq & 0xFFFFFF) )
00466                                 continue;
00467 
00468                         long Delta = freq - ((long)ton_auf_kanal[i].key << 24);
00469 
00470                         char SwitchTone = (LongAbs(Delta) >= ((long)bending_range << 24));
00471 
00472                         // evtl. Ton ausschalten
00473                         if ( SwitchTone ) {
00474                                 MIDI_OUT3(0x80+i, ton_auf_kanal[i].key, 0x7F);
00475                                 ton_auf_kanal[i].key = zugriff[3] & 0x7f;
00476                                 Delta = freq - ((DWORD)ton_auf_kanal[i].key << 24);
00477                         } else if ( Delta == Cd[i].Pitch )
00478                                 continue;
00479 
00480                         // Spezialbending (grofler Range)
00481                         Cd[i].Pitch = Delta;
00482 
00483                         Delta /= (4*bending_range);
00484 
00485                         Delta += 0x400000;
00486 
00487                         MIDI_OUT3(0xE0+i, ((BYTE*)&Delta)[1] >> 1, (((BYTE*)&Delta)[2]));
00488 
00489                         // evtl. Ton einschalten
00490                         if ( SwitchTone )
00491                                 MIDI_OUT3(0x90+i, ton_auf_kanal[i].key, 64);  //3 velo speichern ??
00492                 }
00493 }
00494 
00495 void OutMidiFile::Sustain(char on, int channel)
00496 {}
00497 
00498 void OutMidiFile::MidiOut(DWORD data, char n)
00499 {
00500         Tracks.WriteDelta();
00501 
00502         if ( n == -1 )
00503                 n = lMidiCode[(data & 0xF0) >> 5];
00504 
00505         for (int i = 0; i < n; i++) {
00506                 Tracks.Add(data & 0xFF);
00507                 data >>= 8;
00508         }
00509 }
00510 
00511 void OutMidiFile::MidiOut(BYTE *p, char n)
00512 {
00513         Tracks.WriteDelta();
00514 
00515         for (int i = 0; i < n; i++)
00516                 Tracks.Add(p[i]);
00517 }
00518 
00519 void OutMidiFile::Quite(Route *r)
00520 {
00521         for (int i = 0; i < 16; i++)
00522                 if ( (char)((ton_auf_kanal[i].id >> 16) & 0x0FF) == r->GetId() )
00523                         NoteOff(r->Box, ton_auf_kanal[i].id % 256, 64, r, ton_auf_kanal[i].id >> 24);
00524 }
00525 
00526 void OutMidiFile::ReadData(wxConfigBase * config) 
00527 {
00528         bending_range = config->Read(_("Bending_Range"),
00529                                          (long)bending_range);
00530 }
00531 
00532 void OutMidiFile::WriteData(wxConfigBase * config) 
00533 {
00534         config->Write(_("Bending_Range"), (long)bending_range);
00535 }
00536 
00537 
00538 // InMidiFile -------------------------------------------------------
00539 
00540 /*
00541 void CALLBACK _export MidiTimeFunc(UINT wTimerID, UINT wMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
00542 {
00543  ((InMidiFile*)dwUser)->IncDelta();
00544 }
00545 */
00546 
00547 long ReadDelta(BYTE *data, DWORD *i)
00548 {
00549         long l = 0;
00550         BYTE a;
00551 
00552         do {
00553                 a = data[*i];
00554                 (*i)++;
00555                 l = (l << 7) + (a & 0x7F);
00556         } while ( a & 0x80 );
00557 
00558         return l;
00559 }
00560 
00562 
00564 void InMidiFile::Save (tree_storage & config)
00565 {
00566         config.Write(_T("File Name"),Name);
00567 }
00568 
00570 
00575 void InMidiFile::Save (tree_storage & config, const Route * route)
00576 {
00577         config.Write(_T("Filter Type"), route->Type);
00578         switch(route->Type) {
00579                 case RTchannel: 
00580                         config.Write(_T("Channel From"), route->IFrom);
00581                         config.Write(_T("Channel To"), route->ITo);
00582                         break;
00583                 case RTstaff:
00584                         config.Write(_T("Track From"), route->IFrom);
00585                         config.Write(_T("Track To"), route->ITo);
00586                         break;
00587                 case RTelse:
00588                 case RTall:
00589                         break;
00590         }
00591                         
00592 }
00593 
00594 
00596 
00598 void InMidiFile::Load (tree_storage & config)
00599 {
00600         Name = config.Read(_T("File Name"),mutEmptyString);
00601 }
00602         
00603 
00605 
00610 void InMidiFile::Load (tree_storage & config, Route * route)
00611 {
00612         route -> Type = (RouteType) config.Read(_T("Filter Type"), (int)RTchannel);
00613         switch(route->Type) {
00614                 case RTchannel: 
00615                 {
00616                         int oldfrom, oldto;
00617                         oldfrom = route->IFrom = config.Read(_T("Channel From"), GetMinChannel());
00618                         oldto = route->ITo = config.Read(_T("Channel To"), GetMaxChannel());
00619                         bool correct = true;
00620                         if (route->IFrom < GetMinChannel()) {
00621                                 correct = false;
00622                                 route->IFrom = GetMinChannel();
00623                         }
00624                         if (route->ITo > GetMaxChannel()) {
00625                                 correct = false;
00626                                 route->ITo = GetMaxChannel();
00627                         }
00628                         if (!correct)
00629                                 wxMessageBox(wxString::Format(_("The Channel range %d--%d of the MIDI file %s must be inside %d--%d. The current route had to be corrected."),
00630                                                               oldfrom,oldto,GetName().c_str(),GetMinChannel(),GetMaxChannel()),
00631                                              _("Warning loading route"),wxICON_EXCLAMATION);
00632                         break;
00633                 }
00634                 case RTstaff:
00635                 {
00636                         int oldfrom, oldto;
00637                         route -> IFrom = oldfrom = config.Read(_T("Track From"), GetMinTrack());
00638                         route -> ITo = oldto = config.Read(_T("Track To"), GetMaxTrack());
00639                         bool correct = true;
00640                         if (route->IFrom < GetMinTrack()) {
00641                                 correct = false;
00642                                 route->IFrom = GetMinTrack();
00643                         }
00644                         if (route->ITo > GetMaxTrack()) {
00645                                 correct = false;
00646                                 route->ITo = GetMaxTrack();
00647                         }
00648                         if (!correct)
00649                                 wxMessageBox(wxString::Format(_("The Track range %d--%d of the MIDI file %s must be inside %d--%d. The current route had to be corrected."),
00650                                                               oldfrom,oldto,GetName().c_str(), GetMinTrack(), GetMaxTrack()),
00651                                              _("Warning loading route"),wxICON_EXCLAMATION);
00652                         break;
00653                 }
00654                 case RTelse:
00655                 case RTall:
00656                         break;
00657         }
00658 }
00659 
00660 
00661 bool InMidiFile::Open()
00662 {
00663         DEBUGLOG (other, _T("start"));
00664         Track = 0;
00665         curDelta = 0;
00666         TrackPos = 0;
00667         StatusByte = 0;
00668         TicksPerQuater = 0;
00669         MMSPerQuater = (long) 1000000;
00670         // Datei lesen
00671         mutOpenIFstream(is, Name);
00672 
00673         if ( mutStreamBad(is) ) {
00674                 DEBUGLOG (other, _T("Opening Stream failed"));
00675                 Mode = MutaborDeviceCompileError;
00676                 InDevChanged = 1;
00677 //              LAUFZEIT_ERROR1(_("Can not open Midi input file '%s'."), GetName());
00678                 LAUFZEIT_ERROR1(_("Can not open Midi input file '%s'."), Name.c_str());
00679                 return false;
00680         }
00681 
00682         // Header Chunk
00683         char Header[5];
00684 
00685         mutReadStream(is,Header, 4);
00686 
00687         DWORD l = ReadLength(is);
00688 
00689         BYTE a, b;
00690 
00691         // file type
00692         a = mutGetC(is); //mutGetC(is,a);
00693 
00694         FileType = mutGetC(is); //mutGetC(is,FileType);
00695 
00696         // number of tracks
00697         a = mutGetC(is); //mutGetC(is,a);
00698 
00699         b = mutGetC(is); // mutGetC(is,b);
00700 
00701         nTrack = (((int)a) << 8) + b;
00702 
00703         // speed info
00704         a = mutGetC(is); //mutGetC(is,a);
00705 
00706         b = mutGetC(is); //mutGetC(is,b);
00707 
00708         Speed = (((int)a) << 8) + b;
00709 
00710         NRT_Speed = Speed;
00711 
00712         // rest of header
00713         DWORD i;
00714 
00715         for (i = 6; i < l && !mutStreamEOF(is) && mutStreamGood(is); i++ )
00716                 a = mutGetC(is);// mutGetC(is,a);
00717 
00718         // Tracks lesen
00719         Track = (BYTE**) malloc(nTrack*sizeof(BYTE*));
00720 
00721         for (i = 0; i < nTrack; i++ ) {
00722                 mutReadStream(is,Header, 4);
00723                 l = ReadLength(is);
00724 
00725                 if ( l > (long) 64000 ) {
00726                         Mode = MutaborDeviceCompileError;
00727                         InDevChanged = 1;
00728                         LAUFZEIT_ERROR1(_("Midi input file '%s' is to long."), Name.c_str());
00729                         DEBUGLOG (other, _T("Midi input file '%s' is too long."),Name.c_str());
00730                         return false;
00731                 }
00732 
00733                 Track[i] = (BYTE*)malloc(l*sizeof(BYTE));
00734 
00735                 if ( l > 32000 ) {
00736                         mutReadStream(is, (char*)Track[i], 32000);
00737                         mutReadStream(is, (char*)&Track[i][32000], l-32000);
00738                 } else
00739                         mutReadStream(is, (char*)Track[i], l);
00740 
00741                 if ( /*is.gcount() != l ||*/ mutStreamBad(is) ) {
00742                         DEBUGLOG (other, _("Midi input file '%s' produces errors."),
00743                                  Name.c_str());
00744                         Mode = MutaborDeviceCompileError;
00745                         InDevChanged = 1;
00746                         LAUFZEIT_ERROR1(_("Midi input file '%s' produces errors."), Name.c_str());
00747                         return false;
00748                 }
00749         }
00750 
00751         mutCloseStream(is);
00752 
00753         // Daten vorbereiten
00754         curDelta = (long*)malloc(nTrack*sizeof(long));
00755         TrackPos = (DWORD*)malloc(nTrack*sizeof(DWORD));
00756         StatusByte = (BYTE*)malloc(nTrack*sizeof(BYTE));
00757         // Mode setzen
00758         Mode = MutaborDeviceStop;
00759         // initialisieren
00760         Stop();
00761         DEBUGLOG (other, _T("finished. Mode = %d, this = %p"),Mode,this);
00762         return true;
00763 }
00764 
00765 void InMidiFile::Close()
00766 {
00767         Stop();
00768         // Speicher freigeben
00769 
00770         if ( Mode == MutaborDeviceCompileError )
00771                 return;
00772 
00773         for (size_t i = 0; i < nTrack; i++ )
00774                 free(Track[i]);
00775 
00776         free(Track);
00777         free(TrackPos);
00778         free(curDelta);
00779         free(StatusByte);
00780 }
00781 
00782 void InMidiFile::Stop()
00783 {
00784   DEBUGLOG(routing,_T("old mode = %d"),Mode);
00785         if ( Mode == MutaborDevicePlay || Mode == MutaborDeviceTimingError )
00786                 Pause();
00787 
00788         // OK ?
00789         if ( Mode == MutaborDeviceCompileError )
00790                 return;
00791 
00792         // Delta-Times lesen
00793         minDelta = 0;
00794 
00795         long NewMinDelta = NO_DELTA;
00796 
00797         MMSPerQuater = 1000000l;
00798 
00799         for (size_t i = 0; i < nTrack; i++ ) {
00800                 TrackPos[i] = 0;
00801                 curDelta[i] = ReadDelta(Track[i], &(TrackPos[i]));
00802 
00803                 if ( curDelta[i] < NewMinDelta )
00804                         NewMinDelta = curDelta[i];
00805         }
00806 
00807         minDelta = NewMinDelta;
00808 
00809         actDelta = -1;
00810         Mode = MutaborDeviceStop;
00811 }
00812 
00813 void InMidiFile::Play()
00814 {
00815         if ( RealTime )
00816                 timer.Start(2,wxTIMER_CONTINUOUS);
00817 
00818         //    TimerId = timeSetEvent(2, 1, MidiTimeFunc, (DWORD)this, TIME_PERIODIC);
00819         Busy = FALSE;
00820 
00821         Mode = MutaborDevicePlay;
00822 }
00823 
00824 void InMidiFile::Pause()
00825 {
00826         if ( RealTime )
00827                 timer.Stop();
00828 
00829         //    timeKillEvent(TimerId);
00830         Mode = MutaborDevicePause;
00831 
00832         Quite();
00833 }
00834 
00835 void InMidiFile::IncDelta()
00836 {
00837         actDelta++;
00838 
00839         if ( Busy )
00840                 return;
00841 
00842         if ( actDelta < minDelta )
00843                 return;
00844 
00845         // Zeitpunkt ist ran, also verarbeiten
00846         Busy = TRUE;
00847 
00848         actDelta -= minDelta;
00849 
00850         long passedDelta = minDelta;
00851 
00852         long NewMinDelta = NO_DELTA;
00853 
00854         for (size_t i = 0; i < nTrack; i++ ) {
00855                 if ( curDelta[i] != NO_DELTA ) {
00856                         if ( curDelta[i] <= passedDelta )
00857                                 curDelta[i] = ReadMidiProceed(i, passedDelta-curDelta[i]);
00858                         else
00859                                 curDelta[i] -= passedDelta;
00860 
00861                         if ( curDelta[i] < NewMinDelta )
00862                                 NewMinDelta = curDelta[i];
00863                 }
00864         }
00865 
00866         if ( NewMinDelta == NO_DELTA ) {
00867           // we have reached the end of all tracks
00868           InDevChanged = 1;
00869           Stop();
00870           //            Mode = MutaborDeviceTimingError;
00871         }
00872 
00873 #if (DEBUG && WX)
00874         wxASSERT(NewMinDelta > 0);
00875         DEBUGLOG(midifile,_T("old mindelta = %d, new mindelta = %d"),minDelta,NewMinDelta);
00876 #endif
00877 
00878         minDelta = NewMinDelta;
00879         Busy = FALSE;
00880 }
00881 
00882 long InMidiFile::ReadMidiProceed(size_t nr, long time)
00883 {
00884         long Delta = 0;
00885         long OldPos;
00886 
00887         while ( time >= Delta ) {
00888                 time -= Delta;
00889                 pData = &(Track[nr][TrackPos[nr]]);
00890                 OldPos = TrackPos[nr];
00891                 DWORD a = Track[nr][TrackPos[nr]++];
00892 
00893                 if ( a & 0x80 )
00894                         StatusByte[nr] = a;
00895                 else {
00896                         TrackPos[nr]--;
00897                         a = StatusByte[nr];
00898                 }
00899 
00900                 BYTE SB = StatusByte[nr];
00901 
00902                 if ( SB <  0xF0 ) // normaler midi code
00903                 {
00904                         int l = lMidiCode[(SB >> 4) & 07];
00905                         int shift = 8;
00906 
00907                         for (int i = 1; i < l; i++)
00908                         {
00909                                 a += (DWORD)Track[nr][TrackPos[nr]++] << shift;
00910                                 shift += 8;
00911                         }
00912                 }
00913                 else if ( SB == 0xF0 || SB == 0xF7 ) // SysEx I, SysEx II
00914                 {
00915                         DWORD EventLength = ReadDelta(Track[nr], &(TrackPos[nr])); // length
00916                         TrackPos[nr] += EventLength;
00917                 } else if ( SB == 0xFF ) // meta event
00918                 {
00919                         a += Track[nr][TrackPos[nr]++] << 8;         // event number
00920                         DWORD EventLength = ReadDelta(Track[nr], &(TrackPos[nr])); // length
00921 
00922                         if ( (a >> 8) == 0x58 ) // Time Signature
00923                         {
00924                                 TicksPerQuater = Track[nr][TrackPos[nr]+2];
00925                         } else if ( (a >> 8) == 0x51 ) // Tempo
00926                         {
00927                                 long NewMMSPerQuater =
00928                                         (((DWORD)Track[nr][TrackPos[nr]]) << 16) +
00929                                         (((DWORD)Track[nr][TrackPos[nr]+1]) << 8) +
00930                                         ((DWORD)Track[nr][TrackPos[nr]]);
00931 
00932                                 for (size_t j = 0; j < nr; j++ )
00933                                         if ( curDelta[j] != NO_DELTA )
00934                                                 curDelta[j] = curDelta[j] * NewMMSPerQuater / MMSPerQuater;
00935 
00936                                 for (REUSE(size_t) j = nr+1; j < nTrack; j++ )
00937                                         if ( curDelta[j] != NO_DELTA && curDelta[j] >= minDelta)
00938                                                 curDelta[j] = (curDelta[j]-minDelta) * NewMMSPerQuater / MMSPerQuater +minDelta;
00939 
00940                                 MMSPerQuater = NewMMSPerQuater;
00941                         }
00942                         TrackPos[nr] += EventLength;
00943                 } else if ( SB == 0xF2 ) // song position pointer
00944                 {
00945                         a += Track[nr][TrackPos[nr]++] << 8;
00946                         a += Track[nr][TrackPos[nr]++] << 16;
00947                 } else if ( SB == 0xF3 ) // song select
00948                         a += Track[nr][TrackPos[nr]++] << 8;
00949 
00950                 // ausf¸hren
00951                 nData = TrackPos[nr] - OldPos;
00952 
00953 //9    if ( *((BYTE*)(&a)) < 0xF0 )
00954                 if ( a == 0x2FFF ) {
00955                         TrackPos[nr] = 0xFFFFFFFF;
00956                         return NO_DELTA;
00957                 } else
00958                         Proceed(a, nr);
00959 
00960                 // Delta Time
00961                 Delta = ReadDelta(Track[nr], &(TrackPos[nr]));
00962 
00963                 if ( RealTime )
00964                         Delta = MMSPerQuater / 2000 * Delta / Speed;
00965         }
00966 
00967         return Delta - time;
00968 }
00969 
00970 #define MIDICODE(i) \
00971   (0xff & (midiCode >> (8*i)))
00972 //(((BYTE*)(&midiCode))[i])
00973 
00974 // f¸r bestimmte Route Codeverarbeitung
00975 void InMidiFile::ProceedRoute(DWORD midiCode, Route *route)
00976 {
00977         
00978         DEBUGLOG (other, _T("Code: %x, Active: %d, Out: %x"),midiCode,
00979                  route->Active,
00980                  route->GetOutDevice());
00981         int Box = route->Box;
00982         BYTE MidiChannel = MIDICODE(0) & 0x0F;
00983         BYTE MidiStatus = MIDICODE(0) & 0xF0;
00984         DEBUGLOG (other, _T("Status: %x"), MidiStatus);
00985 
00986         switch ( MidiStatus ) {
00987 
00988         case 0x90: // Note On
00989                 if ( MIDICODE(2) > 0 ) {
00990                         if ( route->Active )
00991                                 AddKey(Box, MIDICODE(1), route->GetId());
00992 
00993                         if ( route->GetOutDevice() )
00994                                 route->GetOutDevice()->NoteOn(Box, MIDICODE(1), MIDICODE(2), route,
00995                                                    MidiChannel, &Cd[MidiChannel]);
00996 
00997                         break;
00998                 }
00999 
01000         case 0x80: // Note Off
01001                 if ( route->Active )
01002                         DeleteKey(Box, MIDICODE(1), route->GetId());
01003 
01004                 if ( route->GetOutDevice() )
01005                         route->GetOutDevice()->NoteOff(Box, MIDICODE(1), MIDICODE(2), route, MidiChannel);
01006 
01007                 break;
01008 
01009         case 0xC0: // Programm Change
01010                 Cd[MidiChannel].Sound = MIDICODE(1);
01011 
01012                 break;
01013 
01014         case 0xB0:
01015                 if ( MIDICODE(1) == 64 ) {
01016                         Cd[MidiChannel].Sustain = MIDICODE(2);
01017 
01018                         if ( route->GetOutDevice() )
01019                                 route->GetOutDevice()->Sustain(Cd[MidiChannel].Sustain, MidiChannel);
01020 
01021                         break;
01022                 } else if ( MIDICODE(1) == 0 ) { // BankSelect MSB
01023                         Cd[MidiChannel].BankSelectMSB = MIDICODE(2);
01024                         break;
01025                 } else if ( MIDICODE(1) == 32 ) {// BankSelectLSB
01026                         Cd[MidiChannel].BankSelectLSB = MIDICODE(2);
01027                         break;
01028                 }
01029 
01030         case 0xA0:
01031 
01032         case 0xD0: // Key Pressure, Controler, Channel Pressure
01033                 //3 ??
01034                 break;
01035 
01036         case 0xF0:
01037                 if ( route->GetOutDevice() )
01038                         route->GetOutDevice()->MidiOut(pData, nData);
01039 
01040         }
01041 
01042         if ( Box >= 0 && route->Active )
01043                 for (int i = 0; i < lMidiCode[MidiStatus >> 5]; i++) {
01044                         MidiAnalysis(Box, MIDICODE(0));
01045                         midiCode >>= 8;
01046                 }
01047 }
01048 
01049 // Routen testen und jenachdem entsprechend Codeverarbeitung
01050 void InMidiFile::Proceed(DWORD midiCode, int track)
01051 {
01052         char DidOut = 0;
01053 
01054         for (Route *R = GetRoutes(); R; R = R->GetNext())
01055                 switch ( R->Type ) {
01056 
01057                 case RTchannel:
01058                         if ( R->Check(midiCode & 0x0F) ) {
01059                                 ProceedRoute(midiCode, R);
01060                                 DidOut = 1;
01061                         }
01062 
01063                         break;
01064 
01065                 case RTstaff:
01066                         if ( R->Check(track) ) {
01067                                 ProceedRoute(midiCode, R);
01068                                 DidOut = 1;
01069                         }
01070 
01071                         break;
01072 
01073                 case RTelse:
01074                         if ( DidOut )
01075                                 break;
01076 
01077                 case RTall:
01078                         ProceedRoute(midiCode, R);
01079                 }
01080 
01081         FLUSH_UPDATE_UI;
01082 }
01083 

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