Update of /cvsroot/audacity/lib-src/portsmf
In directory 23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv11472/lib-src/portsmf

Modified Files:
        allegro.cpp allegro.h allegrord.cpp allegrosmfrd.cpp 
        allegrosmfwr.cpp configure mfmidi.cpp mfmidi.h portsmf.vcproj 
Log Message:
Added the 'portmidi' library (used for MIDI playback) to the repository.
Edited AudioIO.cpp to allow for MIDI playback (all changes are wrapped within 
EXPERIMENTAL_MIDI_OUT).
Edited MidiIOprefs.cpp to allow changing MIDI devices via the MIDI preferences 
panel.
Other various MIDI-related bug fixes in portmidi, portsmf, and libscorealign.

Index: allegro.cpp
===================================================================
RCS file: /cvsroot/audacity/lib-src/portsmf/allegro.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- allegro.cpp 22 Jun 2009 08:48:07 -0000      1.5
+++ allegro.cpp 24 Jun 2009 20:37:25 -0000      1.6
@@ -31,7 +31,8 @@
 // 4267 is size_t to long warning
 #pragma warning(disable: 4311 4996 4267)
 Alg_atoms symbol_table;
-Serial_buffer Alg_track::ser_buf; // declare the static variable
+Serial_read_buffer Alg_track::ser_read_buf; // declare the static variables
+Serial_write_buffer Alg_track::ser_write_buf; 
 
 bool within(double d1, double d2, double epsilon)
 {
@@ -224,9 +225,9 @@
 {
     if (!is_note()) {
         const char* attr = get_attribute();
-        if (STREQL(attr, "gate"))         // volume change
+        if (STREQL(attr, "gater"))         // volume change
             return ALG_GATE;
-        if (STREQL(attr, "bend"))         // pitch bend     
+        if (STREQL(attr, "bendr"))         // pitch bend     
             return ALG_BEND;
         if (strncmp(attr, "control", 7) == 0)      // control change
             // note that midi control changes have attributes of the form
@@ -235,15 +236,15 @@
             // We don't check for decimal numbers in the range 0-127, so any
             // attribute that begins with "control" is an ALG_CONTROL:
             return ALG_CONTROL;
-        if (STREQL(attr, "program"))      // program change
+        if (STREQL(attr, "programi"))      // program change
             return ALG_PROGRAM;
-        if (STREQL(attr, "pressure"))    // pressure change
+        if (STREQL(attr, "pressurer"))    // pressure change
             return ALG_PRESSURE;
-        if (STREQL(attr, "keysig"))       // key signature  
+        if (STREQL(attr, "keysigi"))       // key signature  
             return ALG_KEYSIG;
-        if (STREQL(attr, "timesig_num"))  // time signature numerator
+        if (STREQL(attr, "timesig_numi"))  // time signature numerator
             return ALG_TIMESIG_NUM;
-        if (STREQL(attr, "timesig_den"))  // time signature denominator
+        if (STREQL(attr, "timesig_deni"))  // time signature denominator
             return ALG_TIMESIG_DEN;
         return ALG_OTHER;
     }
@@ -1277,22 +1278,22 @@
     //
     // The format for a track is given within the Seq format above
     assert(get_type() == 't');
-    ser_buf.init_for_write();
+    ser_write_buf.init_for_write();
     serialize_track();
-    *buffer = ser_buf.to_heap(bytes); 
+    *buffer = ser_write_buf.to_heap(bytes); 
 }
 
 
 void Alg_seq::serialize(void **buffer, long *bytes)
 {      
     assert(get_type() == 's');
-    ser_buf.init_for_write();
+    ser_write_buf.init_for_write();
     serialize_seq();
-    *buffer = ser_buf.to_heap(bytes); 
+    *buffer = ser_write_buf.to_heap(bytes); 
 }
 
 
-void Serial_buffer::check_buffer(long needed)
+void Serial_write_buffer::check_buffer(long needed)
 {
     if (len < (ptr - buffer) + needed) { // do we need more space?
         long new_len = len * 2; // exponential growth is important
@@ -1301,9 +1302,11 @@
          // make sure new_len is as big as needed
         if (needed > new_len) new_len = needed;
         char *new_buffer = new char[new_len]; // allocate space
-        memcpy(new_buffer, buffer, len); // copy from old buffer
         ptr = new_buffer + (ptr - buffer); // relocate ptr to new buffer
-        delete buffer; // free old buffer
+        if (len > 0) { // we had a buffer already
+            memcpy(new_buffer, buffer, len); // copy from old buffer
+            delete buffer; // free old buffer
+        }
         buffer = new_buffer; // update buffer information
         len = new_len;
     }
@@ -1316,38 +1319,38 @@
     // we can easily compute how much buffer space we need until we
     // get to tracks, so expand at least that much
     long needed = 64 + 16 * time_map->beats.len + 24 * time_sig.length();
-    ser_buf.check_buffer(needed);
-    ser_buf.set_char('A');
-    ser_buf.set_char('L');
-    ser_buf.set_char('G');
-    ser_buf.set_char('S');
-    long length_offset = ser_buf.get_posn();
-    ser_buf.set_int32(0); // leave room to come back and write length
-    ser_buf.set_int32(channel_offset_per_track);
-    ser_buf.set_int32(units_are_seconds);
-    ser_buf.set_double(beat_dur);
-    ser_buf.set_double(real_dur);
-    ser_buf.set_double(time_map->last_tempo);
-    ser_buf.set_int32(time_map->last_tempo_flag);
-    ser_buf.set_int32(time_map->beats.len);
+    ser_write_buf.check_buffer(needed);
+    ser_write_buf.set_char('A');
+    ser_write_buf.set_char('L');
+    ser_write_buf.set_char('G');
+    ser_write_buf.set_char('S');
+    long length_offset = ser_write_buf.get_posn();
+    ser_write_buf.set_int32(0); // leave room to come back and write length
+    ser_write_buf.set_int32(channel_offset_per_track);
+    ser_write_buf.set_int32(units_are_seconds);
+    ser_write_buf.set_double(beat_dur);
+    ser_write_buf.set_double(real_dur);
+    ser_write_buf.set_double(time_map->last_tempo);
+    ser_write_buf.set_int32(time_map->last_tempo_flag);
+    ser_write_buf.set_int32(time_map->beats.len);
     for (i = 0; i < time_map->beats.len; i++) {
-        ser_buf.set_double(time_map->beats[i].time);
-        ser_buf.set_double(time_map->beats[i].beat);
+        ser_write_buf.set_double(time_map->beats[i].time);
+        ser_write_buf.set_double(time_map->beats[i].beat);
     }
-    ser_buf.set_int32(time_sig.length());
-    ser_buf.pad();
+    ser_write_buf.set_int32(time_sig.length());
+    ser_write_buf.pad();
     for (i = 0; i < time_sig.length(); i++) {
-        ser_buf.set_double(time_sig[i].beat);
-        ser_buf.set_double(time_sig[i].num);
-        ser_buf.set_double(time_sig[i].den);
+        ser_write_buf.set_double(time_sig[i].beat);
+        ser_write_buf.set_double(time_sig[i].num);
+        ser_write_buf.set_double(time_sig[i].den);
     }
-    ser_buf.set_int32(tracks());
-    ser_buf.pad(); 
+    ser_write_buf.set_int32(tracks());
+    ser_write_buf.pad(); 
     for (i = 0; i < tracks(); i++) {
         track(i)->serialize_track();
     }
     // do not include ALGS, include padding at end
-    ser_buf.store_long(length_offset, ser_buf.get_posn() - length_offset);
+    ser_write_buf.store_long(length_offset, ser_write_buf.get_posn() - 
length_offset);
 }
 
 
@@ -1355,51 +1358,51 @@
 {
     // to simplify the code, copy from parameter addresses to locals
     int j;
-    ser_buf.check_buffer(32);
-    ser_buf.set_char('A');
-    ser_buf.set_char('L');
-    ser_buf.set_char('G');
-    ser_buf.set_char('T');
-    long length_offset = ser_buf.get_posn(); // save location for track length
-    ser_buf.set_int32(0); // room to write track length
-    ser_buf.set_int32(units_are_seconds);
-    ser_buf.set_double(beat_dur);
-    ser_buf.set_double(real_dur);
-    ser_buf.set_int32(len);
+    ser_write_buf.check_buffer(32);
+    ser_write_buf.set_char('A');
+    ser_write_buf.set_char('L');
+    ser_write_buf.set_char('G');
+    ser_write_buf.set_char('T');
+    long length_offset = ser_write_buf.get_posn(); // save location for track 
length
+    ser_write_buf.set_int32(0); // room to write track length
+    ser_write_buf.set_int32(units_are_seconds);
+    ser_write_buf.set_double(beat_dur);
+    ser_write_buf.set_double(real_dur);
+    ser_write_buf.set_int32(len);
     for (j = 0; j < len; j++) {
-        ser_buf.check_buffer(24);
+        ser_write_buf.check_buffer(24);
         Alg_event *event = (*this)[j];
-        ser_buf.set_int32(event->get_selected());
-        ser_buf.set_int32(event->get_type());
-        ser_buf.set_int32(event->get_identifier());
-        ser_buf.set_int32(event->chan);
-        ser_buf.set_double(event->time);
+        ser_write_buf.set_int32(event->get_selected());
+        ser_write_buf.set_int32(event->get_type());
+        ser_write_buf.set_int32(event->get_identifier());
+        ser_write_buf.set_int32(event->chan);
+        ser_write_buf.set_double(event->time);
         if (event->is_note()) {
-            ser_buf.check_buffer(20);
+            ser_write_buf.check_buffer(20);
             Alg_note *note = (Alg_note *) event;
-            ser_buf.set_float(note->pitch);
-            ser_buf.set_float(note->loud);
-            ser_buf.set_double(note->dur);
-            long parm_num_offset = ser_buf.get_posn();
+            ser_write_buf.set_float(note->pitch);
+            ser_write_buf.set_float(note->loud);
+            ser_write_buf.set_double(note->dur);
+            long parm_num_offset = ser_write_buf.get_posn();
             long parm_num = 0;
-            ser_buf.set_int32(0); // placeholder for no. parameters
+            ser_write_buf.set_int32(0); // placeholder for no. parameters
             Alg_parameters_ptr parms = note->parameters;
             while (parms) {
                 serialize_parameter(&(parms->parm));
                 parms = parms->next;
                 parm_num++;
             }
-            ser_buf.store_long(parm_num_offset, parm_num);
+            ser_write_buf.store_long(parm_num_offset, parm_num);
         } else {
             assert(event->is_update());
             Alg_update *update = (Alg_update *) event;
             serialize_parameter(&(update->parameter));
         }
-        ser_buf.check_buffer(7); // maximum padding possible
-        ser_buf.pad();
+        ser_write_buf.check_buffer(7); // maximum padding possible
+        ser_write_buf.pad();
     }
     // write length, not including ALGT, including padding at end
-    ser_buf.store_long(length_offset, ser_buf.get_posn() - length_offset);
+    ser_write_buf.store_long(length_offset, ser_write_buf.get_posn() - 
length_offset);
 }
 
 
@@ -1408,29 +1411,29 @@
     // add eight to account for name + zero end-of-string and the
     // possibility of adding 7 padding bytes
     long len = strlen(parm->attr_name()) + 8;
-    ser_buf.check_buffer(len);
-    ser_buf.set_string(parm->attr_name());
-    ser_buf.pad();
+    ser_write_buf.check_buffer(len);
+    ser_write_buf.set_string(parm->attr_name());
+    ser_write_buf.pad();
     switch (parm->attr_type()) {
     case 'r':
-        ser_buf.check_buffer(8);
-        ser_buf.set_double(parm->r);
+        ser_write_buf.check_buffer(8);
+        ser_write_buf.set_double(parm->r);
         break;
     case 's':
-        ser_buf.check_buffer(strlen(parm->s) + 1);
-        ser_buf.set_string(parm->s);
+        ser_write_buf.check_buffer(strlen(parm->s) + 1);
+        ser_write_buf.set_string(parm->s);
         break;
     case 'i':
-        ser_buf.check_buffer(4);
-        ser_buf.set_int32(parm->i);
+        ser_write_buf.check_buffer(4);
+        ser_write_buf.set_int32(parm->i);
         break;
     case 'l':
-        ser_buf.check_buffer(4);
-        ser_buf.set_int32(parm->l);
+        ser_write_buf.check_buffer(4);
+        ser_write_buf.set_int32(parm->l);
         break;
     case 'a':
-        ser_buf.check_buffer(strlen(parm->a) + 1);
-        ser_buf.set_string(parm->a);
+        ser_write_buf.check_buffer(strlen(parm->a) + 1);
+        ser_write_buf.set_string(parm->a);
         break;
     }
 }
