aboutsummaryrefslogtreecommitdiff
path: root/midifile
diff options
context:
space:
mode:
authorMartin Peach <mrpeach@users.sourceforge.net>2007-06-02 01:10:35 +0000
committerMartin Peach <mrpeach@users.sourceforge.net>2007-06-02 01:10:35 +0000
commit0e9ea7dcd4c094e1356c40051c2faf4eb08bcdf4 (patch)
treed2c515af377a65370c16b957c5eaf4d84f114d11 /midifile
parent20f6083ffe23d7fb0b871e37e4223f8d92e7762d (diff)
cleaned up code to reduce number of warnings
svn path=/trunk/externals/mrpeach/; revision=7742
Diffstat (limited to 'midifile')
-rwxr-xr-xmidifile/midifile.c2336
1 files changed, 1169 insertions, 1167 deletions
diff --git a/midifile/midifile.c b/midifile/midifile.c
index 92482aa..d036bac 100755
--- a/midifile/midifile.c
+++ b/midifile/midifile.c
@@ -32,8 +32,6 @@
* 20060110 output totaltime before end-bang
*/
-//#define MSW // useful in m_pd.h if not yet replaced by _MSC_VER
-
#include "m_pd.h"
#include <stdio.h>
#include <string.h>
@@ -48,50 +46,51 @@
static t_class *midifile_class;
#define PATH_BUF_SIZE 256
-#define MAX_TRACKS 128 // track data is allocated as needed but we need to preallocate space for the pointers
-#define MAX_TRACK_LEN 1024 // for now...
+#define MAX_TRACKS 128
+/* track data is allocated as needed but we need to preallocate space for the pointers */
+#define MAX_TRACK_LEN 1024
+/* MAX_TRACK_LEN 1024 for now...*/
#define ALL_TRACKS MAX_TRACKS
typedef enum {mfReset, mfReading, mfWriting} mfstate;
typedef struct mf_header_chunk
{
- char chunk_type[4]; // each chunk begins with a 4-character ASCII type.
- size_t chunk_length ; // followed by a 32-bit length
- int chunk_format;
- int chunk_ntrks;
- int chunk_division;
+ char chunk_type[4]; /* each chunk begins with a 4-character ASCII type.*/
+ size_t chunk_length ; /* followed by a 32-bit length */
+ int chunk_format;
+ int chunk_ntrks;
+ int chunk_division;
} mf_header_chunk;
typedef struct mf_track_chunk
{
- char chunk_type[4]; // each chunk begins with a 4-character ASCII type.
- size_t chunk_length ; // followed by a 32-bit length
- size_t delta_time ; // current delta_time of latest track_data element
- size_t total_time ; // sum of delta_times so far
- size_t track_index ; // current byte offset to next track_data element
- unsigned char running_status;
- char *track_data;
+ char chunk_type[4]; /* each chunk begins with a 4-character ASCII type. */
+ size_t chunk_length ; /* followed by a 32-bit length */
+ size_t delta_time ; /* current delta_time of latest track_data element */
+ size_t total_time ; /* sum of delta_times so far */
+ size_t track_index ; /* current byte offset to next track_data element */
+ unsigned char running_status;
+ char *track_data;
} mf_track_chunk;
typedef struct t_midifile
{
- t_object x_obj;
- size_t total_time; // current time for this MIDI file in delta_time units
- t_atom midi_data[3]; // one MIDI packet as a list
- t_outlet *midi_list_outlet;
- t_outlet *bang_outlet;
- //t_outlet *sysex_outlet; // 20060105 use midi_list_outlet instead
- t_outlet *total_time_outlet;
- FILE *fP;
- FILE *tmpFP;
- char fPath[PATH_BUF_SIZE];
- size_t offset; // character offset into the file fP
- int track; // play this track, or all tracks if negative;
- int verbosity; // nonzero for text output to console
- int ended; // nonzero if all tracks have finished
- mfstate state; // READING or WRITING
- mf_header_chunk header_chunk; // First chunk in the midi file
- mf_track_chunk track_chunk[MAX_TRACKS]; // Subsequent track chunks. Other kinds of chunk are ignored
+ t_object x_obj;
+ size_t total_time; /* current time for this MIDI file in delta_time units */
+ t_atom midi_data[3]; /* one MIDI packet as a list */
+ t_outlet *midi_list_outlet;
+ t_outlet *bang_outlet;
+ t_outlet *total_time_outlet;
+ FILE *fP;
+ FILE *tmpFP;
+ char fPath[PATH_BUF_SIZE];
+ size_t offset; /* character offset into the file fP */
+ int track; /* play this track, or all tracks if negative; */
+ int verbosity; /* nonzero for text output to console */
+ int ended; /* nonzero if all tracks have finished */
+ mfstate state; /* READING or WRITING */
+ mf_header_chunk header_chunk; /* First chunk in the midi file */
+ mf_track_chunk track_chunk[MAX_TRACKS]; /* Subsequent track chunks. Other kinds of chunk are ignored. */
} t_midifile;
void midifile_skip_next_track_chunk_data(t_midifile *x, int index);
@@ -130,111 +129,107 @@ EXPORT_SHARED void midifile_setup(void);
EXPORT_SHARED void midifile_setup(void)
{
- midifile_class = class_new (gensym("midifile"),
- (t_newmethod) midifile_new,
- (t_method)midifile_free, sizeof(t_midifile),
- CLASS_DEFAULT,
- A_GIMME, 0);
- //CLASS_DEFAULT a normal object with one inlet
- class_addbang(midifile_class, midifile_bang);
- class_addfloat(midifile_class, midifile_float);
- class_addlist(midifile_class, midifile_list);
- class_addmethod(midifile_class, (t_method)midifile_read, gensym("read"), A_DEFSYMBOL, 0);
- class_addmethod(midifile_class, (t_method)midifile_flush, gensym("flush"), 0);
- class_addmethod(midifile_class, (t_method)midifile_write, gensym("write"), A_DEFSYMBOL, 0);
- class_addmethod(midifile_class, (t_method)midifile_dump, gensym("dump"), A_DEFFLOAT, 0);
- class_addmethod(midifile_class, (t_method)midifile_single_track, gensym("track"), A_DEFFLOAT, 0);
- class_addmethod(midifile_class, (t_method)midifile_rewind, gensym("rewind"), 0);
- class_addmethod(midifile_class, (t_method)midifile_verbosity, gensym("verbose"), A_DEFFLOAT, 0);
- class_sethelpsymbol(midifile_class, gensym("midifile-help"));
+ midifile_class = class_new (gensym("midifile"),
+ (t_newmethod) midifile_new,
+ (t_method)midifile_free, sizeof(t_midifile),
+ CLASS_DEFAULT,
+ A_GIMME, 0);
+
+ class_addbang(midifile_class, midifile_bang);
+ class_addfloat(midifile_class, midifile_float);
+ class_addlist(midifile_class, midifile_list);
+ class_addmethod(midifile_class, (t_method)midifile_read, gensym("read"), A_DEFSYMBOL, 0);
+ class_addmethod(midifile_class, (t_method)midifile_flush, gensym("flush"), 0);
+ class_addmethod(midifile_class, (t_method)midifile_write, gensym("write"), A_DEFSYMBOL, 0);
+ class_addmethod(midifile_class, (t_method)midifile_dump, gensym("dump"), A_DEFFLOAT, 0);
+ class_addmethod(midifile_class, (t_method)midifile_single_track, gensym("track"), A_DEFFLOAT, 0);
+ class_addmethod(midifile_class, (t_method)midifile_rewind, gensym("rewind"), 0);
+ class_addmethod(midifile_class, (t_method)midifile_verbosity, gensym("verbose"), A_DEFFLOAT, 0);
+ class_sethelpsymbol(midifile_class, gensym("midifile-help"));
}
void *midifile_new(t_symbol *s, int argc, t_atom *argv)
{
- t_midifile *x = (t_midifile *)pd_new(midifile_class);
- t_symbol *pathSymbol;
- int i;
-
- if (x == NULL)
- {
- error("midifile: Could not create...");
- return x;
- }
- x->fP = NULL;
- x->fPath[0] = '\0';
- x->track = ALL_TRACKS; // startup playing anything
- x->midi_data[0].a_type = x->midi_data[1].a_type = x->midi_data[2].a_type = A_FLOAT;
- x->state = mfReset;
- x->verbosity = 1; // default to posting all
- for (i = 0; i < MAX_TRACKS; ++i)
- {
- x->track_chunk[i].track_data = NULL;
- }
- // find the first string in the arg list and interpret it as a path to a midi file
- for (i = 0; i < argc; ++i)
- {
- if (argv[i].a_type == A_SYMBOL)
- {
- pathSymbol = atom_getsymbol(&argv[i]);
- if (pathSymbol != NULL)
- {
- if (midifile_open_path(x, pathSymbol->s_name, "rb"))
- {
- if (x->verbosity) post("midifile: opened %s", x->fPath);
- x->state = mfReading;
- if (midifle_read_chunks(x) == 0) midifile_free_file(x);
- }
- else error("midifile: unable to open %s", pathSymbol->s_name);
- break;
- }
- }
- }
- x->midi_list_outlet = outlet_new(&x->x_obj, &s_list);
- // x->sysex_outlet = outlet_new(&x->x_obj, &s_float); // raw sysex stream (20060105 send a list through midi_list_outlet)
- x->total_time_outlet = outlet_new(&x->x_obj, &s_float); // current total_time
- x->bang_outlet = outlet_new(&x->x_obj, &s_bang); // bang at end of file
- return (void *)x;
+ t_midifile *x = (t_midifile *)pd_new(midifile_class);
+ t_symbol *pathSymbol;
+ int i;
+
+ if (x == NULL)
+ {
+ error("midifile: Could not create...");
+ return x;
+ }
+ x->fP = NULL;
+ x->fPath[0] = '\0';
+ x->track = ALL_TRACKS; /* startup playing anything */
+ x->midi_data[0].a_type = x->midi_data[1].a_type = x->midi_data[2].a_type = A_FLOAT;
+ x->state = mfReset;
+ x->verbosity = 1; /* default to posting all */
+ for (i = 0; i < MAX_TRACKS; ++i)
+ {
+ x->track_chunk[i].track_data = NULL;
+ }
+ /* find the first string in the arg list and interpret it as a path to a midi file */
+ for (i = 0; i < argc; ++i)
+ {
+ if (argv[i].a_type == A_SYMBOL)
+ {
+ pathSymbol = atom_getsymbol(&argv[i]);
+ if (pathSymbol != NULL)
+ {
+ if (midifile_open_path(x, pathSymbol->s_name, "rb"))
+ {
+ if (x->verbosity) post("midifile: opened %s", x->fPath);
+ x->state = mfReading;
+ if (midifle_read_chunks(x) == 0) midifile_free_file(x);
+ }
+ else error("midifile: unable to open %s", pathSymbol->s_name);
+ break;
+ }
+ }
+ }
+ x->midi_list_outlet = outlet_new(&x->x_obj, &s_list);
+ x->total_time_outlet = outlet_new(&x->x_obj, &s_float); /* current total_time */
+ x->bang_outlet = outlet_new(&x->x_obj, &s_bang); /* bang at end of file */
+ return (void *)x;
}
void midifile_close(t_midifile *x)
{
- if (x->fP != NULL)
- {
- fclose (x->fP);
- x->fP = NULL;
- }
- if (x->tmpFP != NULL)
- {
- fclose(x->tmpFP);
- x->tmpFP = NULL;
- }
- x->fPath[0] = '\0';
- x->state = mfReset;
- x->total_time = 0L;
- x->offset = 0L;
- outlet_float(x->total_time_outlet, x->total_time);
+ if (x->fP != NULL)
+ {
+ fclose (x->fP);
+ x->fP = NULL;
+ }
+ if (x->tmpFP != NULL)
+ {
+ fclose(x->tmpFP);
+ x->tmpFP = NULL;
+ }
+ x->fPath[0] = '\0';
+ x->state = mfReset;
+ x->total_time = 0L;
+ x->offset = 0L;
+ outlet_float(x->total_time_outlet, x->total_time);
}
void midifile_free_file(t_midifile *x)
{
- int i;
-
- midifile_close(x);
-
- for (i = 0; i < MAX_TRACKS; ++i)
- {
- if (x->track_chunk[i].track_data != NULL)
- {
- freebytes(x->track_chunk[i].track_data, x->track_chunk[i].chunk_length);
- //if (x->verbosity) post("midifile_free: freed %lu bytes for track %d", x->track_chunk[i].chunk_length, i);
- }
- x->track_chunk[i].track_data = NULL;
- }
+ int i;
+
+ midifile_close(x);
+
+ for (i = 0; i < MAX_TRACKS; ++i)
+ {
+ if (x->track_chunk[i].track_data != NULL)
+ freebytes(x->track_chunk[i].track_data, x->track_chunk[i].chunk_length);
+ x->track_chunk[i].track_data = NULL;
+ }
}
void midifile_free(t_midifile *x)
{
- midifile_free_file(x);
+ midifile_free_file(x);
}
int midifile_open_path(t_midifile *x, char *path, char *mode)
@@ -244,166 +239,172 @@ int midifile_open_path(t_midifile *x, char *path, char *mode)
/* midifile_open_path attempts to open the file for binary mode reading. */
/* Returns 1 if successful, else 0. */
{
- FILE *fP;
- char tryPath[PATH_BUF_SIZE];
-
- strncpy(tryPath, path, PATH_BUF_SIZE-1); // copy path into a length-limited buffer
- // ...if it doesn't work we won't mess up x->fPath
- tryPath[PATH_BUF_SIZE-1] = '\0'; // just make sure there is a null termination
-
- fP = fopen(tryPath, mode);
- if (fP == NULL) return 0;
- x->fP = fP;
- strncpy(x->fPath, tryPath, PATH_BUF_SIZE);
- return 1;
+ FILE *fP;
+ char tryPath[PATH_BUF_SIZE];
+
+ strncpy(tryPath, path, PATH_BUF_SIZE-1); /* copy path into a length-limited buffer */
+ /* ...if it doesn't work we won't mess up x->fPath */
+ tryPath[PATH_BUF_SIZE-1] = '\0'; /* just make sure there is a null termination */
+
+ fP = fopen(tryPath, mode);
+ if (fP == NULL) return 0;
+ x->fP = fP;
+ strncpy(x->fPath, tryPath, PATH_BUF_SIZE);
+ return 1;
}
void midifile_flush(t_midifile *x)
/* write the header to x->fP, copy x->tmpFP into it, and close both files */
/* flush ends the track */
{
- size_t written = 0L;
- size_t end_time = x->total_time;
- int c;
+ size_t written = 0L;
+ size_t end_time = x->total_time;
+ int c;
- if(x->state != mfWriting) return; // only if we're writing
+ if(x->state != mfWriting) return; /* only if we're writing */
- outlet_bang(x->bang_outlet); // bang so tick count can be saved externally
- midifile_write_end_of_track(x, end_time);
- written = midifile_write_header(x);
+ outlet_bang(x->bang_outlet); /* bang so tick count can be saved externally */
+ midifile_write_end_of_track(x, end_time);
+ written = midifile_write_header(x);
/* now copy the MIDI data from tmpFP to fP */
- rewind (x->tmpFP);
- while ((c = getc(x->tmpFP)) != EOF)
- {
- putc(c, x->fP);
- ++written;
- }
- if (x->verbosity) post ("midifile: wrote %lu to %s", written, x->fPath);
- midifile_close(x);
+ rewind (x->tmpFP);
+ while ((c = getc(x->tmpFP)) != EOF)
+ {
+ putc(c, x->fP);
+ ++written;
+ }
+ if (x->verbosity) post ("midifile: wrote %lu to %s", written, x->fPath);
+ midifile_close(x);
}
size_t midifile_write_header(t_midifile *x)
/* write the MThd and MTrk headers to x->fP */
{
- size_t j, written = 0L;
- int i;
- char c;
-
- rewind (x->fP);
- fprintf (x->fP, "MThd");
- j = 6; // length of header data
- for (i = 0; i < 4; ++i)
- { // msb first
- c = (char)((j & 0xFF000000)>>24);
- putc(c, x->fP);
- j <<= 8;
- }
- j = 0; // type of file
- for (i = 0; i < 2; ++i)
- { // msb first
- c = (char)((j & 0xFF00)>>8);
- putc(c, x->fP);
- j <<= 8;
- }
- j = 1; // number of tracks
- for (i = 0; i < 2; ++i)
- { // msb first
- c = (char)((j & 0xFF00)>>8);
- putc(c, x->fP);
- j <<= 8;
- }
- j = x->header_chunk.chunk_division; // ticks per quarter note
- for (i = 0; i < 2; ++i)
- { // msb first
- c = (char)((j & 0xFF00)>>8);
- putc(c, x->fP);
- j <<= 8;
- }
- fprintf (x->fP, "MTrk");
- j = x->track_chunk[0].chunk_length; // length of MIDI data
-// if (x->verbosity) post ("chunk_length is %lu", j);
- for (i = 0; i < 4; ++i)
- { // msb first
- c = (char)((j & 0xFF000000)>>24);
- putc(c, x->fP);
-// if (x->verbosity) post ("...%d...", c);
- j <<= 8;
- }
- written = 22L;
- return written;
+ size_t j, written = 0L;
+ int i;
+ char c;
+
+ rewind (x->fP);
+ fprintf (x->fP, "MThd");
+ j = 6; /* length of header data */
+ for (i = 0; i < 4; ++i)
+ { /* msb first */
+ c = (char)((j & 0xFF000000)>>24);
+ putc(c, x->fP);
+ j <<= 8;
+ }
+ j = 0; /* type of file */
+ for (i = 0; i < 2; ++i)
+ { /* msb first */
+ c = (char)((j & 0xFF00)>>8);
+ putc(c, x->fP);
+ j <<= 8;
+ }
+ j = 1; /* number of tracks */
+ for (i = 0; i < 2; ++i)
+ { /* msb first */
+ c = (char)((j & 0xFF00)>>8);
+ putc(c, x->fP);
+ j <<= 8;
+ }
+ j = x->header_chunk.chunk_division; /* ticks per quarter note */
+ for (i = 0; i < 2; ++i)
+ { /* msb first */
+ c = (char)((j & 0xFF00)>>8);
+ putc(c, x->fP);
+ j <<= 8;
+ }
+ fprintf (x->fP, "MTrk");
+ j = x->track_chunk[0].chunk_length; /* length of MIDI data */
+ for (i = 0; i < 4; ++i)
+ { /* msb first */
+ c = (char)((j & 0xFF000000)>>24);
+ putc(c, x->fP);
+ j <<= 8;
+ }
+ written = 22L;
+ return written;
}
void midifile_write(t_midifile *x, t_symbol *path)
/* open the file for writing and write the header */
{
- midifile_free_file(x);
- if (midifile_open_path(x, path->s_name, "wb"))
- {
- if (x->verbosity) post("midifile: opened %s", x->fPath);
- x->state = mfWriting;
- x->tmpFP = tmpfile (); // a temporary file for the MIDI data while we don't know how long it is
-
- strncpy (x->header_chunk.chunk_type, "MThd", 4L);// track header chunk
- x->header_chunk.chunk_length = 6L; // 3 ints to follow
- x->header_chunk.chunk_format = 0; // single-track file
- x->header_chunk.chunk_ntrks = 1; // one track for type 0 file
- x->header_chunk.chunk_division = 0; // for now
- strncpy (x->track_chunk[0].chunk_type, "MTrk", 4L);
- x->track_chunk[0].chunk_length = 0L; // for now
- midifile_rewind_tracks(x);
- }
- else error("midifile: Unable to open %s", path->s_name);
+ midifile_free_file(x);
+ if (midifile_open_path(x, path->s_name, "wb"))
+ {
+ if (x->verbosity) post("midifile: opened %s", x->fPath);
+ x->state = mfWriting;
+ x->tmpFP = tmpfile (); /* a temporary file for the MIDI data while we don't know how long it is */
+
+ strncpy (x->header_chunk.chunk_type, "MThd", 4L);/* track header chunk */
+ x->header_chunk.chunk_length = 6L; /* 3 ints to follow */
+ x->header_chunk.chunk_format = 0; /* single-track file */
+ x->header_chunk.chunk_ntrks = 1; /* one track for type 0 file */
+ x->header_chunk.chunk_division = 0; /* for now */
+ strncpy (x->track_chunk[0].chunk_type, "MTrk", 4L);
+ x->track_chunk[0].chunk_length = 0L; /* for now */
+ midifile_rewind_tracks(x);
+ }
+ else error("midifile: Unable to open %s", path->s_name);
}
void midifile_read(t_midifile *x, t_symbol *path)
{
- midifile_free_file(x);
- if (midifile_open_path(x, path->s_name, "rb"))
- {
- if (x->verbosity) post("midifile: opened %s", x->fPath);
- x->state = mfReading;
- if (midifle_read_chunks(x) == 0) midifile_free_file(x);
- }
- else error("midifile: Unable to open %s", path->s_name);
+ midifile_free_file(x);
+ if (midifile_open_path(x, path->s_name, "rb"))
+ {
+ if (x->verbosity) post("midifile: opened %s", x->fPath);
+ x->state = mfReading;
+ if (midifle_read_chunks(x) == 0) midifile_free_file(x);
+ }
+ else error("midifile: Unable to open %s", path->s_name);
}
void midifile_bang(t_midifile *x)
/* step forward one tick and process all tracks for that tick */
{
- int j, result = 1, ended = 0;
- size_t total_time;
-
- switch (x->state)
- {
- case mfReading:
- if (x->verbosity > 2) post("midifile_bang: total_time %lu", x->total_time);
- for (j = 0; ((j < x->header_chunk.chunk_ntrks)&&(result != 0)); ++j)
- {
- if (x->track_chunk[j].total_time != NO_MORE_ELEMENTS)
- {
- while ((total_time = midifile_get_next_track_chunk_delta_time(x, j) + x->track_chunk[j].total_time) == x->total_time)
- {
- if ((x->track == j) ||(x->track == ALL_TRACKS)) midifile_get_next_track_chunk_data(x, j);
- else midifile_skip_next_track_chunk_data(x, j);
- }
- x->ended = 0;
- }
- if (x->track_chunk[j].delta_time == NO_MORE_ELEMENTS) ++ended;
- }
- if ((ended == x->header_chunk.chunk_ntrks)&&(x->ended == 0))
- { // set ended flag, only bang once
- if (x->verbosity > 1) post ("ended = %d x->header_chunk.chunk_ntrks = %d", ended, x->header_chunk.chunk_ntrks);
- outlet_bang(x->bang_outlet);
- ++x->ended;
- }
- // fall through into mfWriting
- case mfWriting:
- ++x->total_time;
- outlet_float(x->total_time_outlet, x->total_time);
- break;
- default:
- break;// don't change time when no files are open
- }
+ int j, result = 1, ended = 0;
+ size_t total_time;
+
+ switch (x->state)
+ {
+ case mfReading:
+ if (x->verbosity > 2) post("midifile_bang: total_time %lu", x->total_time);
+ for (j = 0; ((j < x->header_chunk.chunk_ntrks)&&(result != 0)); ++j)
+ {
+ if (x->track_chunk[j].total_time != NO_MORE_ELEMENTS)
+ {
+ while
+ (
+ (
+ total_time = midifile_get_next_track_chunk_delta_time(x, j)
+ + x->track_chunk[j].total_time
+ )
+ == x->total_time
+ )
+ {
+ if ((x->track == j) ||(x->track == ALL_TRACKS)) midifile_get_next_track_chunk_data(x, j);
+ else midifile_skip_next_track_chunk_data(x, j);
+ }
+ x->ended = 0;
+ }
+ if (x->track_chunk[j].delta_time == NO_MORE_ELEMENTS) ++ended;
+ }
+ if ((ended == x->header_chunk.chunk_ntrks)&&(x->ended == 0))
+ { /* set ended flag, only bang once */
+ if (x->verbosity > 1)
+ post ("ended = %d x->header_chunk.chunk_ntrks = %d", ended, x->header_chunk.chunk_ntrks);
+ outlet_bang(x->bang_outlet);
+ ++x->ended;
+ }
+ /* fall through into mfWriting */
+ case mfWriting:
+ ++x->total_time;
+ outlet_float(x->total_time_outlet, x->total_time);
+ break;
+ default:
+ break;/* don't change time when no files are open */
+ }
}
/* The arguments of the ``list''-method
@@ -415,383 +416,379 @@ void midifile_bang(t_midifile *x)
void midifile_list(t_midifile *x, t_symbol *s, int argc, t_atom *argv)
/* add a list containing time and midi packet to the temporary file in MIDI file format */
{
- int i, j, k, m, dt_written = 0;
- size_t len, written = 0L;
- static int warnings = 0;
-
- if (! x->state == mfWriting) return;// list only works for writing
- if (x->tmpFP == NULL)
- {
- if (0 == warnings++) error ("midifile: no file is open for writing");
- return;
- }
- for (i = 0; i < argc; ++i)
- {
- switch (argv[i].a_type)
- {
- case A_FLOAT:
- {
- j = atom_getint(&argv[i]);
- if (x->verbosity > 2) post ("midifile_list. j[%d] = 0x%lX", i, j);
- if (j <= 0x100)
- {
- if (!dt_written)
- { // deltatime
- x->track_chunk[0].delta_time = x->total_time - x->track_chunk[0].total_time;
- x->track_chunk[0].total_time = x->total_time;
- written = midifile_write_variable_length_value(x->tmpFP, x->track_chunk[0].delta_time);
- dt_written = 1;
- }
- if (j == x->track_chunk[0].running_status) break;// don't save redundant status byte
- if (j >= 0x80 && j <= 0xEF)x->track_chunk[0].running_status = j;// new running status
- else if (j >= 0xF0 && j <= 0xF7)
- {
- x->track_chunk[0].running_status = 0;// clear running status
- if (j == 0xF0)
- { // system exclusive:
- // find length
- for (k = i+1, len = 0L; k < argc; ++k, ++len)
- {
- if (argv[k].a_type != A_FLOAT)
- {
- error ("midifile: sysex list must be all floats");
- x->track_chunk[0].chunk_length += written;
- return;
- }
- m = atom_getint(&argv[k]);
- if (m & 0x80) break;// take any non-data as end of exclusive
- }
- if (m != 0xF7)
- {
- error ("midifile: sysex list terminator is 0x%d", m);
- x->track_chunk[0].chunk_length += written;
- return;
- }
- ++len;
- if (x->verbosity) post ("midifile: sysex length %lu. j = 0x%X", len, j);
- putc (j, x->tmpFP);
- ++written;
- // write length as variable length
- written += midifile_write_variable_length_value (x->tmpFP, len);
- // write the rest of the sysex message
- for (k = i+1; j != 0xF7; ++k)
- {
- j = atom_getint(&argv[k]);
- putc (j, x->tmpFP);
- ++written;
- }
- x->track_chunk[0].chunk_length += written;
- return;
- }
- }
- if (x->verbosity > 1) post ("midifile: j = 0x%X", j);
- putc (j, x->tmpFP);
- ++written;
- }
- break;
- }
- }
- }
- x->track_chunk[0].chunk_length += written;
-// if (x->verbosity) post ("midifile_list");
+ int i, j, k, m, dt_written = 0;
+ size_t len, written = 0L;
+ static int warnings = 0;
+
+ if (! x->state == mfWriting) return;/* list only works for writing */
+ if (x->tmpFP == NULL)
+ {
+ if (0 == warnings++) error ("midifile: no file is open for writing");
+ return;
+ }
+ for (i = 0; i < argc; ++i)
+ {
+ if (A_FLOAT == argv[i].a_type)
+ {
+ j = atom_getint(&argv[i]);
+ if (x->verbosity > 2) post ("midifile_list. j[%d] = 0x%lX", i, j);
+ if (j <= 0x100)
+ {
+ if (!dt_written)
+ { /* deltatime */
+ x->track_chunk[0].delta_time = x->total_time - x->track_chunk[0].total_time;
+ x->track_chunk[0].total_time = x->total_time;
+ written = midifile_write_variable_length_value(x->tmpFP, x->track_chunk[0].delta_time);
+ dt_written = 1;
+ }
+ if (j == x->track_chunk[0].running_status) break;/* don't save redundant status byte */
+ if (j >= 0x80 && j <= 0xEF)x->track_chunk[0].running_status = j;/* new running status */
+ else if (j >= 0xF0 && j <= 0xF7)
+ {
+ x->track_chunk[0].running_status = 0;/* clear running status */
+ if (j == 0xF0)
+ { /* system exclusive: */
+ /* find length */
+ for (k = i+1, len = 0L; k < argc; ++k, ++len)
+ {
+ if (argv[k].a_type != A_FLOAT)
+ {
+ error ("midifile: sysex list must be all floats");
+ x->track_chunk[0].chunk_length += written;
+ return;
+ }
+ m = atom_getint(&argv[k]);
+ if (m & 0x80) break;/* take any non-data as end of exclusive */
+ }
+ if (m != 0xF7)
+ {
+ error ("midifile: sysex list terminator is 0x%d", m);
+ x->track_chunk[0].chunk_length += written;
+ return;
+ }
+ ++len;
+ if (x->verbosity) post ("midifile: sysex length %lu. j = 0x%X", len, j);
+ putc (j, x->tmpFP);
+ ++written;
+ /* write length as variable length */
+ written += midifile_write_variable_length_value (x->tmpFP, len);
+ /* write the rest of the sysex message */
+ for (k = i+1; j != 0xF7; ++k)
+ {
+ j = atom_getint(&argv[k]);
+ putc (j, x->tmpFP);
+ ++written;
+ }
+ x->track_chunk[0].chunk_length += written;
+ return;
+ }
+ }
+ if (x->verbosity > 1) post ("midifile: j = 0x%X", j);
+ putc (j, x->tmpFP);
+ ++written;
+ }
+ }
+ }
+ x->track_chunk[0].chunk_length += written;
}
size_t midifile_write_end_of_track(t_midifile *x, size_t end_time)
/* write End of Track event to x->tmpFP */
{
- size_t written = 0L;
-
- x->track_chunk[0].delta_time = end_time - x->track_chunk[0].total_time;
- x->track_chunk[0].total_time = x->total_time;
- written = midifile_write_variable_length_value (x->tmpFP, x->track_chunk[0].delta_time);
- putc (0xFF, x->tmpFP);
- putc (0x2F, x->tmpFP);
- putc (0x00, x->tmpFP);
- written += 3L;
- x->track_chunk[0].chunk_length += written;
- return written;
+ size_t written = 0L;
+
+ x->track_chunk[0].delta_time = end_time - x->track_chunk[0].total_time;
+ x->track_chunk[0].total_time = x->total_time;
+ written = midifile_write_variable_length_value (x->tmpFP, x->track_chunk[0].delta_time);
+ putc (0xFF, x->tmpFP);
+ putc (0x2F, x->tmpFP);
+ putc (0x00, x->tmpFP);
+ written += 3L;
+ x->track_chunk[0].chunk_length += written;
+ return written;
}
void midifile_float(t_midifile *x, t_float ticks)
/* go to a total time of cue_time */
{
- size_t cTime = (size_t)ticks;
- size_t total_time;
- int j, result = 1, ended = 0;
-
- switch (x->state)
- {
- case mfReading: // cue to ticks
- //if (x->verbosity) post ("midifile_float %d", cTime);
- midifile_rewind_tracks(x);
- for (j = 0; ((j < x->header_chunk.chunk_ntrks)&&(result != 0)); ++j)
- {
- if (x->track_chunk[j].total_time != NO_MORE_ELEMENTS)
- {
- while ((total_time = midifile_get_next_track_chunk_delta_time(x, j) + x->track_chunk[j].total_time) < cTime)
- {
- midifile_skip_next_track_chunk_data(x, j);
- }
- }
- if (x->track_chunk[j].delta_time == NO_MORE_ELEMENTS) ++ended;
- }
- x->total_time = cTime;
- outlet_float(x->total_time_outlet, x->total_time);
- if (ended == x->header_chunk.chunk_ntrks)
- {
- if (x->verbosity) post ("midifile: ended = %d x->header_chunk.chunk_ntrks = %d", ended, x->header_chunk.chunk_ntrks);
- outlet_bang(x->bang_outlet);
- }
- break;
- case mfWriting: // add ticks to current time
- x->total_time += cTime;
- outlet_float(x->total_time_outlet, x->total_time);
- break;
- case mfReset: // do nothing
- break;
- }
-
+ size_t cTime = (size_t)ticks;
+ size_t total_time;
+ int j, result = 1, ended = 0;
+
+ switch (x->state)
+ {
+ case mfReading: /* cue to ticks */
+ midifile_rewind_tracks(x);
+ for (j = 0; ((j < x->header_chunk.chunk_ntrks)&&(result != 0)); ++j)
+ {
+ if (x->track_chunk[j].total_time != NO_MORE_ELEMENTS)
+ {
+ while
+ (
+ (
+ total_time = midifile_get_next_track_chunk_delta_time(x, j)
+ + x->track_chunk[j].total_time
+ )
+ < cTime
+ )
+ midifile_skip_next_track_chunk_data(x, j);
+ }
+ if (x->track_chunk[j].delta_time == NO_MORE_ELEMENTS) ++ended;
+ }
+ x->total_time = cTime;
+ outlet_float(x->total_time_outlet, x->total_time);
+ if (ended == x->header_chunk.chunk_ntrks)
+ {
+ if (x->verbosity)
+ post ("midifile: ended = %d x->header_chunk.chunk_ntrks = %d", ended, x->header_chunk.chunk_ntrks);
+ outlet_bang(x->bang_outlet);
+ }
+ break;
+ case mfWriting: /* add ticks to current time */
+ x->total_time += cTime;
+ outlet_float(x->total_time_outlet, x->total_time);
+ break;
+ case mfReset: /* do nothing */
+ break;
+ }
}
int midifle_read_chunks(t_midifile *x)
{
- int j, result;
-// size_t delta_time;
-
- result = midifile_read_header_chunk(x);
- midifile_rewind_tracks(x);
- for (j = 0; ((j < x->header_chunk.chunk_ntrks)&&(result != 0)); ++j)
- midifile_read_track_chunk(x, j);
- return result;
+ int j, result;
+
+ result = midifile_read_header_chunk(x);
+ midifile_rewind_tracks(x);
+ for (j = 0; ((j < x->header_chunk.chunk_ntrks)&&(result != 0)); ++j)
+ midifile_read_track_chunk(x, j);
+ return result;
}
int midifile_read_header_chunk(t_midifile *x)
{
- char *cP = x->header_chunk.chunk_type;
- char *sP;
- char buf[4];
- size_t n;
- int div, smpte, ticks;
-
- if (x->fP == NULL)
- {
- error("midifile: no open file");
- return 0;// no open file
- }
- rewind(x->fP);
- x->offset = 0L;
- n = fread(cP, 1L, 4L, x->fP);
- x->offset += n;
- if (n != 4L)
- {
- error("midifile: read %lu instead of 4", n);
- return 0;
- }
- if (x->verbosity) post("midifile: Header chunk type: %c%c%c%c", cP[0], cP[1], cP[2], cP[3]);
- if (!(cP[0] == 'M' && cP[1] == 'T' && cP[2] == 'h' && cP[3] == 'd'))
- {
- error ("midifile: bad file format: bad header chunk type");
- return 0;
- }
- cP = buf;
- n = fread(cP, 1L, 4L, x->fP);
- x->offset += n;
- if (n != 4L)
- {
- error("midifile: read %lu instead of 4", n);
- return 0;
- }
- x->header_chunk.chunk_length = midifile_get_multibyte_4(cP);
- if (x->verbosity) post("midifile: Header chunk length: %lu", x->header_chunk.chunk_length);
- if (x->header_chunk.chunk_length != 6L)
- {
- error ("midifile: bad file format: bad header chunk length");
- return 0;
- }
- n = fread(cP, 1L, 2L, x->fP);
- x->offset += n;
- if (n != 2L)
- {
- error("midifile: read %lu instead of 2", n);
- return 0;
- }
- x->header_chunk.chunk_format = midifile_get_multibyte_2(cP);
- switch (x->header_chunk.chunk_format)
- {
- case 0:
- sP = "Single multichannel track";
- break;
- case 1:
- sP = "One or more simultaneous tracks";
- break;
- case 2:
- sP = "One or more sequentially independent single tracks";
- break;
- default:
- sP = "Unknown format";
- }
- if (x->verbosity) post("midifile: Header chunk format: %d (%s)", x->header_chunk.chunk_format, sP);
-
- n = fread(cP, 1L, 2L, x->fP);
- x->offset += n;
- if (n != 2L)
- {
- error("midifile: read %lu instead of 2", n);
- return 0;
- }
- x->header_chunk.chunk_ntrks = midifile_get_multibyte_2(cP);
- if (x->verbosity) post("midifile: Header chunk ntrks: %d", x->header_chunk.chunk_ntrks);
- if (x->header_chunk.chunk_ntrks > MAX_TRACKS)
- {
- error ("midifile: Header chunk ntrks (%d) exceeds midifile MAX_TRACKS, set to %d", x->header_chunk.chunk_ntrks, MAX_TRACKS);
- x->header_chunk.chunk_ntrks = MAX_TRACKS;
- }
-
- n = fread(cP, 1L, 2L, x->fP);
- x->offset += n;
- if (n != 2L)
- {
- error("midifile: read %lu instead of 2", n);
- return 0;
- }
- x->header_chunk.chunk_division = midifile_get_multibyte_2(cP);
- div = x->header_chunk.chunk_division;
- if(div & 0x8000)
- {
- smpte = (-(div>>8)) & 0x0FF;
- ticks = div & 0x0FF;
- if (x->verbosity) post("midifile: Header chunk division: 0x%X: %d frames per second, %d ticks per frame", div, smpte, ticks);
- }
- else
- {
- if (x->verbosity) post("midifile: Header chunk division: 0x%X: %d ticks per quarter note", div, div);
- }
- return 1;
+ char *cP = x->header_chunk.chunk_type;
+ char *sP;
+ char buf[4];
+ size_t n;
+ int div, smpte, ticks;
+
+ if (x->fP == NULL)
+ {
+ error("midifile: no open file");
+ return 0;/* no open file */
+ }
+ rewind(x->fP);
+ x->offset = 0L;
+ n = fread(cP, 1L, 4L, x->fP);
+ x->offset += n;
+ if (n != 4L)
+ {
+ error("midifile: read %lu instead of 4", n);
+ return 0;
+ }
+ if (x->verbosity) post("midifile: Header chunk type: %c%c%c%c", cP[0], cP[1], cP[2], cP[3]);
+ if (!(cP[0] == 'M' && cP[1] == 'T' && cP[2] == 'h' && cP[3] == 'd'))
+ {
+ error ("midifile: bad file format: bad header chunk type");
+ return 0;
+ }
+ cP = buf;
+ n = fread(cP, 1L, 4L, x->fP);
+ x->offset += n;
+ if (n != 4L)
+ {
+ error("midifile: read %lu instead of 4", n);
+ return 0;
+ }
+ x->header_chunk.chunk_length = midifile_get_multibyte_4(cP);
+ if (x->verbosity) post("midifile: Header chunk length: %lu", x->header_chunk.chunk_length);
+ if (x->header_chunk.chunk_length != 6L)
+ {
+ error ("midifile: bad file format: bad header chunk length");
+ return 0;
+ }
+ n = fread(cP, 1L, 2L, x->fP);
+ x->offset += n;
+ if (n != 2L)
+ {
+ error("midifile: read %lu instead of 2", n);
+ return 0;
+ }
+ x->header_chunk.chunk_format = midifile_get_multibyte_2(cP);
+ switch (x->header_chunk.chunk_format)
+ {
+ case 0:
+ sP = "Single multichannel track";
+ break;
+ case 1:
+ sP = "One or more simultaneous tracks";
+ break;
+ case 2:
+ sP = "One or more sequentially independent single tracks";
+ break;
+ default:
+ sP = "Unknown format";
+ }
+ if (x->verbosity) post("midifile: Header chunk format: %d (%s)", x->header_chunk.chunk_format, sP);
+
+ n = fread(cP, 1L, 2L, x->fP);
+ x->offset += n;
+ if (n != 2L)
+ {
+ error("midifile: read %lu instead of 2", n);
+ return 0;
+ }
+ x->header_chunk.chunk_ntrks = midifile_get_multibyte_2(cP);
+ if (x->verbosity) post("midifile: Header chunk ntrks: %d", x->header_chunk.chunk_ntrks);
+ if (x->header_chunk.chunk_ntrks > MAX_TRACKS)
+ {
+ error ("midifile: Header chunk ntrks (%d) exceeds midifile MAX_TRACKS, set to %d",
+ x->header_chunk.chunk_ntrks, MAX_TRACKS);
+ x->header_chunk.chunk_ntrks = MAX_TRACKS;
+ }
+ n = fread(cP, 1L, 2L, x->fP);
+ x->offset += n;
+ if (n != 2L)
+ {
+ error("midifile: read %lu instead of 2", n);
+ return 0;
+ }
+ x->header_chunk.chunk_division = midifile_get_multibyte_2(cP);
+ div = x->header_chunk.chunk_division;
+ if(div & 0x8000)
+ {
+ smpte = (-(div>>8)) & 0x0FF;
+ ticks = div & 0x0FF;
+ if (x->verbosity)
+ post("midifile: Header chunk division: 0x%X: %d frames per second, %d ticks per frame", div, smpte, ticks);
+ }
+ else if (x->verbosity) post("midifile: Header chunk division: 0x%X: %d ticks per quarter note", div, div);
+ return 1;
}
int midifile_read_track_chunk(t_midifile *x, int index)
/* read the data part of a track chunk into track_data */
/* after allocating the space for it */
{
- char *cP = x->track_chunk[index].chunk_type;
- char buf[4];
- char type[5];
- size_t n, len;
-
- if (x->fP == NULL)
- {
- error("midifile: no open file");
- return 0;// no open file
- }
- n = fread(cP, 1L, 4L, x->fP);
- x->offset += n;
- if (n != 4L)
- {
- error("midifile: read %lu instead of 4", n);
- return 0;
- }
- if (!(cP[0] == 'M' && cP[1] == 'T' && cP[2] == 'r' && cP[3] == 'k'))
- {
- error ("midifile: bad file format: bad track chunk type");
- return 0;
- }
- type[0] = cP[0];
- type[1] = cP[1];
- type[2] = cP[2];
- type[3] = cP[3];
- type[4] = '\0';
- cP = buf;
- n = fread(cP, 1L, 4L, x->fP);
- x->offset += n;
- if (n != 4L)
- {
- error("midifile: read %lu instead of 4", n);
- return 0;
- }
- len = midifile_get_multibyte_4(cP);
- x->track_chunk[index].chunk_length = len;
- if (x->verbosity) post("midifile: Track chunk %d type: %s, length %lu", index, type, len);
- if ((cP = getbytes(len)) == NULL)
- {
- error ("midifile: Unable to allocate %lu bytes for track data", len);
- return 0;
- }
- x->track_chunk[index].track_data = cP;
- n = fread(cP, 1L, len, x->fP);
-
- return 1;
+ char *cP = x->track_chunk[index].chunk_type;
+ char buf[4];
+ char type[5];
+ size_t n, len;
+
+ if (x->fP == NULL)
+ {
+ error("midifile: no open file");
+ return 0;/* no open file */
+ }
+ n = fread(cP, 1L, 4L, x->fP);
+ x->offset += n;
+ if (n != 4L)
+ {
+ error("midifile: read %lu instead of 4", n);
+ return 0;
+ }
+ if (!(cP[0] == 'M' && cP[1] == 'T' && cP[2] == 'r' && cP[3] == 'k'))
+ {
+ error ("midifile: bad file format: bad track chunk type");
+ return 0;
+ }
+ type[0] = cP[0];
+ type[1] = cP[1];
+ type[2] = cP[2];
+ type[3] = cP[3];
+ type[4] = '\0';
+ cP = buf;
+ n = fread(cP, 1L, 4L, x->fP);
+ x->offset += n;
+ if (n != 4L)
+ {
+ error("midifile: read %lu instead of 4", n);
+ return 0;
+ }
+ len = midifile_get_multibyte_4(cP);
+ x->track_chunk[index].chunk_length = len;
+ if (x->verbosity) post("midifile: Track chunk %d type: %s, length %lu", index, type, len);
+ if ((cP = getbytes(len)) == NULL)
+ {
+ error ("midifile: Unable to allocate %lu bytes for track data", len);
+ return 0;
+ }
+ x->track_chunk[index].track_data = cP;
+ n = fread(cP, 1L, len, x->fP);
+
+ return 1;
}
unsigned short midifile_combine_bytes(unsigned char data1, unsigned char data2)
/* make a short from two 7bit MIDI data bytes */
{
/*
- unsigned short value = (unsigned short)data2;
- value <<= 7;
- value |= (unsigned short)data1;
- return value;
+ unsigned short value = (unsigned short)data2;
+ value <<= 7;
+ value |= (unsigned short)data1;
+ return value;
*/
- return ((((unsigned short)data2)<< 7) | ((unsigned short)data1));
+ return ((((unsigned short)data2)<< 7) | ((unsigned short)data1));
}
unsigned long midifile_get_multibyte_4(char*n)
/* make a long from 4 consecutive bytes in big-endian format */
{
- unsigned long a, b, c, d, e;
- a = (*(unsigned long *)(&n[0])) & 0x0FF;
- b = (*(unsigned long *)(&n[1])) & 0x0FF;
- c = (*(unsigned long *)(&n[2])) & 0x0FF;
- d = (*(unsigned long *)(&n[3])) &0x0FF;
- e = (a<<24) + (b<<16) + (c<<8) + d;
- return e;
+ unsigned long a, b, c, d, e;
+ a = (*(unsigned long *)(&n[0])) & 0x0FF;
+ b = (*(unsigned long *)(&n[1])) & 0x0FF;
+ c = (*(unsigned long *)(&n[2])) & 0x0FF;
+ d = (*(unsigned long *)(&n[3])) &0x0FF;
+ e = (a<<24) + (b<<16) + (c<<8) + d;
+ return e;
}
unsigned long midifile_get_multibyte_3(char*n)
/* make a long from 3 consecutive bytes in big-endian format */
{
- unsigned long a, b, c, d;
- a = (*(unsigned long *)(&n[0])) & 0x0FF;
- b = (*(unsigned long *)(&n[1])) & 0x0FF;
- c = (*(unsigned long *)(&n[2])) & 0x0FF;
- d = (a<<16) + (b<<8) + c;
- return d;
+ unsigned long a, b, c, d;
+ a = (*(unsigned long *)(&n[0])) & 0x0FF;
+ b = (*(unsigned long *)(&n[1])) & 0x0FF;
+ c = (*(unsigned long *)(&n[2])) & 0x0FF;
+ d = (a<<16) + (b<<8) + c;
+ return d;
}
unsigned short midifile_get_multibyte_2(char*n)
/* make a short from 2 consecutive bytes in big-endian format */
{
- unsigned short a, b, c;
- a = (*(unsigned long *)(&n[0])) & 0x0FF;
- b = (*(unsigned long *)(&n[1])) & 0x0FF;
- c = (a<<8) + b;
- return c;
+ unsigned short a, b, c;
+ a = (*(unsigned long *)(&n[0])) & 0x0FF;
+ b = (*(unsigned long *)(&n[1])) & 0x0FF;
+ c = (a<<8) + b;
+ return c;
}
int midifile_write_variable_length_value (FILE *fP, size_t value)
/* return number of characters written to fP */
{
- size_t buffer;
- int i;
- char c;
-
- buffer = value & 0x07F;
- while ((value >>= 7) > 0)
- {
- buffer <<= 8;
- buffer |= 0x80;
- buffer += (value & 0x07F);
- }
- i = 0;
- while (1)
- {
- c = (char)(buffer & (0x0FF));
- putc(c, fP);
- ++i;
- if (buffer & 0x80) buffer >>= 8;
- else break;
- }
- return i;
+ size_t buffer;
+ int i;
+ char c;
+
+ buffer = value & 0x07F;
+ while ((value >>= 7) > 0)
+ {
+ buffer <<= 8;
+ buffer |= 0x80;
+ buffer += (value & 0x07F);
+ }
+ i = 0;
+ while (1)
+ {
+ c = (char)(buffer & (0x0FF));
+ putc(c, fP);
+ ++i;
+ if (buffer & 0x80) buffer >>= 8;
+ else break;
+ }
+ return i;
}
char *midifile_read_var_len (char *cP, size_t *delta)
@@ -800,645 +797,650 @@ char *midifile_read_var_len (char *cP, size_t *delta)
/* set delta to deltatime */
/* return pointer to following data */
- unsigned long value;
- char c;
-
- if (((value = *(cP++))) & 0x80)
- {
- value &= 0x7f;
- do
- {
- value = (value << 7) + ((c = *(cP++)) & 0x7f);
- } while (c & 0x80);
- }
- *delta = value;
- return cP;
+ unsigned long value;
+ char c;
+
+ if (((value = *(cP++))) & 0x80)
+ {
+ value &= 0x7f;
+ do
+ {
+ value = (value << 7) + ((c = *(cP++)) & 0x7f);
+ } while (c & 0x80);
+ }
+ *delta = value;
+ return cP;
}
void midifile_verbosity(t_midifile *x, t_floatarg verbosity)
/* set verbosity of console output */
{
- x->verbosity = verbosity;
+ x->verbosity = verbosity;
}
void midifile_single_track(t_midifile *x, t_floatarg track)
/* play only this track or all tracks if out of range */
{
- if(x->state != mfReading) return; // only if we're reading
- if ((track < 0) || (track >= x->header_chunk.chunk_ntrks))
- // anything out of range will be interpreted as all tracks
- x->track = ALL_TRACKS;
- else x->track = track;
+ if(x->state != mfReading) return; /* only if we're reading */
+ if ((track < 0) || (track >= x->header_chunk.chunk_ntrks))
+ /* anything out of range will be interpreted as all tracks */
+ x->track = ALL_TRACKS;
+ else x->track = track;
}
void midifile_dump(t_midifile *x, t_floatarg track)
{
- int index = (int)track;
-
- if(x->state != mfReading) return; // only if we're reading
- if ((index < x->header_chunk.chunk_ntrks) && (index >= 0))
- midifile_dump_track_chunk_data(x, index);
- else// anything out of range will be interpreted as all tracks
- for (index = 0; index < x->header_chunk.chunk_ntrks; ++index)
- midifile_dump_track_chunk_data(x, index);
+ int index = (int)track;
+
+ if(x->state != mfReading) return; /* only if we're reading */
+ if ((index < x->header_chunk.chunk_ntrks) && (index >= 0))
+ midifile_dump_track_chunk_data(x, index);
+ else /* anything out of range will be interpreted as all tracks */
+ for (index = 0; index < x->header_chunk.chunk_ntrks; ++index)
+ midifile_dump_track_chunk_data(x, index);
}
void midifile_rewind (t_midifile *x)
{
- if(x->state != mfReading) return; // only if we're reading
- midifile_rewind_tracks(x);
+ if(x->state != mfReading) return; /* only if we're reading */
+ midifile_rewind_tracks(x);
}
void midifile_rewind_tracks(t_midifile *x)
/* For all tracks, point to start of track_data */
{
- int i;
- for (i = 0; i < x->header_chunk.chunk_ntrks; ++i)
- {
- x->track_chunk[i].delta_time = 0L;
- x->track_chunk[i].track_index = 0L;
- x->track_chunk[i].total_time = 0L;
- x->track_chunk[i].running_status = 0;
- }
- x->total_time = 0L;
- x->ended = 0L;
- outlet_float(x->total_time_outlet, x->total_time);
+ int i;
+ for (i = 0; i < x->header_chunk.chunk_ntrks; ++i)
+ {
+ x->track_chunk[i].delta_time = 0L;
+ x->track_chunk[i].track_index = 0L;
+ x->track_chunk[i].total_time = 0L;
+ x->track_chunk[i].running_status = 0;
+ }
+ x->total_time = 0L;
+ x->ended = 0L;
+ outlet_float(x->total_time_outlet, x->total_time);
}
size_t midifile_get_next_track_chunk_delta_time(t_midifile *x, int index)
/* return the delta_time of the next event in track[index] */
{
- unsigned char *cP, *last_cP;
- size_t delta_time;
+ unsigned char *cP, *last_cP;
+ size_t delta_time;
- cP = x->track_chunk[index].track_data + x->track_chunk[index].track_index;
- last_cP = x->track_chunk[index].track_data + x->track_chunk[index].chunk_length;
+ cP = x->track_chunk[index].track_data + x->track_chunk[index].track_index;
+ last_cP = x->track_chunk[index].track_data + x->track_chunk[index].chunk_length;
- delta_time = NO_MORE_ELEMENTS;
- if ((cP != NULL) && (cP < last_cP) && (x->track_chunk[index].delta_time != NO_MORE_ELEMENTS)) cP = midifile_read_var_len(cP, &delta_time);
-// if (x->verbosity) post("delta time for track[%d]: %lu", index, delta_time);
- return delta_time;
+ delta_time = NO_MORE_ELEMENTS;
+ if ((cP != NULL) && (cP < last_cP) && (x->track_chunk[index].delta_time != NO_MORE_ELEMENTS))
+ cP = midifile_read_var_len(cP, &delta_time);
+ return delta_time;
}
void midifile_output_long_list (t_outlet *outlet, unsigned char *cP, size_t len, unsigned char first_byte)
-{ // ouput a long MIDI message as a list of floats
- // first_byte is followed by len bytes at cP
- size_t slen;
- unsigned int si;
- t_atom *slist;
-
- slen = (len+1L)*sizeof(t_atom);
- slist = getbytes (slen);
- if (slist == NULL)
- {
- error ("midifile: no memory for long list");
- return;
- }
- slist[0].a_type = A_FLOAT;
- slist[0].a_w.w_float = 0xF0;
- for (si = 0; si < len; ++si)
- {
- slist[si+1].a_type = A_FLOAT;
- slist[si+1].a_w.w_float = cP[si];
- }
- outlet_list(outlet, &s_list, len+1L, slist);
- freebytes(slist, slen);
+{ /* output a long MIDI message as a list of floats */
+ /* first_byte is followed by len bytes at cP */
+ size_t slen;
+ unsigned int si;
+ t_atom *slist;
+
+ slen = (len+1L)*sizeof(t_atom);
+ slist = getbytes (slen);
+ if (slist == NULL)
+ {
+ error ("midifile: no memory for long list");
+ return;
+ }
+ slist[0].a_type = A_FLOAT;
+ slist[0].a_w.w_float = 0xF0;
+ for (si = 0; si < len; ++si)
+ {
+ slist[si+1].a_type = A_FLOAT;
+ slist[si+1].a_w.w_float = cP[si];
+ }
+ outlet_list(outlet, &s_list, len+1L, slist);
+ freebytes(slist, slen);
}
void midifile_dump_track_chunk_data(t_midifile *x, int index)
/* parse entire track chunk and output it to the main window */
{
- unsigned char *cP, *last_cP, *str;
- size_t total_time, delta_time, time_sig, len;
- unsigned char status, running_status, c, d, nn, dd, cc, bb, mi, mcp, ch;
- char sf;
- unsigned short sn;
- unsigned char tt[3];
- char *msgPtr;
- char msg[256];
-
- cP = x->track_chunk[index].track_data;
- last_cP = x->track_chunk[index].track_data + x->track_chunk[index].chunk_length;
- total_time = 0L;
-
- post("midifile: Parsing track[%d]...", index);
- while ((cP != NULL) && (cP < last_cP) && (x->track_chunk[index].delta_time != NO_MORE_ELEMENTS))
- {
- msgPtr = msg;
- cP = midifile_read_var_len(cP, &delta_time);
- status = *cP++;
- total_time += delta_time;
- msgPtr += sprintf (msgPtr, "tick %lu delta %lu status %02X ", total_time, delta_time, status);
- if ((status & 0xF0) == 0xF0)
- {
- switch (status)
- {
- case 0xF0:
- case 0xF7:
- cP = midifile_read_var_len(cP, &len);// not a time but the same variable length format
- msgPtr += sprintf(msgPtr, "Sysex: %02X length %lu ", status, len);
- cP += len;
- break;
- case 0xF3: // song select
- c = *cP++;
- msgPtr += sprintf(msgPtr, "Song Select: %d ", c);
- break;
- case 0xF2: // song position
- c = *cP++;
- d = *cP++;
- msgPtr += sprintf(msgPtr, "Song Position %d ", midifile_combine_bytes(c, d));
- break;
- case 0xF1: // quarter frame
- msgPtr += sprintf(msgPtr, "MIDI Quarter Frame");
- break;
- case 0xF6: // tune request
- msgPtr += sprintf(msgPtr, "MIDI Tune Request");
- break;
- case 0xF8: // MIDI clock
- msgPtr += sprintf(msgPtr, "MIDI Clock");
- break;
- case 0xF9: // MIDI tick
- msgPtr += sprintf(msgPtr, "MIDI Tick");
- break;
- case 0xFA: // MIDI start
- msgPtr += sprintf(msgPtr, "MIDI Start");
- break;
- case 0xFB: // MIDI continue
- msgPtr += sprintf(msgPtr, "MIDI Continue");
- break;
- case 0xFC: // MIDI stop
- msgPtr += sprintf(msgPtr, "MIDI Stop");
- break;
- case 0xFE: // active sense
- msgPtr += sprintf(msgPtr, "MIDI Active Sense");
- break;
- case 0xFF:
- c = *cP++;
- cP = midifile_read_var_len(cP, &len);// not a time but the same variable length format
- msgPtr += sprintf(msgPtr, "Meta 0x%02X length %lu \n", c, len);
- switch (c)
- {
- case 0x58:
- nn = *cP++;
- dd = *cP++;
- dd = 1<<(dd);
- cc = *cP++;
- bb = *cP++;
- msgPtr += sprintf(msgPtr, "Time Signature %d/%d %d clocks per tick, %d 32nd notes per quarter note", nn, dd, cc, bb);
- break;
- case 0x59:
- sf = *(signed char*)cP++;
- mi = *cP++;
- msgPtr += sprintf(msgPtr, "Key Signature: %d %s, %s", sf, (sf<0)?"flats":"sharps", (mi)?"minor":"major");
- break;
- case 0x51:
- tt[0] = *cP++;
- tt[1] = *cP++;
- tt[2] = *cP++;
- time_sig = midifile_get_multibyte_3(tt);
- msgPtr += sprintf(msgPtr, "%lu microseconds per MIDI quarter-note", time_sig);
- break;
- case 0x2F:
- msgPtr += sprintf(msgPtr, "========End of Track %d==========", index);
- cP += len;
- break;
- case 0x21:
- tt[0] = *cP++;
- msgPtr += sprintf(msgPtr, "MIDI port or cable number (unofficial): %d", tt[0]);
- break;
- case 0x20:
- mcp = *cP++;
- msgPtr += sprintf(msgPtr, "MIDI Channel Prefix: %d", mcp);
- break;
- case 0x06:
- str = cP;
- c = cP[len];
- cP[len] = '\0'; //null terminate temporarily
- msgPtr += sprintf(msgPtr, "Marker %s", str);
- cP[len] = c;
- cP += len;
- break;
- case 0x05:
- str = cP;
- c = cP[len];
- cP[len] = '\0'; //null terminate temporarily
- msgPtr += sprintf(msgPtr, "Lyric %s", str);
- cP[len] = c;
- cP += len;
- break;
- case 0x04:
- str = cP;
- c = cP[len];
- cP[len] = '\0'; //null terminate temporarily
- msgPtr += sprintf(msgPtr, "Instrument Name %s", str);
- cP[len] = c;
- cP += len;
- break;
- case 0x03:
- str = cP;
- c = cP[len];
- cP[len] = '\0'; //null terminate temporarily
- msgPtr += sprintf(msgPtr, "Sequence/Track Name %s", str);
- cP[len] = c;
- cP += len;
- break;
- case 0x02:
- str = cP;
- c = cP[len];
- cP[len] = '\0'; //null terminate temporarily
- msgPtr += sprintf(msgPtr, "Copyright Notice %s", str);
- cP[len] = c;
- cP += len;
- break;
- case 0x01:
- str = cP;
- c = cP[len];
- cP[len] = '\0'; //null terminate temporarily
- msgPtr += sprintf(msgPtr, "Text %s", str);
- cP[len] = c;
- cP += len;
- break;
- case 0x00:
- tt[0] = *cP++;
- tt[1] = *cP++;
- sn = midifile_get_multibyte_2(tt);
- msgPtr += sprintf(msgPtr, "Sequence Number %d", sn);
- break;
- default:
- msgPtr += sprintf(msgPtr, "Unknown: 0x%02X", c);
- cP += len;
- break;
- }
- break;
- default: // 0xF4, 0xF5, 0xF9, 0xFD are not defined
- msgPtr += sprintf(msgPtr, "Undefined: 0x%02X", status);
- break;
- }
- }
- else
- {
- if (status & 0x80)
- {
- running_status = status;
- c = *cP++;
- }
- else
- {
- c = status;
- status = running_status;
- }
- ch = (status & 0x0F) + 1; // MIDI channel number
- switch (status & 0xF0)
- {
- case 0x80:
- d = *cP++; // 2 data bytes
- msgPtr += sprintf(msgPtr, "MIDI 0x%02X %02X %02X : channel %d Note %d Off velocity %d", status, c, d, ch, c, d);
- break;
- case 0x90:
- d = *cP++; // 2 data bytes
- if (d == 0)
- msgPtr += sprintf(msgPtr,"MIDI 0x%02X %02X %02X : channel %d Note %d Off", status, c, d, ch, c);
- else
- msgPtr += sprintf(msgPtr,"MIDI 0x%02X %02X %02X : channel %d Note %d On velocity %d", status, c, d, ch, c, d);
- break;
- case 0xA0:
- d = *cP++; // 2 data bytes
- msgPtr += sprintf(msgPtr,"MIDI: 0x%02X %02X %02X : channel %d Note %d Aftertouch %d", status, c, d, ch, c, d);
- break;
- case 0xB0:
- d = *cP++; // 2 data bytes
- msgPtr += sprintf(msgPtr,"MIDI: 0x%02X %02X %02X : channel %d Controller %d: %d", status, c, d, ch, c, d);
- break;
- case 0xC0: // 1 data byte
- msgPtr += sprintf(msgPtr,"MIDI: 0x%02X %02X: channel %d Program Change: %d", status, c, ch, c);
- break;
- case 0xD0: // 1 data byte
- msgPtr += sprintf(msgPtr,"MIDI: 0x%02X %02X: channel %d Channel Pressure: %d", status, c, ch, c);
- break;
- case 0xE0: // 2 data bytes
- d = *cP++; // 2 data bytes
- msgPtr += sprintf(msgPtr,"MIDI: 0x%02X %02X %02X : channel %d Pitch Wheel %d", status, c, d, ch, midifile_combine_bytes(c, d));
- break;
- }
- }
- post("midifile: %s", msg);
- }
+ unsigned char *cP, *last_cP, *str;
+ size_t total_time, delta_time, time_sig, len;
+ unsigned char status, running_status, c, d, nn, dd, cc, bb, mi, mcp, ch;
+ char sf;
+ unsigned short sn;
+ unsigned char tt[3];
+ char *msgPtr;
+ char msg[256];
+
+ cP = x->track_chunk[index].track_data;
+ last_cP = x->track_chunk[index].track_data + x->track_chunk[index].chunk_length;
+ total_time = 0L;
+
+ post("midifile: Parsing track[%d]...", index);
+ while ((cP != NULL) && (cP < last_cP) && (x->track_chunk[index].delta_time != NO_MORE_ELEMENTS))
+ {
+ msgPtr = msg;
+ cP = midifile_read_var_len(cP, &delta_time);
+ status = *cP++;
+ total_time += delta_time;
+ msgPtr += sprintf (msgPtr, "tick %lu delta %lu status %02X ", total_time, delta_time, status);
+ if ((status & 0xF0) == 0xF0)
+ {
+ switch (status)
+ {
+ case 0xF0:
+ case 0xF7:
+ cP = midifile_read_var_len(cP, &len);/* not a time but the same variable length format */
+ msgPtr += sprintf(msgPtr, "Sysex: %02X length %lu ", status, len);
+ cP += len;
+ break;
+ case 0xF3: /* song select */
+ c = *cP++;
+ msgPtr += sprintf(msgPtr, "Song Select: %d ", c);
+ break;
+ case 0xF2: /* song position */
+ c = *cP++;
+ d = *cP++;
+ msgPtr += sprintf(msgPtr, "Song Position %d ", midifile_combine_bytes(c, d));
+ break;
+ case 0xF1: /* quarter frame */
+ msgPtr += sprintf(msgPtr, "MIDI Quarter Frame");
+ break;
+ case 0xF6: /* tune request */
+ msgPtr += sprintf(msgPtr, "MIDI Tune Request");
+ break;
+ case 0xF8: /* MIDI clock */
+ msgPtr += sprintf(msgPtr, "MIDI Clock");
+ break;
+ case 0xF9: /* MIDI tick */
+ msgPtr += sprintf(msgPtr, "MIDI Tick");
+ break;
+ case 0xFA: /* MIDI start */
+ msgPtr += sprintf(msgPtr, "MIDI Start");
+ break;
+ case 0xFB: /* MIDI continue */
+ msgPtr += sprintf(msgPtr, "MIDI Continue");
+ break;
+ case 0xFC: /* MIDI stop */
+ msgPtr += sprintf(msgPtr, "MIDI Stop");
+ break;
+ case 0xFE: /* active sense */
+ msgPtr += sprintf(msgPtr, "MIDI Active Sense");
+ break;
+ case 0xFF:
+ c = *cP++;
+ cP = midifile_read_var_len(cP, &len);/* not a time but the same variable length format */
+ msgPtr += sprintf(msgPtr, "Meta 0x%02X length %lu \n", c, len);
+ switch (c)
+ {
+ case 0x58:
+ nn = *cP++;
+ dd = *cP++;
+ dd = 1<<(dd);
+ cc = *cP++;
+ bb = *cP++;
+ msgPtr += sprintf(
+ msgPtr, "Time Signature %d/%d %d clocks per tick, %d 32nd notes per quarter note",
+ nn, dd, cc, bb);
+ break;
+ case 0x59:
+ sf = *(signed char*)cP++;
+ mi = *cP++;
+ msgPtr += sprintf(
+ msgPtr, "Key Signature: %d %s, %s",
+ sf, (sf<0)?"flats":"sharps", (mi)?"minor":"major");
+ break;
+ case 0x51:
+ tt[0] = *cP++;
+ tt[1] = *cP++;
+ tt[2] = *cP++;
+ time_sig = midifile_get_multibyte_3(tt);
+ msgPtr += sprintf(msgPtr, "%lu microseconds per MIDI quarter-note", time_sig);
+ break;
+ case 0x2F:
+ msgPtr += sprintf(msgPtr, "========End of Track %d==========", index);
+ cP += len;
+ break;
+ case 0x21:
+ tt[0] = *cP++;
+ msgPtr += sprintf(msgPtr, "MIDI port or cable number (unofficial): %d", tt[0]);
+ break;
+ case 0x20:
+ mcp = *cP++;
+ msgPtr += sprintf(msgPtr, "MIDI Channel Prefix: %d", mcp);
+ break;
+ case 0x06:
+ str = cP;
+ c = cP[len];
+ cP[len] = '\0'; /* null terminate temporarily */
+ msgPtr += sprintf(msgPtr, "Marker %s", str);
+ cP[len] = c;
+ cP += len;
+ break;
+ case 0x05:
+ str = cP;
+ c = cP[len];
+ cP[len] = '\0'; /* null terminate temporarily */
+ msgPtr += sprintf(msgPtr, "Lyric %s", str);
+ cP[len] = c;
+ cP += len;
+ break;
+ case 0x04:
+ str = cP;
+ c = cP[len];
+ cP[len] = '\0'; /* null terminate temporarily */
+ msgPtr += sprintf(msgPtr, "Instrument Name %s", str);
+ cP[len] = c;
+ cP += len;
+ break;
+ case 0x03:
+ str = cP;
+ c = cP[len];
+ cP[len] = '\0'; /* null terminate temporarily */
+ msgPtr += sprintf(msgPtr, "Sequence/Track Name %s", str);
+ cP[len] = c;
+ cP += len;
+ break;
+ case 0x02:
+ str = cP;
+ c = cP[len];
+ cP[len] = '\0'; /* null terminate temporarily */
+ msgPtr += sprintf(msgPtr, "Copyright Notice %s", str);
+ cP[len] = c;
+ cP += len;
+ break;
+ case 0x01:
+ str = cP;
+ c = cP[len];
+ cP[len] = '\0'; /* null terminate temporarily */
+ msgPtr += sprintf(msgPtr, "Text %s", str);
+ cP[len] = c;
+ cP += len;
+ break;
+ case 0x00:
+ tt[0] = *cP++;
+ tt[1] = *cP++;
+ sn = midifile_get_multibyte_2(tt);
+ msgPtr += sprintf(msgPtr, "Sequence Number %d", sn);
+ break;
+ default:
+ msgPtr += sprintf(msgPtr, "Unknown: 0x%02X", c);
+ cP += len;
+ break;
+ }
+ break;
+ default: /* 0xF4, 0xF5, 0xF9, 0xFD are not defined */
+ msgPtr += sprintf(msgPtr, "Undefined: 0x%02X", status);
+ break;
+ }
+ }
+ else
+ {
+ if (status & 0x80)
+ {
+ running_status = status;
+ c = *cP++;
+ }
+ else
+ {
+ c = status;
+ status = running_status;
+ }
+ ch = (status & 0x0F) + 1; /* MIDI channel number */
+ switch (status & 0xF0)
+ {
+ case 0x80:
+ d = *cP++; /* 2 data bytes */
+ msgPtr += sprintf(msgPtr,
+ "MIDI 0x%02X %02X %02X : channel %d Note %d Off velocity %d",
+ status, c, d, ch, c, d);
+ break;
+ case 0x90:
+ d = *cP++; /* 2 data bytes */
+ if (d == 0)
+ msgPtr += sprintf(msgPtr,"MIDI 0x%02X %02X %02X : channel %d Note %d Off", status, c, d, ch, c);
+ else
+ msgPtr += sprintf(msgPtr,
+ "MIDI 0x%02X %02X %02X : channel %d Note %d On velocity %d", status, c, d, ch, c, d);
+ break;
+ case 0xA0:
+ d = *cP++; /* 2 data bytes */
+ msgPtr += sprintf(msgPtr,
+ "MIDI: 0x%02X %02X %02X : channel %d Note %d Aftertouch %d", status, c, d, ch, c, d);
+ break;
+ case 0xB0:
+ d = *cP++; /* 2 data bytes */
+ msgPtr += sprintf(msgPtr,
+ "MIDI: 0x%02X %02X %02X : channel %d Controller %d: %d", status, c, d, ch, c, d);
+ break;
+ case 0xC0: /* 1 data byte */
+ msgPtr += sprintf(msgPtr,"MIDI: 0x%02X %02X: channel %d Program Change: %d", status, c, ch, c);
+ break;
+ case 0xD0: /* 1 data byte */
+ msgPtr += sprintf(msgPtr,"MIDI: 0x%02X %02X: channel %d Channel Pressure: %d", status, c, ch, c);
+ break;
+ case 0xE0: /* 2 data bytes */
+ d = *cP++; /* 2 data bytes */
+ msgPtr += sprintf(msgPtr,
+ "MIDI: 0x%02X %02X %02X : channel %d Pitch Wheel %d",
+ status, c, d, ch, midifile_combine_bytes(c, d));
+ break;
+ }
+ }
+ post("midifile: %s", msg);
+ }
}
void midifile_get_next_track_chunk_data(t_midifile *x, int index)
/* parse the next track chunk data element and output via the appropriate outlet or post to main window */
/* Sets the delta_time of the element or NO_MORE_ELEMENTS if no more elements */
{
- unsigned char *cP, *last_cP, *str;
- size_t delta_time, time_sig, len, i;
- unsigned char status, c, d, nn, dd, cc, bb, mi, mcp, n;
- char sf;
- unsigned short sn;
- unsigned char tt[3];
-
- cP = x->track_chunk[index].track_data + x->track_chunk[index].track_index;
- last_cP = x->track_chunk[index].track_data + x->track_chunk[index].chunk_length;
-
-// if (x->verbosity) post("Parsing track[%d]: ", index);
- delta_time = NO_MORE_ELEMENTS;
- if ((cP != NULL) && (cP < last_cP) && (x->track_chunk[index].delta_time != NO_MORE_ELEMENTS))
- {
- cP = midifile_read_var_len(cP, &delta_time);
- status = *cP++;
-// if (x->verbosity) post ("delta time %lu total_time %lu status %02X", delta_time, x->track_chunk[index].total_time, status);
- if ((status & 0xF0) == 0xF0)
- {
- switch (status)
- {// system message
- case 0xF0:
- case 0xF7:
- cP = midifile_read_var_len(cP, &len); // packet length
- if (x->verbosity) post("midifile: Sysex: %02X length %lu", status, len);
- midifile_output_long_list(x->midi_list_outlet, cP, len, 0xF0);
- /*
- outlet_float(x->sysex_outlet, 0xF0); // sysex status
- for (i = 0; i < len; ++i) outlet_float(x->sysex_outlet, cP[i]); // sysex packet
- //if (cP[len-1] != 0xF7)outlet_float(x->sysex_outlet, 0xF0); // sysex terminator
- */
- cP += len;
- x->track_chunk[index].running_status = 0;
- break;
- case 0xF1: // quarter frame
- x->midi_data[0].a_w.w_float = status;
- outlet_list(x->midi_list_outlet, &s_list, 1, x->midi_data);
- x->track_chunk[index].running_status = 0;
- break;
- case 0xF3: // song select
- c = *cP++;
- x->midi_data[0].a_w.w_float = status;
- x->midi_data[1].a_w.w_float = c;
- outlet_list(x->midi_list_outlet, &s_list, 2, x->midi_data);
- x->track_chunk[index].running_status = 0;
- break;
- case 0xF2: // song position
- c = *cP++;
- x->midi_data[0].a_w.w_float = status;
- x->midi_data[1].a_w.w_float = c;
- c = *cP++;
- x->midi_data[2].a_w.w_float = c;
- outlet_list(x->midi_list_outlet, &s_list, 3, x->midi_data);
- x->track_chunk[index].running_status = 0;
- break;
- case 0xF6: // tune request
- x->midi_data[0].a_w.w_float = status;
- outlet_list(x->midi_list_outlet, &s_list, 1, x->midi_data);
- x->track_chunk[index].running_status = 0;
- break;
- case 0xF8: // MIDI clock
- case 0xF9: // MIDI tick
- case 0xFA: // MIDI start
- case 0xFB: // MIDI continue
- case 0xFC: // MIDI stop
- case 0xFE: // active sense
- x->midi_data[0].a_w.w_float = status;
- outlet_list(x->midi_list_outlet, &s_list, 1, x->midi_data);
- break;
- case 0xFF:
- c = *cP++;
- cP = midifile_read_var_len(cP, &len);// meta length
- if (x->verbosity) post("midifile: Track %d Meta: %02X length %lu", index, c, len);
- switch (c)
- {
- case 0x58:
- nn = *cP++;
- dd = *cP++;
- dd = 1<<(dd);
- cc = *cP++;
- bb = *cP++;
- if (x->verbosity) post ("midifile: Time Signature: %d/%d %d clocks per tick, %d 32nd notes per quarternote", nn, dd, cc, bb);
- break;
- case 0x59:
- sf = *(signed char *)cP++;
- mi = *cP++;
- if (x->verbosity) post ("midifile: Key Signature: %d %s, %s", sf, (sf<0)?"flats":"sharps", (mi)?"minor":"major");
- break;
- case 0x51:
- tt[0] = *cP++;
- tt[1] = *cP++;
- tt[2] = *cP++;
- time_sig = midifile_get_multibyte_3(tt);
- if (x->verbosity) post ("midifile: %lu microseconds per MIDI quarter-note", time_sig);
- break;
- case 0x2F:
- if (x->verbosity) post ("midifile: End of Track %d", index);
- delta_time = NO_MORE_ELEMENTS;
- cP += len;
- break;
- case 0x21:
- tt[0] = *cP++;
- if (x->verbosity) post ("midifile: MIDI port or cable number (unofficial): %d", tt[0]);
- break;
- case 0x20:
- mcp = *cP++;
- if (x->verbosity) post ("midifile: MIDI Channel Prefix: %d", mcp);
- break;
- case 0x06:
- str = cP;
- c = cP[len];
- cP[len] = '\0'; //null terminate temporarily
- if (x->verbosity) post ("midifile: Marker: %s", str);
- cP[len] = c;
- cP += len;
- break;
- case 0x05:
- str = cP;
- c = cP[len];
- cP[len] = '\0'; //null terminate temporarily
- if (x->verbosity) post ("midifile: Lyric: %s", str);
- cP[len] = c;
- cP += len;
- break;
- case 0x04:
- str = cP;
- c = cP[len];
- cP[len] = '\0'; //null terminate temporarily
- if (x->verbosity) post ("midifile: Instrument Name: %s", str);
- cP[len] = c;
- cP += len;
- break;
- case 0x03:
- str = cP;
- c = cP[len];
- cP[len] = '\0'; //null terminate temporarily
- if (x->verbosity) post ("midifile: Sequence/Track Name: %s", str);
- cP[len] = c;
- cP += len;
- break;
- case 0x02:
- str = cP;
- c = cP[len];
- cP[len] = '\0'; //null terminate temporarily
- if (x->verbosity) post ("midifile: Copyright Notice: %s", str);
- cP[len] = c;
- cP += len;
- break;
- case 0x01:
- str = cP;
- c = cP[len];
- cP[len] = '\0'; //null terminate temporarily
- if (x->verbosity) post ("midifile: Text Event: %s", str);
- cP[len] = c;
- cP += len;
- break;
- case 0x00:
- tt[0] = *cP++;
- tt[1] = *cP++;
- sn = midifile_get_multibyte_2(tt);
- if (x->verbosity) post ("midifile: Sequence Number %d", sn);
- break;
- default:
- if (x->verbosity) post ("midifile: Unknown: %02X", c);
- cP += len;
- break;
- }
- break;
- default: // 0xF4, 0xF5, 0xF9, 0xFD are not defined
- break;
- }
- }
- else
- {
- if (status & 0x80)
- {
- x->track_chunk[index].running_status = status;// status is true status
- c = *cP++;
- }
- else
- {
- c = status; // status is actually 1st data byte
- status = x->track_chunk[index].running_status;// current status
- }
- switch (status & 0xF0)
- {
- case 0x80:
- case 0x90:
- case 0xA0:
- case 0xB0:
- case 0xE0:
- n = 3;
- d = *cP++; // 2 data bytes
- break;
- case 0xC0: // 1 data byte
- case 0xD0:
- n = 2;
- break;
- }
- x->midi_data[0].a_w.w_float = status;
- x->midi_data[1].a_w.w_float = c;
- x->midi_data[2].a_w.w_float = (n == 3)?d:0;
- if (x->midi_data[0].a_w.w_float != 0) outlet_list(x->midi_list_outlet, &s_list, n, x->midi_data);
- //if (x->verbosity) post("MIDI: %02X %d %d", x->track_chunk[index].running_status, c, d);
- if (x->track_chunk[index].running_status == 0)
- error ("midifile: No running status on track %d at %lu", index, x->track_chunk[index].total_time + delta_time);
- }
- }
- x->track_chunk[index].track_index = (char *)cP - (char *)x->track_chunk[index].track_data;
- x->track_chunk[index].delta_time = delta_time;
- if (delta_time == NO_MORE_ELEMENTS) x->track_chunk[index].total_time = delta_time;
- else x->track_chunk[index].total_time += delta_time;
+ unsigned char *cP, *last_cP, *str;
+ size_t delta_time, time_sig, len, i;
+ unsigned char status, c, d, nn, dd, cc, bb, mi, mcp, n;
+ char sf;
+ unsigned short sn;
+ unsigned char tt[3];
+
+ cP = x->track_chunk[index].track_data + x->track_chunk[index].track_index;
+ last_cP = x->track_chunk[index].track_data + x->track_chunk[index].chunk_length;
+
+ delta_time = NO_MORE_ELEMENTS;
+ if ((cP != NULL) && (cP < last_cP) && (x->track_chunk[index].delta_time != NO_MORE_ELEMENTS))
+ {
+ cP = midifile_read_var_len(cP, &delta_time);
+ status = *cP++;
+ if ((status & 0xF0) == 0xF0)
+ {
+ switch (status)
+ { /* system message */
+ case 0xF0:
+ case 0xF7:
+ cP = midifile_read_var_len(cP, &len); /* packet length */
+ if (x->verbosity) post("midifile: Sysex: %02X length %lu", status, len);
+ midifile_output_long_list(x->midi_list_outlet, cP, len, 0xF0);
+ cP += len;
+ x->track_chunk[index].running_status = 0;
+ break;
+ case 0xF1: /* quarter frame */
+ x->midi_data[0].a_w.w_float = status;
+ outlet_list(x->midi_list_outlet, &s_list, 1, x->midi_data);
+ x->track_chunk[index].running_status = 0;
+ break;
+ case 0xF3: /* song select */
+ c = *cP++;
+ x->midi_data[0].a_w.w_float = status;
+ x->midi_data[1].a_w.w_float = c;
+ outlet_list(x->midi_list_outlet, &s_list, 2, x->midi_data);
+ x->track_chunk[index].running_status = 0;
+ break;
+ case 0xF2: /* song position */
+ c = *cP++;
+ x->midi_data[0].a_w.w_float = status;
+ x->midi_data[1].a_w.w_float = c;
+ c = *cP++;
+ x->midi_data[2].a_w.w_float = c;
+ outlet_list(x->midi_list_outlet, &s_list, 3, x->midi_data);
+ x->track_chunk[index].running_status = 0;
+ break;
+ case 0xF6: /* tune request */
+ x->midi_data[0].a_w.w_float = status;
+ outlet_list(x->midi_list_outlet, &s_list, 1, x->midi_data);
+ x->track_chunk[index].running_status = 0;
+ break;
+ case 0xF8: /* MIDI clock */
+ case 0xF9: /* MIDI tick */
+ case 0xFA: /* MIDI start */
+ case 0xFB: /* MIDI continue */
+ case 0xFC: /* MIDI stop */
+ case 0xFE: /* active sense */
+ x->midi_data[0].a_w.w_float = status;
+ outlet_list(x->midi_list_outlet, &s_list, 1, x->midi_data);
+ break;
+ case 0xFF:
+ c = *cP++;
+ cP = midifile_read_var_len(cP, &len);/* meta length */
+ if (x->verbosity) post("midifile: Track %d Meta: %02X length %lu", index, c, len);
+ switch (c)
+ {
+ case 0x58:
+ nn = *cP++;
+ dd = *cP++;
+ dd = 1<<(dd);
+ cc = *cP++;
+ bb = *cP++;
+ if (x->verbosity)
+ post ("midifile: Time Signature: %d/%d %d clocks per tick, %d 32nd notes per quarternote",
+ nn, dd, cc, bb);
+ break;
+ case 0x59:
+ sf = *(signed char *)cP++;
+ mi = *cP++;
+ if (x->verbosity)
+ post ("midifile: Key Signature: %d %s, %s",
+ sf, (sf<0)?"flats":"sharps", (mi)?"minor":"major");
+ break;
+ case 0x51:
+ tt[0] = *cP++;
+ tt[1] = *cP++;
+ tt[2] = *cP++;
+ time_sig = midifile_get_multibyte_3(tt);
+ if (x->verbosity) post ("midifile: %lu microseconds per MIDI quarter-note", time_sig);
+ break;
+ case 0x2F:
+ if (x->verbosity) post ("midifile: End of Track %d", index);
+ delta_time = NO_MORE_ELEMENTS;
+ cP += len;
+ break;
+ case 0x21:
+ tt[0] = *cP++;
+ if (x->verbosity) post ("midifile: MIDI port or cable number (unofficial): %d", tt[0]);
+ break;
+ case 0x20:
+ mcp = *cP++;
+ if (x->verbosity) post ("midifile: MIDI Channel Prefix: %d", mcp);
+ break;
+ case 0x06:
+ str = cP;
+ c = cP[len];
+ cP[len] = '\0'; /* null terminate temporarily */
+ if (x->verbosity) post ("midifile: Marker: %s", str);
+ cP[len] = c;
+ cP += len;
+ break;
+ case 0x05:
+ str = cP;
+ c = cP[len];
+ cP[len] = '\0'; /* null terminate temporarily */
+ if (x->verbosity) post ("midifile: Lyric: %s", str);
+ cP[len] = c;
+ cP += len;
+ break;
+ case 0x04:
+ str = cP;
+ c = cP[len];
+ cP[len] = '\0'; /* null terminate temporarily */
+ if (x->verbosity) post ("midifile: Instrument Name: %s", str);
+ cP[len] = c;
+ cP += len;
+ break;
+ case 0x03:
+ str = cP;
+ c = cP[len];
+ cP[len] = '\0'; /* null terminate temporarily */
+ if (x->verbosity) post ("midifile: Sequence/Track Name: %s", str);
+ cP[len] = c;
+ cP += len;
+ break;
+ case 0x02:
+ str = cP;
+ c = cP[len];
+ cP[len] = '\0'; /* null terminate temporarily */
+ if (x->verbosity) post ("midifile: Copyright Notice: %s", str);
+ cP[len] = c;
+ cP += len;
+ break;
+ case 0x01:
+ str = cP;
+ c = cP[len];
+ cP[len] = '\0'; /* null terminate temporarily */
+ if (x->verbosity) post ("midifile: Text Event: %s", str);
+ cP[len] = c;
+ cP += len;
+ break;
+ case 0x00:
+ tt[0] = *cP++;
+ tt[1] = *cP++;
+ sn = midifile_get_multibyte_2(tt);
+ if (x->verbosity) post ("midifile: Sequence Number %d", sn);
+ break;
+ default:
+ if (x->verbosity) post ("midifile: Unknown: %02X", c);
+ cP += len;
+ break;
+ }
+ break;
+ default: /* 0xF4, 0xF5, 0xF9, 0xFD are not defined */
+ break;
+ }
+ }
+ else
+ {
+ if (status & 0x80)
+ {
+ x->track_chunk[index].running_status = status;/* status is true status */
+ c = *cP++;
+ }
+ else
+ {
+ c = status; /* status is actually 1st data byte */
+ status = x->track_chunk[index].running_status; /* current status */
+ }
+ switch (status & 0xF0)
+ {
+ case 0x80:
+ case 0x90:
+ case 0xA0:
+ case 0xB0:
+ case 0xE0:
+ n = 3;
+ d = *cP++; /* 2 data bytes */
+ break;
+ case 0xC0: /* 1 data byte */
+ case 0xD0:
+ n = 2;
+ break;
+ }
+ x->midi_data[0].a_w.w_float = status;
+ x->midi_data[1].a_w.w_float = c;
+ x->midi_data[2].a_w.w_float = (n == 3)?d:0;
+ if (x->midi_data[0].a_w.w_float != 0) outlet_list(x->midi_list_outlet, &s_list, n, x->midi_data);
+ if (x->track_chunk[index].running_status == 0)
+ error ("midifile: No running status on track %d at %lu",
+ index, x->track_chunk[index].total_time + delta_time);
+ }
+ }
+ x->track_chunk[index].track_index = (char *)cP - (char *)x->track_chunk[index].track_data;
+ x->track_chunk[index].delta_time = delta_time;
+ if (delta_time == NO_MORE_ELEMENTS) x->track_chunk[index].total_time = delta_time;
+ else x->track_chunk[index].total_time += delta_time;
}
void midifile_skip_next_track_chunk_data(t_midifile *x, int index)
/* parse the next track chunk data element and skip it without any output */
/* Sets the delta_time of the element or NO_MORE_ELEMENTS if no more elements */
{
- unsigned char *cP, *last_cP;
- size_t delta_time, len;
- unsigned char status, c, n;
-
- cP = x->track_chunk[index].track_data + x->track_chunk[index].track_index;
- last_cP = x->track_chunk[index].track_data + x->track_chunk[index].chunk_length;
-
-// if (x->verbosity) post("Parsing track[%d]: ", index);
- delta_time = NO_MORE_ELEMENTS;
-
- if ((cP != NULL) && (cP < last_cP) && (x->track_chunk[index].delta_time != NO_MORE_ELEMENTS))
- {
- cP = midifile_read_var_len(cP, &delta_time);
- status = *cP++;
-// if (x->verbosity) post ("delta time %lu total_time %lu status %02X", delta_time, x->track_chunk[index].total_time, status);
- if ((status & 0xF0) == 0xF0)
- {
- switch (status)
- {// system message
- case 0xF0:
- case 0xF7:
- cP = midifile_read_var_len(cP, &len); // packet length
- cP += len;
- break;
- case 0xF1: // quarter frame
- break;
- case 0xF3: // song select
- cP += 1;
- break;
- case 0xF2: // song position
- cP += 2;
- break;
- case 0xF6: // tune request
- case 0xF8: // MIDI clock
- case 0xF9: // MIDI tick
- case 0xFA: // MIDI start
- case 0xFB: // MIDI continue
- case 0xFC: // MIDI stop
- case 0xFE: // active sense
- break;
- case 0xFF:
- c = *cP++;
- cP = midifile_read_var_len(cP, &len);// meta length
- // if (x->verbosity) post("Meta: %02X length %lu", c, len);
- switch (c)
- {
- case 0x2F:
- if (x->verbosity) post ("midifile: End of Track %d", index);
- delta_time = NO_MORE_ELEMENTS;
- // fall through to default....
- default:
- cP += len;
- break;
- }
- break;
- default: // 0xF4, 0xF5, 0xF9, 0xFD are not defined
- break;
- }
- }
- else
- {
- if (status & 0x80)
- {
- x->track_chunk[index].running_status = status;
- n = 1;
- }
- else
- {
- n = 0; // no status in this message
- status = x->track_chunk[index].running_status;
- }
- switch (status & 0xF0)
- {
- case 0x80:
- case 0x90:
- case 0xA0:
- case 0xB0:
- case 0xE0:
- n += 1; // data bytes
- break;
- case 0xC0:
- case 0xD0:// only one data byte
- break;
- }
- cP += n;
- }
- }
- x->track_chunk[index].track_index = (char *)cP - (char *)x->track_chunk[index].track_data;
- x->track_chunk[index].delta_time = delta_time;
- if (delta_time == NO_MORE_ELEMENTS) x->track_chunk[index].total_time = delta_time;
- else x->track_chunk[index].total_time += delta_time;
+ unsigned char *cP, *last_cP;
+ size_t delta_time, len;
+ unsigned char status, c, n;
+
+ cP = x->track_chunk[index].track_data + x->track_chunk[index].track_index;
+ last_cP = x->track_chunk[index].track_data + x->track_chunk[index].chunk_length;
+
+ delta_time = NO_MORE_ELEMENTS;
+
+ if ((cP != NULL) && (cP < last_cP) && (x->track_chunk[index].delta_time != NO_MORE_ELEMENTS))
+ {
+ cP = midifile_read_var_len(cP, &delta_time);
+ status = *cP++;
+ if ((status & 0xF0) == 0xF0)
+ {
+ switch (status)
+ { /* system message */
+ case 0xF0:
+ case 0xF7:
+ cP = midifile_read_var_len(cP, &len); /* packet length */
+ cP += len;
+ break;
+ case 0xF1: /* quarter frame */
+ break;
+ case 0xF3: /* song select */
+ cP += 1;
+ break;
+ case 0xF2: /* song position */
+ cP += 2;
+ break;
+ case 0xF6: /* tune request */
+ case 0xF8: /* MIDI clock */
+ case 0xF9: /* MIDI tick */
+ case 0xFA: /* MIDI start */
+ case 0xFB: /* MIDI continue */
+ case 0xFC: /* MIDI stop */
+ case 0xFE: /* active sense */
+ break;
+ case 0xFF:
+ c = *cP++;
+ cP = midifile_read_var_len(cP, &len);/* meta length */
+ switch (c)
+ {
+ case 0x2F:
+ if (x->verbosity) post ("midifile: End of Track %d", index);
+ delta_time = NO_MORE_ELEMENTS;
+ /* fall through to default....*/
+ default:
+ cP += len;
+ break;
+ }
+ break;
+ default: /* 0xF4, 0xF5, 0xF9, 0xFD are not defined */
+ break;
+ }
+ }
+ else
+ {
+ if (status & 0x80)
+ {
+ x->track_chunk[index].running_status = status;
+ n = 1;
+ }
+ else
+ {
+ n = 0; /* no status in this message */
+ status = x->track_chunk[index].running_status;
+ }
+ switch (status & 0xF0)
+ {
+ case 0x80:
+ case 0x90:
+ case 0xA0:
+ case 0xB0:
+ case 0xE0:
+ n += 1; /* data bytes */
+ break;
+ case 0xC0:
+ case 0xD0: /* only one data byte */
+ break;
+ }
+ cP += n;
+ }
+ }
+ x->track_chunk[index].track_index = (char *)cP - (char *)x->track_chunk[index].track_data;
+ x->track_chunk[index].delta_time = delta_time;
+ if (delta_time == NO_MORE_ELEMENTS) x->track_chunk[index].total_time = delta_time;
+ else x->track_chunk[index].total_time += delta_time;
}
/* fin midifile.c */