> Great ... hopefully you've found the last bug in dynamic instruments,
> but if not just let me know --
Well, it would appear that something is still amiss with dynamic instr's.
I have made some changes to the fractal piano piece so that it produces
longer (60 seconds) output files. Somewhere about 36 seconds into all of the
tests that I have run, things start to fall apart. It sounds like notes are
droping out.
I did rewrite my instr that generates the notes so that it is generating
them at the krate instead of the original irate. This does not seem to help.
I also bumped up MAXDNOTES to 512, it only delayed the drop out.
I attached the the score, orchestra, and fractal files that I am using. You
will need to put these into the sfront/examples/elpelele folder to get the
other needed files.
Thanks,
Mike
// elpelele.saol
// "El Pelele, E. Granados", MIDI: R. Finley, Piano: E. Scheirer
// Originally written by Eric Scheirer
// Modified by John Lazzaro
// song length: 8 minutes, 50.192 seconds (530.192 seconds)
//
// Modified by Mike McGonagle (3/6/00) all changes are marked
// 3/6 - added fractal table - "algo" instr's are stored in other
// files and appended to this file. the instr info is derived
// from the fractal. there is a "do-nothing" sasl score for
// processing purposes only, it is not part of the score.
// changing the external fractal changes the performance.
// if you change the output from sfront to use a truly "random"
// seed, each performance (or run of the program) will be different.
//
global {
interp 0;
srate 44100;
krate 441; // changed from 1000 - mjm
ksig rvb_on, distance;
outchannels 2;
// added fractal table -mjm
table fractalx(sample, -1, "fractalx.aif");
table fractaly(sample, -1, "fractaly.aif");
table A0(sample, - 1, "samp_1.aif");
table C2(sample, - 1, "samp_3.aif");
table F2(sample, - 1, "samp_5.aif");
table Ds3(sample, - 1, "samp_7.aif");
table Cs4(sample, - 1, "samp_9.aif");
table Fs4(sample, - 1, "samp_11.aif");
table B4(sample, - 1, "samp_13.aif");
route (dry, piano);
// change "large_room" to "small_room" or "schroeder"
// for alternative reverbs
send (large_room; 0.650000, 1; dry);
route (wet, large_room);
send (mix;; dry, wet);
}
//
// instr piano
//
// sample player of global tables
//
instr piano (pitch, vel) preset 0 {
ivar cps, scale, t, l, b, cut;
ksig kamp, localtime, segment, first;
asig samp;
// selects sample based on midi numbers
table pitchmap(step, - 1, 0, 0, 28, 1, 38, 2, 46, 3, 55, 4, 64, 5, 69, 6, 200);
// bogus loop points -- samples are long enough w/o looping
table loop(data, - 1, 197584, 151848, 137124, 132915, 104285, 59648, 50773);
// base frequency for each table
table base(data, - 1, 21, 36, 41, 51, 61, 66, 71);
imports exports table A0, C2, F2, Ds3, Cs4, Fs4, B4;
// pno[] indexed by pitchmap values
tablemap pno (A0, C2, F2, Ds3, Cs4, Fs4, B4);
if (! first) {
segment = 1;
first = 1;
}
// i-rate -- starting parameters for note
pitch = pitch - 12;
t = tableread (pitchmap, pitch);
l = tableread (loop, t);
b = cpsmidi (tableread (base, t));
cps = cpsmidi (pitch);
scale = (vel / 128) * (vel / 128) / 2;
// k-rate -- note envelope
localtime = localtime + 1 / k_rate;
if (segment == 1) {
if (localtime < 0.010000) {
kamp = kline (0, 0.010000, scale);
}
else {
segment = 2;
}
}
if (segment == 2) {
kamp = scale;
if (localtime > 5.000000) {
segment = 4;
turnoff;
}
}
if (released && segment < 3) {
if (MIDIctrl[64] > 15) {
segment = 3;
extend (5.000000 - localtime);
}
else {
segment = 4;
localtime = 0;
extend (0.100000);
}
}
if (segment == 3) {
if (MIDIctrl[64] <= 15) {
segment = 4;
localtime = 0;
}
else {
kamp = scale;
if (localtime >= 5.000000) {
turnoff;
}
}
}
if (segment == 4) {
kamp = var_kline(scale, 0.100000, 0);
if (localtime >= 0.100000) {
turnoff;
}
}
// a-rate
samp = kamp * loscil(pno [ t ], cps, b, l);
output (samp * (1 - (pitch / 100)), samp * pitch / 100);
}
//
// opcode var_kline -- helper routine for piano
//
kopcode var_kline(ksig st, ksig t, ksig e) {
ksig ltime, val;
val = ltime / t * (e - st) + st;
ltime = ltime + 1 / k_rate;
return (val);
}
//
// instr large_room
//
// used in default settings
//
instr large_room (revgain, distance) {
asig first;
ivar f, lpf_pos, lpf_cut, d2;
asig out[2];
table sections (data, - 1, 1, 10, 43, 44, 164, 165, 242);
table gains(data, - 1, 0.300000, 0.300000, 0.500000, 0.250000, 0.500000, 0.250000, 0.250000);
table lengths (data, - 1, 8, 12, 87, 62, 120, 76, 30);
table outs(data, - 1, 26, 161, 290);
table outg(data, - 1, 0.340000, 0.140000, 0.140000);
ksig num_sec, num_out;
// i-rate
lpf_pos = 295;
lpf_cut= 2600;
d2 = distance * distance;
// k-rate
num_sec= ftlen (sections);
num_out = ftlen (outs);
// a-rate
out = gen_allpass(sections, num_sec, gains, lengths, outs, num_out, outg,
lpf_pos, lpf_cut, 1 / 1000, revgain);
output ((input[0]/ d2 + out[0]) * distance, (input[1]/ d2 + out[1]) * distance);
}
//
// gen_allpass -- where *_room reverb gets computed
//
// uses fracdelay as a reverberation engine
//
aopcode gen_allpass(table sections, ksig num_sec, table gains,
table lengths, table outs, ksig num_out,
table outg, ivar lpf_pos, ivar lpf_cut, ivar f, ivar revgain) {
oparray fracdelay[1];
asig first, outl, outr, p1, p2, g, tap1, tap2, i, fb, sum;
// initializes fracdelat as a 300ms tapped line
if (! first && input[0]) {
fracdelay[0](1, 0.300000);
first = 1;
}
if (first) {
// recirculate delay taps through line
i = 0;
while (i < num_sec) {
p1 = tableread (sections, i) * f;
p2 = floor (p1 + tableread (lengths, i) * f);
g = tableread (gains, i);
tap1 = fracdelay[0](2, p1); // read tap
fracdelay[0](4, p2, tap1 * - g); // add back in
tap2 = fracdelay[0](2, p2); // read tap
fracdelay[0](4, p1, tap2 * g); // add back in
i = i + 1;
}
// compute new output
outl = 0;
outr = 0;
i = 0;
while (i < num_out) {
p1 = tableread (outs, i) * f;
g = tableread (outg, i);
outl = outl + fracdelay[0](2, p1) * g;
outr = outr + fracdelay[0](2, p1 + pow (- 1, i) * f) * g;
i = i + 1;
}
p1 = lpf_pos * f;
tap1 = fracdelay[0](2, p1);
fb = lopass (tap1, lpf_cut) * revgain;
i = 0;
// compute new input into line
sum = 0;
while (i < 2) {
sum = sum + input [ i ];
i = i + 1;
}
// insert new input, then shift
fracdelay[0](3, 0, sum + fb);
fracdelay[0](5);
return (outl, outr);
}
else {
return (0, 0);
}
}
//
// instr mix
//
// mixes reverb and direct sound equally
//
instr mix () {
asig out[2];
out[0] = input[0]*1 + input[1]*0 + input[2]*1 + input[3]*0;
out[1] = input[0]*0 + input[1]*1 + input[2]*0 + input[3]*1;
output(out);
}
//
// instr small_room
//
// alternative reverb, uses gen_allpass as engine
//
instr small_room (revgain) {
asig first;
ivar f, lpf_pos, lpf_cut, d2;
asig out[2];
table sections (data, - 1, 24, 25, 48, 61, 62);
table gains (data, - 1, 0.300000, 0.400000, 0.600000,
0.100000, 0.400000);
table lengths (data, - 1, 35, 22, 8.300000, 66, 30);
table outs (data, - 1, 60, 129);
table outg (data, - 1, 0.500000, 0.500000);
ksig num_sec, num_out;
// i-rate
lpf_pos = 128;
lpf_cut = 4200;
num_sec= ftlen (sections);
num_out = ftlen (outs);
// k-rate
out = gen_allpass(sections, num_sec, gains, lengths, outs, num_out,
outg, lpf_pos, lpf_cut, 1 / 1000, revgain);
output (out);
}
//
// instr schroeder
//
// alternative reverb, uses comb and allpass sections
//
instr schroeder (rt) {
ksig first, ki, d2;
asig in, ap1, ap2;
asig c[4];
asig outL, outR;
ivar t[4], revgain[4], i;
table timeconst (data, 5, 0.030000, 0.034300, 0.039300,
0.045000, 0.000000);
imports exports ksig rvb_on, distance;
oparray comb [4];
in = input[0]+ input[1];
if (first == 0) {
rvb_on = 1;
first = 1;
distance = 0.600000;
}
d2 = distance * distance;
i = 0;
while (i < 4) {
t [ i ] = tableread (timeconst, i);
revgain [ i ] = combgain (t [ i ], rt);
i = i + 1;
}
if (rvb_on) {
ap1 = allpass (in / distance, 0.001700, 0.700000);
ap2 = allpass (ap1, 0.005000, 0.700000);
c[0]= comb (ap2, t[0], revgain[0]);
c[1]= comb (ap2, t[1], revgain[1]);
c[2]= comb (ap2, t[2], revgain[2]);
c[3]= comb (ap2, t[3], revgain[3]);
outL = (c[0]+ c[1]+ c[2]+ c[3]) / 4;
outR = (c[0]- c[1]+ c[2]- c[3]) / 4;
output ((input[0]/ d2 + outL) * distance * 0.750000,
(input[1]/ d2 + outR) * distance * 0.750000);
}
else {
output (input);
}
}
//
// opcode combgain
//
// helper routine for schroeder
//
opcode combgain (xsig t, xsig rt) {
xsig temp;
temp = exp (log (10) * - 3 * t / rt);
return (temp);
}
// indexer is used to step thru a fractal table, it is primarily
// expected to be used as a k-rate opcode, but it is a xrate
// opcode to allow 'init' to be set from an irate var.
opcode indexer(xsig init) {
xsig inited, control;
if (inited == 0) {
inited = 1;
control = init;
} else {
control = control + 1;
}
return(control);
}
// in is expected to be in the range of -1..1 (as this is
// intended to be a table-helper)
opcode scalevalue(xsig in, xsig lo, xsig hi) {
return((((in * .5) + .5) * (hi - lo)) + lo);
}
// this "score" is expected to include the file "elpelele.saol".
// it also depends on the external aif file that contains the
// fractal data (or what ever you what to use).
// frac_points calls piano. the parameters that are generated are:
//
// the input is:
//
// iterations - controls the number of events generated.
// frac_index - this is the point at which to start
// extracting data from the fractal
// onset_lo - low onset limit
// onset_hi - high onset limit
// dur_lo - low duration limit
// dur_hi - high duration limit
// freq_lo - low frequency limit
// freq_hi - high frequency limit
// amp_lo - low amplitude limit
// amp_hi - high amplitude limit
//
// this instr expects to have its duration set to -1
instr frac_points(count, frac_index, iterations,
onset_lo, onset_hi, dur_lo, dur_hi,
freq_lo, freq_hi, amp_lo, amp_hi) {
ksig counter, onset_time, duration, pitch, amp;
imports table fractalx;
imports table fractaly;
// irate (this has none)
// krate
if (onset_time <= itime) {
pitch = int(scalevalue(tableread(fractalx, indexer(frac_index)), freq_lo, freq_hi));
amp = scalevalue(tableread(fractaly, indexer(frac_index)), amp_lo, amp_hi);
duration = scalevalue(tableread(fractaly, indexer(frac_index + 1)), dur_lo, dur_hi);
instr piano(0, duration, pitch, amp);
onset_time = onset_time +
scalevalue(tableread(fractalx, indexer(frac_index + 1)), onset_lo, onset_hi);
counter = counter + 1;
if (counter >= iterations) {
instr frac_perpetual(0, -1, frac_index + iterations, count - 1);
turnoff;
}
}
}
instr frac_perpetual(index, count) {
ivar iterations, onset_lo, onset_hi, dur_lo, dur_hi, freq_lo, freq_hi, amp_lo, amp_hi;
imports table fractalx, fractaly;
if (count > 0) {
iterations = int(scalevalue(tableread(fractalx, index), 25, 125));
onset_lo = scalevalue(tableread(fractalx, index + 1), .125, .25);
onset_hi = onset_lo + scalevalue(tableread(fractaly, index + 1), 0, .25);
dur_lo = scalevalue(tableread(fractalx, index + 2), .125, .75);
dur_hi = dur_lo + scalevalue(tableread(fractaly, index + 2), 0, .75);
freq_lo = int(scalevalue(tableread(fractalx, index + 3), 24, 48));
freq_hi = freq_lo + int(scalevalue(tableread(fractaly, index + 3), 0, 48));
amp_lo = scalevalue(tableread(fractalx, index + 4), 12, 64);
amp_hi = amp_lo + scalevalue(tableread(fractaly, index + 4), 0, 56);
// idump(count, index, iterations, onset_lo, onset_hi, dur_lo, dur_hi, freq_lo, freq_hi, amp_lo, amp_hi);
instr frac_points(0, -1, count, index, iterations, onset_lo, onset_hi, dur_lo, dur_hi, freq_lo, freq_hi, amp_lo, amp_hi);
}
}
0 frac_points -1 1 1000 1000 .125 .125 .125 .25 24 72 0 127
120 end
This archive was generated by hypermail 2b29 : Mon Jan 28 2002 - 12:03:53 EST