microcanvas.js
// Parses string/binary score data into internal "tab" representation
Parses string/binary score data into internal "tab" representation
Parses string / binary score data into internal " tab " representation
function parse(score) {
      var pgm_read_byte;
      if (score instanceof Array) {
        pgm_read_byte = score;
      } else {
        pgm_read_byte = score.replace(/(\/\/[^\n]*\n|\/\*(.*?\*\/))/g, '').split(/,/).map(function(n) {
          return parseInt(n);
        });
      }
      var score_cursor, score_start, tune_playing;
      var playhead;
      var chn = [];
      var tab = [],
          tabch = [];
      score_cursor = score_start = playhead = 0;
      tune_playing = true;
      while (score_cursor < pgm_read_byte.length) {
        step();
      }
      return tab;
      function __play_note(channel, note) {
        tab.push(
          { op: "play-note", note: note, freq: ClouduboySynth.freq(note), ch: channel, score: [score_cursor-2, score_cursor-1], time: playhead }
        );
        tabch[ channel ] = tab[ tab.length-1 ];
      }
      function __stop_note(channel) {
        tab.push(
          { op: "stop-note", stops: tabch[channel], ch: channel, score: [score_cursor-1, score_cursor-1], time: playhead }
        );
        if (tabch[channel]) {
          tabch[channel].stop = tab[tab.length-1];
          tabch[channel] = null;
        }
      }
      function __wait(ms) {
        ms *= speed; 
        tab.push(
          { op: "wait", duration: ms, score: [score_cursor-2, score_cursor-1], time: playhead }
        );
        playhead += ms;
      }
      function step() {
        var command, opcode, chan;
        var duration;
        while (score_cursor < pgm_read_byte.length) {
          command = pgm_read_byte[score_cursor++];
          opcode = command & 0xf0;
          chan = command & 0x0f;
          if (opcode == TUNE_OP_STOPNOTE) { 
            __stop_note(chan);
          }
          else if (opcode == TUNE_OP_PLAYNOTE) { 
            __play_note(chan, pgm_read_byte[score_cursor++]);
          }
          else if (opcode == TUNE_OP_RESTART) { 
            score_cursor = score_start;
          }
          else if (opcode == TUNE_OP_STOP) { 
            tune_playing = false;
            break;
          }
          else if (opcode < 0x80) { 
            duration = (command << 8) | (pgm_read_byte[score_cursor++]);
            __wait(duration);
            break;
          }
        }
      } 
    } 
function parse ( score ) { var pgm_read_byte ; if ( score instanceof Array ) { pgm_read_byte = score ; } else { pgm_read_byte = score . replace ( / (\/\/[^\n]*\n|\/\*(.*?\*\/)) / g , '' ) . split ( / , / ) . map ( function ( n ) { return parseInt ( n ) ; } ) ; } var score_cursor , score_start , tune_playing ; var playhead ; var chn = [ ] ; var tab = [ ] , tabch = [ ] ; score_cursor = score_start = playhead = 0 ; tune_playing = true ; while ( score_cursor < pgm_read_byte . length ) { step ( ) ; } return tab ; function __play_note ( channel , note ) { tab . push ( { op : "play-note" , note : note , freq : ClouduboySynth . freq ( note ) , ch : channel , score : [ score_cursor - 2 , score_cursor - 1 ] , time : playhead } ) ; tabch [ channel ] = tab [ tab . length - 1 ] ; } function __stop_note ( channel ) { tab . push ( { op : "stop-note" , stops : tabch [ channel ] , ch : channel , score : [ score_cursor - 1 , score_cursor - 1 ] , time : playhead } ) ; if ( tabch [ channel ] ) { tabch [ channel ] . stop = tab [ tab . length - 1 ] ; tabch [ channel ] = null ; } } function __wait ( ms ) { ms *= speed ; tab . push ( { op : "wait" , duration : ms , score : [ score_cursor - 2 , score_cursor - 1 ] , time : playhead } ) ; playhead += ms ; } function step ( ) { var command , opcode , chan ; var duration ; while ( score_cursor < pgm_read_byte . length ) { command = pgm_read_byte [ score_cursor ++ ] ; opcode = command & 0xf0 ; chan = command & 0x0f ; if ( opcode == TUNE_OP_STOPNOTE ) { __stop_note ( chan ) ; } else if ( opcode == TUNE_OP_PLAYNOTE ) { __play_note ( chan , pgm_read_byte [ score_cursor ++ ] ) ; } else if ( opcode == TUNE_OP_RESTART ) { score_cursor = score_start ; } else if ( opcode == TUNE_OP_STOP ) { tune_playing = false ; break ; } else if ( opcode < 0x80 ) { duration = ( command << 8 ) | ( pgm_read_byte [ score_cursor ++ ] ) ; __wait ( duration ) ; break ; } } } }
Parses string/binary score data into internal "tab" representation
Parses string / binary score data into internal " tab " representation
// Binary score data // Already in binary format // Parse score into binary format //pgm_read_byte = util.cleanComments(score).split(/,/).map(function(n) { // TODO: create index for source data // Current score position // Current play context time // Concurrent channels (3) // Init & play // Play whole song // Done /* Functions used for parsing */ // latest note in channel // link stop-note to the start-note // speed up/slow down TODO: expose this // Advance playhead // Ported from: audio.cpp /* stop note */ /* play note */ /* restart score */ /* stop score */ /* wait count in msec. */ //wait_toggle_count = ((unsigned long) wait_timer_frequency2 * duration + 500) / 1000; //if (wait_toggle_count == 0) wait_toggle_count = 1; // step() // parse()