00001
00089
00090
00091
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
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
00117 #define GET_INDEX(taste,tonsystem) \
00118 ((int)((taste)-( (tonsystem)->anker % (tonsystem)->breite )) \
00119 % (tonsystem)->breite )
00120
00121
00122
00123 #define GET_ABSTAND(taste,tonsystem) \
00124 ( (int)((taste)-( (tonsystem)->anker % (tonsystem)->breite )) \
00125 / (tonsystem)->breite -((int) (tonsystem)->anker \
00126 / (tonsystem)->breite ))
00127
00128
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
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
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
00148 #define zugriff ((unsigned char*) &freq)
00149 #define zgf ((unsigned char*) &pb)
00150
00151
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
00157 #define MIDI_SOUND(i, sound) \
00158 if ( sound != -1 ) MIDI_OUT2(0xC0+i, sound)
00159
00160
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
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
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
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
00302
00303 for (int i = 0; i < 16; i++)
00304 if ( KeyDir[i] >= 16 )
00305 MIDI_OUT3(0x80+i, ton_auf_kanal[i].key, 64);
00306
00307
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
00338 if ( !freq )
00339 return;
00340
00341 int help = r->OTo;
00342
00343 i = r->OFrom;
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 )
00356 {
00357
00358 int AM = 0;
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
00372 MIDI_OUT3(0x80+i, ton_auf_kanal[i].key, 64);
00373
00374
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
00387
00388
00389 if ( (s = cd->Sound) != Cd[i].Sound ) {
00390 MIDI_SOUND(i, s);
00391 Cd[i].Sound = s;
00392 }
00393
00394
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
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 )
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
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
00463
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
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
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
00490 if ( SwitchTone )
00491 MIDI_OUT3(0x90+i, ton_auf_kanal[i].key, 64);
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
00539
00540
00541
00542
00543
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
00671 mutOpenIFstream(is, Name);
00672
00673 if ( mutStreamBad(is) ) {
00674 DEBUGLOG (other, _T("Opening Stream failed"));
00675 Mode = MutaborDeviceCompileError;
00676 InDevChanged = 1;
00677
00678 LAUFZEIT_ERROR1(_("Can not open Midi input file '%s'."), Name.c_str());
00679 return false;
00680 }
00681
00682
00683 char Header[5];
00684
00685 mutReadStream(is,Header, 4);
00686
00687 DWORD l = ReadLength(is);
00688
00689 BYTE a, b;
00690
00691
00692 a = mutGetC(is);
00693
00694 FileType = mutGetC(is);
00695
00696
00697 a = mutGetC(is);
00698
00699 b = mutGetC(is);
00700
00701 nTrack = (((int)a) << 8) + b;
00702
00703
00704 a = mutGetC(is);
00705
00706 b = mutGetC(is);
00707
00708 Speed = (((int)a) << 8) + b;
00709
00710 NRT_Speed = Speed;
00711
00712
00713 DWORD i;
00714
00715 for (i = 6; i < l && !mutStreamEOF(is) && mutStreamGood(is); i++ )
00716 a = mutGetC(is);
00717
00718
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 ( 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
00754 curDelta = (long*)malloc(nTrack*sizeof(long));
00755 TrackPos = (DWORD*)malloc(nTrack*sizeof(DWORD));
00756 StatusByte = (BYTE*)malloc(nTrack*sizeof(BYTE));
00757
00758 Mode = MutaborDeviceStop;
00759
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
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
00789 if ( Mode == MutaborDeviceCompileError )
00790 return;
00791
00792
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
00819 Busy = FALSE;
00820
00821 Mode = MutaborDevicePlay;
00822 }
00823
00824 void InMidiFile::Pause()
00825 {
00826 if ( RealTime )
00827 timer.Stop();
00828
00829
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
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
00868 InDevChanged = 1;
00869 Stop();
00870
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 )
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 )
00914 {
00915 DWORD EventLength = ReadDelta(Track[nr], &(TrackPos[nr]));
00916 TrackPos[nr] += EventLength;
00917 } else if ( SB == 0xFF )
00918 {
00919 a += Track[nr][TrackPos[nr]++] << 8;
00920 DWORD EventLength = ReadDelta(Track[nr], &(TrackPos[nr]));
00921
00922 if ( (a >> 8) == 0x58 )
00923 {
00924 TicksPerQuater = Track[nr][TrackPos[nr]+2];
00925 } else if ( (a >> 8) == 0x51 )
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 )
00944 {
00945 a += Track[nr][TrackPos[nr]++] << 8;
00946 a += Track[nr][TrackPos[nr]++] << 16;
00947 } else if ( SB == 0xF3 )
00948 a += Track[nr][TrackPos[nr]++] << 8;
00949
00950
00951 nData = TrackPos[nr] - OldPos;
00952
00953
00954 if ( a == 0x2FFF ) {
00955 TrackPos[nr] = 0xFFFFFFFF;
00956 return NO_DELTA;
00957 } else
00958 Proceed(a, nr);
00959
00960
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
00973
00974
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:
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:
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:
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 ) {
01023 Cd[MidiChannel].BankSelectMSB = MIDICODE(2);
01024 break;
01025 } else if ( MIDICODE(1) == 32 ) {
01026 Cd[MidiChannel].BankSelectLSB = MIDICODE(2);
01027 break;
01028 }
01029
01030 case 0xA0:
01031
01032 case 0xD0:
01033
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
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