Fix 32-bit overflow for long delays

pull/9/head
Len Shustek 8 years ago
parent 93b539361e
commit 44e5b2de3b
  1. 34
      README.txt
  2. 111
      miditones.c
  3. BIN
      miditones.exe
  4. BIN
      miditones32.exe

@ -8,9 +8,9 @@
* so that a version of the music can be played on a synthesizer having only * so that a version of the music can be played on a synthesizer having only
* tone generators without any volume or tone controls. * tone generators without any volume or tone controls.
* *
* Volume ("velocity") and instrument specifications in the MIDI files are discarded. * Volume ("velocity") and instrument specifications in the MIDI files are generally
* All the tracks are prcoessed and merged into a single time-ordered stream of * discarded. All the tracks are prcoessed and merged into a single time-ordered
* "note on", "note off", and "delay" commands. * stream of "note on", "note off", and "delay" commands.
* *
* This was written for the "Playtune" Arduino library, which plays polyphonic music * This was written for the "Playtune" Arduino library, which plays polyphonic music
* using up to 6 tone generators run by the timers on the processor. See the separate * using up to 6 tone generators run by the timers on the processor. See the separate
@ -45,7 +45,7 @@
* *
* The general form for command line execution is this: * The general form for command line execution is this:
* *
* miditones [-p] [-lg] [-lp] [-s1] [-tn] [-b] [-cn] [-kn] <basefilename> * miditones [-p] [-lg] [-lp] [-s1] [-tn] [-b] [-cn] [-kn] [-v] <basefilename>
* *
* The <basefilename> is the base name, without an extension, for the input and * The <basefilename> is the base name, without an extension, for the input and
* output files. It can contain directory path information, or not. * output files. It can contain directory path information, or not.
@ -87,6 +87,8 @@
* -kn Change the musical key of the output by n chromatic notes. * -kn Change the musical key of the output by n chromatic notes.
* -k-12 goes one octave down, -k12 goes one octave up, etc. * -k-12 goes one octave down, -k12 goes one octave up, etc.
* *
* -v Add velocity information to output
*
* *
* ***** The score bytestream ***** * ***** The score bytestream *****
* *
@ -96,9 +98,10 @@
* *
* If the high-order bit of the byte is 1, then it is one of the following commands: * 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 * 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). * 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. * 8t Stop playing the note on tone generator t.
* *
@ -118,26 +121,7 @@
* that were playing before the delay command will continue to play. * that were playing before the delay command will continue to play.
* *
* *
* Len Shustek, 4 Feb 2011 * Len Shustek, 4 Feb 2011 and later
* *
*----------------------------------------------------------------------------------*/ *----------------------------------------------------------------------------------*/
Update on 28 Feb 2011: I fixed a bug that caused it to stop some notes too soon.
I also wrote a "MIDITONES_SCROLL" program that displays a miditones bytestream as a time-ordered scroll, sort of like a piano roll but with non-uniform time.This is primarily useful to debug programming errors that cause some MIDI scripts to sound strange. It reads the .bin file created from a .mid file by MIDITONES using the -b option.
Update on 25 Apr 2011: Scott Stickeler pointed out that it doesn't work if compiled for a 64-bit environment. I'll put fixing that on my to-do list, but in the meantime the workaround is just to compile for 32 bits. (Thanks, Scott.)
Update on 20 Nov 2011, V1.4: Added options to mask which channels (tracks) to process, and to change key by any chromatic distance. These are in support of music-playing on my Tesla Coil.
Update on 25 Aug 2013, V1.6: I finally fixed it to compile in 64-bit environments. I didn't have a way to test that, so thanks to David Azar for doing so.
Update on 30 Dec 2013: I added version 1.1 of MINITONES_SCROLL with a "-c" option to create annotated C source code initialization of the music bytestream. This makes it easier to manually edit the bytestream. See the beginning of the MINITONES_SCROLL source code for more details.
Update on 7 Mar 2013: I compiled 32-bit versions for people running Windows XP and Vista. Unfortunately code.google.com no longer allows downloaded files! So I put them in a Google Drive folder here:
https://drive.google.com/folderview?id=0B1ZOnb_w5lfBQkNPeFpvRHdQNnc
Update on 5 April 2015: Now code.google.org is going away, so I've migrated this to github.
Update on 6 April 2015: I made the source code friendlier to more compilers. The executables are, of course, for Windows.

