1# clm-ins.rb -- CLM instruments translated to Snd/Ruby
2
3# Translator: Michael Scholz <mi-scholz@users.sourceforge.net>
4# Created: 03/09/16 01:27:09
5# Changed: 14/11/28 02:16:54
6
7# Instruments work with
8#   with_sound (CLM (sample2file gens) and Snd)
9#   with_dac   (dac output, except at least for fullmix)
10#
11# Tested with Snd 15.x and Ruby 2.x.x
12
13# pluck                  reson
14# vox                    cellon
15# fofins                 jl_reverb
16# fm_trumpet             gran_synth
17# pqw_vox                touch_tone
18# stereo_flute           spectra
19# fm_bell                two_tab
20# fm_insect              lbj_piano
21# fm_drum                resflt
22# gong                   scratch
23# attract                pins
24# pqw                    zc
25# tubebell               zn
26# wurley                 za
27# rhodey                 clm_expsrc     exp_snd
28# hammondoid             expfil
29# metal                  graph_eq
30# drone                  anoi
31# canter                 fullmix
32# nrev                   grani
33#
34#  class Ssb_fm < Musgen
35#   initialize(freq)
36#   inspect
37#   to_s
38#   run_func(val1, val2)
39#   ssb_fm(modsig)
40
41# bes_fm(start, dur, freq, amp, ratio, index)
42#
43# make_ssb_fm(freq)
44# ssb_fm?(obj)
45# ssb_fm(gen, modsig)
46#
47# class Fm2 < Musgen
48#  initialize(f1, f2, f3, f4, p1, p2, p3, p4)
49#  inspect
50#  to_s
51#  run_func(val1, val2)
52#  fm2(index)
53#
54# make_fm2(f1, f2, f3, f4, p1, p2, p3, p4)
55# fm2?(obj)
56# fm2(gen, index)
57
58# comments from clm-ins.scm
59
60$now = 0.0
61
62require "ws"
63require "spectr"
64require "env"
65include Math
66with_silence do
67  require "matrix"
68end
69
70def normalize_partials(partials)
71  sum = 0.0
72  parts = partials.dup
73  len = parts.length
74  1.step(len - 1, 2) do |i|
75    sum += parts[i].abs
76  end
77  1.step(len - 1, 2) do |i|
78    parts[i] /= sum
79  end
80  parts
81end unless defined? normalize_partials
82
83# violin is defined as an example in ws.rb
84def violin_test(start = 0.0, dur = 1.0)
85  violin(start, dur, 440, 0.5)
86  $now = start + dur + 0.2
87end
88
89require "v"
90
91# fm_violin is defined in v.rb
92def fm_violin_test(start = 0.0, dur = 1.0)
93  fm_violin(start, dur, 440, 0.5)
94  $now = start + dur + 0.2
95end
96
97# PLUCK
98#
99# The Karplus-Strong algorithm as extended by David Jaffe and Julius
100#  Smith -- see Jaffe and Smith, "Extensions of the Karplus-Strong
101#  Plucked-String Algorithm" CMJ vol 7 no 2 Summer 1983, reprinted in
102#  "The Music Machine".  translated from CLM's pluck.ins
103add_help(:pluck,
104         "pluck(start, dur, freq, amp, weighting, lossfact)  \
105Implements the Jaffe-Smith plucked string physical model.
106WEIGHTING is the ratio of the once-delayed to the twice-delayed samples.  \
107It defaults to 0.5=shortest decay.
108Anything other than 0.5 = longer decay.  \
109Must be between 0 and less than 1.0.
110LOSSFACT can be used to shorten decays.  \
111Most useful values are between 0.8 and 1.0. pluck(0, 1, 330, 0.3, 0.95, 0.95)")
112def pluck(start, dur, freq, amp, weighting = 0.5, lossfact = 0.9)
113  get_optimum_c = lambda do |s, o, p|
114    pa = (1.0 / o) * atan2(s * sin(o), (1.0 - s) + s * cos(o))
115    tmp_int = (p - pa).floor
116    pc = p - pa - tmp_int
117    until pc >= 0.1
118      tmp_int -= 1
119      pc += 1.0
120    end
121    [tmp_int, (sin(o) - sin(o * pc)) / sin(o + o * pc)]
122  end
123  tune_it = lambda do |f, s1|
124    p = @srate / f
125    s = s1.zero? ? 0.5 : s1
126    o = hz2radians(f)
127    t1, c1 = get_optimum_c.call(s, o, p)
128    t2, c2 = get_optimum_c.call(1.0 - s, o, p)
129    if s != 0.5 and c1.abs < c2.abs
130      [1.0 - s, c1, t1]
131    else
132      [s, c2, t2]
133    end
134  end
135  wt0, c, dlen = tune_it.call(freq, weighting)
136  lf = lossfact.zero? ? 1.0 : [1.0, lossfact].min
137  wt = wt0.zero? ? 0.5 : [1.0, wt0].min
138  tab = make_vct(dlen)
139  # get initial waveform in "tab" -- here we can introduce 0's to
140  # simulate different pick positions, and so on -- see the CMJ
141  # article for numerous extensions.  The normal case is to load it
142  # with white noise (between -1 and 1).
143  allp = make_one_zero(lf * (1.0 - wt), lf * wt)
144  feedb = make_one_zero(c, 1.0)     # or feedb = make_one_zero(1.0, c)
145  dlen.times do |i|
146    tab[i] = 1.0 - random(2.0)
147  end
148  run_instrument(start, dur) do
149    val = tab.clm_cycle
150    tab[tab.clm_cycle_index] = (1.0 - c) * one_zero(feedb, one_zero(allp, val))
151    amp * val
152  end
153end
154
155def pluck_test(start = 0.0, dur = 1.0)
156  pluck(start, dur, 330, 0.3, 0.95, 0.95)
157  $now = start + dur + 0.2
158end
159
160# formant center frequencies for a male speaker (vox and pqw_vox)
161Formants = {
162  :I  => [390, 1990, 2550], :E   => [530, 1840, 2480], :AE => [660, 1720, 2410],
163  :UH => [520, 1190, 2390], :A   => [730, 1090, 2440], :OW => [570,  840, 2410],
164  :U  => [440, 1020, 2240], :OO  => [300,  870, 2240], :ER => [490, 1350, 1690],
165  :W  => [300,  610, 2200], :LL  => [380,  880, 2575], :R  => [420, 1300, 1600],
166  :Y  => [300, 2200, 3065], :EE  => [260, 3500, 3800], :LH => [280, 1450, 1600],
167  :L  => [300, 1300, 3000], :I2  => [350, 2300, 3340], :B  => [200,  800, 1750],
168  :D  => [300, 1700, 2600], :G   => [250, 1350, 2000], :M  => [280,  900, 2200],
169  :N  => [280, 1700, 2600], :NG  => [280, 2300, 2750], :P  => [300,  800, 1750],
170  :T  => [200, 1700, 2600], :K   => [350, 1350, 2000], :F  => [175,  900, 4400],
171  :TH => [200, 1400, 2200], :S   => [200, 1300, 2500], :SH => [200, 1800, 2000],
172  :V  => [175, 1100, 2400], :THE => [200, 1600, 2200], :Z  => [200, 1300, 2500],
173  :ZH => [175, 1800, 2000], :ZZ  => [900, 2400, 3800], :VV => [565, 1045, 2400]}
174
175# MLBVOI
176#
177# translation from MUS10 of Marc LeBrun's waveshaping voice instrument
178# (using FM here) this version translated (and simplified slightly)
179# from CLM's mlbvoi.ins
180def vox(start, dur, freq, amp, ampfun, freqfun, freqscl, voxfun, index, vibscl)
181  f1 = []
182  f2 = []
183  f3 = []
184  (voxfun.length - 1).step(1, -2) do |i|
185    phon = Formants[voxfun[i]]
186    x = voxfun[i - 1]
187    f1.unshift(phon[0])
188    f1.unshift(x)
189    f2.unshift(phon[1])
190    f2.unshift(x)
191    f3.unshift(phon[2])
192    f3.unshift(x)
193  end
194  car_os = make_oscil(:frequency, 0)
195  of0 = make_oscil(:frequency, 0)
196  of1 = make_oscil(:frequency, 0)
197  of2 = make_oscil(:frequency, 0)
198  of3 = make_oscil(:frequency, 0)
199  of4 = make_oscil(:frequency, 0)
200  of5 = make_oscil(:frequency, 0)
201  ampf = make_env(:envelope, ampfun, :scaler, amp, :duration, dur)
202  frmf1 = make_env(:envelope, f1, :duration, dur)
203  frmf2 = make_env(:envelope, f2, :duration, dur)
204  frmf3 = make_env(:envelope, f3, :duration, dur)
205  freqf = make_env(:envelope, freqfun, :duration, dur, :scaler, freqscl * freq, :offset, freq)
206  per_vib = make_triangle_wave(:frequency, 6, :amplitude, freq * vibscl)
207  ran_vib = make_rand_interp(:frequency, 20, :amplitude, freq * 0.01)
208  run_instrument(start, dur) do
209    frq = env(freqf) + triangle_wave(per_vib) + rand_interp(ran_vib)
210    car = index * oscil(car_os, hz2radians(frq))
211    frm = env(frmf1)
212    frm0 = frm / frq.to_f
213    frm_int = frm0.floor
214    if frm_int.even?
215      frq0 = hz2radians(frm_int * frq)
216      frq1 = hz2radians((frm_int + 1) * frq)
217      amp1 = frm0 - frm_int
218      amp0 = 1.0 - amp1
219    else
220      frq1 = hz2radians(frm_int * frq)
221      frq0 = hz2radians((frm_int + 1) * frq)
222      amp0 = frm0 - frm_int
223      amp1 = 1.0 - amp0
224    end
225    frm = env(frmf2)
226    frm0 = frm / frq.to_f
227    frm_int = frm0.floor
228    if frm_int.even?
229      frq2 = hz2radians(frm_int * frq)
230      frq3 = hz2radians((frm_int + 1) * frq)
231      amp3 = frm0 - frm_int
232      amp2 = 1.0 - amp3
233    else
234      frq3 = hz2radians(frm_int * frq)
235      frq2 = hz2radians((frm_int + 1) * frq)
236      amp2 = frm0 - frm_int
237      amp3 = 1.0 - amp2
238    end
239    frm = env(frmf3)
240    frm0 = frm / frq.to_f
241    frm_int = frm0.floor
242    if frm_int.even?
243      frq4 = hz2radians(frm_int * frq)
244      frq5 = hz2radians((frm_int + 1) * frq)
245      amp5 = frm0 - frm_int
246      amp4 = 1.0 - amp5
247    else
248      frq5 = hz2radians(frm_int * frq)
249      frq4 = hz2radians((frm_int + 1) * frq)
250      amp4 = frm0 - frm_int
251      amp5 = 1.0 - amp4
252    end
253    env(ampf) * (0.8 * (amp0 * oscil(of0, frq0 + 0.2 * car) +
254                        amp1 * oscil(of1, frq1 + 0.2 * car)) +
255                        0.15 * (amp2 * oscil(of2, frq2 + 0.5 * car) +
256                                amp3 * oscil(of3, frq3 + 0.5 * car)) +
257                                0.05 * (amp4 * oscil(of4, frq4 + car) +
258                                        amp5 * oscil(of5, frq5 + car)))
259  end
260end
261
262def vox_test(start = 0.0, dur = 1.0)
263  amp_env = [0, 0, 25, 1, 75, 1, 100, 0]
264  frq_env = [0, 0, 5, 0.5, 10, 0, 100, 1]
265  examp1 = [0, :E, 25, :AE, 35, :ER, 65, :ER, 75, :I, 100, :UH]
266  examp2 = [0, :I, 5, :OW, 10, :I, 50, :AE, 100, :OO]
267
268  $now = start
269  vox($now, dur, 170, 0.4, amp_env, frq_env, 0.1, examp1, 0.05, 0.1)
270  $now += dur + 0.2
271  vox($now, dur, 300, 0.4, amp_env, frq_env, 0.1, examp2, 0.02, 0.1)
272  $now += dur + 0.2
273  vox($now, 5, 600, 0.4, amp_env, frq_env, 0.1, examp2, 0.01, 0.1)
274  $now += 5.0 + 0.2
275end
276
277# FOF example
278add_help(:fofins,
279         "fofins(beg, dur, frq, amp, vib, f0, a0, f1, a1, \
280f2, a2, ae=[0, 0, 25, 1, 75, 1, 100, 0])  \
281Produces FOF synthesis: \
282fofins(0, 1, 270, 0.2, 0.001, 730, 0.6, 1090, 0.3, 2440, 0.1)")
283def fofins(start, dur, frq, amp, vib, f0, a0, f1, a1, f2, a2,
284           ae = [0, 0, 25, 1, 75, 1, 100,0])
285  ampf = make_env(:envelope, ae, :scaler, amp, :duration, dur)
286  frq0 = hz2radians(f0)
287  frq1 = hz2radians(f1)
288  frq2 = hz2radians(f2)
289  foflen = @srate == 22050.0 ? 100 : 200
290  vibr = make_oscil(:frequency, 6)
291  win_freq = TWO_PI / foflen
292  wt0 = make_wave_train(:size, foflen, :frequency, frq)
293  foftab = mus_data(wt0)
294  foflen.times do |i|
295    foftab[i] = (a0 * sin(i * frq0) + a1 * sin(i * frq1) +
296                     a2 * sin(i * frq2)) * 0.5 * (1.0 - cos(i * win_freq))
297  end
298  run_instrument(start, dur) do
299    env(ampf) * wave_train(wt0, vib * oscil(vibr))
300  end
301end
302
303def fofins_test(start = 0.0, dur = 1.0)
304  fofins(start, dur, 270, 0.2, 0.001, 730, 0.6, 1090, 0.3, 2440, 0.1)
305  $now = start + dur + 0.2
306end
307
308# FM TRUMPET
309#
310# Dexter Morrill's FM-trumpet: from CMJ feb 77 p51
311def fm_trumpet(start, dur, *args)
312  frq1, frq2, amp1, amp2, ampatt1, ampdec1, ampatt2, ampdec2 = nil
313  modfrq1, modind11, modind12, modfrq2, modind21, modind22 = nil
314  rvibamp, rvibfrq, vibamp, vibfrq, vibatt, vibdec = nil
315  frqskw, frqatt, ampenv1, ampenv2 = nil
316  indenv1, indenv2, degree, distance, reverb_amount = nil
317  optkey(args, binding,
318         [:frq1, 250.0],
319         [:frq2, 1500.0],
320         [:amp1, 0.5],
321         [:amp2, 0.1],
322         [:ampatt1, 0.03],
323         [:ampdec1, 0.35],
324         [:ampatt2, 0.03],
325         [:ampdec2, 0.3],
326         [:modfrq1, 250.0],
327         [:modind11, 0.0],
328         [:modind12, 2.66],
329         [:modfrq2, 250.0],
330         [:modind21, 0.0],
331         [:modind22, 1.8],
332         [:rvibamp, 0.007],
333         [:rvibfrq, 125.0],
334         [:vibamp, 0.007],
335         [:vibfrq, 7.0],
336         [:vibatt, 0.6],
337         [:vibdec, 0.2],
338         [:frqskw, 0.03],
339         [:frqatt, 0.06],
340         [:ampenv1, [0, 0, 25, 1, 75, 0.9, 100, 0]],
341         [:ampenv2, [0, 0, 25, 1, 75, 0.9, 100, 0]],
342         [:indenv1, [0, 0, 25, 1, 75, 0.9, 100, 0]],
343         [:indenv2, [0, 0, 25, 1, 75, 0.9, 100, 0]],
344         [:degree, 0.0],
345         [:distance, 1.0],
346         [:reverb_amount, 0.005])
347  dur = dur.to_f
348  per_vib_f = make_env(:envelope,
349                       stretch_envelope([0, 1, 25, 0.1, 75, 0, 100, 0],
350                                        25,
351                                        [100 * (vibatt / dur), 45].min,
352                                        75,
353                                        [100 * (1.0 - vibdec / dur), 55].max),
354                       :scaler, vibamp, :duration, dur)
355
356  ran_vib = make_rand_interp(:frequency, rvibfrq, :amplitude, rvibamp)
357  per_vib = make_oscil(:frequency, vibfrq)
358  dec_01 = [75, 100 * (1.0 - 0.01 / dur)].max
359  frq_f = make_env(:envelope,
360                   stretch_envelope([0, 0, 25, 1, 75, 1, 100, 0],
361                                    25,
362                                    [25, 100 * (frqatt / dur)].min,
363                                    75,
364                                    dec_01),
365                   :scaler, frqskw, :duration, dur)
366  ampattpt1 = [25, 100 * (ampatt1 / dur)].min
367  ampdecpt1 = [75, 100 * (1.0 - ampdec1 / dur)].max
368  ampattpt2 = [25, 100 * (ampatt2 / dur)].min
369  ampdecpt2 = [75, 100 * (1.0 - ampdec2 / dur)].max
370  mod1_f = make_env(:envelope,
371                    stretch_envelope(indenv1, 25, ampattpt1, 75, dec_01),
372                    :scaler, modfrq1 * (modind12 - modind11), :duration, dur)
373  mod1 = make_oscil(:frequency, 0.0)
374  car1 = make_oscil(:frequency, 0.0)
375  # set frequency to zero here because it is handled multiplicatively below
376  car1_f = make_env(:envelope,
377                    stretch_envelope(ampenv1, 25, ampattpt1, 75, ampdecpt1),
378                    :scaler, amp1, :duration, dur)
379  mod2_f = make_env(:envelope,
380                    stretch_envelope(indenv2, 25, ampattpt2, 75, dec_01),
381                    :scaler, modfrq2 * (modind22 - modind21), :duration, dur)
382  mod2 = make_oscil(:frequency, 0.0)
383  car2 = make_oscil(:frequency, 0.0)
384  car2_f = make_env(:envelope,
385                    stretch_envelope(ampenv2, 25, ampattpt2, 75, ampdecpt2),
386                    :scaler, amp2, :duration, dur)
387  run_instrument(start, dur,
388                 :degree, degree,
389                 :distance, distance,
390                 :reverb_amount, reverb_amount) do
391    frq_change = hz2radians((1.0 +
392                             rand_interp(ran_vib)) *
393                             (1.0 + env(per_vib_f) *
394                              oscil(per_vib)) *
395                              (1.0 + env(frq_f)))
396    env(car1_f) *
397      oscil(car1, frq_change *
398            (frq1 + env(mod1_f) * oscil(mod1, modfrq1 * frq_change))) +
399      env(car2_f) *
400      oscil(car2, frq_change *
401            (frq2 + env(mod2_f) * oscil(mod2, modfrq2 * frq_change)))
402  end
403end
404
405def fm_trumpet_test(start = 0.0, dur = 1.0)
406  fm_trumpet(start, dur)
407  $now = start + dur + 0.2
408end
409
410# PQWVOX
411#
412# translation of CLM pqwvox.ins (itself translated from MUS10 of MLB's
413# waveshaping voice instrument (using phase quadrature waveshaping))
414add_help(:pqw_vox,
415         "pqw_vox(start, dur, freq, spacing_freq, \
416amp, ampfun, freqfun, freqscl, phonemes, formant_amps, formant_shapes)  \
417Produces vocal sounds using phase quadrature waveshaping.")
418def pqw_vox(start, dur, freq, spacing_freq, amp, ampfun, freqfun, freqscl,
419            phonemes, formant_amps, formant_shapes)
420  vox_fun = lambda do |phons, which, newenv|
421    # make an envelope from which entry of phoneme data referred to by phons
422    if phons.empty?
423      newenv
424    else
425      vox_fun.call(phons[2..-1],
426                   which, newenv + [phons[0], Formants[phons[1]][which]])
427    end
428  end
429  car_sin = make_oscil(:frequency, 0.0)
430  car_cos = make_oscil(:frequency, 0.0, :initial_phase, HALF_PI)
431  frq_ratio = spacing_freq / freq.to_f
432  fs = formant_amps.length
433  sin_evens = Array.new(fs)
434  cos_evens = Array.new(fs)
435  sin_odds = Array.new(fs)
436  cos_odds = Array.new(fs)
437  amps = Array.new(fs)
438  frmfs = Array.new(fs)
439  sin_coeffs = Array.new(fs)
440  cos_coeffs = Array.new(fs)
441  ampf = make_env(:envelope, ampfun, :scaler, amp, :duration, dur)
442  freqf = make_env(:envelope, freqfun, :scaler, freqscl * freq,
443                   :duration, dur, :offset, freq)
444  per_vib = make_triangle_wave(:frequency, 6.0, :amplitude, freq * 0.1)
445  ran_vib = make_rand_interp(:frequency, 20.0, :amplitude, freq * 0.05)
446  fs.times do |i|
447    sin_evens[i] = make_oscil(:frequency, 0.0)
448    sin_odds[i] = make_oscil(:frequency, 0.0)
449    cos_evens[i] = make_oscil(:frequency, 0.0, :initial_phase, HALF_PI)
450    cos_odds[i] = make_oscil(:frequency, 0.0, :initial_phase, HALF_PI)
451    amps[i] = formant_amps[i]
452    shape = normalize_partials(formant_shapes[i])
453    cos_coeffs[i] = partials2polynomial(shape, 1)
454    sin_coeffs[i] = partials2polynomial(shape, 0)
455    frmfs[i] = make_env(:envelope, vox_fun.call(phonemes, i, []),
456                        :duration, dur)
457  end
458  run_instrument(start, dur) do
459    frq = env(freqf) + triangle_wave(per_vib) + rand_interp(ran_vib)
460    frqscl = hz2radians(frq * frq_ratio)
461    carsin = oscil(car_sin, frqscl)
462    carcos = oscil(car_cos, frqscl)
463    sum = 0.0
464    fs.times do |j|
465      frm = env(frmfs[j])
466      frm0 = frm / frq
467      frm_int = frm0.floor
468      if frm_int.even?
469        even_freq = hz2radians(frm_int * frq)
470        odd_freq = hz2radians((frm_int + 1.0) * frq)
471        odd_amp = frm0 - frm_int
472        even_amp = 1.0 - odd_amp
473      else
474        odd_freq = hz2radians(frm_int * frq)
475        even_freq = hz2radians((frm_int + 1.0) * frq)
476        even_amp = frm0 - frm_int
477        odd_amp = 1.0 - even_amp
478      end
479      fax = polynomial(cos_coeffs[j], carcos)
480      yfax = carsin * polynomial(sin_coeffs[j], carcos)
481      sum = sum + amps[j] *
482        (even_amp * (yfax * oscil(sin_evens[j], even_freq) -
483                     fax * oscil(cos_evens[j], even_freq)) +
484                     odd_amp * (yfax * oscil(sin_odds[j], odd_freq) -
485                                fax * oscil(cos_odds[j], odd_freq)))
486    end
487    env(ampf) * sum
488  end
489end
490
491def pqw_vox_test(start = 0.0, dur = 1.0)
492  ampfun = [0, 0, 50, 1, 100, 0]
493  freqfun = [0, 0, 100, 0]
494  freqramp = [0, 0, 100, 1]
495  sh1 = [[1, 1, 2, 0.5],
496    [1, 0.5, 2, 0.5, 3, 1],
497    [1, 1, 4, 0.5]]
498  sh2 = [[1, 1, 2, 0.5],
499    [1, 1, 2, 0.5, 3, 0.2, 4, 0.1],
500    [1, 1, 3, 0.1, 4, 0.5]]
501  sh3 = [[1, 1, 2, 0.5],
502    [1, 1, 4, 0.1],
503    [1, 1, 2, 0.1, 4, 0.05]]
504  sh4 = [[1, 1, 2, 0.5, 3, 0.1, 4, 0.01],
505    [1, 1, 4, 0.1],
506    [1, 1, 2, 0.1, 4, 0.05]]
507
508  $now = start
509  pqw_vox($now, dur, 300, 300, 0.5, ampfun, freqfun, 0.0,
510          [0, :L, 100, :L], [0.33, 0.33, 0.33], sh1)
511  $now += dur + 0.2
512  pqw_vox($now, dur, 200, 200, 0.1, ampfun, freqramp, 0.1,
513          [0, :UH, 100, :ER], [0.8, 0.15, 0.05], sh2)
514  $now += dur + 0.2
515  pqw_vox($now, dur, 100, 314, 0.1, ampfun, freqramp, 0.1,
516          [0, :UH, 100, :ER], [0.8, 0.15, 0.05], sh2)
517  $now += dur + 0.2
518  pqw_vox($now, dur, 200, 314, 0.1, ampfun, freqramp, 0.01,
519          [0, :UH, 100, :ER], [0.8, 0.15, 0.05], sh3)
520  $now += dur + 0.2
521  pqw_vox($now, dur, 100, 414, 0.2, ampfun, freqramp, 0.01,
522          [0, :OW, 50, :E, 100, :ER], [0.8, 0.15, 0.05], sh4)
523  $now += dur + 0.2
524end
525
526# STEREO-FLUTE
527# slightly simplified [MS]
528add_help(:stereo_flute,
529        "stereo_flute(start, dur, freq, flow, *key_args)
530 :flow_envelope   = [0, 1, 100, 1]
531 :decay           = 0.01
532 :noise           = 0.0356
533 :embouchure_size = 0.5
534 :fbk_scl1        = 0.5
535 :fbk_scl2        = 0.55
536 :out_scl         = 1.0
537 :a0              = 0.7
538 :b1              = -0.3
539 :vib_rate        = 5
540 :vib_amount      = 0.03
541 :ran_rate        = 5
542 :ran_amount      = 0.03
543is a physical model of a flute: \
544stereo_flute(0, 1, 440, 0.55, :flow_envelope, [0, 0, 1, 1, 2, 1, 3, 0])")
545def stereo_flute(start, dur, freq, flow, *args)
546  flow_envelope, decay, noise, embouchure_size = nil
547  fbk_scl1, fbk_scl2, out_scl = nil
548  a0, b1, vib_rate, vib_amount, ran_rate, ran_amount = nil
549  optkey(args, binding,
550         [:flow_envelope, [0, 1, 100, 1]],
551         [:decay, 0.01],   # additional time for instrument to decay
552         [:noise, 0.0356],
553         [:embouchure_size, 0.5],
554         [:fbk_scl1, 0.5], # these two are crucial for good results
555         [:fbk_scl2, 0.55],
556         [:out_scl, 1.0],
557         [:a0, 0.7],       # filter coefficients
558         [:b1, -0.3],
559         [:vib_rate, 5],
560         [:vib_amount, 0.03],
561         [:ran_rate, 5],
562         [:ran_amount, 0.03])
563  flowf = make_env(:envelope, flow_envelope, :scaler, flow,
564                   :length, seconds2samples(dur - decay))
565  periodic_vib = make_oscil(:frequency, vib_rate)
566  ran_vib = make_rand_interp(:frequency, ran_rate)
567  breath = make_rand(:frequency, @srate / 2.0, :amplitude, 1)
568  period_samples = (@srate / freq).floor
569  embouchure_samples = (embouchure_size * period_samples).floor
570  embouchure = make_delay(embouchure_samples, :initial_element, 0.0)
571  bore = make_delay(period_samples)
572  reflection_lp_filter = make_one_pole(a0, b1)
573  out_sig = current_diff = previous_out_sig = previous_dc_blocked_a = 0.0
574  run_instrument(start, dur) do
575    delay_sig = delay(bore, out_sig)
576    emb_sig = delay(embouchure, current_diff)
577    current_flow = vib_amount * oscil(periodic_vib) +
578      ran_amount * rand_interp(ran_vib) + env(flowf)
579    current_diff = (current_flow + noise * current_flow * rand(breath)) +
580      fbk_scl1 * delay_sig
581    current_exitation = emb_sig - emb_sig * emb_sig * emb_sig
582    out_sig = one_pole(reflection_lp_filter,
583                       current_exitation + fbk_scl2 * delay_sig)
584    # NB the DC blocker is not in the cicuit. It is applied to the
585    # out_sig but the result is not fed back into the system.
586    dc_blocked_a = (out_sig - previous_out_sig) + 0.995 * previous_dc_blocked_a
587    previous_out_sig = out_sig
588    previous_dc_blocked_a = dc_blocked_a
589    out_scl * dc_blocked_a
590  end
591end
592
593def flute_test(start = 0.0, dur = 1.0)
594  stereo_flute(start, dur, 440, 0.55, :flow_envelope, [0, 0, 1, 1, 2, 1, 3, 0])
595  $now = start + dur + 0.2
596end
597
598# FM-BELL
599add_help(:fm_bell,
600         "fm_bell(startime, dur, frequency, amplitude, \
601amp-env=[...], index_env=[...], index=1.0)  \
602Mixes in one fm bell note." )
603def fm_bell(start, dur, freq, amp,
604            amp_env = [0, 0, 0.1, 1, 10, 0.6, 25, 0.3,
605              50, 0.15, 90, 0.1, 100, 0],
606            index_env = [0, 1, 2, 1.1, 25, 0.75, 75, 0.5, 100, 0.2],
607            index = 1.0)
608  fm_ind1 = hz2radians(32.0 * freq)
609  fm_ind2 = hz2radians(4.0 * (8.0 - freq / 50.0))
610  fm_ind3 = fm_ind2 * 0.705 * (1.4 - freq / 250.0)
611  fm_ind4 = hz2radians(32.0 * (20.0 - freq / 20.0))
612  mod1 = make_oscil(:frequency, freq * 2.0)
613  mod2 = make_oscil(:frequency, freq * 1.41)
614  mod3 = make_oscil(:frequency, freq * 2.82)
615  mod4 = make_oscil(:frequency, freq * 2.4)
616  car1 = make_oscil(:frequency, freq)
617  car2 = make_oscil(:frequency, freq)
618  car3 = make_oscil(:frequency, freq * 2.4)
619  indf = make_env(:envelope, index_env, :scaler, index, :duration, dur)
620  ampf = make_env(:envelope, amp_env, :scaler, amp, :duration, dur)
621  run_instrument(start, dur) do
622    fmenv = env(indf)
623    env(ampf) *
624      (oscil(car1, fmenv * fm_ind1 * oscil(mod1)) +
625       0.15 *
626       oscil(car2, fmenv * (fm_ind2 * oscil(mod2) + fm_ind3 * oscil(mod3))) +
627       0.15 *
628       oscil(car3, fmenv * fm_ind4 * oscil(mod4)))
629  end
630end
631
632def fm_bell_test(start = 0.0, dur = 1.0)
633  fm_bell(start, dur, 440, 0.5)
634  $now = start + dur + 0.2
635end
636
637# FM-INSECT
638def fm_insect(start, dur, freq, amp, amp_env,
639              mod_freq, mod_skew, mod_freq_env, mod_index, mod_index_env,
640              fm_index, fm_ratio, *args)
641  degree, distance, reverb_amount = nil
642  optkey(args, binding,
643         [:degree, 0.0],
644         [:distance, 1.0],
645         [:reverb_amount, 0.005])
646  carrier = make_oscil(:frequency, freq)
647  fm1_osc = make_oscil(:frequency, mod_freq)
648  fm2_osc = make_oscil(:frequency, fm_ratio * freq)
649  ampf = make_env(:envelope, amp_env, :scaler, amp, :duration, dur)
650  indf = make_env(:envelope, mod_index_env,
651                  :scaler, hz2radians(mod_index),
652                  :duration, dur)
653  modfrqf = make_env(:envelope, mod_freq_env,
654                     :scaler, hz2radians(mod_skew),
655                     :duration, dur)
656  fm2_amp = hz2radians(fm_index * fm_ratio * freq)
657  run_instrument(start, dur,
658                 :degree, degree,
659                 :distance, distance,
660                 :reverb_amount, reverb_amount) do
661    garble_in = env(indf) * oscil(fm1_osc, env(modfrqf))
662    garble_out = fm2_amp * oscil(fm2_osc, garble_in)
663    env(ampf) * oscil(carrier, garble_out + garble_in)
664  end
665end
666
667def fm_insect_test(start = 0.0, dur = 1.0)
668  locust = [0, 0, 40, 1, 95, 1, 100, 0.5]
669  bug_hi = [0, 1, 25, 0.7, 75, 0.78, 100, 1]
670  amp = [0, 0, 25, 1, 75, 0.7, 100, 0]
671
672  $now = start
673  fm_insect($now + 0.000, 1.699, 4142.627, 0.015, amp, 60, -16.707,
674            locust, 500.866, bug_hi, 0.346, 0.5)
675  fm_insect($now + 0.195, 0.233, 4126.284, 0.030, amp, 60, -12.142,
676            locust, 649.490, bug_hi, 0.407, 0.5)
677  fm_insect($now + 0.217, 2.057, 3930.258, 0.045, amp, 60,  -3.011,
678            locust, 562.087, bug_hi, 0.591, 0.5)
679  fm_insect($now + 2.100, 1.500,  900.627, 0.060, amp, 40, -16.707,
680            locust, 300.866, bug_hi, 0.346, 0.5)
681  fm_insect($now + 3.000, 1.500,  900.627, 0.060, amp, 40, -16.707,
682            locust, 300.866, bug_hi, 0.046, 0.5)
683  fm_insect($now + 3.450, 1.500,  900.627, 0.090, amp, 40, -16.707,
684            locust, 300.866, bug_hi, 0.006, 0.5)
685  fm_insect($now + 3.950, 1.500,  900.627, 0.120, amp, 40, -10.707,
686            locust, 300.866, bug_hi, 0.346, 0.5)
687  fm_insect($now + 4.300, 1.500,  900.627, 0.090, amp, 40, -20.707,
688            locust, 300.866, bug_hi, 0.246, 0.5)
689  $now += 6.0
690end
691
692# FM-DRUM
693#
694# Jan Mattox's fm drum:
695def fm_drum(start, dur, freq, amp, index, high = false,
696            degree = 0.0, distance = 1.0, rev_amount = 0.01)
697  casrat = high ? 8.525 : 3.515
698  fmrat = high ? 3.414 : 1.414
699  glsf = make_env(:envelope, [0, 0, 25, 0, 75, 1, 100, 1],
700                  :scaler, high ? hz2radians(66) : 0.0, :duration, dur)
701  ampfun = [0, 0, 3, 0.05, 5, 0.2, 7, 0.8, 8, 0.95,
702    10, 1.0, 12, 0.95, 20, 0.3, 30, 0.1, 100, 0]
703  atdrpt = 100 * (high ? 0.01 : 0.015) / dur
704  ampf = make_env(:envelope,
705                  stretch_envelope(ampfun, 10, atdrpt, 15,
706                                   [atdrpt + 1,
707                                     100 - 100 * ((dur - 0.2) / dur)].max),
708                  :scaler, amp, :duration, dur)
709  indxfun = [0, 0, 5, 0.014, 10, 0.033, 15, 0.061, 20, 0.099,
710    25, 0.153, 30, 0.228, 35, 0.332, 40, 0.477,
711    45, 0.681, 50, 0.964, 55, 0.681, 60, 0.478, 65, 0.332,
712    70, 0.228, 75, 0.153, 80, 0.099, 85, 0.061,
713    90, 0.033, 95, 0.0141, 100, 0]
714  indxpt = 100 - 100 * ((dur - 0.1) / dur)
715  divindxf = stretch_envelope(indxfun, 50, atdrpt, 65, indxpt)
716  indxf = make_env(:envelope, divindxf, :duration, dur,
717                   :scaler, [hz2radians(index * fmrat * freq), PI].min)
718  mindxf = make_env(:envelope, divindxf, :duration, dur,
719                    :scaler, [hz2radians(index * casrat * freq), PI].min)
720  devf = make_env(:envelope,
721                  stretch_envelope(ampfun, 10, atdrpt, 90,
722                                   [atdrpt + 1,
723                                     100 - 100 * ((dur - 0.05) / dur)].max),
724                  :scaler, [hz2radians(7000), PI].min, :duration, dur)
725  rn = make_rand(:frequency, 7000, :amplitude, 1)
726  carrier = make_oscil(:frequency, freq)
727  fmosc = make_oscil(:frequency, freq * fmrat)
728  cascade = make_oscil(:frequency, freq * casrat)
729  run_instrument(start, dur,
730                 :degree, degree,
731                 :distance, distance,
732                 :reverb_amount, rev_amount) do
733    gls = env(glsf)
734    env(ampf) *
735      oscil(carrier,
736            gls +
737            env(indxf) *
738            oscil(fmosc,
739                  gls * fmrat +
740                  env(mindxf) * oscil(cascade,
741                                      gls * casrat +
742                                      env(devf) * rand(rn))))
743  end
744end
745
746def fm_drum_test(start = 0.0, dur = 1.0)
747  $now = start
748  fm_drum($now, dur, 55, 0.3, 5, false)
749  $now += dur + 0.2
750  fm_drum($now, dur, 66, 0.3, 4, true)
751  $now += dur + 0.2
752end
753
754# FM-GONG
755#
756# Paul Weineke's gong.
757def gong(start, dur, freq, amp, *args)
758  degree, distance, reverb_amount = nil
759  optkey(args, binding,
760         [:degree, 0.0],
761         [:distance, 1.0],
762         [:reverb_amount, 0.005])
763  mfq1 = freq * 1.16
764  mfq2 = freq * 3.14
765  mfq3 = freq * 1.005
766  indx01 = hz2radians(0.01 * mfq1)
767  indx11 = hz2radians(0.30 * mfq1)
768  indx02 = hz2radians(0.01 * mfq2)
769  indx12 = hz2radians(0.38 * mfq2)
770  indx03 = hz2radians(0.01 * mfq3)
771  indx13 = hz2radians(0.50 * mfq3)
772  atpt = 5
773  atdur = 100 * (0.002 / dur)
774  expf = [0, 0, 3, 1, 15, 0.5, 27, 0.25, 50, 0.1, 100, 0]
775  rise = [0, 0, 15, 0.3, 30, 1.0, 75, 0.5, 100, 0]
776  fmup = [0, 0, 75, 1.0, 98, 1.0, 100, 0]
777  fmdwn = [0, 0, 2, 1.0, 100, 0]
778  ampfun = make_env(:envelope, stretch_envelope(expf, atpt, atdur),
779                    :scaler, amp, :duration, dur)
780  indxfun1 = make_env(:envelope, fmup, :scaler, indx11 - indx01,
781                      :duration, dur, :offset, indx01)
782  indxfun2 = make_env(:envelope, fmdwn, :scaler, indx12 - indx02,
783                      :duration, dur, :offset, indx02)
784  indxfun3 = make_env(:envelope, rise, :scaler, indx13 - indx03,
785                      :duration, dur, :offset, indx03)
786  carrier = make_oscil(:frequency, freq)
787  mod1 = make_oscil(:frequency, mfq1)
788  mod2 = make_oscil(:frequency, mfq2)
789  mod3 = make_oscil(:frequency, mfq3)
790  run_instrument(start, dur,
791                 :degree, degree,
792                 :distance, distance,
793                 :reverb_amount, reverb_amount) do
794    env(ampfun) *
795      oscil(carrier,
796            env(indxfun1) * oscil(mod1) +
797            env(indxfun2) * oscil(mod2) +
798            env(indxfun3) * oscil(mod3))
799  end
800end
801
802def gong_test(start = 0.0, dur = 1.0)
803  gong(start, dur, 261.61, 0.6)
804  $now = start + dur + 0.2
805end
806
807# ATTRACT
808#
809# by James McCartney, from CMJ vol 21 no 3 p 6
810def attract(start, dur, amp, c)
811  a = b = 0.2
812  dt = 0.04
813  scale = (0.5 * amp) / c
814  x = -1.0
815  y = z = 0.0
816  run_instrument(start, dur) do
817    x1 = x - dt * (y + z)
818    y = y + dt * (x + a * y)
819    z = z + dt * ((b + x * z) - c * z)
820    x = x1
821    scale * x
822  end
823end
824
825def attract_test(start = 0.0, dur = 1.0)
826  attract(start, dur, 0.5, 2.0)
827  $now = start + dur + 0.2
828end
829
830# PQW
831#
832# phase-quadrature waveshaping used to create asymmetric (i.e. single
833# side-band) spectra.  The basic idea here is a variant of sin x sin y
834# - cos x cos y = cos (x + y)
835def pqw(start, dur, spacing_freq, carrier_freq,
836        amp, ampfun, indexfun, partials, *args)
837  degree, distance, reverb_amount = nil
838  optkey(args, binding,
839         [:degree, 0.0],
840         [:distance, 1.0],
841         [:reverb_amount, 0.005])
842  normalized_partials = normalize_partials(partials)
843  spacing_cos = make_oscil(:frequency, spacing_freq, :initial_phase, HALF_PI)
844  spacing_sin = make_oscil(:frequency, spacing_freq)
845  carrier_cos = make_oscil(:frequency, carrier_freq, :initial_phase, HALF_PI)
846  carrier_sin = make_oscil(:frequency, carrier_freq)
847  sin_coeffs = partials2polynomial(normalized_partials, 0)
848  cos_coeffs = partials2polynomial(normalized_partials, 1)
849  amp_env = make_env(:envelope, ampfun, :scaler, amp, :duration, dur)
850  ind_env = make_env(:envelope, indexfun, :duration, dur)
851  r = carrier_freq / spacing_freq.to_f
852  tr = make_triangle_wave(:frequency, 5,
853                          :amplitude, hz2radians(0.005 * spacing_freq))
854  rn = make_rand_interp(:frequency, 12,
855                        :amplitude, hz2radians(0.005 * spacing_freq))
856  run_instrument(start, dur,
857                 :degree, degree,
858                 :distance, distance,
859                 :reverb_amount, reverb_amount) do
860    vib = triangle_wave(tr) + rand_interp(rn)
861    ax = [1.0, env(ind_env)].min * oscil(spacing_cos, vib)
862    fax = polynomial(cos_coeffs, ax)
863    yfax = oscil(spacing_sin, vib) * polynomial(sin_coeffs, ax)
864    env(amp_env) *
865      (oscil(carrier_sin, vib * r) * yfax -
866       oscil(carrier_cos, vib * r) * fax)
867  end
868end
869
870def pqw_test(start = 0.0, dur = 1.0)
871  pqw(start, dur, 200, 1000, 0.2,
872      [0, 0, 25, 1, 100, 0], [0, 1, 100, 0], [2, 0.1, 3, 0.3, 6, 0.5])
873  $now = start + dur + 0.2
874  # to see the asymmetric spectrum most clearly, set the index function
875  # above to [0, 1, 100, 1]
876end
877
878# taken from Perry Cook's stkv1.tar.Z (Synthesis Toolkit), but I was
879# in a bit of a hurry and may not have made slavishly accurate
880# translations.  Please let me (bil@ccrma.stanford.edu) know of any
881# serious (non-envelope) errors.
882#
883# from Perry Cook's TubeBell.cpp
884def tubebell(start, dur, freq, amp, base = 32.0)
885  osc0 = make_oscil(freq * 0.995)
886  osc1 = make_oscil(freq * 0.995 * 1.414)
887  osc2 = make_oscil(freq * 1.005)
888  osc3 = make_oscil(freq * 1.414)
889  ampenv1 = make_env(:envelope, [0, 0, 0.005, 1, dur, 0],
890                     :base, base, :duration, dur)
891  ampenv2 = make_env(:envelope, [0, 0, 0.001, 1, dur, 0],
892                     :base, 2 * base, :duration, dur)
893  ampmod = make_oscil(:frequency, 2.0)
894  g0 = 0.5 * amp * 0.707
895  g1 = 0.203
896  g2 = 0.5 * amp
897  g3 = 0.144
898  run_instrument(start, dur) do
899    (0.007 *
900     oscil(ampmod) + 0.993) *
901     (g0 * env(ampenv1) * oscil(osc0, g1 * oscil(osc1)) +
902      g2 * env(ampenv2) * oscil(osc2, g3 * oscil(osc3)))
903  end
904end
905
906def tubebell_test(start = 0.0, dur = 1.0)
907  tubebell(start, dur, 440, 0.2, 32)
908  $now = start + dur + 0.2
909end
910
911# from Perry Cook's Wurley.cpp
912def wurley(start, dur, freq, amp)
913  osc0 = make_oscil(freq)
914  osc1 = make_oscil(freq * 4.0)
915  osc2 = make_oscil(510.0)
916  osc3 = make_oscil(510.0)
917  ampmod = make_oscil(:frequency, 8.0)
918  g0 = 0.5 * amp
919  g1 = 0.307
920  g2 = 0.5 * amp * 0.307
921  g3 = 0.117
922  dur = [dur, 0.3].max
923  ampenv = make_env(:envelope, [0, 0, 1, 1, 9, 1, 10, 0], :duration, dur)
924  indenv = make_env(:envelope, [0, 0, 0.001, 1, 0.15, 0, dur, 0],
925                    :duration, dur)
926  resenv = make_env(:envelope, [0, 0, 0.001, 1, 0.25, 0, dur, 0],
927                    :duration, dur)
928  run_instrument(start, dur) do
929    env(ampenv) *
930      (1.0 + 0.007 * oscil(ampmod)) *
931      (g0 * oscil(osc0, g1 * oscil(osc1)) +
932       env(resenv) * g2 * oscil(osc2, g3 * env(indenv) * oscil(osc3)))
933  end
934end
935
936def wurley_test(start = 0.0, dur = 1.0)
937  wurley(start, dur, 440, 0.2)
938  $now = start + dur + 0.2
939end
940
941# from Perry Cook's Rhodey.cpp
942def rhodey(start, dur, freq, amp, base = 0.5)
943  osc0 = make_oscil(freq)
944  osc1 = make_oscil(freq * 0.5)
945  osc2 = make_oscil(freq)
946  osc3 = make_oscil(freq * 15.0)
947  dur = [dur, 0.3].max
948  ampenv1 = make_env(:envelope, [0, 0, 0.005, 1, dur, 0],
949                     :base, base, :duration, dur)
950  ampenv2 = make_env(:envelope, [0, 0, 0.001, 1, dur, 0],
951                     :base, base * 1.5, :duration, dur)
952  ampenv3 = make_env(:envelope, [0, 0, 0.001, 1, 0.25, 0, dur, 0],
953                     :base, base * 4, :duration, dur)
954  g0 = 0.5 * amp
955  g1 = 0.535
956  g2 = 0.5 * amp
957  g3 = 0.109
958  run_instrument(start, dur) do
959    g0 * env(ampenv1) * oscil(osc0, g1 * oscil(osc1)) +
960    g2 * env(ampenv2) * oscil(osc2, env(ampenv3) * g3 * oscil(osc3))
961  end
962end
963
964def rhodey_test(start = 0.0, dur = 1.0)
965  rhodey(start, dur, 440, 0.2, 0.5)
966  $now = start + dur + 0.2
967end
968
969# from Perry Cook's BeeThree.cpp
970def hammondoid(start, dur, freq, amp)
971  osc0 = make_oscil(freq * 0.999)
972  osc1 = make_oscil(freq * 1.997)
973  osc2 = make_oscil(freq * 3.006)
974  osc3 = make_oscil(freq * 6.009)
975  dur = [dur, 0.1].max
976  ampenv1 = make_env(:envelope, [0, 0, 0.005, 1, dur - 0.008, 1, dur, 0],
977                     :duration, dur)
978  ampenv2 = make_env(:envelope, [0, 0, 0.005, 1, dur, 0], :duration, dur)
979  g0 = 0.25 * 0.75 * amp
980  g1 = 0.25 * 0.75 * amp
981  g2 = 0.5 * amp
982  g3 = 0.5 * 0.75 * amp
983  run_instrument(start, dur) do
984    env(ampenv1) *
985      (g0 * oscil(osc0) +
986       g1 * oscil(osc1) +
987       g2 * oscil(osc2)) +
988       env(ampenv2) * g3 * oscil(osc3)
989  end
990end
991
992def hammondoid_test(start = 0.0, dur = 1.0)
993  hammondoid(start, dur, 440, 0.2)
994  $now = start + dur + 0.2
995end
996
997# from Perry Cook's HeavyMtl.cpp
998def metal(start, dur, freq, amp)
999  osc0 = make_oscil(freq)
1000  osc1 = make_oscil(freq * 4.0 * 0.999)
1001  osc2 = make_oscil(freq * 3.0 * 1.001)
1002  osc3 = make_oscil(freq * 0.5 * 1.002)
1003  dur = [dur, 0.1].max
1004  ampenv0 = make_env(:envelope, [0, 0, 0.001, 1, dur - 0.002, 1, dur, 0],
1005                     :duration, dur)
1006  ampenv1 = make_env(:envelope, [0, 0, 0.001, 1, dur - 0.011, 1, dur, 0],
1007                     :duration, dur)
1008  ampenv2 = make_env(:envelope, [0, 0, 0.01, 1, dur - 0.015, 1, dur, 0],
1009                     :duration, dur)
1010  ampenv3 = make_env(:envelope, [0, 0, 0.03, 1, dur - 0.04, 1, dur, 0],
1011                     :duration, dur)
1012  g0 = 0.615 * amp
1013  g1 = 0.202
1014  g2 = 0.574
1015  g3 = 0.116
1016  run_instrument(start, dur) do
1017    g0 *
1018      env(ampenv0) *
1019      oscil(osc0,
1020            g1 * env(ampenv1) * oscil(osc1, g2 * env(ampenv2) * oscil(osc2)) +
1021            g3 * env(ampenv3) * oscil(osc3))
1022  end
1023end
1024
1025def metal_test(start = 0.0, dur = 1.0)
1026  metal(start, dur, 440, 0.2)
1027  $now = start + dur + 0.2
1028end
1029
1030# DRONE
1031def drone(start, dur, freq, amp, ampfun, synth,
1032          ampat, ampdc, amtrev, deg, dis, rvibamt, rvibfreq)
1033  waveform = partials2wave(synth)
1034  amp *= 0.25
1035  s = make_table_lookup(:frequency, freq, :wave, waveform)
1036  amp_env = make_env(:envelope,
1037                     stretch_envelope(ampfun, 25, 100 * (ampat / dur.to_f), 75,
1038                                      100 - 100 * (ampdc / dur.to_f)),
1039                     :scaler, amp, :duration, dur)
1040  ran_vib = make_rand(:frequency, rvibfreq,
1041                      :amplitude, hz2radians(rvibamt * freq))
1042  run_instrument(start, dur,
1043                 :distance, dis,
1044                 :degree, deg,
1045                 :reverb_amount, amtrev) do
1046    env(amp_env) * table_lookup(s, rand(ran_vib).abs)
1047  end
1048end
1049
1050# CANTER
1051def canter(start, dur, pitch, amp, deg, dis, pcrev,
1052           ampfun, ranfun, skewfun, skewpc,
1053           ranpc, ranfreq, indexfun, atdr, dcdr,
1054           ampfun1, indfun1, fmtfun1,
1055           ampfun2, indfun2, fmtfun2,
1056           ampfun3, indfun3, fmtfun3,
1057           ampfun4, indfun4, fmtfun4)
1058  amp *= 0.25
1059  dur = dur.to_f
1060  pitch = pitch.to_f
1061  rangetop = 910.0
1062  rangebot = 400.0
1063  k = (100 * (log(pitch / rangebot) / log(rangetop / rangebot))).floor
1064  mfq = pitch
1065  atpt = 100 * (atdr / dur)
1066  dcpt = 100 - 100 * (dcdr / dur)
1067  lfmt1 = envelope_interp(k, fmtfun1)
1068  harm1 = (0.5 + lfmt1 / pitch).floor
1069  dev11 = hz2radians(envelope_interp(k, indfun1) * mfq)
1070  dev01 = dev11 * 0.5
1071  lamp1 = envelope_interp(k, ampfun1) * amp * (1 - (harm1 - lfmt1 / pitch).abs)
1072  lfmt2 = envelope_interp(k, fmtfun2)
1073  harm2 = (0.5 + lfmt2 / pitch).floor
1074  dev12 = hz2radians(envelope_interp(k, indfun2) * mfq)
1075  dev02 = dev12 * 0.5
1076  lamp2 = envelope_interp(k, ampfun2) * amp * (1 - (harm2 - lfmt2 / pitch).abs)
1077  lfmt3 = envelope_interp(k, fmtfun3)
1078  harm3 = (0.5 + lfmt3 / pitch).floor
1079  dev13 = hz2radians(envelope_interp(k, indfun3) * mfq)
1080  dev03 = dev13 * 0.5
1081  lamp3 = envelope_interp(k, ampfun3) * amp * (1 - (harm3 - lfmt3 / pitch).abs)
1082  lfmt4 = envelope_interp(k, fmtfun4)
1083  harm4 = (0.5 + lfmt4 / pitch).floor
1084  dev14 = hz2radians(envelope_interp(k, indfun4) * mfq)
1085  dev04 = dev14 * 0.5
1086  lamp4 = envelope_interp(k, ampfun4) * amp * (1 - (harm4 - lfmt4 / pitch).abs)
1087  tampfun = make_env(:envelope, stretch_envelope(ampfun, 25, atpt, 75, dcpt),
1088                     :duration, dur)
1089  tskwfun = make_env(:envelope, stretch_envelope(skewfun, 25, atpt, 75, dcpt),
1090                     :scaler, hz2radians(pitch * skewpc.to_f), :duration, dur)
1091  tranfun = make_env(:envelope, stretch_envelope(ranfun, 25, atpt, 75, dcpt),
1092                     :duration, dur)
1093  tidxfun = make_env(:envelope, stretch_envelope(indexfun, 25, atpt, 75, dcpt),
1094                     :duration, dur)
1095  modgen = make_oscil(:frequency, pitch)
1096  gen1 = make_oscil(:frequency, pitch * harm1)
1097  gen2 = make_oscil(:frequency, pitch * harm2)
1098  gen3 = make_oscil(:frequency, pitch * harm3)
1099  gen4 = make_oscil(:frequency, pitch * harm4)
1100  ranvib = make_rand(:frequency, ranfreq, :amplitude, hz2radians(ranpc * pitch))
1101  run_instrument(start, dur,
1102                 :degree, deg,
1103                 :distance, dis,
1104                 :reverb_amount, pcrev) do
1105    frqval = env(tskwfun) + env(tranfun) * rand(ranvib)
1106    modval = oscil(modgen, frqval)
1107    ampval = env(tampfun)
1108    indval = env(tidxfun)
1109    lamp1 *
1110      ampval *
1111      oscil(gen1, ((dev01 + indval * dev11) * modval + frqval) * harm1) +
1112      lamp2 *
1113      ampval *
1114      oscil(gen2, ((dev02 + indval * dev12) * modval + frqval) * harm2) +
1115      lamp3 *
1116      ampval *
1117      oscil(gen3, ((dev03 + indval * dev13) * modval + frqval) * harm3) +
1118      lamp4 *
1119      ampval *
1120      oscil(gen4, ((dev04 + indval * dev14) * modval + frqval) * harm4)
1121  end
1122end
1123
1124# NREV (the most popular Samson box reverb)
1125#
1126# reverb_factor controls the length of the decay -- it should not
1127#   exceed (/ 1.0 .823)
1128# lp_coeff controls the strength of the low pass filter inserted
1129#   in the feedback loop
1130# volume can be used to boost the reverb output
1131def nrev(*args)
1132  reverb_factor, lp_coeff, volume = nil
1133  optkey(args, binding,
1134         [:reverb_factor, 1.09],
1135         [:lp_coeff, 0.7],
1136         [:volume, 1.0])
1137  next_prime = lambda do |val|
1138    if val.prime?
1139      val
1140    else
1141      next_prime.call(val + 2)
1142    end
1143  end
1144  srscale = @srate / 25641
1145  dly_len = [1433, 1601, 1867, 2053, 2251, 2399,
1146    347, 113, 37, 59, 53, 43, 37, 29, 19]
1147  dly_len.map! do |x|
1148    val = (x * srscale).round
1149    val += 1 if val.even?
1150    next_prime.call(val)
1151  end
1152  comb1 = make_comb(0.822 * reverb_factor, dly_len[0])
1153  comb2 = make_comb(0.802 * reverb_factor, dly_len[1])
1154  comb3 = make_comb(0.773 * reverb_factor, dly_len[2])
1155  comb4 = make_comb(0.753 * reverb_factor, dly_len[3])
1156  comb5 = make_comb(0.753 * reverb_factor, dly_len[4])
1157  comb6 = make_comb(0.733 * reverb_factor, dly_len[5])
1158  low = make_one_pole(lp_coeff, lp_coeff - 1.0)
1159  chan2 = (@channels > 1)
1160  chan4 = (@channels == 4)
1161  allpass1 = make_all_pass(-0.7, 0.7, dly_len[6])
1162  allpass2 = make_all_pass(-0.7, 0.7, dly_len[7])
1163  allpass3 = make_all_pass(-0.7, 0.7, dly_len[8])
1164  allpass4 = make_all_pass(-0.7, 0.7, dly_len[9]) # 10 for quad
1165  allpass5 = make_all_pass(-0.7, 0.7, dly_len[11])
1166  allpass6 = (chan2 ? make_all_pass(-0.7, 0.7, dly_len[12]) : nil)
1167  allpass7 = (chan4 ? make_all_pass(-0.7, 0.7, dly_len[13]) : nil)
1168  allpass8 = (chan4 ? make_all_pass(-0.7, 0.7, dly_len[14]) : nil)
1169  out_frample = Vct.new(@channels, 0.0)
1170  run_reverb() do |val, i|
1171    rev = volume * val
1172    outrev = all_pass(allpass4,
1173                      one_pole(low,
1174                               all_pass(allpass3,
1175                                        all_pass(allpass2,
1176                                                 all_pass(allpass1,
1177                                                          comb(comb1, rev) +
1178                                                          comb(comb2, rev) +
1179                                                          comb(comb3, rev) +
1180                                                          comb(comb4, rev) +
1181                                                          comb(comb5, rev) +
1182                                                          comb(comb6, rev))))))
1183    out_frample[0] = all_pass(allpass5, outrev)
1184    if chan2
1185      out_frample[1] = all_pass(allpass6, outrev)
1186    end
1187    if chan4
1188      out_frample[2] = all_pass(allpass7, outrev)
1189      out_frample[3] = all_pass(allpass8, outrev)
1190    end
1191    out_frample
1192  end
1193end
1194
1195def drone_canter_test(start = 0.0, dur = 1.0)
1196  fmt1 = [0, 1200, 100, 1000]
1197  fmt2 = [0, 2250, 100, 1800]
1198  fmt3 = [0, 4500, 100, 4500]
1199  fmt4 = [0, 6750, 100, 8100]
1200  amp1 = [0, 0.67, 100, 0.7]
1201  amp2 = [0, 0.95, 100, 0.95]
1202  amp3 = [0, 0.28, 100, 0.33]
1203  amp4 = [0, 0.14, 100, 0.15]
1204  ind1 = [0, 0.75, 100, 0.65]
1205  ind2 = [0, 0.75, 100, 0.75]
1206  ind3 = [0, 1, 100, 1]
1207  ind4 = [0, 1, 100, 1]
1208  skwf = [0, 0, 100, 0]
1209  ampf = [0, 0, 25, 1, 75, 1, 100, 0]
1210  ranf = [0, 0.5, 100, 0.5]
1211  index = [0, 1, 100, 1]
1212  solid = [0, 0, 5, 1, 95, 1, 100, 0]
1213  bassdr2 = [0.5, 0.06, 1, 0.62, 1.5, 0.07, 2, 0.6, 2.5, 0.08, 3, 0.56,
1214    4, 0.24, 5, 0.98, 6, 0.53, 7, 0.16, 8, 0.33, 9, 0.62, 10, 0.12,
1215    12, 0.14, 14, 0.86, 16, 0.12, 23, 0.14, 24, 0.17]
1216  tenordr = [0.3, 0.04, 1, 0.81, 2, 0.27, 3, 0.2, 4, 0.21, 5, 0.18,
1217    6, 0.35, 7, 0.03, 8, 0.07, 9, 0.02, 10, 0.025, 11, 0.035]
1218
1219  $now = start
1220  drone($now, 4, 115, 0.125, solid, bassdr2, 0.1, 0.5, 0.03, 45, 1, 0.01, 10)
1221  drone($now, 4, 229, 0.125, solid, tenordr, 0.1, 0.5, 0.03, 45, 1, 0.01, 11)
1222  drone($now, 4, 229.5, 0.125, solid, tenordr, 0.1, 0.5, 0.03, 45, 1, 0.01, 9)
1223  canter($now, 2.100, 918.000, 0.175, 45.0, 1, 0.05,
1224         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1225         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1226  canter($now + 2.100, 0.300, 688.500, 0.175, 45.0, 1, 0.05,
1227         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1228         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1229  canter($now + 2.400, 0.040, 826.200, 0.175, 45.0, 1, 0.05,
1230         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1231         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1232  canter($now + 2.440, 0.560, 459.000, 0.175, 45.0, 1, 0.05,
1233         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1234         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1235  canter($now + 3.000, 0.040, 408.000, 0.175, 45.0, 1, 0.05,
1236         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1237         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1238  canter($now + 3.040, 0.040, 619.650, 0.175, 45.0, 1, 0.05,
1239         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1240         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1241  canter($now + 3.080, 0.040, 408.000, 0.175, 45.0, 1, 0.05,
1242         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1243         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1244  canter($now + 3.120, 0.040, 688.500, 0.175, 45.0, 1, 0.05,
1245         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1246         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1247  canter($now + 3.160, 0.290, 459.000, 0.175, 45.0, 1, 0.05,
1248         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1249         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1250  canter($now + 3.450, 0.150, 516.375, 0.175, 45.0, 1, 0.05,
1251         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1252         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1253  canter($now + 3.600, 0.040, 826.200, 0.175, 45.0, 1, 0.05,
1254         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1255         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1256  canter($now + 3.640, 0.040, 573.750, 0.175, 45.0, 1, 0.05,
1257         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1258         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1259  canter($now + 3.680, 0.040, 619.650, 0.175, 45.0, 1, 0.05,
1260         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1261         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1262  canter($now + 3.720, 0.180, 573.750, 0.175, 45.0, 1, 0.05,
1263         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1264         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1265  canter($now + 3.900, 0.040, 688.500, 0.175, 45.0, 1, 0.05,
1266         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1267         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1268  canter($now + 3.940, 0.260, 459.000, 0.175, 45.0, 1, 0.05,
1269         ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005,
1270         amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4)
1271  $now += 4.4
1272end
1273
1274# RESON
1275def reson(start, dur, pitch, amp, numformants,
1276          indxfun, skewfun, pcskew, skewat, skewdc,
1277          vibfreq, vibpc, ranvibfreq, ranvibpc,
1278          degree, distance, rev_amount, data)
1279  # data is a list of lists of form
1280  # [ampf, resonfrq, resonamp, ampat, ampdc, dev0, dev1, indxat, indxdc]
1281  dur = dur.to_f
1282  pitch = pitch.to_f
1283  modulator = make_oscil(:frequency, pitch)
1284  carriers = Array.new(numformants)
1285  ampfs = Array.new(numformants)
1286  indfs = Array.new(numformants)
1287  c_rats = Array.new(numformants)
1288  frqf = make_env(:envelope,
1289                  stretch_envelope(skewfun, 25, 100 * (skewat / dur), 75,
1290                                   100 - (100 * (skewdc / dur))),
1291                  :scaler, hz2radians(pcskew * pitch), :duration, dur)
1292  pervib = make_triangle_wave(:frequency, vibfreq,
1293                              :amplitude, hz2radians(vibpc * pitch))
1294  ranvib = make_rand_interp(:frequency, ranvibfreq,
1295                            :amplitude, hz2radians(ranvibpc * pitch))
1296  totalamp = 0.0
1297  numformants.times do |i|
1298    totalamp += data[i][2]
1299  end
1300  numformants.times do |i|
1301    frmdat = data[i]
1302    ampf = frmdat[0]
1303    freq = frmdat[1]
1304    rfamp = frmdat[2]
1305    ampat = 100 * (frmdat[3] / dur)
1306    ampdc = 100 - 100 * (frmdat[4] / dur)
1307    dev0 = hz2radians(frmdat[5] * freq)
1308    dev1 = hz2radians(frmdat[6] * freq)
1309    indxat = 100 * (frmdat[7] / dur)
1310    indxdc = 100 - 100 * (frmdat[8] / dur)
1311    harm = (freq / pitch).round
1312    rsamp = 1.0 - (harm - freq / pitch).abs
1313    cfq = pitch * harm
1314    ampat = 25 if ampat.zero?
1315    ampdc = 75 if ampdc.zero?
1316    indxat = 25 if indxat.zero?
1317    indxdc = 75 if indxdc.zero?
1318    indfs[i] = make_env(:envelope,
1319                        stretch_envelope(indxfun, 25, indxat, 75, indxdc),
1320                        :scaler, dev1 - dev0,
1321                        :offset, dev0,
1322                        :duration, dur)
1323    ampfs[i] = make_env(:envelope,
1324                        stretch_envelope(ampf, 25, ampat, 75, ampdc),
1325                        :scaler, rsamp * amp * (rfamp / totalamp),
1326                        :duration, dur)
1327    c_rats[i] = harm
1328    carriers[i] = make_oscil(:frequency, cfq)
1329  end
1330  run_instrument(start, dur,
1331                 :degree, degree,
1332                 :distance, distance,
1333                 :reverb_amount, rev_amount) do
1334    vib = triangle_wave(pervib) + rand_interp(ranvib) + env(frqf)
1335    modsig = oscil(modulator, vib)
1336    outsum = 0.0
1337    numformants.times do |j|
1338      outsum += env(ampfs[j]) *
1339        oscil(carriers[j],
1340              vib * c_rats[j] +
1341              env(indfs[j]) * modsig)
1342    end
1343    outsum
1344  end
1345end
1346
1347def reson_test(start = 0.0, dur = 1.0)
1348  data = [[[0, 0, 100, 1], 1200, 0.5, 0.1, 0.1, 0, 1.0, 0.1, 0.1],
1349    [[0, 1, 100, 0], 2400, 0.5, 0.1, 0.1, 0, 1.0, 0.1, 0.1]]
1350
1351  reson(start, dur, 440, 0.5, 2, [0, 0, 100, 1], [0, 0, 100, 1],
1352        0.1, 0.1, 0.1, 5, 0.01, 5, 0.01, 0, 1.0, 0.01, data)
1353  $now = start + dur + 0.2
1354end
1355
1356# STK's feedback-fm instrument named CelloN in Sambox-land
1357def cellon(start, dur, pitch0, amp, ampfun, betafun,
1358           beta0, beta1, betaat, betadc, ampat, ampdc, dis, pcrev, deg, pitch1,
1359           glissfun = [0, 0, 100, 0], glissat = 0.0, glissdc = 0.0,
1360           pvibfreq = 0.0, pvibpc = 0.0,
1361           pvibfun = [0, 1, 100, 1], pvibat = 0.0, pvibdc = 0.0,
1362           rvibfreq = 0.0, rvibpc = 0.0, rvibfun = [0, 1, 100, 1])
1363
1364  pit1 = pitch1.zero? ? pitch0 : pitch1
1365  car = make_oscil(:frequency, pitch0)
1366  low = make_one_zero(0.5, -0.5)
1367  fmosc = make_oscil(:frequency, pitch0)
1368  fm = 0.0
1369  dur = dur.to_f
1370  pitch0 = pitch0.to_f
1371  pvib = make_triangle_wave(:frequency, pvibfreq, :amplitude, 1.0)
1372  rvib = make_rand_interp(:frequency, rvibfreq, :amplitude, 1.0)
1373  ampap = (ampat > 0.0 ? (100 * (ampat / dur)) : 25)
1374  ampdp = (ampdc > 0.0 ? (100 * (1.0 - ampdc / dur)) : 75)
1375  glsap = (glissat > 0.0 ? (100 * (glissat / dur)) : 25)
1376  glsdp = (glissdc > 0.0 ? (100 * (1.0 - glissdc / dur)) : 75)
1377  betap = (betaat > 0.0 ? (100 * (betaat / dur)) : 25)
1378  betdp = (betadc > 0.0 ? (100 * (1.0 - betadc / dur)) : 75)
1379  pvbap = (pvibat > 0.0 ? (100 * (pvibat / dur)) : 25)
1380  pvbdp = (pvibdc > 0.0 ? (100 * (1.0 - pvibdc / dur)) : 75)
1381  pvibenv = make_env(:envelope,
1382                     stretch_envelope(pvibfun, 25, pvbap, 75, pvbdp),
1383                     :scaler, hz2radians(pvibpc * pitch0),
1384                     :duration, dur)
1385  rvibenv = make_env(:envelope, stretch_envelope(rvibfun),
1386                     :duration, dur,
1387                     :scaler, hz2radians(rvibpc * pitch0))
1388  glisenv = make_env(:envelope,
1389                     stretch_envelope(glissfun, 25, glsap, 75, glsdp),
1390                     :scaler, hz2radians(pit1 - pitch0),
1391                     :duration, dur)
1392  amplenv = make_env(:envelope, stretch_envelope(ampfun, 25, ampap, 75, ampdp),
1393                     :scaler, amp,
1394                     :duration, dur)
1395  betaenv = make_env(:envelope, stretch_envelope(betafun, 25, betap, 75, betdp),
1396                     :scaler, beta1 - beta0,
1397                     :offset, beta0,
1398                     :duration, dur)
1399  run_instrument(start, dur,
1400                 :degree, deg,
1401                 :distance, dis,
1402                 :reverb_amount, pcrev) do
1403    vib = env(pvibenv) * triangle_wave(pvib) +
1404      env(rvibenv) * rand_interp(rvib) +
1405      env(glisenv)
1406    fm = one_zero(low, env(betaenv) * oscil(fmosc, fm + vib))
1407    env(amplenv) * oscil(car, fm + vib)
1408  end
1409end
1410
1411def cellon_test(start = 0.0, dur = 1.0)
1412  cellon(start, dur, 220, 0.5,
1413         [0, 0, 25, 1, 75, 1, 100, 0],        # ampfun
1414         [0, 0, 25, 1, 75, 1, 100, 0],        # betafun
1415         0.75, 1.0, 0, 0, 0, 0, 1, 0, 0, 220,
1416         [0, 0, 25, 1, 75, 1, 100, 0],        # glissfun
1417         0, 0, 0, 0,
1418         [0, 0, 100, 0],                      # pvibfun
1419         0, 0, 0, 0,
1420         [0, 0, 100, 0])                      # rvibfun
1421  $now = start + dur + 0.2
1422end
1423
1424# JL-REVERB
1425def jl_reverb(*args)
1426  allpass1 = make_all_pass(-0.7, 0.7, 2111)
1427  allpass2 = make_all_pass(-0.7, 0.7,  673)
1428  allpass3 = make_all_pass(-0.7, 0.7,  223)
1429  comb1 = make_comb(0.742,  9601)
1430  comb2 = make_comb(0.733, 10007)
1431  comb3 = make_comb(0.715, 10799)
1432  comb4 = make_comb(0.697, 11597)
1433  outdel1 = make_delay((0.013 * @srate).round)
1434  outdel2 = (@channels > 1 ? make_delay((0.011 * @srate).round) : false)
1435  out_frample = Vct.new(@channels, 0.0)
1436  run_reverb() do |ho, i|
1437    allpass_sum = all_pass(allpass3, all_pass(allpass2, all_pass(allpass1, ho)))
1438    comb_sum = (comb(comb1, allpass_sum) + comb(comb2, allpass_sum) +
1439                comb(comb3, allpass_sum) + comb(comb4, allpass_sum))
1440    out_frample[0] = delay(outdel1, comb_sum)
1441    if outdel2
1442      out_frample[1] = delay(outdel2, comb_sum)
1443    end
1444    out_frample
1445  end
1446end
1447
1448# GRAN-SYNTH
1449def gran_synth(start, dur, freq, grain_dur, interval, amp)
1450  grain_env = make_env(:envelope, [0, 0, 25, 1, 75, 1, 100, 0],
1451                       :duration, grain_dur)
1452  carrier = make_oscil(:frequency, freq)
1453  grain_size = ([grain_dur, interval].max * @srate).ceil
1454  grains = make_wave_train(:size, grain_size, :frequency, 1.0 / interval)
1455  grain = mus_data(grains)
1456  grain_size.times do |i|
1457    grain[i] = env(grain_env) * oscil(carrier)
1458  end
1459  run_instrument(start, dur) do
1460    amp * wave_train(grains)
1461  end
1462end
1463
1464def gran_synth_test(start = 0.0, dur = 1.0)
1465  gran_synth(start, dur, 100, 0.0189, 0.02, 0.4)
1466  $now = start + dur + 0.2
1467end
1468
1469# TOUCH-TONE
1470def touch_tone(start, number)
1471  touch_tab_1 = [0, 697, 697, 697, 770, 770, 770, 852, 852, 852, 941, 941, 941]
1472  touch_tab_2 = [0, 1209, 1336, 1477, 1209, 1336,
1473                 1477, 1209, 1336, 1477, 1209, 1336, 1477]
1474  number.length.times do |i|
1475    k = number[i]
1476    ii = if k.kind_of?(Numeric)
1477          k.zero? ? 11 : k
1478        else
1479          k == ?* ? 10 : 12
1480        end
1481    frq1 = make_oscil(:frequency, touch_tab_1[ii])
1482    frq2 = make_oscil(:frequency, touch_tab_2[ii])
1483    run_instrument(start + i * 0.3, 0.2) do
1484      0.25 * (oscil(frq1) + oscil(frq2))
1485    end
1486  end
1487end
1488
1489def touch_tone_test(start = 0.0, dur = 1.0)
1490  touch_tone(start, [4, 8, 3, 4, 6, 2, 1])
1491  $now = start + dur * 7 + 0.2  # 7 digits
1492end
1493
1494# SPECTRA
1495def spectra(start, dur, freq, amp,
1496            partials = [1, 1, 2, 0.5],
1497            amp_envelope = [0, 0, 50, 1, 100, 0],
1498            vibrato_amplitude = 0.005,
1499            vibrato_speed = 5.0,
1500            degree = 0.0,
1501            distance = 1.0,
1502            rev_amount = 0.005)
1503  waveform = partials2wave(partials)
1504  frq = hz2radians(freq)
1505  s = make_table_lookup(:frequency, freq, :wave, waveform)
1506  amp_env = make_env(:envelope, amp_envelope, :scaler, amp, :duration, dur)
1507  per_vib = make_triangle_wave(:frequency, vibrato_speed,
1508                               :amplitude, vibrato_amplitude * frq)
1509  ran_vib = make_rand_interp(:frequency, vibrato_speed + 1.0,
1510                             :amplitude, vibrato_amplitude * frq)
1511  run_instrument(start, dur,
1512                 :degree, degree,
1513                 :distance, distance,
1514                 :reverb_amount, rev_amount) do
1515    env(amp_env) *
1516      table_lookup(s, triangle_wave(per_vib) + rand_interp(ran_vib))
1517  end
1518end
1519
1520def spectra_test(start = 0.0, dur = 1.0)
1521  spectra(start, dur, 440.0, 0.8, P_a4,
1522          [0, 0, 1, 1, 5, 0.9, 12, 0.5, 25, 0.25, 100, 0])
1523  $now = start + dur + 0.2
1524end
1525
1526# TWO-TAB
1527#
1528# interpolate between two waveforms (this could be extended to
1529# implement all the various wavetable-based synthesis techniques).
1530def two_tab(start, dur, freq, amp,
1531            partial_1 = [1.0, 1.0, 2.0, 0.5],
1532            partial_2 = [1.0, 0.0, 3.0, 1.0],
1533            amp_envelope = [0, 0, 50, 1, 100, 0],
1534            interp_func = [0, 1, 100, 0],
1535            vibrato_amplitude = 0.005,
1536            vibrato_speed = 5.0,
1537            degree = 0.0,
1538            distance = 1.0,
1539            rev_amount = 0.005)
1540  waveform_1 = partials2wave(partial_1)
1541  waveform_2 = partials2wave(partial_2)
1542  frq = hz2radians(freq)
1543  s_1 = make_table_lookup(:frequency, freq, :wave, waveform_1)
1544  s_2 = make_table_lookup(:frequency, freq, :wave, waveform_2)
1545  amp_env = make_env(:envelope, amp_envelope, :scaler, amp, :duration, dur)
1546  interp_env = make_env(:envelope, interp_func, :duration, dur)
1547  per_vib = make_triangle_wave(:frequency, vibrato_speed,
1548                               :amplitude, vibrato_amplitude * frq)
1549  ran_vib = make_rand_interp(:frequency, vibrato_speed + 1.0,
1550                             :amplitude, vibrato_amplitude * frq)
1551  run_instrument(start, dur,
1552                 :degree, degree,
1553                 :distance, distance,
1554                 :reverb_amount, rev_amount) do
1555    vib = triangle_wave(per_vib) + rand_interp(ran_vib)
1556    intrp = env(interp_env)
1557    env(amp_env) *
1558      (intrp * table_lookup(s_1, vib) +
1559       (1.0 - intrp) * table_lookup(s_2, vib))
1560  end
1561end
1562
1563def two_tab_test(start = 0.0, dur = 1.0)
1564  two_tab(start, dur, 440, 0.5)
1565  $now = start + dur + 0.2
1566end
1567
1568# LBJ-PIANO
1569$clm_piano_attack_duration = 0.04
1570$clm_piano_release_duration = 0.2
1571$clm_db_drop_per_second = -10.0
1572
1573Piano_Spectra = [[1.97, 0.0326, 2.99, 0.0086, 3.95, 0.0163, 4.97,
1574  0.0178, 5.98, 0.0177, 6.95, 0.0315, 8.02, 0.0001, 8.94, 0.0076,
1575  9.96, 0.0134, 10.99, 0.0284, 11.98, 0.0229, 13.02, 0.0229, 13.89,
1576  0.0010, 15.06, 0.0090, 16.00, 0.0003, 17.08, 0.0078, 18.16, 0.0064,
1577  19.18, 0.0129, 20.21, 0.0085, 21.27, 0.0225, 22.32, 0.0061, 23.41,
1578  0.0102, 24.48, 0.0005, 25.56, 0.0016, 26.64, 0.0018, 27.70, 0.0113,
1579  28.80, 0.0111, 29.91, 0.0158, 31.06, 0.0093, 32.17, 0.0017, 33.32,
1580  0.0002, 34.42, 0.0018, 35.59, 0.0027, 36.74, 0.0055, 37.90, 0.0037,
1581  39.06, 0.0064, 40.25, 0.0033, 41.47, 0.0014, 42.53, 0.0004, 43.89,
1582  0.0010, 45.12, 0.0039, 46.33, 0.0039, 47.64, 0.0009, 48.88, 0.0016,
1583  50.13, 0.0006, 51.37, 0.0010, 52.70, 0.0002, 54.00, 0.0004, 55.30,
1584  0.0008, 56.60, 0.0025, 57.96, 0.0010, 59.30, 0.0012, 60.67, 0.0011,
1585  61.99, 0.0003, 62.86, 0.0001, 64.36, 0.0005, 64.86, 0.0001, 66.26,
1586  0.0004, 67.70, 0.0006, 68.94, 0.0002, 70.10, 0.0001, 70.58, 0.0002,
1587  72.01, 0.0007, 73.53, 0.0006, 75.00, 0.0002, 77.03, 0.0005, 78.00,
1588  0.0002, 79.57, 0.0006, 81.16, 0.0005, 82.70, 0.0005, 84.22, 0.0003,
1589  85.41, 0.0002, 87.46, 0.0001, 90.30, 0.0001, 94.02, 0.0001, 95.26,
1590  0.0002, 109.39, 0.0003],
1591  [1.98, 0.0194, 2.99, 0.0210, 3.97, 0.0276, 4.96, 0.0297, 5.96, 0.0158,
1592    6.99, 0.0207, 8.01, 0.0009, 9.00, 0.0101, 10.00, 0.0297, 11.01,
1593    0.0289, 12.02, 0.0211, 13.04, 0.0127, 14.07, 0.0061, 15.08, 0.0174,
1594    16.13, 0.0009, 17.12, 0.0093, 18.16, 0.0117, 19.21, 0.0122, 20.29,
1595    0.0108, 21.30, 0.0077, 22.38, 0.0132, 23.46, 0.0073, 24.14, 0.0002,
1596    25.58, 0.0026, 26.69, 0.0035, 27.77, 0.0053, 28.88, 0.0024, 30.08,
1597    0.0027, 31.13, 0.0075, 32.24, 0.0027, 33.36, 0.0004, 34.42, 0.0004,
1598    35.64, 0.0019, 36.78, 0.0037, 38.10, 0.0009, 39.11, 0.0027, 40.32,
1599    0.0010, 41.51, 0.0013, 42.66, 0.0019, 43.87, 0.0007, 45.13, 0.0017,
1600    46.35, 0.0019, 47.65, 0.0021, 48.89, 0.0014, 50.18, 0.0023, 51.42,
1601    0.0015, 52.73, 0.0002, 54.00, 0.0005, 55.34, 0.0006, 56.60, 0.0010,
1602    57.96, 0.0016, 58.86, 0.0005, 59.30, 0.0004, 60.75, 0.0005, 62.22,
1603    0.0003, 63.55, 0.0005, 64.82, 0.0003, 66.24, 0.0003, 67.63, 0.0011,
1604    69.09, 0.0007, 70.52, 0.0004, 72.00, 0.0005, 73.50, 0.0008, 74.95,
1605    0.0003, 77.13, 0.0013, 78.02, 0.0002, 79.48, 0.0004, 82.59, 0.0004,
1606    84.10, 0.0003],
1607   [2.00, 0.0313, 2.99, 0.0109, 4.00, 0.0215, 5.00, 0.0242, 5.98, 0.0355,
1608     7.01, 0.0132, 8.01, 0.0009, 9.01, 0.0071, 10.00, 0.0258, 11.03,
1609     0.0221, 12.02, 0.0056, 13.06, 0.0196, 14.05, 0.0160, 15.11, 0.0107,
1610     16.11, 0.0003, 17.14, 0.0111, 18.21, 0.0085, 19.23, 0.0010, 20.28,
1611     0.0048, 21.31, 0.0128, 22.36, 0.0051, 23.41, 0.0041, 24.05, 0.0006,
1612     25.54, 0.0019, 26.62, 0.0028, 27.72, 0.0034, 28.82, 0.0062, 29.89,
1613     0.0039, 30.98, 0.0058, 32.08, 0.0011, 33.21, 0.0002, 34.37, 0.0008,
1614     35.46, 0.0018, 36.62, 0.0036, 37.77, 0.0018, 38.92, 0.0042, 40.07,
1615     0.0037, 41.23, 0.0011, 42.67, 0.0003, 43.65, 0.0018, 44.68, 0.0025,
1616     45.99, 0.0044, 47.21, 0.0051, 48.40, 0.0044, 49.67, 0.0005, 50.88,
1617     0.0019, 52.15, 0.0003, 53.42, 0.0008, 54.69, 0.0010, 55.98, 0.0005,
1618     57.26, 0.0013, 58.53, 0.0027, 59.83, 0.0011, 61.21, 0.0027, 62.54,
1619     0.0003, 63.78, 0.0003, 65.20, 0.0001, 66.60, 0.0006, 67.98, 0.0008,
1620     69.37, 0.0019, 70.73, 0.0007, 72.14, 0.0004, 73.62, 0.0002, 74.40,
1621     0.0003, 76.52, 0.0006, 77.97, 0.0002, 79.49, 0.0004, 80.77, 0.0003,
1622     81.00, 0.0001, 82.47, 0.0005, 83.97, 0.0001, 87.27, 0.0002],
1623   [2.00, 0.0257, 2.99, 0.0142, 3.97, 0.0202, 4.95, 0.0148, 5.95, 0.0420,
1624     6.95, 0.0037, 7.94, 0.0004, 8.94, 0.0172, 9.95, 0.0191, 10.96, 0.0115,
1625     11.97, 0.0059, 12.98, 0.0140, 14.00, 0.0178, 15.03, 0.0121, 16.09,
1626     0.0002, 17.07, 0.0066, 18.08, 0.0033, 19.15, 0.0022, 20.18, 0.0057,
1627     21.22, 0.0077, 22.29, 0.0037, 23.33, 0.0066, 24.97, 0.0002, 25.49,
1628     0.0019, 26.55, 0.0042, 27.61, 0.0043, 28.73, 0.0038, 29.81, 0.0084,
1629     30.91, 0.0040, 32.03, 0.0025, 33.14, 0.0005, 34.26, 0.0003, 35.38,
1630     0.0019, 36.56, 0.0037, 37.68, 0.0049, 38.86, 0.0036, 40.11, 0.0011,
1631     41.28, 0.0008, 42.50, 0.0004, 43.60, 0.0002, 44.74, 0.0022, 45.99,
1632     0.0050, 47.20, 0.0009, 48.40, 0.0036, 49.68, 0.0004, 50.92, 0.0009,
1633     52.17, 0.0005, 53.46, 0.0007, 54.76, 0.0006, 56.06, 0.0005, 57.34,
1634     0.0011, 58.67, 0.0005, 59.95, 0.0015, 61.37, 0.0008, 62.72, 0.0004,
1635     65.42, 0.0009, 66.96, 0.0003, 68.18, 0.0003, 69.78, 0.0003, 71.21,
1636     0.0004, 72.45, 0.0002, 74.22, 0.0003, 75.44, 0.0001, 76.53, 0.0003,
1637     78.31, 0.0004, 79.83, 0.0003, 80.16, 0.0001, 81.33, 0.0003, 82.44,
1638     0.0001, 83.17, 0.0002, 84.81, 0.0003, 85.97, 0.0003, 89.08, 0.0001,
1639     90.70, 0.0002, 92.30, 0.0002, 95.59, 0.0002, 97.22, 0.0003, 98.86,
1640     0.0001, 108.37, 0.0001, 125.54, 0.0001],
1641   [1.99, 0.0650, 3.03, 0.0040, 4.03, 0.0059, 5.02, 0.0090, 5.97, 0.0227,
1642     6.98, 0.0050, 8.04, 0.0020, 9.00, 0.0082, 9.96, 0.0078, 11.01, 0.0056,
1643     12.01, 0.0095, 13.02, 0.0050, 14.04, 0.0093, 15.08, 0.0064, 16.14,
1644     0.0017, 17.06, 0.0020, 18.10, 0.0025, 19.14, 0.0023, 20.18, 0.0015,
1645     21.24, 0.0032, 22.29, 0.0029, 23.32, 0.0014, 24.37, 0.0005, 25.43,
1646     0.0030, 26.50, 0.0022, 27.60, 0.0027, 28.64, 0.0024, 29.76, 0.0035,
1647     30.81, 0.0136, 31.96, 0.0025, 33.02, 0.0003, 34.13, 0.0005, 35.25,
1648     0.0007, 36.40, 0.0014, 37.51, 0.0020, 38.64, 0.0012, 39.80, 0.0019,
1649     40.97, 0.0004, 42.09, 0.0003, 43.24, 0.0003, 44.48, 0.0002, 45.65,
1650     0.0024, 46.86, 0.0005, 48.07, 0.0013, 49.27, 0.0008, 50.49, 0.0006,
1651     52.95, 0.0001, 54.23, 0.0005, 55.45, 0.0004, 56.73, 0.0001, 58.03,
1652     0.0003, 59.29, 0.0002, 60.59, 0.0003, 62.04, 0.0002, 65.89, 0.0002,
1653     67.23, 0.0002, 68.61, 0.0002, 69.97, 0.0004, 71.36, 0.0005, 85.42,
1654     0.0001],
1655   [1.98, 0.0256, 2.96, 0.0158, 3.95, 0.0310, 4.94, 0.0411, 5.95, 0.0238,
1656     6.94, 0.0152, 7.93, 0.0011, 8.95, 0.0185, 9.92, 0.0166, 10.93, 0.0306,
1657     11.94, 0.0258, 12.96, 0.0202, 13.97, 0.0403, 14.95, 0.0228, 15.93,
1658     0.0005, 17.01, 0.0072, 18.02, 0.0034, 19.06, 0.0028, 20.08, 0.0124,
1659     21.13, 0.0137, 22.16, 0.0102, 23.19, 0.0058, 23.90, 0.0013, 25.30,
1660     0.0039, 26.36, 0.0039, 27.41, 0.0025, 28.47, 0.0071, 29.64, 0.0031,
1661     30.60, 0.0027, 31.71, 0.0021, 32.84, 0.0003, 33.82, 0.0002, 35.07,
1662     0.0019, 36.09, 0.0054, 37.20, 0.0038, 38.33, 0.0024, 39.47, 0.0055,
1663     40.55, 0.0016, 41.77, 0.0006, 42.95, 0.0002, 43.27, 0.0018, 44.03,
1664     0.0006, 45.25, 0.0019, 46.36, 0.0033, 47.50, 0.0024, 48.87, 0.0012,
1665     50.03, 0.0016, 51.09, 0.0004, 53.52, 0.0017, 54.74, 0.0012, 56.17,
1666     0.0003, 57.40, 0.0011, 58.42, 0.0020, 59.70, 0.0007, 61.29, 0.0008,
1667     62.56, 0.0003, 63.48, 0.0002, 64.83, 0.0002, 66.12, 0.0012, 67.46,
1668     0.0017, 68.81, 0.0003, 69.13, 0.0003, 70.53, 0.0002, 71.84, 0.0001,
1669     73.28, 0.0002, 75.52, 0.0010, 76.96, 0.0005, 77.93, 0.0003, 78.32,
1670     0.0003, 79.73, 0.0003, 81.69, 0.0002, 82.52, 0.0001, 84.01, 0.0001,
1671     84.61, 0.0002, 86.88, 0.0001, 88.36, 0.0002, 89.85, 0.0002, 91.35,
1672     0.0003, 92.86, 0.0002, 93.40, 0.0001, 105.28, 0.0002, 106.22, 0.0002,
1673     107.45, 0.0001, 108.70, 0.0003, 122.08, 0.0002],
1674   [1.97, 0.0264, 2.97, 0.0211, 3.98, 0.0234, 4.98, 0.0307, 5.96, 0.0085,
1675     6.94, 0.0140, 7.93, 0.0005, 8.96, 0.0112, 9.96, 0.0209, 10.98, 0.0194,
1676     11.98, 0.0154, 12.99, 0.0274, 13.99, 0.0127, 15.01, 0.0101, 15.99,
1677     0.0002, 17.04, 0.0011, 18.08, 0.0032, 19.14, 0.0028, 20.12, 0.0054,
1678     21.20, 0.0053, 22.13, 0.0028, 23.22, 0.0030, 24.32, 0.0006, 25.24,
1679     0.0004, 26.43, 0.0028, 27.53, 0.0048, 28.52, 0.0039, 29.54, 0.0047,
1680     30.73, 0.0044, 31.82, 0.0007, 32.94, 0.0008, 34.04, 0.0012, 35.13,
1681     0.0018, 36.29, 0.0007, 37.35, 0.0075, 38.51, 0.0045, 39.66, 0.0014,
1682     40.90, 0.0004, 41.90, 0.0002, 43.08, 0.0002, 44.24, 0.0017, 45.36,
1683     0.0013, 46.68, 0.0020, 47.79, 0.0015, 48.98, 0.0010, 50.21, 0.0012,
1684     51.34, 0.0001, 53.82, 0.0003, 55.09, 0.0004, 56.23, 0.0005, 57.53,
1685     0.0004, 58.79, 0.0005, 59.30, 0.0002, 60.03, 0.0002, 61.40, 0.0003,
1686     62.84, 0.0001, 66.64, 0.0001, 67.97, 0.0001, 69.33, 0.0001, 70.68,
1687     0.0001, 73.57, 0.0002, 75.76, 0.0002, 76.45, 0.0001, 79.27, 0.0001,
1688     80.44, 0.0002, 81.87, 0.0002],
1689   [2.00, 0.0311, 2.99, 0.0086, 3.99, 0.0266, 4.97, 0.0123, 5.98, 0.0235,
1690     6.97, 0.0161, 7.97, 0.0008, 8.96, 0.0088, 9.96, 0.0621, 10.99, 0.0080,
1691     11.99, 0.0034, 12.99, 0.0300, 14.03, 0.0228, 15.04, 0.0105, 16.03,
1692     0.0004, 17.06, 0.0036, 18.09, 0.0094, 18.95, 0.0009, 20.17, 0.0071,
1693     21.21, 0.0161, 22.25, 0.0106, 23.28, 0.0104, 24.33, 0.0008, 25.38,
1694     0.0030, 26.46, 0.0035, 27.50, 0.0026, 28.59, 0.0028, 29.66, 0.0128,
1695     30.75, 0.0139, 31.81, 0.0038, 32.93, 0.0006, 34.04, 0.0004, 35.16,
1696     0.0005, 36.25, 0.0023, 37.35, 0.0012, 38.46, 0.0021, 39.59, 0.0035,
1697     40.71, 0.0006, 41.86, 0.0007, 42.42, 0.0001, 43.46, 0.0003, 44.17,
1698     0.0032, 45.29, 0.0013, 46.57, 0.0004, 47.72, 0.0011, 48.79, 0.0005,
1699     50.11, 0.0005, 51.29, 0.0003, 52.47, 0.0002, 53.68, 0.0004, 55.02,
1700     0.0005, 56.18, 0.0003, 57.41, 0.0003, 58.75, 0.0007, 59.33, 0.0009,
1701     60.00, 0.0004, 61.34, 0.0001, 64.97, 0.0003, 65.20, 0.0002, 66.48,
1702     0.0002, 67.83, 0.0002, 68.90, 0.0003, 70.25, 0.0003, 71.59, 0.0002,
1703     73.68, 0.0001, 75.92, 0.0001, 77.08, 0.0002, 78.45, 0.0002, 81.56,
1704     0.0002, 82.99, 0.0001, 88.39, 0.0001],
1705   [0.97, 0.0059, 1.98, 0.0212, 2.99, 0.0153, 3.99, 0.0227, 4.96, 0.0215,
1706     5.97, 0.0153, 6.98, 0.0085, 7.98, 0.0007, 8.97, 0.0179, 9.98, 0.0512,
1707     10.98, 0.0322, 12.00, 0.0098, 13.02, 0.0186, 14.00, 0.0099, 15.05,
1708     0.0109, 15.88, 0.0011, 17.07, 0.0076, 18.11, 0.0071, 19.12, 0.0045,
1709     20.16, 0.0038, 21.23, 0.0213, 22.27, 0.0332, 23.34, 0.0082, 24.34,
1710     0.0014, 25.42, 0.0024, 26.47, 0.0012, 27.54, 0.0014, 28.60, 0.0024,
1711     29.72, 0.0026, 30.10, 0.0008, 31.91, 0.0021, 32.13, 0.0011, 33.02,
1712     0.0007, 34.09, 0.0014, 35.17, 0.0007, 36.27, 0.0024, 37.39, 0.0029,
1713     38.58, 0.0014, 39.65, 0.0017, 40.95, 0.0012, 41.97, 0.0004, 42.43,
1714     0.0002, 43.49, 0.0001, 44.31, 0.0012, 45.42, 0.0031, 46.62, 0.0017,
1715     47.82, 0.0013, 49.14, 0.0013, 50.18, 0.0010, 51.54, 0.0003, 53.90,
1716     0.0006, 55.06, 0.0010, 56.31, 0.0003, 57.63, 0.0001, 59.02, 0.0003,
1717     60.09, 0.0004, 60.35, 0.0004, 61.62, 0.0009, 63.97, 0.0001, 65.19,
1718     0.0001, 65.54, 0.0002, 66.92, 0.0002, 67.94, 0.0002, 69.17, 0.0003,
1719     69.60, 0.0004, 70.88, 0.0002, 72.24, 0.0002, 76.12, 0.0001, 78.94,
1720     0.0001, 81.75, 0.0001, 82.06, 0.0001, 83.53, 0.0001, 90.29, 0.0002,
1721     91.75, 0.0001, 92.09, 0.0002, 93.28, 0.0001, 97.07, 0.0001],
1722   [1.98, 0.0159, 2.98, 0.1008, 3.98, 0.0365, 4.98, 0.0133, 5.97, 0.0101,
1723     6.97, 0.0115, 7.97, 0.0007, 8.99, 0.0349, 10.01, 0.0342, 11.01,
1724     0.0236, 12.00, 0.0041, 13.02, 0.0114, 14.05, 0.0137, 15.06, 0.0100,
1725     16.05, 0.0007, 17.04, 0.0009, 18.12, 0.0077, 19.15, 0.0023, 20.12,
1726     0.0017, 21.24, 0.0113, 22.26, 0.0126, 23.30, 0.0093, 24.36, 0.0007,
1727     25.43, 0.0007, 26.47, 0.0009, 27.55, 0.0013, 28.59, 0.0025, 29.61,
1728     0.0010, 30.77, 0.0021, 31.86, 0.0023, 32.96, 0.0003, 34.03, 0.0007,
1729     35.06, 0.0005, 36.20, 0.0006, 37.34, 0.0006, 38.36, 0.0009, 39.60,
1730     0.0016, 40.69, 0.0005, 41.77, 0.0002, 42.92, 0.0002, 44.02, 0.0003,
1731     45.24, 0.0006, 46.33, 0.0004, 47.50, 0.0007, 48.71, 0.0007, 49.87,
1732     0.0002, 51.27, 0.0002, 53.42, 0.0003, 55.88, 0.0003, 57.10, 0.0004,
1733     58.34, 0.0002, 59.86, 0.0003, 61.13, 0.0003, 67.18, 0.0001, 68.50,
1734     0.0001, 71.17, 0.0001, 83.91, 0.0001, 90.55, 0.0001],
1735   [0.98, 0.0099, 2.00, 0.0181, 2.99, 0.0353, 3.98, 0.0285, 4.97, 0.0514,
1736     5.96, 0.0402, 6.96, 0.0015, 7.98, 0.0012, 8.98, 0.0175, 9.98, 0.0264,
1737     10.98, 0.0392, 11.98, 0.0236, 13.00, 0.0153, 14.04, 0.0049, 15.00,
1738     0.0089, 16.01, 0.0001, 17.03, 0.0106, 18.03, 0.0028, 19.05, 0.0024,
1739     20.08, 0.0040, 21.11, 0.0103, 22.12, 0.0104, 23.20, 0.0017, 24.19,
1740     0.0008, 25.20, 0.0007, 26.24, 0.0011, 27.36, 0.0009, 27.97, 0.0030,
1741     29.40, 0.0044, 30.37, 0.0019, 31.59, 0.0017, 32.65, 0.0008, 33.59,
1742     0.0005, 34.79, 0.0009, 35.75, 0.0027, 36.88, 0.0035, 37.93, 0.0039,
1743     39.00, 0.0031, 40.08, 0.0025, 41.16, 0.0010, 43.25, 0.0004, 44.52,
1744     0.0012, 45.62, 0.0023, 45.85, 0.0012, 47.00, 0.0006, 47.87, 0.0008,
1745     48.99, 0.0003, 50.48, 0.0003, 51.62, 0.0001, 52.43, 0.0001, 53.56,
1746     0.0002, 54.76, 0.0002, 56.04, 0.0002, 56.68, 0.0006, 57.10, 0.0003,
1747     58.28, 0.0005, 59.47, 0.0003, 59.96, 0.0002, 60.67, 0.0001, 63.08,
1748     0.0002, 64.29, 0.0002, 66.72, 0.0001, 67.97, 0.0001, 68.65, 0.0001,
1749     70.43, 0.0001, 79.38, 0.0001, 80.39, 0.0001, 82.39, 0.0001],
1750   [1.00, 0.0765, 1.99, 0.0151, 2.99, 0.0500, 3.99, 0.0197, 5.00, 0.0260,
1751     6.00, 0.0145, 6.98, 0.0128, 7.97, 0.0004, 8.98, 0.0158, 9.99, 0.0265,
1752     11.02, 0.0290, 12.02, 0.0053, 13.03, 0.0242, 14.03, 0.0103, 15.06,
1753     0.0054, 16.04, 0.0006, 17.08, 0.0008, 18.10, 0.0058, 19.16, 0.0011,
1754     20.16, 0.0055, 21.18, 0.0040, 22.20, 0.0019, 23.22, 0.0014, 24.05,
1755     0.0005, 25.31, 0.0019, 26.38, 0.0018, 27.44, 0.0022, 28.45, 0.0024,
1756     29.57, 0.0073, 30.58, 0.0032, 31.66, 0.0071, 32.73, 0.0015, 33.85,
1757     0.0005, 34.96, 0.0003, 36.00, 0.0020, 37.11, 0.0018, 38.18, 0.0055,
1758     39.23, 0.0006, 40.33, 0.0004, 41.52, 0.0003, 43.41, 0.0028, 45.05,
1759     0.0003, 45.99, 0.0002, 47.07, 0.0003, 48.52, 0.0002, 49.48, 0.0003,
1760     50.63, 0.0003, 51.81, 0.0002, 54.05, 0.0002, 55.24, 0.0001, 56.62,
1761     0.0001, 57.81, 0.0004, 59.16, 0.0013, 60.23, 0.0003, 66.44, 0.0001,
1762     68.99, 0.0004, 75.49, 0.0001, 87.56, 0.0004],
1763   [0.98, 0.0629, 1.99, 0.0232, 2.98, 0.0217, 4.00, 0.0396, 4.98, 0.0171,
1764     5.97, 0.0098, 6.99, 0.0167, 7.99, 0.0003, 8.98, 0.0192, 9.98, 0.0266,
1765     10.99, 0.0256, 12.01, 0.0061, 13.02, 0.0135, 14.02, 0.0062, 15.05,
1766     0.0158, 16.06, 0.0018, 17.08, 0.0101, 18.09, 0.0053, 19.11, 0.0074,
1767     20.13, 0.0020, 21.17, 0.0052, 22.22, 0.0077, 23.24, 0.0035, 24.00,
1768     0.0009, 25.32, 0.0016, 26.40, 0.0022, 27.43, 0.0005, 28.55, 0.0026,
1769     29.60, 0.0026, 30.65, 0.0010, 31.67, 0.0019, 32.77, 0.0008, 33.81,
1770     0.0003, 34.91, 0.0003, 36.01, 0.0005, 37.11, 0.0010, 38.20, 0.0014,
1771     39.29, 0.0039, 40.43, 0.0012, 41.50, 0.0006, 43.38, 0.0017, 43.75,
1772     0.0002, 44.94, 0.0005, 46.13, 0.0002, 47.11, 0.0003, 48.28, 0.0005,
1773     48.42, 0.0005, 49.44, 0.0003, 50.76, 0.0004, 51.93, 0.0002, 54.15,
1774     0.0003, 55.31, 0.0005, 55.50, 0.0003, 56.98, 0.0003, 57.90, 0.0004,
1775     60.33, 0.0002, 61.39, 0.0001, 61.59, 0.0001, 65.09, 0.0002, 66.34,
1776     0.0001, 68.85, 0.0001, 70.42, 0.0002, 71.72, 0.0001, 73.05, 0.0003,
1777     79.65, 0.0001, 85.28, 0.0002, 93.52, 0.0001],
1778   [1.02, 0.0185, 1.99, 0.0525, 2.98, 0.0613, 3.99, 0.0415, 4.98, 0.0109,
1779     5.97, 0.0248, 6.99, 0.0102, 7.98, 0.0005, 8.98, 0.0124, 9.99, 0.0103,
1780     10.99, 0.0124, 12.00, 0.0016, 13.01, 0.0029, 14.03, 0.0211, 15.04,
1781     0.0128, 16.07, 0.0021, 17.09, 0.0009, 18.09, 0.0043, 19.14, 0.0022,
1782     20.13, 0.0016, 21.20, 0.0045, 22.21, 0.0088, 23.26, 0.0046, 24.29,
1783     0.0013, 25.35, 0.0009, 26.39, 0.0028, 27.49, 0.0009, 28.51, 0.0006,
1784     29.58, 0.0012, 30.70, 0.0010, 31.74, 0.0019, 32.75, 0.0002, 33.85,
1785     0.0001, 34.95, 0.0005, 36.02, 0.0003, 37.16, 0.0009, 38.25, 0.0018,
1786     39.35, 0.0008, 40.54, 0.0004, 41.61, 0.0002, 43.40, 0.0004, 43.74,
1787     0.0003, 45.05, 0.0001, 46.11, 0.0003, 47.40, 0.0002, 48.36, 0.0004,
1788     49.55, 0.0004, 50.72, 0.0002, 52.00, 0.0001, 55.58, 0.0002, 57.02,
1789     0.0001, 57.98, 0.0002, 59.13, 0.0003, 61.56, 0.0001, 66.56, 0.0001,
1790     87.65, 0.0002],
1791   [1.00, 0.0473, 1.99, 0.0506, 2.99, 0.0982, 3.99, 0.0654, 5.00, 0.0196,
1792     5.99, 0.0094, 6.99, 0.0118, 7.93, 0.0001, 8.99, 0.0057, 10.01, 0.0285,
1793     11.01, 0.0142, 12.03, 0.0032, 13.03, 0.0056, 14.06, 0.0064, 15.06,
1794     0.0059, 16.11, 0.0005, 17.09, 0.0033, 18.14, 0.0027, 19.15, 0.0014,
1795     20.17, 0.0010, 21.21, 0.0059, 22.26, 0.0043, 23.31, 0.0031, 24.31,
1796     0.0018, 25.33, 0.0009, 26.41, 0.0005, 27.47, 0.0015, 28.53, 0.0015,
1797     29.58, 0.0041, 30.65, 0.0025, 31.73, 0.0011, 32.83, 0.0010, 34.98,
1798     0.0003, 36.07, 0.0009, 37.23, 0.0001, 38.26, 0.0020, 39.41, 0.0014,
1799     40.53, 0.0005, 41.40, 0.0003, 42.80, 0.0002, 43.48, 0.0028, 43.93,
1800     0.0001, 45.03, 0.0003, 46.18, 0.0007, 47.41, 0.0001, 48.57, 0.0002,
1801     49.67, 0.0001, 50.83, 0.0002, 54.39, 0.0001, 55.58, 0.0002, 57.97,
1802     0.0005, 58.11, 0.0002, 59.21, 0.0001, 60.42, 0.0002, 61.66, 0.0001],
1803   [1.00, 0.0503, 2.00, 0.0963, 2.99, 0.1304, 3.99, 0.0218, 4.98, 0.0041,
1804     5.98, 0.0292, 6.98, 0.0482, 7.99, 0.0005, 8.99, 0.0280, 10.00, 0.0237,
1805     11.00, 0.0152, 12.02, 0.0036, 12.95, 0.0022, 14.06, 0.0111, 15.07,
1806     0.0196, 16.08, 0.0016, 17.11, 0.0044, 18.13, 0.0073, 19.17, 0.0055,
1807     20.19, 0.0028, 21.20, 0.0012, 22.27, 0.0068, 23.30, 0.0036, 24.35,
1808     0.0012, 25.35, 0.0002, 26.46, 0.0005, 27.47, 0.0005, 28.59, 0.0009,
1809     29.65, 0.0021, 30.70, 0.0020, 31.78, 0.0012, 32.89, 0.0010, 35.06,
1810     0.0005, 36.16, 0.0008, 37.27, 0.0010, 38.36, 0.0010, 39.47, 0.0014,
1811     40.58, 0.0004, 41.43, 0.0007, 41.82, 0.0003, 43.48, 0.0008, 44.53,
1812     0.0001, 45.25, 0.0003, 46.43, 0.0002, 47.46, 0.0002, 48.76, 0.0005,
1813     49.95, 0.0004, 50.96, 0.0002, 51.12, 0.0002, 52.33, 0.0001, 54.75,
1814     0.0001, 55.75, 0.0002, 56.90, 0.0002, 58.17, 0.0002, 59.40, 0.0004,
1815     60.62, 0.0002, 65.65, 0.0001, 66.91, 0.0002, 69.91, 0.0001, 71.25,
1816     0.0002],
1817   [1.00, 0.1243, 1.98, 0.1611, 3.00, 0.0698, 3.98, 0.0390, 5.00, 0.0138,
1818     5.99, 0.0154, 7.01, 0.0287, 8.01, 0.0014, 9.01, 0.0049, 10.00, 0.0144,
1819     11.01, 0.0055, 12.05, 0.0052, 13.01, 0.0011, 14.05, 0.0118, 15.07,
1820     0.0154, 16.12, 0.0028, 17.14, 0.0061, 18.25, 0.0007, 19.22, 0.0020,
1821     20.24, 0.0011, 21.27, 0.0029, 22.30, 0.0046, 23.34, 0.0049, 24.35,
1822     0.0004, 25.45, 0.0003, 26.47, 0.0007, 27.59, 0.0008, 28.16, 0.0009,
1823     29.12, 0.0002, 29.81, 0.0006, 30.81, 0.0009, 31.95, 0.0004, 33.00,
1824     0.0011, 34.12, 0.0005, 35.18, 0.0003, 36.30, 0.0008, 37.38, 0.0003,
1825     38.55, 0.0003, 39.64, 0.0006, 40.77, 0.0007, 41.52, 0.0006, 41.89,
1826     0.0006, 43.04, 0.0011, 43.60, 0.0009, 44.31, 0.0002, 45.68, 0.0002,
1827     46.56, 0.0003, 47.60, 0.0001, 48.83, 0.0006, 50.01, 0.0003, 51.27,
1828     0.0003, 56.04, 0.0005, 57.21, 0.0003, 58.56, 0.0004, 59.83, 0.0003,
1829     61.05, 0.0001, 62.20, 0.0001, 67.37, 0.0002, 76.53, 0.0001],
1830   [0.99, 0.0222, 1.99, 0.0678, 2.99, 0.0683, 4.00, 0.0191, 5.00, 0.0119,
1831     6.01, 0.0232, 6.98, 0.0336, 7.99, 0.0082, 9.01, 0.0201, 10.01, 0.0189,
1832     11.01, 0.0041, 12.01, 0.0053, 13.05, 0.0154, 14.04, 0.0159, 15.06,
1833     0.0092, 16.11, 0.0038, 17.12, 0.0014, 18.15, 0.0091, 19.16, 0.0006,
1834     20.30, 0.0012, 21.25, 0.0061, 22.28, 0.0099, 23.34, 0.0028, 24.38,
1835     0.0012, 25.43, 0.0016, 26.49, 0.0048, 27.55, 0.0025, 28.62, 0.0015,
1836     29.71, 0.0032, 30.78, 0.0077, 31.88, 0.0011, 32.97, 0.0007, 34.08,
1837     0.0006, 35.16, 0.0008, 36.28, 0.0004, 37.41, 0.0006, 38.54, 0.0005,
1838     39.62, 0.0002, 40.80, 0.0003, 41.93, 0.0001, 43.06, 0.0002, 44.21,
1839     0.0003, 45.38, 0.0002, 46.54, 0.0007, 47.78, 0.0003, 48.95, 0.0004,
1840     50.10, 0.0003, 51.37, 0.0002, 53.79, 0.0003, 56.20, 0.0001, 58.71,
1841     0.0002, 66.47, 0.0003],
1842   [1.01, 0.0241, 1.99, 0.1011, 2.98, 0.0938, 3.98, 0.0081, 4.99, 0.0062,
1843     5.99, 0.0291, 6.99, 0.0676, 7.59, 0.0004, 8.98, 0.0127, 9.99, 0.0112,
1844     10.99, 0.0142, 12.00, 0.0029, 13.02, 0.0071, 14.02, 0.0184, 15.03,
1845     0.0064, 16.07, 0.0010, 17.09, 0.0011, 18.11, 0.0010, 19.15, 0.0060,
1846     20.19, 0.0019, 21.24, 0.0025, 22.29, 0.0013, 23.31, 0.0050, 25.41,
1847     0.0030, 26.50, 0.0018, 27.53, 0.0006, 28.63, 0.0012, 29.66, 0.0013,
1848     30.77, 0.0020, 31.84, 0.0006, 34.04, 0.0001, 35.14, 0.0001, 36.32,
1849     0.0004, 37.41, 0.0007, 38.53, 0.0007, 39.67, 0.0009, 40.85, 0.0003,
1850     45.49, 0.0002, 46.65, 0.0001, 47.81, 0.0004, 49.01, 0.0002, 53.91,
1851     0.0002, 55.14, 0.0002, 57.69, 0.0002],
1852   [1.00, 0.0326, 2.00, 0.1066, 2.99, 0.1015, 4.00, 0.0210, 4.97, 0.0170,
1853     5.99, 0.0813, 6.98, 0.0820, 7.96, 0.0011, 8.99, 0.0248, 10.03, 0.0107,
1854     11.01, 0.0126, 12.01, 0.0027, 13.01, 0.0233, 14.04, 0.0151, 15.05,
1855     0.0071, 16.04, 0.0002, 17.10, 0.0061, 18.12, 0.0059, 19.15, 0.0087,
1856     20.23, 0.0005, 21.25, 0.0040, 22.30, 0.0032, 23.35, 0.0004, 24.40,
1857     0.0001, 25.45, 0.0030, 26.54, 0.0022, 27.60, 0.0003, 28.70, 0.0009,
1858     29.80, 0.0029, 30.85, 0.0006, 31.97, 0.0006, 34.19, 0.0004, 35.30,
1859     0.0003, 36.43, 0.0007, 37.56, 0.0005, 38.68, 0.0019, 39.88, 0.0013,
1860     41.00, 0.0003, 43.35, 0.0003, 44.51, 0.0002, 45.68, 0.0006, 46.93,
1861     0.0010, 48.11, 0.0006, 49.29, 0.0003, 55.58, 0.0002],
1862   [0.98, 0.0113, 1.99, 0.0967, 3.00, 0.0719, 3.98, 0.0345, 4.98, 0.0121,
1863     6.00, 0.0621, 7.00, 0.0137, 7.98, 0.0006, 9.01, 0.0314, 10.01, 0.0171,
1864     11.02, 0.0060, 12.03, 0.0024, 13.05, 0.0077, 14.07, 0.0040, 15.12,
1865     0.0032, 16.13, 0.0004, 17.15, 0.0011, 18.20, 0.0028, 19.18, 0.0003,
1866     20.26, 0.0003, 21.31, 0.0025, 22.35, 0.0021, 23.39, 0.0005, 25.55,
1867     0.0002, 26.62, 0.0014, 27.70, 0.0003, 28.78, 0.0005, 29.90, 0.0030,
1868     31.01, 0.0011, 32.12, 0.0005, 34.31, 0.0001, 35.50, 0.0002, 36.62,
1869     0.0002, 37.76, 0.0005, 38.85, 0.0002, 40.09, 0.0004, 43.60, 0.0001,
1870     44.73, 0.0002, 46.02, 0.0002, 47.25, 0.0004, 48.44, 0.0004],
1871   [0.99, 0.0156, 1.98, 0.0846, 2.98, 0.0178, 3.98, 0.0367, 4.98, 0.0448,
1872     5.98, 0.0113, 6.99, 0.0189, 8.00, 0.0011, 9.01, 0.0247, 10.02, 0.0089,
1873     11.01, 0.0184, 12.03, 0.0105, 13.00, 0.0039, 14.07, 0.0116, 15.09,
1874     0.0078, 16.13, 0.0008, 17.14, 0.0064, 18.19, 0.0029, 19.22, 0.0028,
1875     20.25, 0.0017, 21.32, 0.0043, 22.37, 0.0055, 23.42, 0.0034, 24.48,
1876     0.0004, 25.54, 0.0002, 26.61, 0.0017, 27.70, 0.0011, 28.80, 0.0002,
1877     29.89, 0.0019, 30.97, 0.0028, 32.09, 0.0007, 34.30, 0.0002, 35.44,
1878     0.0003, 36.55, 0.0001, 37.69, 0.0004, 38.93, 0.0002, 40.05, 0.0005,
1879     41.20, 0.0005, 42.37, 0.0002, 43.54, 0.0003, 44.73, 0.0001, 45.95,
1880     0.0002, 47.16, 0.0001, 48.43, 0.0005, 49.65, 0.0004, 55.90, 0.0002,
1881     59.81, 0.0004],
1882   [1.01, 0.0280, 2.00, 0.0708, 2.99, 0.0182, 3.99, 0.0248, 4.98, 0.0245,
1883     5.98, 0.0279, 6.98, 0.0437, 7.99, 0.0065, 8.99, 0.0299, 10.00, 0.0073,
1884     10.99, 0.0011, 12.03, 0.0122, 13.03, 0.0028, 14.08, 0.0044, 15.11,
1885     0.0097, 16.15, 0.0010, 17.17, 0.0025, 18.19, 0.0017, 19.24, 0.0008,
1886     20.28, 0.0040, 21.32, 0.0024, 22.38, 0.0008, 23.46, 0.0032, 24.52,
1887     0.0010, 25.59, 0.0008, 26.68, 0.0009, 27.76, 0.0012, 28.88, 0.0003,
1888     29.95, 0.0005, 31.05, 0.0017, 32.14, 0.0002, 33.29, 0.0003, 37.88,
1889     0.0002, 39.03, 0.0002, 40.19, 0.0004, 41.37, 0.0003, 43.74, 0.0002,
1890     46.20, 0.0001, 48.68, 0.0001, 49.93, 0.0001, 51.19, 0.0002],
1891   [1.00, 0.0225, 1.99, 0.0921, 2.98, 0.0933, 3.99, 0.0365, 4.99, 0.0100,
1892     5.98, 0.0213, 6.98, 0.0049, 7.98, 0.0041, 8.98, 0.0090, 9.99, 0.0068,
1893     11.01, 0.0040, 12.03, 0.0086, 13.02, 0.0015, 14.04, 0.0071, 15.09,
1894     0.0082, 16.14, 0.0011, 17.15, 0.0014, 18.18, 0.0010, 19.26, 0.0013,
1895     20.26, 0.0005, 21.33, 0.0006, 22.36, 0.0011, 23.46, 0.0016, 24.52,
1896     0.0004, 25.59, 0.0002, 26.70, 0.0006, 27.78, 0.0007, 28.87, 0.0002,
1897     30.03, 0.0008, 31.14, 0.0010, 32.24, 0.0006, 33.37, 0.0002, 35.67,
1898     0.0003, 37.99, 0.0004, 39.17, 0.0004, 40.35, 0.0005, 41.53, 0.0001,
1899     46.42, 0.0001],
1900   [1.00, 0.0465, 1.99, 0.0976, 2.98, 0.0678, 4.00, 0.0727, 4.99, 0.0305,
1901     5.98, 0.0210, 6.98, 0.0227, 8.00, 0.0085, 9.01, 0.0183, 10.02, 0.0258,
1902     11.05, 0.0003, 12.06, 0.0061, 13.05, 0.0021, 14.10, 0.0089, 15.12,
1903     0.0077, 16.16, 0.0016, 17.21, 0.0061, 18.23, 0.0011, 19.29, 0.0031,
1904     20.36, 0.0031, 21.41, 0.0007, 22.48, 0.0013, 23.55, 0.0020, 24.64,
1905     0.0004, 25.74, 0.0005, 26.81, 0.0006, 27.95, 0.0006, 29.03, 0.0001,
1906     30.22, 0.0010, 31.30, 0.0004, 32.48, 0.0001, 33.60, 0.0002, 38.30,
1907     0.0003],
1908   [1.00, 0.0674, 1.99, 0.0841, 2.98, 0.0920, 3.99, 0.0328, 4.99, 0.0368,
1909     5.98, 0.0206, 6.99, 0.0246, 8.01, 0.0048, 9.01, 0.0218, 10.03, 0.0155,
1910     11.05, 0.0048, 12.06, 0.0077, 13.00, 0.0020, 14.10, 0.0083, 15.15,
1911     0.0084, 16.18, 0.0015, 17.22, 0.0039, 18.27, 0.0032, 19.34, 0.0026,
1912     20.40, 0.0012, 21.47, 0.0009, 22.54, 0.0008, 23.62, 0.0016, 24.71,
1913     0.0005, 25.82, 0.0004, 26.91, 0.0002, 28.03, 0.0008, 29.17, 0.0002,
1914     30.32, 0.0028, 31.45, 0.0004, 32.61, 0.0005, 33.77, 0.0001, 36.14,
1915     0.0003, 37.32, 0.0002, 38.54, 0.0005, 39.75, 0.0002, 42.23, 0.0002,
1916     48.65, 0.0001],
1917   [1.01, 0.0423, 1.99, 0.0240, 2.98, 0.0517, 4.00, 0.0493, 5.00, 0.0324,
1918     6.00, 0.0094, 6.99, 0.0449, 7.99, 0.0050, 9.00, 0.0197, 10.03, 0.0132,
1919     11.03, 0.0009, 12.07, 0.0017, 13.08, 0.0023, 14.12, 0.0094, 15.16,
1920     0.0071, 16.21, 0.0020, 17.25, 0.0005, 18.30, 0.0027, 19.04, 0.0004,
1921     20.43, 0.0022, 21.51, 0.0002, 22.59, 0.0006, 23.72, 0.0018, 24.80,
1922     0.0002, 25.88, 0.0002, 27.03, 0.0002, 28.09, 0.0006, 29.31, 0.0002,
1923     30.46, 0.0004, 31.61, 0.0007, 32.78, 0.0005, 33.95, 0.0001, 36.34,
1924     0.0002, 37.56, 0.0001, 38.80, 0.0001, 40.02, 0.0001, 44.14, 0.0001],
1925   [1.00, 0.0669, 1.99, 0.0909, 2.99, 0.0410, 3.98, 0.0292, 4.98, 0.0259,
1926     5.98, 0.0148, 6.98, 0.0319, 7.99, 0.0076, 9.01, 0.0056, 10.02, 0.0206,
1927     11.04, 0.0032, 12.05, 0.0085, 13.08, 0.0040, 14.12, 0.0037, 15.16,
1928     0.0030, 16.20, 0.0013, 17.24, 0.0021, 18.30, 0.0010, 19.36, 0.0015,
1929     20.44, 0.0013, 21.50, 0.0009, 22.60, 0.0015, 23.69, 0.0014, 24.80,
1930     0.0006, 25.87, 0.0002, 27.02, 0.0006, 28.12, 0.0002, 29.28, 0.0003,
1931     30.43, 0.0002, 31.59, 0.0007, 32.79, 0.0001, 35.14, 0.0001, 37.57,
1932     0.0001, 40.03, 0.0002, 41.28, 0.0004, 44.10, 0.0001],
1933   [0.99, 0.0421, 1.99, 0.1541, 2.98, 0.0596, 3.98, 0.0309, 4.98, 0.0301,
1934     5.99, 0.0103, 7.00, 0.0240, 8.01, 0.0073, 9.01, 0.0222, 10.04, 0.0140,
1935     11.05, 0.0033, 12.08, 0.0045, 13.13, 0.0009, 14.13, 0.0015, 15.21,
1936     0.0026, 16.24, 0.0003, 17.30, 0.0004, 18.35, 0.0010, 19.39, 0.0003,
1937     20.50, 0.0015, 21.57, 0.0003, 22.68, 0.0011, 23.80, 0.0005, 24.90,
1938     0.0008, 26.02, 0.0002, 27.16, 0.0001, 28.30, 0.0006, 29.48, 0.0002,
1939     31.81, 0.0005, 33.00, 0.0003, 34.21, 0.0001, 37.89, 0.0001],
1940   [0.99, 0.0389, 2.00, 0.2095, 3.00, 0.0835, 3.99, 0.0289, 5.00, 0.0578,
1941     5.99, 0.0363, 7.01, 0.0387, 8.01, 0.0056, 9.04, 0.0173, 10.05, 0.0175,
1942     11.08, 0.0053, 12.10, 0.0056, 13.15, 0.0064, 14.19, 0.0036, 15.22,
1943     0.0019, 16.29, 0.0010, 17.36, 0.0017, 18.43, 0.0018, 19.51, 0.0004,
1944     20.60, 0.0011, 21.70, 0.0003, 22.82, 0.0003, 23.95, 0.0001, 25.05,
1945     0.0004, 26.17, 0.0001, 28.50, 0.0003, 29.68, 0.0001, 32.07, 0.0003,
1946     33.28, 0.0004, 34.52, 0.0001],
1947   [1.00, 0.1238, 1.99, 0.2270, 3.00, 0.0102, 3.99, 0.0181, 4.98, 0.0415,
1948     6.00, 0.0165, 7.01, 0.0314, 8.02, 0.0148, 9.04, 0.0203, 10.05, 0.0088,
1949     11.07, 0.0062, 12.11, 0.0070, 13.14, 0.0054, 14.19, 0.0028, 15.24,
1950     0.0044, 16.30, 0.0029, 17.38, 0.0009, 18.45, 0.0026, 19.56, 0.0003,
1951     20.65, 0.0025, 21.74, 0.0014, 22.87, 0.0013, 23.99, 0.0007, 25.15,
1952     0.0002, 27.46, 0.0004, 28.39, 0.0006, 28.65, 0.0004, 29.85, 0.0001,
1953     31.05, 0.0002, 32.27, 0.0003, 33.52, 0.0002, 34.76, 0.0003],
1954   [1.00, 0.1054, 2.00, 0.2598, 2.99, 0.0369, 3.98, 0.0523, 4.99, 0.0020,
1955     5.99, 0.0051, 7.00, 0.0268, 8.01, 0.0027, 9.04, 0.0029, 10.05, 0.0081,
1956     11.08, 0.0047, 12.12, 0.0051, 13.16, 0.0091, 14.19, 0.0015, 15.27,
1957     0.0030, 16.34, 0.0017, 17.42, 0.0006, 18.51, 0.0003, 19.61, 0.0007,
1958     20.72, 0.0003, 21.84, 0.0001, 22.99, 0.0010, 24.13, 0.0001, 28.44,
1959     0.0001, 30.09, 0.0001],
1960   [0.99, 0.0919, 2.00, 0.0418, 2.99, 0.0498, 3.99, 0.0135, 4.99, 0.0026,
1961     6.00, 0.0155, 7.01, 0.0340, 8.02, 0.0033, 9.04, 0.0218, 10.08, 0.0084,
1962     11.11, 0.0057, 12.15, 0.0051, 13.21, 0.0043, 14.25, 0.0015, 15.31,
1963     0.0023, 16.40, 0.0008, 17.48, 0.0004, 18.59, 0.0016, 19.71, 0.0010,
1964     20.84, 0.0018, 21.98, 0.0002, 23.11, 0.0013, 24.26, 0.0003, 26.67,
1965     0.0002, 29.12, 0.0002, 30.37, 0.0002, 31.62, 0.0003, 32.92, 0.0001],
1966   [0.99, 0.1174, 1.99, 0.1126, 2.99, 0.0370, 3.99, 0.0159, 5.01, 0.0472,
1967     6.01, 0.0091, 7.03, 0.0211, 8.05, 0.0015, 9.07, 0.0098, 10.11, 0.0038,
1968     11.15, 0.0042, 12.20, 0.0018, 13.24, 0.0041, 14.32, 0.0033, 15.41,
1969     0.0052, 16.49, 0.0001, 17.61, 0.0004, 18.71, 0.0004, 19.84, 0.0004,
1970     20.99, 0.0002, 22.14, 0.0006, 23.31, 0.0006, 24.50, 0.0004, 25.70,
1971     0.0002, 28.09, 0.0002, 28.66, 0.0002, 32.00, 0.0001],
1972   [1.00, 0.1085, 2.00, 0.1400, 2.99, 0.0173, 3.99, 0.0229, 5.00, 0.0272,
1973     6.02, 0.0077, 7.03, 0.0069, 8.04, 0.0017, 9.08, 0.0045, 10.10, 0.0030,
1974     11.15, 0.0040, 12.20, 0.0007, 13.25, 0.0019, 14.32, 0.0008, 15.42,
1975     0.0024, 16.50, 0.0002, 17.59, 0.0005, 18.71, 0.0003, 19.83, 0.0002,
1976     20.98, 0.0005, 23.29, 0.0008],
1977   [1.00, 0.0985, 2.00, 0.1440, 2.99, 0.0364, 3.99, 0.0425, 5.00, 0.0190,
1978     6.01, 0.0089, 7.03, 0.0278, 8.04, 0.0006, 9.07, 0.0083, 10.10, 0.0021,
1979     11.14, 0.0050, 12.18, 0.0005, 13.26, 0.0036, 14.33, 0.0005, 15.41,
1980     0.0026, 17.62, 0.0004, 18.75, 0.0004, 19.89, 0.0003, 21.04, 0.0012,
1981     22.21, 0.0002, 23.38, 0.0004, 27.04, 0.0001],
1982   [0.99, 0.1273, 2.00, 0.1311, 2.99, 0.0120, 4.00, 0.0099, 5.00, 0.0235,
1983     6.02, 0.0068, 7.03, 0.0162, 8.06, 0.0009, 9.08, 0.0083, 10.12, 0.0014,
1984     11.17, 0.0050, 12.24, 0.0010, 13.29, 0.0013, 14.39, 0.0022, 15.48,
1985     0.0011, 16.59, 0.0002, 17.70, 0.0003, 18.84, 0.0010, 20.00, 0.0003,
1986     21.17, 0.0003, 23.56, 0.0004, 28.79, 0.0003],
1987   [1.00, 0.1018, 2.00, 0.1486, 3.00, 0.0165, 4.00, 0.0186, 5.01, 0.0194,
1988     6.02, 0.0045, 7.04, 0.0083, 8.06, 0.0012, 9.10, 0.0066, 10.15, 0.0009,
1989     11.19, 0.0008, 12.26, 0.0011, 13.34, 0.0028, 14.45, 0.0006, 15.53,
1990     0.0009, 16.66, 0.0002, 17.79, 0.0006, 18.94, 0.0005, 20.11, 0.0003,
1991     21.29, 0.0005, 22.49, 0.0003, 23.73, 0.0005, 26.22, 0.0001, 27.52,
1992     0.0001, 28.88, 0.0002],
1993   [1.00, 0.1889, 1.99, 0.1822, 3.00, 0.0363, 4.00, 0.0047, 5.01, 0.0202,
1994     6.03, 0.0053, 7.05, 0.0114, 8.01, 0.0002, 9.13, 0.0048, 10.17, 0.0010,
1995     11.23, 0.0033, 12.30, 0.0010, 13.38, 0.0006, 14.50, 0.0002, 15.62,
1996     0.0010, 20.27, 0.0001, 21.47, 0.0001],
1997   [1.00, 0.0522, 1.99, 0.0763, 2.99, 0.0404, 4.00, 0.0139, 5.01, 0.0185,
1998     6.01, 0.0021, 7.06, 0.0045, 8.09, 0.0002, 9.11, 0.0003, 10.17, 0.0006,
1999     11.25, 0.0004, 12.32, 0.0005, 13.40, 0.0003, 14.53, 0.0003, 15.65,
2000     0.0007, 16.80, 0.0001, 17.95, 0.0002, 19.14, 0.0006, 20.34, 0.0002,
2001     21.56, 0.0003],
2002   [0.99, 0.1821, 1.99, 0.0773, 3.00, 0.0125, 4.01, 0.0065, 5.01, 0.0202,
2003     6.03, 0.0071, 7.05, 0.0090, 8.08, 0.0006, 9.13, 0.0008, 10.18, 0.0013,
2004     11.25, 0.0010, 12.33, 0.0012, 13.42, 0.0006, 14.54, 0.0005, 15.65,
2005     0.0004, 17.97, 0.0002, 19.15, 0.0001],
2006   [1.00, 0.1868, 2.00, 0.0951, 3.00, 0.0147, 4.01, 0.0134, 5.02, 0.0184,
2007     6.04, 0.0132, 7.06, 0.0011, 8.11, 0.0008, 9.15, 0.0010, 10.22, 0.0012,
2008     11.30, 0.0011, 12.40, 0.0003, 13.11, 0.0004, 13.49, 0.0002, 14.62,
2009     0.0003, 15.77, 0.0001],
2010   [1.00, 0.1933, 2.00, 0.0714, 3.00, 0.0373, 4.00, 0.0108, 5.02, 0.0094,
2011     6.02, 0.0010, 7.07, 0.0022, 8.11, 0.0002, 9.16, 0.0065, 10.23, 0.0015,
2012     11.31, 0.0023, 12.40, 0.0003, 13.53, 0.0014, 14.66, 0.0002, 15.81,
2013     0.0011, 18.20, 0.0002, 19.41, 0.0001],
2014   [0.99, 0.2113, 1.99, 0.0877, 3.00, 0.0492, 4.01, 0.0094, 5.02, 0.0144,
2015     6.04, 0.0103, 7.07, 0.0117, 8.12, 0.0006, 9.19, 0.0019, 10.25, 0.0007,
2016     11.35, 0.0017, 12.45, 0.0010, 13.58, 0.0003, 14.74, 0.0003, 15.91,
2017     0.0003, 19.57, 0.0002],
2018   [0.99, 0.2455, 1.99, 0.0161, 3.00, 0.0215, 4.01, 0.0036, 5.03, 0.0049,
2019     6.04, 0.0012, 7.09, 0.0036, 8.14, 0.0011, 9.21, 0.0009, 10.30, 0.0001,
2020     11.40, 0.0012, 12.50, 0.0001, 13.66, 0.0005, 14.84, 0.0001],
2021   [1.00, 0.1132, 2.00, 0.0252, 3.00, 0.0292, 4.01, 0.0136, 5.03, 0.0045,
2022     6.06, 0.0022, 7.11, 0.0101, 8.17, 0.0004, 9.23, 0.0010, 10.33, 0.0012,
2023     11.44, 0.0013, 12.58, 0.0011, 13.75, 0.0002, 14.93, 0.0005, 16.14, 0.0002],
2024   [1.00, 0.1655, 2.00, 0.0445, 3.00, 0.0120, 4.00, 0.0038, 5.02, 0.0015,
2025     6.07, 0.0038, 7.11, 0.0003, 8.19, 0.0002, 9.25, 0.0010, 10.36, 0.0011,
2026     11.48, 0.0005, 12.63, 0.0002, 13.79, 0.0003, 16.24, 0.0002],
2027   [0.99, 0.3637, 1.99, 0.0259, 3.01, 0.0038, 4.01, 0.0057, 5.03, 0.0040,
2028     6.07, 0.0067, 7.12, 0.0014, 8.19, 0.0004, 9.27, 0.0003, 10.38, 0.0002,
2029     12.67, 0.0001],
2030   [1.00, 0.1193, 2.00, 0.0230, 3.00, 0.0104, 4.01, 0.0084, 5.04, 0.0047,
2031     6.08, 0.0035, 7.13, 0.0041, 8.20, 0.0002, 9.29, 0.0005, 10.40, 0.0005,
2032     11.53, 0.0003, 12.70, 0.0002, 13.91, 0.0002],
2033   [1.00, 0.0752, 2.00, 0.0497, 3.00, 0.0074, 4.02, 0.0076, 5.05, 0.0053,
2034     6.09, 0.0043, 7.15, 0.0024, 8.22, 0.0001, 9.32, 0.0006, 10.45, 0.0002,
2035     11.58, 0.0001, 12.78, 0.0001, 15.22, 0.0001],
2036   [1.00, 0.2388, 2.00, 0.0629, 3.01, 0.0159, 4.04, 0.0063, 5.07, 0.0051,
2037     6.12, 0.0045, 7.19, 0.0026, 8.29, 0.0015, 9.43, 0.0001, 11.75, 0.0002],
2038   [1.00, 0.1919, 2.01, 0.0116, 3.01, 0.0031, 4.03, 0.0090, 5.07, 0.0061,
2039     6.13, 0.0036, 7.19, 0.0013, 8.30, 0.0016, 9.13, 0.0001, 10.59, 0.0002,
2040     11.78, 0.0002],
2041   [1.00, 0.1296, 2.00, 0.0135, 3.01, 0.0041, 4.04, 0.0045, 5.09, 0.0028,
2042     6.14, 0.0046, 7.23, 0.0007, 8.32, 0.0007, 9.50, 0.0001],
2043   [1.00, 0.0692, 2.00, 0.0209, 3.02, 0.0025, 4.05, 0.0030, 5.09, 0.0047,
2044     6.17, 0.0022, 7.25, 0.0015, 8.36, 0.0015, 9.53, 0.0010, 10.69, 0.0001,
2045     13.40, 0.0001],
2046   [1.00, 0.1715, 2.00, 0.0142, 3.01, 0.0024, 4.03, 0.0015, 5.07, 0.0017,
2047     6.13, 0.0018, 7.22, 0.0009, 8.33, 0.0014, 9.51, 0.0007, 10.69, 0.0002],
2048   [1.00, 0.1555, 2.01, 0.0148, 3.02, 0.0007, 4.06, 0.0006, 5.10, 0.0005,
2049     6.16, 0.0008, 7.26, 0.0009, 8.39, 0.0008, 9.58, 0.0002],
2050   [1.00, 0.1357, 2.00, 0.0116, 3.02, 0.0026, 4.04, 0.0009, 5.09, 0.0004,
2051     6.17, 0.0005, 7.27, 0.0002, 8.40, 0.0001],
2052   [1.00, 0.2185, 2.01, 0.0087, 3.03, 0.0018, 4.06, 0.0025, 5.11, 0.0020,
2053     6.20, 0.0012, 7.32, 0.0005, 8.46, 0.0001, 9.66, 0.0003],
2054   [1.00, 0.2735, 2.00, 0.0038, 3.02, 0.0008, 4.06, 0.0012, 5.12, 0.0008,
2055     6.22, 0.0011, 7.35, 0.0003, 8.50, 0.0002],
2056   [1.00, 0.1441, 1.99, 0.0062, 3.01, 0.0023, 4.05, 0.0011, 5.11, 0.0012,
2057     6.20, 0.0003, 7.33, 0.0004, 8.50, 0.0001],
2058   [1.00, 0.0726, 2.01, 0.0293, 3.03, 0.0022, 5.14, 0.0005, 6.26, 0.0011,
2059     7.41, 0.0002, 8.63, 0.0002],
2060   [1.00, 0.0516, 2.00, 0.0104, 3.02, 0.0029, 5.15, 0.0002, 6.27, 0.0001],
2061   [1.00, 0.0329, 2.00, 0.0033, 3.03, 0.0013, 4.10, 0.0005, 5.19,
2062     0.0004, 6.32, 0.0002],
2063   [1.00, 0.0179, 1.99, 0.0012, 3.04, 0.0005, 4.10, 0.0017, 5.20, 0.0005,
2064     6.35, 0.0001],
2065   [1.00, 0.0334, 2.01, 0.0033, 3.04, 0.0011, 4.13, 0.0003, 5.22, 0.0003],
2066   [0.99, 0.0161, 2.01, 0.0100, 3.04, 0.0020, 4.13, 0.0003],
2067   [1.00, 0.0475, 1.99, 0.0045, 3.03, 0.0035, 4.12, 0.0011],
2068   [1.00, 0.0593, 2.00, 0.0014, 4.17, 0.0002],
2069   [1.00, 0.0249, 2.01, 0.0016],
2070   [1.00, 0.0242, 2.00, 0.0038, 4.19, 0.0002],
2071   [1.00, 0.0170, 2.02, 0.0030],
2072   [1.00, 0.0381, 2.00, 0.0017, 3.09, 0.0002],
2073   [1.00, 0.0141, 2.03, 0.0005, 3.11, 0.0003, 4.26, 0.0001],
2074   [1.00, 0.0122, 2.03, 0.0024],
2075   [1.00, 0.0107, 2.07, 0.0007, 3.12, 0.0004],
2076   [1.00, 0.0250, 2.02, 0.0026, 3.15, 0.0002],
2077   [1.01, 0.0092],
2078   [1.01, 0.0102, 2.09, 0.0005],
2079   [1.00, 0.0080, 2.00, 0.0005, 3.19, 0.0001],
2080   [1.01, 0.0298, 2.01, 0.0005]]
2081
2082def lbj_piano(start, dur, freq, amp, *args)
2083  pfreq, degree, distance, reverb_amount = nil
2084  optkey(args, binding,
2085         [:pfreq, freq],
2086         [:degree, 45.0],
2087         [:distance, 1.0],
2088         [:reverb_amount, 0.0])
2089  get_piano_partials = lambda do |frq|
2090    Piano_Spectra[(12 * (log(frq / 32.703) / log(2))).round]
2091  end
2092  make_piano_ampfun = lambda do |dr|
2093    release_amp = db2linear($clm_db_drop_per_second * dr)
2094    attack_time = $clm_piano_attack_duration * 100.0 / dr
2095    [0, 0, attack_time / 4, 1.0, attack_time, 1.0, 100, release_amp]
2096  end
2097  # This thing sounds pretty good down low, below middle c or so.
2098  # Unfortunately, there are some tens of partials down there and
2099  # we're using exponential envelopes.  You're going to wait for a
2100  # long long time just to hear a single low note.  The high notes
2101  # sound pretty rotten--they just don't sparkle; I have a feeling
2102  # that this is due to the low amplitude of the original data, and
2103  # the lack of mechanical noise.
2104  #
2105  # The only thing you can do to alter the sound of a piano note is to
2106  # set the pfreq parameter.  Pfreq is used to look up the partials.
2107  # By default, it's set to the requested frequency.  Setting it to a
2108  # neighboring freq is useful when you're repeating notes.  Note that
2109  # there's no nyquist detection; a high freq with a low pfreq, will
2110  # give you fold over (hmmm...maybe I can get those high notes to
2111  # sparkle after all).
2112  partials = normalize_partials(get_piano_partials.call(pfreq))
2113  newdur = dur + $clm_piano_attack_duration + $clm_piano_release_duration
2114  env1dur = newdur - $clm_piano_release_duration
2115  env1samples = (env1dur * @srate).floor
2116  siz = (partials.length / 2).floor
2117  oscils = Array.new(siz)
2118  alist = make_vct(siz)
2119  ampfun1 = make_piano_ampfun.call(env1dur)
2120  ampenv1 = make_env(:envelope, ampfun1, :scaler, amp,
2121                     :duration, env1dur, :base, 10000.0)
2122  releaseamp = ampfun1.last
2123  ampenv2 = make_env(:envelope, [0, 1, 100, 0], :scaler, amp * releaseamp,
2124                     :duration, env1dur, :base, 1.0)
2125  sktr = j = 0
2126  0.step(partials.length - 1, 2) do |i|
2127    alist[j] = partials[i + 1]
2128    oscils[j] = make_oscil(:frequency, partials[i] * freq)
2129    j += 1
2130  end
2131  run_instrument(start, newdur,
2132                 :degree, degree,
2133                 :distance, distance,
2134                 :reverb_amount, reverb_amount) do
2135    sktr += 1
2136    let(0.0) do |sum|
2137      oscils.each_with_index do |osc, i|
2138        sum = sum + oscil(osc) * alist[i]
2139      end
2140      sum * env(((sktr > env1samples) ? ampenv2 : ampenv1))
2141    end
2142  end
2143end
2144
2145def lbj_piano_test(start = 0.0, dur = 1.0)
2146  lbj_piano(start, dur, 440.0, 0.5)
2147  $now = start + dur + 0.24 + 0.2
2148end
2149
2150# RESFLT
2151def resflt(start, dur, driver,
2152           ranfreq, noiamp, noifun, cosamp, cosfreq1, cosfreq0, cosnum,
2153           ampcosfun, freqcosfun,
2154           frq1, r1, g1, frq2, r2, g2, frq3, r3, g3, *args)
2155  degree, distance, reverb_amount = nil
2156  optkey(args, binding,
2157         [:degree, 0.0],
2158         [:distance, 1.0],
2159         [:reverb_amount, 0.005])
2160  # driver=0 -- use sum of cosines to drive the filter,
2161  # driver=1 -- use white noise
2162  # if noise used, ranfreq=frequency of random number generator,
2163  #                noiamp=amplitude thereof,
2164  #                noifun=amplitude envelope on white noise
2165  # if sum-of-cosines (i.e. a band-limited pulse train),
2166  #                cosamp=amplitude of pulse train,
2167  #                cosfreq1=top frequency (given freqcosfun)
2168  #                  (i.e. pulse frequency)
2169  #                cosfreq0=bottom frequency,
2170  #                cosnum=number of cosines in the pulse,
2171  #                ampcosfun=amplitude envelope on pulse train
2172  #                freqcosfun=frequency envelope on pulse train
2173  # There are then 3 resonators, centered at frq1, frq2, frq3,
2174  # with pole-radius r1, r2, and r3 respectively, and
2175  # with gains of g1, g2, and g3.
2176  f1 = make_two_pole(frq1, r1)
2177  f2 = make_two_pole(frq2, r2)
2178  f3 = make_two_pole(frq3, r3)
2179  with_noise = (driver == 1)
2180  frqf = if with_noise
2181           nil
2182         else
2183           make_env(:envelope, freqcosfun, :duration, dur,
2184                    :scaler, hz2radians(cosfreq1 - cosfreq0))
2185         end
2186  ampf = if with_noise
2187           make_env(:envelope, noifun, :scaler, noiamp, :duration, dur)
2188         else
2189           make_env(:envelope, ampcosfun, :scaler, cosamp, :duration, dur)
2190         end
2191  rn = if with_noise
2192         make_rand(:frequency, ranfreq)
2193       else
2194         nil
2195       end
2196  cn = if with_noise
2197         nil
2198       else
2199         make_sum_of_cosines(:frequency, cosfreq0, :cosines, cosnum)
2200       end
2201  if with_noise
2202    run_instrument(start, dur,
2203                   :distance, distance,
2204                   :degree, degree,
2205                   :reverb_amount, reverb_amount) do
2206      input1 = env(ampf) * rand(rn)
2207      two_pole(f1, input1 * g1) +
2208        two_pole(f2, input1 * g2) +
2209        two_pole(f3, input1 * g3)
2210    end
2211  else
2212    run_instrument(start, dur,
2213                   :distance, distance,
2214                   :degree, degree,
2215                   :reverb_amount, reverb_amount) do
2216      input1 = env(ampf) * sum_of_cosines(cn, env(frqf))
2217      two_pole(f1, input1 * g1) +
2218        two_pole(f2, input1 * g2) +
2219        two_pole(f3, input1 * g3)
2220    end
2221  end
2222end
2223
2224def resflt_test(start = 0.0, dur = 1.0)
2225  $now = start
2226  resflt($now, dur, 0, 0, 0, nil,
2227         0.1, 200, 230, 10, [0, 0, 50, 1, 100, 0], [0, 0, 100, 1],
2228         500, 0.995, 0.1, 1000, 0.995, 0.1, 2000, 0.995, 0.1)
2229  $now += dur + 0.2
2230  resflt($now, dur, 1, 10000, 0.01, [0, 0, 50, 1, 100, 0],
2231         0, 0, 0, 0, nil, nil,
2232         500, 0.995, 0.1, 1000, 0.995, 0.1, 2000, 0.995, 0.1)
2233  $now += dur + 0.2
2234end
2235
2236# SCRATCH
2237def scratch(start, file, src_ratio, turntable)
2238  assert_type(File.exist?(file), file, 1, "an existing file")
2239  f = make_file2sample(file)
2240  turn_i = 1
2241  turns = turntable.length
2242  cur_sample = seconds2samples(turntable[0])
2243  turn_sample = seconds2samples(turntable[turn_i])
2244  rd = make_src(:srate, src_ratio)
2245  forwards = (src_ratio > 0.0)
2246  set_mus_increment(rd, -src_ratio) if forwards and turn_sample < cur_sample
2247  turning = 0
2248  last_val = last_val2 = 0.0
2249  run_instrument(start, ws_duration(file)) do
2250    break if turn_i >= turns
2251    val = src(rd, 0.0, lambda do |dir|
2252                inval = file2sample(f, cur_sample)
2253                cur_sample += dir
2254                inval
2255              end)
2256    if turning.zero?
2257      # we past turn point going forwards
2258      if forwards and cur_sample >= turn_sample
2259        turning = 1
2260        # we past turn point going backwards
2261      elsif (not forwards) and cur_sample <= turn_sample
2262        turning = -1
2263      end
2264    else
2265      # wait for an inflection...
2266      if (last_val2 <= last_val and last_val >= val) or
2267          (last_val2 >= last_val and last_val <= val)
2268        turn_i += 1
2269        if turn_i < turns
2270          turn_sample = seconds2samples(turntable[turn_i])
2271          forwards = (not forwards)
2272          set_mus_increment(rd, -mus_increment(rd))
2273        end
2274        turning = 0
2275      end
2276    end
2277    last_val2, last_val = last_val, val
2278    val
2279  end
2280  mus_close(f)
2281end
2282
2283def scratch_test(start = 0.0, dur = 1.0)
2284  scratch(start, "fyow.snd", [dur, 1.5].min, [0.0, 0.5, 0.25, 1.0])
2285  $now = start + mus_sound_duration("fyow.snd") + 0.2
2286end
2287
2288# PINS
2289#
2290# spectral modeling (SMS)
2291def pins(start, dur, file, amp, *args)
2292  assert_type(File.exist?(file), file, 2, "an existing file")
2293  transposition, time_scaler, fftsize, highest_bin, max_peaks, attack = nil
2294  optkey(args, binding,
2295         [:transposition, 1.0], # this can be used to transpose the sound
2296         [:time_scaler, 1.0],   # this can make things happen faster
2297                                # (< 1.0)/slower (> 1.0) in the output
2298         [:fftsize, 256],       # should be a power of 2
2299                                # at 22050 srate, this is ok for
2300                                # sounds above 300Hz or so, below that
2301                                # you need 512 or 1024, at 44100,
2302                                # probably best to double these sizes
2303                                # -- it takes some searching
2304                                # sometimes.
2305         [:highest_bin, 128],   # how high in fft data should we search for pks
2306         [:max_peaks, 16],      # how many spectral peaks to track at the max
2307         :attack)               # whether to use original attack via time domain
2308                                # splice do the sliding fft shuffle,
2309                                # translate to polar coordinates, find
2310                                # spectral peaks, match with current,
2311                                # do some interesting transformation,
2312                                # resynthesize using oscils All the
2313                                # envelopes are created on the fly.
2314                                # max-peaks is how many of these peaks
2315                                # we are willing to track at any given
2316                                # time.
2317  fil = make_file2sample(file)
2318  file_duration = ws_duration(file)
2319  fdr = make_vct(fftsize)
2320  fdi = make_vct(fftsize)
2321  window = make_fft_window(Blackman2_window, fftsize)
2322  fftamps = make_vct(fftsize)
2323  max_oscils = 2 * max_peaks
2324  current_peak_freqs = make_vct(max_oscils)
2325  last_peak_freqs = make_vct(max_oscils)
2326  current_peak_amps = make_vct(max_oscils)
2327  last_peak_amps = make_vct(max_oscils)
2328  peak_amps = make_vct(max_peaks)
2329  peak_freqs = make_vct(max_peaks)
2330  resynth_oscils = make_array(max_oscils) do
2331    make_oscil(:frequency, 0)
2332  end
2333  # run-time generated amplitude and frequency envelopes
2334  amps = make_vct(max_oscils)
2335  rates = make_vct(max_oscils)
2336  freqs = make_vct(max_oscils)
2337  sweeps = make_vct(max_oscils)
2338  lowest_magnitude = 0.001
2339  hop = (fftsize / 4).floor
2340  outhop = (time_scaler * hop).floor
2341  ifreq = 1.0 / outhop
2342  ihifreq = hz2radians(ifreq)
2343  # integrate Blackman-Harris window = .42323*window
2344  fftscale = 1.0 / (fftsize * 0.42323)
2345  # width and shift by fftsize
2346  fft_mag = @srate / fftsize
2347  furthest_away_accepted = 0.1
2348  filptr = 0
2349  cur_oscils = max_oscils
2350  ramped = (attack or 0)
2351  splice_attack = attack.kind_of?(Numeric)
2352  attack_size = (attack or 1)
2353  ramp_ind = 0
2354  ramped_attack = make_vct(attack_size)
2355  if (dur / time_scaler) > file_duration
2356    error("%s is %1.3f seconds long, \
2357but we'll need %1.3f seconds of data for this note",
2358          file, file_duration, dur / time_scaler)
2359  end
2360  trigger = outhop
2361  vct_scale!(window, fftscale)
2362  run_instrument(start, dur) do
2363    if splice_attack
2364      ramp = 1.0 / attack_size
2365      # my experience in translating SMS, and rumor via Greg Sandell
2366      # leads me to believe that there is in fact no way to model some
2367      # attacks successfully in this manner, so this block simply
2368      # splices the original attack on to the rest of the note.
2369      # "attack" is the number of samples to include bodily.
2370      out_val = amp * file2sample(fil, filptr)
2371      filptr += 1
2372      if filptr > attack_size
2373        mult = 1.0
2374        attack_size.times do |j|
2375          ramped_attack[j] = mult * file2sample(fil, filptr + j)
2376          mult -= ramp
2377        end
2378        splice_attack = false
2379      end
2380      # if out_val
2381      out_val
2382    else
2383      if trigger >= outhop
2384        peaks = 0
2385        # get next block of data and apply window to it
2386        trigger = 0
2387        fftsize.times do |j|
2388          fdr[j] = window[j] * file2sample(fil, filptr)
2389          filptr += 1
2390        end
2391        vct_fill!(fdi, 0.0)
2392        filptr -= fftsize - hop
2393        # get the fft
2394        mus_fft(fdr, fdi, fftsize, 1)
2395        # change to polar coordinates (ignoring phases)
2396        highest_bin.times do |j|
2397          # no need to paw through the upper half
2398          # (so (<= highest-bin (floor fft-size 2)))
2399          x = fdr[j]
2400          y = fdi[j]
2401          fftamps[j] = 2.0 * sqrt(x * x + y * y)
2402        end
2403        max_oscils.times do |j|
2404          last_peak_freqs[j] = current_peak_freqs[j]
2405          last_peak_amps[j] = current_peak_amps[j]
2406          current_peak_amps[j] = 0.0
2407        end
2408        vct_fill!(peak_amps, 0.0)
2409        ra = fftamps[0]
2410        la = ca = 0.0
2411        # search for current peaks following Xavier Serra's recommendations in
2412        # "A System for Sound Analysis/Transformation/Synthesis
2413        #      Based on a Deterministic Plus Stochastic Decomposition"
2414        highest_bin.times do |j|
2415          la, ca, ra = ca, ra, fftamps[j]
2416          if ca > lowest_magnitude and ca > ra and ca > la
2417            # found a local maximum above the current threshold
2418            # (its bin number is j-1)
2419            logla = log10(la)
2420            logca = log10(ca)
2421            logra = log10(ra)
2422            offset = (0.5 * (logla - logra)) / (logla + -2 * logca + logra)
2423            amp_1 = 10.0 ** (logca - (0.25 * (logla - logra) * offset))
2424            freq = fft_mag * (j + offset - 1)
2425            if peaks == max_peaks
2426              # gotta either flush this peak,
2427              # or find current lowest and flush him
2428              minp = 0
2429              minpeak = peak_amps[0]
2430              1.upto(max_peaks - 1) do |k|
2431                if peak_amps[k] < minpeak
2432                  minp = k
2433                  minpeak = peak_amps[k]
2434                end
2435              end
2436              if amp_1 > minpeak
2437                peak_freqs[minp] = freq
2438                peak_amps[minp] = amp_1
2439              end
2440            else
2441              peak_freqs[peaks] = freq
2442              peak_amps[peaks] = amp_1
2443              peaks += 1
2444            end
2445          end
2446        end
2447        # now we have the current peaks -- match them to the previous
2448        # set and do something interesting with the result the end
2449        # results are reflected in the updated values in the rates and
2450        # sweeps arrays.  search for fits between last and current,
2451        # set rates/sweeps for those found try to go by largest amp
2452        # first
2453        peaks.times do |j|
2454          maxp = 0
2455          maxpk = peak_amps[0]
2456          1.upto(max_peaks - 1) do |k|
2457            if peak_amps[k] > maxpk
2458              maxp = k
2459              maxpk = peak_amps[k]
2460            end
2461          end
2462          # now maxp points to next largest unmatched peak
2463          if maxpk > 0.0
2464            closestp = -1
2465            closestamp = 10.0
2466            current_freq = peak_freqs[maxp]
2467            icf = 1.0 / current_freq
2468            max_peaks.times do |k|
2469              if last_peak_amps[k] > 0.0
2470                closeness = icf * (last_peak_freqs[k] - current_freq).abs
2471                if closeness < closestamp
2472                  closestamp = closeness
2473                  closestp = k
2474                end
2475              end
2476            end
2477            if closestamp < furthest_away_accepted
2478              # peak_amp is transferred to appropriate current_amp and zeroed,
2479              current_peak_amps[closestp] = peak_amps[maxp]
2480              peak_amps[maxp] = 0.0
2481              current_peak_freqs[closestp] = current_freq
2482            end
2483          end
2484        end
2485        max_peaks.times do |j|
2486          if peak_amps[j] > 0.0
2487            # find a place for a new oscil and start it up
2488            new_place = -1
2489            max_oscils.times do |k|
2490              if last_peak_amps[k].zero? and current_peak_amps[k].zero?
2491                new_place = k
2492                break
2493              end
2494            end
2495            current_peak_amps[new_place] = peak_amps[j]
2496            peak_amps[j] = 0.0
2497            current_peak_freqs[new_place] = peak_freqs[j]
2498            last_peak_freqs[new_place] = peak_freqs[j]
2499            set_mus_frequency(resynth_oscils[new_place],
2500                              transposition * peak_freqs[j])
2501          end
2502        end
2503        cur_oscils = 0
2504        max_oscils.times do |j|
2505          rates[j] = ifreq * (current_peak_amps[j] - last_peak_amps[j])
2506          if current_peak_amps[j].nonzero? or last_peak_amps[j].nonzero?
2507            cur_oscils = j
2508          end
2509          sweeps[j] = ihifreq * transposition *
2510            (current_peak_freqs[j] - last_peak_freqs[j])
2511        end
2512        cur_oscils += 1
2513      end
2514      # run oscils, update envelopes
2515      trigger += 1
2516      if ramped.zero?
2517        sum = 0.0
2518      else
2519        sum = ramped_attack[ramp_ind]
2520        ramp_ind += 1
2521        ramped = 0 if ramp_ind == ramped
2522      end
2523      cur_oscils.times do |j|
2524        if amps[j].nonzero? or rates[j].nonzero?
2525          sum = sum + amps[j] * oscil(resynth_oscils[j], freqs[j])
2526          amps[j] += rates[j]
2527          freqs[j] += sweeps[j]
2528        end
2529      end
2530      # else out_val
2531      amp * sum
2532    end
2533  end
2534  mus_close(fil)
2535end
2536
2537def pins_test(start = 0.0, dur = 1.0)
2538  pins(start, dur, "fyow.snd", 1, :time_scaler, 2)
2539  $now = start + dur + 0.2
2540end
2541
2542# ZC
2543def zc(start, dur, freq, amp, length1, length2, feedback)
2544  s = make_pulse_train(:frequency, freq)
2545  d0 = make_comb(:size, length1,
2546                 :max_size, [length1, length2].max + 1,
2547                 :scaler, feedback)
2548  zenv = make_env(:envelope, [0, 0, 1, 1],
2549                  :scaler, length2 - length1,
2550                  :duration, dur)
2551  run_instrument(start, dur) do
2552    comb(d0, amp * pulse_train(s), env(zenv))
2553  end
2554end
2555
2556def zc_test(start = 0.0, dur = 1.0)
2557  $now = start
2558  zc($now, dur, 100, 0.4, 20, 100, 0.95)
2559  $now += dur + 0.2
2560  zc($now, dur, 100, 0.4, 100, 20, 0.95)
2561  $now += dur + 0.2
2562end
2563
2564# ZN
2565#
2566# notches are spaced at srate/len, feedforward sets depth thereof so
2567# sweep of len from 20 to 100 sweeps the notches down from 1000 Hz to
2568# ca 200 Hz so we hear our downward glissando beneath the pulses.
2569def zn(start, dur, freq, amp, length1, length2, feedforward)
2570  s = make_pulse_train(:frequency, freq)
2571  d0 = make_notch(:size, length1,
2572                  :max_size, [length1, length2].max + 1,
2573                  :scaler, feedforward)
2574  zenv = make_env(:envelope, [0, 0, 1, 1],
2575                  :scaler, length2 - length1,
2576                  :duration, dur)
2577  run_instrument(start, dur) do
2578    notch(d0, amp * pulse_train(s), env(zenv))
2579  end
2580end
2581
2582def zn_test(start = 0.0, dur = 1.0)
2583  $now = start
2584  zn($now, dur, 100, 0.5, 20, 100, 0.95)
2585  $now += dur + 0.2
2586  zn($now, dur, 100, 0.5, 100, 20, 0.95)
2587  $now += dur + 0.2
2588end
2589
2590# ZA
2591def za(start, dur, freq, amp, length1, length2, feedback, feedforward)
2592  s = make_pulse_train(:frequency, freq)
2593  d0 = make_all_pass(:feedback, feedback,
2594                     :feedforward, feedforward,
2595                     :size, length1,
2596                     :max_size, [length1, length2].max + 1)
2597  zenv = make_env(:envelope, [0, 0, 1, 1],
2598                  :scaler, length2 - length1,
2599                  :duration, dur)
2600  run_instrument(start, dur) do
2601    all_pass(d0, amp * pulse_train(s), env(zenv))
2602  end
2603end
2604
2605def za_test(start = 0.0, dur = 1.0)
2606  $now = start
2607  za($now, dur, 100, 0.3, 20, 100, 0.95, 0.95)
2608  $now += dur + 0.2
2609  za($now, dur, 100, 0.3, 100, 20, 0.95, 0.95)
2610  $now += dur + 0.2
2611end
2612
2613# CLM-EXPSRC
2614def clm_expsrc(start, dur, in_file, exp_ratio, src_ratio, amp,
2615               rev = false, start_in_file = 0)
2616  assert_type(File.exist?(in_file), in_file, 0, "an existing file")
2617  stf = (start_in_file * srate(in_file)).floor
2618  fda = make_readin(in_file, :channel, 0, :start, stf)
2619  exa = make_granulate(lambda do |dir|
2620                         readin(fda)
2621                       end, :expansion, exp_ratio)
2622  srca = make_src(lambda do |dir|
2623                    granulate(exa)
2624                  end, :srate, src_ratio)
2625  two_chans = (channels(in_file) == 2) and (channels(@ws_output) == 2)
2626  revit = @reverb and rev
2627  beg = seconds2samples(start)
2628  fin = seconds2samples(dur) + beg
2629  # to satisfy with_sound-option :info and :notehook
2630  with_sound_info(get_func_name, start, dur)
2631  if two_chans
2632    fdb = make_readin(in_file, :channel, 1, :srate, stf)
2633    exb = make_granulate(lambda do |dir|
2634                           readin(fdb)
2635                         end, :expansion, exp_ratio)
2636    srcb = make_src(lambda do |dir|
2637                      granulate(exb)
2638                    end, :srate, src_ratio)
2639    if revit
2640      rev_amp = rev * 0.5
2641      (beg..fin).each do |i|
2642        vala = src(srca) * amp
2643        valb = src(srcb) * amp
2644        outa(i, vala, @ws_output)
2645        outb(i, valb, @ws_output)
2646        outa(i, (vala + valb) * rev_amp, @reverb)
2647      end
2648    else                        # !revit
2649      (beg..fin).each do |i|
2650        outa(i, src(srca) * amp, @ws_output)
2651        outb(i, src(srcb) * amp, @ws_output)
2652      end
2653    end                         # revit
2654  else                          # !two_chans
2655    if revit
2656      rev_amp = rev
2657      (beg..fin).each do |i|
2658        vala = src(srca) * amp
2659        outa(i, vala, @ws_output)
2660        outa(i, vala * rev_amp, @ws_reverb)
2661      end
2662    else                        # !revit
2663      (beg..fin).each do |i|
2664        outa(i, src(srca) * amp, @ws_output)
2665      end
2666    end                         # revit
2667  end                           # two_chans
2668end
2669
2670def clm_expsrc_test(start = 0.0, dur = 1.0)
2671  clm_expsrc(start, dur, "oboe.snd", 2.0, 1.0, 1.0, 0.05)
2672  $now = start + dur + 0.2
2673end
2674
2675# EXP-SND
2676#
2677# granulate with envelopes on the expansion amount, segment envelope
2678# shape, segment length, hop length, and input file resampling rate
2679def exp_snd(file, start, dur, amp,
2680            exp_amt = 1.0, ramp = 0.4, seglen = 0.15,
2681            sr = 1.0, hop = 0.05, ampenv = nil)
2682  assert_type(File.exist?(file), file, 0, "an existing file")
2683  f0 = make_ws_reader(file, :start, 0)
2684  expenv = make_env(:envelope,
2685                    (exp_amt.kind_of?(Array) ?
2686                     exp_amt : [0, exp_amt, 1, exp_amt]),
2687                    :duration, dur)
2688  lenenv = make_env(:envelope,
2689                    (seglen.kind_of?(Array) ?
2690                     seglen : [0, seglen, 1, seglen]),
2691                    :duration, dur)
2692  max_seg_len, initial_seg_len = if seglen
2693                                   if seglen.kind_of?(Array)
2694                                     [max_envelope(seglen), seglen[1]]
2695                                   else
2696                                     [seglen, seglen]
2697                                   end
2698                                 else
2699                                   [0.15, 0.15]
2700                                 end
2701  scaler_amp = ((max_seg_len > 0.15) ? ((0.6 * 0.15) / max_seg_len) : 0.6)
2702  srenv = make_env(:envelope, (sr.kind_of?(Array) ? sr : [0, sr, 1, sr]),
2703                   :duration, dur)
2704  rampdata = (ramp.kind_of?(Array) ? ramp : [0, ramp, 1, ramp])
2705  rampenv = make_env(:envelope, rampdata, :duration, dur)
2706  initial_ramp_time = if ramp
2707                        if ramp.kind_of?(Array)
2708                          ramp[1]
2709                        else
2710                          ramp
2711                        end
2712                      else
2713                        0.4
2714                      end
2715  hopenv = make_env(:envelope, (hop.kind_of?(Array) ? hop : [0, hop, 1, hop]),
2716                    :duration, dur)
2717  max_out_hop, initial_out_hop = if hop
2718                                   if hop.kind_of?(Array)
2719                                     [max_envelope(hop), hop[1]]
2720                                   else
2721                                     [hop, hop]
2722                                   end
2723                                 else
2724                                   [0.05, 0.05]
2725                                 end
2726  min_exp_amt, initial_exp_amt = if exp_amt
2727                                   if exp_amt.kind_of?(Array)
2728                                     [min_envelope(exp_amt), exp_amt[1]]
2729                                   else
2730                                     [exp_amt, exp_amt]
2731                                   end
2732                                 else
2733                                   [1.0, 1.0]
2734                                 end
2735  max_in_hop = max_out_hop / min_exp_amt.to_f
2736  max_len = (@srate * ([max_out_hop, max_in_hop].max + max_seg_len)).ceil
2737  ampe = make_env(:envelope, (ampenv or [0, 0, 0.5, 1, 1, 0]),
2738                  :scaler, amp,
2739                  :duration, dur)
2740  ex_a = make_granulate(:input, lambda do |dir| ws_readin(f0) end,
2741                        :expansion, initial_exp_amt,
2742                        :max_size, max_len,
2743                        :ramp, initial_ramp_time,
2744                        :hop, initial_out_hop,
2745                        :length, initial_seg_len,
2746                        :scaler, scaler_amp)
2747  ex_samp = next_samp = 0.0
2748  vol = env(ampe)
2749  val_a0 = vol * granulate(ex_a)
2750  val_a1 = vol * granulate(ex_a)
2751  if min_envelope(rampdata) <= 0.0 or max_envelope(rampdata) >= 0.5
2752    error("ramp argument to expand must always be between 0.0 and 0.5: %1.3f",
2753          ramp)
2754  else
2755    run_instrument(start, dur) do
2756      expa = env(expenv)  # current expansion amount
2757      segl = env(lenenv)  # current segment length
2758      resa = env(srenv)   # current resampling increment
2759      rmpl = env(rampenv) # current ramp length (0 to 0.5)
2760      hp = env(hopenv)    # current hop size
2761      # now we set the granulate generator internal state to reflect all
2762      # these envelopes
2763      sl = (segl * @srate).floor
2764      rl = (rmpl * sl).floor
2765      vol = env(ampe)
2766      set_mus_length(ex_a, sl)
2767      set_mus_ramp(ex_a, rl)
2768      set_mus_frequency(ex_a, hp)
2769      set_mus_increment(ex_a, expa)
2770      next_samp += resa
2771      if next_samp > (ex_samp + 1)
2772        (next_samp - ex_samp).floor.times do
2773          val_a0, val_a1 = val_a1, vol * granulate(ex_a)
2774          ex_samp += 1
2775        end
2776      end
2777      if next_samp == ex_samp
2778        val_a0
2779      else
2780        val_a0 + (next_samp - ex_samp) * (val_a1 - val_a0)
2781      end
2782    end
2783    close_ws_reader(f0)
2784  end
2785end
2786
2787def exp_snd_test(start = 0.0, dur = 1.0)
2788  $now = start
2789  exp_snd("fyow.snd", $now, dur, 1, [0, 1, 1, 3], 0.4, 0.15,
2790          [0, 2, 1, 0.5], 0.05)
2791  $now += dur + 0.2
2792  exp_snd("oboe.snd", $now, dur, 1, [0, 1, 1, 3], 0.4, 0.15,
2793          [0, 2, 1, 0.5], 0.2)
2794  $now += dur + 0.2
2795end
2796
2797# EXPFIL
2798Grn = Struct.new("Grn",
2799                 :rampval, :rampinc,
2800                 :loc, :segctr, :whichseg, :ramplen, :steadylen, :trigger)
2801
2802def expfil(start, dur, hopsecs, rampsecs, steadysecs, file1, file2)
2803  assert_type(File.exist?(file1), file1, 5, "an existing file")
2804  assert_type(File.exist?(file2), file2, 6, "an existing file")
2805  fil1 = make_file2sample(file1)
2806  fil2 = make_file2sample(file2)
2807  hop = seconds2samples(hopsecs)
2808  ramplen = seconds2samples(rampsecs)
2809  steadylen = seconds2samples(steadysecs)
2810  grn1 = Grn.new(0.0, 1.0 / ramplen, 0, 0, 0, ramplen, steadylen, 0)
2811  grn2 = Grn.new(0.0, 1.0 / ramplen, 0, 0, 0, ramplen, steadylen, 0)
2812  beg = seconds2samples(start)
2813  out1 = beg
2814  out2 = hop + beg
2815  run_instrument(start, dur) do |i|
2816    val = 0.0
2817    if i == out1
2818      inval = ina(grn1.loc, fil1)
2819      grn1.loc += 1
2820      if grn1.whichseg.zero? # ramp-up
2821        inval *= grn1.rampval
2822        grn1.rampval += grn1.rampinc
2823        grn1.segctr += 1
2824        if grn1.segctr == grn1.ramplen
2825          grn1.segctr = 0
2826          grn1.whichseg += 1
2827        end
2828      else
2829        if grn1.whichseg == 1 # steady-state
2830          grn1.segctr += 1
2831          if grn1.segctr == grn1.steadylen
2832            grn1.segctr = 0
2833            grn1.whichseg += 1
2834          end
2835        else # ramp-down
2836          inval *= grn1.rampval
2837          grn1.segctr += 1
2838          grn1.rampval -= grn1.rampinc
2839          if grn1.segctr == grn1.ramplen
2840            grn1.segctr = 0
2841            grn1.trigger = 1
2842            grn1.whichseg = 0
2843            grn1.rampval = 0.0
2844          end
2845        end
2846      end
2847      val += inval
2848      out1 += 1
2849      if grn1.trigger == 1
2850        grn1.trigger = 0
2851        out1 += hop
2852      end
2853    end
2854    if i == out2
2855      inval = ina(grn2.loc, fil2)
2856      grn2.loc += 1
2857      if grn2.whichseg.zero? # ramp-up
2858        inval *= grn2.rampval
2859        grn2.rampval += grn2.rampinc
2860        grn2.segctr += 1
2861        if grn2.segctr == grn2.ramplen
2862          grn2.segctr = 0
2863          grn2.whichseg += 1
2864        end
2865      else
2866        if grn2.whichseg == 1 # steady-state
2867          grn2.segctr += 1
2868          if grn2.segctr == grn2.steadylen
2869            grn2.segctr = 0
2870            grn2.whichseg += 1
2871          end
2872        else # ramp-down
2873          inval *= grn2.rampval
2874          grn2.segctr += 1
2875          grn2.rampval -= grn2.rampinc
2876          if grn2.segctr == grn2.ramplen
2877            grn2.segctr = 0
2878            grn2.trigger = 1
2879            grn2.whichseg = 0
2880            grn2.rampval = 0.0
2881          end
2882        end
2883      end
2884      val += inval
2885      out2 += 1
2886      if grn2.trigger == 1
2887        grn2.trigger = 0
2888        out2 += hop
2889      end
2890    end
2891    val
2892  end
2893end
2894
2895def expfil_test(start = 0.0, dur = 1.0)
2896  expfil(start, dur, 0.2, 0.01, 0.1, "oboe.snd", "fyow.snd")
2897  $now = start + dur + 0.2
2898end
2899
2900# GRAPH-EQ
2901#
2902=begin
2903From: Marco Trevisani <marco@ccrma.Stanford.EDU>
2904
2905This should work like a Graphic Equalizer....
2906Very easy to use. Just some note:
2907
2908"amp" & "amp-env" apply an enveloppe to the final result of the
2909filtering.
2910
2911"dur" as ""standard"" in my instruments, when dur = 0 it will take the length
2912of the sndfile input, otherwise the duration in seconds.
2913
2914"gain-freq-list" is a list of gains and frequencies to
2915filter --in this order gain and frequencies--. There is no limit to
2916the size of the list. Gain can be a number or an
2917envelope. Unfortunatelly in this version they cant alternate, one
2918should chose, all envelopes or all numbers i.e.:
2919case 1 -> '( .1 440.0 .3 1500.0 .2 330.0 ...etc) or
2920case 2 -> '((0 .1 1 .5) 440.0 (0 1 1 .01) 1500 (0 .3 1 .5) 330.0 ...etc)
2921'( .1 440.0 (0 1 1 .01) 1500 ..etc) <<< again, this is not allowed ..
2922
2923"offset-gain" This apply to all the gains if case 1. It adds or
2924subtracts an offset to all the gains in the list. This number can be positive
2925or negative. In case the result is a negative number --let's say offset =
2926-.4 and, like in case 1, the first gain is .1, the result would be
2927-.3 -- the instrument will pass a gain equal to 0.
2928
2929"filt-gain-scale" & "filt-gain-base" will apply to the elements of the
2930envelopes if we are in case 2, gains are envelopes.
2931
2932"stats" if #t --default-- prints the number of seconds processed, if
2933nil doesnt print anything, which will speed up a bit the process.
2934=end
2935#
2936def graph_eq(file, start, dur, *args)
2937  assert_type(File.exist?(file), file, 0, "an existing file")
2938  or_beg, amplitude, amp_env, amp_base, offset_gain = nil
2939  gain_freq_list, filt_gain_scale, filt_gain_base, a1 = nil
2940  optkey(args, binding,
2941         [:or_beg, 0],
2942         [:amplitude, 1],
2943         [:amp_env, [0, 1, 0.8, 1, 1, 0]],
2944         [:amp_base, 1],
2945         [:offset_gain, 0],
2946         [:gain_freq_list, [[0, 1, 1, 0], 440, [0, 0, 1, 1], 660]],
2947         [:filt_gain_scale, 1],
2948         [:filt_gain_base, 1],
2949         [:a1, 0.99])
2950  durata = (dur.zero? ? ws_duration(file) : dur)
2951  len = seconds2samples(durata)
2952  or_start = (or_beg * ws_srate(file)).round
2953  rd_a = make_ws_reader(file, :start, or_start)
2954  half_list = gain_freq_list.length / 2
2955  ampenv = make_env(:envelope, amp_env,
2956                    :scaler, amplitude,
2957                    :duration, durata,
2958                    :base, amp_base)
2959  gain_list = []
2960  0.step(gain_freq_list.length - 1, 2) do |i|
2961    gain_list << gain_freq_list[i]
2962  end
2963  freq_list = []
2964  1.step(gain_freq_list.length - 1, 2) do |i|
2965    freq_list << gain_freq_list[i]
2966  end
2967  if_list_in_gain = gain_list[0].kind_of?(Array)
2968  env_size = (if_list_in_gain ? Array.new(freq_list.length) : nil)
2969  frm_size = Array.new(freq_list.length)
2970  gains = Vct.new(len, 1.0)
2971  half_list.times do |i|
2972    gval = gain_list[i]
2973    fval = freq_list[i]
2974    if gval.kind_of?(Array)
2975      env_size[i] = make_env(:envelope, gval,
2976                             :scaler, filt_gain_scale,
2977                             :duration, durata,
2978                             :base, filt_gain_base)
2979      frm_size[i] = make_formant(fval, a1)
2980    else
2981      gains[i] = (offset_gain + gval < 0) ? 0 : (offset_gain + gain)
2982      frm_size[i] = make_formant(fval, a1)
2983    end
2984  end
2985  run_instrument(start, durata) do
2986    outval = 0.0
2987    inval = ws_readin(rd_a)
2988    half_list.times do |j|
2989      if if_list_in_gain
2990        gains[j] = env(env_size[j]) * (1.0 - a1)
2991      end
2992      outval = outval + gains[j] * formant(frm_size[j], inval)
2993    end
2994    env(ampenv) * outval
2995  end
2996  close_ws_reader(rd_a)
2997end
2998
2999def graph_eq_test(start = 0.0, dur = 1.0)
3000  graph_eq("oboe.snd", start, dur, :amplitude, 50.0)
3001  $now = start + dur + 0.2
3002end
3003
3004# ANOI
3005#
3006# a kind of noise reduction -- on-going average spectrum is squelched
3007# to some extent obviously aimed at intermittent signal in background
3008# noise
3009# this is based on Perry Cook's Scrubber.m
3010def anoi(infile, start, dur, fftsize = 128, amp_scaler = 1.0, r = TWO_PI)
3011  assert_type(File.exist?(infile), infile, 0, "an existing file")
3012  freq_inc = (fftsize / 2).floor
3013  fdi = make_vct(fftsize)
3014  fdr = make_vct(fftsize)
3015  spectr = make_vct(freq_inc, 1.0)
3016  scales = make_vct(freq_inc, 1.0)
3017  diffs = make_vct(freq_inc)
3018  win = make_fft_window(Blackman2_window, fftsize)
3019  k = 0
3020  amp = 0.0
3021  incr = amp_scaler * 4.0 / @srate
3022  file = make_file2sample(infile)
3023  radius = 1.0 - r / fftsize.to_f
3024  bin = @srate / fftsize
3025  fs = make_array(freq_inc) do |i|
3026    make_formant(i * bin, radius)
3027  end
3028  samp = 0
3029  run_instrument(start, dur) do
3030    inval = file2sample(file, samp)
3031    samp += 1
3032    fdr[k] = inval
3033    k += 1
3034    amp += incr if amp < amp_scaler
3035    if k >= fftsize
3036      k = 0
3037      spectrum(fdr, fdi, win, 1)
3038      freq_inc.times do |j|
3039        spectr[j] = 0.9 * spectr[j] + 0.1 * fdr[j]
3040        if spectr[j] >= fdr[j]
3041          diffs[j] = scales[j] / -fftsize
3042        else
3043          diffs[j] = ((fdr[j] - spectr[j]) / fdr[j] - scales[j]) / fftsize
3044        end
3045      end
3046    end
3047    outval = 0.0
3048    1.upto(freq_inc - 1) do |j|
3049      cur_scale = scales[j]
3050      outval = outval + cur_scale * formant(fs[j], inval)
3051      scales[j] += diffs[j]
3052    end
3053    amp * outval
3054  end
3055end
3056
3057def anoi_test(start = 0.0, dur = 1.0)
3058  anoi("fyow.snd", start, dur, 128, 2.0)
3059  $now = start + dur + 0.2
3060end
3061
3062=begin
3063Date: Fri, 25 Sep 1998 09:56:41 +0300
3064From: Matti Koskinen <mjkoskin@sci.fi>
3065To: linux-audio-dev@ginette.musique.umontreal.ca
3066Subject: [linux-audio-dev] Announce: alpha version of denoising
3067[...]
3068  I wrote a simple denoiser called anoi after it's parent
3069  clm-instrument anoi.ins.
3070
3071  anoi tries to remove white noise like tape hiss from wav-
3072  files. Removing of noise succeeds ok, but depending of the
3073  original sound, some distortion can be audible.
3074
3075  If someone is interested, http://www.sci.fi/~mjkoskin
3076  contains tarred and gzipped file.
3077
3078  Now only monophonic wav-files can be denoised, but adding
3079  others isn't too difficult.
3080
3081-matti
3082mjkoskin@sci.fi
3083=end
3084
3085# FULLMIX
3086#
3087# ;; "matrix" can be a simple amplitude or a list of lists each inner
3088# ;;     list represents one input channel's amps into one output channel
3089# ;;     each element of the list can be a number, a list (turned into an
3090# ;;     env) or an env
3091# ;;
3092# ;; "srate" can be a negative number (read in reverse), or an envelope.
3093def fullmix(in_file,
3094            start = 0.0,
3095            outdur = false,
3096            inbeg = 0.0,
3097            matrix = false,
3098            srate = false,
3099            reverb_amount = false)
3100  unless File.exist?(in_file)
3101    Snd.raise(:no_such_file, in_file, "no such file")
3102  end
3103  unless start
3104    start = 0.0
3105  end
3106  unless inbeg
3107    inbeg = 0.0
3108  end
3109  if number?(outdur)
3110    dur = outdur
3111  else
3112    sr = number?(srate) ? srate.abs : 1.0
3113    dur = (mus_sound_duration(in_file) - inbeg) / sr
3114  end
3115  in_chans = channels(in_file)
3116  reversed = ((number?(srate) and srate.negative?) or
3117              (array?(srate) and srate.cadr.negative?))
3118  inloc = (Float(inbeg) * mus_sound_srate(in_file)).round
3119  ochans = [in_chans, @channels].max
3120  if @ws_reverb and number?(reverb_amount) and reverb_amount.positive?
3121    rev_mx = Vct.new(in_chans * in_chans, reverb_amount)
3122  else
3123    rev_mx = false
3124  end
3125  dir = (reversed ? -1 : 1)
3126  if (not srate) or (number?(srate) and srate == 1.0)
3127    file = make_file2frample(in_file)
3128  else
3129    file = make_array(in_chans) do |i|
3130      make_readin(in_file, i, inloc, :direction, dir)
3131    end
3132  end
3133  envs = false
3134  if array?(srate)
3135    srcenv = make_env(srate, :duration, dur, :scaler, Float(dir))
3136  else
3137    srcenv = false
3138  end
3139  case matrix
3140  when Array
3141    mx = Vct.new(ochans * ochans, 0.0)
3142    matrix.each_with_index do |inlist, inp|
3143      break if inp >= in_chans
3144      inlist.each_with_index do |outn, outp|
3145        break if outp >= @channels
3146        case outn
3147        when Numeric
3148          # mx[inp][outp] = outn
3149          mx[inp * ochans + outp] = outn
3150        when Array, Mus
3151          unless envs
3152            envs = Array.new(in_chans * @channels, false)
3153          end
3154          if env?(outn)
3155            envs[inp * @channels + outp] = outn
3156          else
3157            envs[inp * @channels + outp] = make_env(outn, :duration, dur)
3158          end
3159        else
3160          Snd.warning("unknown element in matrix: %p", outn)
3161        end
3162      end
3163    end
3164  when Numeric
3165    # ; matrix is a number in this case (a global scaler)
3166    mx = Vct.new(ochans * ochans, matrix)
3167  else
3168    mx = Vct.new(ochans * ochans, 1.0)
3169  end
3170  # to satisfy with_sound-option :info and :notehook
3171  with_sound_info(get_func_name, start, dur)
3172  beg = seconds2samples(start)
3173  samps = seconds2samples(dur)
3174  if (not array?(file))
3175    mxe = envs
3176    if envs
3177      mxe = Array.new(in_chans) do |i|
3178        Array.new(@channels) do |j|
3179          envs[i * @channels + j]
3180        end
3181      end
3182    end
3183    if sound?(@ws_output)
3184      output = file_name(@ws_output)
3185      if sound?(@ws_reverb)
3186        revout = file_name(@ws_reverb)
3187      end
3188    else
3189      output = @ws_output
3190      revout = @ws_reverb
3191    end
3192    mus_file_mix(output, file, beg, samps, inloc, mx, mxe)
3193    if rev_mx
3194      mus_file_mix(revout, file, beg, samps, inloc, rev_mx)
3195    end
3196  else
3197    if sound?(@ws_output)
3198      Snd.raise(:wrong_type_arg, "don't use :to_snd true")
3199    end
3200    sr = (number?(srate) ? srate.abs : 0.0)
3201    srcs = Array.new(in_chans) do |i|
3202      make_src(:input, file[i], :srate, sr)
3203    end
3204    mus_file_mix_with_envs(file, beg, samps, mx, rev_mx, envs, srcs, srcenv,
3205                           @ws_output, @ws_reverb)
3206  end
3207end
3208
3209def fullmix_test(start = 0.0, dur = 1.0)
3210  $now = start
3211  fullmix("pistol.snd", $now, dur)
3212  $now += dur + 0.2
3213  fullmix("oboe.snd", $now, dur, 0,
3214          [[0.1, make_env([0, 0, 1, 1], :duration, dur, :scaler, 0.5)]])
3215  $now += dur + 0.2
3216end
3217
3218# Original header:
3219
3220# ;;; grani: a granular synthesis instrument
3221# ;;;   by Fernando Lopez-Lezcano
3222# ;;;   http://ccrma.stanford.edu/~nando/clm/grani/
3223# ;;;
3224# ;;;   Original grani.ins instrument written for the 220a Course by
3225# ;;;   Fernando Lopez-Lezcano & Juan Pampin, November 6 1996
3226# ;;;
3227# ;;; Mar 21 1997: working with hop and grain-dur envelopes
3228# ;;; Mar 22 1997: working with src envelope (grain wise) & src spread
3229# ;;; Jan 26 1998: started work on new version
3230# ;;; Nov  7 1998: input soundfile duration calculation wrong
3231# ;;; Nov 10 1998: bug in in-samples (thanks to Kristopher D. Giesing for this one)
3232# ;;; Dec 20 1998: added standard locsig code
3233# ;;; Feb 19 1999: added "nil" as default value of where to avoid warning (by bill)
3234# ;;; Jan 10 2000: added input-channel to select which channel of the input file
3235# ;;;              to process.
3236# ;;;              added grain-start-in-seconds to be able to specify input file
3237# ;;;              locations in seconds for the grain-start envelope
3238# ;;; May 06 2002: fixed array passing of where-bins in clisp (reported by Charles
3239# ;;;              Nichols and jennifer l doering
3240# ;;; Mar 27 2003: added option for sending grains to all channels (requested by
3241# ;;;              Oded Ben-Tal)
3242
3243# ;;; calculate a random spread around a center of 0
3244def random_spread(spread)
3245  spread.nonzero? ? (random(spread) - spread / 2.0) : 0.0
3246end
3247
3248# ;;; create a constant envelope if argument is a number
3249def envelope_or_number(val)
3250  assert_type((number?(val) or array?(val) or vct?(val)),
3251              val, 0, "a number, an array or a vct")
3252  case val
3253  when Numeric
3254    [0, Float(val), 1, Float(val)]
3255  when Vct
3256    val.to_a
3257  when Array
3258    val
3259  end
3260end
3261
3262# ;;; create a vct from an envelope
3263def make_gr_env(env, length = 512)
3264  length_1 = (length - 1).to_f
3265  make_vct!(length) do |i|
3266    envelope_interp(i / length_1, env)
3267  end
3268end
3269
3270# ;;; Grain envelopes
3271def raised_cosine(*args)
3272  duty_cycle, length = nil
3273  optkey(args, binding,
3274         [:duty_cycle, 100],
3275         [:length, 128])
3276  active = length * duty_cycle.to_f * 0.01
3277  incr = PI / (active - 1.0)
3278  start = (length - active) / 2.0
3279  fin = (length + active) / 2.0
3280  s = -1
3281  make_vct!(length) do |i|
3282    sine = if i >= start and i < fin
3283             s += 1
3284             sin(s * incr)
3285           else
3286             0.0
3287           end
3288    sine * sine
3289  end
3290end
3291
3292# ;;;=============================================================================
3293# ;;; Granular synthesis instrument
3294# ;;;=============================================================================
3295#
3296# ;;; input-channel:
3297# ;;;   from which channel in the input file are samples read
3298# ;;; amp-envelope:
3299# ;;;   amplitude envelope for the note
3300# ;;; grain-envelope:
3301# ;;; grain-envelope-end:
3302# ;;;   envelopes for each individual grain. The envelope applied in the result
3303# ;;;   of interpolating both envelopes. The interpolation is controlled by
3304# ;;;   grain-envelope-trasition. If "grain-envelope-end" is nil interpolation
3305# ;;;   is turned off and only grain-envelope is applied to the grains.
3306# ;;; grain-envelope-trasition:
3307# ;;;   an enveloper that controls the interpolation between the two grain envelopes
3308# ;;;   0 -> selects "grain-envelope"
3309# ;;;   1 -> selects "grain-envelope-end"
3310# ;;; grain-envelope-array-size
3311# ;;;   size of the array passed to make-table-lookup
3312# ;;; grain-duration:
3313# ;;;   envelope that controls grain duration in seconds
3314# ;;; srate-linear:
3315# ;;;   t -> sample rate envelope is linear
3316# ;;;   nil -> sample rate envelope is exponential
3317# ;;; srate:
3318# ;;;   envelope that controls sample rate conversion. The envelope is an
3319# ;;;   exponential envelope, the base and error bound of the conversion
3320# ;;;   are controlled by "srate-base" and "srate-error".
3321# ;;; srate-spread:
3322# ;;;   random spread of sample rate conversion around "srate"
3323# ;;; srate-base:
3324# ;;;   base for the exponential conversion
3325# ;;;   for example: base = (expt 2 (/ 12)) creates a semitone envelope
3326# ;;; srate-error:
3327# ;;;   error bound for the exponential conversion.
3328# ;;; grain-start:
3329# ;;;   envelope that determines the starting point of the current grain in
3330# ;;;   the input file. "y"->0 starts the grain at the beginning of the input
3331# ;;;   file. "y"->1 starts the grain at the end of the input file.
3332# ;;; grain-start-spread:
3333# ;;;   random spread around the value of "grain-start"
3334# ;;; grain-start-in-seconds:
3335# ;;;   nil -> grain-start y envelope expressed in percent of the duration of the input file
3336# ;;;   t   -> grain-start y envelope expressed in seconds
3337# ;;; grain-density:
3338# ;;;   envelope that controls the number of grains per second generated in the output file
3339
3340# ;;; grain-density-spread:
3341
3342Grani_to_locsig            = 0
3343Grani_to_grain_duration    = 1
3344Grani_to_grain_start       = 2
3345Grani_to_grain_sample_rate = 3
3346Grani_to_grain_random      = 4
3347Grani_to_grain_allchans    = 5
3348
3349def grani(start, dur, amp, file, *args)
3350  assert_type(File.exist?(file), file, 3, "an existing file")
3351  input_channel = nil
3352  grains, amp_envelope, grain_envelope, grain_envelope_end = nil
3353  grain_envelope_transition, grain_envelope_array_size, grain_duration = nil
3354  grain_duration_spread, grain_duration_limit, srate, srate_spread = nil
3355  srate_linear, srate_base, srate_error, grain_start, grain_start_spread = nil
3356  grain_start_in_seconds, grain_density, grain_density_spread = nil
3357  reverb_amount, reverse, where_to, where_bins, grain_distance = nil
3358  grain_distance_spread, grain_degree, grain_degree_spread = nil
3359  optkey(args, binding,
3360         [:input_channel, 0],
3361         [:grains, 0],
3362         [:amp_envelope, [0, 0, 0.3, 1, 0.7, 1, 1, 0]],
3363         [:grain_envelope, [0, 0, 0.3, 1, 0.7, 1, 1, 0]],
3364         [:grain_envelope_end, false],
3365         [:grain_envelope_transition, [0, 0, 1, 1]],
3366         [:grain_envelope_array_size, 512],
3367         [:grain_duration, 0.1],
3368         [:grain_duration_spread, 0.0],
3369         [:grain_duration_limit, 0.002],
3370         [:srate, 0.0],
3371         [:srate_spread, 0.0],
3372         [:srate_linear, false],
3373         [:srate_base, 2.0 ** (1.0 / 12)],
3374         [:srate_error, 0.01],
3375         [:grain_start, [0, 0, 1, 1]],
3376         [:grain_start_spread, 0.0],
3377         [:grain_start_in_seconds, false],
3378         [:grain_density, 10.0],
3379         [:grain_density_spread, 0.0],
3380         [:reverb_amount, 0.01],
3381         [:reverse, false],
3382         [:where_to, 0],
3383         [:where_bins, []],
3384         [:grain_distance, 1.0],
3385         [:grain_distance_spread, 0.0],
3386         [:grain_degree, 45.0],
3387         [:grain_degree_spread, 0.0])
3388  beg, fin = times2samples(start, dur)
3389  in_file_channels = ws_channels(file)
3390  in_file_sr       = ws_srate(file)
3391  in_file_dur      = ws_duration(file)
3392  rd = make_ws_reader(file,
3393                      :channel, [input_channel, in_file_channels - 1].min,
3394                      :vct?, true)
3395  in_file_reader   = make_src(:input, lambda do |dir| ws_readin(rd) end,
3396                              :srate, 1.0)
3397  set_mus_increment(in_file_reader, -1) if reverse
3398  last_in_sample   = (in_file_dur * in_file_sr).round
3399  srate_ratio      = in_file_sr / mus_srate()
3400  sr_env = make_env(:envelope, if srate_linear
3401                                 envelope_or_number(srate)
3402                               else
3403                                 exp_envelope(envelope_or_number(srate),
3404                                              :base, srate_base,
3405                                              :error, srate_error)
3406                               end,
3407                    :scaler, srate_ratio,
3408                    :duration, dur)
3409  sr_spread_env = make_env(:envelope, envelope_or_number(srate_spread),
3410                           :duration, dur)
3411  amp_env = make_env(:envelope, amp_envelope, :scaler, amp, :duration, dur)
3412  gr_dur = make_env(:envelope, envelope_or_number(grain_duration),
3413                    :duration, dur)
3414  gr_dur_spread = make_env(:envelope, envelope_or_number(grain_duration_spread),
3415                           :duration, dur)
3416  gr_start_scaler = (grain_start_in_seconds ? 1.0 : in_file_dur)
3417  gr_start = make_env(:envelope, envelope_or_number(grain_start),
3418                      :duration, dur)
3419  gr_start_spread = make_env(:envelope, envelope_or_number(grain_start_spread),
3420                             :duration, dur)
3421  gr_dens_env = make_env(:envelope, envelope_or_number(grain_density),
3422                         :duration, dur)
3423  gr_dens_spread_env = make_env(:envelope,
3424                                envelope_or_number(grain_density_spread),
3425                                :duration, dur)
3426  if vct?(grain_envelope)
3427    ge = grain_envelope
3428  else
3429    ge = make_gr_env(grain_envelope, grain_envelope_array_size)
3430  end
3431  gr_env = make_table_lookup(:frequency, 1.0, :initial_phase, 0, :wave, ge)
3432  if grain_envelope_end
3433    if vct?(grain_envelope_end)
3434      ge = grain_envelope_end
3435    else
3436      ge = make_gr_env(grain_envelope_end, grain_envelope_array_size)
3437    end
3438  else
3439    ge = make_vct(512)
3440  end
3441  gr_env_end = make_table_lookup(:frequency, 1.0, :initial_phase, 0, :wave, ge)
3442  gr_int_env = make_env(:envelope,
3443                        envelope_or_number(grain_envelope_transition),
3444                        :duration, dur)
3445  gr_dist = make_env(:envelope, envelope_or_number(grain_distance),
3446                     :duration, dur)
3447  gr_dist_spread = make_env(:envelope,
3448                            envelope_or_number(grain_distance_spread),
3449                            :duration, dur)
3450  gr_degree = make_env(:envelope, envelope_or_number(grain_degree),
3451                       :duration, dur)
3452  gr_degree_spread = make_env(:envelope,
3453                              envelope_or_number(grain_degree_spread),
3454                              :duration, dur)
3455  gr_start_sample = beg
3456  gr_samples = 0
3457  gr_offset = 1
3458  gr_dens = 0.0
3459  gr_dens_spread = 0.0
3460  grain_counter = 0
3461  samples = 0
3462  first_grain = true
3463  case grain_duration
3464  when Numeric
3465    dur += grain_duration
3466  when Array
3467    dur += grain_duration.last
3468  end
3469  run_instrument(start, dur, :degree, 45.0) do
3470    if gr_offset < gr_samples
3471      gr_offset += 1
3472      (if grain_envelope_end
3473         gr_where = env(gr_int_env)
3474         (1 - gr_where) * table_lookup(gr_env) +
3475           gr_where * table_lookup(gr_env_end)
3476       else
3477         table_lookup(gr_env)
3478       end) * env(amp_env) * src(in_file_reader)
3479    else
3480      if first_grain
3481        first_grain = false
3482        gr_start_sample = beg
3483      else
3484        gr_start_sample += seconds2samples(1.0 / (gr_dens + gr_dens_spread))
3485        if (gr_start_sample > fin) or
3486          (grains.nonzero? and (grain_counter >= grains))
3487          break
3488        end
3489      end
3490      gr_offset = 0
3491      gr_from_beg = gr_start_sample - beg
3492      set_mus_location(amp_env, gr_from_beg)
3493      set_mus_location(gr_dur, gr_from_beg)
3494      set_mus_location(gr_dur_spread, gr_from_beg)
3495      set_mus_location(sr_env, gr_from_beg)
3496      set_mus_location(sr_spread_env, gr_from_beg)
3497      set_mus_location(gr_start, gr_from_beg)
3498      set_mus_location(gr_start_spread, gr_from_beg)
3499      set_mus_location(gr_dens_env, gr_from_beg)
3500      set_mus_location(gr_dens_spread_env, gr_from_beg)
3501      in_start_value = env(gr_start) * gr_start_scaler +
3502        random_spread(env(gr_start_spread) * gr_start_scaler)
3503      in_start = (in_start_value * in_file_sr).round
3504      gr_duration = [grain_duration_limit,
3505        env(gr_dur) + random_spread(env(gr_dur_spread))].max
3506      gr_samples = seconds2samples(gr_duration)
3507      gr_srate = if srate_linear
3508                   env(sr_env) + random_spread(env(sr_spread_env))
3509                 else
3510                   env(sr_env) * srate_base ** random_spread(env(sr_spread_env))
3511                 end
3512      set_mus_increment(in_file_reader, gr_srate)
3513      in_samples = (gr_samples / (1.0 / srate_ratio)).round
3514      set_mus_phase(gr_env, 0.0)
3515      set_mus_phase(gr_env_end, 0.0)
3516      set_mus_frequency(gr_env, 1.0 / gr_duration)
3517      set_mus_frequency(gr_env_end, 1.0 / gr_duration)
3518      gr_dens = env(gr_dens_env)
3519      gr_dens_spread = random_spread(env(gr_dens_spread_env))
3520      samples += gr_samples
3521      grain_counter += 1
3522      where = case where_to
3523              when Grani_to_grain_duration
3524                gr_duration
3525              when Grani_to_grain_start
3526                in_start_value
3527              when Grani_to_grain_sample_rate
3528                gr_srate
3529              when Grani_to_grain_random
3530                random(1.0)
3531              else
3532                Grani_to_locsig
3533              end
3534      if where.nonzero? and where_bins.length > 0
3535        (where_bins.length - 1).times do |chn|
3536          locsig_set!(@locsig, chn,
3537                      (where.between?(where_bins[chn], where_bins[chn + 1]) ?
3538                       1.0 :
3539                       0.0))
3540        end
3541      else
3542        if where_to == Grani_to_grain_allchans
3543          @channels.times do |chn|
3544            locsig_set!(@locsig, chn, 1.0)
3545          end
3546        else
3547          set_mus_location(gr_dist, gr_from_beg)
3548          set_mus_location(gr_dist_spread, gr_from_beg)
3549          set_mus_location(gr_degree, gr_from_beg)
3550          set_mus_location(gr_degree_spread, gr_from_beg)
3551          deg = env(gr_degree) + random_spread(env(gr_degree_spread))
3552          dist = env(gr_dist) + random_spread(env(gr_dist_spread))
3553          dist_scl = 1.0 / [dist, 1.0].max
3554          if sample2file?(@ws_reverb)
3555            locsig_reverb_set!(@locsig, 0,
3556                               reverb_amount * (1.0 / sqrt([dist, 1.0].max)))
3557          end
3558          if @channels == 1
3559            locsig_set!(@locsig, 0, dist_scl)
3560          else
3561            if @channels == 2
3562              frac = [90.0, [0.0, deg].max].min / 90.0
3563              locsig_set!(@locsig, 0, dist_scl * (1.0 - frac))
3564              locsig_set!(@locsig, 1, dist_scl * frac)
3565            else
3566              if @channels > 2
3567                locsig_set!(@locsig, 0, if deg.between?(0, 90)
3568                                          dist_scl * ((90.0 - deg) / 90.0)
3569                                        else
3570                                          if deg.between?(270, 360)
3571                                            dist_scl * ((deg - 270.0) / 90.0)
3572                                          else
3573                                            0.0
3574                                          end
3575                                        end)
3576                locsig_set!(@locsig, 1, if deg.between?(90, 180)
3577                                          dist_scl * (180.0 - deg) / 90.0
3578                                        else
3579                                          if deg.between?(0, 90)
3580                                            dist_scl * (deg / 90.0)
3581                                          else
3582                                            0.0
3583                                          end
3584                                        end)
3585                locsig_set!(@locsig, 2, if deg.between?(180, 270)
3586                                          dist_scl * (270.0 - deg) / 90.0
3587                                        else
3588                                          if deg.between?(90, 180)
3589                                            dist_scl * (deg - 90.0) / 90.0
3590                                          else
3591                                            0.0
3592                                          end
3593                                        end)
3594                if @channels > 3
3595                  locsig_set!(@locsig, 3, if deg.between?(270, 360)
3596                                            dist_scl * (360.0 - deg) / 90.0
3597                                          else
3598                                            if deg.between?(180, 270)
3599                                              dist_scl * (deg - 180.0) / 90.0
3600                                            else
3601                                              0.0
3602                                            end
3603                                          end)
3604                end
3605              end
3606            end
3607          end
3608        end
3609      end
3610      in_start = if (in_start + in_samples) > last_in_sample
3611                   last_in_sample - in_samples
3612                 else
3613                   [in_start, 0].max
3614                 end
3615      set_ws_location(rd, in_start)
3616      0.0
3617    end
3618  end
3619  close_ws_reader(rd)
3620end
3621
3622def grani_test(start = 0.0, dur = 1.0)
3623  grani(start, dur, 5.0, "oboe.snd", :grain_envelope, raised_cosine())
3624  $now = start + dur + 0.2
3625end
3626
3627# BES-FM
3628def bes_fm(start, dur, freq, amp, ratio, index)
3629  car_ph = mod_ph = 0.0
3630  car_incr = hz2radians(freq)
3631  mod_incr = ratio.to_f * car_incr
3632  ampenv = make_env(:envelope, [0, 0, 25, 1, 75, 1, 100, 0],
3633                    :scaler, amp,
3634                    :duration, dur)
3635  run_instrument(start, dur) do
3636    out_val = env(ampenv) * bes_j1(car_ph)
3637    car_ph = car_ph + car_incr + index.to_f * bes_j1(mod_ph)
3638    mod_ph += mod_incr
3639    out_val
3640  end
3641end
3642
3643def bes_fm_test(start = 0.0, dur = 1.0)
3644  bes_fm(start, dur, 440, 10, 1, 4)
3645  $now = start + dur + 0.2
3646end
3647
3648# SSB_FM
3649class Ssb_fm < Musgen
3650  def initialize(freq)
3651    super()
3652    @frequency = freq
3653    @osc1 = make_oscil(freq, 0)
3654    @osc2 = make_oscil(freq, HALF_PI)
3655    @osc3 = make_oscil(0, 0)
3656    @osc4 = make_oscil(0, HALF_PI)
3657    @hilbert = make_hilbert_transform(40)
3658    @delay = make_delay(40)
3659  end
3660
3661  def inspect
3662    format("%s.new(%s)", self.class, @frequency)
3663  end
3664
3665  def to_s
3666    format("#<%s freq: %s>", self.class, @frequency)
3667  end
3668
3669  def run_func(val1 = 0.0, val2 = 0.0)
3670    ssb_fm(val1)
3671  end
3672
3673  def ssb_fm(modsig)
3674    am0 = oscil(@osc1)
3675    am1 = oscil(@osc2)
3676    car0 = oscil(@osc3, hilbert_transform(@hilbert, modsig))
3677    car1 = oscil(@osc4, delay(@delay, modsig))
3678    am0 * car0 + am1 * car1
3679  end
3680end
3681
3682def make_ssb_fm(freq = 440.0)
3683  Ssb_fm.new(freq)
3684end
3685
3686def ssb_fm?(obj)
3687  obj.kind_of?(Ssb_fm)
3688end
3689
3690def ssb_fm(gen, modsig = 0.0)
3691  gen.ssb_fm(modsig)
3692end
3693
3694# FM2
3695class Fm2 < Musgen
3696  def initialize(f1, f2, f3, f4, p1, p2, p3, p4)
3697    super()
3698    @osc1 = make_oscil(f1, p1)
3699    @osc2 = make_oscil(f2, p2)
3700    @osc3 = make_oscil(f3, p3)
3701    @osc4 = make_oscil(f4, p4)
3702  end
3703
3704  def inspect
3705    format("%s.new(%s, %s, %s, %s, %s, %s, %s, %s)",
3706           self.class, @f1, @f2, @f3, @f4, @p1, @p2, @p3, @p4)
3707  end
3708
3709  def to_s
3710    format("#<%s %1.3f, %1.3f, %1.3f, %1.3f, %1.3f, %1.3f, %1.3f, %1.3f>",
3711           self.class, @f1, @f2, @f3, @f4, @p1, @p2, @p3, @p4)
3712  end
3713
3714  def run_func(val1 = 0.0, val2 = 0.0)
3715    fm2(val1)
3716  end
3717
3718  def fm2(index)
3719    (oscil(@osc1, index * oscil(@osc2)) +
3720     oscil(@osc3, index * oscil(@osc4))) * 0.25
3721  end
3722end
3723
3724# make_fm2(1000, 100, 1000, 100, 0, 0, HALF_PI, HALF_PI)
3725# make_fm2(1000, 100, 1000, 100, 0, 0, 0, HALF_PI)
3726def make_fm2(f1, f2, f3, f4, p1, p2, p3, p4)
3727  Fm2.new(f1, f2, f3, f4, p1, p2, p3, p4)
3728end
3729
3730def fm2?(obj)
3731  obj.kind_of?(Fm2)
3732end
3733
3734def fm2(gen, index = 0.0)
3735  gen.fm2(index)
3736end
3737
3738def clm_ins_test(start = 0.0, dur = 1.0)
3739  $now = start
3740  violin_test($now, dur)
3741  fm_violin_test($now, dur)
3742  pluck_test($now, dur)
3743  vox_test($now, dur)
3744  fofins_test($now, dur)
3745  fm_trumpet_test($now, dur)
3746  pqw_vox_test($now, dur)
3747  flute_test($now, dur)
3748  fm_bell_test($now, dur)
3749  fm_insect_test($now, dur)
3750  fm_drum_test($now, dur)
3751  gong_test($now, dur)
3752  attract_test($now, dur)
3753  pqw_test($now, dur)
3754  tubebell_test($now, dur)
3755  wurley_test($now, dur)
3756  rhodey_test($now, dur)
3757  hammondoid_test($now, dur)
3758  metal_test($now, dur)
3759  drone_canter_test($now, dur)
3760  reson_test($now, dur)
3761  cellon_test($now, dur)
3762  gran_synth_test($now, dur)
3763  touch_tone_test($now, dur)
3764  spectra_test($now, dur)
3765  two_tab_test($now, dur)
3766  lbj_piano_test($now, dur)
3767  resflt_test($now, dur)
3768  scratch_test($now, dur)
3769  pins_test($now, dur)
3770  zc_test($now, dur)
3771  zn_test($now, dur)
3772  za_test($now, dur)
3773  clm_expsrc_test($now, dur)
3774  exp_snd_test($now, dur)
3775  expfil_test($now, dur)
3776  graph_eq_test($now, dur)
3777  anoi_test($now, dur)
3778  fullmix_test($now, dur)
3779  grani_test($now, dur)
3780  bes_fm_test($now, dur)
3781end
3782
3783# clm-ins.rb ends here
3784