Using Perl as the RTcmix Command-Language Interface
The default RTcmix application (invoked by the
CMIX
command) uses the included scorefile language
Minc.
However, if you configure the build of RTcmix for Perl support
using the --with-perl flag
(see the
installation guide
for information about this),
then compiling RTcmix will make a Perl-enabled command
(PCMIX)
that has a Perl parser as the 'front-end' instead of Minc.
Using Perl/RTcmix
To use Perl with RTcmix, write a Perl script with the following
statement at the top:
Then use any Perl statements and any of the function calls you
would use in an RTcmix Minc script. Run the script with the
command PCMIX (instead of CMIX).
Now, whenever a PCMIX script uses a function name unknown to Perl,
Perl will pass the function and its arguments to RTcmix. If it's
unknown to RTcmix, then RTcmix will give its usual error message
about it and continue processing the script.
This means that any RTcmix functions loaded into a script (with
the load command) will work, even if these belong to an instrument
not part of the distribution source tree.
Some Minc functions have the same names as internal Perl functions.
In general, Perl versions take precedence over RTcmix versions, with
the following exceptions:
If your script uses these names, you'll get the RTcmix versions.
If you want to use the Perl versions, you must use the CORE::
prefix, like this:
CORE::srand(4);
$foo = CORE::rand(99);
If you want to use the other RTcmix functions whose names collide
with Perl ones, then you must use the RT:: prefix., like this:
The only such functions that you could possibly care about are
print, splice and open. But who wouldn't want to use the Perl
print instead of the RTcmix one?
Sample Scorefiles
A simple
WAVETABLE
Perl script:
use RT;
print "\nWelcome to the Perl front end to RTcmix!\n\n";
rtsetparams(44100, 1);
load("WAVETABLE");
setline(0,0, 1,1, 4,1, 5,0);
makegen(2, 10, 1000, 1, 0.3, 0.2);
$start = 0;
$dur = 0.7;
$amp = 15000;
$freq = 7.00;
for ($i = 0; $i < 5; $i++) {
WAVETABLE($start, $dur, $amp, $freq);
$start += 0.5;
$amp -= 2000;
$freq += 0.07;
}
Another
WAVETABLE
Perl script:
# This is a translation of sample_scos_1.0/WAVETABLE3.sco into Perl. -JGG
use RT;
rtsetparams(44100, 2);
load("WAVETABLE");
print_off();
makegen(1, 24, 1000, 0, 1, 950, 0);
makegen(2, 10, 1000, 1, 0.3, 0.2);
srand(0.35);
for ($start = 0; $start < 7; $start += 0.14) {
$freq = (random() * 200) + 35;
for ($i = 0; $i < 3; $i += 1) {
WAVETABLE($start, 0.4, 1500, $freq, 0);
WAVETABLE($start + random()*0.1, 0.4, 1500, $freq + (random()*7), 1);
if ($start > 3.5) {
makegen(2, 10, 1000, 1, random(), random(), random(), random(),
random(), random(), random(), random(), random(), random(),
random());
}
$freq += 125;
}
}
Perl script showing the RTcmix ability to chain several
instruments together:
# Quick translation of sample_scos_3.0/LONGCHAIN_1.sco to Perl, for testing.
# This score makes a wavetable synth riff and feeds it through 3 effects
# in series: flange -> delay -> reverb
use RT;
print_off();
rtsetparams(44100, 2);
load("WAVETABLE");
load("FLANGE");
load("JDELAY");
load("REVERBIT");
bus_config("WAVETABLE", "aux 0-1 out");
bus_config("FLANGE", "aux 0-1 in", "aux 10-11 out");
bus_config("JDELAY", "aux 10-11 in", "aux 4-5 out");
bus_config("REVERBIT", "aux 4-5 in", "out 0-1");
$totdur = 30;
$masteramp = 1.0;
$atk = 2; $dcy = 4;
$numnotes = makegen(3, 2, 99,
5.00, 5.001, 5.02, 5.03, 5.05, 5.07, 5.069, 5.10, 6.00);
$transposition = 2.00; # try 7.00 also, for some cool aliasing...
srand(2);
# ---------------------------------------------------------------- synth ---
$notedur = .10;
$incr = $notedur + .015;
$maxampdb = 92;
$minampdb = 75;
$ampdiff = $maxampdb - $minampdb;
control_rate(20000); # need high control rate for short synth notes
setline(0,0, 1,1, 20,0);
makegen(2, 10, 10000, 1, .9, .7, .5, .3, .2, .1, .05, .02);
for ($st = 0; $st < $totdur; $st += $incr) {
$slot = random() * $numnotes;
$pitch = pchoct(octpch(sampfunc(3, $slot)) + octpch($transposition));
$amp = ampdb($minampdb + ($ampdiff * random()));
WAVETABLE($st, $notedur, $amp, $pitch, $pctleft=random());
}
# for the rest
control_rate(500);
$amp = $masteramp;
# --------------------------------------------------------------- flange ---
$resonance = 0.3;
$lowpitch = 5.00;
$moddepth = 90;
$modspeed = 0.08;
$wetdrymix = 0.5;
$flangetype = 0;
$gensize = 100000;
makegen(2,10,$gensize, 1);
$maxdelay = 1.0 / cpspch($lowpitch);
setline(0,1,1,1);
FLANGE($st=0, $insk=0, $totdur, $amp, $resonance, $maxdelay, $moddepth,
$modspeed, $wetdrymix, $flangetype, $inchan=0, $pctleft=1);
$lowpitch += .07;
$maxdelay = 1.0 / cpspch($lowpitch);
makegen(2,9,$gensize, 1,1,-180);
FLANGE($st=0, $insk=0, $totdur, $amp, $resonance, $maxdelay, $moddepth,
$modspeed, $wetdrymix, $flangetype, $inchan=1, $pctleft=0);
# ---------------------------------------------------------------- delay ---
$deltime = $notedur * 2.2;
$regen = 0.70;
$wetdry = 0.12;
$cutoff = 0;
$ringdur = 2.0;
setline(0,0, $atk,1, $totdur-$dcy,1, $totdur,0);
JDELAY($st=0, $insk=0, $totdur, $amp, $deltime, $regen, $ringdur, $cutoff,
$wetdry, $inchan=0, $pctleft=1);
JDELAY($st=0.02, $insk=0, $totdur, $amp, $deltime, $regen, $ringdur, $cutoff,
$wetdry, $inchan=1, $pctleft=0);
# --------------------------------------------------------------- reverb ---
$revtime = 1.0;
$revpct = .3;
$rtchandel = .05;
$cf = 0;
setline(0,1, 1,1);
REVERBIT($st=0, $insk=0, $totdur+$ringdur, $amp, $revtime, $revpct,
$rtchandel, $cf);
# john gibson, 17-june-00
FInally, a Perl script invoking a number of simultaneous notes:
# Illustrates using a function to play one note consisting of
# multiple RTcmix notes.
use RT;
rtsetparams(44100, 2);
load("WAVETABLE");
# Set to 1 to write a sound file (if processor too slow for rt playback).
$writeit = 0;
if ($writeit) {
set_option("audio_off", "clobber_on");
rtoutput("/tmp/bell.aiff");
}
# just a sine wave (try extra harmonics for more complex bell sound)
makegen(2, 10, 5000, 1);
# exponential amplitude envelope
makegen(1, 5, 1000, 1, 1000, .0005);
# individual bell notes
# start dur amp freq
bell(0, 5.0, 4000, 1000);
bell(3, 8.0, 5000, 1200);
bell(6, 12.0, 3000, 800);
# bell notes in a loop (needs fast processor for real time playback)
$incr = 0.1;
for ($st = 10; $st < 20; $st += $incr) {
$freq = (random() * 1000) + 400;
bell($st, 8, 2000, $freq);
$incr += 0.2;
}
# Play one bell note. Parameters are start time, duration, amplitude,
# and fundamental frequency. (Based on description of Risset's bell
# instrument in the Dodge book.)
sub bell () {
my($start, $dur, $amp, $freq) = @_;
my $pan;
print "fundamental frequency: $freq\n";
WAVETABLE($start, $dur, $amp, $freq * .56, $pan=1);
WAVETABLE($start, $dur * .9, $amp * .67, $freq * .56 + 1, $pan=0);
WAVETABLE($start, $dur * .65, $amp, $freq * .92, $pan=.9);
WAVETABLE($start, $dur * .55, $amp * 1.8, $freq * .92 + 1.7, $pan=.1);
WAVETABLE($start, $dur * .325, $amp * 2.67, $freq * 1.19, $pan=.8);
WAVETABLE($start, $dur * .35, $amp * 1.67, $freq * 1.7, $pan=.2);
WAVETABLE($start, $dur * .25, $amp * 1.46, $freq * 2, $pan=.7);
WAVETABLE($start, $dur * .2, $amp * 1.33, $freq * 2.74, $pan=.3);
WAVETABLE($start, $dur * .15, $amp * 1.33, $freq * 3, $pan=.6);
WAVETABLE($start, $dur * .1, $amp, $freq * 3.76, $pan=.4);
WAVETABLE($start, $dur * .075, $amp * 1.33, $freq * 4.07, $pan=.5);
}
# [scorefile by John Gibson]
|