aboutsummaryrefslogtreecommitdiff
path: root/midifile
diff options
context:
space:
mode:
Diffstat (limited to 'midifile')
-rw-r--r--midifile/midifile.c130
1 files changed, 71 insertions, 59 deletions
diff --git a/midifile/midifile.c b/midifile/midifile.c
index bd28d22..747e794 100644
--- a/midifile/midifile.c
+++ b/midifile/midifile.c
@@ -1,5 +1,5 @@
/* midifile.c An external for Pure Data that reads and writes MIDI files
-* Copyright (C) 2005-2008 Martin Peach
+* Copyright (C) 2005-2014 Martin Peach
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -45,11 +45,11 @@ 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
@@ -60,7 +60,7 @@ typedef struct mf_track_chunk
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;
+ unsigned char *track_data;
} mf_track_chunk;
typedef struct t_midifile
@@ -89,12 +89,12 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex);
static size_t midifile_get_next_track_chunk_delta_time(t_midifile *x, int mfindex);
static void midifile_output_long_list (t_outlet *outlet, unsigned char *cP, size_t len, unsigned char first_byte);
static void midifile_dump_track_chunk_data(t_midifile *x, int mfindex);
-static char *midifile_read_var_len (char *cP, size_t *delta);
+static unsigned char *midifile_read_var_len (unsigned char *cP, size_t *delta);
static int midifile_write_variable_length_value (FILE *fP, size_t value);
static unsigned short midifile_combine_bytes(unsigned char data1, unsigned char data2);
-static unsigned short midifile_get_multibyte_2(char*n);
-static unsigned long midifile_get_multibyte_3(char*n);
-static unsigned long midifile_get_multibyte_4(char*n);
+static unsigned short midifile_get_multibyte_2(unsigned char*n);
+static unsigned long midifile_get_multibyte_3(unsigned char*n);
+static unsigned long midifile_get_multibyte_4(unsigned char*n);
static int midifile_read_track_chunk(t_midifile *x, int mfindex);
static int midifile_read_header_chunk(t_midifile *x);
static void midifile_rewind (t_midifile *x);
@@ -121,6 +121,8 @@ void midifile_setup(void);
void midifile_setup(void)
{
+ char aStr[] = "midifile 20140127 by Martin Peach";
+
midifile_class = class_new (gensym("midifile"),
(t_newmethod) midifile_new,
(t_method)midifile_free, sizeof(t_midifile),
@@ -138,6 +140,11 @@ void midifile_setup(void)
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"));
+#if PD_MAJOR_VERSION==0 && PD_MINOR_VERSION<43
+ post(aStr);
+#else
+ logpost(NULL, 3, aStr);
+#endif
}
static void *midifile_new(t_symbol *s, int argc, t_atom *argv)
@@ -154,6 +161,11 @@ static void *midifile_new(t_symbol *s, int argc, t_atom *argv)
x->fP = NULL;
x->fPath[0] = '\0';
x->our_directory = canvas_getcurrentdir();/* get the current directory to use as the base for relative file paths */
+//#if PD_MAJOR_VERSION==0 && PD_MINOR_VERSION<43
+// post(x->our_directory->s_name);
+//#else
+// logpost(NULL, 3, x->our_directory->s_name);
+//#endif
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;
@@ -184,7 +196,6 @@ static void *midifile_new(t_symbol *s, int argc, t_atom *argv)
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->status_outlet = outlet_new(&x->x_obj, &s_anything);/* last outlet for everything else */
- post("midifile 20110212 by Martin Peach");
return (void *)x;
}
@@ -337,7 +348,7 @@ static size_t midifile_write_header(t_midifile *x)
static void midifile_write(t_midifile *x, t_symbol *s, int argc, t_atom *argv)
/* open the file for writing and write the header */
{
- char *path;
+ char *path = NULL;
int frames_per_second = 0;/* default */
int ticks_per_frame = 90; /* default*/
@@ -443,7 +454,7 @@ static void midifile_bang(t_midifile *x)
static 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;
+ int i, j, k, m = 0, dt_written = 0;
size_t len, written = 0L;
static int warnings = 0;
@@ -593,12 +604,12 @@ static int midifle_read_chunks(t_midifile *x)
static 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;
- t_atom output_atom;
+ unsigned char *cP = (unsigned char *)x->header_chunk.chunk_type;
+ char *sP;
+ char buf[4];
+ size_t n;
+ int div, smpte, ticks;
+ t_atom output_atom;
if (x->fP == NULL)
{
@@ -611,7 +622,7 @@ static int midifile_read_header_chunk(t_midifile *x)
x->offset += n;
if (n != 4L)
{
- error("midifile: read %lu instead of 4", n);
+ error("midifile: read %zu 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]);
@@ -620,12 +631,12 @@ static int midifile_read_header_chunk(t_midifile *x)
error ("midifile: bad file format: bad header chunk type");
return 0;
}
- cP = buf;
+ cP = (unsigned char *)buf;
n = fread(cP, 1L, 4L, x->fP);
x->offset += n;
if (n != 4L)
{
- error("midifile: read %lu instead of 4", n);
+ error("midifile: read %zu instead of 4", n);
return 0;
}
x->header_chunk.chunk_length = midifile_get_multibyte_4(cP);
@@ -639,7 +650,7 @@ static int midifile_read_header_chunk(t_midifile *x)
x->offset += n;
if (n != 2L)
{
- error("midifile: read %lu instead of 2", n);
+ error("midifile: read %zu instead of 2", n);
return 0;
}
x->header_chunk.chunk_format = midifile_get_multibyte_2(cP);
@@ -665,7 +676,7 @@ static int midifile_read_header_chunk(t_midifile *x)
x->offset += n;
if (n != 2L)
{
- error("midifile: read %lu instead of 2", n);
+ error("midifile: read %zu instead of 2", n);
return 0;
}
x->header_chunk.chunk_ntrks = midifile_get_multibyte_2(cP);
@@ -682,7 +693,7 @@ static int midifile_read_header_chunk(t_midifile *x)
x->offset += n;
if (n != 2L)
{
- error("midifile: read %lu instead of 2", n);
+ error("midifile: read %zu instead of 2", n);
return 0;
}
x->header_chunk.chunk_division = midifile_get_multibyte_2(cP);
@@ -712,10 +723,10 @@ static int midifile_read_track_chunk(t_midifile *x, int mfindex)
/* read the data part of a track chunk into track_data */
/* after allocating the space for it */
{
- char *cP = x->track_chunk[mfindex].chunk_type;
- char buf[4];
- char type[5];
- size_t n, len;
+ unsigned char *cP = (unsigned char *)x->track_chunk[mfindex].chunk_type;
+ char buf[4];
+ char type[5];
+ size_t n, len;
if (x->fP == NULL)
{
@@ -726,7 +737,7 @@ static int midifile_read_track_chunk(t_midifile *x, int mfindex)
x->offset += n;
if (n != 4L)
{
- error("midifile: read %lu instead of 4", n);
+ error("midifile: read %zu instead of 4", n);
return 0;
}
if (!(cP[0] == 'M' && cP[1] == 'T' && cP[2] == 'r' && cP[3] == 'k'))
@@ -739,23 +750,23 @@ static int midifile_read_track_chunk(t_midifile *x, int mfindex)
type[2] = cP[2];
type[3] = cP[3];
type[4] = '\0';
- cP = buf;
+ cP = (unsigned char *)buf;
n = fread(cP, 1L, 4L, x->fP);
x->offset += n;
if (n != 4L)
{
- error("midifile: read %lu instead of 4", n);
+ error("midifile: read %zu instead of 4", n);
return 0;
}
len = midifile_get_multibyte_4(cP);
x->track_chunk[mfindex].chunk_length = len;
- if (x->verbosity) post("midifile: Track chunk %d type: %s, length %lu", mfindex, type, len);
+ if (x->verbosity) post("midifile: Track chunk %d type: %s, length %zu", mfindex, type, len);
if ((cP = getbytes(len)) == NULL)
{
- error ("midifile: Unable to allocate %lu bytes for track data", len);
+ error ("midifile: Unable to allocate %zu bytes for track data", len);
return 0;
}
- x->track_chunk[mfindex].track_data = cP;
+ x->track_chunk[mfindex].track_data = (unsigned char*)cP;
n = fread(cP, 1L, len, x->fP);
return 1;
@@ -773,7 +784,7 @@ static unsigned short midifile_combine_bytes(unsigned char data1, unsigned char
return ((((unsigned short)data2)<< 7) | ((unsigned short)data1));
}
-static unsigned long midifile_get_multibyte_4(char*n)
+static unsigned long midifile_get_multibyte_4(unsigned char*n)
/* make a long from 4 consecutive bytes in big-endian format */
{
unsigned long a, b, c, d, e;
@@ -785,7 +796,7 @@ static unsigned long midifile_get_multibyte_4(char*n)
return e;
}
-static unsigned long midifile_get_multibyte_3(char*n)
+static unsigned long midifile_get_multibyte_3(unsigned char*n)
/* make a long from 3 consecutive bytes in big-endian format */
{
unsigned long a, b, c, d;
@@ -796,7 +807,7 @@ static unsigned long midifile_get_multibyte_3(char*n)
return d;
}
-static unsigned short midifile_get_multibyte_2(char*n)
+static unsigned short midifile_get_multibyte_2(unsigned char*n)
/* make a short from 2 consecutive bytes in big-endian format */
{
unsigned short a, b, c;
@@ -833,7 +844,7 @@ static int midifile_write_variable_length_value (FILE *fP, size_t value)
return i;
}
-static char *midifile_read_var_len (char *cP, size_t *delta)
+static unsigned char *midifile_read_var_len (unsigned char *cP, size_t *delta)
{
/* enter with cP pointing to deltatime */
/* set delta to deltatime */
@@ -936,7 +947,7 @@ static void midifile_output_long_list (t_outlet *outlet, unsigned char *cP, size
return;
}
slist[0].a_type = A_FLOAT;
- slist[0].a_w.w_float = 0xF0;
+ slist[0].a_w.w_float = first_byte;//0xF0;
for (si = 0; si < len; ++si)
{
slist[si+1].a_type = A_FLOAT;
@@ -950,8 +961,9 @@ static void midifile_dump_track_chunk_data(t_midifile *x, int mfindex)
/* 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;
+ size_t total_time, delta_time, len;
+ unsigned long time_sig;
+ unsigned char status, running_status = 0, c, d, nn, dd, cc, bb, mi, mcp, ch;
char sf;
unsigned short sn;
unsigned char tt[3];
@@ -969,7 +981,7 @@ static void midifile_dump_track_chunk_data(t_midifile *x, int mfindex)
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);
+ msgPtr += sprintf (msgPtr, "tick %zu delta %zu status %02X ", total_time, delta_time, status);
if ((status & 0xF0) == 0xF0)
{
switch (status)
@@ -977,7 +989,7 @@ static void midifile_dump_track_chunk_data(t_midifile *x, int mfindex)
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);
+ msgPtr += sprintf(msgPtr, "Sysex: %02X length %zu ", status, len);
cP += len;
break;
case 0xF3: /* song select */
@@ -1016,7 +1028,7 @@ static void midifile_dump_track_chunk_data(t_midifile *x, int mfindex)
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);
+ msgPtr += sprintf(msgPtr, "Meta 0x%02X length %zu \n", c, len);
switch (c)
{
case 0x58:
@@ -1182,7 +1194,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex)
/* 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;
+ size_t delta_time, time_sig, len;
unsigned char status, c, d, nn, dd, cc, bb, mi, mcp, n;
char sf;
char fps, hour, min, sec, frame, subframe;
@@ -1206,7 +1218,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex)
case 0xF0:
case 0xF7:
cP = midifile_read_var_len(cP, &len); /* packet length */
- if (x->verbosity) post("midifile: Sysex: %02X length %lu", status, len);
+ if (x->verbosity) post("midifile: Sysex: %02X length %zu", status, len);
midifile_output_long_list(x->midi_list_outlet, cP, len, 0xF0);
cP += len;
x->track_chunk[mfindex].running_status = 0;
@@ -1249,7 +1261,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex)
case 0xFF: /* meta event */
c = *cP++;
cP = midifile_read_var_len(cP, &len);/* meta length */
- if (x->verbosity) post("midifile: Track %d Meta: %02X length %lu", mfindex, c, len);
+ if (x->verbosity) post("midifile: Track %d Meta: %02X length %zu", mfindex, c, len);
switch (c)
{
case 0x59: /* key signature */
@@ -1301,7 +1313,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex)
sec = *cP++;
frame = *cP++;
subframe = *cP++;
- if (x->verbosity) post ("midifile: %lu SMPTE offset: %d:%d:%d:%d:%d, %d fps", hour, min, sec, frame, subframe, fps);
+ if (x->verbosity) post ("midifile: SMPTE offset: %d:%d:%d:%d:%d, %d fps", hour, min, sec, frame, subframe, fps);
SETFLOAT(&output_atom[0], hour);
SETFLOAT(&output_atom[1], min);
SETFLOAT(&output_atom[2], sec);
@@ -1343,7 +1355,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex)
c = cP[len];
cP[len] = '\0'; /* null terminate temporarily */
if (x->verbosity) post ("midifile: Cue Point: %s", str);
- SETSYMBOL(&output_atom[0], gensym(str));
+ SETSYMBOL(&output_atom[0], gensym((char *)str));
outlet_anything( x->status_outlet, gensym("cue"), 1, output_atom);
cP[len] = c;
cP += len;
@@ -1353,7 +1365,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex)
c = cP[len];
cP[len] = '\0'; /* null terminate temporarily */
if (x->verbosity) post ("midifile: Marker: %s", str);
- SETSYMBOL(&output_atom[0], gensym(str));
+ SETSYMBOL(&output_atom[0], gensym((char *)str));
outlet_anything( x->status_outlet, gensym("marker"), 1, output_atom);
cP[len] = c;
cP += len;
@@ -1363,7 +1375,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex)
c = cP[len];
cP[len] = '\0'; /* null terminate temporarily */
if (x->verbosity) post ("midifile: Lyric: %s", str);
- SETSYMBOL(&output_atom[0], gensym(str));
+ SETSYMBOL(&output_atom[0], gensym((char *)str));
outlet_anything( x->status_outlet, gensym("lyrics"), 1, output_atom);
cP[len] = c;
cP += len;
@@ -1373,7 +1385,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex)
c = cP[len];
cP[len] = '\0'; /* null terminate temporarily */
if (x->verbosity) post ("midifile: Instrument Name: %s", str);
- SETSYMBOL(&output_atom[0], gensym(str));
+ SETSYMBOL(&output_atom[0], gensym((char *)str));
outlet_anything( x->status_outlet, gensym("instr_name"), 1, output_atom);
cP[len] = c;
cP += len;
@@ -1384,7 +1396,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex)
cP[len] = '\0'; /* null terminate temporarily */
if (x->verbosity) post ("midifile: Sequence/Track Name: %s", str);
SETFLOAT(&output_atom[0], mfindex);
- SETSYMBOL(&output_atom[1], gensym(str));
+ SETSYMBOL(&output_atom[1], gensym((char *)str));
outlet_anything( x->status_outlet, gensym("name"), 2, output_atom);
cP[len] = c;
cP += len;
@@ -1394,7 +1406,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex)
c = cP[len];
cP[len] = '\0'; /* null terminate temporarily */
if (x->verbosity) post ("midifile: Copyright Notice: %s", str);
- SETSYMBOL(&output_atom[0], gensym(str));
+ SETSYMBOL(&output_atom[0], gensym((char *)str));
outlet_anything( x->status_outlet, gensym("copyright"), 1, output_atom);
cP[len] = c;
cP += len;
@@ -1404,7 +1416,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex)
c = cP[len];
cP[len] = '\0'; /* null terminate temporarily */
if (x->verbosity) post ("midifile: Text Event: %s", str);
- SETSYMBOL(&output_atom[0], gensym(str));
+ SETSYMBOL(&output_atom[0], gensym((char *)str));
outlet_anything( x->status_outlet, gensym("text"), 1, output_atom);
cP[len] = c;
cP += len;
@@ -1459,7 +1471,7 @@ static void midifile_get_next_track_chunk_data(t_midifile *x, int mfindex)
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[mfindex].running_status == 0)
- error ("midifile: No running status on track %d at %lu",
+ error ("midifile: No running status on track %d at %zu",
mfindex, x->track_chunk[mfindex].total_time + delta_time);
}
}
@@ -1566,7 +1578,7 @@ static void midifile_skip_next_track_chunk_data(t_midifile *x, int mfindex)
static t_symbol *midifile_key_name(int sf, int mi)
{
/* set a symbole to the key name baseed on */
- /* sf= number of sharps if positive, else flats
+ /* sf= number of sharps if positive, else flats */
/* mi = 0=major 1= minor */
char *maj_key[15]={"B", "Gb", "Db", "Ab", "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "Db"};
char *min_key[15]={"G#", "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "C#", "G#", "D#", "Bb"};