#!/usr/bin/perl use strict; use File::Find; # ### This is version 0.34 # ### Current enhancements: # ### * AIFF format saves my $pi = 3.14159265358979323; my $bitdepth = 16; my $samprate = 44100; my $sampratedivten = $samprate / 10; my $stepstat; my ($exitloop, $ops, @ops, $sound, @sound, %procnames, $lengthsecs, $lengthrate, $lenrateplus, $samplealert, $rawsound, $byte1, $byte2, $byte3, $byte4, $doublerate, $tab); # ### These are values of lesser consequence, used in individual routines: my ($inp, $i, $fun, $j, $vstore, $junk, $krap, @jlist, $jlist, $tally, @vlist, $vlist, $threesult, $k, $p, $c, $d, $e, $f, $g, $listgetflag, $filenames, @filenames, $path, $key, $value, $normloop, $normalizer, $dcoffsetval, $dcoffsetmult, $dcoffsetfreq, $timestamp); # ### sub threepute: my (@sultlist, $sultlist, $sultjunk, $sultj); # ### sub renderstatus; my ($ii); # ### getting ops: function 10 loading file my ($assresult, $asslenrate); # ### basic sine, square, etc rendering my ($out, $stepforward); # ### Andy's stammer rendering: my ($stamlength, $stamposition, $stampostally, $carrier); # ### Integral / Derivative / render: my ($track, $calcstyle, $headroom); # ### Crossover: my ($carriersound, $crossdex); # ### Amplitude tracking: my ($absound, $track, $attack, $sustain, $sustaintally, $release); # ### Basic mixer rendering my ($numberofmods, @carriers); # ### FM rendering my ($numberofmods, $modutotal, $modulayer, $modudex, $forwardpos, $carrier, $fmalg); # ### ring mod render my ($numofmods); # ### power comparisn render my ($mainstay, $comparison, $difference, $power, $mindifference); # ### wavemirror + granular phase distortion rendering my ($carrier, $firstpolarity, $doublepolarity, $switchpolar, $origpos, $outputpos, $shard, @shard, $shardsize, $lenratehalf, $mirrorstyle, $shardpos); # ### abnormalizer rendering my ($carrier, $shard, $normconstant, $noisefloor, $outputpos, $endoutpos, $origpos, $shardsize, $realoutpos, $flip); # ### pitched stammer render my ($origpos, $outputpos, $shardsize, $shardpitch, $lastpitch, $lastshardstart, $lastshardstartjunk, $lastshardlength, $pitchtolerance, $noisefloor, $polartoggle, $lastpolar, $pitchcompare, $minlen, $repeats, $zerotoggle); # ### jigsine render my ($leftover, $lastfreq, $activefreq, $allowreps, $modfactor, $polarity, $freqlist, @freqlist, $numoffreqs, $forwardmarch); # ### sine mosaic render my ($lastslave, $activeslave, $slavelist, @slavelist, $numofslaves, $sinposition, $endforward, $consecutive, $consecnum); # ### magical 3D render my ($function, $frequency, $x, $y, $r, $n, $radius, $angle, $freqtrack); # ### fractalizer render my ($logtrigger, $truebegin, $beginshard, $endshard, $shardlength, $intlength, $fracdex, $intdex, $modulodex, @fracbetween); # ### shimmer-sine render # ### HEY PROGRAMMER: 97 is base freq, 98 is # of shim freqs, 99 is shimrate # ### 96 is linear / log amp control, 95 is amp power exponent # ### everything in this goddamn render is threepute except 98 my ($numoffreqs, $freqnumber, @freqpos, @freqamp, $ampcontrol, $poweramp, $freqgain, $basefreq, $overtone, $shimratestep, $normalizer, $lengthhalf); # ### zero-cross verb render my ($carrier, $origpos, $origsound, $polarflop, $newcross, $lastcross, $amplitude, $frequency, $decayconstant, $decaydenom, $decayrate, $stepforward, $sineposition, $sinerenderpos, $junktally); %procnames = ( # #### basic waves 'none', 'Nuttin\' Honey', 'sin', 'Sine', 'saw', 'Sawtooth', 'sq', 'Square', 'tri', 'Triangle', 'pul', 'Pulse', 'noi', 'Noise', 'sil', 'Silence', 'l', '-Load- a File', # #### singular filters 'gain', 'Gainsmasher', 'wrap', 'Wrapsmasher', 'ref', 'Triangular Reflector', 'shap', 'Sinusoid Waveshaping', 'int', 'Integral', 'der', 'Derivative', 'cro', 'Crossover Distortion', 'pow', 'Raise to Power', # #### double filters 'mix', 'Basic Mixer', 'fm', 'Frequency Modulation (FM)', 'ring', 'Ring Modulation (x)', 'pc', 'Power Comparison', # #### lfo gener 'amp', 'Amplitude Tracking', # #### granular generators 'jsi', 'Jig-Sine', 'jco', 'Jig-Cosine', 'mos', 'Sine Mosaic', 'ter', '3D Terrain Mapper', # #### granular filters 'stam', 'Andy\'s Stammerverb', 'mir', 'W@vE -mirror- 3^@M', 'flip', 'Granular Phase Flipping', 'abn', 'Ab-Normalizer', 'frac', 'Fractalizer', 'ps', 'Pitched Stammer', # #### additive synthesis 'shim', 'Shimmer-Sine', 'zv', 'Zero-Cross Verb', 'pv', 'Pitched Verb', ); $lengthsecs = 5; $lengthrate = $lengthsecs * $samprate; $samplealert = 0; $tab = "\t>> "; sub hline { print " ... "; print $_[0] x 64; print " ...\n"; } sub oneget { $junk = $ops->[$inp][$_[0]][0]; if ($junk) { print "($junk) "; } $krap=<>; chomp $krap; if ($krap) { $ops->[$inp][$_[0]][0] = $krap; } else { print "$tab Keeping value $junk.\n"; } } sub threeget { print "[##x] "; for $k(0..2) { $jlist[$k] = $ops->[$inp][$_[0]][$k]; } if ($jlist[0]) { print "(@jlist) "; } $krap=<>; chomp $krap; if ($krap) { # #### Thanks Garrett!!! @vlist = split(",",$krap); # #### 2 items in list? then it is a ramp, designated by ->[2] = -1 if ($#vlist == 1) {$vlist[2] = -1;} for $k(0..2) { $ops->[$inp][$_[0]][$k] = $vlist[$k]; } } else { print "$tab Keeping value @jlist.\n"; } } sub threepute { # #### # #### By the way, the order of passed info is: # #### [process number ($ops[*]) ],[$ops data 1-99],[lengthrate step] # #### Obnoxious, huh. Perl can't seem to pass for{} values. # #### if ($ops->[$_[0]][$_[1]][2]) { for $sultj(0..2) { $sultlist[$sultj] = $ops->[$_[0]][$_[1]][$sultj]; } # #### When the modulation is a simple ramp: if ($sultlist[2] < 0) { # #### $junk (the modulator value) is from 0 to 1 # #### first case is for -1 straight ramp; second is exponent for curves if ($sultlist[2] == -1) { $sultjunk = ($_[2] / $lengthrate); } else { $sultjunk = ($_[2] / $lengthrate) ** abs ($sultlist[2]); } } # #### When it draws from another rendered sound: else { $sultjunk = ($sound->[$sultlist[2]][$_[2]] + 1) / 2; } $threesult = ($sultjunk * ($sultlist[1] - $sultlist[0])) + $sultlist[0]; } else { # #### When no modulation: $threesult = $ops->[$_[0]][$_[1]][0]; } } sub listget { $vstore=<>; chomp $vstore; if ($vstore) { $ops->[$inp][$_[0]][0] = $vstore; } if (!$vstore) { print "$tab End of input.\n"; $ops->[$inp][$_[0]][0] = 0; $listgetflag = 0; } } sub saveask { print "Should this layer be -=SAVED=- ? "; $junk = $ops->[$inp][100][0]; if ($junk) {print "(yes) "} else {print "(no) "} $krap=<>; chomp ($krap); if ($krap eq "n") { $ops->[$inp][100][0] = 0; $junk = 0; } if (($krap eq "y") || ($junk)) { if (!$junk) { $ops->[$inp][100][0] = $inp . '._' . $fun . '_' . $ops->[$inp][1][0] . '.' . $ops->[$inp][2][0] . '.aiff'; } print "Filename: "; oneget (100); } } sub procspit { $tally = 0; for $p(1..100) { if ($ops->[$p][0][0]) { $tally++; procline ($p); } } if (!$tally) { print "\t\tNo processes! Type a number from 1-100 to begin.\n"; } } sub procline { $k = $_[0]; print "\t\t#$k - \t\U$ops->[$k][0][0]\E\t"; for $i(1..2) { for $j(0..2) { $krap = $ops->[$k][$i][$j]; if (($krap) && ($krap != -1)) { if ($j) {print ","} print "$krap"; } } if ($i == 1) {print "\t";} } if ($ops->[$k][100][0]) { print "\t-=SAVE=-"; } print "\n"; } sub normalize { # #### normalize: [0] is the sound layer to be affected, # #### [1] is the minimum normalizer value to start with $normalizer = $_[1]; if (!$normalizer) {$normalizer = .1}; for $normloop(0..$lenrateplus) { if (abs ($sound->[$_[0]][$normloop]) > $normalizer) { $normalizer = abs ($sound->[$_[0]][$normloop]); print "$tab Finding normalization constant: $normalizer...\n"; } } print "$tab *** Normalizing... ***\n"; $normalizer = 1 / $normalizer; for $normloop(0..$lenrateplus) { $sound->[$_[0]][$normloop] *= $normalizer; } } sub dcoffset { print "Repairing the horrible DC offset, stand by...\n"; $dcoffsetval = 0; $dcoffsetfreq = 5; $dcoffsetmult = $dcoffsetfreq * (1 / $samprate); $g = ($samprate - $dcoffsetfreq) / $samprate; for $j(0..$lenrateplus) { $dcoffsetval = ($dcoffsetval * (1 - $dcoffsetmult)) + ($sound->[$_[0]][$j] * $dcoffsetmult); $sound->[$_[0]][$j] -= $dcoffsetval; } # old, broad sweeping dc summation crap # for $j(0..$lengthrate) { # $dcoffsetval += $sound->[$_[0]][$j]; # } # $dcoffsetval /= $lengthrate; # print "DC offset is $dcoffsetval, so let's fix that...\n"; # for $j(0..$lenrateplus) { # $sound->[$_[0]][$j] -= $dcoffsetval; # } print "Alright then!\n"; } sub renderstatus { if ($_[0] / $samprate > $tally) { $| = 1; $junk = $procnames{$fun}; print "\r$ii.\t$junk\t$tally "; $tally += .1; $| = 0; } } sub stepstatus { $stepstat ++; if ($stepstat >= $sampratedivten) { $| = 1; $junk = $procnames{$fun}; print "\r$ii.\t$junk\t$tally "; $tally += .1; $stepstat = 0; $| = 0; } } sub log2 { return log($_[0])/log(2); } sub polar { if ($_[0] > 0) {return 1} elsif ($_[0] < 0) {return -1} else {return 0}; } sub wanted { push (@filenames, $File::Find::name) if ( # add this file to tree, if (-f) # && # # it's a file (not a dir) # ($_ =~ /.pl$/i) # # and ends in .txt (or whatever) ); } # 345678901234567890123456789012345678901234567890123456789012345678901234567890 print "\n\n"; hline ('='); hline ('/'); hline ('|'); print " FILTERCHRIST 0.34!\n"; print " I Died For Your Sines\n"; hline ('|'); hline ('/'); hline ('='); print "\n\n"; $exitloop = 1; while ($exitloop) { hline ('='); print "\tLENGTH: $lengthsecs seconds ($lengthrate samples)\n"; print "\tPROCESSES:\n"; procspit; hline ('-'); print "\t[#] Add/Edit a process [L]oad a process list\n"; print "\t[D]elete a process [S]ave a process list\n"; print "\t[M]ove a process [X]tend/truncate duration\n"; print "\t[C]lone a process [/]the hell's going on here?\n"; print "\t[R]ender the bastard [Q]uit\n"; hline ('='); print "\nYour command, master? "; $inp=<>; chomp $inp; print "\n\n"; # ########## THIS IS WHERE WE ALL GO INSANE ########## # #### NUMBERED PROCESS GAUNTLET: #### # if (($inp >= 1) && ($inp <= 100)) { $fun = $ops->[$inp][0][0]; if (!$fun) { hline ('~'); print "\n"; print " WAVES SINGULAR FILTERS MULTIPLE FILTERS\n"; print " ----------------- ----------------- -----------------\n"; print " [sin]e [gain]-Smasher Basic [mix]er\n"; print " [saw] [wrap]-Smasher [fm] Frequency Mod.\n"; print " [sq]uare [ref] Reflector [ring] Modulation\n"; print " [tri]angle [shap] Sinusoid Shaper [pc] Power Compare\n"; print " [noi]se [int]egral, [der]ivative LFO GENERATORS\n"; print " [sil]ence [cro]ssover Distortion -----------------\n"; print " [l] Load a sound file [pow] Raise to Power [amp]litude Tracking\n"; print "\n"; print " GRANULAR WAVES GRANULAR FILTERS ADDITIVE WAVES\n"; print " ----------------- -------------------------- -----------------\n"; print " [jsi] Jig-Sine [stam] Andy\'s Stammerverb [shim]mer-Sine\n"; print " [jco] Jig-Cosine [mir] W\@ve -mirror- 3^\@M [zv] Zero-Cross Verb\n"; print " [mos] Sine Mosaic [flip] Flip Chunking [pv] Pitched Verb\n"; print " [ter] 3D Terrain [abn] Ab-Normalizer\n"; print " [frac] Fractalizer\n"; print " [ps] Pitched Stammer\n"; hline ('~'); print "\n"; # #### old method of displaying functions: # while (($key, $value) = each %procnames) { # print "\t$key\t$value\n"; # } # print "\t^M\tForget about it\n"; print "Which function for process $inp ? (^M if none) "; $fun=<>; chomp $fun; # #### What if that thing don't exist? if ((!$procnames{$fun}) && ($fun)) { print "$tab That \'$fun\' crap is whack, home boy.\n"; print "$tab Whack bitch.\n"; $fun = 0; } $ops->[$inp][0][0] = $fun; } print "\n\n"; if ($fun) { # #### No proc list if loading a sound if ($fun ne 'l') { hline ('~'); procspit; } } hline ('~'); # ########## EVERY FUCTION GETS ITS VARS ($ops) FROM BELOW HERE ########## # # #### WAVES + LOAD A FILE if (($fun eq 'sin') || ($fun eq 'sq') || ($fun eq 'saw') || ($fun eq 'tri')) { print "$tab Awwright a \U$procnames{$fun}\E wave!\n"; print "Frequency? "; threeget (1); print "Amplitude? "; threeget (2); saveask; } if ($fun eq 'pul') { print "$tab Pulsey rectangle! Look out Brian Eno\n"; print "Frequency? "; threeget (1); print "Modulation? (range: -1 to 1) "; threeget (2); print "Amplitude? "; threeget (3); saveask; } if ($fun eq 'noi') { print "$tab Dude, Merzbow was so doing that 15 years ago.\n$tab No settings for this function.\n"; } if ($fun eq 'sil') { print "$tab Silence is golden. It is also very boring.\n$tab No settings for this function.\n"; } if ($fun eq 'l') { print "$tab Load a file, huh?! Jeezus, you kids\n"; hline ('.'); $path = "."; find(\&wanted, $path); # get recursive list into @filenames $krap = @filenames; print "I'm finding $krap files\n"; for $j(0..$#filenames) { $f = $j + 1; print "$tab $f - $filenames[$j]\n"; } hline ('.'); print "Which file to load? "; oneget (1); $g = $ops->[$inp][1][0]; $e = $filenames[$g - 1]; $ops->[$inp][2][0] = $e; if ($g) { { local (*HONK,$/); open (HONK,"$e"); $assresult = ; close HONK; } # print $assresult; $krap = length($assresult) / 2; # #### CHANGE THE SIZE??? OR JUST DICKS AGAIN $k = 0; if ($samplealert) { if ($krap >= $samplealert) { print "$tab This sample is longer than the render duration: $krap samples, ($krap / $samprate) secs.\n"; print "Extend the length of the render? (yes) "; $junk=<>; chomp $junk; if (($junk eq "y") || ($junk eq "Y")) {$k = 1} } } else { $samplealert = 1; $asslenrate = $krap / $samprate; if ($krap <= $lengthrate) { print "$tab This sample is shorter than the current render length: $krap samples, ($asslenrate) secs.\n"; } else { print "$tab This sample is longer than I expected: $krap samples, ($asslenrate) secs.\n"; } print "Change the length of the render? (yes) "; $junk=<>; chomp $junk; if (($junk eq "y") || (!$junk)) {$k = 1} } if ($k) { $lengthrate = $krap; $lengthsecs = $krap / $samprate; print "$tab Changed! That's just great\n"; } } # saveask; } # #### SINGULAR FILTERS if ($fun eq 'gain') { print "$tab Gain smasher!!! WATCH OUT this will blow yo speaka cone\n"; print "Source wave? "; oneget (1); print "Amplitude gain? (1 = full scale, no change) "; threeget (2); print "Pulse width modulation? (1 = 100%, don't go there) "; threeget (3); saveask; } if ($fun eq 'wrap') { print "$tab Wrap smasher!!! WATCH OUT this can blow speakers\n"; print "Source wave? "; oneget (1); print "Amplitude gain? (1 = full scale, no change) "; threeget (2); print "Pulse width modulation? (2 = back where it started) "; threeget (3); print "Type of wraparound? (1 = back to zero, 2 = full wrap) "; oneget (4); saveask; } if ($fun eq 'ref') { print "$tab Bouncy triangular waveshaping from hell!!! YES\n"; print "Source wave? "; oneget (1); print "Reflector gain? (1 = no change) "; threeget (2); saveask; } if ($fun eq 'shap') { print "$tab Kurzweil did it first!\n"; print "Source wave? "; oneget (1); print "Shaper index? (1 = 1 full sinusoid) "; threeget (2); saveask; } if ($fun eq 'int') { print "$tab Calculus nightmares made easy! INTEG\n"; hline ('.'); print "Source wave? "; oneget (1); print "How much headroom to move without clipping? (50+ may be clean) "; oneget (3); saveask; } if ($fun eq 'der') { print "$tab Calculus nightmares made easy! DERIV\n"; hline ('.'); print "Source wave? "; oneget (1); print "How much headroom to move without clipping? (2 is max clean) "; oneget (3); saveask; } if ($fun eq 'cro') { print "$tab Crossover distortion! Ya know,\n$tab usually peaple pay to NOT have this effect\n"; hline ('.'); print "Source wave? "; oneget (1); print "Distortion index? (Ranges: 0-1 is crossover, 1-2 is bloat) "; threeget (2); saveask; } if ($fun eq 'pow') { print "$tab Raise to friggin' power already\n"; hline ('.'); print "Sounce wave? "; oneget (1); print "Power to raise to? (Think: 0 - 2 is ideal) "; threeget (2); saveask; } # #### MULTIPLE FILTERS if ($fun eq 'mix') { print "$tab A basic, boring mixer!\n"; print "$tab Programmed in real BASIC! No, I just kid\n"; hline ('.'); $listgetflag=1;$tally=1; while ($listgetflag) { $k = ($tally + 1) / 2; print "Modulator wave #$k? "; if ($k >= 2) {print "(^M when done) "} listget ($tally); if ($listgetflag) { print "How much gain on layer #$k? "; threeget ($tally + 1); $tally = $tally + 2; } } $ops->[$inp][98][0] = $k - 1; print "Normalize the mix to a safe and sane level? (0 no, 1 yes) "; oneget (99); saveask; } if ($fun eq 'fm') { print "$tab Frequency modulation! Yamaha be damned\n"; hline ('.'); print "FM algorithm? (1 is FM [forward], 2 is PM [phase wobble]) "; oneget (99); print "Carrier wave? (choose a process from the list) "; oneget (1); $listgetflag=1;$tally=2; while ($listgetflag) { $k = $tally / 2; print "Modulator wave #$k? "; if ($k >= 2) {print "(^M when done) "} listget ($tally); if ($listgetflag) { print "Modulation index for layer #$k? "; # if ($ops->[$inp][99][0] == 1) {print "(try -X,X,layer) ";} threeget ($tally + 1); $tally = $tally + 2; } } saveask; } if ($fun eq 'ring') { print "$tab Ring modulation! Dow NOW now NOW <-- *air guitar*\n"; hline ('.'); $listgetflag = 1;$tally=1; while ($listgetflag) { print "Modulation layer #$tally? "; if ($tally >= 2) {print "(^M when done) ";} listget ($tally); $tally++; } saveask; } if ($fun eq 'pc') { print "$tab Power Comparison!! BOOM SHAKA LAKA\n"; print "$tab NOTE TO USER: this does not work correctly yet\n"; hline ('.'); print "Mainstay wave? "; oneget (1); print "Comparison wave? "; oneget (2); print "How much POWER??? (min 0, max 2) "; threeget (3); saveask; } # #### LFO GENERATORS if ($fun eq 'amp') { print "$tab Amplitude tracking oh PAIN\n"; print "$tab Note that this creates a >NON-AUDIO WAVE<. This creates controller\n$tab data, ranging in value from -1 to 1.\n"; hline ('.'); print "Wave to be tracked? "; oneget (1); print "Attack time, in seconds? (this can be 0) "; threeget (2); print "Release time? "; threeget (3); saveask; } # #### GRANULAR WAVES if ($fun eq 'jsi') { print "$tab Half-sinusoid splicer machine!\n"; hline ('.'); $listgetflag = 1;$tally=1; while ($listgetflag) { print "Frequency #$tally? "; if ($tally >= 2) {print "(^M when done) ";} listget ($tally); $tally++; } print "Modulation factor? (0 quiet - 1 loud) "; threeget (98); print "Allow repetition? (0=no, 1=yes) "; oneget (99); saveask; } if ($fun eq 'jco') { print "$tab Half-cosinator splicer machine! Hat damn\n"; hline ('.'); $listgetflag = 1;$tally=1; while ($listgetflag) { print "Frequency #$tally? "; if ($tally >= 2) {print "(^M when done) ";} listget ($tally); $tally++; } print "$tab This function has no modulation ability yet.\n"; print "Allow repetition? (0=no, 1=yes) "; oneget (99); saveask; } if ($fun eq 'mos') { print "$tab Crazy-ass sine mosaic thing!! Ha ha woo CRAZY\n"; hline ('.'); $listgetflag = 1;$tally=2; print "Master frequency? "; threeget (1); while ($listgetflag) { $c = $tally - 1; print "Slave frequency #$c? "; if ($tally >= 3) {print "(^M when done) ";} listget ($tally); $tally++; } print "Consecutive ordering? (0 no, 1 yes) "; oneget (99); saveask; } if ($fun eq 'ter') { print "$tab 3D terrain generator!!! Fuck yeah dude\n"; hline ('.'); print "$tab PRE-DEFINED FUNCTIONS: \n"; print "a). sin(2*(\$x**3))-cos(3*(\$y**2)) [best within: +/- 2.5]\n"; print "b). sin(\$pi**\$x)-cos(\$pi**\$y) [3.5]\n"; print "c). sin(\$pi**\$x)*cos(\$pi**\$y) [5]\n"; print "d). sin((\$x**2)/5)*cos((\$y**3)/7) [10, barely]\n"; print "e). cos(\$r)*sin(\$x) [?]\n"; print "f). (\$x-\$y)*(\$x+1)*(\$x-1)*(\$y+1)*(\$y-1)\n"; print "g). ((sin(\$x*\$y)+cos(\$x*2)/2+sin(\$y*3)/3)/(1+abs(sin(\$y*5)+cos(\$x*6)/2)))/1\n"; hline ('.'); print "$tab Or, enter your own function using \$x, \$y, \$r :\n"; print "? "; oneget (1); $b = $ops->[$inp][1][0]; if ($b eq "a") {$ops->[$inp][1][0] = "sin(2*(\$x**3))-cos(3*(\$y**2))";} elsif ($b eq "b") {$ops->[$inp][1][0] = "sin(\$pi**\$x)-cos(\$pi**\$y)";} elsif ($b eq "c") {$ops->[$inp][1][0] = "sin(\$pi**\$x)*cos(\$pi**\$y)";} elsif ($b eq "d") {$ops->[$inp][1][0] = "sin((\$x**2)/5)*cos((\$y**3)/7)";} elsif ($b eq "e") {$ops->[$inp][1][0] = "cos(\$r)*sin(\$x)";} elsif ($b eq "f") {$ops->[$inp][1][0] = "(\$x-\$y)*(\$x+1)*(\$x-1)*(\$y+1)*(\$y-1)";} elsif ($b eq "g") {$ops->[$inp][1][0] = "((sin(\$x*\$y)+cos(\$x*2)/2+sin(\$y*3)/3)/(1+abs(sin(\$y*5)+cos(\$x*6)/2)))/1";} else {} print "Frequency? "; threeget (2); print "X sweep axis point? "; threeget (3); print "Y sweep axis point? "; threeget (4); print "Radius? "; threeget (5); # #### n is fucking useless # print "Value of n? (^M if you're not using this) "; # threeget (6); saveask; print "Well! That was fucking great\n"; } # #### GRANULAR FILTERS if ($fun eq 'mir') { print "$tab Wavemirror! Look out\n"; print "Source wave? "; oneget (1); print "What style of mirroring? (1=stand [vert], 2=hit [rota], 3=double, 4=nothing) "; oneget (2); print "$tab Current length is $lengthsecs seconds, $lengthrate samples.\n"; print "Would you like to double the render length? (n) "; $junk=<>; chomp $junk; if (($junk eq "y") || ($junk eq "Y")) { $lengthrate = $lengthrate * 2; $lengthsecs = $lengthrate / $samprate; print "$tab It's now $lengthsecs seconds, $lengthrate samples.\n"; } saveask; } if ($fun eq 'stam') { print "$tab Experimental stim!\n"; print "$tab LENGTH: $lengthsecs seconds ($lengthrate samples)\n"; hline ('.'); print "Source wave? "; oneget (1); print "Packet starting position? (in seconds) "; threeget (2); print "Frequency-size packets to draw from? (440 etc) "; threeget (3); saveask; } if ($fun eq 'flip') { print "$tab Granular Phase Distortion HULAGUPULEGOALUEOLG\n"; print "Source wave? "; oneget (1); print "$tab Okay. No more controls yet, sorry...\n"; saveask; } if ($fun eq 'abn') { print "$tab AbNormalizer, woot\n"; print "Source wave? "; oneget (1); print "Normalization frequency? "; threeget (2); print "Polarity flipping? [0/1] "; oneget (3); saveask; } if ($fun eq 'frac') { print "$tab FRACTALIZER baby!!!\n"; print "Source wave? "; oneget (1); print "Splision frequency? (0 for something that don't work yet) "; threeget (2); print "Linear (1) or logarithmic (2) fractalization? "; oneget (3); print "$tab Okay, now listen carefully.\n"; if ($ops->[$inp][3][0] == 1) { print "$tab The fractal index can be from 1 to infinity. 1 is no effect.\n$tab Each step up will be an overtone of the original sample, so\n$tab octaves are at: 1, 2, 4, 8, etc. 10 is probably extreme and bright.\n"; } else { print "$tab The fractal index can be from 0 to infinity. 0 is no effect.\n$tab Anything more than 6 is likely way too much effect.\n$tab 1 doubles the pitch; 2 quadruples it, etc.\n"; } print "Fractal Index? "; threeget (4); saveask; } if ($fun eq 'ps') { print "$tab Pitched stammer! Bad Sector beat-down\n"; print "Source wave? "; oneget (1); print "Acceptable repeat: +/- how many semitones? \n"; threeget (2); print "Maximum frequency to stammer? \n"; threeget (3); print "Maximum number of stammers? (25 etc) \n"; threeget (4); saveask; } # #### ADDITIVE SYNTHESIS FUNCTIONS if ($fun eq 'shim') { print "$tab AAGH my ears are additive!\n"; hline ('.'); $listgetflag = 1; $tally=1; print "Base frequency? (in hertz) "; threeget (97); while ($listgetflag) { print "Overtone #$tally? (1, 2, 3, 2.5, etc) "; if ($tally >= 2) { print "(^M when done) "; } threeget ($tally); if (!$ops->[$inp][$tally][0]) { print "$tab End of input.\n"; $listgetflag = 0; } $tally ++; } $ops->[$inp][98][0] = $tally - 2; print "Linear (0) or Logarithmic (1) rate control? "; oneget (96); if ((!$ops->[$inp][99][0]) && (!$ops->[$inp][99][1])) { $ops->[$inp][99][0] = 1; } print "Amp exponent? (1 is normal, 0-1 louder, 1-higher softer) "; threeget (95); print "And finally, what's the base frequency shim rate? (1 is standard) "; threeget (99); saveask; } if ($fun eq 'zv') { print "$tab Zero-crossing verb! It is roXor\n"; hline ('.'); print "Source wave? "; oneget (1); print "Amplitude half-life, in seconds? (Recommended: .001 - .05)"; threeget (2); print "Frequency ratio? (1 is no change, 2 is higher, .5 lower) "; threeget (3); saveask; } if ($fun eq 'pv') { print "$tab This don't work yet.\n"; } # #### END OF NUMBERED PROCESSES #### # hline ('~'); } if (($inp eq "x") || ($inp eq "X")) { hline ('^'); print "$tab Current length is $lengthsecs seconds, $lengthrate samples.\n"; hline ('-'); print "Input new length (<= 3000 will be treated as seconds)? (^M if none) "; # $lengthrate = $lengthsecs * $samprate; $junk=<>; chomp $junk; if ($junk) { if ($junk <= 3000) { $lengthsecs = $junk; $k = $junk * $samprate; if ($k != int($k)) {$k = int($k) + 1;} $lengthrate = $k; } else { $lengthrate = $junk; $lengthsecs = $junk / $samprate; } hline ('-'); print "$tab It's now $lengthsecs seconds, $lengthrate samples, and I LOVE YOU!!!\n"; hline ('^'); } } if (($inp eq "d") || ($inp eq "D")) { hline ('x'); procspit; hline ('.'); print "Which process would you like to DELETE? (^M if none) "; $junk=<>; chomp $junk; if ($junk) { for $i(0..100) { for $j(0..2) { $ops->[$junk][$i][$j] = 0; } } print "$tab Aaarr matey!!!!1\n"; hline ('x'); } } if (($inp eq "m") || ($inp eq "M")) { hline ('<'); procspit; hline ('.'); print "Which process would you like to MOVE? (^M if none) "; $junk=<>; chomp $junk; if ($junk) { print "To what process number? (^M if never mind) "; $krap=<>; chomp $krap; if ($krap) { for $i(0..100) { for $j(0..2) { $ops->[$krap][$i][$j] = $ops->[$junk][$i][$j]; $ops->[$junk][$i][$j] = 0; } } # if ($ops->[$krap][100][0]) { # $inp = $krap; # $ops->[$inp][100][0] = 0; # } print "$tab Shovin' right off to port!\n"; hline ('>'); } } } if (($inp eq "c") || ($inp eq "C")) { hline ('*'); procspit; hline ('.'); print "Which process would you like to COPY? (^M if none) "; $junk=<>; chomp $junk; if ($junk) { print "To what process number? (^M if never mind) "; $krap=<>; chomp $krap; if ($krap) { for $i(0..100) { for $j(0..2) { $ops->[$krap][$i][$j] = $ops->[$junk][$i][$j]; } } if ($ops->[$krap][100][0]) { $inp = $krap; $ops->[$inp][100][0] = 0; saveask; } print "$tab My laboratory sheep impression!\n"; hline ('*'); } } } if (($inp eq "q") || ($inp eq "Q")) { print "$tab Later skater\n"; exit(1); } if ($inp eq "/") { print "\n"; hline ('?'); hline ('+'); print "$tab Self-righteous spew goes here (chaz\@dslnorthwest.net)\n$tab Many thanks to: Alex, Andy, Skot, Garrett\n\n"; print "$tab THIS IS IMPORTANT:\nMany inputs in Filterchrist can accept up to three variables.\nWhenever you see the symbol [##x], you can enter data in any\nof these three formats:\n\n"; print " 440 (a unchanging constant, 440)\n"; print " 440,880 (a modulation that ramps from 440 to 880 as the sound plays)\n"; print " 440,880,3 (a modulation that ranges from 440 to 880 depending\n\t\ton the value of process 3's output, as the sound plays)\n\n"; print "\t$tab [Get it? The processes can >modulate each other<.\n\t$tab That's why it's called filterCHRIST. Have fun.]\n"; hline ('+'); hline ('?'); print "\n\n$tab Pound the fuck out of the return key (^M) to continue..."; $krap=<>; chomp ($krap); if (($krap eq "v") || ($krap eq "V")) { print "\n\n\n\n\n\n"; hline ('V'); print "$tab VERSION HISTORY\n"; print "$tab (like anyone cares, but I'm still proud)\n"; hline ('.'); print "$tab v0.34: _7/24/02_ AIFF format saves, more funcs\n"; print "$tab v0.3: _4/18/02_ Function calls now names, not numbers;\n\t created additive synthesis functions!! Awesome and slow\n"; print "$tab v0.25: _4/03/02_ Enabled and (mostly) debugged 6 tasty granular\n\t filters when I should have been doing work! Yeah bud I'm a stud\n"; print "$tab v0.2: _2/12/02_ Can now import sound files! Aww sheeyit\n"; print "$tab v0.1: _2/07/02_ Enabled triple input, and the godliness began\n"; hline ('-'); print "\t$tab Fuck all ya bitch-ass niggas\n"; hline ('^'); print "\n\n\n\n$tab Pound the fuck out of the return key (^M) to continue..."; $krap=<>; } print "\n\n"; } if (($inp eq "r") || ($inp eq "R")) { $exitloop = 0; } # #### END OF LETTERED PROCESSES and WHILE #### # print "\n\n"; } # #### RENDER STARTS HERE #### # print "\n\n$tab Okay! Uh. Here we go. I think. Oh god.\n"; print "$tab The sounds will be $lengthsecs seconds long / $lengthrate samples.\n"; $lenrateplus = $lengthrate + 100; for $i(1..100) { if ($ops->[$i][0][0]) { hline ('-'); procline ($i); hline ('-'); $tally = .1; $stepstat = 0; $fun = $ops->[$i][0][0]; $ii = $i; $timestamp = time; # #### # #### WAVES # #### # #### 1 SINE WAVE if ($fun eq 'sin') { $outputpos = 0; # #### Rock it for $j(0..$lenrateplus) { # #### get the value: proc number, 1 (freq), lengthrate position threepute ($i,1,$j); $stepforward = $threesult / $samprate * 2 * $pi; threepute ($i,2,$j); $sound->[$i][$j] = sin($outputpos) * $threesult; $outputpos += $stepforward; stepstatus; } } # #### 2 SAW WAVE # #### This is a lot like function 1 (sine). Except it is different. if ($fun eq 'saw') { $outputpos = 0; # #### Rock it for $j(0..$lenrateplus) { # #### get the value: proc number, 1 (freq), lengthrate position threepute ($i,1,$j); $stepforward = $threesult / $samprate * 2 * $pi; $g = $outputpos / $pi / 2; threepute ($i,2,$j); $sound->[$i][$j] = (2 * ($g - int($g)) - 1) * $threesult; $outputpos += $stepforward; stepstatus; } } # #### 3 SKWAR WAVE if ($fun eq 'sq') { $outputpos = 0; # #### Rock it for $j(0..$lenrateplus) { # #### get the value: proc number, 1 (freq), lengthrate position threepute ($i,1,$j); $stepforward = $threesult / $samprate * 2 * $pi; $g = ($outputpos / $pi / 2); threepute ($i,2,$j); if ($g - int($g) >= .5) { $sound->[$i][$j] = $threesult; } else { $sound->[$i][$j] = 0 - $threesult; } $outputpos += $stepforward; stepstatus; } } # #### 4 TRIANGUL WAVE if ($fun eq 'tri') { $outputpos = 0; # #### Rock it for $j(0..$lenrateplus) { # #### get the value: proc number, 1 (freq), lengthrate position threepute ($i,1,$j); $stepforward = $threesult / $samprate * 2 * $pi; $g = ($outputpos / $pi / 2); $g = 4 * ($g - int($g)) - 2; if ($g >= 1) {$g = 2 - $g;} if ($g <= -1) {$g = -2 - $g;} # #### theoretically the sawtooth (0 - 1) is now changed into a triangle wave between 1 and -1 threepute ($i,2,$j); $sound->[$i][$j] = $g * $threesult; $outputpos += $stepforward; stepstatus; } } # #### 5 PULSE WAVE if ($fun eq 'pul') { $outputpos = 0; # #### Rock it for $j(0..$lenrateplus) { # #### get the value: proc number, 1 (freq), lengthrate position threepute ($i,1,$j); $stepforward = $threesult / $samprate * 2 * $pi; $g = ($outputpos / $pi / 2); threepute ($i,2,$j); $c = ($threesult + 1) / 2; threepute ($i,3,$j); if ($g - int($g) >= $c) { $sound->[$i][$j] = $threesult; } else { $sound->[$i][$j] = 0 - $threesult; } $outputpos += $stepforward; stepstatus; } } # #### 8 NOISE if ($fun eq 'noi') { for $j(0..$lenrateplus) { $sound->[$i][$j] = (rand() * 2) - 1; stepstatus; } } # #### 9 SILENCE if ($fun eq 'sil') { for $j(0..$lenrateplus) { $sound->[$i][$j] = 0; stepstatus; } } # #### 10 LOAD A FILE if ($fun eq 'l') { # ### Thanks Alex!!! print "Loading $ops->[$i][2][0]...\n"; { local (*BRAP,$/); open (BRAP,"$ops->[$i][2][0]"); $assresult = ; close (BRAP); } $c = length($assresult) / 2; if ($c > $lenrateplus) {$c = $lenrateplus} for $j(0..$c) { $byte1 = substr($assresult,$j * 2,1); $byte2 = substr($assresult,$j * 2 + 1,1); $d = ord($byte1) + (ord($byte2) / 256); if ($d >= 128) { $d = $d - 256 } $sound->[$i][$j] = $d / 128; # print "$sound->[$i][$j]\n"; } $assresult = ""; print "Even the lovely ladies of Barcelona say it: 'Hot Damn'!"; } # #### # #### SINGULAR FILTERS # #### # #### 11 GAINSMASHER if ($fun eq 'gain') { $c = $ops->[$i][1][0]; for $j(0..$lenrateplus) { $out = $sound->[$c][$j]; # #### get the value: proc number, 1 (freq), lengthrate position threepute ($i,2,$j); $out = $out * $threesult; threepute ($i,3,$j); $out = $out + $threesult; if ($out >= 1) {$out = 1} if ($out <= -1) {$out = -1} $sound->[$i][$j] = $out; stepstatus; } } # #### 12 WRAPSMASHER if ($fun eq 'wrap') { $c = $ops->[$i][1][0]; # #### type 1 = half wrap, type 2 = full wrap $e = $ops->[$i][4][0]; for $j(0..$lenrateplus) { $out = $sound->[$c][$j]; # #### get the value: proc number, 1 (freq), lengthrate position threepute ($i,2,$j); $out = $out * $threesult; threepute ($i,3,$j); $out = $out + $threesult; until ($out <= 1) {$out = $out - $e} until ($out >= -1) {$out = $out + $e} $sound->[$i][$j] = $out; stepstatus; } } # #### 13 REFLECTOR if ($fun eq 'ref') { $c = $ops->[$i][1][0]; for $j(0..$lenrateplus) { $out = $sound->[$c][$j]; # #### get the value: proc number, 1 (freq), lengthrate position threepute ($i,2,$j); $out = $out * $threesult; until (($out <= 1) && ($out >= -1)) { if ($out >= 1) {$out = 2 - $out} if ($out <= -1) {$out = -2 - $out} } $sound->[$i][$j] = $out; stepstatus; } } # #### 14 SINUSOID WAVESHAPING if ($fun eq 'shap') { $c = $ops->[$i][1][0]; for $j(0..$lenrateplus) { $out = $sound->[$c][$j]; # #### get the value: proc number, 1 (freq), lengthrate position threepute ($i,2,$j); $out = sin ($out * $pi * $threesult); $sound->[$i][$j] = $out; stepstatus; } } # #### 16 INTEGRAL if ($fun eq 'int') { $carrier = $ops->[$i][1][0]; $track = 0; $calcstyle = $ops->[$i][2][0]; $headroom = $ops->[$i][3][0]; for $j(0..$lenrateplus) { $track += $sound->[$carrier][$j] / $headroom; if ($track >= 1) {$track = 1}; if ($track <= -1) {$track = -1}; $sound->[$i][$j] = $track; stepstatus; } } # #### 17 DERIVATIVE if ($fun eq 'der') { $carrier = $ops->[$i][1][0]; $headroom = $ops->[$i][3][0]; for $j(0..$lenrateplus) { $sound->[$i][$j] = ($sound->[$carrier][$j] - $sound->[$carrier][$j - 1]) / $headroom; stepstatus; } } # #### CROSSOVER DISTORTION - 4/12/02 if ($fun eq 'cro') { $carrier = $ops->[$i][1][0]; for $j(0..$lenrateplus) { threepute ($i,2,$j); $crossdex = $threesult; $carriersound = $sound->[$carrier][$j]; if ($threesult < 1) { if (abs ($carriersound) <= (1 - $crossdex)) { $sound->[$i][$j] = 0; } else { # #### avoid divide-by-zero error if (!$crossdex) {$crossdex = .0001} $sound->[$i][$j] = (abs ($carriersound) - (1 - $crossdex)) * polar ($carriersound) / $crossdex; } } else { $sound->[$i][$j] = ($carriersound * (2 - $crossdex)) + (($crossdex - 1) * polar ($carriersound)); } stepstatus; } } # #### RAISE TO POWER - 4/12/02 if ($fun eq 'pow') { $carrier = $ops->[$i][1][0]; for $j(0..$lenrateplus) { $c = $sound->[$carrier][$j]; threepute ($i,2,$j); $d = (abs ($c) ** $threesult) * polar ($c); $sound->[$i][$j] = $d; stepstatus; } } # #### # #### MULTIPLE FILTERS # #### # #### BASIC MIXER - 4/18/02 i hate people who mow their laws at 8 pm if ($fun eq 'mix') { $numberofmods = $ops->[$i][98][0]; for $j(0..$lenrateplus) { $e = 0; for $k(1..$numberofmods) { $carriers[$k] = $ops->[$i][($k * 2) - 1][0]; } for $k(1..$numberofmods) { threepute ($i,$k * 2,$j); $e += $sound->[$carriers[$k]][$j] * $threesult; } $sound->[$i][$j] = $e; stepstatus; } if ($ops->[$i][98]) { normalize ($i,0); } } # #### 21 FREQUENCY MODULATION (if I can write this, I can write anything) # "What's going on here??" Brought to you by Anacin # $numberofmods is the number of modulators (1, 2, 3 ...) # $modutotal is a junk value, the sum total of the modulations # $modulayer is a junk ref to each modulator layer # $modudex is a junk ref to each modulator index # $forwardpos is a tally push used for forward-only modulation # $carrier is the reference to the carrier layer # $fmalg is the FM algorithm being used if ($fun eq 'fm') { $numberofmods = 0; $forwardpos = -1; # #### How many layers of modulation? put it into $numberofmods while ($ops->[$i][$numberofmods+2][0]) {$numberofmods = $numberofmods + 2} $numberofmods = $numberofmods / 2; print "Working with $numberofmods layer"; if ($numberofmods != 1) {print "s"}; print " of modulation, hope that's right\n"; $carrier = $ops->[$i][1][0]; $fmalg = $ops->[$i][99][0]; # #### Here we go... for $j(0..$lenrateplus) { $modutotal = 0; for $k(1..$numberofmods) { $modulayer = $ops->[$i][$k * 2][0]; # #### get the value: proc number, mindex, lengthrate position threepute ($i,($k * 2) + 1,$j); # #### compute the individual mindex $modudex = $threesult * $sound->[$modulayer][$j]; $modutotal = $modutotal + $modudex; } if ($fmalg == 1) { # #### This modulates too fast: constant shouldn't be 2, but anyway... $forwardpos = $forwardpos + (2 ** $modutotal); # #### for now, this line loops the carrier data when it runs out if ($forwardpos >= $lengthrate) { $forwardpos = $forwardpos % $lengthrate; } $sound->[$i][$j] = $sound->[$carrier][int ($forwardpos)]; } else { # #### the int() needs to act like a round() eventually (same above) $sound->[$i][$j] = $sound->[$carrier][int ($j + $modutotal)]; } stepstatus; } } # #### 22 RING MODULATION if ($fun eq 'ring') { $numofmods = 0; # #### How many layers of ring mod? put it in $numofmods while ($ops->[$i][$numofmods+1][0]) {$numofmods = $numofmods + 1;} print "Ring modding $numofmods layers, so fuckin' hang on a sec...\n"; for $j(0..$lenrateplus) { $b = 1; for $c(1..$numofmods) { $b = $b * $sound->[$ops->[$i][$c][0]][$j]; } $sound->[$i][$j] = $b; stepstatus; } } # #### POWER COMPARISON 6/2/02 if ($fun eq 'pc') { $mainstay = $ops->[$i][1][0]; $comparison = $ops->[$i][2][0]; # #### maximum of 50 times gain $mindifference = .02; for $j(0..$lenrateplus) { $g = $sound->[$mainstay][$j]; # $c = $sound->[$comparison][$j]; $difference = abs ($g - $sound->[$comparison][$j]); if ($difference < $mindifference) { $difference = $mindifference; } threepute ($i,3,$j); $power = $threesult; if ($difference < $power) { # $g *= $power / $difference; # #### variation $g /= $power * $difference; # #### crappy variation # $g = (($g + $c) / 2) + (polar ($g - $c) * $difference / 2); } $sound->[$i][$j] = $g; stepstatus; } normalize ($i,1); } # #### # #### LFO GENERATORS # #### # #### AMPLITUDE TRACKING - 4/10 and I'm still unemployed if ($fun eq 'amp') { $carrier = $ops->[$i][1][0]; # #### 440hz sustain $sustain = int ($samprate / 440); $sustaintally = $sustain; $track = 0; for $j(0..$lenrateplus) { $absound = abs ($sound->[$carrier][$j]); if ($absound > $track) { # #### reset the sustain value since it's going up again: $sustaintally = $sustain; threepute ($i,2,$j); $attack = $absound * (1 - ($threesult / $samprate)); if ($track + $attack > $track) { $track = $attack; } else { $track += $attack; } } elsif ($absound < $track) { if ($sustaintally) { $sustaintally -= 1; } else { threepute ($i,3,$j); $track -= ($threesult / $samprate); if ($track < 0) { $track = 0; } } } $sound->[$i][$j] = ($track * 2) - 1; stepstatus; } } # #### # #### GRANULAR WAVES # #### # #### 34 JIG-SINE is a silly name if ($fun eq 'jsi') { $numoffreqs = 0; $tally = 0; # #### How many frequencies to blarr together? put it in $numoffreqs while ($ops->[$i][$numoffreqs+1][0]) {$numoffreqs = $numoffreqs + 1;} $outputpos = 0; $polarity = 1; $leftover = 0; $lastfreq = 0; $activefreq = 0; $allowreps = $ops->[$i][99][0]; @freqlist = (); for $k(1..$numoffreqs) { $freqlist[$k] = $ops->[$i][$k][0]; } @freqlist = sort {$a <=> $b} @freqlist; print "Splicing everything together, so hold on tight...\n"; while ($outputpos < $lenrateplus) { $activefreq = $ops->[$i][int (rand() * $numoffreqs + 1)][0]; while ((!$allowreps) && ($activefreq == $lastfreq)) { $activefreq = $ops->[$i][int (rand() * $numoffreqs + 1)][0]; } $lastfreq = $activefreq; $stepforward = $activefreq / $samprate * 2 * $pi; threepute ($i,98,$outputpos); $modfactor = $threesult; $c = $freqlist[1] / $activefreq; # print $freqlist[1] . " " . $freqlist[2] . " " . $freqlist [3] . "\n"; # #### This line looks confusing, it's finding the amplitude of the individual # #### hump about to be rendered $modfactor = 1 - ((1 - $c) * (1 - $modfactor)); $forwardmarch = $samprate / $activefreq / 2; if ($leftover + $forwardmarch > int ($forwardmarch) + 1) { $forwardmarch = $forwardmarch - 1; } $forwardmarch = int ($forwardmarch); $leftover = $leftover * $stepforward; for $j($outputpos..$outputpos + $forwardmarch) { $sound->[$i][$j] = sin ($leftover) * $polarity * $modfactor; $leftover = $leftover + $stepforward; # print $modfactor . " " . $stepforward . "\n"; } $outputpos = $outputpos + $forwardmarch + 1; $leftover = ($leftover - $pi) / $stepforward; $polarity = $polarity * -1; renderstatus ($outputpos); } } # #### 35 JIG-COSINE is practically offensive to hear if ($fun eq 'jco') { $numoffreqs = 0; $tally = 0; # #### How many frequencies to blarr together? put it in $numoffreqs while ($ops->[$i][$numoffreqs+1][0]) {$numoffreqs = $numoffreqs + 1;} $outputpos = 0; $polarity = 1; $leftover = 0; $lastfreq = 0; $activefreq = 0; $allowreps = $ops->[$i][99][0]; @freqlist = (); for $k(1..$numoffreqs) { $freqlist[$k] = $ops->[$i][$k][0]; } @freqlist = sort {$a <=> $b} @freqlist; print "Splicing everything together, so hold on tight...\n"; while ($outputpos < $lenrateplus) { $activefreq = $ops->[$i][int (rand() * $numoffreqs + 1)][0]; while ((!$allowreps) && ($activefreq == $lastfreq)) { $activefreq = $ops->[$i][int (rand() * $numoffreqs + 1)][0]; } $lastfreq = $activefreq; $stepforward = $activefreq / $samprate * 2 * $pi; threepute ($i,99,$outputpos); $modfactor = $threesult; # print $freqlist[1] . " " . $freqlist[2] . " " . $freqlist [3] . "\n"; $forwardmarch = $samprate / $activefreq / 2; if ($leftover + $forwardmarch > int ($forwardmarch) + 1) { $forwardmarch = $forwardmarch - 1; } $forwardmarch = int ($forwardmarch); $leftover = $leftover * $stepforward; for $j($outputpos..$outputpos + $forwardmarch) { $sound->[$i][$j] = cos ($leftover) * $polarity; $leftover = $leftover + $stepforward; # print $modfactor . " " . $stepforward . "\n"; } $outputpos = $outputpos + $forwardmarch + 1; $leftover = ($leftover - $pi) / $stepforward; $polarity = $polarity * -1; renderstatus ($outputpos); } } # #### 36 SINE MOSAIC if ($fun eq 'mos') { $consecutive = $ops->[$i][99][0]; # #### How many slavefreqs? put it in $numoffreqs $numofslaves = 0; while ($ops->[$i][$numofslaves+2][0]) {$numofslaves = $numofslaves + 1;} @slavelist = (); for $k(1..$numofslaves) { $slavelist[$k] = $ops->[$i][$k+1][0]; } if (!$consecutive) { @slavelist = sort {$a <=> $b} @slavelist; } $outputpos = 0; $forwardmarch = 0; $sinposition = 0; $c = 1; $consecnum = 1; while ($outputpos < $lenrateplus) { # #### what will the slave freq be? if (!$consecutive) { while ($activeslave == $lastslave) { $activeslave = $slavelist[int (rand() * $numofslaves + 1)]; } $lastslave = $activeslave; } # #### sequential order of freq distribution else { $activeslave = $slavelist[$consecnum]; if ($consecnum == $numofslaves) { $consecnum = 1; } else { $consecnum ++; } } $stepforward = $activeslave / $samprate * 2 * $pi; # #### how far will slave freq run? # #### get the carrier freq value: proc number, 1 (freq), lengthrate position threepute ($i,1,$outputpos); $forwardmarch = $samprate / $threesult / 2; # #### are we between digital output points? $c = (1 - $c); if ($c) { $sinposition += $c * $stepforward; $forwardmarch -= $c; } # #### for this section, $outputpos is assumed to be an integer $endforward = int ($outputpos + $forwardmarch); for $j($outputpos..$endforward) { $sound->[$i][$j] = sin ($sinposition); # #### quit leaping forward if it's farther than $endforward; this entails # #### fractional crap to happen, as you shall see if ($j != $endforward) {$sinposition += $stepforward;} } # #### now it must adjust for leftover $forwardmarch $c = $forwardmarch - int ($forwardmarch); # #### does it even exist? if not, this will be taken care of next round # #### with the (1-$c) et al if ($c) { $sinposition += ($c * $stepforward); } $outputpos += int ($forwardmarch) + 1; renderstatus ($outputpos); } } # #### Magical 3D Terrain Mapper Bllaarrr 6/1/02 # func: 1, freq 2, x center 3, y center 4, radius 5, N 6 if ($fun eq 'ter') { $function = $ops->[$i][1][0]; $freqtrack = 0; $angle = 0; for $j(0..$lenrateplus) { threepute ($i,2,$j); $frequency = $threesult; threepute ($i,3,$j); $x = $threesult; threepute ($i,4,$j); $y = $threesult; threepute ($i,5,$j); $radius = $threesult; # threepute ($i,6,$j); # $n = $threesult; $y += sin ($freqtrack) * $radius; $x += cos ($freqtrack) * $radius; $r = sqrt (($x ** 2) + ($y ** 2)); $sound->[$i][$j] = eval ($function); $freqtrack += ($frequency / $samprate) * $pi; stepstatus; } dcoffset ($i); normalize ($i,.1); } # #### # #### GRANULAR FILTERS # #### # #### 31 WAVEMIRROR (first try) if ($fun eq 'mir') { $carrier = $ops->[$i][1][0]; $mirrorstyle = $ops->[$i][2][0]; $origpos = 0; $firstpolarity = polar ($sound->[$carrier][0]); if (!$firstpolarity) {$firstpolarity = 1}; $doublepolarity = 1; # #### There's probably a much more efficient way to do this, BUT, $switchpolar is for alternating up and down wave chunks when the mirror style is double, or nothing. Goddamn this thing is complicated. And the function of this thing is so simple, it's so ludicrous that the code is this bloated and enormous. One of these days I'll whip out some graph paper and logically boil down this whole algorithm into one expression or some shit. But for now. $switchpolar = 1; $outputpos = 0; while ($outputpos < $lenrateplus) { $shardsize = 0; $c = polar ($sound->[$carrier][$origpos]); while ((($c == $firstpolarity) || (!$c)) && ($outputpos < $lenrateplus)) { $g = $sound->[$carrier][$origpos] * $firstpolarity * $switchpolar; $sound->[$i][$outputpos] = $g; # #### don't bother making shards if style is 'nothing' if ($mirrorstyle != 4) {$shard[$shardsize] = $g;} $origpos ++; $shardsize ++; $outputpos ++; $c = polar ($sound->[$carrier][$origpos]); } if ($mirrorstyle != 4) { # #### determine starting position for repeat of shard if ($mirrorstyle == 2) {$shardpos = $shardsize} elsif ($mirrorstyle == 3) { $shardpos = -2; $doublepolarity = $switchpolar; } else {$shardpos = -1} # #### now, finally, repeat the shard for $j(1..$shardsize) { if ($mirrorstyle == 2) {$shardpos = $shardpos - 1} elsif ($mirrorstyle == 3) { $shardpos = $shardpos + 2; if ($shardpos >= $shardsize) { $shardpos = 1; $doublepolarity = $doublepolarity * -1; } } else {$shardpos ++} $sound->[$i][$outputpos] = $shard[$shardpos] * -1 * $doublepolarity * $switchpolar; $outputpos ++; } $doublepolarity = $doublepolarity * -1; } # #### if mirrorstyle is 4, just skip some dead space and move on else { $outputpos += $shardsize; } if ($mirrorstyle >= 3) { $switchpolar = $switchpolar * -1; } $firstpolarity = $firstpolarity * -1; renderstatus ($outputpos); } } # #### 15 ANDY'S STAMMER EFFECT if ($fun eq 'stam') { $carrier = $ops->[$i][1][0]; $stamposition = 0; $stamlength = 0; $stampostally = 1; for $j(0..$lenrateplus) { if ($stampostally > $stamlength) { threepute ($i,2,$j); $stamposition = int ($threesult * $samprate); threepute ($i,3,$j); $stamlength = $samprate / $threesult; $stampostally = 0; renderstatus ($j); } $sound->[$i][$j] = $sound->[$carrier][$stamposition]; $stamposition ++; $stampostally ++; } } # #### ORIGINAL STAMMER ALGORITHM: # $c = $ops->[$i][1][0]; # $f = $ops->[$i][2][0]; # $f = $samprate / $f * $pi; # $e = 0; # $g = 0; # until ($e >= $lenrateplus) { # $sound->[$i][$e] = $sound->[$c][$g]; # $e = $e + 1; # $g = $g + 1; # if ($g >= $f) { # threepute ($i,3,$e); # $f = $f + ($samprate / $threesult * $pi) # $g = 0; # renderstatus ($e); # } #} #} # #### 32 GRANULAR PHASE FLIPPING if ($fun eq 'flip') { $carrier = $ops->[$i][1][0]; $origpos = 0; $firstpolarity = polar ($sound->[$carrier][0]); if (!$firstpolarity) {$firstpolarity = 1}; $outputpos = 0; while ($outputpos < $lenrateplus) { $shardsize = 0; $c = polar ($sound->[$carrier][$origpos]); while ((($c == $firstpolarity) || (!$c)) && ($origpos < $lenrateplus)) { $shard[$shardsize] = $sound->[$carrier][$origpos]; $origpos ++; $shardsize ++; $c = polar ($sound->[$carrier][$origpos]); } for $j(1..$shardsize) { $sound->[$i][$outputpos] = $shard[$shardsize - $j]; $outputpos ++; } $firstpolarity = $firstpolarity * -1; renderstatus ($outputpos); } } # #### 33 ABNORMALIZER if ($fun eq 'abn') { $carrier = $ops->[$i][1][0]; $origpos = 0; $outputpos = 0; $flip = $ops->[$i][3][0]; # #### -36 db noisefloor: $noisefloor = 1 / 2 / 2 / 2 / 2 / 2 / 2; # #### no noisefloor adjustment: # $noisefloor = 0; while ($realoutpos < $lenrateplus) { # #### get the value: proc number, mindex, time where shard occurs threepute ($i,2,int ($realoutpos)); # #### protection line against frequency = 0 and what have you: if ($threesult < 1) {$threesult = 1} $shardsize = $samprate / $threesult; $outputpos = int ($realoutpos); $endoutpos = int ($realoutpos + $shardsize); $normconstant = 0; for $j($outputpos..$endoutpos) { $a = abs ( $sound->[$carrier][$j] ); if ($a > abs ( $normconstant) ) { if ($flip) { $normconstant = $sound->[$carrier][$j]; } else { $normconstant = $a; } } } if ($normconstant < $noisefloor) { if ($flip) { $normconstant = polar ($normconstant); } else { $normconstant = 1; } } # #### avoid goddamn 32-bit digital clipping: $normconstant = $normconstant * 1.01; # #### no division by zero: if ($normconstant) { for $j($outputpos..$endoutpos) { $sound->[$i][$j] = $sound->[$carrier][$j] / $normconstant; } } $realoutpos = $realoutpos + $shardsize; renderstatus ($realoutpos); } } # #### FRACTALIZER - written 4/12/02 (still unemployed, yes) if ($fun eq 'frac') { $carrier = $ops->[$i][1][0]; $logtrigger = ($ops->[$i][3][0]) - 1; # #### fucked-up way to get the render to start from 0 $truebegin = -.0001; $beginshard = 0; while ($beginshard < $lenrateplus) { threepute ($i,2,$beginshard); $shardlength = $threesult; if (!$shardlength) { # ### automatically determine shard size here } else { # #### change the frequency into sample length $shardlength = $samprate / $shardlength; } $beginshard = int ($truebegin) + 1; $endshard = int ($truebegin + $shardlength); $intlength = int ($shardlength); for $j($beginshard..$endshard) { # #### optimization: the first shard sample will always copy the original... if ($j == $beginshard) { $sound->[$i][$j] = $sound->[$carrier][$j]; } else { threepute ($i,4,$j); $fracdex = $threesult; $intdex = int ($fracdex); $modulodex = ($fracdex - $intdex); for $k(0..1) { if ($logtrigger) { # ### logarithmic steps: (0, 1, 2, 3) becomes 1, 2, 4, 8 $c = (2 ** ($intdex + $k)) * ($j - $beginshard); } else { # ### linear steps: 1, 2, 3, 4 $c = ($intdex + $k) * ($j - $beginshard); } $d = $c % $intlength; $fracbetween[$k] = $sound->[$carrier][$beginshard + $d]; } $sound->[$i][$j] = ($modulodex * $fracbetween[1]) + ((1 - $modulodex) * $fracbetween[0]); } } $truebegin = $truebegin + $shardlength; renderstatus ($truebegin); } } # #### PITCHED STAMMER 6-14-02 (damn these groin muscles) if ($fun eq 'ps') { $carrier = $ops->[$i][1][0]; $origpos = 0; $outputpos = 0; $lastpitch = 44100; $lastshardstart = 0; $lastshardlength = 1; # #### Noisefloor is 30 db $noisefloor = 1 / (2 ** 5); # #### first sample must be positive, so screw you: wait no it doesn't # while ($sound->[$carrier][$origpos] < 0) {$origpos ++;} while (($outputpos <= $lenrateplus) && ($origpos <= $lenrateplus)) { $polartoggle = 0; $shardlength = 0; $lastpolar = polar ($sound->[$carrier][$origpos]); threepute ($i,3,$outputpos); $minlen = $samprate / $threesult; until ( ( ($polartoggle >= 2) && (($polartoggle / 2) == int ($polartoggle / 2)) && ($shardlength >= $minlen) # #### comment this line for horrible discontinuous good time && ($zerotoggle) ) || ($origpos + $shardlength > $lenrateplus) ) { $g = polar ($sound->[$carrier][$origpos + $shardlength]); $zerotoggle = 0; # #### make sure polarity 0 doesn't count: (($g) if (($g) && ($g != $lastpolar)) { $polartoggle ++; $lastpolar = $g; $zerotoggle = 1; } $shardlength ++; } $shardpitch = $samprate / $shardlength; threepute ($i,2,$outputpos); $pitchtolerance = 2 ** ($threesult / 12); $pitchcompare = abs ($shardpitch / $lastpitch); if ($pitchcompare < 1) {$pitchcompare = 1 / $pitchcompare}; # #### pitches close enough? repeat the bastard if ($pitchcompare <= $pitchtolerance) { $repeats ++; threepute ($i,4,$outputpos); if ($repeats >= $threesult) {$lastpitch = 44100; $repeats = 0} } # #### pitches not close enough? there is a new king in town baby else { $lastshardstart = $origpos; $lastshardlength = $shardlength; $lastpitch = $pitchcompare; } $origpos += $shardlength; # #### now actually transfer the appropriate chunk: $d = 0; # #### repeat the shard if not far enough along, avoid evil time loss while (!$d) { $lastshardstartjunk = $lastshardstart; for (0..$lastshardlength) { $sound->[$i][$outputpos] = $sound->[$carrier][$lastshardstartjunk]; $outputpos ++; $lastshardstartjunk ++; } if ($outputpos >= $origpos) {$d = 1}; } renderstatus ($outputpos); } } # #### # #### ADDITIVE SYNTHESIS # #### # #### SHIMMER-SINE - 4/14/02, DO NOT DWELL ON THE PAIN if ($fun eq 'shim') { $numoffreqs = $ops->[$i][98][0]; print "$tab Working with $numoffreqs frequenc"; if ($numoffreqs == 1) {print "y"} else {print "ies"}; print "...\n"; for $k(1..$numoffreqs) { # #### Next couple lines are a phase-alteration thing to get waves to # #### resemble saws and squares more closely threepute ($i,$k,0); # #### according to AbSynth, this equation is pre-computed to pi: # #### phase alteration on the 64th harmonic $freqpos[$k] = ($threesult * (-.015726 / 64)); # #### This is the boring plain version that may or may not be better: $freqpos[$k] = 0; $freqamp[$k] = -1; } $lengthhalf = $lengthrate / 2; $ampcontrol = $ops->[$i][96][0]; for $j(0..$lenrateplus) { # #### first get the base freq threepute ($i,97,$j); $basefreq = $threesult; # #### now get the shimrate threepute ($i,99,$j); $shimratestep = $threesult / $lengthhalf; # #### and the exponent for amp control threepute ($i,95,$j); $poweramp = $threesult; for $freqnumber(1..$numoffreqs) { threepute ($i,$freqnumber,$j); $overtone = $threesult; # #### first version: linear freqamp, second is loga if (!$ampcontrol) { $freqamp[$freqnumber] += $shimratestep * $overtone; } else { $freqamp[$freqnumber] += $shimratestep * (2 ** ($overtone - 1)); } # print (2 ** ($overtone - 1)) . "\n"; while ($freqamp[$freqnumber] > 1) { $freqamp[$freqnumber] -= 2; } $freqpos[$freqnumber] += ($overtone * $basefreq) / $samprate * 2 * $pi; # #### the output sound is: frequency data, * volume, * sawtooth-like # #### volume adjustment (higher partials have less energy), to half of # #### fundamental # #### 2 + (1 / overtone) should be 1 + ... if 'realism' desired # #### ------------------------------------ # #### More notes: the 5 + 3 thing is the golden section $sound->[$i][$j] += sin ($freqpos[$freqnumber]) * ((abs ($freqamp[$freqnumber])) ** $poweramp) * (5 + (3 / $overtone)); } stepstatus; } # #### normalize: the layer, then the minimum normalization ratio normalize ($i,1); } # #### ZERO-CROSS VERB - 4/17/02 halo is a rockin game if ($fun eq 'zv') { $carrier = $ops->[$i][1][0]; # #### this is the polarity thing, flops from 1 to -1. Renders positive waves # #### first, then negative ones: for ($polarflop = 1; $polarflop >= -1; $polarflop -= 2) { print "$tab Now verbing "; if ($polarflop == 1) { print "positive"; } else { print "negative"; } print " wave crests, stand by...\n"; $tally = .1; $stepstat = 0; $origpos = 0; $lastcross = 0; # #### this big if statement is for when the sound data doesn't start with # #### the desired polarity: it has to calculate the true starting place if (polar ($sound->[$carrier][0]) != $polarflop) { $junktally = 0; while ($lastcross == 0) { if (polar ($sound->[$carrier][$junktally + 1]) == $polarflop) { $f = abs ($sound->[$carrier][$junktally]); $g = abs ($sound->[$carrier][$junktally + 1]); $lastcross = $junktally + ($f / ($f + $g)); $origpos = $junktally + 1; } else { $junktally ++; } } } $amplitude = 0; # #### this is where the actual render starts while ($origpos <= $lenrateplus) { $origsound = $sound->[$carrier][$origpos]; if (polar ($origsound) == $polarflop) { if (abs ($origsound) > $amplitude) { $amplitude = abs ($origsound); } if (polar ($sound->[$carrier][$origpos + 1]) != $polarflop) { $f = abs ($origsound); $g = abs ($sound->[$carrier][$origpos + 1]); $newcross = $origpos + ($f / ($f + $g)); $frequency = $samprate / ($newcross - $lastcross); # #### determine how long the tail will last threepute ($i,2,$origpos); $decayconstant = $amplitude; $decaydenom = 0; $decayrate = (1 / $samprate) * (1 / $threesult); # #### determine the particular pitch threepute ($i,3,$origpos); $frequency = $frequency * $threesult; # #### no goddamn subsonic pitches cuz of yer wankin dc offset if (($frequency >= 50) && ($frequency <= $samprate / 2)) { $stepforward = $frequency / $samprate * 2 * $pi; $sineposition = 0; $sinerenderpos = $origpos; while (($amplitude > 0.01) && ($sinerenderpos <= $lenrateplus)) { $sound->[$i][$sinerenderpos] += (sin ($sineposition) * $amplitude * $polarflop); $sineposition += $stepforward; $decaydenom += $decayrate; $amplitude = $decayconstant / (2 ** $decaydenom); $sinerenderpos ++; } } $amplitude = 0; $lastcross = $newcross; renderstatus ($origpos); } } $origpos ++; } } normalize ($i,.1); } print "\n\t\t * COMPLETE *\n"; $timestamp = (time - $timestamp); print "\t\t * RENDER TIME: $timestamp seconds *\n"; if ($ops->[$i][100][0]) { $krap = $ops->[$i][100][0]; print "$tab Saving routine goes here\n"; open (OUT, ">$krap"); # #### AIFF FORMAT fucker print OUT "FORM"; # header form length $doublerate = ($lengthrate * 2) - 8; $byte1 = ($doublerate & 0xff000000) >> 24; $byte2 = ($doublerate & 0x00ff0000) >> 16; $byte3 = ($doublerate & 0x0000ff00) >> 8; $byte4 = ($doublerate & 0x000000ff); print OUT chr($byte1),chr($byte2),chr($byte3),chr($byte4); print OUT "AIFFCOMM"; print OUT chr(0) x 3, chr(18); print OUT chr(0), chr(1); # header comm frame $doublerate = (($lengthrate * 2) - 40) / 2; $byte1 = ($doublerate & 0xff000000) >> 24; $byte2 = ($doublerate & 0x00ff0000) >> 16; $byte3 = ($doublerate & 0x0000ff00) >> 8; $byte4 = ($doublerate & 0x000000ff); print OUT chr($byte1),chr($byte2),chr($byte3),chr($byte4); print OUT chr(0), chr(16); print OUT chr(64), chr(14), chr(172), chr(68); print OUT chr(0) x 6; print OUT "SSND"; # header ssnd length $doublerate = ($lengthrate * 2) - 40; $byte1 = ($doublerate & 0xff000000) >> 24; $byte2 = ($doublerate & 0x00ff0000) >> 16; $byte3 = ($doublerate & 0x0000ff00) >> 8; $byte4 = ($doublerate & 0x000000ff); print OUT chr($byte1),chr($byte2),chr($byte3),chr($byte4); print OUT chr(0) x 8; for $j(0..$lengthrate) { $rawsound = $sound->[$i][$j]; # #### 127.999 because otherwise $rawsound=1 becomes full negative when multiplied, and yer square waves disappear UTTERLY and you get digital clipping and crap like that AURGH $rawsound = $rawsound * 127.999; # #### to avoid horrible things like -8.9270512436029e-06 duuhh awesome, perl if (abs ($rawsound) < .0001) {$rawsound = 0}; # #### Unsigned data adjustment, or whatever it is: if ($rawsound < 0) {$rawsound = $rawsound + 256;} $byte1 = int($rawsound); $byte2 = int(($rawsound - $byte1) * 256); print OUT chr($byte1),chr($byte2); # #### Obnoxious beta-testing text spew: # print "$byte1,$byte2\t"; } close (OUT); print "$tab Aww yeah! Saved its azz\n"; } # #### END OF POSITIVE PROCESS ROUTINE print "\n\n"; } # #### NEXT $I } hline ('.'); hline ('!'); hline ('!'); hline ('!'); print "\t\tAll done!! Thank you for flying Filterchrist.\n"; hline ('!'); hline ('!'); hline ('!'); hline ('='); print "\tLENGTH: $lengthsecs seconds\n"; print "\tPROCESSES:\n"; procspit; hline ('='); print "\n"; undef *sound; exit 0;