My sound slicer

(This article should be very confusing for you to read, sorry, but I can’t explain this tool I made very well)

When I was very new to BMS making I use Audacity to slice the sounds manually. It’s very tiresome!

So I made a tool to slice the wav files into parts. Written in PHP:

The Code: http://share11.appspot.com/38421

To use it, copy the code into text editor, save it as .php, use Bamcompile to compile .PHP file into .EXE.

Make a folder called “sox” in the same folder as the .EXE file and download the windows version of SoX. Put the exe in the “sox” folder.

Then, for example, I have a .wav file called “x.wav”, I need to make a text file called “x.txt” and type in some beats.

File Structure:

120bpm
16th
,..,..,. ,..,..,.
,...,... ,...,.,.
12th
,,,,,, ,,,,,,

Here are the explainations.

  • 120bpm -> The BPM of the wav file is 120 (changes the tempo, affects the commands after it)
  • 16th -> 1 measure is divided into 16 steps (changes the step size, will affect the commands after it)
  • , -> Starts a new wave file and put 1 step into that file.
  • . -> Put 1 step into the last file.
  • Other texts are treated as comments.

So from the above text file, the application would slice the wav file like this:

  • 0.000 sec
  • 0.375 sec
  • 0.750 sec
  • 1.000 sec
  • 1.375 sec
  • 1.750 sec
  • 2.000 sec
  • 2.500 sec
  • 3.000 sec
  • 3.500 sec
  • 3.750 sec
  • 4.000 sec
  • 4.167 sec
  • 4.333 sec
  • 4.500 sec
  • 4.667 sec
  • 4.833 sec
  • 5.000 sec
  • 5.167 sec
  • 5.333 sec
  • 5.500 sec
  • 5.667 sec
  • 5.833 sec (and lasts for 0.167 seconds)

The generated files will be saved in the folder called “wav”. You can them import and use in BMSE.

<?php chdir (dirname($argv[0])); function debug_msg($text) { echo “$text\n”; } function process_file($txt, &$commands, &$dirs) { // Init. debug_msg (‘==================================’); debug_msg (‘[ii] Text File: ‘ . $txt); if (strtolower(substr($txt, -4)) !== ‘.txt’) { debug_msg (‘[!!] Accept only .txt file!’); return; } if (!file_exists($txt)) { debug_msg (‘[!!] .txt file not found!’); return; } $wav = substr($txt, 0, -3) . ‘wav’; debug_msg (‘[ii] Wave File: ‘ . $wav); if (!file_exists($wav)) { debug_msg (‘[!!] .wav file not found!’); return; } debug_msg (‘[..] Opening Text File: ‘ . $wav); $d = file_get_contents($txt); $render_mode = ‘normal’; if (preg_match(‘~#(soft|double)~’, $d, $match)) { $render_mode = $match[1]; } debug_msg (‘[..] Render Mode: ‘ . $render_mode); // Parse Tokens if (!preg_match_all(‘~(?:[\d.]+)bpm|(?:[\d.]+)(?:st|nd|rd|th)|\.|,~i’, $d, $tokens)) { debug_msg (‘[!!] No tokens found.’); return; } $tokens = array_map(‘strtolower’, $tokens[0]); debug_msg (‘[ii] ‘ . count($tokens) . ‘ tokens found.’); // Default. $bpm = 140; $divide = 4; $parts = array(); $samples = 0; $rate = 44100; // Process Tokens. $fp = fopen(substr($txt, 0, -3) . ‘bms-clipboard.txt’, ‘w’); fwrite ($fp, ‘BMSE ClipBoard Object Data Format’ . “\r\n”); $timecodes = 0; foreach ($tokens as $v) { if ($v == ‘,’) { if ($samples) { $parts[] = $samples; } $samples = compute_samples($bpm, $divide, $rate); fwrite ($fp, sprintf(’1010%07d1′, (int)$timecodes) . “\r\n”); $timecodes += 192 / $divide; continue; } if ($v == ‘.’) { $samples += compute_samples($bpm, $divide, $rate); $timecodes += 192 / $divide; continue; } if (substr($v, -3) == ‘bpm’) { $bpm = floatval(substr($v, 0, -3)); continue; } $divide = floatval(substr($v, 0, -2)); } fclose ($fp); if ($samples) { $parts[] = $samples; } if ($render_mode == ‘double’) { $parts[] = 0; } // Generate Batch Commands debug_msg (‘[ii] ‘ . count($parts) . ‘ slices.’); $start = 0; $source = escapeshellarg($wav); $index = 0; $output = dirname($wav) . ‘\\wav’; $dirs[] = $output; $last_length = 0; $extra_global = ”; $extra_in = ”; $extra_out = ”; if ($render_mode == ‘double’) { $index –; } reset ($parts); while (list($key, $length) = each($parts)) { $is_first = $key == 0; $is_last  = $key >= count($parts) – 1; $index ++; $destination = escapeshellarg( $output . ‘\\’ . substr(basename($wav), 0, -4) . ‘-’ . sprintf(‘%03d’, $index) . ‘.wav’ ); $fade_in = 10; $fade_out = 30; $out_start = $start; $out_length = $length; if ($render_mode == ‘double’) { $out_start -= $last_length; $out_length += $last_length; $extra_in = ‘-v 0.64′; } else if ($render_mode == ‘soft’) { if (!$is_last) { $soft_length = min(16000, floor($parts[$key + 1] / 2)); $fade_out = $soft_length; $out_length += $soft_length; } if (!$is_first) { $soft_length = min(16000, floor($length / 2)); $fade_in = $soft_length; } } $commands[] = sprintf(‘sox\sox %s %s %s %s %s trim %ds %ds fade q %ds %ds %ds’, $extra_global, $extra_in, $source, $extra_out, $destination, (int)($out_start), (int)($out_length), (int)($fade_in), (int)($out_length), (int)($fade_out) ); $last_length = $length; $start += $length; } } function compute_samples($bpm, $divide, $rate) { return ((240 / $bpm) / $divide) * $rate; } $args = $argv; array_shift ($args); $commands = array(); $dirs = array(); foreach ($args as $v) { process_file ($v, $commands, $dirs); } $count = count($commands); debug_msg (‘==================================’); debug_msg (‘[ii] Number of files to be generated: ‘ . $count); debug_msg (‘[..] Creating directories.’); $made = 0; foreach (array_unique($dirs) as $v) { if (!file_exists($v)) { debug_msg (‘[..] Making output directory: ‘ . $v); mkdir ($v); $made ++; } else { debug_msg (‘[ii] Output directory already exists: ‘ . $v); } } debug_msg (‘[ii] Number of new directories created: ‘ . $made . ”); debug_msg (‘==================================’); debug_msg (‘[ii] Generating wav files..’); $index = 0; $digits = strlen(” . $count); foreach ($commands as $v) { $index ++; debug_msg (‘( ‘ . sprintf(‘%0′ . $digits . ‘d’, $index) . ‘ / ‘ . $count . ‘ ): ‘ . $v); exec ($v); } ?>
This entry was posted in BMS, PHP, Windows. Bookmark the permalink.

One Response to My sound slicer

  1. GJoseph says:

    I’m confused too, but I’ll try to understand..

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>