@@ -1440,19 +1443,21 @@
 Alg_track *Alg_track::unserialize(void *buffer, long len)
 {
     assert(len > 8);
-    ser_buf.init_for_read(buffer, len);
-    bool alg = ser_buf.get_char() == 'A' &&
-               ser_buf.get_char() == 'L' &&
-               ser_buf.get_char() == 'G';
+    ser_read_buf.init_for_read(buffer, len);
+    bool alg = ser_read_buf.get_char() == 'A' &&
+               ser_read_buf.get_char() == 'L' &&
+               ser_read_buf.get_char() == 'G';
     assert(alg);
-    char c = ser_buf.get_char();
+    char c = ser_read_buf.get_char();
     if (c == 'S') {
         Alg_seq *seq = new Alg_seq;
+        ser_read_buf.unget_chars(4); // undo get_char() of A,L,G,S
         seq->unserialize_seq();
         return seq;
     } else {
         assert(c == 'T');
         Alg_track *track = new Alg_track;
+        ser_read_buf.unget_chars(4); // undo get_char() of A,L,G,T
         track->unserialize_track();
         return track;
     }
@@ -1461,84 +1466,88 @@
 
 #pragma warning(disable: 4800) // long to bool performance warning
 
+/* Note: this Alg_seq must have a default initialized Alg_time_map.
+ * It will be filled in with data from the ser_read_buf buffer.
+ */
 void Alg_seq::unserialize_seq()
 {
-    ser_buf.check_input_buffer(28);
-    long len = ser_buf.get_int32();
-    assert(ser_buf.get_len() >= len);
-    channel_offset_per_track = ser_buf.get_int32();
-    units_are_seconds = ser_buf.get_int32() != 0;
-    beat_dur = ser_buf.get_double();
-    real_dur = ser_buf.get_double();
-    // no need to allocate an Alg_time_map since its done during instantiation
-    time_map->last_tempo = ser_buf.get_double();
-    time_map->last_tempo_flag = ser_buf.get_int32() != 0;
-    long beats = ser_buf.get_int32();
-    ser_buf.check_input_buffer(beats * 16 + 4);
+    ser_read_buf.check_input_buffer(48);
+    bool algs = (ser_read_buf.get_char() == 'A') &&
+                (ser_read_buf.get_char() == 'L') &&
+                (ser_read_buf.get_char() == 'G') &&
+                (ser_read_buf.get_char() == 'S');
+    assert(algs);
+    long len = ser_read_buf.get_int32();
+    assert(ser_read_buf.get_len() >= len);
+    channel_offset_per_track = ser_read_buf.get_int32();
+    units_are_seconds = ser_read_buf.get_int32() != 0;
+    beat_dur = ser_read_buf.get_double();
+    real_dur = ser_read_buf.get_double();
+    // no need to allocate an Alg_time_map since it's done during 
initialization
+    time_map->last_tempo = ser_read_buf.get_double();
+    time_map->last_tempo_flag = ser_read_buf.get_int32() != 0;
+    long beats = ser_read_buf.get_int32();
+    ser_read_buf.check_input_buffer(beats * 16 + 4);
     int i;
     for (i = 0; i < beats; i++) {
-        double time = ser_buf.get_double();
-        double beat = ser_buf.get_double();
+        double time = ser_read_buf.get_double();
+        double beat = ser_read_buf.get_double();
         time_map->insert_beat(time, beat);
         // printf("time_map: %g, %g\n", time, beat);
     }
-    long time_sig_len = ser_buf.get_int32();
-    ser_buf.get_pad();
-    ser_buf.check_input_buffer(time_sig_len * 24 + 8);
+    long time_sig_len = ser_read_buf.get_int32();
+    ser_read_buf.get_pad();
+    ser_read_buf.check_input_buffer(time_sig_len * 24 + 8);
     for (i = 0; i < time_sig_len; i++) {
-        double beat = ser_buf.get_double();
-        double num = ser_buf.get_double();
-        double den = ser_buf.get_double();
+        double beat = ser_read_buf.get_double();
+        double num = ser_read_buf.get_double();
+        double den = ser_read_buf.get_double();
         time_sig.insert(beat, num, den);
     }
-    long tracks_num = ser_buf.get_int32();
-    ser_buf.get_pad();
+    long tracks_num = ser_read_buf.get_int32();
+    ser_read_buf.get_pad();
     add_track(tracks_num - 1); // create tracks_num tracks
     for (i = 0; i < tracks_num; i++) {
-        bool algt = ser_buf.get_char() == 'A' &&
-                    ser_buf.get_char() == 'L' &&
-                    ser_buf.get_char() == 'G' &&
-                    ser_buf.get_char() == 'T';
-        if (!algt) {
-            assert(algt);
-            // bug or bad data
-            break;
-        }
         track(i)->unserialize_track();
     }
     // assume seq started at beginning of buffer. len measures
     // bytes after 'ALGS' header, so add 4 bytes and compare to
     // current buffer position -- they should agree
-    assert(ser_buf.get_posn() == len + 4);
+    assert(ser_read_buf.get_posn() == len + 4);
 }
 
 
 void Alg_track::unserialize_track()
 {
-    ser_buf.check_input_buffer(24);
-    long offset = ser_buf.get_posn(); // stored length does not include 'ALGT'
-    long bytes = ser_buf.get_int32();
-    assert(bytes <= ser_buf.get_len() - offset);
-    units_are_seconds = ser_buf.get_int32() != 0;
-    beat_dur = ser_buf.get_double();
-    real_dur = ser_buf.get_double();
-    int event_count = ser_buf.get_int32();
+    ser_read_buf.check_input_buffer(32);
+    bool algt = (ser_read_buf.get_char() == 'A') &&
+                (ser_read_buf.get_char() == 'L') &&
+                (ser_read_buf.get_char() == 'G') &&
+                (ser_read_buf.get_char() == 'T');
+    assert(algt);
+    long offset = ser_read_buf.get_posn(); // stored length does not include 
'ALGT'
+    long bytes = ser_read_buf.get_int32();
+    assert(bytes <= ser_read_buf.get_len() - offset);
+    units_are_seconds = (bool) ser_read_buf.get_int32();
+    beat_dur = ser_read_buf.get_double();
+    real_dur = ser_read_buf.get_double();
+    int event_count = ser_read_buf.get_int32();
     for (int i = 0; i < event_count; i++) {
-        ser_buf.check_input_buffer(24);
-        long selected = ser_buf.get_int32();
-        char type = (char) ser_buf.get_int32();
-        long key = ser_buf.get_int32();
-        long channel = ser_buf.get_int32();
-        double time = ser_buf.get_double();
+        ser_read_buf.check_input_buffer(24);
+        long selected = ser_read_buf.get_int32();
+        char type = (char) ser_read_buf.get_int32();
+        long key = ser_read_buf.get_int32();
+        long channel = ser_read_buf.get_int32();
+        double time = ser_read_buf.get_double();
         if (type == 'n') {
-            ser_buf.check_input_buffer(20);
-            float pitch = ser_buf.get_float();
-            float loud = ser_buf.get_float();
-            double dur = ser_buf.get_double();
+            ser_read_buf.check_input_buffer(20);
+            float pitch = ser_read_buf.get_float();
+            float loud = ser_read_buf.get_float();
+            double dur = ser_read_buf.get_double();
             Alg_note *note = 
                     create_note(time, channel, key, pitch, loud, dur);
             note->set_selected(selected != 0);
-            long param_num = ser_buf.get_int32();
+            long param_num = ser_read_buf.get_int32();
             int j;
             // this builds a list of parameters in the correct order
             // (although order shouldn't matter)
@@ -1556,34 +1565,34 @@
             unserialize_parameter(&(update->parameter));
             append(update);
         }
-        ser_buf.get_pad();
+        ser_read_buf.get_pad();
     }
-    assert(offset + bytes == ser_buf.get_posn());
+    assert(offset + bytes == ser_read_buf.get_posn());
 }
 
 
 void Alg_track::unserialize_parameter(Alg_parameter_ptr parm_ptr)
 {
-    char *attr = ser_buf.get_string();
+    char *attr = ser_read_buf.get_string();
     parm_ptr->attr = symbol_table.insert_string(attr);
     switch (parm_ptr->attr_type()) {
     case 'r':
-        ser_buf.check_input_buffer(8);
-        parm_ptr->r = ser_buf.get_double();
+        ser_read_buf.check_input_buffer(8);
+        parm_ptr->r = ser_read_buf.get_double();
         break;
     case 's':
-        parm_ptr->s = heapify(ser_buf.get_string());
+        parm_ptr->s = heapify(ser_read_buf.get_string());
         break;
     case 'i':
-        ser_buf.check_input_buffer(4);
-        parm_ptr->i = ser_buf.get_int32();
+        ser_read_buf.check_input_buffer(4);
+        parm_ptr->i = ser_read_buf.get_int32();
         break;
     case 'l':
-        ser_buf.check_input_buffer(4);
-        parm_ptr->l = ser_buf.get_int32() != 0;
+        ser_read_buf.check_input_buffer(4);
+        parm_ptr->l = ser_read_buf.get_int32() != 0;
         break;
     case 'a':
-        parm_ptr->a = symbol_table.insert_attribute(ser_buf.get_string());
+        parm_ptr->a = symbol_table.insert_attribute(ser_read_buf.get_string());
         break;
     }
 }
@@ -2204,8 +2213,8 @@
     // all track events are incorporated into the seq,
     // so all we need to delete are the arrays of pointers
     for (int i = 0; i < len; i++) {
-        printf("deleting track at %d (%x, this %x) = %x\n", i, &(tracks[i]), 
-               this, tracks[i]);
+        // printf("deleting track at %d (%x, this %x) = %x\n", i, 
&(tracks[i]), 
+        //       this, tracks[i]);
         delete tracks[i];
     }
     if (tracks) delete [] tracks;
@@ -2215,6 +2224,126 @@
 }
 
 
