diff options
Diffstat (limited to 'libkmid/midfile.cc')
-rw-r--r-- | libkmid/midfile.cc | 460 |
1 files changed, 0 insertions, 460 deletions
diff --git a/libkmid/midfile.cc b/libkmid/midfile.cc deleted file mode 100644 index 4bf19f5b1..000000000 --- a/libkmid/midfile.cc +++ /dev/null @@ -1,460 +0,0 @@ -/************************************************************************** - - midfile.cc - function which reads a midi file,and creates the track classes - 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 <larrosa@kde.org> - -***************************************************************************/ -#include "midfile.h" -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include "sndcard.h" -#include "midispec.h" -#include "mt32togm.h" -#include "sys/stat.h" -#include <config.h> - -#include <kprocess.h> -#include <tqfile.h> - -int fsearch(FILE *fh,const char *text,long *ptr); - -/* This function gives the metronome tempo, from a tempo data as found in - a midi file */ -double tempoToMetronomeTempo(ulong x) -{ - return 60/((double)x/1000000); -} - -double metronomeTempoToTempo(ulong x) -{ - return ((double)60*x)/1000000; -} - -int uncompressFile(const char *gzname, char *tmpname) - // Returns 0 if OK, 1 if error (tmpname not set) -{ - TQString cmd("gzip -dc " + TDEProcess::quote(gzname)); - FILE *infile = popen( TQFile::encodeName(cmd).data(), "r"); - if (infile==NULL) { - fprintf(stderr,"ERROR : popen failed : %s\n",TQFile::encodeName(cmd).data()); - return 1; - } - strcpy(tmpname, "/tmp/KMid.XXXXXXXXXX"); - int fd = mkstemp(tmpname); - if (fd == -1) - { - pclose(infile); - return 1; - } - FILE *outfile= fdopen(fd,"wb"); - if (outfile==NULL) - { - pclose(infile); - return 1; - } - int n=getc(infile); - if (n==EOF) - { - pclose(infile); - fclose(outfile); - unlink(tmpname); - return 1; - } - fputc(n,outfile); - int buf[BUFSIZ]; - n = fread(buf, 1, BUFSIZ, infile); - while (n>0) - { - fwrite(buf, 1, n, outfile); - n = fread(buf, 1, BUFSIZ, infile); - } - - pclose(infile); - - //if (pclose(infile) != 0) fprintf(stderr,"Error : pclose failed\n"); - // Is it right for pclose to always fail ? - - fclose(outfile); - return 0; -} - -MidiTrack **readMidiFile( const char *name, MidiFileInfo *info, int &ok) -{ - ok=1; - MidiTrack **tracks; - - struct stat buf; - if (stat(name,&buf) || !S_ISREG(buf.st_mode)) - { - fprintf(stderr,"ERROR: %s is not a regular file\n",name); - ok=-6; - return NULL; - } - - FILE *fh=fopen(name,"rb"); - if (fh==NULL) - { - fprintf(stderr,"ERROR: Can't open file %s\n",name); - ok=-1; - return NULL; - } - char text[4]; - text[0] = 0; - fread(text,1,4,fh); - if ((strncmp(text,"MThd",4)!=0)&&(strcmp(&name[strlen(name)-3],".gz")==0)) - { - fclose(fh); - char tempname[200]; - fprintf(stderr,"Trying to open zipped midi file...\n"); - if (uncompressFile(name,tempname)!=0) - { - fprintf(stderr,"ERROR: %s is not a (zipped) midi file\n",name); - ok=-2; - return NULL; - } - fh=fopen(tempname,"rb"); - fread(text,1,4,fh); - unlink(tempname); - } - - if (strncmp(text,"MThd",4)!=0) - { - fseek(fh,0,SEEK_SET); - long pos; - if (fsearch(fh,"MThd",&pos)==0) - { - fclose(fh); - fprintf(stderr,"ERROR: %s is not a midi file.\n",name); - ok=-2; - return NULL; - } - fseek(fh,pos,SEEK_SET); - fread(text,1,4,fh); - } - long header_size=readLong(fh); - info->format=readShort(fh); - info->ntracks=readShort(fh); - info->ticksPerCuarterNote=readShort(fh); - if (info->ticksPerCuarterNote<0) - { - fprintf(stderr,"ERROR: Ticks per cuarter note is negative !\n"); - fprintf(stderr,"Please report this error to : larrosa@kde.org\n"); - fclose(fh); - ok=-3; - return NULL; - } - if (header_size>6) fseek(fh,header_size-6,SEEK_CUR); - tracks=new MidiTrack*[info->ntracks]; - if (tracks==NULL) - { - fprintf(stderr,"ERROR: Not enough memory\n"); - fclose(fh); - ok=-4; - return NULL; - } - int i=0; - while (i<info->ntracks) - { - fread(text,1,4,fh); - if (strncmp(text,"MTrk",4)!=0) - { - fprintf(stderr,"ERROR: Not a well built midi file\n"); - fprintf(stderr,"%s",text); - fclose(fh); - ok=-5; - return NULL; - } - tracks[i]=new MidiTrack(fh,info->ticksPerCuarterNote,i); - if (tracks[i]==NULL) - { - fprintf(stderr,"ERROR: Not enough memory"); - fclose(fh); - ok=-4; - return NULL; - } - i++; - } - - fclose(fh); - - return tracks; - -} - -void parseInfoData(MidiFileInfo *info,MidiTrack **tracks,float ratioTempo) -{ - - info->ticksTotal=0; - info->millisecsTotal=0.0; - info->ticksPlayed=0; - int i; - for (i=0;i<256;i++) - { - info->patchesUsed[i]=0; - } - - int parsing=1; - int trk,minTrk; - ulong tempo=(ulong)(500000 * ratioTempo); - -#ifdef MIDFILEDEBUG - printf("Parsing 1 ...\n"); -#endif - - int pgminchannel[16]; - for (i=0;i<16;i++) - { - pgminchannel[i]=0; - } - - int j; - for (i=0;i<info->ntracks;i++) - { - tracks[i]->init(); - tracks[i]->changeTempo(tempo); - } - double prevms=0; - double minTime=0; - double maxTime; - MidiEvent *ev=new MidiEvent; - while (parsing) - { - prevms=minTime; - trk=0; - minTrk=0; - maxTime=minTime + 2 * 60000L; - minTime=maxTime; - while (trk<info->ntracks) - { - if (tracks[trk]->absMsOfNextEvent()<minTime) - { - minTrk=trk; - minTime=tracks[minTrk]->absMsOfNextEvent(); - } - trk++; - } - if ((minTime==maxTime)) - { - parsing=0; -#ifdef MIDFILEDEBUG - printf("END of parsing\n"); -#endif - } - else - { - trk=0; - while (trk<info->ntracks) - { - tracks[trk]->currentMs(minTime); - trk++; - } - } - trk=minTrk; - tracks[trk]->readEvent(ev); - - switch (ev->command) - { - case (MIDI_NOTEON) : - if (ev->chn!=PERCUSSION_CHANNEL) - info->patchesUsed[pgminchannel[ev->chn]]++; - else - info->patchesUsed[ev->note+128]++; - break; - case (MIDI_PGM_CHANGE) : - pgminchannel[ev->chn]=(ev->patch); - break; - case (MIDI_SYSTEM_PREFIX) : - if (((ev->command|ev->chn)==META_EVENT)&&(ev->d1==ME_SET_TEMPO)) - { - tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2])) * ratioTempo); - for (j=0;j<info->ntracks;j++) - { - tracks[j]->changeTempo(tempo); - } - } - break; - } - } - - delete ev; - info->millisecsTotal=prevms; - - for (i=0;i<info->ntracks;i++) - { - tracks[i]->init(); - } - -#ifdef MIDFILEDEBUG - printf("info.ticksTotal = %ld \n",info->ticksTotal); - printf("info.ticksPlayed= %ld \n",info->ticksPlayed); - printf("info.millisecsTotal = %g \n",info->millisecsTotal); - printf("info.TicksPerCN = %d \n",info->ticksPerCuarterNote); -#endif - -} - - -void parsePatchesUsed(MidiTrack **tracks,MidiFileInfo *info,int gm) -{ - int i; - for (i=0;i<256;i++) - { - info->patchesUsed[i]=0; - } - int parsing=1; - int trk,minTrk; - ulong tempo=500000; - -#ifdef MIDFILEDEBUG - printf("Parsing for patches ...\n"); -#endif - - int j; - for (i=0;i<info->ntracks;i++) - { - tracks[i]->init(); - } - double prevms=0; - double minTime=0; - double maxTime; - ulong tmp; - MidiEvent *ev=new MidiEvent; - int pgminchannel[16]; - for (i=0;i<16;i++) - { - pgminchannel[i]=0; - } - - while (parsing) - { - prevms=minTime; - trk=0; - minTrk=0; - maxTime=minTime + 2 * 60000L; - minTime=maxTime; - while (trk<info->ntracks) - { - if (tracks[trk]->absMsOfNextEvent()<minTime) - { - minTrk=trk; - minTime=tracks[minTrk]->absMsOfNextEvent(); - } - trk++; - } - if ((minTime==maxTime)) - { - parsing=0; -#ifdef MIDFILEDEBUG - printf("END of parsing for patches\n"); -#endif - } - else - { - trk=0; - while (trk<info->ntracks) - { - tracks[trk]->currentMs(minTime); - trk++; - } - } - trk=minTrk; - tracks[trk]->readEvent(ev); - switch (ev->command) - { - case (MIDI_NOTEON) : - if (ev->chn!=PERCUSSION_CHANNEL) - info->patchesUsed[pgminchannel[ev->chn]]++; - else - info->patchesUsed[ev->note+128]++; - break; - case (MIDI_PGM_CHANGE) : - pgminchannel[ev->chn]=(gm==1)?(ev->patch):(MT32toGM[ev->patch]); - break; - case (MIDI_SYSTEM_PREFIX) : - if (((ev->command|ev->chn)==META_EVENT)&&(ev->d1==ME_SET_TEMPO)) - { - if (tempoToMetronomeTempo(tmp=((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2])))>=8) - { - tempo=tmp; - // printf("setTempo %ld\n",tempo); - for (j=0;j<info->ntracks;j++) - { - tracks[j]->changeTempo(tempo); - } - } - } - break; - } - } - - delete ev; - - for (i=0;i<info->ntracks;i++) - { - tracks[i]->init(); - } - -} - -int fsearch(FILE *fh,const char *text,long *ptr) - // Search for "text" through the fh file and then returns : - // text MUST BE smaller than 256 characters - // 0 if not was found - // 1 if it was found and in ptr (if !=NULL) the position where text begins. -{ - if ((text==NULL)||(text[0]==0)) return 0; - char buf[1024]; - char tmp[256]; - long pos; - int l=strlen(text); - int i,k,r; - while (!feof(fh)) - { - pos=ftell(fh); - k=fread(buf,1,1024,fh); - i=0; - while (i<k) - { - if (buf[i]==text[0]) - { - if (k-i>=l) - r=strncmp(text,&buf[i],l); - else - { - fseek(fh,pos+i,SEEK_SET); - if (fread(tmp,1,l,fh)<(uint)l) return 0; - fseek(fh,pos+k,SEEK_SET); - r=strncmp(text,tmp,l); - } - if (r==0) - { - if (ptr!=NULL) *ptr=pos+i; - return 1; - } - } - i++; - } - } - return 0; -} |