Location: PHPKode > projects > XRNS-PHP > xrns_randomizer.php
<?php

/*

Requires: PHP5 and Info-Zip (http://www.info-zip.org/)
Usage: `php xrns_randomizer.php /path/to/file1.xrns file2.xrns [mode] [keep_octave]`
Will output randomized file to current working directory

Public Domain, last modified September 23rd, 2007
Coded by Dac Chartrand of http://www.trotch.com/

Special thanks for collaborative efforts to:
Taktik / Bantai of http://www.renoise.com/
Beatslaughter of http://www.beatslaughter.de/

*/

// ----------------------------------------------------------------------------
// Variables
// ----------------------------------------------------------------------------

$valid_modes = array(
    'chaos',
    'shuffle',
    'harmonic_minor',
    'locrian',
    'lydian',
    'melodic_minor',
    'pentatonic_blues',
    'pentatonic_major',
    'pentatonic_minor',
    'pentatonic_neutral',
    );

$tmp_dir = '/tmp';

// ----------------------------------------------------------------------------
// Requires
// ----------------------------------------------------------------------------

require_once('xrns_functions.php');

// ----------------------------------------------------------------------------
// Functions
// ----------------------------------------------------------------------------

function randomize_note($mode = null, $note = null) {

    // Scales
    $notes = array();
    if ($mode == 'harmonic_minor') {
        // Harmonic Minor
        $notes  = array('C-', 'D-', 'D#', 'F-', 'G-', 'G#');
    }
    else if ($mode == 'locrian') {
        // Locrian
        $notes  = array('C-', 'C#', 'D#', 'F-', 'F#', 'G#', 'A#', 'C-');
    }
    else if ($mode == 'lydian') {
        // Lydian
        $notes  = array('C-', 'D-', 'E-', 'F#', 'G-', 'A-', 'B-');
    }
    else if ($mode == 'melodic_minor') {
        // Melodic Minor
        $notes  = array('C-', 'D-', 'D#', 'F-', 'G-', 'A-', 'B-');
    }
    else if ($mode == 'pentatonic_blues') {
        // Pentatonic Blues
        $notes  = array('C-', 'D#', 'F-', 'F#', 'G-');
    }
    else if ($mode == 'pentatonic_major') {
        // Pentatonic Major
        $notes  = array('C-', 'D-', 'F-', 'G-', 'A-');
    }
    else if ($mode == 'pentatonic_minor') {
        // Pentatonic Minor
        $notes  = array('C-', 'D#', 'F-', 'G-', 'A#');
    }
    else if ($mode == 'pentatonic_neutral') {
        // Pentatonic Neutral
        $notes  = array('C-', 'D-', 'F-', 'G-', 'A#');
    }
    else {
        // Chaos, all notes
        $notes  = array('C-', 'C#', 'D-', 'D#', 'E-', 'F-', 'F#', 'G-', 'G#', 'A-', 'A#', 'B-');
    }

    // Octaves
    $number = null;
    if ($note) $number = substr($note, -1, 1); // Preserve octave
    if (!ctype_digit($number)) $number = rand(0, 9); // Pick a random octave

    $key = array_rand($notes);
    $random = $notes[$key] . $number;

    return $random;

}

// ----------------------------------------------------------------------------
// Check Variables
// ----------------------------------------------------------------------------

// get filename component of path
$argv[0] = basename($argv[0]);

if (!is_dir($tmp_dir)) {
    $tmp_dir = get_temp_dir();
    if (!$tmp_dir) die("Error: Please set \$tmp_dir in $argv[0] to an existing directory.\n");
}

// ----------------------------------------------------------------------------
// Check User Input
// ----------------------------------------------------------------------------

function listMode($item, $key)
{
   echo "\n * " . $key . ": " . $item;
}

if ($argc < 3) {
    echo "\nError: $argv[0] expects at least 2 parameters.\n";
    echo "Usage: `php $argv[0] /path/to/file1.xrns file2.xrns [mode] [keep_octave=<yes|no>]`\n";
    echo "\nValid modes are: \n ";
    array_walk($valid_modes, 'listMode');
    echo "\n\nTo keep octave, the 4th parameter must be 'yes' or '1'.";
    echo "\n\n$argv[0] will output randomized file (file2.xrns) to current working directory.\n";
    die();
}

if (!file_exists($argv[1])) die("Error: The file $argv[1] was not found.\n");