+void Alg_iterator::expand_to(int new_max)
+{
+    maxlen = new_max;
+    Alg_pending_event_ptr new_pending_events = new Alg_pending_event[maxlen];
+    // now do copy
+    memcpy(new_pending_events, pending_events, 
+           len * sizeof(Alg_pending_event));
+    if (pending_events) {
+        delete[] pending_events;
+    }
+    pending_events = new_pending_events;
+}      
+
+
+void Alg_iterator::expand()
+{
+    maxlen = (maxlen + 5);   // extra growth for small sizes
+    maxlen += (maxlen >> 2); // add 25%
+    expand_to(maxlen);
+}
+
+
+Alg_iterator::~Alg_iterator()
+{
+    if (pending_events) {
+        delete[] pending_events;
+    }
+}
+
+
+/* in the heap, the children of N are (N+1)*2 and (N+1)*2-1, so
+ * the parent of N is (N+1)/2-1. This would be easier if arrays
+ * were 1-based instead of 0-based
+ */
+#define HEAP_PARENT(loc) ((((loc) + 1) / 2) - 1)
+#define FIRST_CHILD(loc) (((loc) * 2) + 1)
+
+void Alg_iterator::show()
+{
+    for (int i = 0; i < len; i++) {
+        Alg_pending_event_ptr p = &(pending_events[i]);
+        printf("    %d: %p[%d] on %d\n", i, p->events, p->index, p->note_on);
+    }
+}
+
+
+bool Alg_iterator::earlier(int i, int j)
+// see if event i is earlier than event j
+{
+    Alg_pending_event_ptr p_i = &(pending_events[i]);
+    Alg_event_ptr e_i = (*(p_i->events))[p_i->index];
+    double t_i = (p_i->note_on ? e_i->time : e_i->get_end_time());
+    
+    Alg_pending_event_ptr p_j = &(pending_events[j]);
+    Alg_event_ptr e_j = (*(p_j->events))[p_j->index];
+    double t_j = (p_j->note_on ? e_j->time : e_j->get_end_time());
+
+    if (t_i < t_j) return true;
+    // not sure if this case really exists or this is the best rule, but
+    // we want to give precedence to note-off events
+    else if (t_i == t_j && pending_events[j].note_on) return true;
+    return false;
+}
+
+
+void Alg_iterator::insert(Alg_events_ptr events, long index, bool note_on)
+{
+    if (len == maxlen) expand();
+    pending_events[len].events = events;
+    pending_events[len].index = index;
+    pending_events[len].note_on = note_on;
+    int loc = len;
+    int loc_parent = HEAP_PARENT(loc);
+    len++;
+    // sift up:
+    while (loc > 0 &&
+           earlier(loc, loc_parent)) {
+        // swap loc with loc_parent
+        Alg_pending_event temp = pending_events[loc];
+        pending_events[loc] = pending_events[loc_parent];
+        pending_events[loc_parent] = temp;
+        loc = loc_parent;
+        loc_parent = HEAP_PARENT(loc);
+    }
+    //    printf("After insert:"); show();
+}
+
+bool Alg_iterator::remove_next(Alg_events_ptr &events, long &index, 
+                              bool &note_on)
+{
+    if (len == 0) return false; // empty!
+    events = pending_events[0].events;
+    index = pending_events[0].index;
+    note_on = pending_events[0].note_on;
+    len--;
+    pending_events[0] = pending_events[len];
+    // sift down
+    long loc = 0;
+    long loc_child = FIRST_CHILD(loc);
+    while (loc_child < len) {
+        if (loc_child + 1 < len) {
+            if (earlier(loc_child + 1, loc_child)) {
+                loc_child++;
+            }
+        }
+        if (earlier(loc_child, loc)) {
+            Alg_pending_event temp = pending_events[loc];
+            pending_events[loc] = pending_events[loc_child];
+            pending_events[loc_child] = temp;
+            loc = loc_child;
+            loc_child = FIRST_CHILD(loc);
+        } else {
+            loc_child = len;
+        }
+    }
+    //    printf("After remove:"); show();
+    return true;
+}
+
+
 Alg_seq::Alg_seq(const char *filename, bool smf)
 {
     basic_initialization();
@@ -2813,43 +2942,47 @@
 */
 
 
-void Alg_seq::iteration_begin()
+void Alg_iterator::begin(bool note_off_flag)
 {
     // keep an array of indexes into tracks
-    current = new long[track_list.length()];
+    printf("new pending\n");
     int i;
-    for (i = 0; i < track_list.length(); i++) {
-        current[i] = 0;
+    for (i = 0; i < seq->track_list.length(); i++) {
+        if (seq->track_list[i].length() > 0) {
+            insert(&(seq->track_list[i]), 0, true);
+        }
     }    
 }
 
 
-Alg_event_ptr Alg_seq::iteration_next()
+Alg_event_ptr Alg_iterator::next(bool *note_on)
     // return the next event in time from any track
 {
-    long cur;           // a track index
-    // find lowest next time of any track:
-    double next = 1000000.0;
-    int i, track;
-    for (i = 0; i < track_list.length(); i++) {
-        Alg_track &tr = track_list[i];
-        cur = current[i];
-        if (cur < tr.length() && tr[cur]->time < next) {
-            next = tr[cur]->time;
-            track = i;
-        }
-    }
-    if (next < 1000000.0) {
-        return track_list[track][current[track]++];
-    } else {
+    Alg_events_ptr events_ptr;
+    long index;
+    bool on;
+    if (!remove_next(events_ptr, index, on)) {
         return NULL;
     }
+    if (note_on) *note_on = on;
+    Alg_event_ptr event = (*events_ptr)[index];
+    if (on) {
+        if (note_off_flag && event->is_note()) {
+            // this was a note-on, so insert pending note-off
+            insert(events_ptr, index, false);
+        }
+        // for both notes and updates, insert next event (at index + 1)
+        index++;
+        if (index < events_ptr->length()) {
+            insert(events_ptr, index, true);
+        }
+    }
+    return event;
 }
 
 
-void Alg_seq::iteration_end()
+void Alg_iterator::end()
 {
-    delete[] current;
 }
 
 
@@ -2862,17 +2995,18 @@
     }
     // preallocate array for efficiency:
     Alg_event_ptr *notes = new Alg_event_ptr[sum];
-    iteration_begin();
+    Alg_iterator iterator(this, false);
+    iterator.begin();
     long notes_index = 0;
 
     Alg_event_ptr event;
-    while (event = iteration_next()) {
+    while (event = iterator.next()) {
         notes[notes_index++] = event;
     }
     track_list.reset(); // don't need them any more
     add_track(0);
     track(0)->set_events(notes, sum, sum);
-    iteration_end();
+    iterator.end();
 }
 
 

Index: allegro.h
===================================================================
RCS file: /cvsroot/audacity/lib-src/portsmf/allegro.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- allegro.h   22 Jun 2009 08:48:07 -0000      1.7
+++ allegro.h   24 Jun 2009 20:37:26 -0000      1.8
@@ -79,13 +79,18 @@
         maxlen = len = 0;
         atoms = NULL;
     }
+    // Note: the code is possibly more correct and faster without the 
+    // following destructor, which will only run after the program takes 
+    // a normal exit. Cleaning up after the program exit slows down the exit,
+    // and will cause problems if any other destructor tries to reference an
+    // Alg_atom (which will now be freed). The advantage of this code is
+    // that Alg_atoms will not be reported as memory leaks by automation
+    // that doesn't know better. -RBD
     virtual ~Alg_atoms() {
         for (int i = 0; i < len; i++) {
-            if (atoms[i]) {
-                delete atoms[i];
-            }
+            delete atoms[i];
         }
-        if (atoms) delete[] atoms;
+        if (atoms) delete [] atoms;
     }
     // insert/lookup an atttribute
     Alg_attribute insert_attribute(Alg_attribute attr);
@@ -496,23 +501,72 @@
 } *Alg_time_map_ptr;
 
 
