summaryrefslogtreecommitdiffstats
path: root/libkmid/track.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libkmid/track.cc')
-rw-r--r--libkmid/track.cc566
1 files changed, 0 insertions, 566 deletions
diff --git a/libkmid/track.cc b/libkmid/track.cc
deleted file mode 100644
index ccaaf69d2..000000000
--- a/libkmid/track.cc
+++ /dev/null
@@ -1,566 +0,0 @@
-/**************************************************************************
-
- track.cc - class track, which has a midi file track and its events
- This file is part of LibKMid 0.9.5
- Copyright (C) 1997,98,99,2000 Antonio Larrosa Jimenez
- LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libkmid.html
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-
- Send comments and bug fixes to Antonio Larrosa <[email protected]>
-
-***************************************************************************/
-
-#include "track.h"
-#include <stdlib.h>
-#include "sndcard.h"
-#include "midispec.h"
-#include "midfile.h"
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#define T2MS(ticks) (((double)ticks)*(double)60000L)/((double)tempoToMetronomeTempo(tempo)*(double)tPCN)
-
-#define MS2T(ms) (((ms)*(double)tempoToMetronomeTempo(tempo)*(double)tPCN)/((double)60000L))
-
-#define PEDANTIC_TRACK
-#define CHANGETEMPO_ONLY_IN_TRACK0
-//#define TRACKDEBUG
-//#define TRACKDEBUG2
-
-MidiTrack::MidiTrack(FILE *file,int tpcn,int Id)
-{
- id=Id;
- tPCN=tpcn;
- currentpos=0;
- size=0;
- data=0L;
- tempo=1000000;
- if (feof(file))
- {
- clear();
- return;
- };
- size=readLong(file);
-#ifdef TRACKDEBUG
- printf("Track %d : Size %ld\n",id,size);
-#endif
- data=new uchar[size];
- if (data==NULL)
- {
- perror("track: Not enough memory ?");
- exit(-1);
- }
- ulong rsize=0;
- if ((rsize=fread(data,1,size,file))!=size)
- {
- fprintf(stderr,"track (%d): File is corrupt : Couldn't load track (%ld!=%ld) !!\n", id, rsize, size);
- size=rsize;
- };
- /*
- ptrdata=data;
- current_ticks=0;
- delta_ticks=readVariableLengthValue();
- wait_ticks=delta_ticks;
- endoftrack=0;
- */
- init();
-}
-
-MidiTrack::~MidiTrack()
-{
- delete data;
- endoftrack=1;
- currentpos=0;
- size=0;
-}
-
-int MidiTrack::power2to(int i)
-{
- return 1<<i;
-}
-
-ulong MidiTrack::readVariableLengthValue(void)
-{
- ulong dticks=0;
-
- while ((*ptrdata) & 0x80)
- {
-#ifdef PEDANTIC_TRACK
- if (currentpos>=size)
- {
- endoftrack=1;
- fprintf(stderr, "track (%d) : EndofTrack found by accident !\n",id);
- delta_ticks = wait_ticks = ~0;
- time_at_next_event=10000 * 60000L;
- return 0;
- }
- else
-#endif
- {
- dticks=(dticks << 7) | (*ptrdata) & 0x7F;
- ptrdata++;currentpos++;
- }
-
- }
- dticks=((dticks << 7) | (*ptrdata) & 0x7F);
- ptrdata++;currentpos++;
-
-#ifdef PEDANTIC_TRACK
-
- if (currentpos>=size)
- {
- endoftrack=1;
- fprintf(stderr,"track (%d): EndofTrack found by accident 2 !\n",id);
- dticks=0;
- delta_ticks = wait_ticks = ~0;
- time_at_next_event=10000 * 60000L;
- return 0;
- }
-#endif
-#ifdef TRACKDEBUG
- printfdebug("track(%d): DTICKS : %ld\n",id,dticks);
- usleep(10);
-#endif
- return dticks;
-}
-
-int MidiTrack::ticksPassed (ulong ticks)
-{
- if (endoftrack==1) return 0;
- if (ticks>wait_ticks)
- {
- printfdebug("track (%d): ERROR : TICKS PASSED > WAIT TICKS\n", id);
- return 1;
- }
- wait_ticks-=ticks;
- return 0;
-}
-
-int MidiTrack::msPassed (ulong ms)
-{
- if (endoftrack==1) return 0;
- current_time+=ms;
- //fprintf(stderr, "old + %ld = CURR %g ", ms,current_time);
- if ( current_time>time_at_next_event )
- {
- fprintf(stderr, "track (%d): ERROR : MS PASSED > WAIT MS\n", id);
- return 1;
- }
-#ifdef TRACKDEBUG
- if (current_time==time_at_next_event) printfdebug("track(%d): _OK_",id);
-#endif
- return 0;
-}
-
-int MidiTrack::currentMs(double ms)
-{
- if (endoftrack==1) return 0;
- current_time=ms;
- //printfdebug("CURR %g",current_time);
-#ifdef PEDANTIC_TRACK
- if (current_time>time_at_next_event)
- {
- fprintf(stderr,"track(%d): ERROR : MS PASSED > WAIT MS\n", id);
- exit(-1);
- return 1;
- }
-#endif
- return 0;
-}
-
-void MidiTrack::readEvent(MidiEvent *ev)
-{
- int i,j;
- if (endoftrack==1)
- {
- ev->command=0;
- return;
- }
- /*
- printfdebug("...... %d\n",id);
- printfdebug("current : %g , tane : %g\n",current_time,time_at_next_event);
- printfdebug("......\n");
- */
- int skip_event=0;
- current_time=time_at_next_event;
- if (((*ptrdata)&0x80)!=0)
- {
- ev->command=(*ptrdata);
- ptrdata++;currentpos++;
- lastcommand=ev->command;
- }
- else
- {
- ev->command=lastcommand;
- }
-
-#ifdef PEDANTIC_TRACK
- if (currentpos>=size)
- {
- endoftrack=1;
- delta_ticks = wait_ticks = ~0;
- time_at_next_event=10000 * 60000L;
- ev->command=MIDI_SYSTEM_PREFIX;
- ev->chn=0xF;
- ev->d1=ME_END_OF_TRACK;
- fprintf(stderr, "track (%d): EndofTrack found by accident 3\n",id);
- return;
- }
-#endif
-
- ev->chn=ev->command & 0xF;
- ev->command=ev->command & 0xF0;
- switch (ev->command)
- {
- case (MIDI_NOTEON) :
- ev->note = *ptrdata;ptrdata++;currentpos++;
- ev->vel = *ptrdata;ptrdata++;currentpos++;
- if (ev->vel==0)
- note[ev->chn][ev->note]=FALSE;
- else
- note[ev->chn][ev->note]=TRUE;
-
-#ifdef TRACKDEBUG2
- if (ev->chn==6) {
- if (ev->vel==0) printfdebug("Note Onf\n");
- else printfdebug("Note On\n");
- };
-#endif
- break;
- case (MIDI_NOTEOFF) :
-#ifdef TRACKDEBUG2
- if (ev->chn==6) printfdebug("Note Off\n");
-#endif
- ev->note = *ptrdata;ptrdata++;currentpos++;
- ev->vel = *ptrdata;ptrdata++;currentpos++;
- note[ev->chn][ev->note]=FALSE;
-
- break;
- case (MIDI_KEY_PRESSURE) :
-#ifdef TRACKDEBUG2
- if (ev->chn==6) printfdebug ("Key press\n");
-#endif
- ev->note = *ptrdata;ptrdata++;currentpos++;
- ev->vel = *ptrdata;ptrdata++;currentpos++;
- break;
- case (MIDI_PGM_CHANGE) :
-#ifdef TRACKDEBUG2
- if (ev->chn==6) printfdebug ("Pgm\n");
-#endif
- ev->patch = *ptrdata;ptrdata++;currentpos++;
- break;
- case (MIDI_CHN_PRESSURE) :
-#ifdef TRACKDEBUG2
- if (ev->chn==6) printfdebug ("Chn press\n");
-#endif
- ev->vel = *ptrdata;ptrdata++;currentpos++;
- break;
- case (MIDI_PITCH_BEND) :
-#ifdef TRACKDEBUG2
- if (ev->chn==6) printfdebug ("Pitch\n");
-#endif
- ev->d1 = *ptrdata;ptrdata++;currentpos++;
- ev->d2 = *ptrdata;ptrdata++;currentpos++;
- break;
- case (MIDI_CTL_CHANGE) :
-#ifdef TRACKDEBUG2
- if (ev->chn==6) printfdebug (stderr, "Ctl\n");
-#endif
- ev->ctl = *ptrdata;ptrdata++; currentpos++;
- ev->d1 = *ptrdata;ptrdata++;currentpos++;
- /*
- switch (ev->ctl)
- {
- case (96) : printfdebug("RPN Increment\n");break;
- case (97) : printfdebug("RPN Decrement\n");break;
- case (98) : printfdebug("nRPN 98 %d\n",ev->d1);break;
- case (99) : printfdebug("nRPN 99 %d\n",ev->d1);break;
- case (100) : printfdebug("RPN 100 %d\n",ev->d1);break;
- case (101) : printfdebug("RPN 101 %d\n",ev->d1);break;
- };
- */
- break;
-
- case (MIDI_SYSTEM_PREFIX) :
-#ifdef TRACKDEBUG2
- if (ev->chn==6) printfdebug ("Sys Prefix\n");
-#endif
- switch ((ev->command|ev->chn))
- {
- case (0xF0) :
- case (0xF7) :
- ev->length=readVariableLengthValue();
-#ifdef PEDANTIC_TRACK
- if (endoftrack)
- {
- ev->command=MIDI_SYSTEM_PREFIX;
- ev->chn=0xF;
- ev->d1=ME_END_OF_TRACK;
- }
- else
-#endif
- {
- ev->data=ptrdata;
- ptrdata+=ev->length;currentpos+=ev->length;
- }
- break;
- case (0xFE):
- case (0xF8):
- // printfdebug("Active sensing\n");
- break;
- case (META_EVENT) :
- ev->d1=*ptrdata;ptrdata++;currentpos++;
- switch (ev->d1)
- {
- case (ME_END_OF_TRACK) :
- i=0;
- j=0;
- while ((i<16)&&(note[i][j]==FALSE))
- {
- j++;
- if (j==128) { j=0; i++; };
- }
- if (i<16) // that is, if there is any key still pressed
- {
- ptrdata--;currentpos--;
- ev->chn=i;
- ev->command=MIDI_NOTEOFF;
- ev->note = j;
- ev->vel = 0;
- note[ev->chn][ev->note]=FALSE;
- fprintf(stderr,"Note Off(simulated)\n");
- return;
- }
- else
- {
- endoftrack=1;
- delta_ticks = wait_ticks = ~0;
- time_at_next_event=10000 * 60000L;
-#ifdef TRACKDEBUG
- printfdebug("EndofTrack %d event\n",id);
-#endif
- }
- break;
- case (ME_SET_TEMPO):
- ev->length=readVariableLengthValue();
-#ifdef PEDANTIC_TRACK
- if (endoftrack)
- {
- ev->command=MIDI_SYSTEM_PREFIX;
- ev->chn=0xF;
- ev->d1=ME_END_OF_TRACK;
- }
- else
-#endif
- {
- ev->data=ptrdata;
- ptrdata+=ev->length;currentpos+=ev->length;
- // tempo=((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]));
- // ticks_from_previous_tempochange=0;
- // time_at_previous_tempochange=current_time;
-#ifdef TRACKDEBUG
- printfdebug("Track %d : Set Tempo : %ld\n",id,tempo);
-#endif
-#ifdef CHANGETEMPO_ONLY_IN_TRACK0
- if (id!=0) skip_event=1;
-#endif
- }
- break;
- case (ME_TIME_SIGNATURE) :
- ev->length=*ptrdata;ptrdata++;currentpos++;
- ev->d2=*ptrdata;ptrdata++;currentpos++;
- ev->d3=power2to(*ptrdata);ptrdata++;currentpos++;
- ev->d4=*ptrdata;ptrdata++;currentpos++;
- ev->d5=*ptrdata;ptrdata++;currentpos++;
-#ifdef TRACKDEBUG
- printfdebug("TIME SIGNATURE :\n");
- printfdebug("%d\n",ev->d2);
- printfdebug("---- %d metronome , %d number of 32nd notes per quarter note\n",ev->d4,ev->d5);
- printfdebug("%d\n",ev->d3);
-#endif
- break;
- case (ME_TRACK_SEQ_NUMBER) :
- case (ME_TEXT) :
- case (ME_COPYRIGHT) :
- case (ME_SEQ_OR_TRACK_NAME) :
- case (ME_TRACK_INSTR_NAME) :
- case (ME_LYRIC) :
- case (ME_MARKER) :
- case (ME_CUE_POINT) :
- case (ME_CHANNEL_PREFIX) :
- case (ME_MIDI_PORT) :
- case (ME_SMPTE_OFFSET) :
- case (ME_KEY_SIGNATURE) :
- ev->length=readVariableLengthValue();
-#ifdef PEDANTIC_TRACK
- if (endoftrack)
- {
- ev->command=MIDI_SYSTEM_PREFIX;
- ev->chn=0xF;
- ev->d1=ME_END_OF_TRACK;
- }
- else
-#endif
- {
- ev->data=ptrdata;
- ptrdata+=ev->length;currentpos+=ev->length;
- }
- break;
- default:
-#ifdef GENERAL_DEBUG_MESSAGES
- fprintf(stderr,"track (%d) : Default handler for meta event " \
- "0x%x\n", id, ev->d1);
-#endif
- ev->length=readVariableLengthValue();
-#ifdef PEDANTIC_TRACK
- if (endoftrack)
- {
- ev->command=MIDI_SYSTEM_PREFIX;
- ev->chn=0xF;
- ev->d1=ME_END_OF_TRACK;
- }
- else
-#endif
- {
- ev->data=ptrdata;
- ptrdata+=ev->length;currentpos+=ev->length;
- }
- break;
- }
- break;
- default :
- fprintf(stderr,"track (%d): Default handler for system event 0x%x\n",
- id, (ev->command|ev->chn));
- break;
- }
- break;
- default :
- fprintf(stderr,"track (%d): Default handler for event 0x%x\n",
- id, (ev->command|ev->chn));
- break;
- }
-#ifdef PEDANTIC_TRACK
- if (currentpos>=size)
- {
- endoftrack=1;
- delta_ticks = wait_ticks = ~0;
- time_at_next_event=10000 * 60000L;
- printfdebug("track (%d): EndofTrack reached\n",id);
- }
-#endif
- if (endoftrack==0)
- {
- current_ticks+=delta_ticks;
- delta_ticks=readVariableLengthValue();
-#ifdef PEDANTIC_TRACK
- if (endoftrack)
- {
- ev->command=MIDI_SYSTEM_PREFIX;
- ev->chn=0xF;
- ev->d1=ME_END_OF_TRACK;
- return;
- }
-#endif
- ticks_from_previous_tempochange+=delta_ticks;
-
- time_at_next_event=T2MS(ticks_from_previous_tempochange)+time_at_previous_tempochange;
- /*
- printf("tane2 : %g, ticks : %g, delta_ticks %ld, tempo : %ld\n",
- time_at_next_event,ticks_from_previous_tempochange,delta_ticks,tempo);
- printf("timeatprevtc %g , curr %g\n",time_at_previous_tempochange,current_time);
- */
- wait_ticks=delta_ticks;
-
- }
- if (skip_event) readEvent(ev);
-}
-
-
-void MidiTrack::clear(void)
-{
- endoftrack=1;
- ptrdata=data;
- current_ticks=0;
- currentpos=0;
-
- for (int i=0;i<16;i++)
- for (int j=0;j<128;j++)
- note[i][j]=FALSE;
-
- delta_ticks = wait_ticks = ~0;
- time_at_previous_tempochange=0;
- current_time=0;
- ticks_from_previous_tempochange=0;
- tempo=1000000;
- time_at_next_event=10000 * 60000L;
-
-}
-
-
-void MidiTrack::init(void)
-{
- if (data==0L) { clear(); return; };
- endoftrack=0;
- ptrdata=data;
- current_ticks=0;
- currentpos=0;
-
- for (int i=0;i<16;i++)
- for (int j=0;j<128;j++)
- note[i][j]=FALSE;
-
- delta_ticks=readVariableLengthValue();
- if (endoftrack) return;
- wait_ticks=delta_ticks;
-
-
- time_at_previous_tempochange=0;
- current_time=0;
- ticks_from_previous_tempochange=wait_ticks;
- tempo=1000000;
- time_at_next_event=T2MS(delta_ticks);
- //printf("tane1 : %g\n",time_at_next_event);
-}
-
-void MidiTrack::changeTempo(ulong t)
-{
- if (endoftrack==1) return;
- if (tempo==t) return;
- double ticks;
- time_at_previous_tempochange=current_time;
- ticks=MS2T(time_at_next_event-current_time);
- tempo=t;
- time_at_next_event=T2MS(ticks)+current_time;
- ticks_from_previous_tempochange=ticks;
-
-}
-
-/*
-double MidiTrack::absMsOfNextEvent (void)
-{
- //printf("%d : %g\n",id,time_at_next_event);
- return time_at_next_event;
-}
-*/
-
-#undef T2MS
-#undef MS2T