snippets / rock

All snippets tagged rock (1)

  1. rockvocals.php

    CLI PHP script that outputs files based on vocals part information in Rock Band MIDI files.

      1 #!php
    2 <?php
    3
    4 error_reporting(E_ALL);
    5 require('./classes/midi.class.php');
    6
    7
    8 function processFile($file, $options) {
    9 $midi = new Midi();
    10 $midi->importMid($file);
    11 $track = $midi->getTrack(0);
    12 // Find track name so we can rename output file
    13 foreach ($track as $msgStr){
    14 $msg = explode(' ',$msgStr);
    15 if ($msg[1]=='Meta'&&$msg[2]=='TrkName') {
    16 $newname = substr($msgStr,strpos($msgStr,'"')+1,-1);
    17 if ($options['verbose']) echo "$file -> $newname\n";
    18 }
    19 }
    20 if (!isset($newname)) {
    21 echo "No Track 0 Meta TrkName for $file - is it a Rock Band MIDI?\n"; exit(1);
    22 }
    23 $midi->soloTrack(4); // delete all non-vocal tracks, leaving track 1
    24 $midi->newTrack(); // add a track for percussion (returns wrong number, but I know it's track 2)
    25 $ch = 'ch=4'; // mostly channel 4 is used, overwrite with what we find later
    26 $lyrics = array(); $notes = array();
    27 $slides = array(); $slide = false;
    28 $notelist = $midi->getNoteList();
    29 foreach ($notelist as $k=>$v) {
    30 $notelist[$k] = substr($v,0,1); // remove octave number
    31 if (strlen($v)==3) $notelist[$k] .= '#'; // # looks a bit like a talky, but I don't like s for sharp
    32 }
    33 $mc = $midi->getMsgCount(1);
    34 for ($i=0; $i<$mc; $i++) {
    35 $msg = explode(' ',$midi->getMsg(1,$i));
    36 if ($msg[1]=='Meta') {
    37 if ($msg[2]=='Text' && substr($msg[3],1,1)=='[') {
    38 // Delete all Meta Text that starts with '[',
    39 // it breaks many MIDI parsers and we're not interested in it
    40 $midi->deleteMsg(1,$i);
    41 $i--;
    42 $mc--;
    43 } else if ($msg[2]=='Text' || $msg[2]=='Lyric') {
    44 $l = substr($msg[3],1,-1);
    45 $lyrics[] = $l;
    46 if ($l=='+') {
    47 $slide = count($lyrics)-1;
    48 }
    49 }
    50 } else if ($msg[1]=='On'){
    51 $ch = $msg[2];
    52 $n = substr($msg[3],2)+0;
    53 if ($n<36 || $n>95) { // not a musical note
    54 $midi->deleteMsg(1,$i);
    55 $i--;
    56 $mc--;
    57 if ($n==96) {
    58 $msg[2]='ch=10'; // MIDI percussion channel
    59 $msg[3]=$options['midi_percussion'];
    60 $midi->addMsg(2, implode(' ',$msg));
    61 } else if (($n==105 || $n==106) &&
    62 $msg[4]=='v=0' && (count($lyrics)==0 ||
    63 substr($lyrics[count($lyrics)-1],-1,1)!="\n")) {
    64 // Ignore Player 1/2 info, just start a new phrase here
    65 $lyrics[] = "\n";
    66 $notes[] = "\n";
    67 }
    68 } else if (substr($msg[4],2) > 0) { // musical note on
    69 $msg[4]=='v=127';
    70 $midi->tracks[1][$i] = implode(' ',$msg);
    71 $notes[] = $n;
    72 } else { // musical note off
    73 $lastofftime = $msg[0]+0;
    74 $lastoffnote = $n;
    75 }
    76 }
    77 if ($options['enable_slides'] && $slide && count($notes)-1 >= $slide) {
    78 $slides[] = array($lastofftime, $lastoffnote, $msg[0], $notes[$slide]);
    79 $slide = false;
    80 }
    81 }
    82
    83
    84 if ($options['enable_txt']) {
    85 $txtl =''; $txtn=''; $txt='';
    86 foreach ($lyrics as $k=>$l) {
    87 if ($l!="\n") {
    88 $mod = substr($l,-1,1);
    89 if ($mod=='#' || $mod=='^' || $mod=='*') {
    90 // Known talkie part.
    91 // Show modifier symbol in place of note instead of in lyric.
    92 $l = substr($l,0,-1);
    93 $n = $mod;
    94 if (substr($l,-1,1)!='-') {
    95 $l .= ' ';
    96 }
    97 } else {
    98 // Leave unknown symbols like = and % in lyric for now
    99 if ($mod != '-') {
    100 $l = $l.' ';
    101 }
    102 $n = $notelist[$notes[$k]];
    103 }
    104
    105 if (strlen($l) > strlen($n)+1) {
    106 $txtn .= str_pad($n,strlen($l),' ');
    107 $txtl .= $l;
    108 } else {
    109 $txtn .= $n.' ';
    110 $txtl .= str_pad($l,strlen($n)+1,' ');
    111 }
    112 } else {
    113 $txt .= $txtn."\r\n".$txtl."\r\n\r\n";
    114 $txtl =''; $txtn='';
    115 }
    116 }
    117 $write = fopen($newname.'.txt', 'w');
    118 fwrite($write, $txt);
    119 fclose($write);
    120 }
    121 if ($options['enable_midi'] || $options['enable_midixml']) {
    122 if ($options['enable_slides']) {
    123 foreach ($slides as $g) {
    124 $x0 = $g[0]; $y0 = $g[1];
    125 $x1 = $g[2]; $y1 = $g[3];
    126 if ($options['slide_type']=='glissando') {
    127 $dx = $x1-$x0;
    128 $dy = $y1-$y0;
    129 if ($dx>0) {
    130 $m = $dy/$dx;
    131 $b = $y0-$m*$x0;
    132 $lastnote = $y0;
    133 $midi->insertMsg(1, "$x0 On $ch n=$y0 v=127");
    134 while ($x0 != $x1) {
    135 $x0++;
    136 $y0 = round($m*$x0 + $b);
    137 if (($m>0 && $y0 > $lastnote) || ($m<0 && $y0 < $lastnote)) {
    138 $midi->insertMsg(1, ($x0-1+1)." On $ch n=$lastnote v=0");
    139 $midi->insertMsg(1, "$x0 On $ch n=$y0 v=127");
    140 $lastnote=$y0;
    141 }
    142 }
    143 $midi->insertMsg(1, "$x1 On $ch n=$lastnote v=0");
    144 }
    145 } else if ($options['slide_type']=='portamento') {
    146 $midi->insertMsg(1, "$x0 Par $ch c=65 v=127"); // portamento: on
    147 $t = $x1-$x0; // almost certainly wrong calculation since 0 is the "slowest rate"
    148 $midi->insertMsg(1, "$x0 Par $ch c=5 v=".(($t >> 7) & 0x7f)); // portamento time MSB
    149 $midi->insertMsg(1, "$x0 Par $ch c=37 v=".($t & 0x7f)); // portamento time LSB
    150 $midi->insertMsg(1, "$x0 On $ch n=$y0 v=127");
    151 $midi->insertMsg(1, "$x1 On $ch n=$y0 v=0");
    152 $midi->insertMsg(1, "$x0 On $ch n=$y1 v=127");
    153 $midi->insertMsg(1, "$x1 On $ch n=$y1 v=0");
    154 $midi->insertMsg(1, "$x0 Par $ch c=65 v=0"); // portamento: off
    155 } else if ($options['slide_type']=='pitchbend') {
    156 $midi->insertMsg(1, "$x0 On $ch n=$y0 v=127");
    157 $midi->insertMsg(1, "$x1 On $ch n=$y0 v=0");
    158 // TODO lots of carefully timed pitch bend instructions (these are very wrong)
    159 /* 0x2000 is center position
    160 * 0x0000 is two semitones down
    161 * 0x3fff is two semitones up
    162 */
    163 $t = $x1-$x0;
    164 for ($i=0; $i<$t; $i+=8) {
    165 $midi->insertMsg(1, $i+$x0." Pb $ch v=".round(0x2000+0x1fff*($i/$t)));
    166 }
    167 $midi->insertMsg(1, "$x1 Pb $ch v=2000");
    168 // TODO maybe combine with glissando? similar functionality needed for bigger intervals
    169 }
    170 }
    171 }
    172 $midi->insertMsg(1, "0 PrCh $ch ".$options['midi_instrument']);
    173 if ($options['enable_midi']) {
    174 $midi->saveMidFile($newname.'.mid');
    175 }
    176 if ($options['enable_midixml']) {
    177 $write = fopen($newname.'.xml', 'w');
    178 fwrite($write, $midi->getXml());
    179 fclose($write);
    180 }
    181 }
    182 }
    183
    184 function help($arg0) {
    185 echo "Usage: $arg0 [OPTION]... [--files] [FILE]...\n";
    186 ?>
    187 Output files based on vocals part information in Rock Band MIDI files. Files are
    188 created in the current directory and named based on information found in the
    189 input file (for example, wontgetfooled_short.mid).
    190
    191 MIDI OPTIONS
    192 --disable-midi don't output a standard MIDI file
    193 --enable-midi do output a standard MIDI file (default)
    194 --enable-midixml do output a MIDI XML file
    195 --disable-midixml don't output a MIDI XML file (default)
    196 --enable-slides add slides to the MIDI file where the game would have
    197 diagonal note tubes (default)
    198 --disable-slides don't add slides to the MIDI file where the game would
    199 have diagonal note tubes
    200 --slide-type=TYPE one of:
    201 glissando (play every note in between) (default)
    202 portamento (broken)
    203 pitchbend (broken)
    204 --midi-instrument=P MIDI instrument number between 1 and 128 for normal
    205 notes (default is 81 Lead 1 (square), try 19 Rock Organ)
    206 --midi_percussion=N MIDI percussion note between 0 and 127 for percussion
    207 section (default is 39 Hand Clap, try 54 Tambourine or
    208 56 Cowbell)
    209
    210 TEXT FILE OPTIONS
    211 --enable-txt output a text file (default)
    212 --disable-txt don't output a text file
    213
    214 OTHER OPTIONS
    215 --verbose do show some file info while processing (default)
    216 --quiet don't show some file info while processing
    217 --help show this help
    218 --files the remainder of the paramaters are input filenames
    219 (optional, not normally needed)
    220 <?php
    221 exit(0);
    222 }
    223
    224 function processArguments($argv) {
    225 //default options:
    226 $options['enable_midi'] = true;
    227 $options['enable_txt'] = true;
    228 $options['enable_midixml'] = false;
    229 $options['midi_instrument'] = 'p=80'; // 80=Lead 1 (square), 18=Rock Organ
    230 $options['midi_percussion'] = 'n=39'; // 39=hand clap, 54=tambourine, 56=cowbell)
    231 $options['enable_slides'] = true;
    232 $options['slide_type'] = 'glissando';
    233 $options['verbose'] = true;
    234
    235 $processingOptions = true;
    236 if (count($argv)==1) help($argv[0]);
    237 $args = array_slice($argv,1);
    238 foreach ($args as $arg) {
    239 if ($processingOptions) {
    240 if (substr($arg,0,1)=='-') {
    241 if ($arg=='--disable-midi') {
    242 $options['enable_midi'] = false;
    243 } else if ($arg=='--enable-midi') {
    244 $options['enable_midi'] = true;
    245 } else if ($arg=='--disable-txt') {
    246 $options['enable_txt'] = false;
    247 } else if ($arg=='--enable-txt') {
    248 $options['enable_txt'] = true;
    249 } else if ($arg=='--disable-midixml') {
    250 $options['enable_midixml'] = false;
    251 } else if ($arg=='--enable-midixml') {
    252 $options['enable_midixml'] = true;
    253 } else if ($arg=='--enable-slides') {
    254 $options['enable_slides'] = false;
    255 } else if ($arg=='--disable-slides') {
    256 $options['enable_slides'] = true;
    257 } else if ($arg=='--verbose') {
    258 $options['verbose'] = true;
    259 } else if ($arg=='--quiet') {
    260 $options['verbose'] = false;
    261 } else if (substr($arg,0,13)=='--slide-type=') {
    262 $options['slide_type'] = substr($arg,13);
    263 } else if (substr($arg,0,18)=='--midi-instrument=') {
    264 $p = substr($arg,18)-1;
    265 if ($p>=1 && $p<=128) {
    266 $options['midi_instrument'] = "p=$p";
    267 } else {
    268 echo "MIDI instrument should be between 1 and 128.\n"; exit(1);
    269 }
    270 } else if (substr($arg,0,18)=='--midi-percussion=') {
    271 $n = substr($arg,18);
    272 if ($n>=0 && $n<=127) {
    273 $options['percussion'] = "n=$n";
    274 } else {
    275 echo "MIDI percussion note should be between 0 and 127.\n"; exit(1);
    276 }
    277 } else if ($arg=='--help') {
    278 help($argv[0]);
    279 } else if ($arg=='--files') {
    280 $processingOptions = false;
    281 }
    282 } else {
    283 $processingOptions = false;
    284 processFile($arg, $options);
    285 }
    286 } else {
    287 processFile($arg, $options);
    288 }
    289 }
    290 }
    291
    292
    293
    294
    295
    296
    297
    298 // Main entry
    299
    300
    301 processArguments($argv);
    302 ?>
    Posted by GuestWednesday to php rock band ... saved by 1 person ... 0 comments ... 8 months
showing 10, 25, 50 items per pages

Pages : 1

Flux RSS friendsnippetLatest snippets


More...