-typedef class Serial_buffer {
-private:
+// Serial_buffer is an abstract class with common elements of
+//     Serial_read_buffer and Serial_write_buffer
+class Serial_buffer {
+  protected:
     char *buffer;
     char *ptr;
     long len;
-public:
+  public:
     Serial_buffer() {
         buffer = NULL;
         ptr = NULL;
         len = 0;
     }
-    ~Serial_buffer() {
+    virtual ~Serial_buffer() { }
+
+    long get_posn() { return (long) (ptr - buffer); }
+    long get_len() { return len; }
+};
+
+
+typedef class Serial_read_buffer : public Serial_buffer {
+public:
+    // note that a Serial_read_buffer is initialized for reading by
+    // setting buffer, but it is not the Serial_read_buffer's responsibility
+    // to delete the buffer (owner might want to reuse it), so the destructor
+    // does nothing.
+    virtual ~Serial_read_buffer() {  }
+#pragma warning(disable: 546) // cast to int is OK, we only want low 7 bits
+#pragma warning(disable: 4311) // type cast pointer to long warning
+    void get_pad() { while (((long) ptr) & 7) ptr++; }
+#pragma warning(default: 4311 546)
+    // Prepare to read n bytes from buf. The caller must manage buf: it is
+    // valid until reading is finished, and it is caller's responsibility
+    // to free buf when it is no longer needed.
+    void init_for_read(void *buf, long n) {
+        buffer = (char *) buf;
+        ptr = (char *) buf;
+        len = n;
+    }
+    char get_char() { return *ptr++; }
+    void unget_chars(int n) { ptr -= n; } // undo n get_char() calls
+    long get_int32() { long i = *((long *) ptr); ptr += 4; return i; }
+    float get_float() { float f = *((float *) ptr); ptr += 4; return f; }
+    double get_double() { double d = *((double *) ptr); ptr += sizeof(double); 
+                          return d; }
+    char *get_string() { char *s = ptr; char *fence = buffer + len;
+                         assert(ptr < fence);
+                         while (*ptr++) assert(ptr < fence);
+                         get_pad();
+                         return s; }
+    void check_input_buffer(long needed) {
+        assert(get_posn() + needed <= len); }
+} *Serial_read_buffer_ptr;
+
+
+typedef class Serial_write_buffer: public Serial_buffer {
+  public:
+    // Note: allegro.cpp declares one static instance of Serial_buffer to 
+    // reduce large memory (re)allocations when serializing tracks for UNDO.
+    // This destructor will only run when the program exits, which will only
+    // add overhead to the exit process, but it will eliminate an incorrect
+    // report of memory leakage from automation that doesn't know better. -RBD
+    virtual ~Serial_write_buffer() {
         if (buffer) delete [] buffer;
     }
     void init_for_write() { ptr = buffer; }
-    long get_posn() { return (long) (ptr - buffer); }
-    long get_len() { return len; }
     // store_long writes a long at a given offset
     void store_long(long offset, long value) {
         assert(offset <= get_posn() - 4);
@@ -526,8 +580,8 @@
         // two lots of brackets surpress a g++ warning, because this is an
         // assignment operator inside a test.
         while ((*ptr++ = *s++)) assert(ptr < fence);
-// 4311 is type cast pointer to long warning
-// 4312 is type cast loing to pointer warning
+        // 4311 is type cast pointer to long warning
+        // 4312 is type cast long to pointer warning
 #pragma warning(disable: 4311 4312)
         assert((char *)(((long) (ptr + 7)) & ~7) <= fence);
 #pragma warning(default: 4311 4312)
@@ -539,37 +593,14 @@
 #pragma warning(disable: 546) // cast to int is OK, we only want low 7 bits
 #pragma warning(disable: 4311) // type cast pointer to long warning
     void pad() { while (((long) ptr) & 7) set_char(0); }
-    void get_pad() { while (((long) ptr) & 7) ptr++; }
-#pragma warning(default: 4311)
-#pragma warning(default: 546)
+#pragma warning(default: 4311 546)
     void *to_heap(long *len) {
         *len = get_posn();
         char *newbuf = new char[*len];
         memcpy(newbuf, buffer, *len);
         return newbuf;
     }
-    void init_for_read(void *buf, long n) {
-        if (buffer) {
-            delete [] buffer;
-        }
-        buffer = new char[n];
-        memcpy(buffer, buf, n);
-        ptr = buffer;
-        len = n;
-    }
-    char get_char() { return *ptr++; }
-    long get_int32() { long i = *((long *) ptr); ptr += 4; return i; }
-    float get_float() { float f = *((float *) ptr); ptr += 4; return f; }
-    double get_double() { double d = *((double *) ptr); ptr += sizeof(double); 
-                          return d; }
-    char *get_string() { char *s = ptr; char *fence = buffer + len;
-                         assert(ptr < fence);
-                         while (*ptr++) assert(ptr < fence);
-                         get_pad();
-                         return s; }
-    void check_input_buffer(long needed) {
-        assert(get_posn() + needed <= len); }
-} *Serial_buffer_ptr;
+} *Serial_write_buffer_ptr;
 
 typedef class Alg_seq *Alg_seq_ptr;
 
@@ -581,7 +612,8 @@
     long get_int32(char **p, long *b);
     double get_double(char **p, long *b);
     float get_float(char **p, long *b);
-    static Serial_buffer ser_buf;
+    static Serial_read_buffer ser_read_buf;
+    static Serial_write_buffer ser_write_buf;
     void serialize_parameter(Alg_parameter *parm);
     // *buffer_ptr points to binary data, bytes_ptr points to how many
     // bytes have been used so far, len is length of binary data
@@ -604,7 +636,8 @@
     // copy constructor: event_list is copied, map is installed and referenced
     Alg_track(Alg_event_list_ref event_list, Alg_time_map_ptr map, 
               bool units_are_seconds);
-    virtual ~Alg_track() { if (time_map) time_map->dereference(); time_map = 
NULL; }
+    virtual ~Alg_track() { // note: do not call set_time_map(NULL)!
+        if (time_map) time_map->dereference(); time_map = NULL; }
 
     // Returns a buffer containing a serialization of the
     // file.  It will be an ASCII representation unless text is true.
@@ -839,20 +872,65 @@
 typedef enum {
     alg_no_error = 0,      // no error reading Allegro or MIDI file
     alg_error_open = -800, // could not open Allegro or MIDI file
-    alg_error_syntax       // something found in the file that could not be 
parsed;
-    // generally you should ignore syntax errors or look at the printed error 
messages
-    // because there are some things in standard midi files that we do not 
handle;
-    // (maybe we should only set alg_error_syntax when there is a real problem 
with
-    // the file as opposed to when there is some warning message for the user)
+    alg_error_syntax   // something found in the file that could not be parsed;
+    // generally you should ignore syntax errors or look at the printed error 
+    // messages because there are some things in standard midi files that we do
+    // not handle; (maybe we should only set alg_error_syntax when there is a
+    // real problem with the file as opposed to when there is some warning
+    // message for the user)
 } Alg_error;
 
 
+typedef struct Alg_pending_event {
+    Alg_events *events; // the array of events
+    long index; // offset of this event
+    bool note_on; // is this a note-on or a note-off (if applicable)?
+} *Alg_pending_event_ptr;
+
+typedef class Alg_iterator {
+private:
+    long maxlen;
+    void expand();
+    void expand_to(int new_max);
+    long len;
+    Alg_seq_ptr seq;
+    Alg_pending_event *pending_events;
+
+    void show();
+    bool earlier(int i, int j);
+    void insert(Alg_events_ptr events, long index, bool note_on);
+    bool remove_next(Alg_events_ptr &events, long &index, bool &note_on);
+public:
+    bool note_off_flag; // remembers if we are iterating over note-off
+                        // events as well as note-on and update events
+    long length() { return len; }
+    Alg_iterator(Alg_seq_ptr s, bool note_off) {
+        seq = s;
+        note_off_flag = note_off;
+        maxlen = len = 0;
+        pending_events = NULL;
+    }
+    ~Alg_iterator();
+    // Prepare to enumerate events in order. If note_off_flag is true, then
+    // iteration_next will merge note-off events into the sequence.
+    void begin(bool note_off_flag = false); 
+    // return next event (or NULL). If iteration_begin was called with
+    // note_off_flag = true, and if note_on is not NULL, then *note_on
+    // is set to true when the result value represents a note-on or update.
+    // (With note_off_flag, each Alg_note event is returned twice, once
+    // at the note-on time, with *note_on == true, and once at the note-off
+    // time, with *note_on == false
+    Alg_event_ptr next(bool *note_on = NULL); 
+    void end();   // clean up after enumerating events
+} *Alg_iterator_ptr;
+
+
 // An Alg_seq is an array of Alg_events, each a sequence of Alg_event, 
 // with a tempo map and a sequence of time signatures
 //
 typedef class Alg_seq : public Alg_track {
 protected:
-    long *current; // array of indexes used by iteration methods
+    Alg_iterator_ptr pending; // iterator used internally by Alg_seq methods
     void serialize_seq();
     Alg_error error; // error code set by file readers
     // an internal function used for writing Allegro track names
@@ -948,9 +1026,6 @@
                          double *num, double *den);
     // void set_events(Alg_event_ptr *events, long len, long max);
     void merge_tracks();    // move all track data into one track
-    void iteration_begin(); // prepare to enumerate events in order
-    Alg_event_ptr iteration_next(); // return next event (or NULL)
-    void iteration_end();   // clean up after enumerating events
 } *Alg_seq_ptr, &Alg_seq_ref;
 
 

Index: configure
===================================================================
RCS file: /cvsroot/audacity/lib-src/portsmf/configure,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- configure   17 Jan 2009 22:25:39 -0000      1.3
+++ configure   24 Jun 2009 20:37:26 -0000      1.4
@@ -7121,7 +7121,8 @@
 if test -n "$CONFIG_FILES"; then
 
 
-ac_cr='
'
+ac_cr='
+'
 ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
 if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
   ac_cs_awk_cr='\\r'

Index: portsmf.vcproj
===================================================================
RCS file: /cvsroot/audacity/lib-src/portsmf/portsmf.vcproj,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- portsmf.vcproj      11 Jul 2008 15:39:25 -0000      1.1
+++ portsmf.vcproj      24 Jun 2009 20:37:27 -0000      1.2
@@ -1,11 +1,12 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
        ProjectType="Visual C++"
-       Version="8.00"
+       Version="9.00"
        Name="portsmf"
        ProjectGUID="{D035BCF8-CF15-4456-A4E1-C7E6ACD79346}"
        RootNamespace="allegro"
        Keyword="Win32Proj"
+       TargetFrameworkVersion="131072"
        >
        <Platforms>
                <Platform
@@ -46,7 +47,7 @@
                                RuntimeLibrary="3"
                                UsePrecompiledHeader="0"
                                WarningLevel="0"
-                               Detect64BitPortabilityProblems="true"
+                               Detect64BitPortabilityProblems="false"
                                DebugInformationFormat="4"
                        />
                        <Tool
@@ -103,10 +104,10 @@
                        <Tool
                                Name="VCCLCompilerTool"
                                PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
-                               RuntimeLibrary="2"
+                               RuntimeLibrary="0"
                                UsePrecompiledHeader="0"
                                WarningLevel="3"
-                               Detect64BitPortabilityProblems="true"
+                               Detect64BitPortabilityProblems="false"
                                DebugInformationFormat="3"
                        />
                        <Tool

Index: allegrosmfrd.cpp
===================================================================
RCS file: /cvsroot/audacity/lib-src/portsmf/allegrosmfrd.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- allegrosmfrd.cpp    22 Jun 2009 08:48:07 -0000      1.3
+++ allegrosmfrd.cpp    24 Jun 2009 20:37:26 -0000      1.4
@@ -13,13 +13,13 @@
 
 using namespace std;
 
-typedef class Alg_pending {
+typedef class Alg_note_list {
 public:
     Alg_note_ptr note;
-    class Alg_pending *next;
-    Alg_pending(Alg_note_ptr n, class Alg_pending *list) { 
+    class Alg_note_list *next;
+    Alg_note_list(Alg_note_ptr n, class Alg_note_list *list) { 
         note = n; next = list; }
-} *Alg_pending_ptr;
+} *Alg_note_list_ptr;
 
 
 class Alg_midifile_reader: public Midifile_reader {
@@ -27,7 +27,7 @@
     istream *file;
     Alg_seq_ptr seq;
     int divisions;
-    Alg_pending_ptr pending;
+    Alg_note_list_ptr note_list;
     Alg_track_ptr track;
     int track_number; // the number of the (current) track
     // chan is actual_channel + channel_offset_per_track * track_num +
@@ -41,7 +41,7 @@
 
     Alg_midifile_reader(istream &f, Alg_seq_ptr new_seq) {
         file = &f;
-        pending = NULL;
+        note_list = NULL;
         seq = new_seq;
         channel_offset_per_track = 0;
         channel_offset_per_port = 16;
@@ -83,25 +83,25 @@
     void Mf_pitchbend(int,int,int);
     void Mf_program(int,int);
     void Mf_chanpressure(int,int);
-    void binary_msg(int len, char *msg, const char *attr_string);
-    void Mf_sysex(int,char*);
-    void Mf_arbitrary(int,char*);
-    void Mf_metamisc(int,int,char*);
+    void binary_msg(int len, unsigned char *msg, const char *attr_string);
+    void Mf_sysex(int,unsigned char*);
+    void Mf_arbitrary(int,unsigned char*);
+    void Mf_metamisc(int,int,unsigned char*);
     void Mf_seqnum(int);
     void Mf_smpte(int,int,int,int,int);
     void Mf_timesig(int,int,int,int);
     void Mf_tempo(int);
     void Mf_keysig(int,int);
-    void Mf_sqspecific(int,char*);
-    void Mf_text(int,int,char*);
+    void Mf_sqspecific(int,unsigned char*);
+    void Mf_text(int,int,unsigned char*);
 };
 
 
 Alg_midifile_reader::~Alg_midifile_reader()
 {
-    while (pending) {
-        Alg_pending_ptr to_be_freed = pending;
-        pending = pending->next;
+    while (note_list) {
+        Alg_note_list_ptr to_be_freed = note_list;
+        note_list = note_list->next;
         delete to_be_freed;
     }
     finalize(); // free Mf reader memory
@@ -203,7 +203,7 @@
         return;
     }
     Alg_note_ptr note = new Alg_note();
-    pending = new Alg_pending(note, pending);
+    note_list = new Alg_note_list(note, note_list);
     /*    trace("on: %d at %g\n", key, get_time()); */
     note->time = get_time();
     note->chan = chan + channel_offset + port * channel_offset_per_port;
@@ -219,14 +219,14 @@
 void Alg_midifile_reader::Mf_off(int chan, int key, int vel)
 {
     double time = get_time();
-    Alg_pending_ptr *p = &pending;
+    Alg_note_list_ptr *p = &note_list;
     while (*p) {
         if ((*p)->note->get_identifier() == key &&
             (*p)->note->chan == 
                     chan + channel_offset + port * channel_offset_per_port) {
             (*p)->note->dur = time - (*p)->note->time;
             // trace("updated %d dur %g\n", (*p)->note->key, (*p)->note->dur);
-            Alg_pending_ptr to_be_freed = *p;
+            Alg_note_list_ptr to_be_freed = *p;
             *p = to_be_freed->next;
             delete to_be_freed;
         } else {
@@ -308,7 +308,7 @@
 }
 
 
-void Alg_midifile_reader::binary_msg(int len, char *msg, 
+void Alg_midifile_reader::binary_msg(int len, unsigned char *msg, 
                                      const char *attr_string)
 {
     Alg_parameter parameter;
@@ -324,20 +324,20 @@
 }
 
 
-void Alg_midifile_reader::Mf_sysex(int len, char *msg)
+void Alg_midifile_reader::Mf_sysex(int len, unsigned char *msg)
 {
     // sysex messages become updates with attribute sysexs and a hex string
     binary_msg(len, msg, "sysexs");
 }
 
 
-void Alg_midifile_reader::Mf_arbitrary(int len, char *msg)
+void Alg_midifile_reader::Mf_arbitrary(int len, unsigned char *msg)
 {
     Mf_error("arbitrary data ignored");
 }
 
 
-void Alg_midifile_reader::Mf_metamisc(int type, int len, char *msg)
+void Alg_midifile_reader::Mf_metamisc(int type, int len, unsigned char *msg)
 {
     char text[128];
 #pragma warning(disable: 4996) // text is long enough
@@ -408,7 +408,7 @@
 }
 
 
-void Alg_midifile_reader::Mf_sqspecific(int len, char *msg)
+void Alg_midifile_reader::Mf_sqspecific(int len, unsigned char *msg)
 {
     // sequencer specific messages become updates with attribute sqspecifics
     // and a hex string for the value
@@ -416,7 +416,7 @@
 }
 
 
-char *heapify2(int len, char *s)
+char *heapify2(int len, unsigned char *s)
 {
     char *h = new char[len + 1];
     memcpy(h, s, len);
@@ -425,7 +425,7 @@
 }
 
 
-void Alg_midifile_reader::Mf_text(int type, int len, char *msg)
+void Alg_midifile_reader::Mf_text(int type, int len, unsigned char *msg)
 {
     Alg_parameter text;
     text.s = heapify2(len, msg);

Index: mfmidi.h
===================================================================
RCS file: /cvsroot/audacity/lib-src/portsmf/mfmidi.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- mfmidi.h    6 Aug 2008 17:57:54 -0000       1.2
+++ mfmidi.h    24 Jun 2009 20:37:27 -0000      1.3
@@ -55,16 +55,16 @@
     virtual void Mf_pitchbend(int,int,int) = 0;
     virtual void Mf_program(int,int) = 0;
     virtual void Mf_chanpressure(int,int) = 0;
-    virtual void Mf_sysex(int,char*) = 0;
-    virtual void Mf_arbitrary(int,char*) = 0;
-    virtual void Mf_metamisc(int,int,char*) = 0;
+    virtual void Mf_sysex(int,unsigned char*) = 0;
+    virtual void Mf_arbitrary(int,unsigned char*) = 0;
+    virtual void Mf_metamisc(int,int,unsigned char*) = 0;
     virtual void Mf_seqnum(int) = 0;
     virtual void Mf_smpte(int,int,int,int,int) = 0;
     virtual void Mf_timesig(int,int,int,int) = 0;
     virtual void Mf_tempo(int) = 0;
     virtual void Mf_keysig(int,int) = 0;
-    virtual void Mf_sqspecific(int,char*) = 0;
-    virtual void Mf_text(int,int,char*) = 0;
+    virtual void Mf_sqspecific(int,unsigned char*) = 0;
+    virtual void Mf_text(int,int,unsigned char*) = 0;
 
 private:
     long Mf_toberead;
@@ -73,7 +73,7 @@
     long read32bit();
     int read16bit();
     void msgenlarge();
-    char *msg();
+    unsigned char *msg();
     int readheader();
     void readtrack();
     void sysex();
@@ -90,7 +90,7 @@
     void msgadd(int);
     void chanmessage(int,int,int);
 
-    char *Msgbuff;
+    unsigned char *Msgbuff;
     long Msgsize;
     long Msgindex;
 };

Index: mfmidi.cpp
===================================================================
RCS file: /cvsroot/audacity/lib-src/portsmf/mfmidi.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- mfmidi.cpp  22 Jun 2009 08:48:07 -0000      1.3
+++ mfmidi.cpp  24 Jun 2009 20:37:27 -0000      1.4
@@ -193,7 +193,7 @@
             msginit();
 
             while ( Mf_toberead > lookfor ) {
-                char c = egetc();
+                unsigned char c = egetc();
                 if (midifile_error) return;
                 msgadd(c);
             }
@@ -266,7 +266,8 @@
 void Midifile_reader::metaevent(int type)
 {
     int leng = msgleng();
-    char *m = msg();
+    // made this unsigned to avoid sign extend
+    unsigned char *m = msg();
 
     switch ( type ) {
     case 0x00:
@@ -449,7 +450,7 @@
     Msgindex = 0;
 }
 
-char *Midifile_reader::msg()
+unsigned char *Midifile_reader::msg()
 {
     return(Msgbuff);
 }
@@ -469,21 +470,16 @@
 
 void Midifile_reader::msgenlarge()
 {
-    char *newmess;
-    char *oldmess = Msgbuff;
+    unsigned char *newmess;
+    unsigned char *oldmess = Msgbuff;
     int oldleng = Msgsize;
 
     Msgsize += MSGINCREMENT;
-    newmess = (char *) Mf_malloc((sizeof(char) * Msgsize) );
+    newmess = (unsigned char *) Mf_malloc((sizeof(unsigned char) * Msgsize) );
 
     /* copy old message into larger new one */
     if ( oldmess != 0 ) {
-        register char *p = newmess;
-        register char *q = oldmess;
-        register char *endq = &oldmess[oldleng];
-
-        for ( ; q!=endq ; p++,q++ )
-            *p = *q;
+        memcpy(newmess, oldmess, oldleng);
         Mf_free(oldmess, oldleng);
     }
     Msgbuff = newmess;

Index: allegrosmfwr.cpp
===================================================================
RCS file: /cvsroot/audacity/lib-src/portsmf/allegrosmfwr.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- allegrosmfwr.cpp    22 Jun 2009 08:48:07 -0000      1.3
+++ allegrosmfwr.cpp    24 Jun 2009 20:37:26 -0000      1.4
@@ -517,7 +517,7 @@
     write_varinum(divs - previous_divs);
     out_file->put('\xFF');
     out_file->put('\x58');  // time signature
-    out_file->put('\x04');  // length of message
+    out_file->put('\x04');     // length of message
     out_file->put(ROUND(ts[i].num));
     int den = ROUND(ts[i].den);
     int den_byte = 0;

Index: allegrord.cpp
===================================================================
RCS file: /cvsroot/audacity/lib-src/portsmf/allegrord.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- allegrord.cpp       22 Jun 2009 08:48:07 -0000      1.5
+++ allegrord.cpp       24 Jun 2009 20:37:26 -0000      1.6
@@ -262,7 +262,7 @@
                         parse_error(field, 0, "Dur specified twice");
                     } else {
                         // prepend 'U' to field, copy EOS too
-                        field.insert((unsigned int)0, 1, 'U');
+                        field.insert((unsigned int) 0, 1, 'U');
                         dur = parse_dur(field, time);
                         dur_flag = true;
                     }
@@ -271,7 +271,7 @@
                         parse_error(field, 0, "Pitch specified twice");
                     } else {
                         // prepend 'P' to field
-                        field.insert((unsigned int)0, 1, 'P');
+                        field.insert((unsigned int) 0, 1, 'P');
                         new_pitch = parse_pitch(field);
                         new_pitch_flag = true;
                     }
@@ -678,8 +678,6 @@
         // so total memory to allocate is (len - i) - 1
         char *r = new char[(len - i) - 1];
         strncpy(r, s.c_str() + i + 1, (len - i) - 2);
-//      Windows only
-//      strncpy_s(r, (len - i) - 2, s.c_str() + i + 1, _TRUNCATE);
         r[(len - i) - 2] = 0; // terminate the string
         param->s = r;
     } else if (s[i] == '\'') {


------------------------------------------------------------------------------
_______________________________________________
Audacity-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/audacity-cvs

Reply via email to