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
* tone generators without any volume or tone controls.
*
* Volume ("velocity") and instrument specifications in the MIDI files are discarded.
* All the tracks are prcoessed and merged into a single time-ordered stream of
* "note on", "note off", and "delay" commands.
* Volume ("velocity") and instrument specifications in the MIDI files are generally
* discarded. All the tracks are prcoessed and merged into a single time-ordered
* stream of "note on", "note off", and "delay" commands.
*
* 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
@ -45,7 +45,7 @@
*
* 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
* 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.
* -k-12 goes one octave down, -k12 goes one octave up, etc.
*
* -v Add velocity information to output
*
*
* ***** 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:
*
* 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.
*
@ -118,26 +121,7 @@
* 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
* -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
* -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
* tone generators without any volume or tone controls.
*
* Volume ("velocity") and instrument specifications in the MIDI files are discarded.
* All the tracks are prcoessed and merged into a single time-ordered stream of
* "note on", "note off", and "delay" commands.
* Volume ("velocity") and instrument specifications in the MIDI files are generally
* discarded. All the tracks are prcoessed and merged into a single time-ordered
* stream of "note on", "note off", and "delay" commands.
*
* 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
@ -106,7 +109,7 @@
*
* 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
* 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
* 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
* If the -v option is enabled, a second byte is added to indicate velocity.
*
* 8t Stop playing the note on tone generator t.
*
@ -182,7 +185,7 @@
* 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[]) {
int i;
fprintf(outfile, "// command line: ");
fprintf(outfile, "// command line: ");
for (i=0; i< argc; i++) fprintf(outfile,"%s ",argv[i]);
fprintf(outfile, "\n");
}
@ -371,54 +374,54 @@ void print_command_line (int argc,char *argv[]) {
/* safe string copy */
size_t miditones_strlcpy(char *dst, const char *src, size_t siz) {
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0)
{
while (--n != 0)
{
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++)
;
}
return (s - src - 1); /* count does not include NUL */
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0)
{
while (--n != 0)
{
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++)
;
}
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++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return (dlen + strlen(s));
while (*s != '\0')
{
if (n != 1)
{
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return (dlen + (s - src)); /* count does not include NUL */
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++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return (dlen + strlen(s));
while (*s != '\0')
{
if (n != 1)
{
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return (dlen + (s - src)); /* count does not include NUL */
}
/* match a constant character sequence */
@ -861,7 +864,9 @@ int main(int argc,char *argv[]) {
delta_time = earliest_time - timenow;
if (delta_time) {
/* 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 (delta_msec > 0x7fff) midi_error ("INTERNAL: time delta too big", trk->trkptr);
/* output a 15-bit delay in big-endian format */

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save