"Fossies" - the Fresh Open Source Software Archive

Member "audacious-plugins-3.10.1/src/amidiplug/i_midi.cc" (26 Dec 2018, 22033 Bytes) of package /linux/misc/audacious-plugins-3.10.1.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "i_midi.cc" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 3.9_vs_3.10.

    1 /*
    2 *
    3 * Author: Giacomo Lozito <james@develia.org>, (C) 2005-2006
    4 *
    5 * MIDI (SMF) parser based on aplaymidi.c from ALSA-utils
    6 * aplaymidi.c is Copyright (c) 2004 Clemens Ladisch <clemens@ladisch.de>
    7 *
    8 * This program is free software; you can redistribute it and/or modify it
    9 * under the terms of the GNU General Public License as published by the
   10 * Free Software Foundation; either version 2 of the License, or (at your
   11 * option) any later version.
   12 *
   13 * This program is distributed in the hope that it will be useful, but
   14 * WITHOUT ANY WARRANTY; without even the implied warranty of
   15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   16 * General Public License for more details.
   17 *
   18 * You should have received a copy of the GNU General Public License along
   19 * with this program; if not, write to the Free Software Foundation, Inc.,
   20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
   21 *
   22 */
   23 
   24 #include "i_midi.h"
   25 
   26 #include <stdlib.h>
   27 #include <string.h>
   28 
   29 #include <libaudcore/audstrings.h>
   30 #include <libaudcore/runtime.h>
   31 #include <libaudcore/vfs.h>
   32 
   33 #include "i_configure.h"
   34 
   35 #define MAKE_ID(c1, c2, c3, c4) ((c1) | ((c2) << 8) | ((c3) << 16) | ((c4) << 24))
   36 
   37 #define WARNANDBREAK(...) { AUDERR (__VA_ARGS__); break; }
   38 
   39 #define ERRMSG_MIDITRACK() { AUDERR ("%s: invalid MIDI data (offset %#x)", \
   40     (const char *) file_name, file_offset); return false; }
   41 
   42 
   43 /* skip a certain number of bytes */
   44 void midifile_t::skip_bytes (int bytes)
   45 {
   46     while (bytes > 0)
   47     {
   48         read_byte ();
   49         --bytes;
   50     }
   51 }
   52 
   53 
   54 /* reads a single byte */
   55 int midifile_t::read_byte ()
   56 {
   57     if (file_offset >= file_data.len ())
   58     {
   59         file_eof = true;
   60         return -1;
   61     }
   62 
   63     return (unsigned char) file_data[file_offset ++];
   64 }
   65 
   66 
   67 /* reads a little-endian 32-bit integer */
   68 int midifile_t::read_32_le ()
   69 {
   70     int value;
   71     value = read_byte ();
   72     value |= read_byte () << 8;
   73     value |= read_byte () << 16;
   74     value |= read_byte () << 24;
   75     return !file_eof ? value : -1;
   76 }
   77 
   78 
   79 /* reads a 4-character identifier */
   80 int midifile_t::read_id ()
   81 {
   82     return read_32_le ();
   83 }
   84 
   85 
   86 /* reads a fixed-size big-endian number */
   87 int midifile_t::read_int (int bytes)
   88 {
   89     int c, value = 0;
   90 
   91     do
   92     {
   93         c = read_byte ();
   94 
   95         if (c < 0) return -1;
   96 
   97         value = (value << 8) | c;
   98     }
   99     while (--bytes);
  100 
  101     return value;
  102 }
  103 
  104 
  105 /* reads a variable-length number */
  106 int midifile_t::read_var ()
  107 {
  108     int value, c;
  109 
  110     c = read_byte ();
  111     value = c & 0x7f;
  112 
  113     if (c & 0x80)
  114     {
  115         c = read_byte ();
  116         value = (value << 7) | (c & 0x7f);
  117 
  118         if (c & 0x80)
  119         {
  120             c = read_byte ();
  121             value = (value << 7) | (c & 0x7f);
  122 
  123             if (c & 0x80)
  124             {
  125                 c = read_byte ();
  126                 value = (value << 7) | c;
  127 
  128                 if (c & 0x80)
  129                     return -1;
  130             }
  131         }
  132     }
  133 
  134     return value;
  135 }
  136 
  137 
  138 /* reads one complete track from the file */
  139 bool midifile_t::read_track (midifile_track_t & track, int track_end, int port_count)
  140 {
  141     int tick = 0;
  142     unsigned char last_cmd = 0;
  143     unsigned char port = 0;
  144 
  145     track.start_tick = -1;
  146     track.end_tick = -1;
  147 
  148     /* the current file position is after the track ID and length */
  149     while (file_offset < track_end)
  150     {
  151         unsigned char cmd;
  152         midievent_t * event;
  153         int delta_ticks, len, c;
  154 
  155         delta_ticks = read_var ();
  156 
  157         if (delta_ticks < 0)
  158             break;
  159 
  160         tick += delta_ticks;
  161 
  162         c = read_byte ();
  163 
  164         if (c < 0)
  165             break;
  166 
  167         if (c & 0x80)
  168         {
  169             /* have command */
  170             cmd = c;
  171 
  172             if (cmd < 0xf0)
  173                 last_cmd = cmd;
  174         }
  175         else
  176         {
  177             /* running status */
  178             file_offset--;
  179             cmd = last_cmd;
  180 
  181             if (!cmd)
  182                 ERRMSG_MIDITRACK();
  183         }
  184 
  185         switch (cmd >> 4)
  186         {
  187             /* maps SMF events to ALSA sequencer events */
  188             static unsigned char cmd_type[16] =
  189             {
  190                 0, 0, 0, 0, 0, 0, 0, 0,
  191                 SND_SEQ_EVENT_NOTEOFF,     // 08h
  192                 SND_SEQ_EVENT_NOTEON,      // 09h
  193                 SND_SEQ_EVENT_KEYPRESS,    // 0ah
  194                 SND_SEQ_EVENT_CONTROLLER,  // 0bh
  195                 SND_SEQ_EVENT_PGMCHANGE,   // 0ch
  196                 SND_SEQ_EVENT_CHANPRESS,   // 0dh
  197                 SND_SEQ_EVENT_PITCHBEND    // 0eh
  198             };
  199 
  200         case 0x8: /* channel msg with 2 parameter bytes */
  201         case 0x9:
  202         case 0xa:
  203         {
  204             event = track.add_event ();
  205             event->type = cmd_type[cmd >> 4];
  206             event->port = port;
  207             event->tick = tick;
  208             event->d[0] = cmd & 0x0f;
  209 
  210             /* if this note is not in standard drum channel (10), apply transpose */
  211             if (event->d[0] != 9)
  212             {
  213                 int transpose = aud_get_int ("amidiplug", "ap_opts_transpose_value");
  214                 int data_tr = (read_byte () & 0x7f) + transpose;
  215 
  216                 if (data_tr > 127) data_tr = 127;
  217                 else if (data_tr < 0) data_tr = 0;
  218 
  219                 event->d[1] = (unsigned char) data_tr;
  220             }
  221             else /* this note is in standard drum channel (10), apply drum shift */
  222             {
  223                 int drumshift = aud_get_int ("amidiplug", "ap_opts_drumshift_value");
  224                 int data_ds = (read_byte () & 0x7f) + drumshift; /* always > 0 */
  225 
  226                 if (data_ds > 127) data_ds -= 127;
  227 
  228                 event->d[1] = (unsigned char) data_ds;
  229             }
  230 
  231             event->d[2] = read_byte () & 0x7f;
  232 
  233             if (event->type == SND_SEQ_EVENT_NOTEON && track.start_tick < 0)
  234                 track.start_tick = tick;
  235             if (track.start_tick >= 0 && tick >= track.start_tick)
  236                 track.end_tick = tick;
  237         }
  238         break;
  239 
  240         case 0xb: /* channel msg with 2 parameter bytes */
  241         case 0xe:
  242         {
  243             event = track.add_event ();
  244             event->type = cmd_type[cmd >> 4];
  245             event->port = port;
  246             event->tick = tick;
  247             event->d[0] = cmd & 0x0f;
  248             event->d[1] = read_byte () & 0x7f;
  249             event->d[2] = read_byte () & 0x7f;
  250 
  251             if (track.start_tick >= 0 && tick >= track.start_tick)
  252                 track.end_tick = tick;
  253         }
  254         break;
  255 
  256         case 0xc: /* channel msg with 1 parameter byte */
  257         case 0xd:
  258         {
  259             event = track.add_event ();
  260             event->type = cmd_type[cmd >> 4];
  261             event->port = port;
  262             event->tick = tick;
  263             event->d[0] = cmd & 0x0f;
  264             event->d[1] = read_byte () & 0x7f;
  265 
  266             if (track.start_tick >= 0 && tick >= track.start_tick)
  267                 track.end_tick = tick;
  268         }
  269         break;
  270 
  271         case 0xf:
  272         {
  273             switch (cmd)
  274             {
  275             case 0xf0: /* sysex */
  276             case 0xf7: /* continued sysex, or escaped commands */
  277             {
  278                 len = read_var ();
  279 
  280                 if (len < 0)
  281                     ERRMSG_MIDITRACK();
  282 
  283                 /* skip sysex */
  284                 skip_bytes (len);
  285             }
  286             break;
  287 
  288             case 0xff: /* meta event */
  289             {
  290                 c = read_byte ();
  291                 len = read_var ();
  292 
  293                 if (len < 0)
  294                     ERRMSG_MIDITRACK();
  295 
  296                 switch (c)
  297                 {
  298                 case 0x21: /* port number */
  299                 {
  300                     if (len < 1)
  301                         ERRMSG_MIDITRACK();
  302 
  303                     port = read_byte () % port_count;
  304                     skip_bytes (len - 1);
  305                 }
  306                 break;
  307 
  308                 case 0x2f: /* end of track */
  309                 {
  310                     if (! aud_get_bool ("amidiplug", "skip_leading"))
  311                         track.start_tick = 0;
  312                     if (! aud_get_bool ("amidiplug", "skip_trailing"))
  313                         track.end_tick = tick;
  314 
  315                     skip_bytes (track_end - file_offset);
  316                     return true;
  317                 }
  318 
  319                 case 0x51: /* tempo */
  320                 {
  321                     if (len < 3)
  322                         ERRMSG_MIDITRACK();
  323 
  324                     if (smpte_timing)
  325                     {
  326                         /* SMPTE timing doesn't change */
  327                         skip_bytes (len);
  328                     }
  329                     else
  330                     {
  331                         event = track.add_event ();
  332                         event->type = SND_SEQ_EVENT_TEMPO;
  333                         event->port = port;
  334                         event->tick = tick;
  335                         event->tempo = read_byte () << 16;
  336                         event->tempo |= read_byte () << 8;
  337                         event->tempo |= read_byte ();
  338                         skip_bytes (len - 3);
  339                     }
  340                 }
  341                 break;
  342 
  343                 case 0x01: /* text comments */
  344                 {
  345                     if (len < 0)
  346                         ERRMSG_MIDITRACK();
  347 
  348                     event = track.add_event ();
  349                     event->type = SND_SEQ_EVENT_META_TEXT;
  350                     event->tick = tick;
  351 
  352                     StringBuf buf (len);
  353                     for (int i = 0; i < len; i ++)
  354                         buf[i] = read_byte ();
  355 
  356                     event->metat = String (str_to_utf8 (std::move (buf)));
  357                 }
  358                 break;
  359 
  360                 case 0x05: /* lyrics */
  361                 {
  362                     if (len < 0)
  363                         ERRMSG_MIDITRACK();
  364 
  365                     event = track.add_event ();
  366                     event->type = SND_SEQ_EVENT_META_LYRIC;
  367                     event->tick = tick;
  368 
  369                     StringBuf buf (len);
  370                     for (int i = 0; i < len; i ++)
  371                         buf[i] = read_byte ();
  372 
  373                     event->metat = String (str_to_utf8 (std::move (buf)));
  374                 }
  375                 break;
  376 
  377                 default: /* ignore all other meta events */
  378                 {
  379                     skip_bytes (len);
  380                 }
  381                 break;
  382                 }
  383             }
  384             break;
  385 
  386             default: /* invalid Fx command */
  387                 ERRMSG_MIDITRACK();
  388             }
  389         }
  390         break;
  391 
  392         default: /* cannot happen */
  393             ERRMSG_MIDITRACK();
  394         }
  395     }
  396 
  397     ERRMSG_MIDITRACK();
  398 }
  399 
  400 
  401 /* read a MIDI file in Standard MIDI Format */
  402 /* return values: 0 = error, 1 = ok */
  403 bool midifile_t::parse_smf (int port_count)
  404 {
  405     int header_len;
  406 
  407     /* the curren position is immediately after the "MThd" id */
  408     header_len = read_int (4);
  409 
  410     if (header_len < 6)
  411     {
  412         AUDERR ("%s: invalid file format\n", (const char *) file_name);
  413         return false;
  414     }
  415 
  416     format = read_int (2);
  417 
  418     if (format != 0 && format != 1)
  419     {
  420         AUDERR ("%s: type %d format is not supported\n", (const char *) file_name, format);
  421         return false;
  422     }
  423 
  424     int num_tracks = read_int (2);
  425 
  426     if (num_tracks < 1 || num_tracks > 1000)
  427     {
  428         AUDERR ("%s: invalid number of tracks (%d)\n", (const char *) file_name, num_tracks);
  429         return false;
  430     }
  431 
  432     tracks.insert (0, num_tracks);
  433 
  434     time_division = read_int (2);
  435 
  436     if (time_division < 0)
  437     {
  438         AUDERR ("%s: invalid file format\n", (const char *) file_name);
  439         return false;
  440     }
  441 
  442     smpte_timing = !! (time_division & 0x8000);
  443 
  444     /* read tracks */
  445     for (midifile_track_t & track : tracks)
  446     {
  447         int len;
  448 
  449         /* search for MTrk chunk */
  450         for (;;)
  451         {
  452             int id = read_id ();
  453             len = read_int (4);
  454 
  455             if (file_eof)
  456             {
  457                 AUDERR ("%s: unexpected end of file\n", (const char *) file_name);
  458                 return false;
  459             }
  460 
  461             if (len < 0 || len >= 0x10000000)
  462             {
  463                 AUDERR ("%s: invalid chunk length %d\n", (const char *) file_name, len);
  464                 return false;
  465             }
  466 
  467             if (id == MAKE_ID ('M', 'T', 'r', 'k'))
  468                 break;
  469 
  470             skip_bytes (len);
  471         }
  472 
  473         if (! read_track (track, file_offset + len, port_count))
  474             return false;
  475     }
  476 
  477     /* calculate the max_tick for the entire file */
  478     start_tick = -1;
  479     max_tick = 0;
  480 
  481     for (midifile_track_t & track : tracks)
  482     {
  483         if (track.start_tick >= 0 && (start_tick < 0 || track.start_tick < start_tick))
  484             start_tick = track.start_tick;
  485         if (track.end_tick > max_tick)
  486             max_tick = track.end_tick;
  487     }
  488 
  489     if (start_tick < 0)
  490         start_tick = 0;
  491 
  492     /* ok, success */
  493     return true;
  494 }
  495 
  496 
  497 /* read a MIDI file enclosed in RIFF format */
  498 /* return values: 0 = error, 1 = ok */
  499 bool midifile_t::parse_riff ()
  500 {
  501     /* skip file length (4 bytes) */
  502     skip_bytes (4);
  503 
  504     /* check file type ("RMID" = RIFF MIDI) */
  505     if (read_id () != MAKE_ID ('R', 'M', 'I', 'D'))
  506         return false;
  507 
  508     /* search for "data" chunk */
  509     for (;;)
  510     {
  511         int id = read_id ();
  512         int len = read_32_le ();
  513 
  514         if (file_eof)
  515             return false;
  516 
  517         if (id == MAKE_ID ('d', 'a', 't', 'a'))
  518             break;
  519 
  520         if (len < 0)
  521             return false;
  522 
  523         skip_bytes ((len + 1) & ~1);
  524     }
  525 
  526     /* the "data" chunk must contain data in SMF format */
  527     if (read_id () != MAKE_ID ('M', 'T', 'h', 'd'))
  528         return false;
  529 
  530     /* ok, success */
  531     return true;
  532 }
  533 
  534 
  535 /* queue set tempo */
  536 bool midifile_t::setget_tempo ()
  537 {
  538     /* interpret and set tempo */
  539     bool smpte_timing = !! (time_division & 0x8000);
  540 
  541     if (!smpte_timing)
  542     {
  543         /* time_division is ticks per quarter */
  544         current_tempo = 500000;
  545         ppq = time_division;
  546     }
  547     else
  548     {
  549         /* upper byte is negative frames per second */
  550         int fps = 0x80 - ((time_division >> 8) & 0x7f);
  551         /* lower byte is ticks per frame */
  552         int tpf = time_division & 0xff;
  553 
  554         /* now pretend that we have quarter-note based timing */
  555         switch (fps)
  556         {
  557         case 24:
  558             current_tempo = 500000;
  559             ppq = 12 * tpf;
  560             break;
  561 
  562         case 25:
  563             current_tempo = 400000;
  564             ppq = 10 * tpf;
  565             break;
  566 
  567         case 29: /* 30 drop-frame */
  568             current_tempo = 100000000;
  569             ppq = 2997 * tpf;
  570             break;
  571 
  572         case 30:
  573             current_tempo = 500000;
  574             ppq = 15 * tpf;
  575             break;
  576 
  577         default:
  578             AUDERR ("Invalid number of SMPTE frames per second (%d)\n", fps);
  579             return false;
  580         }
  581     }
  582 
  583     AUDDBG ("MIDI tempo set -> time division: %i\n", time_division);
  584     AUDDBG ("MIDI tempo set -> tempo: %i\n", current_tempo);
  585     AUDDBG ("MIDI tempo set -> ppq: %i\n", ppq);
  586     return true;
  587 }
  588 
  589 
  590 /* this will set the midi length in microseconds
  591    COMMENT: this will also reset current position in each track! */
  592 void midifile_t::setget_length ()
  593 {
  594     int64_t length_microsec = 0;
  595     int last_tick = start_tick;
  596     /* get the first microsec_per_tick ratio */
  597     int microsec_per_tick = (int) (current_tempo / ppq);
  598 
  599     /* initialize current position in each track */
  600     for (midifile_track_t & track : tracks)
  601         track.current_event = track.events.head ();
  602 
  603     /* search for tempo events in each track; in fact, since the program
  604        currently supports type 0 and type 1 MIDI files, we should find
  605        tempo events only in one track */
  606     AUDDBG ("LENGTH calc: starting calc loop\n");
  607 
  608     for (;;)
  609     {
  610         midievent_t * event = nullptr;
  611         midifile_track_t * event_track = nullptr;
  612         int min_tick = max_tick + 1;
  613 
  614         /* search next event */
  615         for (midifile_track_t & track : tracks)
  616         {
  617             midievent_t * e2 = track.current_event;
  618 
  619             if (e2 && e2->tick < min_tick)
  620             {
  621                 min_tick = e2->tick;
  622                 event = e2;
  623                 event_track = & track;
  624             }
  625         }
  626 
  627         if (!event)
  628         {
  629             /* calculate the remaining length */
  630             length_microsec += (microsec_per_tick * (max_tick - last_tick));
  631             break; /* end of song reached */
  632         }
  633 
  634         /* advance pointer to next event */
  635         event_track->current_event = event_track->events.next (event);
  636 
  637         /* check if this is a tempo event */
  638         if (event->type == SND_SEQ_EVENT_TEMPO)
  639         {
  640             int tick = aud::max (event->tick, start_tick);
  641             AUDDBG ("LENGTH calc: tempo event (%i) on tick %i\n", event->tempo, tick);
  642 
  643             /* increment length_microsec with the amount of microsec before tempo change */
  644             length_microsec += (microsec_per_tick * (tick - last_tick));
  645             /* now update last_tick and the microsec_per_tick ratio */
  646             last_tick = tick;
  647             microsec_per_tick = (int) (event->tempo / ppq);
  648         }
  649     }
  650 
  651     /* IMPORTANT
  652        this couple of important values is set by midifile_t::set_length */
  653     length = length_microsec;
  654 
  655     if (max_tick > start_tick)
  656         avg_microsec_per_tick = (int) (length_microsec / (max_tick - start_tick));
  657     else
  658         avg_microsec_per_tick = 0;
  659 
  660     return;
  661 }
  662 
  663 
  664 /* this will get the weighted average bpm of the midi file;
  665    if the file has a variable bpm, 'bpm' is set to -1;
  666    COMMENT: this will also reset current position in each track! */
  667 void midifile_t::get_bpm (int * bpm, int * wavg_bpm)
  668 {
  669     int last_tick = start_tick;
  670     unsigned weighted_avg_tempo = 0;
  671     bool is_monotempo = true;
  672     int last_tempo = current_tempo;
  673 
  674     /* initialize current position in each track */
  675     for (midifile_track_t & track : tracks)
  676         track.current_event = track.events.head ();
  677 
  678     /* search for tempo events in each track; in fact, since the program
  679        currently supports type 0 and type 1 MIDI files, we should find
  680        tempo events only in one track */
  681     AUDDBG ("BPM calc: starting calc loop\n");
  682 
  683     for (;;)
  684     {
  685         midievent_t * event = nullptr;
  686         midifile_track_t * event_track = nullptr;
  687         int min_tick = max_tick + 1;
  688 
  689         /* search next event */
  690         for (midifile_track_t & track : tracks)
  691         {
  692             midievent_t * e2 = track.current_event;
  693 
  694             if (e2 && e2->tick < min_tick)
  695             {
  696                 min_tick = e2->tick;
  697                 event = e2;
  698                 event_track = & track;
  699             }
  700         }
  701 
  702         if (!event)
  703         {
  704             /* calculate the remaining length */
  705             if (max_tick > start_tick)
  706                 weighted_avg_tempo += (unsigned) (last_tempo *
  707                  ((float) (max_tick - last_tick) / (float) (max_tick - start_tick)));
  708 
  709             break; /* end of song reached */
  710         }
  711 
  712         /* advance pointer to next event */
  713         event_track->current_event = event_track->events.next (event);
  714 
  715         /* check if this is a tempo event */
  716         if (event->type == SND_SEQ_EVENT_TEMPO)
  717         {
  718             int tick = aud::max (event->tick, start_tick);
  719             AUDDBG ("BPM calc: tempo event (%i) on tick %i\n", event->tempo, tick);
  720 
  721             /* check if this is a tempo change (real change, tempo should be
  722                different) in the midi file (and it shouldn't be at tick 0); */
  723             if (is_monotempo && tick > start_tick && event->tempo != last_tempo)
  724                 is_monotempo = false;
  725 
  726             /* add the previous tempo change multiplied for its weight (the tick interval for the tempo )  */
  727             if (max_tick > start_tick)
  728                 weighted_avg_tempo += (unsigned) (last_tempo *
  729                  ((float) (tick - last_tick) / (float) (max_tick - start_tick)));
  730 
  731             /* now update last_tick and the microsec_per_tick ratio */
  732             last_tick = tick;
  733             last_tempo = event->tempo;
  734         }
  735     }
  736 
  737     AUDDBG ("BPM calc: weighted average tempo: %i\n", weighted_avg_tempo);
  738 
  739     if (weighted_avg_tempo > 0)
  740         *wavg_bpm = (int) (60000000 / weighted_avg_tempo);
  741     else
  742         *wavg_bpm = 0;
  743 
  744     AUDDBG ("BPM calc: weighted average bpm: %i\n", *wavg_bpm);
  745 
  746     if (is_monotempo)
  747         *bpm = *wavg_bpm; /* the song has fixed bpm */
  748     else
  749         *bpm = -1; /* the song has variable bpm */
  750 }
  751 
  752 
  753 /* helper function that parses a midi file; returns 1 on success, 0 otherwise */
  754 bool midifile_t::parse_from_file (const char * filename, VFSFile & file)
  755 {
  756     bool success = false;
  757 
  758     file_name = String (filename);
  759     file_data = file.read_all ();
  760 
  761     switch (read_id ())
  762     {
  763     case MAKE_ID ('R', 'I', 'F', 'F') :
  764         AUDDBG ("PARSE_FROM_FILENAME requested, RIFF chunk found, processing...\n");
  765 
  766         /* read riff chunk */
  767         if (!parse_riff ())
  768             WARNANDBREAK ("%s: invalid file format (riff parser)\n", filename);
  769 
  770         /* if that was read correctly, go ahead and read smf data */
  771 
  772     case MAKE_ID ('M', 'T', 'h', 'd') :
  773         AUDDBG ("PARSE_FROM_FILENAME requested, MThd chunk found, processing...\n");
  774 
  775         /* we don't care about port count here, pass 1 */
  776         if (!parse_smf (1))
  777             WARNANDBREAK ("%s: invalid file format (smf parser)\n", filename);
  778 
  779         if (time_division < 1)
  780             WARNANDBREAK ("%s: invalid time division (%i)\n", filename, time_division);
  781 
  782         /* fill ppq and tempo using time_division */
  783         if (!setget_tempo ())
  784             WARNANDBREAK ("%s: invalid values while setting ppq and tempo\n", filename);
  785 
  786         /* fill length, keeping in count tempo-changes */
  787         setget_length ();
  788 
  789         /* ok, mf has been filled with information; successfully return */
  790         success = true;
  791         break;
  792 
  793     default:
  794         AUDERR ("%s is not a Standard MIDI File\n", filename);
  795         break;
  796     }
  797 
  798     file_name = String ();
  799     file_data.clear ();
  800 
  801     return success;
  802 }