#!/usr/bin/perl -sw # BeatBox2001 use strict; # # usage: BeatBox [-t=120] input.tab | timidity - # or BeatBox input.tab > output.mid # # The -t switch can be optionnaly be used to set the tempo # (default 60) # # See the __DATA__ section for instructions on how to # write the input.tab files # use MIDI::Simple; new_score; $main::t ||= 60; set_tempo( 100000 / ($main::t / 120) ); my %beatbox = process(); play_beat( \%beatbox ); write_score( \*STDOUT ); exit; ### Process the 'music sheet' ### sub process { my ( %beatbox, $module_flag ); while (<>) { next if /^#/; if (/^\s*PLAY\(([^)]+)\)/) { push @{ $beatbox{'PLAYLIST'} }, split ( /,/, $1 ); } if (/^\s*\*(\w+)\*$/) { $module_flag = $1 } if (/^\s*(\w+)\s*:\s*([x|-]+)$/) { my ( $instr, $event ) = ( $1, $2 ); @{ $beatbox{$module_flag}{$instr} } = split ( //, $event ); } } return %beatbox; } ### Make some noise ### sub play_beat { my %beatbox = %{ +shift }; my $patches = load_patches(); foreach my $segment ( @{ $beatbox{'PLAYLIST'} } ) { foreach my $beat ( 0 .. 15 ) { synch(map { $beatbox{$segment}{$_}[$beat] eq 'x' && exists $patches->{$_} ? $patches->{$_} : $patches->{'_silent_'}; } keys %{ $beatbox{$segment}} ); } } } ### Instruments (ab)used by the processor ### # # the (n35, n44, n42, ...) are the notes of the percussions # on channel 9. sub load_patches { my $patches = { '_silent_' => sub { my $it = shift; $it->r }, # Drums 'C' => sub { my $it = shift; $it->n('c9','ff','n35','qn')}, 'H' => sub { my $it = shift; $it->n('c9','mf','n44','qn')}, 'Rd' => sub { my $it = shift; $it->n('c9','mf','n44','qn')}, 't' => sub { my $it = shift; $it->n('c9','mf','n50','qn')}, 'T' => sub { my $it = shift; $it->n('c9','mf','n48','qn')}, 'S' => sub { my $it = shift; $it->n('c9','ff','n40','qn')}, 'S2' => sub { my $it = shift; $it->n('c9','ff','n38','qn')}, 'F' => sub { my $it = shift; $it->n('c9','ff','n49','qn')}, 'F2' => sub { my $it = shift; $it->n('c9','ff','n47','qn')}, 'B' => sub { my $it = shift; $it->n('c9','ff','n36','qn')}, 'Hf' => sub { my $it = shift; $it->n('c9','mf','n42','qn')}, }, }; __END__ # # Pretty straightforward format # *whateveryouwant* : name of the measure # instrumentname : must be a delared sub in your code # '--x-x-' line : is the 16 beats of a measure, put # a 'x' if you want to make it sound. # PLAY(A1,A2,...) : The playlist, will play all the pre # declared measures in the given order # (note that you have to put a colon between the # instrument's name and the miserable excuse for a partition # # If you make some cool grooves send'em my way! # # C : Cymbal # H : Hi-Hat # Rd : Ride Cymbal # t : Small Tom # T : Medium Tom # S : Snare Drum # F : Floor Tom # F2 : 2nd Floor Tom # B : Bass Drum # Hf : Hi-Ha w/Foot # *R0* S : ----x-------x--- B : x-x---x---x----- H : x-x-x-x-x-x-x-x- *R1* S : ----x--x----x--- B : x-------x-x----- H : x-x-x-x-x-x-x-x- *R2* S : ----x--x----xxxx B : x---x---x---x--- H : x-xxx-x-x-x-xxx- # from http://www.mxtabs.net/ *F1* H : xxxx-xx-x-xx-x-x S : ----x--x-x--x-x- B : x-x-----x-xx---- *F1FILL* t : --x------------- T : -----------x---- S : --x---x----x---x F : ------x--------x B : x--xx--x-x--xx-- *HH1* H : x-x-x-x-x-x-x-x- S : ----x-------x--- B : x--x-xx--xx----- *HH2* H : x-x-x-x-x-x-x-x- S : ----x-------x--- B : x--x--x--xx----- *HH3* H : x-x-x-x-x-x-x-x- S : ----x-------x--- B : x-x--x-x-------- *X1* C : x--------------- H : --x-x-x-x-x-x-x- S : ----x--x----x--- B : x-x------xx--x-x *X2* C : x--------------- H : --x-x-x-x-x-x-x- S : ----x--x-x--x--- B : xx-x--x-x--x-x-x *X3* C : x--------------- H : --x-x-x-x-x-x-x- S : ----x--xx--xx--x B : x-xx-x-x--x--x-x *XF* C : x-----------x--- H : --x-x---x------- S : ----x-xx-x--x-x- B : -x-x------x--x-- #PLAY(R0,R1,R0,R1,R2,R1,R0,R2,R1,R1,R1,R0,R2) #PLAY(F1,F1,F1,F1FILL,F1,F1,F1,F1FILL) #PLAY(HH3,HH1,HH2,HH1,HH2,HH1,HH1,HH2,HH3) PLAY(X1,X2,X3,XF,X1,X2,X3,XF,X1,X2,X3)