if (!(preg_match('/(\.zip$|\.xrns$)/i', $argv[2]))) {
    die("Error: The filename $argv[2] is invalid, use .xrns (or .zip)\n");
}

// File names
$song1 = $argv[1];
$song2 = $argv[2];

// Mode
$mode = 'chaos'; // Default
if (isset($argv[3])) {
    if (is_numeric($argv[3]) && array_key_exists($argv[3],$valid_modes)) 
      $mode = $valid_modes[$argv[3]];
    elseif (in_array(strtolower($argv[3]), $valid_modes)) 
      $mode = strtolower($argv[3]);

}

// Keep Octave
$keep_octave = (isset($argv[4]) && $argv[4] == 1 || strtolower($argv[4]) == 'yes')  ? true : false;


// ----------------------------------------------------------------------------
// Unpack
// ----------------------------------------------------------------------------

echo "---------------------------------------\n";
echo "$argv[0] is working...\n";
echo date("D M j G:i:s T Y\n");
echo "---------------------------------------\n";
echo "Using temporary directory: $tmp_dir\n";

// Create a unique directory
$unzip1 = $tmp_dir . '/xrns_randomizer_' . md5(uniqid(mt_rand(), true)) . '_Track01/';

// Unzip song1
$result = UnzipAllFiles($song1, $unzip1);
if($result === FALSE) {
    echo "Error: There was a problem unzipping the first file.\n";
    die();
}

// Load XML
$sx1 = simplexml_load_file($unzip1 . 'Song.xml');

// ----------------------------------------------------------------------------
// Randomize The Notes
// ----------------------------------------------------------------------------

if ($mode == 'shuffle') {

    // Mode: shuffle
    // Scan the PatternTrack once and store all the notes in an $array.

    echo "Mode: shuffle \n";
    foreach ($sx1->PatternPool->Patterns->Pattern as $p) {
        foreach ($p->Tracks->PatternTrack as $x) {
            $array = array() ;
            if ($x->Lines->Line) {
                foreach ($x->Lines->Line as $y) {
                    if ($y->NoteColumns->NoteColumn) {
                        foreach ($y->NoteColumns->NoteColumn as $z) {
                            if ($z->Note && $z->Note != 'OFF') {
                                $array[] = $z->Note;
                            }
                        }
                    }
                }

                // Randomize the $array
                shuffle($array);

                // Scan the PatternTrack again and pop the values from $array into the notes.
                foreach ($x->Lines->Line as $y) {
                    if ($y->NoteColumns->NoteColumn) {
                        foreach ($y->NoteColumns->NoteColumn as $z) {
                            if ($z->Note && $z->Note != 'OFF') {
                                $z->Note = '' . array_pop($array);
                            }
                        }
                    }
                }
            }
        }
    }

}
else {


    echo "Mode: $mode";
    if ($keep_octave) echo ", will preserve octave";
    echo "\n";
    foreach ($sx1->PatternPool->Patterns->Pattern as $p) {
        foreach ($p->Tracks->PatternTrack as $x) {
            if ($x->Lines->Line) {
                foreach ($x->Lines->Line as $y) {
                    if ($y->NoteColumns->NoteColumn) {
                        foreach ($y->NoteColumns->NoteColumn as $z) {
                            if ($z->Note && $z->Note != 'OFF') {

                                if ($keep_octave) $z->Note = randomize_note($mode, $z->Note);
                                else $z->Note = randomize_note($mode);

                            }
                        }
                    }
                }
            }
        }
    }


}

// ----------------------------------------------------------------------------
// Validate
// ----------------------------------------------------------------------------

if (!xrns_xsd_check($sx1, (int)$sx1['doc_version'])) {

    echo "Error: XML is invalid!\n";
    obliterate_directory($unzip1);
    die();

}

// ----------------------------------------------------------------------------
// Replace Song.xml
// ----------------------------------------------------------------------------

unlink($unzip1 . 'Song.xml') or die("Error: There was a problem deleting a file.\n");
file_put_contents($unzip1 . 'Song.xml', $sx1->asXML());

// Zip song
$result = ZipAllFiles($song2, $unzip1);
if($result === FALSE) {
    echo "Error: There was a problem zipping the final file.\n";
    die();
}

// ----------------------------------------------------------------------------
// Remove temp directories
// ----------------------------------------------------------------------------

obliterate_directory($unzip1);

echo "---------------------------------------\n";
echo "$argv[0] is done!\n";
echo date("D M j G:i:s T Y\n");
echo "---------------------------------------\n";

?>
Return current item: XRNS-PHP