Merge pull request #9 from MLXXXp/fixes

Fixes and minor changes
pull/10/head
Len Shustek 8 years ago committed by GitHub
commit 53311b536e
  1. 4
      README.txt
  2. 62
      miditones.c

@ -8,7 +8,7 @@
* only simple tone generators. This is on github at www.github.com/LenShustek/miditones. * only simple tone generators. This is on github at www.github.com/LenShustek/miditones.
* *
* Volume ("velocity") and instrument information in the MIDI file can either be * Volume ("velocity") and instrument information in the MIDI file can either be
* discarded or kept. All the tracks are prcoessed and merged into a single time-ordered * discarded or kept. All the tracks are processed and merged into a single time-ordered
* stream of "note on", "note off", "change instrument" and "delay" commands. * stream of "note on", "note off", "change instrument" and "delay" commands.
* *
* This was written for the "Playtune" series of Arduino and Teensy microcontroller * This was written for the "Playtune" series of Arduino and Teensy microcontroller
@ -73,7 +73,7 @@
* -b Generate a binary file with the name <basefilename>.bin, instead of a * -b Generate a binary file with the name <basefilename>.bin, instead of a
* C-language source file with the name <basefilename>.c. * C-language source file with the name <basefilename>.c.
* *
* -tn Generate the bytestream so that at most n tone generators are used. * -tn Generate the bytestream so that at most "n" tone generators are used.
* The default is 6 tone generators, and the maximum is 16. The program * The default is 6 tone generators, and the maximum is 16. The program
* will report how many notes had to be discarded because there weren't * will report how many notes had to be discarded because there weren't
* enough tone generators. * enough tone generators.

