#!/usr/bin/perl -w use strict; use MIDI::Simple; use Getopt::Long; =head1 NAME BeatBox2003 - Create kickin' beats =head1 SYNOPSIS C<beatbox.pl [-t=80] [-b=24] [-p=tph] [-f=input.tab] --nosave> =head1 DESCRIPTION This program enables you to create rhythm tracks from tabulature in a +very short amount of time. You can configure the instruments used, the vol +ume and tempo for your rhythm track. You can send the MIDI data to STDOUT or write +it to a file. =head2 COMMAND LINE OPTIONS =over 4 =item B<-tempo> Set the tempo. (Defaults to 60.) =item B<-beats> Set the numbers of beats in a tabulature. (Comes in handy with jeffa's Triple Paradiddle with Hi-hat.) =item B<-play> The name of the playlist to use. (LIST by default.) This option, if +used, also creates a MIDI file with the same name (as opposed to sending it +to STDOUT). =item B<--nosave> This flag prevents the creation of a MIDI file named for the playlist. + This option is recommended for use with timidity. =item B<-file> The name of the tabulation file to read from (F<sample.tab> is the def +ault). =back =head1 USAGE EXAMPLES =head2 *NIX C<beatbox.pl -p=hh --nosave | timidity -> C<beatbox.pl -p=x | XMM x.mid> =head2 WINDOWS NT/2k/XP C<beatbox.pl -t=80 -b=24 -p=tph | "C:\Program Files\Winamp\winamp.exe" + tph.mid> =head2 WINDOWS 9x C<perl beatbox.pl -p=m | "C:\Program Files\Winamp\winamp.exe" m.mid> =head1 INPUT.TAB The format of the input.tab files is pretty straightforward. =over 4 =item MEASURE A measure contains one or more instruments beat tracks and must be listed in a playlist in order to be played. Each instrument's beat track in a measure must have the same number of beats. Measures should generally contain 16 beats. =item *NAME* Put the name of the measure inside of asterisks on a line by itself. =item INSTRUMENT The instrument must be a declared subroutine in your code. New instruments if added to the DATA section will have a new subroutine will be created for them as runtime provided that you properly follow the instrument declaration format. If you choose not to add your new instrument to the DATA section, then you must add in the appropriate subroutine for your instrument. Note: There must be a colon between the instrument name and the beat track for that instrument. =item BEAT TRACK The "beat track" for an instrument looks like -x--x. This is where you define the beats for an instrument. An "x" signifies that a beat will be played. A beat track should generally be 16 beats in length. =item PLAYLIST The playlist name allows you to have multiple playlists that you can choose to play. The name of the playlist and the playlist itself must be separated by an "=". The playlist is simply a list of predeclared measures in the order they are to be played. =back =head1 SEE ALSO F<sample.tab>, L<MIDI::Simple>, L<Getopt::Long> =head1 AUTHOR OeufMayo Mr. Muskrat =cut my $tempo = 60; my $beats = 16; my $play; my $save; my $file = 'sample.tab'; my $out = 1; my $list = qr/LIST\s*=/i; GetOptions ('save!', \$out, 't|tempo=i', \$tempo, 'b|beats=i', \$beats, 'p|play=s' , \$play, 'f|file=s' , \$file, ); if (defined $play) { $save = lc($play).'.mid'; $list = qr/$play\s*=/i; } $out = 0 if ($out && !defined $save); $beats--; # adjust so that 0 .. $beats works right new_score; set_tempo( 100000 / ($tempo / 120) ); my %beatbox = process( $list, $file ); play_beat( $beats, \%beatbox ); write_score( $out ? $save : \*STDOUT ); exit; ### Process the 'music sheet' ### sub process { my $list = shift; my $file = shift; my ( %beatbox, $module_flag ); open(TAB, '<', $file); while (<TAB>) { next if /^#/; if (/^$list\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 $beats = shift; my %beatbox = %{ +shift }; my $patches = load_patches(); foreach my $segment ( @{ $beatbox{'PLAYLIST'} } ) { foreach my $beat ( 0 .. $beats ) { synch(map { $beatbox{$segment}{$_}[$beat] eq 'x' && exists $patches +->{$_} ? $patches->{$_} : $patches->{'_silent_'}; } keys %{ $beatbox{$segment} } ); } } } sub load_patches { my $channel = 'c9'; # channel 10 my $dur = 'qn'; my $volume = 'ff'; my $patches = { '_silent_' => sub { my $it = shift; $it->r }, }; while (my $line = <DATA>) { next if ($line =~ /^$/); next if ($line =~ /^#/); chomp $line; my (undef, $key, $note, $vol) = split',',$line; $key =~ s/\s+//; $vol ||= $volume; $patches->{$key} = sub {my $it = shift; $it->n($channel,$vol,$no +te,$dur)}; } return $patches; }; __DATA__ # Instrument definitions follow # Instrument Name,XXX,00[,Volume] Agogo High ,AH ,67, Agogo Low ,AL ,68, Bass Drum 1 ,BD1,36, Bass Drum Acoustic,BDA,35, Bongo Hi ,BH ,60, Bongo Low ,BL ,61, Cymbal Chinese ,CC ,52, Cymbal Crash 1 ,CC1,49, Cymbal Crash 2 ,CC2,57, Cymbal Ride 1 ,CR1,51, Cymbal Ride 2 ,CR2,59, Cymbal Splash ,CS ,55, Conga Low ,CL ,64, Conga Mute Hi ,CMH,62, Conga Open Hi ,COH,63, Cuica Mute ,CM ,78, Cuica Open ,CO ,79, Guiro Long ,GL ,74, Guiro Short ,GS ,73, Hi-Hat Closed ,HC ,42, Hi-Hat Open ,HO ,46, Hi-Hat Pedal ,HP ,44, Timbale High ,TBH,65, Timbale Low ,TBL,66, Tom Low Floor ,TLF,41, Tom High Floor ,THF,43, Tom Low ,TL ,45, Tom Low-Mid ,TLM,47, Tom Hi-Mid ,THM,48, Tom High ,TH ,50, Snare Acoustic ,SA ,38, Snare Electric ,SE ,40, Triangle Mute ,TM ,80, Triangle Open ,TO ,81, Whistle Short ,WS ,71, Whistle Long ,WL ,72, Wood Block Hi ,WBH,76, Wood Block Low ,WBL,77, Side Stick ,XSS,37, Hand Clap ,XHC,39, Ride Bell ,XRB,53,mf Tambourine ,XT ,54, Cowbell ,XCB,56,mf Vibraslap ,XV ,58, Claves ,XCL,75, Cabasa ,XCA,69, Maracas ,XM ,70,

In reply to BeatBox 2003 by Mr. Muskrat

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.