⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 midifile.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Read a Standard MIDI File.  Externally-assigned function pointers are * called upon recognizing things in the file.  See midifile(3). *//****************************************************************************** Change Log*   Date    | who : Change*-----------+-----------------------------------------------------------------*  2-Mar-92 | GWL : created changelog; MIDIFILE_ERROR to satisfy compiler* 28-Apr-03 | DM  : changed #includes and give return types for portability*****************************************************************************/#include "switches.h"#include <stdio.h>#include <stdlib.h>#include "mfmidi.h"#include "midifile.h"#include "cext.h"#include "userio.h"#include "string.h"#define MIDIFILE_ERROR -1#ifdef PROTOTYPES#define NOARGS void#else#define NOARGS#endif/* public stuff */extern int abort_flag;/* Functions to be called while processing the MIDI file. */void (*Mf_starttrack)(NOARGS) = 0;void (*Mf_endtrack)(NOARGS) = 0;int (*Mf_getc)(NOARGS) = 0;void (*Mf_eot)(NOARGS) = 0;#ifdef PROTOTYPESvoid (*Mf_error)(char *) = 0;void (*Mf_header)(int,int,int) = 0;void (*Mf_on)(int,int,int) = 0;void (*Mf_off)(int,int,int) = 0;void (*Mf_pressure)(int,int,int) = 0;void (*Mf_controller)(int,int,int) = 0;void (*Mf_pitchbend)(int,int,int) = 0;void (*Mf_program)(int,int) = 0;void (*Mf_chanpressure)(int,int) = 0;void (*Mf_sysex)(int,char*) = 0;void (*Mf_arbitrary)(int,char*) = 0;void (*Mf_metamisc)(int,int,char*) = 0;void (*Mf_seqnum)(int) = 0;void (*Mf_smpte)(int,int,int,int,int) = 0;void (*Mf_timesig)(int,int,int,int) = 0;void (*Mf_tempo)(int) = 0;void (*Mf_keysig)(int,int) = 0;void (*Mf_sqspecific)(int,char*) = 0;void (*Mf_text)(int,int,char*) = 0;#elsevoid (*Mf_error)() = 0;void (*Mf_header)() = 0;void (*Mf_on)() = 0;void (*Mf_off)() = 0;void (*Mf_pressure)() = 0;void (*Mf_controller)() = 0;void (*Mf_pitchbend)() = 0;void (*Mf_program)() = 0;void (*Mf_chanpressure)() = 0;void (*Mf_sysex)() = 0;void (*Mf_arbitrary)() = 0;void (*Mf_metamisc)() = 0;void (*Mf_seqnum)() = 0;void (*Mf_smpte)() = 0;void (*Mf_tempo)() = 0;void (*Mf_timesig)() = 0;void (*Mf_keysig)() = 0;void (*Mf_sqspecific)() = 0;void (*Mf_text)() = 0;#endifint Mf_nomerge = 0;             /* 1 => continue'ed system exclusives are */                                /* not collapsed. */long Mf_currtime = 0L;          /* current time in delta-time units */int Mf_skipinit = 0;            /* 1 if initial garbage should be skipped *//* private stuff */static long Mf_toberead = 0L;static long readvarinum(NOARGS);static long read32bit(NOARGS);static int read16bit(NOARGS);static void msgenlarge(NOARGS);static char *msg(NOARGS);static int readheader(NOARGS);static void readtrack(NOARGS);static void sysex(NOARGS), msginit(NOARGS);static int egetc(NOARGS);static int msgleng(NOARGS);#ifdef PROTOTYPESstatic int readmt(char*,int);static long to32bit(int,int,int,int);static int to16bit(int,int);static void mferror(char *);static void badbyte(int);static void metaevent(int);static void msgadd(int);static void chanmessage(int,int,int);#elsestatic long to32bit();static int to16bit();static void mferror();static void badbyte();static void metaevent();static void msgadd();static void chanmessage();#endifstatic int midifile_error;voidmidifile()              /* The only non-static function in this file. */{        int ntrks;        midifile_error = 0;        if ( Mf_getc == 0 ) {                mferror("mf.h() called without setting Mf_getc");                 return;        }        ntrks = readheader();        if (midifile_error) return;        if ( ntrks <= 0 ) {                mferror("No tracks!");                /* no need to return since midifile_error is set */        }        while ( ntrks-- > 0 && !midifile_error && !check_aborted())                readtrack();        if (check_aborted()) {                mferror("Midifile read aborted\n\\tthe rest of your file will be ignored.\n");            if (abort_flag == BREAK_LEVEL) abort_flag = 0;        }}static intreadmt(s,skip)          /* read through the "MThd" or "MTrk" header string */char *s;int skip;               /* if 1, we attempt to skip initial garbage. */{        int nread = 0;        char b[4];        char buff[32];        int c;        char *errmsg = "expecting ";    retry:        while ( nread<4 ) {                c = (*Mf_getc)();                if ( c == EOF ) {                        errmsg = "EOF while expecting ";                        goto err;                }                b[nread++] = c;        }        /* See if we found the 4 characters we're looking for */        if ( s[0]==b[0] && s[1]==b[1] && s[2]==b[2] && s[3]==b[3] )                return(0);        if ( skip ) {                /* If we are supposed to skip initial garbage, */                /* try again with the next character. */                b[0]=b[1];                b[1]=b[2];                b[2]=b[3];                nread = 3;                goto retry;        }    err:        (void) strcpy(buff,errmsg);        (void) strcat(buff,s);        mferror(buff);        return(0);}static integetc()                 /* read a single character and abort on EOF */{        int c = (*Mf_getc)();        if ( c == EOF ) {                mferror("premature EOF");                return EOF;        }        Mf_toberead--;        return(c);}static intreadheader()            /* read a header chunk */{        int format, ntrks, division;        if ( readmt("MThd",Mf_skipinit) == EOF )                return(0);        Mf_toberead = read32bit();        if (midifile_error) return MIDIFILE_ERROR;        format = read16bit();        if (midifile_error) return MIDIFILE_ERROR;        ntrks = read16bit();        if (midifile_error) return MIDIFILE_ERROR;        division = read16bit();        if (midifile_error) return MIDIFILE_ERROR;        if ( Mf_header )                (*Mf_header)(format,ntrks,division);        /* flush any extra stuff, in case the length of header is not 6 */        while ( Mf_toberead > 0 && !midifile_error)                (void) egetc();        return(ntrks);}static voidreadtrack()              /* read a track chunk */{        /* This array is indexed by the high half of a status byte.  It's */        /* value is either the number of bytes needed (1 or 2) for a channel */        /* message, or 0 (meaning it's not  a channel message). */        static int chantype[] = {                0, 0, 0, 0, 0, 0, 0, 0,         /* 0x00 through 0x70 */                2, 2, 2, 2, 1, 1, 2, 0          /* 0x80 through 0xf0 */        };        long lookfor, lng;        int c, c1, type;        int sysexcontinue = 0;  /* 1 if last message was an unfinished sysex */        int running = 0;        /* 1 when running status used */        int status = 0;         /* (possibly running) status byte */        int needed;        if ( readmt("MTrk",0) == EOF )                return;        Mf_toberead = read32bit();        if (midifile_error) return;        Mf_currtime = 0L;        if ( Mf_starttrack ){                (*Mf_starttrack)();        }        while ( Mf_toberead > 0 ) {                Mf_currtime += readvarinum();   /* delta time */                if (midifile_error) return;                c = egetc(); if (midifile_error) return;                if ( sysexcontinue && c != 0xf7 ) {                        mferror("didn't find expected continuation of a sysex");                        return;                }                if ( (c & 0x80) == 0 ) {         /* running status? */                        if ( status == 0 ) {                                mferror("unexpected running status");                                return;                        }                        running = 1;                }                else {                        status = c;                        running = 0;                }                needed = chantype[ (status>>4) & 0xf ];                if ( needed ) {         /* ie. is it a channel message? */                        if ( running )                                c1 = c;                        else {                                c1 = egetc();                                if (midifile_error) return;                        }                        chanmessage( status, c1, (needed>1) ? egetc() : 0 );                        if (midifile_error) return;                        continue;;                }                switch ( c ) {                case 0xff:                      /* meta event */                        type = egetc();                        if (midifile_error) return;                        /* watch out - Don't combine the next 2 statements */                        lng = readvarinum();                        if (midifile_error) return;                        lookfor = Mf_toberead - lng;                        msginit();                        while ( Mf_toberead > lookfor ) {                                char c = egetc();                                if (midifile_error) return;                                msgadd(c);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -