From dab0d8ea31e9ba28cbb80a2ca534d3be6751354c Mon Sep 17 00:00:00 2001 From: Len Shustek Date: Tue, 8 Jan 2019 11:39:47 -0800 Subject: [PATCH] test version for -m --- miditones.c | 238 +++++++++++++++++++++++++++++--------------------- miditones.exe | Bin 60416 -> 61440 bytes 2 files changed, 139 insertions(+), 99 deletions(-) diff --git a/miditones.c b/miditones.c index 2dd74cd..fe2a336 100644 --- a/miditones.c +++ b/miditones.c @@ -111,6 +111,10 @@ * * -pi Ignore notes in the MIDI percussion track 9 (also called 10 by some) * +* -mx Merge events that are within x milliseconds, to reduce the number of "delay" +* commands and thus make the bytestream smaller. The deficits are accumulated +* so that there is no loss of synchronization in the long term. +* * -dp Generate IDE-dependent C code to define PROGMEM * * -r Terminate the output file with a "restart" command instead of a "stop" command. @@ -260,7 +264,7 @@ * seen, this makes the bytestream 21% smaller! * 13 November 2017, Earle Philhower, V1.15 * - Allow META fields to be larger than 127 bytes. -* 2 January 2018, Kodest, V1.16 +* 2 January 2018, Kodest, V1 * - Don't generate zero-length delays * 13 September 2018, Paul Stoffregen, V1.17 - Fix compile errors on Linux with gcc run in default mode @@ -270,8 +274,13 @@ - Abandon LCC and compile under Microsoft Visual Studio 2017. - Reformat to condense the source code, so you see more protein and less syntactic sugar on each screen. +* 4 January 2019, Len Shustek, V1.19 + - As suggested by Chris van Marle, add the "-mx" parameter to allow timing to be + flexible in order to avoid small delays and thus save space in the bytestream. + - Don't discard fractions of a millisecond in the delay timing, to avoid gradual + drift of the music. This has been a minor problem since V1.0 in 2011. */ -#define VERSION "1.18" +#define VERSION "1.19" /*-------------------------------------------------------------------------------------------- @@ -291,9 +300,13 @@ a MIDI file is: a header_chunk is: "MThd" 00000006 ffff nnnn dddd + ffff is the format type (we have only seen 1) + nnnn is the number of tracks + dddd is the number of ticks per beat (ie, quarter note) a track_chunk is: "MTrk" llllllll { track_event}... + is the number of ticks to delay before this event a running status track_event is: 0x to 7x: assume a missing 8n to En event code which is the same as the last MIDI-event track_event @@ -337,8 +350,43 @@ a meta event track_event is: FF 58 04 nnddccbb set time signature FF 59 02 sfmi set key signature FF 7F data sequencer-specific data - ---------------------------------------------------------------------------------------------*/ + --------------------------------------------------------------------------------------------*/ + + /*--------------- processing outline ------------------------------------------------------- + main + forall trks, find_note + do + find trk with earliest_time = min(trk->time) + if timenow-earliest_time > minimum delay + gen_stopnotes + output: delay timenow-earliest_time + if CMD_TEMPO, + set global tempo + find_note + else if CMD_STOPNOTE + do + tgen->stopnote_pending = true + find_note + while CMD_STOPNOTE + else if CMD_PLAYNOTE + find tgen + stopnote_pending = false + output: CMD_PLAYNOTE + find_note + while not all CMD_TRACKDONE + exit +find_note + do forever + t->time = varlen + if "note off", CMD_STOPNOTE, return + if "note on", CMD_PLAYNOTE, return + if "tempo", CMD_TEMPO, return + if end of track, CMD_TRACKDONE, return + gen_stopnotes + forall tgen + if stopnote_pending, + output: CMD_STOPNOTE, stopnote_pending = false + --------------------------------------------------------------------------------------------*/ #include #include @@ -388,8 +436,12 @@ unsigned channel_mask = 0xffff; // bit mask of channels to process int keyshift = 0; // optional chromatic note shift for output file long int outfile_bytecount = 0; unsigned int ticks_per_beat = 240; -unsigned long timenow = 0; -unsigned long tempo; /* current tempo in usec/qnote */ +unsigned long timenow = 0; // time now, in ticks +unsigned long tempo; // current global tempo in usec/beat +unsigned long long songtime_usec = 0; +int tempo_changes = 0; // how many times we changed the global tempo +unsigned closetime_msec = 0; // how close, in msec, events should be before they are merged +long int delays_saved = 0; // how many delays were saved because of non-zero merge time struct tonegen_status { /* current status of a tone generator */ bool playing; /* is it playing? */ @@ -404,8 +456,9 @@ struct tonegen_status { /* current status of a tone generator */ struct track_status { /* current processing point of a MIDI track */ uint8_t *trkptr; /* ptr to the next note change */ uint8_t *trkend; /* ptr past the end of the track */ - unsigned long time; /* what time we're at in the score */ - unsigned long tempo; /* the tempo last set, in usec per qnote */ + unsigned long time; /* what time we're at in the score, in ticks */ + unsigned long deficit_usec; /* how much behind we are, in usec */ + unsigned long tempo; /* the tempo last set, in usec per beat */ 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 */ @@ -482,6 +535,7 @@ void SayUsage (char *programName) { " -cn mask for which tracks to process, e.g. -c3 for only 0 and 1", " -kn key shift in chromatic notes, positive or negative", " -pi ignore notes in the percussion track (9)", + " -mx merge events that are within x msec, to save bytestream space", " -dp define PROGMEM in output C code", " -r terminate output file with \"restart\" instead of \"stop\" command", NULL }; @@ -505,97 +559,78 @@ int HandleOptions (int argc, char *argv[]) { SayUsage (argv[0]); exit (1); case 'L': - if (toupper (argv[i][2]) == 'G') - loggen = true; - else if (toupper (argv[i][2]) == 'P') - logparse = true; - else - goto opterror; - if (argv[i][3] != '\0') - goto opterror; + if (toupper (argv[i][2]) == 'G') loggen = true; + else if (toupper (argv[i][2]) == 'P') logparse = true; + else goto opterror; + if (argv[i][3] != '\0') goto opterror; break; case 'P': if (argv[i][2] == '\0') { parseonly = true; break; } - else if (toupper (argv[i][2]) == 'I') - percussion_ignore = true; - else if (toupper (argv[i][2]) == 'T') - percussion_translate = true; - else - goto opterror; - if (argv[i][3] != '\0') - goto opterror; + else if (toupper (argv[i][2]) == 'I') percussion_ignore = true; + else if (toupper (argv[i][2]) == 'T') percussion_translate = true; + else goto opterror; + if (argv[i][3] != '\0') goto opterror; break; case 'B': binaryoutput = true; - if (argv[i][2] != '\0') - goto opterror; + if (argv[i][2] != '\0') goto opterror; break; case 'V': velocityoutput = true; - if (argv[i][2] != '\0') - goto opterror; + if (argv[i][2] != '\0') goto opterror; break; case 'I': instrumentoutput = true; - if (argv[i][2] != '\0') - goto opterror; + if (argv[i][2] != '\0') goto opterror; break; case 'S': - if (argv[i][2] == '1') - strategy1 = true; - else if (argv[i][2] == '2') - strategy2 = true; - else - goto opterror; - if (argv[i][3] != '\0') - goto opterror; + if (argv[i][2] == '1') strategy1 = true; + else if (argv[i][2] == '2') strategy2 = true; + else goto opterror; + if (argv[i][3] != '\0') goto opterror; break; case 'T': if (sscanf (&argv[i][2], "%d%n", &num_tonegens, &nch) != 1 || num_tonegens < 1 || num_tonegens > MAX_TONEGENS) goto opterror; printf ("Using %d tone generators.\n", num_tonegens); - if (argv[i][2 + nch] != '\0') - goto opterror; + if (argv[i][2 + nch] != '\0') goto opterror; break; case 'N': if (sscanf (&argv[i][2], "%d%n", &outfile_maxitems, &nch) != 1 || outfile_maxitems < 1) goto opterror; - if (argv[i][2 + nch] != '\0') - goto opterror; + if (argv[i][2 + nch] != '\0') goto opterror; + break; + case 'M': + if (sscanf(&argv[i][2], "%d%n", &closetime_msec, &nch) != 1) goto opterror; + if (argv[i][2 + nch] != '\0') goto opterror; break; case 'C': if (sscanf (&argv[i][2], "%i%n", &channel_mask, &nch) != 1 || channel_mask > 0xffff) goto opterror; printf ("Channel (track) mask is %04X.\n", channel_mask); - if (argv[i][2 + nch] != '\0') - goto opterror; + if (argv[i][2 + nch] != '\0') goto opterror; break; case 'K': if (sscanf (&argv[i][2], "%d%n", &keyshift, &nch) != 1 || keyshift < -100 || keyshift > 100) goto opterror; printf ("Using keyshift %d.\n", keyshift); - if (argv[i][2 + nch] != '\0') - goto opterror; + if (argv[i][2 + nch] != '\0') goto opterror; break; case 'D': if (argv[i][2] == '\0') { do_header = true; break; } - if (toupper (argv[i][2]) == 'P') - define_progmem = true; - else - goto opterror; - if (argv[i][3] != '\0') - goto opterror; + if (toupper (argv[i][2]) == 'P') define_progmem = true; + else goto opterror; + if (argv[i][3] != '\0') goto opterror; break; case 'R': gen_restart = true; - if (argv[i][2] != '\0') - goto opterror; + if (argv[i][2] != '\0') goto opterror; break; /* add more option switches here */ opterror: @@ -608,12 +643,12 @@ opterror: break; } } return firstnonoption; } -void print_command_line (int argc, char *argv[]) { +void print_command_line (FILE *file, int argc, char *argv[]) { int i; - fprintf (outfile, "// command line: "); + fprintf (file, "// command line: "); for (i = 0; i < argc; i++) - fprintf (outfile, "%s ", argv[i]); - fprintf (outfile, "\n"); } + fprintf (file, "%s ", argv[i]); + fprintf (file, "\n"); } /**************** utility routines **********************/ @@ -632,30 +667,25 @@ size_t miditones_strlcpy (char *dst, const char *src, size_t siz) { /* Copy as many bytes as will fit */ if (n != 0) { while (--n != 0) { - if ((*d++ = *s++) == '\0') - break; } } + if ((*d++ = *s++) == '\0') break; } } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++); } + if (siz != 0) *d = '\0'; /* NUL-terminate dst */ + while (*s++) ; } return (s - src - 1); /* count does not include NUL */ } /* safe string concatenation */ - size_t miditones_strlcat (char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; + while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; - if (n == 0) - return (dlen + strlength (s)); + if (n == 0) return (dlen + strlength (s)); while (*s != '\0') { if (n != 1) { *d++ = *s; @@ -666,7 +696,6 @@ size_t miditones_strlcat (char *dst, const char *src, size_t siz) { } /* match a constant character sequence */ - int charcmp (const char *buf, const char *match) { int len, i; len = strlength (match); @@ -1024,7 +1053,8 @@ int main (int argc, char *argv[]) { if (!logfile) { fprintf (stderr, "Unable to open log file %s\n", filename); return 1; } - fprintf (logfile, "MIDITONES V%s log file\n", VERSION); } + fprintf (logfile, "MIDITONES V%s log file\n", VERSION); + print_command_line(logfile, argc, argv); } /* Open the input file */ @@ -1072,7 +1102,7 @@ int main (int argc, char *argv[]) { fprintf (outfile, "// Playtune bytestream for file \"%s.mid\" ", filebasename); fprintf (outfile, "created by MIDITONES V%s on %s", VERSION, asctime (localtime (&rawtime))); - print_command_line (argc, argv); + print_command_line (outfile, argc, argv); if (channel_mask != 0xffff) fprintf (outfile, "// Only the masked channels were processed: %04X\n", channel_mask); if (keyshift != 0) @@ -1128,7 +1158,7 @@ int main (int argc, char *argv[]) { struct tonegen_status *tg; int tgnum; int count_tracks; - unsigned long delta_time, delta_msec; + unsigned long delta_ticks, delta_msec; /* Find the track with the earliest event time, and output a delay command if time has advanced. @@ -1151,8 +1181,7 @@ int main (int argc, char *argv[]) { if (strategy1) tracknum = num_tracks; /* beyond the end, so we start with track 0 */ do { - if (++tracknum >= num_tracks) - tracknum = 0; + if (++tracknum >= num_tracks) tracknum = 0; trk = &track[tracknum]; if (trk->cmd != CMD_TRACKDONE && trk->time < earliest_time) { earliest_time = trk->time; @@ -1166,18 +1195,25 @@ int main (int argc, char *argv[]) { if (earliest_time < timenow) midi_error ("INTERNAL: time went backwards", trk->trkptr); - /* If time has advanced, output a "delay" command */ - - delta_time = earliest_time - timenow; - if (delta_time) { - /* Convert ticks to milliseconds based on the current tempo */ - delta_msec = ((unsigned long long) delta_time * tempo) / ticks_per_beat / 1000; - if (delta_msec) { // if time delay didn't round down to zero msec - gen_stopnotes(); /* first check if any tone generators have "stop note" commands pending */ - if (loggen) - fprintf (logfile, "->Delay %ld msec (%ld ticks)\n", delta_msec, delta_time); - if (delta_msec > 0x7fff) - midi_error ("INTERNAL: time delta too big", trk->trkptr); + /* If time has advanced, maybe output a "delay" command */ + + delta_ticks = earliest_time - timenow; + unsigned long delta_usec = ((unsigned long long) delta_ticks * tempo) / ticks_per_beat; + songtime_usec += delta_usec; + // We round up closetime_ticks, because otherwise the default tempo of 500,000 usec/beat with + // the default 480 ticks/beat results in 1.04166 msec/tick, so -m1 doesn't work as expected. + unsigned long closetime_ticks = (((unsigned long)closetime_msec * 1000 + 500) * ticks_per_beat) / tempo; + unsigned long deficit_ticks = (trk->deficit_usec * ticks_per_beat) / tempo; + // Generate a delay only if it is larger than the specified "merge if closer than x msec" time. + // But we accumulate the deficit for each track so that we eventually catch up. + if (delta_ticks + deficit_ticks > closetime_ticks) { // yes, we should generate a delay + gen_stopnotes(); /* first check if any tone generators have "stop note" commands pending */ + delta_usec += trk->deficit_usec; // include any previously accumulated deficit + delta_msec = delta_usec / 1000; // the integral number of milliseconds + trk->deficit_usec = delta_usec % 1000; // save the fraction of a milliscond as the new deficit + if (delta_msec) { // really do it if the delay didn't round down to zero msec + if (loggen) fprintf (logfile, "->Delay %ld msec (%ld ticks)\n", delta_msec, delta_ticks); + if (delta_msec > 0x7fff) midi_error ("INTERNAL: time delta too big", trk->trkptr); /* output a 15-bit delay in big-endian format */ if (binaryoutput) { putc ((unsigned char) (delta_msec >> 8), outfile); @@ -1186,15 +1222,19 @@ int main (int argc, char *argv[]) { else { fprintf (outfile, "%ld,%ld, ", delta_msec >> 8, delta_msec & 0xff); outfile_items (2); } } } + else if (delta_usec) { + trk->deficit_usec += delta_usec; // accumulate time for delays we skip + ++delays_saved; } timenow = earliest_time; /* If this track event is "set tempo", just change the global tempo. That affects how we generate "delay" commands. */ if (trk->cmd == CMD_TEMPO) { + if (tempo != trk->tempo) ++tempo_changes; tempo = trk->tempo; if (loggen) - fprintf (logfile, "Tempo changed to %ld usec/qnote\n", tempo); + fprintf (logfile, "Tempo set to %ld usec/qnote\n", tempo); find_note (tracknum); } /* If this track event is "stop note", process it and all subsequent "stop notes" for this track @@ -1277,10 +1317,8 @@ int main (int argc, char *argv[]) { } else { /* shift notes as requested */ shifted_note = trk->note + keyshift; - if (shifted_note < 0) - shifted_note = 0; - if (shifted_note > 127) - shifted_note = 127; } + if (shifted_note < 0) shifted_note = 0; + if (shifted_note > 127) shifted_note = 127; } if (binaryoutput) { putc (CMD_PLAYNOTE | tgnum, outfile); putc (shifted_note, outfile); @@ -1293,13 +1331,11 @@ int main (int argc, char *argv[]) { 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); + fprintf (outfile, "0x%02X,%d,%d, ", CMD_PLAYNOTE | tgnum, shifted_note, trk->velocity); outfile_items (3); } } } else { if (loggen) - fprintf (logfile, - "----> No free generator, skipping note %d, track %d\n", + fprintf (logfile, "----> No free generator, skipping note %d, track %d\n", trk->note, tracknum); ++notes_skipped; } } find_note (tracknum); // use up the note @@ -1323,10 +1359,14 @@ int main (int argc, char *argv[]) { printf (" %s %d tone generators were used.\n", num_tonegens_used < num_tonegens ? "Only" : "All", num_tonegens_used); if (notes_skipped) - printf - (" %d notes were skipped because there weren't enough tone generators.\n", - notes_skipped); - printf (" %ld bytes of score data were generated.\n", outfile_bytecount); + printf (" %d notes were skipped because there weren't enough tone generators.\n", + notes_skipped); + printf (" %ld bytes of score data were generated, ", outfile_bytecount); + printf("representing %u.%03u seconds of music with %d tempo changes\n", + (unsigned)(songtime_usec / 1000000), (unsigned)(songtime_usec/1000 % 1000), tempo_changes); + if (closetime_msec) + printf (" %ld delays were removed because events within %u msec were merged\n", + delays_saved, closetime_msec); if (loggen) fprintf (logfile, "%d note-on commands, %d instrument changes.\n", note_on_commands, instrument_changes); diff --git a/miditones.exe b/miditones.exe index 025533366f14bab624d1a9614d5c7ee6a290a8cd..86f223117de84d9ad29d80141f39ef2d613a420b 100644 GIT binary patch delta 17607 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