Re: ??? Huh!

From: Michael J McGonagle (fndsnd@earthlink.net)
Date: Sun Mar 12 2000 - 20:41:41 EST


> 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