@ -53,10 +53,13 @@
* 23 January 2016, D. Blackketter, V1.8 * 23 January 2016, D. Blackketter, V1.8
* -Fix warnings and errors building on Mac OS X via "gcc miditones.c" * -Fix warnings and errors building on Mac OS X via "gcc miditones.c"
* 25 January 2016, D. Blackketter, Paul Stoffregen, V1.9 * 25 January 2016, D. Blackketter, Paul Stoffregen, V1.9
-Merge in velocity output option from Arduino/Teensy Audio Library * -Merge in velocity output option from Arduino/Teensy Audio Library
* 26 June 2016, L. Shustek, V1.10
* -Fix overflow problem in calculating long delays. (Thanks go to Tiago Rocha.)
* In the process I discover and work around an LCC 32-bit compiler bug.
*/ */
#define VERSION "1.9" #define VERSION "1.10"
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
@ -69,9 +72,9 @@
* so that a version of the music can be played on a synthesizer having only * so that a version of the music can be played on a synthesizer having only
* tone generators without any volume or tone controls. * tone generators without any volume or tone controls.
* *
* Volume ("velocity") and instrument specifications in the MIDI files are discarded. * Volume ("velocity") and instrument specifications in the MIDI files are generally
* All the tracks are prcoessed and merged into a single time-ordered stream of * discarded. All the tracks are prcoessed and merged into a single time-ordered
* "note on", "note off", and "delay" commands. * stream of "note on", "note off", and "delay" commands.
* *
* This was written for the "Playtune" Arduino library, which plays polyphonic music * This was written for the "Playtune" Arduino library, which plays polyphonic music
* using up to 6 tone generators run by the timers on the processor. See the separate * using up to 6 tone generators run by the timers on the processor. See the separate
@ -106,7 +109,7 @@
* *
* The general form for command line execution is this: * The general form for command line execution is this:
* *
* miditones [-p] [-lg] [-lp] [-s1] [-tn] [-b] [-cn] [-kn] <basefilename> * miditones [-p] [-lg] [-lp] [-s1] [-tn] [-b] [-cn] [-kn] [-v] <basefilename>
* *
* The <basefilename> is the base name, without an extension, for the input and * The <basefilename> is the base name, without an extension, for the input and
* output files. It can contain directory path information, or not. * output files. It can contain directory path information, or not.
@ -162,7 +165,7 @@
* 9t nn [vv] 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 * 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). * 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 * If the -v option is enabled, a second byte is added to indicate velocity.
* *
* 8t Stop playing the note on tone generator t. * 8t Stop playing the note on tone generator t.
* *
@ -182,7 +185,7 @@
* that were playing before the delay command will continue to play. * that were playing before the delay command will continue to play.
* *
* *
* Len Shustek, 4 Feb 2011 * Len Shustek, 4 Feb 2011 and later
* *
*----------------------------------------------------------------------------------*/ *----------------------------------------------------------------------------------*/
@ -360,7 +363,7 @@ opterror:
void print_command_line (int argc,char *argv[]) { void print_command_line (int argc,char *argv[]) {
int i; int i;
fprintf(outfile, "// command line: "); fprintf(outfile, "// command line: ");
for (i=0; i< argc; i++) fprintf(outfile,"%s ",argv[i]); for (i=0; i< argc; i++) fprintf(outfile,"%s ",argv[i]);
fprintf(outfile, "\n"); fprintf(outfile, "\n");
} }
@ -371,54 +374,54 @@ void print_command_line (int argc,char *argv[]) {
/* safe string copy */ /* safe string copy */
size_t miditones_strlcpy(char *dst, const char *src, size_t siz) { size_t miditones_strlcpy(char *dst, const char *src, size_t siz) {
char *d = dst; char *d = dst;
const char *s = src; const char *s = src;
size_t n = siz; size_t n = siz;
/* Copy as many bytes as will fit */ /* Copy as many bytes as will fit */
if (n != 0) if (n != 0)
{ {
while (--n != 0) while (--n != 0)
{ {
if ((*d++ = *s++) == '\0') if ((*d++ = *s++) == '\0')
break; break;
} }
} }
/* Not enough room in dst, add NUL and traverse rest of src */ /* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) if (n == 0)
{ {
if (siz != 0) if (siz != 0)
*d = '\0'; /* NUL-terminate dst */ *d = '\0'; /* NUL-terminate dst */
while (*s++) while (*s++)
; ;
} }
return (s - src - 1); /* count does not include NUL */ return (s - src - 1); /* count does not include NUL */
} }
/* safe string concatenation */ /* safe string concatenation */
size_t miditones_strlcat(char *dst, const char *src, size_t siz) { size_t miditones_strlcat(char *dst, const char *src, size_t siz) {
char *d = dst; char *d = dst;
const char *s = src; const char *s = src;
size_t n = siz; size_t n = siz;
size_t dlen; size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */ /* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0') while (n-- != 0 && *d != '\0')
d++; d++;
dlen = d - dst; dlen = d - dst;
n = siz - dlen; n = siz - dlen;
if (n == 0) if (n == 0)
return (dlen + strlen(s)); return (dlen + strlen(s));
while (*s != '\0') while (*s != '\0')
{ {
if (n != 1) if (n != 1)
{ {
*d++ = *s; *d++ = *s;
n--; n--;
} }
s++; s++;
} }
*d = '\0'; *d = '\0';
return (dlen + (s - src)); /* count does not include NUL */ return (dlen + (s - src)); /* count does not include NUL */
} }
/* match a constant character sequence */ /* match a constant character sequence */
@ -861,7 +864,9 @@ int main(int argc,char *argv[]) {
delta_time = earliest_time - timenow; delta_time = earliest_time - timenow;
if (delta_time) { if (delta_time) {
/* Convert ticks to milliseconds based on the current tempo */ /* Convert ticks to milliseconds based on the current tempo */
delta_msec = ((unsigned long) delta_time * tempo) / ticks_per_beat / 1000; unsigned long long temp;
temp = ((unsigned long long) delta_time * tempo) / ticks_per_beat;
delta_msec = temp / 1000; // get around LCC compiler bug
if (loggen) fprintf (logfile, "->Delay %ld msec (%ld ticks)\n", delta_msec, delta_time); 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 (delta_msec > 0x7fff) midi_error ("INTERNAL: time delta too big", trk->trkptr);
/* output a 15-bit delay in big-endian format */ /* output a 15-bit delay in big-endian format */

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save