@ -9,7 +9,7 @@
* only simple tone generators. This is on github at www.github.com/LenShustek/miditones. * only simple tone generators. This is on github at www.github.com/LenShustek/miditones.
* *
* Volume ("velocity") and instrument information in the MIDI file can either be * Volume ("velocity") and instrument information in the MIDI file can either be
* discarded or kept. All the tracks are prcoessed and merged into a single time-ordered * discarded or kept. All the tracks are processed and merged into a single time-ordered
* stream of "note on", "note off", "change instrument" and "delay" commands. * stream of "note on", "note off", "change instrument" and "delay" commands.
* *
* This was written for the "Playtune" series of Arduino and Teensy microcontroller * This was written for the "Playtune" series of Arduino and Teensy microcontroller
@ -74,7 +74,7 @@
* -b Generate a binary file with the name <basefilename>.bin, instead of a * -b Generate a binary file with the name <basefilename>.bin, instead of a
* C-language source file with the name <basefilename>.c. * C-language source file with the name <basefilename>.c.
* *
* -tn Generate the bytestream so that at most n tone generators are used. * -tn Generate the bytestream so that at most "n" tone generators are used.
* The default is 6 tone generators, and the maximum is 16. The program * The default is 6 tone generators, and the maximum is 16. The program
* will report how many notes had to be discarded because there weren't * will report how many notes had to be discarded because there weren't
* enough tone generators. * enough tone generators.
@ -236,7 +236,7 @@
* -Add -pi and -pt options to ignore or translate the MIDI percussion track 9. * -Add -pi and -pt options to ignore or translate the MIDI percussion track 9.
* -Remove string.h for more portability; add strlength(). * -Remove string.h for more portability; add strlength().
* -Add -i option for recording instrument types.in the bytestream. * -Add -i option for recording instrument types.in the bytestream.
* -Add -d option for generting a file description header. * -Add -d option for generating a file description header.
* -Add -dp option to make generating the PROGMEM definition optional * -Add -dp option to make generating the PROGMEM definition optional
* -Add -n option to specify number of items per output line * -Add -n option to specify number of items per output line
* -Do better error checking on options * -Do better error checking on options
@ -354,7 +354,7 @@ uint8_t *buffer, *hdrptr;
unsigned long buflen; unsigned long buflen;
int num_tracks; int num_tracks;
int tracks_done = 0; int tracks_done = 0;
int outfile_maxitems = 25; int outfile_maxitems = 26;
int outfile_itemcount = 0; int outfile_itemcount = 0;
int num_tonegens = DEFAULT_TONEGENS; int num_tonegens = DEFAULT_TONEGENS;
int num_tonegens_used = 0; int num_tonegens_used = 0;
@ -401,7 +401,7 @@ int midi_chan_instrument[16] = {
/* output bytestream commands, which are also stored in track_status.cmd */ /* output bytestream commands, which are also stored in track_status.cmd */
#define CMD_PLAYNOTE 0x90 /* play a note: low nibble is generator #, note is next byte */ #define CMD_PLAYNOTE 0x90 /* play a note: low nibble is generator #, note is next byte */
#define CMD_STOPNOTE 0x80 /* stop a note: low nibble is generator # */ #define CMD_STOPNOTE 0x80 /* stop a note: low nibble is generator # */
#define CMD_INSTRUMENT 0xc0 /* change instrument; low nibble is generator #, instrument is next byte */ #define CMD_INSTRUMENT 0xc0 /* change instrument; low nibble is generator #, instrument is next byte */
#define CMD_RESTART 0xe0 /* restart the score from the beginning */ #define CMD_RESTART 0xe0 /* restart the score from the beginning */
#define CMD_STOP 0xf0 /* stop playing */ #define CMD_STOP 0xf0 /* stop playing */
@ -454,7 +454,7 @@ void SayUsage (char *programName) {
" -p parse only, don't generate bytestream", " -p parse only, don't generate bytestream",
" -lp log input parsing", " -lp log input parsing",
" -lg log output generation", " -lg log output generation",
" -nx Put about x items on each line of the C file output", " -nx put about x items on each line of the C file output",
" -s1 strategy 1: favor track 1", " -s1 strategy 1: favor track 1",
" -s2 strategy 2: try to assign tracks to specific tone generators", " -s2 strategy 2: try to assign tracks to specific tone generators",
" -cn mask for which tracks to process, e.g. -c3 for only 0 and 1", " -cn mask for which tracks to process, e.g. -c3 for only 0 and 1",
@ -494,8 +494,10 @@ does not start with a dash or a slash*/
goto opterror; goto opterror;
break; break;
case 'P': case 'P':
if (argv[i][2] == '\0') if (argv[i][2] == '\0') {
parseonly = true; parseonly = true;
break;
}
else if (toupper (argv[i][2]) == 'I') else if (toupper (argv[i][2]) == 'I')
percussion_ignore = true; percussion_ignore = true;
else if (toupper (argv[i][2]) == 'T') else if (toupper (argv[i][2]) == 'T')
@ -661,7 +663,7 @@ int charcmp (const char *buf, const char *match) {
return 1; return 1;
} }
/* announce a fatal MIDI file format error */ /* announce a fatal MIDI file format error */
void midi_error (char *msg, unsigned char *bufptr) { void midi_error (char *msg, unsigned char *bufptr) {
unsigned char *ptr; unsigned char *ptr;
@ -701,7 +703,7 @@ and generate a newline every so often. */
void outfile_items (int n) { void outfile_items (int n) {
outfile_bytecount += n; outfile_bytecount += n;
outfile_itemcount += n; outfile_itemcount += n;
if (!binaryoutput && outfile_itemcount > outfile_maxitems) { if (!binaryoutput && outfile_itemcount >= outfile_maxitems) {
fprintf (outfile, "\n"); fprintf (outfile, "\n");
outfile_itemcount = 0; outfile_itemcount = 0;
} }
@ -1004,6 +1006,11 @@ int main (int argc, char *argv[]) {
/* process options */ /* process options */
argno = HandleOptions (argc, argv); argno = HandleOptions (argc, argv);
if (argno == 0) {
fprintf (stderr, "\n*** No basefilename given\n\n");
SayUsage (argv[0]);
exit (4);
}
filebasename = argv[argno]; filebasename = argv[argno];
/* Open the log file */ /* Open the log file */
@ -1013,7 +1020,7 @@ int main (int argc, char *argv[]) {
miditones_strlcat (filename, ".log", MAXPATH); miditones_strlcat (filename, ".log", MAXPATH);
logfile = fopen (filename, "w"); logfile = fopen (filename, "w");
if (!logfile) { if (!logfile) {
fprintf (stderr, "Unable to open log file %s", filename); fprintf (stderr, "Unable to open log file %s\n", filename);
return 1; return 1;
} }
fprintf (logfile, "MIDITONES V%s log file\n", VERSION); fprintf (logfile, "MIDITONES V%s log file\n", VERSION);
@ -1025,7 +1032,7 @@ int main (int argc, char *argv[]) {
miditones_strlcat (filename, ".mid", MAXPATH); miditones_strlcat (filename, ".mid", MAXPATH);
infile = fopen (filename, "rb"); infile = fopen (filename, "rb");
if (!infile) { if (!infile) {
fprintf (stderr, "Unable to open input file %s", filename); fprintf (stderr, "Unable to open input file %s\n", filename);
return 1; return 1;
} }
@ -1036,7 +1043,7 @@ int main (int argc, char *argv[]) {
fseek (infile, 0, SEEK_SET); fseek (infile, 0, SEEK_SET);
buffer = (unsigned char *) malloc (buflen + 1); buffer = (unsigned char *) malloc (buflen + 1);
if (!buffer) { if (!buffer) {
fprintf (stderr, "Unable to allocate %ld bytes for the file", buflen); fprintf (stderr, "Unable to allocate %ld bytes for the file\n", buflen);
return 1; return 1;
} }
fread (buffer, buflen, 1, infile); fread (buffer, buflen, 1, infile);
@ -1056,7 +1063,7 @@ int main (int argc, char *argv[]) {
outfile = fopen (filename, "w"); outfile = fopen (filename, "w");
} }
if (!outfile) { if (!outfile) {
fprintf (stderr, "Unable to open output file %s", filename); fprintf (stderr, "Unable to open output file %s\n", filename);
return 1; return 1;
} }
file_header.f1 = (velocityoutput ? HDR_F1_VOLUME_PRESENT : 0) file_header.f1 = (velocityoutput ? HDR_F1_VOLUME_PRESENT : 0)
@ -1087,11 +1094,13 @@ int main (int argc, char *argv[]) {
fflush (outfile); fflush (outfile);
file_header_num_tgens_position = ftell (outfile); // remember where the number of tone generators is file_header_num_tgens_position = ftell (outfile); // remember where the number of tone generators is
fprintf (outfile, "%2d, // (Playtune file header)\n", file_header.num_tgens); fprintf (outfile, "%2d, // (Playtune file header)\n", file_header.num_tgens);
outfile_bytecount += 6;
} }
} else if (do_header) { // write the binary file header } else if (do_header) { // write the binary file header
for (int i = 0; i < sizeof (file_header); ++i) for (int i = 0; i < sizeof (file_header); ++i)
fputc (((unsigned char *) &file_header)[i], outfile); fputc (((unsigned char *) &file_header)[i], outfile);
file_header_num_tgens_position = (char *) &file_header.num_tgens - (char *) &file_header; file_header_num_tgens_position = (char *) &file_header.num_tgens - (char *) &file_header;
outfile_bytecount += sizeof (file_header);
} }
} }
@ -1119,7 +1128,7 @@ int main (int argc, char *argv[]) {
This is not unlike multiway merging used for tape sorting algoritms in the 50's! */ This is not unlike multiway merging used for tape sorting algoritms in the 50's! */
tracknum = 0; tracknum = 0;
if (!parseonly) if (!parseonly) {
do { /* while there are still track notes to process */ do { /* while there are still track notes to process */
struct track_status *trk; struct track_status *trk;
struct tonegen_status *tg; struct tonegen_status *tg;
@ -1331,8 +1340,8 @@ This is not unlike multiway merging used for tape sorting algoritms in the 50's!
} /* !parseonly do */ } /* !parseonly do */
while (tracks_done < num_tracks); while (tracks_done < num_tracks);
if (!parseonly) {
// generate the end-of-score command and some commentary // generate the end-of-score command and some commentary
outfile_bytecount++;
if (binaryoutput) if (binaryoutput)
putc (CMD_STOP, outfile); putc (CMD_STOP, outfile);
else { else {
@ -1353,18 +1362,19 @@ This is not unlike multiway merging used for tape sorting algoritms in the 50's!
if (loggen) if (loggen)
fprintf (logfile, "%d note-on commands, %d instrument changes.\n", fprintf (logfile, "%d note-on commands, %d instrument changes.\n",
note_on_commands, instrument_changes); note_on_commands, instrument_changes);
} if (do_header) { // rewrite the file header with the actual number of tone generators used
if (do_header) { // rewrite the file header with the actual number of tone generators used if (fseek (outfile, file_header_num_tgens_position, SEEK_SET) != 0)
if (fseek (outfile, file_header_num_tgens_position, SEEK_SET) != 0) fprintf (stderr, "Can't seek to number of tone generators in the header\n");
fprintf (stderr, "Can't seek to number of tone generators in the header"); else {
else { if (binaryoutput)
if (binaryoutput) putc (num_tonegens_used, outfile);
putc (num_tonegens_used, outfile); else
else fprintf (outfile, "%2d", num_tonegens_used);
fprintf (outfile, "%2d", num_tonegens_used); }
} }
} fclose (outfile);
fclose (outfile); } /* if (!parseonly) */
if (loggen || logparse) if (loggen || logparse)
fclose (logfile); fclose (logfile);
printf (" Done.\n"); printf (" Done.\n");

Loading…
Cancel
Save