somewhat better solution to prev commit.
authorRobin Gareus <robin@gareus.org>
Sun, 27 Dec 2015 02:40:48 +0000 (03:40 +0100)
committerRobin Gareus <robin@gareus.org>
Sun, 27 Dec 2015 02:40:48 +0000 (03:40 +0100)
parse up to 32bit VLQs, match smf_format_vlq()

libs/evoral/src/Event.cpp
libs/evoral/src/libsmf/smf_load.c

index 3c1cc000bd964572801ecf8ccb39fadc4a3b51cd..64caba39523cbfc40f35bbe0e88e2a6b0cb155a2 100644 (file)
@@ -38,23 +38,16 @@ init_event_id_counter(event_id_t n)
 event_id_t
 next_event_id ()
 {
-       /* libsmf supports reading variable-length data up to 4 bytes only.
-        * so we wrap around at 2^(4 * 7) - 1
-        *
-        * interestingly enough libsmf happily writes data longer than that, but then
-        * fails to load it in ./libs/evoral/src/libsmf/smf_load.c:237
-        * g_critical("SMF error: Variable Length Quantities longer than four bytes are not supported yet.");
+       /* TODO: handle 31bit overflow , event_id_t is an int32_t,
+        * and libsmf only supports loading uint32_t vlq's, see smf_extract_vlq()
         *
         * event-IDs only have to be unique per .mid file.
         * Previously (Ardour 4.2ish) Ardour re-generated those IDs when loading the
         * file but that lead to .mid files being modified on every load/save.
         *
-        * For now just assume that by the time 2^28 is reached, files with low ids have vanished.
-        * There is only one user who managed to get to 268 million events so far.
-        * quite a feat: id-counter="6483089" event-counter="276390506"
-        * Eventually a proper solution will have to be implemented.
+        * current user-record: is event-counter="276390506" (just abov 2^28)
         */
-       return g_atomic_int_add (&_event_id_counter, 1) & 268435455;
+       return g_atomic_int_add (&_event_id_counter, 1);
 }
 
 #ifdef EVORAL_EVENT_ALLOC
index a23a88fa49e6282461c582ce6f4231bda649e88b..001774cd1430c861a59fc82ef35237128db30a8e 100644 (file)
@@ -214,13 +214,19 @@ smf_extract_vlq(const unsigned char *buf, const size_t buffer_length, uint32_t *
 {
        uint32_t val = 0;
        const unsigned char *c = buf;
+       int i = 0;
 
-       for (;;) {
+       for (;; ++i) {
                if (c >= buf + buffer_length) {
                        g_critical("End of buffer in extract_vlq().");
                        return (-1);
                }
 
+               if (i == 4 && (val & 0xfe000000)) {
+                       g_critical("SMF error: Variable Length Quantities longer than four bytes are not supported yet.");
+                       return (-2);
+               }
+
                val = (val << 7) + (*c & 0x7F);
 
                if (*c & 0x80)
@@ -233,7 +239,7 @@ smf_extract_vlq(const unsigned char *buf, const size_t buffer_length, uint32_t *
        *value = val;
        *len = c - buf + 1;
 
-       if (*len > 4) {
+       if (*len > 5) {
                g_critical("SMF error: Variable Length Quantities longer than four bytes are not supported yet.");
                return (-2);
        }