Merge pull request #5 from blackketter/master

Merge changes from miditones used in the Arduino/Teensy library (PaulStoffregen/Audio)
pull/9/head
Len Shustek 8 years ago
commit b6070573e9
  1. 5
      Makefile
  2. 51
      miditones.c

@ -0,0 +1,5 @@
miditones: miditones.c
gcc -O2 -Wall -o miditones miditones.c
clean:
rm -f miditones

@ -5,7 +5,7 @@
* Convert a MIDI file into a bytestream of notes
*
*
* (C) Copyright 2011,2013,2015, Len Shustek
* (C) Copyright 2011,2013,2015,2016 Len Shustek
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of version 3 of the GNU General Public License as
@ -52,9 +52,11 @@
* Generate "const" for data initialization for compatibility with Arduino IDE v1.6.x.
* 23 January 2016, D. Blackketter, V1.8
* -Fix warnings and errors building on Mac OS X via "gcc miditones.c"
* 25 January 2016, D. Blackketter, Paul Stoffregen, V1.9
-Merge in velocity output option from Arduino/Teensy Audio Library
*/
#define VERSION "1.8"
#define VERSION "1.9"
/*--------------------------------------------------------------------------------
@ -146,6 +148,8 @@
* -kn Change the musical key of the output by n chromatic notes.
* -k-12 goes one octave down, -k12 goes one octave up, etc.
*
* -v Add velocity information to output
*
*
* ***** The score bytestream *****
*
@ -155,9 +159,10 @@
*
* If the high-order bit of the byte is 1, then it is one of the following commands:
*
* 9t nn Start playing note nn on tone generator t. Generators are numbered
* 9t nn [vv] Start playing note nn on tone generator t. Generators are numbered
* starting with 0. The notes numbers are the MIDI numbers for the chromatic
* scale, with decimal 60 being Middle C, and decimal 69 being Middle A (440 Hz).
* if the -v option is enabled, a second byte is added to indicate velocity
*
* 8t Stop playing the note on tone generator t.
*
@ -213,7 +218,7 @@ struct track_header {
#define DEFAULT_TONEGENS 6 /* default number of tone generators */
#define MAX_TRACKS 24 /* max number of MIDI tracks we will process */
bool loggen, logparse, parseonly, strategy1, strategy2, binaryoutput;
bool loggen, logparse, parseonly, strategy1, strategy2, binaryoutput, velocityoutput;
FILE *infile, *outfile, *logfile;
uint8_t *buffer, *hdrptr;
unsigned long buflen;
@ -235,7 +240,7 @@ struct tonegen_status { /* current status of a tone generator */
int note; /* what note is playing? */
}
tonegen [MAX_TONEGENS] = {
0};
{0}};
struct track_status { /* current processing point of a MIDI track */
uint8_t *trkptr; /* ptr to the next note change */
@ -245,11 +250,12 @@ struct track_status { /* current processing point of a MIDI track */
unsigned int preferred_tonegen; /* for strategy2: try to use this generator */
unsigned char cmd; /* CMD_xxxx next to do */
unsigned char note; /* for which note */
unsigned char velocity;
unsigned char last_event; /* the last event, for MIDI's "running status" */
bool tonegens[MAX_TONEGENS];/* which tone generators our notes are playing on */
}
track[MAX_TRACKS] = {
0};
{0}};
/* output bytestream commands, which are also stored in track_status.cmd */
@ -271,7 +277,7 @@ track[MAX_TRACKS] = {
void SayUsage(char *programName){
static char *usage[] = {
"Convert MIDI files to an Arduino PLAYTUNE bytestream",
"miditones [-p] [-lg] [-lp] [-s1] [-tn] <basefilename>",
"miditones [-p] [-lg] [-lp] [-s1] [-tn] [-v] <basefilename>",
" -p parse only, don't generate bytestream",
" -lp log input parsing",
" -lg log output generation",
@ -281,6 +287,7 @@ void SayUsage(char *programName){
" -b binary file output instead of C source text",
" -cn mask for which tracks to process, e.g. -c3 for only 0 and 1",
" -kn key shift in chromatic notes, positive or negative",
" -v include velocity data in play note commands",
"input file: <basefilename>.mid",
"output file: <basefilename>.bin or .c",
"log file: <basefilename>.log",
@ -314,6 +321,9 @@ int HandleOptions(int argc,char *argv[]) {
case 'B':
binaryoutput = true;
break;
case 'V':
velocityoutput = true;
break;
case 'S':
if (argv[i][2] == '1') strategy1 = true;
else if (argv[i][2] == '2') strategy2 = true;
@ -413,7 +423,7 @@ size_t miditones_strlcat(char *dst, const char *src, size_t siz) {
/* match a constant character sequence */
int charcmp (char *buf, char *match) {
int charcmp (const char *buf, const char *match) {
int len, i;
len = strlen (match);
for (i=0; i<len; ++i)
@ -501,7 +511,7 @@ void start_track (int tracknum) {
chk_bufdata(hdrptr, sizeof(struct track_header));
hdr = (struct track_header *) hdrptr;
if (!charcmp((char*)hdr->MTrk,"MTrk")) midi_error("Missing 'MTrk'", hdrptr);
if (!charcmp((char *)(hdr->MTrk),"MTrk")) midi_error("Missing 'MTrk'", hdrptr);
tracklen = rev_long(hdr->track_size);
if (logparse) fprintf (logfile, "\nTrack %d length %ld\n", tracknum, tracklen);
@ -640,6 +650,7 @@ note_off:
t->note = *t->trkptr++;
velocity = *t->trkptr++;
if (velocity == 0) /* some scores use note-on with zero velocity for off! */ goto note_off;
t->velocity = velocity;
if (logparse) fprintf (logfile, "note %02X on, chan %d, velocity %d\n", t->note, chan, velocity);
if ((1<<chan) & channel_mask) { // if we're processing this channel
t->cmd = CMD_PLAYNOTE;
@ -697,7 +708,7 @@ int main(int argc,char *argv[]) {
unsigned long earliest_time;
int notes_skipped = 0;
printf("MIDITONES V%s, (C) 2011,2015 Len Shustek\n", VERSION);
printf("MIDITONES V%s, (C) 2011,2015,2016 Len Shustek\n", VERSION);
printf("See the source code for license information.\n\n");
if (argc == 1) { /* no arguments */
SayUsage(argv[0]);
@ -773,7 +784,12 @@ int main(int argc,char *argv[]) {
fprintf(outfile, "// Only the masked channels were processed: %04X\n", channel_mask);
if (keyshift != 0)
fprintf(outfile, "// Keyshift was %d chromatic notes\n", keyshift);
fprintf(outfile, "const byte PROGMEM score [] = {\n");
fprintf(outfile, "#ifdef __AVR__\n");
fprintf(outfile, "#include <avr/pgmspace.h>\n");
fprintf(outfile, "#else\n");
fprintf(outfile, "#define PROGMEM\n");
fprintf(outfile, "#endif\n");
fprintf(outfile, "const unsigned char PROGMEM score [] = {\n");
}
}
@ -932,10 +948,19 @@ int main(int argc,char *argv[]) {
putc (CMD_PLAYNOTE | tgnum, outfile);
putc (shifted_note, outfile);
outfile_bytecount += 2;
if (velocityoutput) {
putc (trk->velocity, outfile);
outfile_bytecount++;
}
}
else {
fprintf (outfile, "0x%02X,%d, ", CMD_PLAYNOTE | tgnum, shifted_note);
outfile_items(2);
if (velocityoutput == 0) {
fprintf (outfile, "0x%02X,%d, ", CMD_PLAYNOTE | tgnum, shifted_note);
outfile_items(2);
} else {
fprintf (outfile, "0x%02X,%d,%d, ", CMD_PLAYNOTE | tgnum, shifted_note, trk->velocity);
outfile_items(3);
}
}
}
else {

Loading…
Cancel
Save