libkmid Library API Documentation

player.cc

00001 /************************************************************************** 00002 00003 player.cc - class MidiPlayer. Plays a set of tracks 00004 This file is part of LibKMid 0.9.5 00005 Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez 00006 LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libkmid.html 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Library General Public 00010 License as published by the Free Software Foundation; either 00011 version 2 of the License, or (at your option) any later version. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Library General Public License for more details. 00017 00018 You should have received a copy of the GNU Library General Public License 00019 along with this library; see the file COPYING.LIB. If not, write to 00020 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00021 Boston, MA 02111-1307, USA. 00022 00023 $Id: player.cc,v 1.43 2002/12/07 16:39:52 waba Exp $ 00024 00025 Send comments and bug fixes to Antonio Larrosa <larrosa@kde.org> 00026 00027 ***************************************************************************/ 00028 #include "player.h" 00029 #include "sndcard.h" 00030 #include "midispec.h" 00031 #include <string.h> 00032 #include <unistd.h> 00033 #include <sys/time.h> 00034 #include "midistat.h" 00035 #include "mt32togm.h" 00036 00037 //#define PLAYERDEBUG 00038 //#define GENERAL_DEBUG_MESSAGES 00039 00040 #define T2MS(ticks) (((double)ticks)*(double)60000L)/((double)tempoToMetronomeTempo(tempo)*(double)info->ticksPerCuarterNote) 00041 00042 #define MS2T(ms) (((ms)*(double)tempoToMetronomeTempo(tempo)*(double)info->ticksPerCuarterNote)/((double)60000L)) 00043 00044 #define REMOVEDUPSTRINGS 00045 00046 MidiPlayer::MidiPlayer(DeviceManager *midi_,PlayerController *pctl) 00047 { 00048 midi=midi_; 00049 info=NULL; 00050 tracks=NULL; 00051 songLoaded=0; 00052 ctl=pctl; 00053 spev=NULL; 00054 na=NULL; 00055 parsesong=true; 00056 generatebeats=false; 00057 } 00058 00059 MidiPlayer::~MidiPlayer() 00060 { 00061 removeSpecialEvents(); 00062 removeSong(); 00063 } 00064 00065 void MidiPlayer::removeSong(void) 00066 { 00067 if ((songLoaded)&&(tracks!=NULL)) 00068 { 00069 #ifdef PLAYERDEBUG 00070 printf("Removing song from memory\n"); 00071 #endif 00072 int i=0; 00073 while (i<info->ntracks) 00074 { 00075 if (tracks[i]!=NULL) delete tracks[i]; 00076 i++; 00077 } 00078 delete tracks; 00079 tracks=NULL; 00080 if (info!=NULL) 00081 { 00082 delete info; 00083 info=NULL; 00084 } 00085 } 00086 songLoaded=0; 00087 } 00088 00089 int MidiPlayer::loadSong(const char *filename) 00090 { 00091 removeSong(); 00092 #ifdef PLAYERDEBUG 00093 printf("Loading Song : %s\n",filename); 00094 #endif 00095 info=new MidiFileInfo; 00096 int ok; 00097 tracks=readMidiFile(filename,info,ok); 00098 if (ok<0) return ok; 00099 if (tracks==NULL) return -4; 00100 00101 parseInfoData(info,tracks,ctl->ratioTempo); 00102 00103 if (parsesong) 00104 { 00105 parseSpecialEvents(); 00106 if (generatebeats) generateBeats(); 00107 } 00108 00109 songLoaded=1; 00110 return 0; 00111 } 00112 00113 void MidiPlayer::insertBeat(SpecialEvent *ev,ulong ms,int num,int den) 00114 { 00115 SpecialEvent *beat=new SpecialEvent; 00116 beat->next=ev->next; 00117 ev->next=beat; 00118 beat->id=1; 00119 beat->type=7; 00120 beat->absmilliseconds=ms; 00121 beat->num=num; 00122 beat->den=den; 00123 } 00124 00125 00126 void MidiPlayer::generateBeats(void) 00127 { 00128 #ifdef PLAYERDEBUG 00129 printf("player::Generating Beats...\n"); 00130 #endif 00131 00132 if (spev==NULL) return; 00133 SpecialEvent *ev=spev; 00134 SpecialEvent *nextev=ev->next; 00135 ulong tempo=(ulong)(500000 * ctl->ratioTempo); 00136 int i=1; 00137 int num=4; 00138 int den=4; 00139 // ulong beatstep=((double)tempo*4/(den*1000)); 00140 // ulong beatstep=T2MS(info->ticksPerCuarterNote*(4/den)); 00141 double ticksleft=(((double)info->ticksPerCuarterNote*4)/den); 00142 00143 double beatstep=T2MS(ticksleft); 00144 double nextbeatms=0; 00145 double lastbeatms=0; 00146 double measurems=0; 00147 00148 while (nextev!=NULL) 00149 { 00150 switch (ev->type) 00151 { 00152 case (0): // End of list 00153 { 00154 };break; 00155 case (1): // Text 00156 case (2): // Lyrics 00157 { 00158 };break; 00159 case (3): // Change Tempo 00160 { 00161 lastbeatms=ev->absmilliseconds; 00162 ticksleft=MS2T(nextbeatms-lastbeatms); 00163 tempo=ev->tempo; 00164 nextbeatms=lastbeatms+T2MS(ticksleft); 00165 // printf("Change at %lu to %d\n",ev->absmilliseconds,ev->tempo); 00166 // beatstep=((double)tempo*4/(den*1000)); 00167 beatstep=T2MS(((static_cast<double>(info->ticksPerCuarterNote)*4)/den)); 00168 };break; 00169 case (6): // Change number of beats per measure 00170 { 00171 num=ev->num; 00172 i=1; 00173 den=ev->den; 00174 // printf("Change at %lu to %d/%d\n",ev->absmilliseconds,num,den); 00175 // beatstep=((double)tempo*4/(den*1000)); 00176 // beatstep=T2MS(info->ticksPerCuarterNote*(4/den)); 00177 beatstep=T2MS((((double)info->ticksPerCuarterNote*4)/den)); 00178 nextbeatms=ev->absmilliseconds; 00179 };break; 00180 }; 00181 if (nextev->absmilliseconds>nextbeatms) 00182 { 00183 //printf("Adding %d,%d\n",num,tot); 00184 //printf("beat at %g , %d/%d\n",nextbeatms,i,num); 00185 //printf(" %ld %d\n",nextev->absmilliseconds,nextev->type); 00186 if (i == 1) { 00187 measurems=nextbeatms; 00188 } 00189 insertBeat(ev, static_cast<unsigned long>(nextbeatms), i++, num); 00190 if (i > num) { 00191 i=1; 00192 } 00193 lastbeatms=nextbeatms; 00194 nextbeatms+=beatstep; 00195 // nextbeatms=measurems+beatstep*i; 00196 00197 ticksleft = ( (static_cast<double>(info->ticksPerCuarterNote)*4) / den); 00198 00199 } 00200 00201 ev=ev->next; 00202 nextev=ev->next; 00203 } 00204 00205 /* ev==NULL doesn't indicate the end of the song, so continue generating beats */ 00206 00207 if (ev!=NULL) 00208 { 00209 if (ev->type==0) 00210 { 00211 ev=spev; 00212 /* Looking if ev->next is NULL is not needed because 00213 we are sure that a ev->type == 0 exists, we just have 00214 to assure that the first spev is not the only one */ 00215 if (ev->next!=NULL) 00216 while (ev->next->type!=0) ev=ev->next; 00217 } 00218 while (nextbeatms<info->millisecsTotal) 00219 { 00220 // printf("beat2 at %g , %d/%d\n",nextbeatms,i,num); 00221 if (i==1) measurems=nextbeatms; 00222 insertBeat(ev, static_cast<unsigned long>(nextbeatms), i++, num); 00223 if (i>num) i=1; 00224 nextbeatms+=beatstep; 00225 ev=ev->next; 00226 } 00227 } 00228 00229 /* Regenerate IDs */ 00230 00231 ev=spev; 00232 i=1; 00233 while (ev!=NULL) 00234 { 00235 ev->id=i++; 00236 ev=ev->next; 00237 } 00238 00239 00240 #ifdef PLAYERDEBUG 00241 printf("player::Beats Generated\n"); 00242 #endif 00243 00244 } 00245 00246 void MidiPlayer::removeSpecialEvents(void) 00247 { 00248 SpecialEvent * ev=spev; 00249 while (spev!=NULL) 00250 { 00251 ev=spev->next; 00252 delete spev; 00253 spev=ev; 00254 } 00255 delete na; 00256 na=0; 00257 } 00258 00259 void MidiPlayer::parseSpecialEvents(void) 00260 { 00261 #ifdef PLAYERDEBUG 00262 printf("player::Parsing...\n"); 00263 #endif 00264 removeSpecialEvents(); 00265 spev=new SpecialEvent; 00266 if (spev==NULL) return; 00267 SpecialEvent *pspev=spev; 00268 pspev->type=0; 00269 pspev->ticks=0; 00270 if (na) delete na; 00271 na=new NoteArray(); 00272 if (!na) { delete spev; spev=0L; return; }; 00273 int trk; 00274 int minTrk; 00275 double minTime=0; 00276 double maxTime; 00277 ulong tempo=(ulong)(500000 * (ctl->ratioTempo)); 00278 ulong firsttempo=0; 00279 for (int i=0;i<info->ntracks;i++) 00280 { 00281 tracks[i]->init(); 00282 tracks[i]->changeTempo(tempo); 00283 } 00284 MidiEvent *ev=new MidiEvent; 00285 //ulong mspass; 00286 double prevms=0; 00287 int spev_id=1; 00288 int j; 00289 int parsing=1; 00290 #ifdef REMOVEDUPSTRINGS 00291 char lasttext[1024]; 00292 ulong lasttexttime=0; 00293 lasttext[0]=0; 00294 int lasttexttype=0; 00295 #endif 00296 while (parsing) 00297 { 00298 prevms=minTime; 00299 trk=0; 00300 minTrk=0; 00301 maxTime=minTime + 2 * 60000L; 00302 minTime=maxTime; 00303 parsing=0; 00304 while (trk<info->ntracks) 00305 { 00306 if (tracks[trk]->absMsOfNextEvent()<minTime) 00307 { 00308 minTrk=trk; 00309 minTime=tracks[minTrk]->absMsOfNextEvent(); 00310 parsing=1; 00311 } 00312 trk++; 00313 } 00314 // if ((minTime==maxTime)) 00315 if (parsing==0) 00316 { 00317 // parsing=0; 00318 #ifdef PLAYERDEBUG 00319 printf("END of parsing\n"); 00320 #endif 00321 } 00322 else 00323 { 00324 // mspass=(ulong)(minTime-prevms); 00325 trk=0; 00326 while (trk<info->ntracks) 00327 { 00328 tracks[trk]->currentMs(minTime); 00329 trk++; 00330 } 00331 } 00332 trk=minTrk; 00333 tracks[trk]->readEvent(ev); 00334 switch (ev->command) 00335 { 00336 case (MIDI_NOTEON) : 00337 if (ev->vel==0) na->add((ulong)minTime,ev->chn,0, ev->note); 00338 else na->add((ulong)minTime,ev->chn,1,ev->note); 00339 break; 00340 case (MIDI_NOTEOFF) : 00341 na->add((ulong)minTime,ev->chn,0, ev->note); 00342 break; 00343 case (MIDI_PGM_CHANGE) : 00344 na->add((ulong)minTime,ev->chn, 2,ev->patch); 00345 break; 00346 case (MIDI_SYSTEM_PREFIX) : 00347 { 00348 if ((ev->command|ev->chn)==META_EVENT) 00349 { 00350 switch (ev->d1) 00351 { 00352 case (1) : 00353 case (5) : 00354 { 00355 if (pspev!=NULL) 00356 { 00357 pspev->absmilliseconds=(ulong)minTime; 00358 pspev->type=ev->d1; 00359 pspev->id=spev_id++; 00360 #ifdef PLAYERDEBUG 00361 printf("ev->length %ld\n",ev->length); 00362 00363 #endif 00364 strncpy(pspev->text,(char *)ev->data, 00365 (ev->length>1024)? (1023) : (ev->length) ); 00366 pspev->text[(ev->length>1024)? (1023):(ev->length)]=0; 00367 #ifdef PLAYERDEBUG 00368 printf("(%s)(%s)\n",pspev->text,lasttext); 00369 #endif 00370 #ifdef REMOVEDUPSTRINGS 00371 if ((strcmp(pspev->text,lasttext)!=0)||(pspev->absmilliseconds!=lasttexttime)||(pspev->type!=lasttexttype)) 00372 { 00373 lasttexttime=pspev->absmilliseconds; 00374 lasttexttype=pspev->type; 00375 strncpy(lasttext, pspev->text, 1024); 00376 lasttext[1023] = 0; 00377 #endif 00378 pspev->next=new SpecialEvent; 00379 #ifdef PLAYERDEBUG 00380 if (pspev->next==NULL) printf("pspev->next=NULL\n"); 00381 #endif 00382 pspev=pspev->next; 00383 #ifdef REMOVEDUPSTRINGS 00384 } 00385 #endif 00386 } 00387 } 00388 break; 00389 case (ME_SET_TEMPO) : 00390 { 00391 if (pspev!=NULL) 00392 { 00393 pspev->absmilliseconds=(ulong)minTime; 00394 pspev->type=3; 00395 pspev->id=spev_id++; 00396 tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2])) * ctl->ratioTempo); 00397 pspev->tempo=tempo; 00398 if (firsttempo==0) firsttempo=tempo; 00399 for (j=0;j<info->ntracks;j++) 00400 { 00401 tracks[j]->changeTempo(tempo); 00402 } 00403 pspev->next=new SpecialEvent; 00404 pspev=pspev->next; 00405 } 00406 } 00407 break; 00408 case (ME_TIME_SIGNATURE) : 00409 { 00410 if (pspev!=NULL) 00411 { 00412 pspev->absmilliseconds=(ulong)minTime; 00413 pspev->type=6; 00414 pspev->id=spev_id++; 00415 pspev->num=ev->d2; 00416 pspev->den=ev->d3; 00417 pspev->next=new SpecialEvent; 00418 pspev=pspev->next; 00419 } 00420 } 00421 break; 00422 } 00423 } 00424 } 00425 break; 00426 } 00427 } 00428 00429 delete ev; 00430 pspev->type=0; 00431 pspev->absmilliseconds=(ulong)prevms; 00432 pspev->next=NULL; 00433 if (firsttempo==0) firsttempo=tempo; 00434 ctl->tempo=firsttempo; 00435 00436 //writeSPEV(); 00437 for (int i=0;i<info->ntracks;i++) 00438 { 00439 tracks[i]->init(); 00440 } 00441 } 00442 00443 /* 00444 NoteArray *MidiPlayer::parseNotes(void) 00445 { 00446 #ifdef PLAYERDEBUG 00447 printf("player::Parsing Notes...\n"); 00448 #endif 00449 NoteArray *na=new NoteArray(); 00450 int trk; 00451 int minTrk; 00452 double minTime=0; 00453 double maxTime; 00454 for (int i=0;i<info->ntracks;i++) 00455 { 00456 tracks[i]->init(); 00457 }; 00458 ulong tempo=1000000; 00459 ulong tmp; 00460 Midi_event *ev=new Midi_event; 00461 //ulong mspass; 00462 double prevms=0; 00463 int j; 00464 int parsing=1; 00465 while (parsing) 00466 { 00467 prevms=minTime; 00468 trk=0; 00469 minTrk=0; 00470 maxTime=minTime + 2 * 60000L; 00471 minTime=maxTime; 00472 while (trk<info->ntracks) 00473 { 00474 if (tracks[trk]->absMsOfNextEvent()<minTime) 00475 { 00476 minTrk=trk; 00477 minTime=tracks[minTrk]->absMsOfNextEvent(); 00478 }; 00479 trk++; 00480 }; 00481 if ((minTime==maxTime)) 00482 { 00483 parsing=0; 00484 #ifdef PLAYERDEBUG 00485 printf("END of parsing\n"); 00486 #endif 00487 } 00488 else 00489 { 00490 // mspass=(ulong)(minTime-prevms); 00491 trk=0; 00492 while (trk<info->ntracks) 00493 { 00494 tracks[trk]->currentMs(minTime); 00495 trk++; 00496 }; 00497 }; 00498 trk=minTrk; 00499 tracks[trk]->readEvent(ev); 00500 if (ev->command==MIDI_NOTEON) 00501 { 00502 if (ev->vel==0) {printf("note off at %g\n",minTime);na->add((ulong)minTime,ev->chn,0, ev->note);} 00503 else {printf("note on at %g\n",minTime);na->add((ulong)minTime,ev->chn,1,ev->note);} 00504 } 00505 else 00506 if (ev->command==MIDI_NOTEOFF) na->add((ulong)minTime,ev->chn,0, ev->note); 00507 if (ev->command==MIDI_PGM_CHANGE) na->add((ulong)minTime,ev->chn, 2,ev->patch); 00508 if (ev->command==MIDI_SYSTEM_PREFIX) 00509 { 00510 if (((ev->command|ev->chn)==META_EVENT)&&(ev->d1==ME_SET_TEMPO)) 00511 { 00512 tempo=(ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]); 00513 for (j=0;j<info->ntracks;j++) 00514 { 00515 tracks[j]->changeTempo(tempo); 00516 }; 00517 }; 00518 }; 00519 00520 }; 00521 00522 delete ev; 00523 for (int i=0;i<info->ntracks;i++) 00524 { 00525 tracks[i]->init(); 00526 }; 00527 return na; 00528 }; 00529 */ 00530 00531 void MidiPlayer::play(bool calloutput,void output(void)) 00532 { 00533 #ifdef PLAYERDEBUG 00534 printf("Playing...\n"); 00535 #endif 00536 00537 if (midi->midiPorts()+midi->synthDevices()==0) 00538 { 00539 fprintf(stderr,"Player :: There are no midi ports !\n"); 00540 ctl->error=1; 00541 return; 00542 } 00543 00544 midi->openDev(); 00545 if (midi->ok()==0) 00546 { 00547 fprintf(stderr,"Player :: Couldn't play !\n"); 00548 ctl->error=1; 00549 return; 00550 } 00551 midi->setVolumePercentage(ctl->volumepercentage); 00552 midi->initDev(); 00553 // parsePatchesUsed(tracks,info,ctl->gm); 00554 midi->setPatchesToUse(info->patchesUsed); 00555 00556 int trk; 00557 int minTrk; 00558 double minTime=0; 00559 double maxTime; 00560 int i; 00561 ulong tempo=(ulong)(500000 * ctl->ratioTempo); 00562 for (i=0;i<info->ntracks;i++) 00563 { 00564 tracks[i]->init(); 00565 tracks[i]->changeTempo(tempo); 00566 } 00567 00568 midi->tmrStart(info->ticksPerCuarterNote); 00569 MidiEvent *ev=new MidiEvent; 00570 ctl->ev=ev; 00571 ctl->ticksTotal=info->ticksTotal; 00572 ctl->ticksPlayed=0; 00573 //ctl->millisecsPlayed=0; 00574 ulong ticksplayed=0; 00575 double absTimeAtChangeTempo=0; 00576 double absTime=0; 00577 double diffTime=0; 00578 MidiStatus *midistat; 00579 //ulong mspass; 00580 double prevms=0; 00581 int j; 00582 int halt=0; 00583 ctl->tempo=tempo; 00584 ctl->num=4; 00585 ctl->den=4; 00586 int playing; 00587 ctl->paused=0; 00588 if ((ctl->message!=0)&&(ctl->message & PLAYER_SETPOS)) 00589 { 00590 ctl->moving=1; 00591 ctl->message&=~PLAYER_SETPOS; 00592 midi->sync(1); 00593 midi->tmrStop(); 00594 midi->closeDev(); 00595 midistat = new MidiStatus(); 00596 setPos(ctl->gotomsec,midistat); 00597 minTime=ctl->gotomsec; 00598 prevms=(ulong)minTime; 00599 midi->openDev(); 00600 midi->tmrStart(info->ticksPerCuarterNote); 00601 diffTime=ctl->gotomsec; 00602 midistat->sendData(midi,ctl->gm); 00603 delete midistat; 00604 midi->setPatchesToUse(info->patchesUsed); 00605 ctl->moving=0; 00606 } else 00607 for (i=0;i<16;i++) 00608 { 00609 if (ctl->forcepgm[i]) 00610 { 00611 midi->chnPatchChange(i, ctl->pgm[i]); 00612 } 00613 } 00614 00615 timeval begintv; 00616 gettimeofday(&begintv, NULL); 00617 ctl->beginmillisec=begintv.tv_sec*1000+begintv.tv_usec/1000; 00618 ctl->OK=1; 00619 ctl->playing=playing=1; 00620 00621 while (playing) 00622 { 00623 /* 00624 if (ctl->message!=0) 00625 { 00626 if (ctl->message & PLAYER_DOPAUSE) 00627 { 00628 diffTime=minTime; 00629 ctl->message&=~PLAYER_DOPAUSE; 00630 midi->sync(1); 00631 midi->tmrStop(); 00632 ctl->paused=1; 00633 midi->closeDev(); 00634 while ((ctl->paused)&&(!(ctl->message&PLAYER_DOSTOP)) 00635 &&(!(ctl->message&PLAYER_HALT))) sleep(1); 00636 midi->openDev(); 00637 midi->tmrStart(); 00638 ctl->OK=1; 00639 printf("Continue playing ... \n"); 00640 }; 00641 if (ctl->message & PLAYER_DOSTOP) 00642 { 00643 ctl->message&=~PLAYER_DOSTOP; 00644 playing=0; 00645 }; 00646 if (ctl->message & PLAYER_HALT) 00647 { 00648 ctl->message&=~PLAYER_HALT; 00649 playing=0; 00650 halt=1; 00651 }; 00652 if (ctl->message & PLAYER_SETPOS) 00653 { 00654 ctl->moving=1; 00655 ctl->message&=~PLAYER_SETPOS; 00656 midi->sync(1); 00657 midi->tmrStop(); 00658 midi->closeDev(); 00659 midistat = new midiStat(); 00660 SetPos(ctl->gotomsec,midistat); 00661 minTime=ctl->gotomsec; 00662 prevms=(ulong)minTime; 00663 midi->openDev(); 00664 midi->tmrStart(); 00665 diffTime=ctl->gotomsec; 00666 ctl->moving=0; 00667 midistat->sendData(midi,ctl->gm); 00668 delete midistat; 00669 ctl->OK=1; 00670 while (ctl->OK==1) ; 00671 ctl->moving=0; 00672 }; 00673 }; 00674 */ 00675 prevms=minTime; 00676 // ctl->millisecsPlayed=minTime; 00677 trk=0; 00678 minTrk=0; 00679 maxTime=minTime + 120000L /* milliseconds */; 00680 minTime=maxTime; 00681 playing=0; 00682 while (trk<info->ntracks) 00683 { 00684 if (tracks[trk]->absMsOfNextEvent()<minTime) 00685 { 00686 minTrk=trk; 00687 minTime=tracks[minTrk]->absMsOfNextEvent(); 00688 playing=1; 00689 } 00690 trk++; 00691 } 00692 #ifdef PLAYERDEBUG 00693 printf("minTime %g\n",minTime); 00694 #endif 00695 // if ((minTime==maxTime)/* || (minTicks> 60000L)*/) 00696 if (playing==0) 00697 { 00698 // playing=0; 00699 #ifdef PLAYERDEBUG 00700 printf("END of playing\n"); 00701 #endif 00702 } 00703 else 00704 { 00705 // mspass=(ulong)(minTime-prevms); 00706 trk=0; 00707 while (trk<info->ntracks) 00708 { 00709 tracks[trk]->currentMs(minTime); 00710 trk++; 00711 } 00712 midi->wait(minTime-diffTime); 00713 } 00714 trk=minTrk; 00715 tracks[trk]->readEvent(ev); 00716 switch (ev->command) 00717 { 00718 case (MIDI_NOTEON) : 00719 midi->noteOn(ev->chn, ev->note, ev->vel);break; 00720 case (MIDI_NOTEOFF): 00721 midi->noteOff(ev->chn, ev->note, ev->vel);break; 00722 case (MIDI_KEY_PRESSURE) : 00723 midi->keyPressure(ev->chn, ev->note,ev->vel);break; 00724 case (MIDI_PGM_CHANGE) : 00725 if (!ctl->forcepgm[ev->chn]) 00726 midi->chnPatchChange(ev->chn, (ctl->gm==1)?(ev->patch):(MT32toGM[ev->patch]));break; 00727 case (MIDI_CHN_PRESSURE) : 00728 midi->chnPressure(ev->chn, ev->vel);break; 00729 case (MIDI_PITCH_BEND) : 00730 midi->chnPitchBender(ev->chn, ev->d1,ev->d2);break; 00731 case (MIDI_CTL_CHANGE) : 00732 midi->chnController(ev->chn, ev->ctl,ev->d1);break; 00733 case (MIDI_SYSTEM_PREFIX) : 00734 if ((ev->command|ev->chn)==META_EVENT) 00735 { 00736 if ((ev->d1==5)||(ev->d1==1)) 00737 { 00738 ctl->SPEVplayed++; 00739 } 00740 if (ev->d1==ME_SET_TEMPO) 00741 { 00742 absTimeAtChangeTempo=absTime; 00743 ticksplayed=0; 00744 ctl->SPEVplayed++; 00745 tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]))*ctl->ratioTempo); 00746 #ifdef PLAYERDEBUG 00747 printf("Tempo : %ld %g (ratio : %g)\n",tempo,tempoToMetronomeTempo(tempo),ctl->ratioTempo); 00748 #endif 00749 midi->tmrSetTempo((int)tempoToMetronomeTempo(tempo)); 00750 ctl->tempo=tempo; 00751 for (j=0;j<info->ntracks;j++) 00752 { 00753 tracks[j]->changeTempo(tempo); 00754 } 00755 } 00756 if (ev->d1==ME_TIME_SIGNATURE) 00757 { 00758 ctl->num=ev->d2; 00759 ctl->den=ev->d3; 00760 ctl->SPEVplayed++; 00761 } 00762 } 00763 break; 00764 } 00765 if (calloutput) 00766 { 00767 midi->sync(); 00768 output(); 00769 } 00770 00771 } 00772 ctl->ev=NULL; 00773 delete ev; 00774 #ifdef PLAYERDEBUG 00775 printf("Syncronizing ...\n"); 00776 #endif 00777 if (halt) 00778 midi->sync(1); 00779 else 00780 midi->sync(); 00781 #ifdef PLAYERDEBUG 00782 printf("Closing device ...\n"); 00783 #endif 00784 midi->allNotesOff(); 00785 midi->closeDev(); 00786 ctl->playing=0; 00787 #ifdef PLAYERDEBUG 00788 printf("Bye...\n"); 00789 #endif 00790 ctl->OK=1; 00791 ctl->finished=1; 00792 } 00793 00794 00795 void MidiPlayer::setPos(ulong gotomsec,MidiStatus *midistat) 00796 { 00797 int trk,minTrk; 00798 ulong tempo=(ulong)(500000 * ctl->ratioTempo); 00799 double minTime=0,maxTime,prevms=0; 00800 int i,j,likeplaying=1; 00801 00802 MidiEvent *ev=new MidiEvent; 00803 ctl->SPEVplayed=0; 00804 for (i=0;i<info->ntracks;i++) 00805 { 00806 tracks[i]->init(); 00807 tracks[i]->changeTempo(tempo); 00808 } 00809 00810 for (i=0;i<16;i++) 00811 { 00812 if (ctl->forcepgm[i]) midistat->chnPatchChange(i, ctl->pgm[i]); 00813 } 00814 00815 while (likeplaying) 00816 { 00817 trk=0; 00818 minTrk=0; 00819 maxTime=minTime + 120000L; /*milliseconds (2 minutes)*/ 00820 minTime=maxTime; 00821 while (trk<info->ntracks) 00822 { 00823 if (tracks[trk]->absMsOfNextEvent()<minTime) 00824 { 00825 minTrk=trk; 00826 minTime=tracks[minTrk]->absMsOfNextEvent(); 00827 } 00828 trk++; 00829 } 00830 if (minTime==maxTime) 00831 { 00832 likeplaying=0; 00833 #ifdef GENERAL_DEBUG_MESSAGES 00834 printf("END of likeplaying\n"); 00835 #endif 00836 } 00837 else 00838 { 00839 if (minTime>=gotomsec) 00840 { 00841 prevms=gotomsec; 00842 likeplaying=0; 00843 #ifdef GENERAL_DEBUG_MESSAGES 00844 printf("Position reached !! \n"); 00845 #endif 00846 minTime=gotomsec; 00847 } 00848 else 00849 { 00850 prevms=minTime; 00851 } 00852 trk=0; 00853 while (trk<info->ntracks) 00854 { 00855 tracks[trk]->currentMs(minTime); 00856 trk++; 00857 } 00858 } 00859 00860 if (likeplaying) 00861 { 00862 trk=minTrk; 00863 tracks[trk]->readEvent(ev); 00864 switch (ev->command) 00865 { 00866 /* case (MIDI_NOTEON) : 00867 midistat->noteOn(ev->chn, ev->note, ev->vel);break; 00868 case (MIDI_NOTEOFF): 00869 midistat->noteOff(ev->chn, ev->note, ev->vel);break; 00870 case (MIDI_KEY_PRESSURE) : 00871 midistat->keyPressure(ev->chn, ev->note,ev->vel);break; 00872 */ 00873 case (MIDI_PGM_CHANGE) : 00874 if (!ctl->forcepgm[ev->chn]) midistat->chnPatchChange(ev->chn, ev->patch);break; 00875 case (MIDI_CHN_PRESSURE) : 00876 midistat->chnPressure(ev->chn, ev->vel);break; 00877 case (MIDI_PITCH_BEND) : 00878 midistat->chnPitchBender(ev->chn, ev->d1,ev->d2);break; 00879 case (MIDI_CTL_CHANGE) : 00880 midistat->chnController(ev->chn, ev->ctl,ev->d1);break; 00881 case (MIDI_SYSTEM_PREFIX) : 00882 if ((ev->command|ev->chn)==META_EVENT) 00883 { 00884 if ((ev->d1==5)||(ev->d1==1)) 00885 { 00886 ctl->SPEVplayed++; 00887 } 00888 if (ev->d1==ME_SET_TEMPO) 00889 { 00890 ctl->SPEVplayed++; 00891 tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]))*ctl->ratioTempo); 00892 00893 midistat->tmrSetTempo((int)tempoToMetronomeTempo(tempo)); 00894 for (j=0;j<info->ntracks;j++) 00895 { 00896 tracks[j]->changeTempo(tempo); 00897 } 00898 } 00899 if (ev->d1==ME_TIME_SIGNATURE) 00900 { 00901 ctl->num=ev->d2; 00902 ctl->den=ev->d3; 00903 ctl->SPEVplayed++; 00904 } 00905 } 00906 break; 00907 } 00908 } 00909 } 00910 delete ev; 00911 ctl->tempo=tempo; 00912 } 00913 00914 00915 void MidiPlayer::debugSpecialEvents(void) 00916 { 00917 SpecialEvent *pspev=spev; 00918 printf("**************************************\n"); 00919 while ((pspev!=NULL)&&(pspev->type!=0)) 00920 { 00921 printf("t:%d ticks:%d diff:%ld abs:%ld s:%s tempo:%ld\n",pspev->type,pspev->ticks,pspev->diffmilliseconds,pspev->absmilliseconds,pspev->text,pspev->tempo); 00922 pspev=pspev->next; 00923 } 00924 00925 } 00926 00927 void MidiPlayer::setParseSong(bool b) 00928 { 00929 parsesong=b; 00930 } 00931 00932 void MidiPlayer::setGenerateBeats(bool b) 00933 { 00934 generatebeats=b; 00935 } 00936 00937 void MidiPlayer::setTempoRatio(double ratio) 00938 { 00939 if (songLoaded) 00940 { 00941 ctl->ratioTempo=ratio; 00942 parseInfoData(info,tracks,ctl->ratioTempo); 00943 if (parsesong) 00944 { 00945 parseSpecialEvents(); 00946 if (generatebeats) generateBeats(); 00947 00948 } 00949 } 00950 else 00951 { 00952 ctl->tempo=(ulong)((ctl->tempo*ctl->ratioTempo)/ratio); 00953 ctl->ratioTempo=ratio; 00954 } 00955 00956 } 00957 00958 #undef T2MS 00959 #undef MS2T
KDE Logo
This file is part of the documentation for libkmid Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Aug 30 22:55:31 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003