# clm-ins.rb -- CLM instruments translated to Snd/Ruby # Translator: Michael Scholz # Created: 03/09/16 01:27:09 # Changed: 14/11/28 02:16:54 # Instruments work with # with_sound (CLM (sample2file gens) and Snd) # with_dac (dac output, except at least for fullmix) # # Tested with Snd 15.x and Ruby 2.x.x # pluck reson # vox cellon # fofins jl_reverb # fm_trumpet gran_synth # pqw_vox touch_tone # stereo_flute spectra # fm_bell two_tab # fm_insect lbj_piano # fm_drum resflt # gong scratch # attract pins # pqw zc # tubebell zn # wurley za # rhodey clm_expsrc exp_snd # hammondoid expfil # metal graph_eq # drone anoi # canter fullmix # nrev grani # # class Ssb_fm < Musgen # initialize(freq) # inspect # to_s # run_func(val1, val2) # ssb_fm(modsig) # bes_fm(start, dur, freq, amp, ratio, index) # # make_ssb_fm(freq) # ssb_fm?(obj) # ssb_fm(gen, modsig) # # class Fm2 < Musgen # initialize(f1, f2, f3, f4, p1, p2, p3, p4) # inspect # to_s # run_func(val1, val2) # fm2(index) # # make_fm2(f1, f2, f3, f4, p1, p2, p3, p4) # fm2?(obj) # fm2(gen, index) # comments from clm-ins.scm $now = 0.0 require "ws" require "spectr" require "env" include Math with_silence do require "matrix" end def normalize_partials(partials) sum = 0.0 parts = partials.dup len = parts.length 1.step(len - 1, 2) do |i| sum += parts[i].abs end 1.step(len - 1, 2) do |i| parts[i] /= sum end parts end unless defined? normalize_partials # violin is defined as an example in ws.rb def violin_test(start = 0.0, dur = 1.0) violin(start, dur, 440, 0.5) $now = start + dur + 0.2 end require "v" # fm_violin is defined in v.rb def fm_violin_test(start = 0.0, dur = 1.0) fm_violin(start, dur, 440, 0.5) $now = start + dur + 0.2 end # PLUCK # # The Karplus-Strong algorithm as extended by David Jaffe and Julius # Smith -- see Jaffe and Smith, "Extensions of the Karplus-Strong # Plucked-String Algorithm" CMJ vol 7 no 2 Summer 1983, reprinted in # "The Music Machine". translated from CLM's pluck.ins add_help(:pluck, "pluck(start, dur, freq, amp, weighting, lossfact) \ Implements the Jaffe-Smith plucked string physical model. WEIGHTING is the ratio of the once-delayed to the twice-delayed samples. \ It defaults to 0.5=shortest decay. Anything other than 0.5 = longer decay. \ Must be between 0 and less than 1.0. LOSSFACT can be used to shorten decays. \ Most useful values are between 0.8 and 1.0. pluck(0, 1, 330, 0.3, 0.95, 0.95)") def pluck(start, dur, freq, amp, weighting = 0.5, lossfact = 0.9) get_optimum_c = lambda do |s, o, p| pa = (1.0 / o) * atan2(s * sin(o), (1.0 - s) + s * cos(o)) tmp_int = (p - pa).floor pc = p - pa - tmp_int until pc >= 0.1 tmp_int -= 1 pc += 1.0 end [tmp_int, (sin(o) - sin(o * pc)) / sin(o + o * pc)] end tune_it = lambda do |f, s1| p = @srate / f s = s1.zero? ? 0.5 : s1 o = hz2radians(f) t1, c1 = get_optimum_c.call(s, o, p) t2, c2 = get_optimum_c.call(1.0 - s, o, p) if s != 0.5 and c1.abs < c2.abs [1.0 - s, c1, t1] else [s, c2, t2] end end wt0, c, dlen = tune_it.call(freq, weighting) lf = lossfact.zero? ? 1.0 : [1.0, lossfact].min wt = wt0.zero? ? 0.5 : [1.0, wt0].min tab = make_vct(dlen) # get initial waveform in "tab" -- here we can introduce 0's to # simulate different pick positions, and so on -- see the CMJ # article for numerous extensions. The normal case is to load it # with white noise (between -1 and 1). allp = make_one_zero(lf * (1.0 - wt), lf * wt) feedb = make_one_zero(c, 1.0) # or feedb = make_one_zero(1.0, c) dlen.times do |i| tab[i] = 1.0 - random(2.0) end run_instrument(start, dur) do val = tab.clm_cycle tab[tab.clm_cycle_index] = (1.0 - c) * one_zero(feedb, one_zero(allp, val)) amp * val end end def pluck_test(start = 0.0, dur = 1.0) pluck(start, dur, 330, 0.3, 0.95, 0.95) $now = start + dur + 0.2 end # formant center frequencies for a male speaker (vox and pqw_vox) Formants = { :I => [390, 1990, 2550], :E => [530, 1840, 2480], :AE => [660, 1720, 2410], :UH => [520, 1190, 2390], :A => [730, 1090, 2440], :OW => [570, 840, 2410], :U => [440, 1020, 2240], :OO => [300, 870, 2240], :ER => [490, 1350, 1690], :W => [300, 610, 2200], :LL => [380, 880, 2575], :R => [420, 1300, 1600], :Y => [300, 2200, 3065], :EE => [260, 3500, 3800], :LH => [280, 1450, 1600], :L => [300, 1300, 3000], :I2 => [350, 2300, 3340], :B => [200, 800, 1750], :D => [300, 1700, 2600], :G => [250, 1350, 2000], :M => [280, 900, 2200], :N => [280, 1700, 2600], :NG => [280, 2300, 2750], :P => [300, 800, 1750], :T => [200, 1700, 2600], :K => [350, 1350, 2000], :F => [175, 900, 4400], :TH => [200, 1400, 2200], :S => [200, 1300, 2500], :SH => [200, 1800, 2000], :V => [175, 1100, 2400], :THE => [200, 1600, 2200], :Z => [200, 1300, 2500], :ZH => [175, 1800, 2000], :ZZ => [900, 2400, 3800], :VV => [565, 1045, 2400]} # MLBVOI # # translation from MUS10 of Marc LeBrun's waveshaping voice instrument # (using FM here) this version translated (and simplified slightly) # from CLM's mlbvoi.ins def vox(start, dur, freq, amp, ampfun, freqfun, freqscl, voxfun, index, vibscl) f1 = [] f2 = [] f3 = [] (voxfun.length - 1).step(1, -2) do |i| phon = Formants[voxfun[i]] x = voxfun[i - 1] f1.unshift(phon[0]) f1.unshift(x) f2.unshift(phon[1]) f2.unshift(x) f3.unshift(phon[2]) f3.unshift(x) end car_os = make_oscil(:frequency, 0) of0 = make_oscil(:frequency, 0) of1 = make_oscil(:frequency, 0) of2 = make_oscil(:frequency, 0) of3 = make_oscil(:frequency, 0) of4 = make_oscil(:frequency, 0) of5 = make_oscil(:frequency, 0) ampf = make_env(:envelope, ampfun, :scaler, amp, :duration, dur) frmf1 = make_env(:envelope, f1, :duration, dur) frmf2 = make_env(:envelope, f2, :duration, dur) frmf3 = make_env(:envelope, f3, :duration, dur) freqf = make_env(:envelope, freqfun, :duration, dur, :scaler, freqscl * freq, :offset, freq) per_vib = make_triangle_wave(:frequency, 6, :amplitude, freq * vibscl) ran_vib = make_rand_interp(:frequency, 20, :amplitude, freq * 0.01) run_instrument(start, dur) do frq = env(freqf) + triangle_wave(per_vib) + rand_interp(ran_vib) car = index * oscil(car_os, hz2radians(frq)) frm = env(frmf1) frm0 = frm / frq.to_f frm_int = frm0.floor if frm_int.even? frq0 = hz2radians(frm_int * frq) frq1 = hz2radians((frm_int + 1) * frq) amp1 = frm0 - frm_int amp0 = 1.0 - amp1 else frq1 = hz2radians(frm_int * frq) frq0 = hz2radians((frm_int + 1) * frq) amp0 = frm0 - frm_int amp1 = 1.0 - amp0 end frm = env(frmf2) frm0 = frm / frq.to_f frm_int = frm0.floor if frm_int.even? frq2 = hz2radians(frm_int * frq) frq3 = hz2radians((frm_int + 1) * frq) amp3 = frm0 - frm_int amp2 = 1.0 - amp3 else frq3 = hz2radians(frm_int * frq) frq2 = hz2radians((frm_int + 1) * frq) amp2 = frm0 - frm_int amp3 = 1.0 - amp2 end frm = env(frmf3) frm0 = frm / frq.to_f frm_int = frm0.floor if frm_int.even? frq4 = hz2radians(frm_int * frq) frq5 = hz2radians((frm_int + 1) * frq) amp5 = frm0 - frm_int amp4 = 1.0 - amp5 else frq5 = hz2radians(frm_int * frq) frq4 = hz2radians((frm_int + 1) * frq) amp4 = frm0 - frm_int amp5 = 1.0 - amp4 end env(ampf) * (0.8 * (amp0 * oscil(of0, frq0 + 0.2 * car) + amp1 * oscil(of1, frq1 + 0.2 * car)) + 0.15 * (amp2 * oscil(of2, frq2 + 0.5 * car) + amp3 * oscil(of3, frq3 + 0.5 * car)) + 0.05 * (amp4 * oscil(of4, frq4 + car) + amp5 * oscil(of5, frq5 + car))) end end def vox_test(start = 0.0, dur = 1.0) amp_env = [0, 0, 25, 1, 75, 1, 100, 0] frq_env = [0, 0, 5, 0.5, 10, 0, 100, 1] examp1 = [0, :E, 25, :AE, 35, :ER, 65, :ER, 75, :I, 100, :UH] examp2 = [0, :I, 5, :OW, 10, :I, 50, :AE, 100, :OO] $now = start vox($now, dur, 170, 0.4, amp_env, frq_env, 0.1, examp1, 0.05, 0.1) $now += dur + 0.2 vox($now, dur, 300, 0.4, amp_env, frq_env, 0.1, examp2, 0.02, 0.1) $now += dur + 0.2 vox($now, 5, 600, 0.4, amp_env, frq_env, 0.1, examp2, 0.01, 0.1) $now += 5.0 + 0.2 end # FOF example add_help(:fofins, "fofins(beg, dur, frq, amp, vib, f0, a0, f1, a1, \ f2, a2, ae=[0, 0, 25, 1, 75, 1, 100, 0]) \ Produces FOF synthesis: \ fofins(0, 1, 270, 0.2, 0.001, 730, 0.6, 1090, 0.3, 2440, 0.1)") def fofins(start, dur, frq, amp, vib, f0, a0, f1, a1, f2, a2, ae = [0, 0, 25, 1, 75, 1, 100,0]) ampf = make_env(:envelope, ae, :scaler, amp, :duration, dur) frq0 = hz2radians(f0) frq1 = hz2radians(f1) frq2 = hz2radians(f2) foflen = @srate == 22050.0 ? 100 : 200 vibr = make_oscil(:frequency, 6) win_freq = TWO_PI / foflen wt0 = make_wave_train(:size, foflen, :frequency, frq) foftab = mus_data(wt0) foflen.times do |i| foftab[i] = (a0 * sin(i * frq0) + a1 * sin(i * frq1) + a2 * sin(i * frq2)) * 0.5 * (1.0 - cos(i * win_freq)) end run_instrument(start, dur) do env(ampf) * wave_train(wt0, vib * oscil(vibr)) end end def fofins_test(start = 0.0, dur = 1.0) fofins(start, dur, 270, 0.2, 0.001, 730, 0.6, 1090, 0.3, 2440, 0.1) $now = start + dur + 0.2 end # FM TRUMPET # # Dexter Morrill's FM-trumpet: from CMJ feb 77 p51 def fm_trumpet(start, dur, *args) frq1, frq2, amp1, amp2, ampatt1, ampdec1, ampatt2, ampdec2 = nil modfrq1, modind11, modind12, modfrq2, modind21, modind22 = nil rvibamp, rvibfrq, vibamp, vibfrq, vibatt, vibdec = nil frqskw, frqatt, ampenv1, ampenv2 = nil indenv1, indenv2, degree, distance, reverb_amount = nil optkey(args, binding, [:frq1, 250.0], [:frq2, 1500.0], [:amp1, 0.5], [:amp2, 0.1], [:ampatt1, 0.03], [:ampdec1, 0.35], [:ampatt2, 0.03], [:ampdec2, 0.3], [:modfrq1, 250.0], [:modind11, 0.0], [:modind12, 2.66], [:modfrq2, 250.0], [:modind21, 0.0], [:modind22, 1.8], [:rvibamp, 0.007], [:rvibfrq, 125.0], [:vibamp, 0.007], [:vibfrq, 7.0], [:vibatt, 0.6], [:vibdec, 0.2], [:frqskw, 0.03], [:frqatt, 0.06], [:ampenv1, [0, 0, 25, 1, 75, 0.9, 100, 0]], [:ampenv2, [0, 0, 25, 1, 75, 0.9, 100, 0]], [:indenv1, [0, 0, 25, 1, 75, 0.9, 100, 0]], [:indenv2, [0, 0, 25, 1, 75, 0.9, 100, 0]], [:degree, 0.0], [:distance, 1.0], [:reverb_amount, 0.005]) dur = dur.to_f per_vib_f = make_env(:envelope, stretch_envelope([0, 1, 25, 0.1, 75, 0, 100, 0], 25, [100 * (vibatt / dur), 45].min, 75, [100 * (1.0 - vibdec / dur), 55].max), :scaler, vibamp, :duration, dur) ran_vib = make_rand_interp(:frequency, rvibfrq, :amplitude, rvibamp) per_vib = make_oscil(:frequency, vibfrq) dec_01 = [75, 100 * (1.0 - 0.01 / dur)].max frq_f = make_env(:envelope, stretch_envelope([0, 0, 25, 1, 75, 1, 100, 0], 25, [25, 100 * (frqatt / dur)].min, 75, dec_01), :scaler, frqskw, :duration, dur) ampattpt1 = [25, 100 * (ampatt1 / dur)].min ampdecpt1 = [75, 100 * (1.0 - ampdec1 / dur)].max ampattpt2 = [25, 100 * (ampatt2 / dur)].min ampdecpt2 = [75, 100 * (1.0 - ampdec2 / dur)].max mod1_f = make_env(:envelope, stretch_envelope(indenv1, 25, ampattpt1, 75, dec_01), :scaler, modfrq1 * (modind12 - modind11), :duration, dur) mod1 = make_oscil(:frequency, 0.0) car1 = make_oscil(:frequency, 0.0) # set frequency to zero here because it is handled multiplicatively below car1_f = make_env(:envelope, stretch_envelope(ampenv1, 25, ampattpt1, 75, ampdecpt1), :scaler, amp1, :duration, dur) mod2_f = make_env(:envelope, stretch_envelope(indenv2, 25, ampattpt2, 75, dec_01), :scaler, modfrq2 * (modind22 - modind21), :duration, dur) mod2 = make_oscil(:frequency, 0.0) car2 = make_oscil(:frequency, 0.0) car2_f = make_env(:envelope, stretch_envelope(ampenv2, 25, ampattpt2, 75, ampdecpt2), :scaler, amp2, :duration, dur) run_instrument(start, dur, :degree, degree, :distance, distance, :reverb_amount, reverb_amount) do frq_change = hz2radians((1.0 + rand_interp(ran_vib)) * (1.0 + env(per_vib_f) * oscil(per_vib)) * (1.0 + env(frq_f))) env(car1_f) * oscil(car1, frq_change * (frq1 + env(mod1_f) * oscil(mod1, modfrq1 * frq_change))) + env(car2_f) * oscil(car2, frq_change * (frq2 + env(mod2_f) * oscil(mod2, modfrq2 * frq_change))) end end def fm_trumpet_test(start = 0.0, dur = 1.0) fm_trumpet(start, dur) $now = start + dur + 0.2 end # PQWVOX # # translation of CLM pqwvox.ins (itself translated from MUS10 of MLB's # waveshaping voice instrument (using phase quadrature waveshaping)) add_help(:pqw_vox, "pqw_vox(start, dur, freq, spacing_freq, \ amp, ampfun, freqfun, freqscl, phonemes, formant_amps, formant_shapes) \ Produces vocal sounds using phase quadrature waveshaping.") def pqw_vox(start, dur, freq, spacing_freq, amp, ampfun, freqfun, freqscl, phonemes, formant_amps, formant_shapes) vox_fun = lambda do |phons, which, newenv| # make an envelope from which entry of phoneme data referred to by phons if phons.empty? newenv else vox_fun.call(phons[2..-1], which, newenv + [phons[0], Formants[phons[1]][which]]) end end car_sin = make_oscil(:frequency, 0.0) car_cos = make_oscil(:frequency, 0.0, :initial_phase, HALF_PI) frq_ratio = spacing_freq / freq.to_f fs = formant_amps.length sin_evens = Array.new(fs) cos_evens = Array.new(fs) sin_odds = Array.new(fs) cos_odds = Array.new(fs) amps = Array.new(fs) frmfs = Array.new(fs) sin_coeffs = Array.new(fs) cos_coeffs = Array.new(fs) ampf = make_env(:envelope, ampfun, :scaler, amp, :duration, dur) freqf = make_env(:envelope, freqfun, :scaler, freqscl * freq, :duration, dur, :offset, freq) per_vib = make_triangle_wave(:frequency, 6.0, :amplitude, freq * 0.1) ran_vib = make_rand_interp(:frequency, 20.0, :amplitude, freq * 0.05) fs.times do |i| sin_evens[i] = make_oscil(:frequency, 0.0) sin_odds[i] = make_oscil(:frequency, 0.0) cos_evens[i] = make_oscil(:frequency, 0.0, :initial_phase, HALF_PI) cos_odds[i] = make_oscil(:frequency, 0.0, :initial_phase, HALF_PI) amps[i] = formant_amps[i] shape = normalize_partials(formant_shapes[i]) cos_coeffs[i] = partials2polynomial(shape, 1) sin_coeffs[i] = partials2polynomial(shape, 0) frmfs[i] = make_env(:envelope, vox_fun.call(phonemes, i, []), :duration, dur) end run_instrument(start, dur) do frq = env(freqf) + triangle_wave(per_vib) + rand_interp(ran_vib) frqscl = hz2radians(frq * frq_ratio) carsin = oscil(car_sin, frqscl) carcos = oscil(car_cos, frqscl) sum = 0.0 fs.times do |j| frm = env(frmfs[j]) frm0 = frm / frq frm_int = frm0.floor if frm_int.even? even_freq = hz2radians(frm_int * frq) odd_freq = hz2radians((frm_int + 1.0) * frq) odd_amp = frm0 - frm_int even_amp = 1.0 - odd_amp else odd_freq = hz2radians(frm_int * frq) even_freq = hz2radians((frm_int + 1.0) * frq) even_amp = frm0 - frm_int odd_amp = 1.0 - even_amp end fax = polynomial(cos_coeffs[j], carcos) yfax = carsin * polynomial(sin_coeffs[j], carcos) sum = sum + amps[j] * (even_amp * (yfax * oscil(sin_evens[j], even_freq) - fax * oscil(cos_evens[j], even_freq)) + odd_amp * (yfax * oscil(sin_odds[j], odd_freq) - fax * oscil(cos_odds[j], odd_freq))) end env(ampf) * sum end end def pqw_vox_test(start = 0.0, dur = 1.0) ampfun = [0, 0, 50, 1, 100, 0] freqfun = [0, 0, 100, 0] freqramp = [0, 0, 100, 1] sh1 = [[1, 1, 2, 0.5], [1, 0.5, 2, 0.5, 3, 1], [1, 1, 4, 0.5]] sh2 = [[1, 1, 2, 0.5], [1, 1, 2, 0.5, 3, 0.2, 4, 0.1], [1, 1, 3, 0.1, 4, 0.5]] sh3 = [[1, 1, 2, 0.5], [1, 1, 4, 0.1], [1, 1, 2, 0.1, 4, 0.05]] sh4 = [[1, 1, 2, 0.5, 3, 0.1, 4, 0.01], [1, 1, 4, 0.1], [1, 1, 2, 0.1, 4, 0.05]] $now = start pqw_vox($now, dur, 300, 300, 0.5, ampfun, freqfun, 0.0, [0, :L, 100, :L], [0.33, 0.33, 0.33], sh1) $now += dur + 0.2 pqw_vox($now, dur, 200, 200, 0.1, ampfun, freqramp, 0.1, [0, :UH, 100, :ER], [0.8, 0.15, 0.05], sh2) $now += dur + 0.2 pqw_vox($now, dur, 100, 314, 0.1, ampfun, freqramp, 0.1, [0, :UH, 100, :ER], [0.8, 0.15, 0.05], sh2) $now += dur + 0.2 pqw_vox($now, dur, 200, 314, 0.1, ampfun, freqramp, 0.01, [0, :UH, 100, :ER], [0.8, 0.15, 0.05], sh3) $now += dur + 0.2 pqw_vox($now, dur, 100, 414, 0.2, ampfun, freqramp, 0.01, [0, :OW, 50, :E, 100, :ER], [0.8, 0.15, 0.05], sh4) $now += dur + 0.2 end # STEREO-FLUTE # slightly simplified [MS] add_help(:stereo_flute, "stereo_flute(start, dur, freq, flow, *key_args) :flow_envelope = [0, 1, 100, 1] :decay = 0.01 :noise = 0.0356 :embouchure_size = 0.5 :fbk_scl1 = 0.5 :fbk_scl2 = 0.55 :out_scl = 1.0 :a0 = 0.7 :b1 = -0.3 :vib_rate = 5 :vib_amount = 0.03 :ran_rate = 5 :ran_amount = 0.03 is a physical model of a flute: \ stereo_flute(0, 1, 440, 0.55, :flow_envelope, [0, 0, 1, 1, 2, 1, 3, 0])") def stereo_flute(start, dur, freq, flow, *args) flow_envelope, decay, noise, embouchure_size = nil fbk_scl1, fbk_scl2, out_scl = nil a0, b1, vib_rate, vib_amount, ran_rate, ran_amount = nil optkey(args, binding, [:flow_envelope, [0, 1, 100, 1]], [:decay, 0.01], # additional time for instrument to decay [:noise, 0.0356], [:embouchure_size, 0.5], [:fbk_scl1, 0.5], # these two are crucial for good results [:fbk_scl2, 0.55], [:out_scl, 1.0], [:a0, 0.7], # filter coefficients [:b1, -0.3], [:vib_rate, 5], [:vib_amount, 0.03], [:ran_rate, 5], [:ran_amount, 0.03]) flowf = make_env(:envelope, flow_envelope, :scaler, flow, :length, seconds2samples(dur - decay)) periodic_vib = make_oscil(:frequency, vib_rate) ran_vib = make_rand_interp(:frequency, ran_rate) breath = make_rand(:frequency, @srate / 2.0, :amplitude, 1) period_samples = (@srate / freq).floor embouchure_samples = (embouchure_size * period_samples).floor embouchure = make_delay(embouchure_samples, :initial_element, 0.0) bore = make_delay(period_samples) reflection_lp_filter = make_one_pole(a0, b1) out_sig = current_diff = previous_out_sig = previous_dc_blocked_a = 0.0 run_instrument(start, dur) do delay_sig = delay(bore, out_sig) emb_sig = delay(embouchure, current_diff) current_flow = vib_amount * oscil(periodic_vib) + ran_amount * rand_interp(ran_vib) + env(flowf) current_diff = (current_flow + noise * current_flow * rand(breath)) + fbk_scl1 * delay_sig current_exitation = emb_sig - emb_sig * emb_sig * emb_sig out_sig = one_pole(reflection_lp_filter, current_exitation + fbk_scl2 * delay_sig) # NB the DC blocker is not in the cicuit. It is applied to the # out_sig but the result is not fed back into the system. dc_blocked_a = (out_sig - previous_out_sig) + 0.995 * previous_dc_blocked_a previous_out_sig = out_sig previous_dc_blocked_a = dc_blocked_a out_scl * dc_blocked_a end end def flute_test(start = 0.0, dur = 1.0) stereo_flute(start, dur, 440, 0.55, :flow_envelope, [0, 0, 1, 1, 2, 1, 3, 0]) $now = start + dur + 0.2 end # FM-BELL add_help(:fm_bell, "fm_bell(startime, dur, frequency, amplitude, \ amp-env=[...], index_env=[...], index=1.0) \ Mixes in one fm bell note." ) def fm_bell(start, dur, freq, amp, amp_env = [0, 0, 0.1, 1, 10, 0.6, 25, 0.3, 50, 0.15, 90, 0.1, 100, 0], index_env = [0, 1, 2, 1.1, 25, 0.75, 75, 0.5, 100, 0.2], index = 1.0) fm_ind1 = hz2radians(32.0 * freq) fm_ind2 = hz2radians(4.0 * (8.0 - freq / 50.0)) fm_ind3 = fm_ind2 * 0.705 * (1.4 - freq / 250.0) fm_ind4 = hz2radians(32.0 * (20.0 - freq / 20.0)) mod1 = make_oscil(:frequency, freq * 2.0) mod2 = make_oscil(:frequency, freq * 1.41) mod3 = make_oscil(:frequency, freq * 2.82) mod4 = make_oscil(:frequency, freq * 2.4) car1 = make_oscil(:frequency, freq) car2 = make_oscil(:frequency, freq) car3 = make_oscil(:frequency, freq * 2.4) indf = make_env(:envelope, index_env, :scaler, index, :duration, dur) ampf = make_env(:envelope, amp_env, :scaler, amp, :duration, dur) run_instrument(start, dur) do fmenv = env(indf) env(ampf) * (oscil(car1, fmenv * fm_ind1 * oscil(mod1)) + 0.15 * oscil(car2, fmenv * (fm_ind2 * oscil(mod2) + fm_ind3 * oscil(mod3))) + 0.15 * oscil(car3, fmenv * fm_ind4 * oscil(mod4))) end end def fm_bell_test(start = 0.0, dur = 1.0) fm_bell(start, dur, 440, 0.5) $now = start + dur + 0.2 end # FM-INSECT def fm_insect(start, dur, freq, amp, amp_env, mod_freq, mod_skew, mod_freq_env, mod_index, mod_index_env, fm_index, fm_ratio, *args) degree, distance, reverb_amount = nil optkey(args, binding, [:degree, 0.0], [:distance, 1.0], [:reverb_amount, 0.005]) carrier = make_oscil(:frequency, freq) fm1_osc = make_oscil(:frequency, mod_freq) fm2_osc = make_oscil(:frequency, fm_ratio * freq) ampf = make_env(:envelope, amp_env, :scaler, amp, :duration, dur) indf = make_env(:envelope, mod_index_env, :scaler, hz2radians(mod_index), :duration, dur) modfrqf = make_env(:envelope, mod_freq_env, :scaler, hz2radians(mod_skew), :duration, dur) fm2_amp = hz2radians(fm_index * fm_ratio * freq) run_instrument(start, dur, :degree, degree, :distance, distance, :reverb_amount, reverb_amount) do garble_in = env(indf) * oscil(fm1_osc, env(modfrqf)) garble_out = fm2_amp * oscil(fm2_osc, garble_in) env(ampf) * oscil(carrier, garble_out + garble_in) end end def fm_insect_test(start = 0.0, dur = 1.0) locust = [0, 0, 40, 1, 95, 1, 100, 0.5] bug_hi = [0, 1, 25, 0.7, 75, 0.78, 100, 1] amp = [0, 0, 25, 1, 75, 0.7, 100, 0] $now = start fm_insect($now + 0.000, 1.699, 4142.627, 0.015, amp, 60, -16.707, locust, 500.866, bug_hi, 0.346, 0.5) fm_insect($now + 0.195, 0.233, 4126.284, 0.030, amp, 60, -12.142, locust, 649.490, bug_hi, 0.407, 0.5) fm_insect($now + 0.217, 2.057, 3930.258, 0.045, amp, 60, -3.011, locust, 562.087, bug_hi, 0.591, 0.5) fm_insect($now + 2.100, 1.500, 900.627, 0.060, amp, 40, -16.707, locust, 300.866, bug_hi, 0.346, 0.5) fm_insect($now + 3.000, 1.500, 900.627, 0.060, amp, 40, -16.707, locust, 300.866, bug_hi, 0.046, 0.5) fm_insect($now + 3.450, 1.500, 900.627, 0.090, amp, 40, -16.707, locust, 300.866, bug_hi, 0.006, 0.5) fm_insect($now + 3.950, 1.500, 900.627, 0.120, amp, 40, -10.707, locust, 300.866, bug_hi, 0.346, 0.5) fm_insect($now + 4.300, 1.500, 900.627, 0.090, amp, 40, -20.707, locust, 300.866, bug_hi, 0.246, 0.5) $now += 6.0 end # FM-DRUM # # Jan Mattox's fm drum: def fm_drum(start, dur, freq, amp, index, high = false, degree = 0.0, distance = 1.0, rev_amount = 0.01) casrat = high ? 8.525 : 3.515 fmrat = high ? 3.414 : 1.414 glsf = make_env(:envelope, [0, 0, 25, 0, 75, 1, 100, 1], :scaler, high ? hz2radians(66) : 0.0, :duration, dur) ampfun = [0, 0, 3, 0.05, 5, 0.2, 7, 0.8, 8, 0.95, 10, 1.0, 12, 0.95, 20, 0.3, 30, 0.1, 100, 0] atdrpt = 100 * (high ? 0.01 : 0.015) / dur ampf = make_env(:envelope, stretch_envelope(ampfun, 10, atdrpt, 15, [atdrpt + 1, 100 - 100 * ((dur - 0.2) / dur)].max), :scaler, amp, :duration, dur) indxfun = [0, 0, 5, 0.014, 10, 0.033, 15, 0.061, 20, 0.099, 25, 0.153, 30, 0.228, 35, 0.332, 40, 0.477, 45, 0.681, 50, 0.964, 55, 0.681, 60, 0.478, 65, 0.332, 70, 0.228, 75, 0.153, 80, 0.099, 85, 0.061, 90, 0.033, 95, 0.0141, 100, 0] indxpt = 100 - 100 * ((dur - 0.1) / dur) divindxf = stretch_envelope(indxfun, 50, atdrpt, 65, indxpt) indxf = make_env(:envelope, divindxf, :duration, dur, :scaler, [hz2radians(index * fmrat * freq), PI].min) mindxf = make_env(:envelope, divindxf, :duration, dur, :scaler, [hz2radians(index * casrat * freq), PI].min) devf = make_env(:envelope, stretch_envelope(ampfun, 10, atdrpt, 90, [atdrpt + 1, 100 - 100 * ((dur - 0.05) / dur)].max), :scaler, [hz2radians(7000), PI].min, :duration, dur) rn = make_rand(:frequency, 7000, :amplitude, 1) carrier = make_oscil(:frequency, freq) fmosc = make_oscil(:frequency, freq * fmrat) cascade = make_oscil(:frequency, freq * casrat) run_instrument(start, dur, :degree, degree, :distance, distance, :reverb_amount, rev_amount) do gls = env(glsf) env(ampf) * oscil(carrier, gls + env(indxf) * oscil(fmosc, gls * fmrat + env(mindxf) * oscil(cascade, gls * casrat + env(devf) * rand(rn)))) end end def fm_drum_test(start = 0.0, dur = 1.0) $now = start fm_drum($now, dur, 55, 0.3, 5, false) $now += dur + 0.2 fm_drum($now, dur, 66, 0.3, 4, true) $now += dur + 0.2 end # FM-GONG # # Paul Weineke's gong. def gong(start, dur, freq, amp, *args) degree, distance, reverb_amount = nil optkey(args, binding, [:degree, 0.0], [:distance, 1.0], [:reverb_amount, 0.005]) mfq1 = freq * 1.16 mfq2 = freq * 3.14 mfq3 = freq * 1.005 indx01 = hz2radians(0.01 * mfq1) indx11 = hz2radians(0.30 * mfq1) indx02 = hz2radians(0.01 * mfq2) indx12 = hz2radians(0.38 * mfq2) indx03 = hz2radians(0.01 * mfq3) indx13 = hz2radians(0.50 * mfq3) atpt = 5 atdur = 100 * (0.002 / dur) expf = [0, 0, 3, 1, 15, 0.5, 27, 0.25, 50, 0.1, 100, 0] rise = [0, 0, 15, 0.3, 30, 1.0, 75, 0.5, 100, 0] fmup = [0, 0, 75, 1.0, 98, 1.0, 100, 0] fmdwn = [0, 0, 2, 1.0, 100, 0] ampfun = make_env(:envelope, stretch_envelope(expf, atpt, atdur), :scaler, amp, :duration, dur) indxfun1 = make_env(:envelope, fmup, :scaler, indx11 - indx01, :duration, dur, :offset, indx01) indxfun2 = make_env(:envelope, fmdwn, :scaler, indx12 - indx02, :duration, dur, :offset, indx02) indxfun3 = make_env(:envelope, rise, :scaler, indx13 - indx03, :duration, dur, :offset, indx03) carrier = make_oscil(:frequency, freq) mod1 = make_oscil(:frequency, mfq1) mod2 = make_oscil(:frequency, mfq2) mod3 = make_oscil(:frequency, mfq3) run_instrument(start, dur, :degree, degree, :distance, distance, :reverb_amount, reverb_amount) do env(ampfun) * oscil(carrier, env(indxfun1) * oscil(mod1) + env(indxfun2) * oscil(mod2) + env(indxfun3) * oscil(mod3)) end end def gong_test(start = 0.0, dur = 1.0) gong(start, dur, 261.61, 0.6) $now = start + dur + 0.2 end # ATTRACT # # by James McCartney, from CMJ vol 21 no 3 p 6 def attract(start, dur, amp, c) a = b = 0.2 dt = 0.04 scale = (0.5 * amp) / c x = -1.0 y = z = 0.0 run_instrument(start, dur) do x1 = x - dt * (y + z) y = y + dt * (x + a * y) z = z + dt * ((b + x * z) - c * z) x = x1 scale * x end end def attract_test(start = 0.0, dur = 1.0) attract(start, dur, 0.5, 2.0) $now = start + dur + 0.2 end # PQW # # phase-quadrature waveshaping used to create asymmetric (i.e. single # side-band) spectra. The basic idea here is a variant of sin x sin y # - cos x cos y = cos (x + y) def pqw(start, dur, spacing_freq, carrier_freq, amp, ampfun, indexfun, partials, *args) degree, distance, reverb_amount = nil optkey(args, binding, [:degree, 0.0], [:distance, 1.0], [:reverb_amount, 0.005]) normalized_partials = normalize_partials(partials) spacing_cos = make_oscil(:frequency, spacing_freq, :initial_phase, HALF_PI) spacing_sin = make_oscil(:frequency, spacing_freq) carrier_cos = make_oscil(:frequency, carrier_freq, :initial_phase, HALF_PI) carrier_sin = make_oscil(:frequency, carrier_freq) sin_coeffs = partials2polynomial(normalized_partials, 0) cos_coeffs = partials2polynomial(normalized_partials, 1) amp_env = make_env(:envelope, ampfun, :scaler, amp, :duration, dur) ind_env = make_env(:envelope, indexfun, :duration, dur) r = carrier_freq / spacing_freq.to_f tr = make_triangle_wave(:frequency, 5, :amplitude, hz2radians(0.005 * spacing_freq)) rn = make_rand_interp(:frequency, 12, :amplitude, hz2radians(0.005 * spacing_freq)) run_instrument(start, dur, :degree, degree, :distance, distance, :reverb_amount, reverb_amount) do vib = triangle_wave(tr) + rand_interp(rn) ax = [1.0, env(ind_env)].min * oscil(spacing_cos, vib) fax = polynomial(cos_coeffs, ax) yfax = oscil(spacing_sin, vib) * polynomial(sin_coeffs, ax) env(amp_env) * (oscil(carrier_sin, vib * r) * yfax - oscil(carrier_cos, vib * r) * fax) end end def pqw_test(start = 0.0, dur = 1.0) pqw(start, dur, 200, 1000, 0.2, [0, 0, 25, 1, 100, 0], [0, 1, 100, 0], [2, 0.1, 3, 0.3, 6, 0.5]) $now = start + dur + 0.2 # to see the asymmetric spectrum most clearly, set the index function # above to [0, 1, 100, 1] end # taken from Perry Cook's stkv1.tar.Z (Synthesis Toolkit), but I was # in a bit of a hurry and may not have made slavishly accurate # translations. Please let me (bil@ccrma.stanford.edu) know of any # serious (non-envelope) errors. # # from Perry Cook's TubeBell.cpp def tubebell(start, dur, freq, amp, base = 32.0) osc0 = make_oscil(freq * 0.995) osc1 = make_oscil(freq * 0.995 * 1.414) osc2 = make_oscil(freq * 1.005) osc3 = make_oscil(freq * 1.414) ampenv1 = make_env(:envelope, [0, 0, 0.005, 1, dur, 0], :base, base, :duration, dur) ampenv2 = make_env(:envelope, [0, 0, 0.001, 1, dur, 0], :base, 2 * base, :duration, dur) ampmod = make_oscil(:frequency, 2.0) g0 = 0.5 * amp * 0.707 g1 = 0.203 g2 = 0.5 * amp g3 = 0.144 run_instrument(start, dur) do (0.007 * oscil(ampmod) + 0.993) * (g0 * env(ampenv1) * oscil(osc0, g1 * oscil(osc1)) + g2 * env(ampenv2) * oscil(osc2, g3 * oscil(osc3))) end end def tubebell_test(start = 0.0, dur = 1.0) tubebell(start, dur, 440, 0.2, 32) $now = start + dur + 0.2 end # from Perry Cook's Wurley.cpp def wurley(start, dur, freq, amp) osc0 = make_oscil(freq) osc1 = make_oscil(freq * 4.0) osc2 = make_oscil(510.0) osc3 = make_oscil(510.0) ampmod = make_oscil(:frequency, 8.0) g0 = 0.5 * amp g1 = 0.307 g2 = 0.5 * amp * 0.307 g3 = 0.117 dur = [dur, 0.3].max ampenv = make_env(:envelope, [0, 0, 1, 1, 9, 1, 10, 0], :duration, dur) indenv = make_env(:envelope, [0, 0, 0.001, 1, 0.15, 0, dur, 0], :duration, dur) resenv = make_env(:envelope, [0, 0, 0.001, 1, 0.25, 0, dur, 0], :duration, dur) run_instrument(start, dur) do env(ampenv) * (1.0 + 0.007 * oscil(ampmod)) * (g0 * oscil(osc0, g1 * oscil(osc1)) + env(resenv) * g2 * oscil(osc2, g3 * env(indenv) * oscil(osc3))) end end def wurley_test(start = 0.0, dur = 1.0) wurley(start, dur, 440, 0.2) $now = start + dur + 0.2 end # from Perry Cook's Rhodey.cpp def rhodey(start, dur, freq, amp, base = 0.5) osc0 = make_oscil(freq) osc1 = make_oscil(freq * 0.5) osc2 = make_oscil(freq) osc3 = make_oscil(freq * 15.0) dur = [dur, 0.3].max ampenv1 = make_env(:envelope, [0, 0, 0.005, 1, dur, 0], :base, base, :duration, dur) ampenv2 = make_env(:envelope, [0, 0, 0.001, 1, dur, 0], :base, base * 1.5, :duration, dur) ampenv3 = make_env(:envelope, [0, 0, 0.001, 1, 0.25, 0, dur, 0], :base, base * 4, :duration, dur) g0 = 0.5 * amp g1 = 0.535 g2 = 0.5 * amp g3 = 0.109 run_instrument(start, dur) do g0 * env(ampenv1) * oscil(osc0, g1 * oscil(osc1)) + g2 * env(ampenv2) * oscil(osc2, env(ampenv3) * g3 * oscil(osc3)) end end def rhodey_test(start = 0.0, dur = 1.0) rhodey(start, dur, 440, 0.2, 0.5) $now = start + dur + 0.2 end # from Perry Cook's BeeThree.cpp def hammondoid(start, dur, freq, amp) osc0 = make_oscil(freq * 0.999) osc1 = make_oscil(freq * 1.997) osc2 = make_oscil(freq * 3.006) osc3 = make_oscil(freq * 6.009) dur = [dur, 0.1].max ampenv1 = make_env(:envelope, [0, 0, 0.005, 1, dur - 0.008, 1, dur, 0], :duration, dur) ampenv2 = make_env(:envelope, [0, 0, 0.005, 1, dur, 0], :duration, dur) g0 = 0.25 * 0.75 * amp g1 = 0.25 * 0.75 * amp g2 = 0.5 * amp g3 = 0.5 * 0.75 * amp run_instrument(start, dur) do env(ampenv1) * (g0 * oscil(osc0) + g1 * oscil(osc1) + g2 * oscil(osc2)) + env(ampenv2) * g3 * oscil(osc3) end end def hammondoid_test(start = 0.0, dur = 1.0) hammondoid(start, dur, 440, 0.2) $now = start + dur + 0.2 end # from Perry Cook's HeavyMtl.cpp def metal(start, dur, freq, amp) osc0 = make_oscil(freq) osc1 = make_oscil(freq * 4.0 * 0.999) osc2 = make_oscil(freq * 3.0 * 1.001) osc3 = make_oscil(freq * 0.5 * 1.002) dur = [dur, 0.1].max ampenv0 = make_env(:envelope, [0, 0, 0.001, 1, dur - 0.002, 1, dur, 0], :duration, dur) ampenv1 = make_env(:envelope, [0, 0, 0.001, 1, dur - 0.011, 1, dur, 0], :duration, dur) ampenv2 = make_env(:envelope, [0, 0, 0.01, 1, dur - 0.015, 1, dur, 0], :duration, dur) ampenv3 = make_env(:envelope, [0, 0, 0.03, 1, dur - 0.04, 1, dur, 0], :duration, dur) g0 = 0.615 * amp g1 = 0.202 g2 = 0.574 g3 = 0.116 run_instrument(start, dur) do g0 * env(ampenv0) * oscil(osc0, g1 * env(ampenv1) * oscil(osc1, g2 * env(ampenv2) * oscil(osc2)) + g3 * env(ampenv3) * oscil(osc3)) end end def metal_test(start = 0.0, dur = 1.0) metal(start, dur, 440, 0.2) $now = start + dur + 0.2 end # DRONE def drone(start, dur, freq, amp, ampfun, synth, ampat, ampdc, amtrev, deg, dis, rvibamt, rvibfreq) waveform = partials2wave(synth) amp *= 0.25 s = make_table_lookup(:frequency, freq, :wave, waveform) amp_env = make_env(:envelope, stretch_envelope(ampfun, 25, 100 * (ampat / dur.to_f), 75, 100 - 100 * (ampdc / dur.to_f)), :scaler, amp, :duration, dur) ran_vib = make_rand(:frequency, rvibfreq, :amplitude, hz2radians(rvibamt * freq)) run_instrument(start, dur, :distance, dis, :degree, deg, :reverb_amount, amtrev) do env(amp_env) * table_lookup(s, rand(ran_vib).abs) end end # CANTER def canter(start, dur, pitch, amp, deg, dis, pcrev, ampfun, ranfun, skewfun, skewpc, ranpc, ranfreq, indexfun, atdr, dcdr, ampfun1, indfun1, fmtfun1, ampfun2, indfun2, fmtfun2, ampfun3, indfun3, fmtfun3, ampfun4, indfun4, fmtfun4) amp *= 0.25 dur = dur.to_f pitch = pitch.to_f rangetop = 910.0 rangebot = 400.0 k = (100 * (log(pitch / rangebot) / log(rangetop / rangebot))).floor mfq = pitch atpt = 100 * (atdr / dur) dcpt = 100 - 100 * (dcdr / dur) lfmt1 = envelope_interp(k, fmtfun1) harm1 = (0.5 + lfmt1 / pitch).floor dev11 = hz2radians(envelope_interp(k, indfun1) * mfq) dev01 = dev11 * 0.5 lamp1 = envelope_interp(k, ampfun1) * amp * (1 - (harm1 - lfmt1 / pitch).abs) lfmt2 = envelope_interp(k, fmtfun2) harm2 = (0.5 + lfmt2 / pitch).floor dev12 = hz2radians(envelope_interp(k, indfun2) * mfq) dev02 = dev12 * 0.5 lamp2 = envelope_interp(k, ampfun2) * amp * (1 - (harm2 - lfmt2 / pitch).abs) lfmt3 = envelope_interp(k, fmtfun3) harm3 = (0.5 + lfmt3 / pitch).floor dev13 = hz2radians(envelope_interp(k, indfun3) * mfq) dev03 = dev13 * 0.5 lamp3 = envelope_interp(k, ampfun3) * amp * (1 - (harm3 - lfmt3 / pitch).abs) lfmt4 = envelope_interp(k, fmtfun4) harm4 = (0.5 + lfmt4 / pitch).floor dev14 = hz2radians(envelope_interp(k, indfun4) * mfq) dev04 = dev14 * 0.5 lamp4 = envelope_interp(k, ampfun4) * amp * (1 - (harm4 - lfmt4 / pitch).abs) tampfun = make_env(:envelope, stretch_envelope(ampfun, 25, atpt, 75, dcpt), :duration, dur) tskwfun = make_env(:envelope, stretch_envelope(skewfun, 25, atpt, 75, dcpt), :scaler, hz2radians(pitch * skewpc.to_f), :duration, dur) tranfun = make_env(:envelope, stretch_envelope(ranfun, 25, atpt, 75, dcpt), :duration, dur) tidxfun = make_env(:envelope, stretch_envelope(indexfun, 25, atpt, 75, dcpt), :duration, dur) modgen = make_oscil(:frequency, pitch) gen1 = make_oscil(:frequency, pitch * harm1) gen2 = make_oscil(:frequency, pitch * harm2) gen3 = make_oscil(:frequency, pitch * harm3) gen4 = make_oscil(:frequency, pitch * harm4) ranvib = make_rand(:frequency, ranfreq, :amplitude, hz2radians(ranpc * pitch)) run_instrument(start, dur, :degree, deg, :distance, dis, :reverb_amount, pcrev) do frqval = env(tskwfun) + env(tranfun) * rand(ranvib) modval = oscil(modgen, frqval) ampval = env(tampfun) indval = env(tidxfun) lamp1 * ampval * oscil(gen1, ((dev01 + indval * dev11) * modval + frqval) * harm1) + lamp2 * ampval * oscil(gen2, ((dev02 + indval * dev12) * modval + frqval) * harm2) + lamp3 * ampval * oscil(gen3, ((dev03 + indval * dev13) * modval + frqval) * harm3) + lamp4 * ampval * oscil(gen4, ((dev04 + indval * dev14) * modval + frqval) * harm4) end end # NREV (the most popular Samson box reverb) # # reverb_factor controls the length of the decay -- it should not # exceed (/ 1.0 .823) # lp_coeff controls the strength of the low pass filter inserted # in the feedback loop # volume can be used to boost the reverb output def nrev(*args) reverb_factor, lp_coeff, volume = nil optkey(args, binding, [:reverb_factor, 1.09], [:lp_coeff, 0.7], [:volume, 1.0]) next_prime = lambda do |val| if val.prime? val else next_prime.call(val + 2) end end srscale = @srate / 25641 dly_len = [1433, 1601, 1867, 2053, 2251, 2399, 347, 113, 37, 59, 53, 43, 37, 29, 19] dly_len.map! do |x| val = (x * srscale).round val += 1 if val.even? next_prime.call(val) end comb1 = make_comb(0.822 * reverb_factor, dly_len[0]) comb2 = make_comb(0.802 * reverb_factor, dly_len[1]) comb3 = make_comb(0.773 * reverb_factor, dly_len[2]) comb4 = make_comb(0.753 * reverb_factor, dly_len[3]) comb5 = make_comb(0.753 * reverb_factor, dly_len[4]) comb6 = make_comb(0.733 * reverb_factor, dly_len[5]) low = make_one_pole(lp_coeff, lp_coeff - 1.0) chan2 = (@channels > 1) chan4 = (@channels == 4) allpass1 = make_all_pass(-0.7, 0.7, dly_len[6]) allpass2 = make_all_pass(-0.7, 0.7, dly_len[7]) allpass3 = make_all_pass(-0.7, 0.7, dly_len[8]) allpass4 = make_all_pass(-0.7, 0.7, dly_len[9]) # 10 for quad allpass5 = make_all_pass(-0.7, 0.7, dly_len[11]) allpass6 = (chan2 ? make_all_pass(-0.7, 0.7, dly_len[12]) : nil) allpass7 = (chan4 ? make_all_pass(-0.7, 0.7, dly_len[13]) : nil) allpass8 = (chan4 ? make_all_pass(-0.7, 0.7, dly_len[14]) : nil) out_frample = Vct.new(@channels, 0.0) run_reverb() do |val, i| rev = volume * val outrev = all_pass(allpass4, one_pole(low, all_pass(allpass3, all_pass(allpass2, all_pass(allpass1, comb(comb1, rev) + comb(comb2, rev) + comb(comb3, rev) + comb(comb4, rev) + comb(comb5, rev) + comb(comb6, rev)))))) out_frample[0] = all_pass(allpass5, outrev) if chan2 out_frample[1] = all_pass(allpass6, outrev) end if chan4 out_frample[2] = all_pass(allpass7, outrev) out_frample[3] = all_pass(allpass8, outrev) end out_frample end end def drone_canter_test(start = 0.0, dur = 1.0) fmt1 = [0, 1200, 100, 1000] fmt2 = [0, 2250, 100, 1800] fmt3 = [0, 4500, 100, 4500] fmt4 = [0, 6750, 100, 8100] amp1 = [0, 0.67, 100, 0.7] amp2 = [0, 0.95, 100, 0.95] amp3 = [0, 0.28, 100, 0.33] amp4 = [0, 0.14, 100, 0.15] ind1 = [0, 0.75, 100, 0.65] ind2 = [0, 0.75, 100, 0.75] ind3 = [0, 1, 100, 1] ind4 = [0, 1, 100, 1] skwf = [0, 0, 100, 0] ampf = [0, 0, 25, 1, 75, 1, 100, 0] ranf = [0, 0.5, 100, 0.5] index = [0, 1, 100, 1] solid = [0, 0, 5, 1, 95, 1, 100, 0] bassdr2 = [0.5, 0.06, 1, 0.62, 1.5, 0.07, 2, 0.6, 2.5, 0.08, 3, 0.56, 4, 0.24, 5, 0.98, 6, 0.53, 7, 0.16, 8, 0.33, 9, 0.62, 10, 0.12, 12, 0.14, 14, 0.86, 16, 0.12, 23, 0.14, 24, 0.17] tenordr = [0.3, 0.04, 1, 0.81, 2, 0.27, 3, 0.2, 4, 0.21, 5, 0.18, 6, 0.35, 7, 0.03, 8, 0.07, 9, 0.02, 10, 0.025, 11, 0.035] $now = start drone($now, 4, 115, 0.125, solid, bassdr2, 0.1, 0.5, 0.03, 45, 1, 0.01, 10) drone($now, 4, 229, 0.125, solid, tenordr, 0.1, 0.5, 0.03, 45, 1, 0.01, 11) drone($now, 4, 229.5, 0.125, solid, tenordr, 0.1, 0.5, 0.03, 45, 1, 0.01, 9) canter($now, 2.100, 918.000, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 2.100, 0.300, 688.500, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 2.400, 0.040, 826.200, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 2.440, 0.560, 459.000, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 3.000, 0.040, 408.000, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 3.040, 0.040, 619.650, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 3.080, 0.040, 408.000, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 3.120, 0.040, 688.500, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 3.160, 0.290, 459.000, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 3.450, 0.150, 516.375, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 3.600, 0.040, 826.200, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 3.640, 0.040, 573.750, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 3.680, 0.040, 619.650, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 3.720, 0.180, 573.750, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 3.900, 0.040, 688.500, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) canter($now + 3.940, 0.260, 459.000, 0.175, 45.0, 1, 0.05, ampf, ranf, skwf, 0.050, 0.01, 10, index, 0.005, 0.005, amp1, ind1, fmt1, amp2, ind2, fmt2, amp3, ind3, fmt3, amp4, ind4, fmt4) $now += 4.4 end # RESON def reson(start, dur, pitch, amp, numformants, indxfun, skewfun, pcskew, skewat, skewdc, vibfreq, vibpc, ranvibfreq, ranvibpc, degree, distance, rev_amount, data) # data is a list of lists of form # [ampf, resonfrq, resonamp, ampat, ampdc, dev0, dev1, indxat, indxdc] dur = dur.to_f pitch = pitch.to_f modulator = make_oscil(:frequency, pitch) carriers = Array.new(numformants) ampfs = Array.new(numformants) indfs = Array.new(numformants) c_rats = Array.new(numformants) frqf = make_env(:envelope, stretch_envelope(skewfun, 25, 100 * (skewat / dur), 75, 100 - (100 * (skewdc / dur))), :scaler, hz2radians(pcskew * pitch), :duration, dur) pervib = make_triangle_wave(:frequency, vibfreq, :amplitude, hz2radians(vibpc * pitch)) ranvib = make_rand_interp(:frequency, ranvibfreq, :amplitude, hz2radians(ranvibpc * pitch)) totalamp = 0.0 numformants.times do |i| totalamp += data[i][2] end numformants.times do |i| frmdat = data[i] ampf = frmdat[0] freq = frmdat[1] rfamp = frmdat[2] ampat = 100 * (frmdat[3] / dur) ampdc = 100 - 100 * (frmdat[4] / dur) dev0 = hz2radians(frmdat[5] * freq) dev1 = hz2radians(frmdat[6] * freq) indxat = 100 * (frmdat[7] / dur) indxdc = 100 - 100 * (frmdat[8] / dur) harm = (freq / pitch).round rsamp = 1.0 - (harm - freq / pitch).abs cfq = pitch * harm ampat = 25 if ampat.zero? ampdc = 75 if ampdc.zero? indxat = 25 if indxat.zero? indxdc = 75 if indxdc.zero? indfs[i] = make_env(:envelope, stretch_envelope(indxfun, 25, indxat, 75, indxdc), :scaler, dev1 - dev0, :offset, dev0, :duration, dur) ampfs[i] = make_env(:envelope, stretch_envelope(ampf, 25, ampat, 75, ampdc), :scaler, rsamp * amp * (rfamp / totalamp), :duration, dur) c_rats[i] = harm carriers[i] = make_oscil(:frequency, cfq) end run_instrument(start, dur, :degree, degree, :distance, distance, :reverb_amount, rev_amount) do vib = triangle_wave(pervib) + rand_interp(ranvib) + env(frqf) modsig = oscil(modulator, vib) outsum = 0.0 numformants.times do |j| outsum += env(ampfs[j]) * oscil(carriers[j], vib * c_rats[j] + env(indfs[j]) * modsig) end outsum end end def reson_test(start = 0.0, dur = 1.0) data = [[[0, 0, 100, 1], 1200, 0.5, 0.1, 0.1, 0, 1.0, 0.1, 0.1], [[0, 1, 100, 0], 2400, 0.5, 0.1, 0.1, 0, 1.0, 0.1, 0.1]] reson(start, dur, 440, 0.5, 2, [0, 0, 100, 1], [0, 0, 100, 1], 0.1, 0.1, 0.1, 5, 0.01, 5, 0.01, 0, 1.0, 0.01, data) $now = start + dur + 0.2 end # STK's feedback-fm instrument named CelloN in Sambox-land def cellon(start, dur, pitch0, amp, ampfun, betafun, beta0, beta1, betaat, betadc, ampat, ampdc, dis, pcrev, deg, pitch1, glissfun = [0, 0, 100, 0], glissat = 0.0, glissdc = 0.0, pvibfreq = 0.0, pvibpc = 0.0, pvibfun = [0, 1, 100, 1], pvibat = 0.0, pvibdc = 0.0, rvibfreq = 0.0, rvibpc = 0.0, rvibfun = [0, 1, 100, 1]) pit1 = pitch1.zero? ? pitch0 : pitch1 car = make_oscil(:frequency, pitch0) low = make_one_zero(0.5, -0.5) fmosc = make_oscil(:frequency, pitch0) fm = 0.0 dur = dur.to_f pitch0 = pitch0.to_f pvib = make_triangle_wave(:frequency, pvibfreq, :amplitude, 1.0) rvib = make_rand_interp(:frequency, rvibfreq, :amplitude, 1.0) ampap = (ampat > 0.0 ? (100 * (ampat / dur)) : 25) ampdp = (ampdc > 0.0 ? (100 * (1.0 - ampdc / dur)) : 75) glsap = (glissat > 0.0 ? (100 * (glissat / dur)) : 25) glsdp = (glissdc > 0.0 ? (100 * (1.0 - glissdc / dur)) : 75) betap = (betaat > 0.0 ? (100 * (betaat / dur)) : 25) betdp = (betadc > 0.0 ? (100 * (1.0 - betadc / dur)) : 75) pvbap = (pvibat > 0.0 ? (100 * (pvibat / dur)) : 25) pvbdp = (pvibdc > 0.0 ? (100 * (1.0 - pvibdc / dur)) : 75) pvibenv = make_env(:envelope, stretch_envelope(pvibfun, 25, pvbap, 75, pvbdp), :scaler, hz2radians(pvibpc * pitch0), :duration, dur) rvibenv = make_env(:envelope, stretch_envelope(rvibfun), :duration, dur, :scaler, hz2radians(rvibpc * pitch0)) glisenv = make_env(:envelope, stretch_envelope(glissfun, 25, glsap, 75, glsdp), :scaler, hz2radians(pit1 - pitch0), :duration, dur) amplenv = make_env(:envelope, stretch_envelope(ampfun, 25, ampap, 75, ampdp), :scaler, amp, :duration, dur) betaenv = make_env(:envelope, stretch_envelope(betafun, 25, betap, 75, betdp), :scaler, beta1 - beta0, :offset, beta0, :duration, dur) run_instrument(start, dur, :degree, deg, :distance, dis, :reverb_amount, pcrev) do vib = env(pvibenv) * triangle_wave(pvib) + env(rvibenv) * rand_interp(rvib) + env(glisenv) fm = one_zero(low, env(betaenv) * oscil(fmosc, fm + vib)) env(amplenv) * oscil(car, fm + vib) end end def cellon_test(start = 0.0, dur = 1.0) cellon(start, dur, 220, 0.5, [0, 0, 25, 1, 75, 1, 100, 0], # ampfun [0, 0, 25, 1, 75, 1, 100, 0], # betafun 0.75, 1.0, 0, 0, 0, 0, 1, 0, 0, 220, [0, 0, 25, 1, 75, 1, 100, 0], # glissfun 0, 0, 0, 0, [0, 0, 100, 0], # pvibfun 0, 0, 0, 0, [0, 0, 100, 0]) # rvibfun $now = start + dur + 0.2 end # JL-REVERB def jl_reverb(*args) allpass1 = make_all_pass(-0.7, 0.7, 2111) allpass2 = make_all_pass(-0.7, 0.7, 673) allpass3 = make_all_pass(-0.7, 0.7, 223) comb1 = make_comb(0.742, 9601) comb2 = make_comb(0.733, 10007) comb3 = make_comb(0.715, 10799) comb4 = make_comb(0.697, 11597) outdel1 = make_delay((0.013 * @srate).round) outdel2 = (@channels > 1 ? make_delay((0.011 * @srate).round) : false) out_frample = Vct.new(@channels, 0.0) run_reverb() do |ho, i| allpass_sum = all_pass(allpass3, all_pass(allpass2, all_pass(allpass1, ho))) comb_sum = (comb(comb1, allpass_sum) + comb(comb2, allpass_sum) + comb(comb3, allpass_sum) + comb(comb4, allpass_sum)) out_frample[0] = delay(outdel1, comb_sum) if outdel2 out_frample[1] = delay(outdel2, comb_sum) end out_frample end end # GRAN-SYNTH def gran_synth(start, dur, freq, grain_dur, interval, amp) grain_env = make_env(:envelope, [0, 0, 25, 1, 75, 1, 100, 0], :duration, grain_dur) carrier = make_oscil(:frequency, freq) grain_size = ([grain_dur, interval].max * @srate).ceil grains = make_wave_train(:size, grain_size, :frequency, 1.0 / interval) grain = mus_data(grains) grain_size.times do |i| grain[i] = env(grain_env) * oscil(carrier) end run_instrument(start, dur) do amp * wave_train(grains) end end def gran_synth_test(start = 0.0, dur = 1.0) gran_synth(start, dur, 100, 0.0189, 0.02, 0.4) $now = start + dur + 0.2 end # TOUCH-TONE def touch_tone(start, number) touch_tab_1 = [0, 697, 697, 697, 770, 770, 770, 852, 852, 852, 941, 941, 941] touch_tab_2 = [0, 1209, 1336, 1477, 1209, 1336, 1477, 1209, 1336, 1477, 1209, 1336, 1477] number.length.times do |i| k = number[i] ii = if k.kind_of?(Numeric) k.zero? ? 11 : k else k == ?* ? 10 : 12 end frq1 = make_oscil(:frequency, touch_tab_1[ii]) frq2 = make_oscil(:frequency, touch_tab_2[ii]) run_instrument(start + i * 0.3, 0.2) do 0.25 * (oscil(frq1) + oscil(frq2)) end end end def touch_tone_test(start = 0.0, dur = 1.0) touch_tone(start, [4, 8, 3, 4, 6, 2, 1]) $now = start + dur * 7 + 0.2 # 7 digits end # SPECTRA def spectra(start, dur, freq, amp, partials = [1, 1, 2, 0.5], amp_envelope = [0, 0, 50, 1, 100, 0], vibrato_amplitude = 0.005, vibrato_speed = 5.0, degree = 0.0, distance = 1.0, rev_amount = 0.005) waveform = partials2wave(partials) frq = hz2radians(freq) s = make_table_lookup(:frequency, freq, :wave, waveform) amp_env = make_env(:envelope, amp_envelope, :scaler, amp, :duration, dur) per_vib = make_triangle_wave(:frequency, vibrato_speed, :amplitude, vibrato_amplitude * frq) ran_vib = make_rand_interp(:frequency, vibrato_speed + 1.0, :amplitude, vibrato_amplitude * frq) run_instrument(start, dur, :degree, degree, :distance, distance, :reverb_amount, rev_amount) do env(amp_env) * table_lookup(s, triangle_wave(per_vib) + rand_interp(ran_vib)) end end def spectra_test(start = 0.0, dur = 1.0) spectra(start, dur, 440.0, 0.8, P_a4, [0, 0, 1, 1, 5, 0.9, 12, 0.5, 25, 0.25, 100, 0]) $now = start + dur + 0.2 end # TWO-TAB # # interpolate between two waveforms (this could be extended to # implement all the various wavetable-based synthesis techniques). def two_tab(start, dur, freq, amp, partial_1 = [1.0, 1.0, 2.0, 0.5], partial_2 = [1.0, 0.0, 3.0, 1.0], amp_envelope = [0, 0, 50, 1, 100, 0], interp_func = [0, 1, 100, 0], vibrato_amplitude = 0.005, vibrato_speed = 5.0, degree = 0.0, distance = 1.0, rev_amount = 0.005) waveform_1 = partials2wave(partial_1) waveform_2 = partials2wave(partial_2) frq = hz2radians(freq) s_1 = make_table_lookup(:frequency, freq, :wave, waveform_1) s_2 = make_table_lookup(:frequency, freq, :wave, waveform_2) amp_env = make_env(:envelope, amp_envelope, :scaler, amp, :duration, dur) interp_env = make_env(:envelope, interp_func, :duration, dur) per_vib = make_triangle_wave(:frequency, vibrato_speed, :amplitude, vibrato_amplitude * frq) ran_vib = make_rand_interp(:frequency, vibrato_speed + 1.0, :amplitude, vibrato_amplitude * frq) run_instrument(start, dur, :degree, degree, :distance, distance, :reverb_amount, rev_amount) do vib = triangle_wave(per_vib) + rand_interp(ran_vib) intrp = env(interp_env) env(amp_env) * (intrp * table_lookup(s_1, vib) + (1.0 - intrp) * table_lookup(s_2, vib)) end end def two_tab_test(start = 0.0, dur = 1.0) two_tab(start, dur, 440, 0.5) $now = start + dur + 0.2 end # LBJ-PIANO $clm_piano_attack_duration = 0.04 $clm_piano_release_duration = 0.2 $clm_db_drop_per_second = -10.0 Piano_Spectra = [[1.97, 0.0326, 2.99, 0.0086, 3.95, 0.0163, 4.97, 0.0178, 5.98, 0.0177, 6.95, 0.0315, 8.02, 0.0001, 8.94, 0.0076, 9.96, 0.0134, 10.99, 0.0284, 11.98, 0.0229, 13.02, 0.0229, 13.89, 0.0010, 15.06, 0.0090, 16.00, 0.0003, 17.08, 0.0078, 18.16, 0.0064, 19.18, 0.0129, 20.21, 0.0085, 21.27, 0.0225, 22.32, 0.0061, 23.41, 0.0102, 24.48, 0.0005, 25.56, 0.0016, 26.64, 0.0018, 27.70, 0.0113, 28.80, 0.0111, 29.91, 0.0158, 31.06, 0.0093, 32.17, 0.0017, 33.32, 0.0002, 34.42, 0.0018, 35.59, 0.0027, 36.74, 0.0055, 37.90, 0.0037, 39.06, 0.0064, 40.25, 0.0033, 41.47, 0.0014, 42.53, 0.0004, 43.89, 0.0010, 45.12, 0.0039, 46.33, 0.0039, 47.64, 0.0009, 48.88, 0.0016, 50.13, 0.0006, 51.37, 0.0010, 52.70, 0.0002, 54.00, 0.0004, 55.30, 0.0008, 56.60, 0.0025, 57.96, 0.0010, 59.30, 0.0012, 60.67, 0.0011, 61.99, 0.0003, 62.86, 0.0001, 64.36, 0.0005, 64.86, 0.0001, 66.26, 0.0004, 67.70, 0.0006, 68.94, 0.0002, 70.10, 0.0001, 70.58, 0.0002, 72.01, 0.0007, 73.53, 0.0006, 75.00, 0.0002, 77.03, 0.0005, 78.00, 0.0002, 79.57, 0.0006, 81.16, 0.0005, 82.70, 0.0005, 84.22, 0.0003, 85.41, 0.0002, 87.46, 0.0001, 90.30, 0.0001, 94.02, 0.0001, 95.26, 0.0002, 109.39, 0.0003], [1.98, 0.0194, 2.99, 0.0210, 3.97, 0.0276, 4.96, 0.0297, 5.96, 0.0158, 6.99, 0.0207, 8.01, 0.0009, 9.00, 0.0101, 10.00, 0.0297, 11.01, 0.0289, 12.02, 0.0211, 13.04, 0.0127, 14.07, 0.0061, 15.08, 0.0174, 16.13, 0.0009, 17.12, 0.0093, 18.16, 0.0117, 19.21, 0.0122, 20.29, 0.0108, 21.30, 0.0077, 22.38, 0.0132, 23.46, 0.0073, 24.14, 0.0002, 25.58, 0.0026, 26.69, 0.0035, 27.77, 0.0053, 28.88, 0.0024, 30.08, 0.0027, 31.13, 0.0075, 32.24, 0.0027, 33.36, 0.0004, 34.42, 0.0004, 35.64, 0.0019, 36.78, 0.0037, 38.10, 0.0009, 39.11, 0.0027, 40.32, 0.0010, 41.51, 0.0013, 42.66, 0.0019, 43.87, 0.0007, 45.13, 0.0017, 46.35, 0.0019, 47.65, 0.0021, 48.89, 0.0014, 50.18, 0.0023, 51.42, 0.0015, 52.73, 0.0002, 54.00, 0.0005, 55.34, 0.0006, 56.60, 0.0010, 57.96, 0.0016, 58.86, 0.0005, 59.30, 0.0004, 60.75, 0.0005, 62.22, 0.0003, 63.55, 0.0005, 64.82, 0.0003, 66.24, 0.0003, 67.63, 0.0011, 69.09, 0.0007, 70.52, 0.0004, 72.00, 0.0005, 73.50, 0.0008, 74.95, 0.0003, 77.13, 0.0013, 78.02, 0.0002, 79.48, 0.0004, 82.59, 0.0004, 84.10, 0.0003], [2.00, 0.0313, 2.99, 0.0109, 4.00, 0.0215, 5.00, 0.0242, 5.98, 0.0355, 7.01, 0.0132, 8.01, 0.0009, 9.01, 0.0071, 10.00, 0.0258, 11.03, 0.0221, 12.02, 0.0056, 13.06, 0.0196, 14.05, 0.0160, 15.11, 0.0107, 16.11, 0.0003, 17.14, 0.0111, 18.21, 0.0085, 19.23, 0.0010, 20.28, 0.0048, 21.31, 0.0128, 22.36, 0.0051, 23.41, 0.0041, 24.05, 0.0006, 25.54, 0.0019, 26.62, 0.0028, 27.72, 0.0034, 28.82, 0.0062, 29.89, 0.0039, 30.98, 0.0058, 32.08, 0.0011, 33.21, 0.0002, 34.37, 0.0008, 35.46, 0.0018, 36.62, 0.0036, 37.77, 0.0018, 38.92, 0.0042, 40.07, 0.0037, 41.23, 0.0011, 42.67, 0.0003, 43.65, 0.0018, 44.68, 0.0025, 45.99, 0.0044, 47.21, 0.0051, 48.40, 0.0044, 49.67, 0.0005, 50.88, 0.0019, 52.15, 0.0003, 53.42, 0.0008, 54.69, 0.0010, 55.98, 0.0005, 57.26, 0.0013, 58.53, 0.0027, 59.83, 0.0011, 61.21, 0.0027, 62.54, 0.0003, 63.78, 0.0003, 65.20, 0.0001, 66.60, 0.0006, 67.98, 0.0008, 69.37, 0.0019, 70.73, 0.0007, 72.14, 0.0004, 73.62, 0.0002, 74.40, 0.0003, 76.52, 0.0006, 77.97, 0.0002, 79.49, 0.0004, 80.77, 0.0003, 81.00, 0.0001, 82.47, 0.0005, 83.97, 0.0001, 87.27, 0.0002], [2.00, 0.0257, 2.99, 0.0142, 3.97, 0.0202, 4.95, 0.0148, 5.95, 0.0420, 6.95, 0.0037, 7.94, 0.0004, 8.94, 0.0172, 9.95, 0.0191, 10.96, 0.0115, 11.97, 0.0059, 12.98, 0.0140, 14.00, 0.0178, 15.03, 0.0121, 16.09, 0.0002, 17.07, 0.0066, 18.08, 0.0033, 19.15, 0.0022, 20.18, 0.0057, 21.22, 0.0077, 22.29, 0.0037, 23.33, 0.0066, 24.97, 0.0002, 25.49, 0.0019, 26.55, 0.0042, 27.61, 0.0043, 28.73, 0.0038, 29.81, 0.0084, 30.91, 0.0040, 32.03, 0.0025, 33.14, 0.0005, 34.26, 0.0003, 35.38, 0.0019, 36.56, 0.0037, 37.68, 0.0049, 38.86, 0.0036, 40.11, 0.0011, 41.28, 0.0008, 42.50, 0.0004, 43.60, 0.0002, 44.74, 0.0022, 45.99, 0.0050, 47.20, 0.0009, 48.40, 0.0036, 49.68, 0.0004, 50.92, 0.0009, 52.17, 0.0005, 53.46, 0.0007, 54.76, 0.0006, 56.06, 0.0005, 57.34, 0.0011, 58.67, 0.0005, 59.95, 0.0015, 61.37, 0.0008, 62.72, 0.0004, 65.42, 0.0009, 66.96, 0.0003, 68.18, 0.0003, 69.78, 0.0003, 71.21, 0.0004, 72.45, 0.0002, 74.22, 0.0003, 75.44, 0.0001, 76.53, 0.0003, 78.31, 0.0004, 79.83, 0.0003, 80.16, 0.0001, 81.33, 0.0003, 82.44, 0.0001, 83.17, 0.0002, 84.81, 0.0003, 85.97, 0.0003, 89.08, 0.0001, 90.70, 0.0002, 92.30, 0.0002, 95.59, 0.0002, 97.22, 0.0003, 98.86, 0.0001, 108.37, 0.0001, 125.54, 0.0001], [1.99, 0.0650, 3.03, 0.0040, 4.03, 0.0059, 5.02, 0.0090, 5.97, 0.0227, 6.98, 0.0050, 8.04, 0.0020, 9.00, 0.0082, 9.96, 0.0078, 11.01, 0.0056, 12.01, 0.0095, 13.02, 0.0050, 14.04, 0.0093, 15.08, 0.0064, 16.14, 0.0017, 17.06, 0.0020, 18.10, 0.0025, 19.14, 0.0023, 20.18, 0.0015, 21.24, 0.0032, 22.29, 0.0029, 23.32, 0.0014, 24.37, 0.0005, 25.43, 0.0030, 26.50, 0.0022, 27.60, 0.0027, 28.64, 0.0024, 29.76, 0.0035, 30.81, 0.0136, 31.96, 0.0025, 33.02, 0.0003, 34.13, 0.0005, 35.25, 0.0007, 36.40, 0.0014, 37.51, 0.0020, 38.64, 0.0012, 39.80, 0.0019, 40.97, 0.0004, 42.09, 0.0003, 43.24, 0.0003, 44.48, 0.0002, 45.65, 0.0024, 46.86, 0.0005, 48.07, 0.0013, 49.27, 0.0008, 50.49, 0.0006, 52.95, 0.0001, 54.23, 0.0005, 55.45, 0.0004, 56.73, 0.0001, 58.03, 0.0003, 59.29, 0.0002, 60.59, 0.0003, 62.04, 0.0002, 65.89, 0.0002, 67.23, 0.0002, 68.61, 0.0002, 69.97, 0.0004, 71.36, 0.0005, 85.42, 0.0001], [1.98, 0.0256, 2.96, 0.0158, 3.95, 0.0310, 4.94, 0.0411, 5.95, 0.0238, 6.94, 0.0152, 7.93, 0.0011, 8.95, 0.0185, 9.92, 0.0166, 10.93, 0.0306, 11.94, 0.0258, 12.96, 0.0202, 13.97, 0.0403, 14.95, 0.0228, 15.93, 0.0005, 17.01, 0.0072, 18.02, 0.0034, 19.06, 0.0028, 20.08, 0.0124, 21.13, 0.0137, 22.16, 0.0102, 23.19, 0.0058, 23.90, 0.0013, 25.30, 0.0039, 26.36, 0.0039, 27.41, 0.0025, 28.47, 0.0071, 29.64, 0.0031, 30.60, 0.0027, 31.71, 0.0021, 32.84, 0.0003, 33.82, 0.0002, 35.07, 0.0019, 36.09, 0.0054, 37.20, 0.0038, 38.33, 0.0024, 39.47, 0.0055, 40.55, 0.0016, 41.77, 0.0006, 42.95, 0.0002, 43.27, 0.0018, 44.03, 0.0006, 45.25, 0.0019, 46.36, 0.0033, 47.50, 0.0024, 48.87, 0.0012, 50.03, 0.0016, 51.09, 0.0004, 53.52, 0.0017, 54.74, 0.0012, 56.17, 0.0003, 57.40, 0.0011, 58.42, 0.0020, 59.70, 0.0007, 61.29, 0.0008, 62.56, 0.0003, 63.48, 0.0002, 64.83, 0.0002, 66.12, 0.0012, 67.46, 0.0017, 68.81, 0.0003, 69.13, 0.0003, 70.53, 0.0002, 71.84, 0.0001, 73.28, 0.0002, 75.52, 0.0010, 76.96, 0.0005, 77.93, 0.0003, 78.32, 0.0003, 79.73, 0.0003, 81.69, 0.0002, 82.52, 0.0001, 84.01, 0.0001, 84.61, 0.0002, 86.88, 0.0001, 88.36, 0.0002, 89.85, 0.0002, 91.35, 0.0003, 92.86, 0.0002, 93.40, 0.0001, 105.28, 0.0002, 106.22, 0.0002, 107.45, 0.0001, 108.70, 0.0003, 122.08, 0.0002], [1.97, 0.0264, 2.97, 0.0211, 3.98, 0.0234, 4.98, 0.0307, 5.96, 0.0085, 6.94, 0.0140, 7.93, 0.0005, 8.96, 0.0112, 9.96, 0.0209, 10.98, 0.0194, 11.98, 0.0154, 12.99, 0.0274, 13.99, 0.0127, 15.01, 0.0101, 15.99, 0.0002, 17.04, 0.0011, 18.08, 0.0032, 19.14, 0.0028, 20.12, 0.0054, 21.20, 0.0053, 22.13, 0.0028, 23.22, 0.0030, 24.32, 0.0006, 25.24, 0.0004, 26.43, 0.0028, 27.53, 0.0048, 28.52, 0.0039, 29.54, 0.0047, 30.73, 0.0044, 31.82, 0.0007, 32.94, 0.0008, 34.04, 0.0012, 35.13, 0.0018, 36.29, 0.0007, 37.35, 0.0075, 38.51, 0.0045, 39.66, 0.0014, 40.90, 0.0004, 41.90, 0.0002, 43.08, 0.0002, 44.24, 0.0017, 45.36, 0.0013, 46.68, 0.0020, 47.79, 0.0015, 48.98, 0.0010, 50.21, 0.0012, 51.34, 0.0001, 53.82, 0.0003, 55.09, 0.0004, 56.23, 0.0005, 57.53, 0.0004, 58.79, 0.0005, 59.30, 0.0002, 60.03, 0.0002, 61.40, 0.0003, 62.84, 0.0001, 66.64, 0.0001, 67.97, 0.0001, 69.33, 0.0001, 70.68, 0.0001, 73.57, 0.0002, 75.76, 0.0002, 76.45, 0.0001, 79.27, 0.0001, 80.44, 0.0002, 81.87, 0.0002], [2.00, 0.0311, 2.99, 0.0086, 3.99, 0.0266, 4.97, 0.0123, 5.98, 0.0235, 6.97, 0.0161, 7.97, 0.0008, 8.96, 0.0088, 9.96, 0.0621, 10.99, 0.0080, 11.99, 0.0034, 12.99, 0.0300, 14.03, 0.0228, 15.04, 0.0105, 16.03, 0.0004, 17.06, 0.0036, 18.09, 0.0094, 18.95, 0.0009, 20.17, 0.0071, 21.21, 0.0161, 22.25, 0.0106, 23.28, 0.0104, 24.33, 0.0008, 25.38, 0.0030, 26.46, 0.0035, 27.50, 0.0026, 28.59, 0.0028, 29.66, 0.0128, 30.75, 0.0139, 31.81, 0.0038, 32.93, 0.0006, 34.04, 0.0004, 35.16, 0.0005, 36.25, 0.0023, 37.35, 0.0012, 38.46, 0.0021, 39.59, 0.0035, 40.71, 0.0006, 41.86, 0.0007, 42.42, 0.0001, 43.46, 0.0003, 44.17, 0.0032, 45.29, 0.0013, 46.57, 0.0004, 47.72, 0.0011, 48.79, 0.0005, 50.11, 0.0005, 51.29, 0.0003, 52.47, 0.0002, 53.68, 0.0004, 55.02, 0.0005, 56.18, 0.0003, 57.41, 0.0003, 58.75, 0.0007, 59.33, 0.0009, 60.00, 0.0004, 61.34, 0.0001, 64.97, 0.0003, 65.20, 0.0002, 66.48, 0.0002, 67.83, 0.0002, 68.90, 0.0003, 70.25, 0.0003, 71.59, 0.0002, 73.68, 0.0001, 75.92, 0.0001, 77.08, 0.0002, 78.45, 0.0002, 81.56, 0.0002, 82.99, 0.0001, 88.39, 0.0001], [0.97, 0.0059, 1.98, 0.0212, 2.99, 0.0153, 3.99, 0.0227, 4.96, 0.0215, 5.97, 0.0153, 6.98, 0.0085, 7.98, 0.0007, 8.97, 0.0179, 9.98, 0.0512, 10.98, 0.0322, 12.00, 0.0098, 13.02, 0.0186, 14.00, 0.0099, 15.05, 0.0109, 15.88, 0.0011, 17.07, 0.0076, 18.11, 0.0071, 19.12, 0.0045, 20.16, 0.0038, 21.23, 0.0213, 22.27, 0.0332, 23.34, 0.0082, 24.34, 0.0014, 25.42, 0.0024, 26.47, 0.0012, 27.54, 0.0014, 28.60, 0.0024, 29.72, 0.0026, 30.10, 0.0008, 31.91, 0.0021, 32.13, 0.0011, 33.02, 0.0007, 34.09, 0.0014, 35.17, 0.0007, 36.27, 0.0024, 37.39, 0.0029, 38.58, 0.0014, 39.65, 0.0017, 40.95, 0.0012, 41.97, 0.0004, 42.43, 0.0002, 43.49, 0.0001, 44.31, 0.0012, 45.42, 0.0031, 46.62, 0.0017, 47.82, 0.0013, 49.14, 0.0013, 50.18, 0.0010, 51.54, 0.0003, 53.90, 0.0006, 55.06, 0.0010, 56.31, 0.0003, 57.63, 0.0001, 59.02, 0.0003, 60.09, 0.0004, 60.35, 0.0004, 61.62, 0.0009, 63.97, 0.0001, 65.19, 0.0001, 65.54, 0.0002, 66.92, 0.0002, 67.94, 0.0002, 69.17, 0.0003, 69.60, 0.0004, 70.88, 0.0002, 72.24, 0.0002, 76.12, 0.0001, 78.94, 0.0001, 81.75, 0.0001, 82.06, 0.0001, 83.53, 0.0001, 90.29, 0.0002, 91.75, 0.0001, 92.09, 0.0002, 93.28, 0.0001, 97.07, 0.0001], [1.98, 0.0159, 2.98, 0.1008, 3.98, 0.0365, 4.98, 0.0133, 5.97, 0.0101, 6.97, 0.0115, 7.97, 0.0007, 8.99, 0.0349, 10.01, 0.0342, 11.01, 0.0236, 12.00, 0.0041, 13.02, 0.0114, 14.05, 0.0137, 15.06, 0.0100, 16.05, 0.0007, 17.04, 0.0009, 18.12, 0.0077, 19.15, 0.0023, 20.12, 0.0017, 21.24, 0.0113, 22.26, 0.0126, 23.30, 0.0093, 24.36, 0.0007, 25.43, 0.0007, 26.47, 0.0009, 27.55, 0.0013, 28.59, 0.0025, 29.61, 0.0010, 30.77, 0.0021, 31.86, 0.0023, 32.96, 0.0003, 34.03, 0.0007, 35.06, 0.0005, 36.20, 0.0006, 37.34, 0.0006, 38.36, 0.0009, 39.60, 0.0016, 40.69, 0.0005, 41.77, 0.0002, 42.92, 0.0002, 44.02, 0.0003, 45.24, 0.0006, 46.33, 0.0004, 47.50, 0.0007, 48.71, 0.0007, 49.87, 0.0002, 51.27, 0.0002, 53.42, 0.0003, 55.88, 0.0003, 57.10, 0.0004, 58.34, 0.0002, 59.86, 0.0003, 61.13, 0.0003, 67.18, 0.0001, 68.50, 0.0001, 71.17, 0.0001, 83.91, 0.0001, 90.55, 0.0001], [0.98, 0.0099, 2.00, 0.0181, 2.99, 0.0353, 3.98, 0.0285, 4.97, 0.0514, 5.96, 0.0402, 6.96, 0.0015, 7.98, 0.0012, 8.98, 0.0175, 9.98, 0.0264, 10.98, 0.0392, 11.98, 0.0236, 13.00, 0.0153, 14.04, 0.0049, 15.00, 0.0089, 16.01, 0.0001, 17.03, 0.0106, 18.03, 0.0028, 19.05, 0.0024, 20.08, 0.0040, 21.11, 0.0103, 22.12, 0.0104, 23.20, 0.0017, 24.19, 0.0008, 25.20, 0.0007, 26.24, 0.0011, 27.36, 0.0009, 27.97, 0.0030, 29.40, 0.0044, 30.37, 0.0019, 31.59, 0.0017, 32.65, 0.0008, 33.59, 0.0005, 34.79, 0.0009, 35.75, 0.0027, 36.88, 0.0035, 37.93, 0.0039, 39.00, 0.0031, 40.08, 0.0025, 41.16, 0.0010, 43.25, 0.0004, 44.52, 0.0012, 45.62, 0.0023, 45.85, 0.0012, 47.00, 0.0006, 47.87, 0.0008, 48.99, 0.0003, 50.48, 0.0003, 51.62, 0.0001, 52.43, 0.0001, 53.56, 0.0002, 54.76, 0.0002, 56.04, 0.0002, 56.68, 0.0006, 57.10, 0.0003, 58.28, 0.0005, 59.47, 0.0003, 59.96, 0.0002, 60.67, 0.0001, 63.08, 0.0002, 64.29, 0.0002, 66.72, 0.0001, 67.97, 0.0001, 68.65, 0.0001, 70.43, 0.0001, 79.38, 0.0001, 80.39, 0.0001, 82.39, 0.0001], [1.00, 0.0765, 1.99, 0.0151, 2.99, 0.0500, 3.99, 0.0197, 5.00, 0.0260, 6.00, 0.0145, 6.98, 0.0128, 7.97, 0.0004, 8.98, 0.0158, 9.99, 0.0265, 11.02, 0.0290, 12.02, 0.0053, 13.03, 0.0242, 14.03, 0.0103, 15.06, 0.0054, 16.04, 0.0006, 17.08, 0.0008, 18.10, 0.0058, 19.16, 0.0011, 20.16, 0.0055, 21.18, 0.0040, 22.20, 0.0019, 23.22, 0.0014, 24.05, 0.0005, 25.31, 0.0019, 26.38, 0.0018, 27.44, 0.0022, 28.45, 0.0024, 29.57, 0.0073, 30.58, 0.0032, 31.66, 0.0071, 32.73, 0.0015, 33.85, 0.0005, 34.96, 0.0003, 36.00, 0.0020, 37.11, 0.0018, 38.18, 0.0055, 39.23, 0.0006, 40.33, 0.0004, 41.52, 0.0003, 43.41, 0.0028, 45.05, 0.0003, 45.99, 0.0002, 47.07, 0.0003, 48.52, 0.0002, 49.48, 0.0003, 50.63, 0.0003, 51.81, 0.0002, 54.05, 0.0002, 55.24, 0.0001, 56.62, 0.0001, 57.81, 0.0004, 59.16, 0.0013, 60.23, 0.0003, 66.44, 0.0001, 68.99, 0.0004, 75.49, 0.0001, 87.56, 0.0004], [0.98, 0.0629, 1.99, 0.0232, 2.98, 0.0217, 4.00, 0.0396, 4.98, 0.0171, 5.97, 0.0098, 6.99, 0.0167, 7.99, 0.0003, 8.98, 0.0192, 9.98, 0.0266, 10.99, 0.0256, 12.01, 0.0061, 13.02, 0.0135, 14.02, 0.0062, 15.05, 0.0158, 16.06, 0.0018, 17.08, 0.0101, 18.09, 0.0053, 19.11, 0.0074, 20.13, 0.0020, 21.17, 0.0052, 22.22, 0.0077, 23.24, 0.0035, 24.00, 0.0009, 25.32, 0.0016, 26.40, 0.0022, 27.43, 0.0005, 28.55, 0.0026, 29.60, 0.0026, 30.65, 0.0010, 31.67, 0.0019, 32.77, 0.0008, 33.81, 0.0003, 34.91, 0.0003, 36.01, 0.0005, 37.11, 0.0010, 38.20, 0.0014, 39.29, 0.0039, 40.43, 0.0012, 41.50, 0.0006, 43.38, 0.0017, 43.75, 0.0002, 44.94, 0.0005, 46.13, 0.0002, 47.11, 0.0003, 48.28, 0.0005, 48.42, 0.0005, 49.44, 0.0003, 50.76, 0.0004, 51.93, 0.0002, 54.15, 0.0003, 55.31, 0.0005, 55.50, 0.0003, 56.98, 0.0003, 57.90, 0.0004, 60.33, 0.0002, 61.39, 0.0001, 61.59, 0.0001, 65.09, 0.0002, 66.34, 0.0001, 68.85, 0.0001, 70.42, 0.0002, 71.72, 0.0001, 73.05, 0.0003, 79.65, 0.0001, 85.28, 0.0002, 93.52, 0.0001], [1.02, 0.0185, 1.99, 0.0525, 2.98, 0.0613, 3.99, 0.0415, 4.98, 0.0109, 5.97, 0.0248, 6.99, 0.0102, 7.98, 0.0005, 8.98, 0.0124, 9.99, 0.0103, 10.99, 0.0124, 12.00, 0.0016, 13.01, 0.0029, 14.03, 0.0211, 15.04, 0.0128, 16.07, 0.0021, 17.09, 0.0009, 18.09, 0.0043, 19.14, 0.0022, 20.13, 0.0016, 21.20, 0.0045, 22.21, 0.0088, 23.26, 0.0046, 24.29, 0.0013, 25.35, 0.0009, 26.39, 0.0028, 27.49, 0.0009, 28.51, 0.0006, 29.58, 0.0012, 30.70, 0.0010, 31.74, 0.0019, 32.75, 0.0002, 33.85, 0.0001, 34.95, 0.0005, 36.02, 0.0003, 37.16, 0.0009, 38.25, 0.0018, 39.35, 0.0008, 40.54, 0.0004, 41.61, 0.0002, 43.40, 0.0004, 43.74, 0.0003, 45.05, 0.0001, 46.11, 0.0003, 47.40, 0.0002, 48.36, 0.0004, 49.55, 0.0004, 50.72, 0.0002, 52.00, 0.0001, 55.58, 0.0002, 57.02, 0.0001, 57.98, 0.0002, 59.13, 0.0003, 61.56, 0.0001, 66.56, 0.0001, 87.65, 0.0002], [1.00, 0.0473, 1.99, 0.0506, 2.99, 0.0982, 3.99, 0.0654, 5.00, 0.0196, 5.99, 0.0094, 6.99, 0.0118, 7.93, 0.0001, 8.99, 0.0057, 10.01, 0.0285, 11.01, 0.0142, 12.03, 0.0032, 13.03, 0.0056, 14.06, 0.0064, 15.06, 0.0059, 16.11, 0.0005, 17.09, 0.0033, 18.14, 0.0027, 19.15, 0.0014, 20.17, 0.0010, 21.21, 0.0059, 22.26, 0.0043, 23.31, 0.0031, 24.31, 0.0018, 25.33, 0.0009, 26.41, 0.0005, 27.47, 0.0015, 28.53, 0.0015, 29.58, 0.0041, 30.65, 0.0025, 31.73, 0.0011, 32.83, 0.0010, 34.98, 0.0003, 36.07, 0.0009, 37.23, 0.0001, 38.26, 0.0020, 39.41, 0.0014, 40.53, 0.0005, 41.40, 0.0003, 42.80, 0.0002, 43.48, 0.0028, 43.93, 0.0001, 45.03, 0.0003, 46.18, 0.0007, 47.41, 0.0001, 48.57, 0.0002, 49.67, 0.0001, 50.83, 0.0002, 54.39, 0.0001, 55.58, 0.0002, 57.97, 0.0005, 58.11, 0.0002, 59.21, 0.0001, 60.42, 0.0002, 61.66, 0.0001], [1.00, 0.0503, 2.00, 0.0963, 2.99, 0.1304, 3.99, 0.0218, 4.98, 0.0041, 5.98, 0.0292, 6.98, 0.0482, 7.99, 0.0005, 8.99, 0.0280, 10.00, 0.0237, 11.00, 0.0152, 12.02, 0.0036, 12.95, 0.0022, 14.06, 0.0111, 15.07, 0.0196, 16.08, 0.0016, 17.11, 0.0044, 18.13, 0.0073, 19.17, 0.0055, 20.19, 0.0028, 21.20, 0.0012, 22.27, 0.0068, 23.30, 0.0036, 24.35, 0.0012, 25.35, 0.0002, 26.46, 0.0005, 27.47, 0.0005, 28.59, 0.0009, 29.65, 0.0021, 30.70, 0.0020, 31.78, 0.0012, 32.89, 0.0010, 35.06, 0.0005, 36.16, 0.0008, 37.27, 0.0010, 38.36, 0.0010, 39.47, 0.0014, 40.58, 0.0004, 41.43, 0.0007, 41.82, 0.0003, 43.48, 0.0008, 44.53, 0.0001, 45.25, 0.0003, 46.43, 0.0002, 47.46, 0.0002, 48.76, 0.0005, 49.95, 0.0004, 50.96, 0.0002, 51.12, 0.0002, 52.33, 0.0001, 54.75, 0.0001, 55.75, 0.0002, 56.90, 0.0002, 58.17, 0.0002, 59.40, 0.0004, 60.62, 0.0002, 65.65, 0.0001, 66.91, 0.0002, 69.91, 0.0001, 71.25, 0.0002], [1.00, 0.1243, 1.98, 0.1611, 3.00, 0.0698, 3.98, 0.0390, 5.00, 0.0138, 5.99, 0.0154, 7.01, 0.0287, 8.01, 0.0014, 9.01, 0.0049, 10.00, 0.0144, 11.01, 0.0055, 12.05, 0.0052, 13.01, 0.0011, 14.05, 0.0118, 15.07, 0.0154, 16.12, 0.0028, 17.14, 0.0061, 18.25, 0.0007, 19.22, 0.0020, 20.24, 0.0011, 21.27, 0.0029, 22.30, 0.0046, 23.34, 0.0049, 24.35, 0.0004, 25.45, 0.0003, 26.47, 0.0007, 27.59, 0.0008, 28.16, 0.0009, 29.12, 0.0002, 29.81, 0.0006, 30.81, 0.0009, 31.95, 0.0004, 33.00, 0.0011, 34.12, 0.0005, 35.18, 0.0003, 36.30, 0.0008, 37.38, 0.0003, 38.55, 0.0003, 39.64, 0.0006, 40.77, 0.0007, 41.52, 0.0006, 41.89, 0.0006, 43.04, 0.0011, 43.60, 0.0009, 44.31, 0.0002, 45.68, 0.0002, 46.56, 0.0003, 47.60, 0.0001, 48.83, 0.0006, 50.01, 0.0003, 51.27, 0.0003, 56.04, 0.0005, 57.21, 0.0003, 58.56, 0.0004, 59.83, 0.0003, 61.05, 0.0001, 62.20, 0.0001, 67.37, 0.0002, 76.53, 0.0001], [0.99, 0.0222, 1.99, 0.0678, 2.99, 0.0683, 4.00, 0.0191, 5.00, 0.0119, 6.01, 0.0232, 6.98, 0.0336, 7.99, 0.0082, 9.01, 0.0201, 10.01, 0.0189, 11.01, 0.0041, 12.01, 0.0053, 13.05, 0.0154, 14.04, 0.0159, 15.06, 0.0092, 16.11, 0.0038, 17.12, 0.0014, 18.15, 0.0091, 19.16, 0.0006, 20.30, 0.0012, 21.25, 0.0061, 22.28, 0.0099, 23.34, 0.0028, 24.38, 0.0012, 25.43, 0.0016, 26.49, 0.0048, 27.55, 0.0025, 28.62, 0.0015, 29.71, 0.0032, 30.78, 0.0077, 31.88, 0.0011, 32.97, 0.0007, 34.08, 0.0006, 35.16, 0.0008, 36.28, 0.0004, 37.41, 0.0006, 38.54, 0.0005, 39.62, 0.0002, 40.80, 0.0003, 41.93, 0.0001, 43.06, 0.0002, 44.21, 0.0003, 45.38, 0.0002, 46.54, 0.0007, 47.78, 0.0003, 48.95, 0.0004, 50.10, 0.0003, 51.37, 0.0002, 53.79, 0.0003, 56.20, 0.0001, 58.71, 0.0002, 66.47, 0.0003], [1.01, 0.0241, 1.99, 0.1011, 2.98, 0.0938, 3.98, 0.0081, 4.99, 0.0062, 5.99, 0.0291, 6.99, 0.0676, 7.59, 0.0004, 8.98, 0.0127, 9.99, 0.0112, 10.99, 0.0142, 12.00, 0.0029, 13.02, 0.0071, 14.02, 0.0184, 15.03, 0.0064, 16.07, 0.0010, 17.09, 0.0011, 18.11, 0.0010, 19.15, 0.0060, 20.19, 0.0019, 21.24, 0.0025, 22.29, 0.0013, 23.31, 0.0050, 25.41, 0.0030, 26.50, 0.0018, 27.53, 0.0006, 28.63, 0.0012, 29.66, 0.0013, 30.77, 0.0020, 31.84, 0.0006, 34.04, 0.0001, 35.14, 0.0001, 36.32, 0.0004, 37.41, 0.0007, 38.53, 0.0007, 39.67, 0.0009, 40.85, 0.0003, 45.49, 0.0002, 46.65, 0.0001, 47.81, 0.0004, 49.01, 0.0002, 53.91, 0.0002, 55.14, 0.0002, 57.69, 0.0002], [1.00, 0.0326, 2.00, 0.1066, 2.99, 0.1015, 4.00, 0.0210, 4.97, 0.0170, 5.99, 0.0813, 6.98, 0.0820, 7.96, 0.0011, 8.99, 0.0248, 10.03, 0.0107, 11.01, 0.0126, 12.01, 0.0027, 13.01, 0.0233, 14.04, 0.0151, 15.05, 0.0071, 16.04, 0.0002, 17.10, 0.0061, 18.12, 0.0059, 19.15, 0.0087, 20.23, 0.0005, 21.25, 0.0040, 22.30, 0.0032, 23.35, 0.0004, 24.40, 0.0001, 25.45, 0.0030, 26.54, 0.0022, 27.60, 0.0003, 28.70, 0.0009, 29.80, 0.0029, 30.85, 0.0006, 31.97, 0.0006, 34.19, 0.0004, 35.30, 0.0003, 36.43, 0.0007, 37.56, 0.0005, 38.68, 0.0019, 39.88, 0.0013, 41.00, 0.0003, 43.35, 0.0003, 44.51, 0.0002, 45.68, 0.0006, 46.93, 0.0010, 48.11, 0.0006, 49.29, 0.0003, 55.58, 0.0002], [0.98, 0.0113, 1.99, 0.0967, 3.00, 0.0719, 3.98, 0.0345, 4.98, 0.0121, 6.00, 0.0621, 7.00, 0.0137, 7.98, 0.0006, 9.01, 0.0314, 10.01, 0.0171, 11.02, 0.0060, 12.03, 0.0024, 13.05, 0.0077, 14.07, 0.0040, 15.12, 0.0032, 16.13, 0.0004, 17.15, 0.0011, 18.20, 0.0028, 19.18, 0.0003, 20.26, 0.0003, 21.31, 0.0025, 22.35, 0.0021, 23.39, 0.0005, 25.55, 0.0002, 26.62, 0.0014, 27.70, 0.0003, 28.78, 0.0005, 29.90, 0.0030, 31.01, 0.0011, 32.12, 0.0005, 34.31, 0.0001, 35.50, 0.0002, 36.62, 0.0002, 37.76, 0.0005, 38.85, 0.0002, 40.09, 0.0004, 43.60, 0.0001, 44.73, 0.0002, 46.02, 0.0002, 47.25, 0.0004, 48.44, 0.0004], [0.99, 0.0156, 1.98, 0.0846, 2.98, 0.0178, 3.98, 0.0367, 4.98, 0.0448, 5.98, 0.0113, 6.99, 0.0189, 8.00, 0.0011, 9.01, 0.0247, 10.02, 0.0089, 11.01, 0.0184, 12.03, 0.0105, 13.00, 0.0039, 14.07, 0.0116, 15.09, 0.0078, 16.13, 0.0008, 17.14, 0.0064, 18.19, 0.0029, 19.22, 0.0028, 20.25, 0.0017, 21.32, 0.0043, 22.37, 0.0055, 23.42, 0.0034, 24.48, 0.0004, 25.54, 0.0002, 26.61, 0.0017, 27.70, 0.0011, 28.80, 0.0002, 29.89, 0.0019, 30.97, 0.0028, 32.09, 0.0007, 34.30, 0.0002, 35.44, 0.0003, 36.55, 0.0001, 37.69, 0.0004, 38.93, 0.0002, 40.05, 0.0005, 41.20, 0.0005, 42.37, 0.0002, 43.54, 0.0003, 44.73, 0.0001, 45.95, 0.0002, 47.16, 0.0001, 48.43, 0.0005, 49.65, 0.0004, 55.90, 0.0002, 59.81, 0.0004], [1.01, 0.0280, 2.00, 0.0708, 2.99, 0.0182, 3.99, 0.0248, 4.98, 0.0245, 5.98, 0.0279, 6.98, 0.0437, 7.99, 0.0065, 8.99, 0.0299, 10.00, 0.0073, 10.99, 0.0011, 12.03, 0.0122, 13.03, 0.0028, 14.08, 0.0044, 15.11, 0.0097, 16.15, 0.0010, 17.17, 0.0025, 18.19, 0.0017, 19.24, 0.0008, 20.28, 0.0040, 21.32, 0.0024, 22.38, 0.0008, 23.46, 0.0032, 24.52, 0.0010, 25.59, 0.0008, 26.68, 0.0009, 27.76, 0.0012, 28.88, 0.0003, 29.95, 0.0005, 31.05, 0.0017, 32.14, 0.0002, 33.29, 0.0003, 37.88, 0.0002, 39.03, 0.0002, 40.19, 0.0004, 41.37, 0.0003, 43.74, 0.0002, 46.20, 0.0001, 48.68, 0.0001, 49.93, 0.0001, 51.19, 0.0002], [1.00, 0.0225, 1.99, 0.0921, 2.98, 0.0933, 3.99, 0.0365, 4.99, 0.0100, 5.98, 0.0213, 6.98, 0.0049, 7.98, 0.0041, 8.98, 0.0090, 9.99, 0.0068, 11.01, 0.0040, 12.03, 0.0086, 13.02, 0.0015, 14.04, 0.0071, 15.09, 0.0082, 16.14, 0.0011, 17.15, 0.0014, 18.18, 0.0010, 19.26, 0.0013, 20.26, 0.0005, 21.33, 0.0006, 22.36, 0.0011, 23.46, 0.0016, 24.52, 0.0004, 25.59, 0.0002, 26.70, 0.0006, 27.78, 0.0007, 28.87, 0.0002, 30.03, 0.0008, 31.14, 0.0010, 32.24, 0.0006, 33.37, 0.0002, 35.67, 0.0003, 37.99, 0.0004, 39.17, 0.0004, 40.35, 0.0005, 41.53, 0.0001, 46.42, 0.0001], [1.00, 0.0465, 1.99, 0.0976, 2.98, 0.0678, 4.00, 0.0727, 4.99, 0.0305, 5.98, 0.0210, 6.98, 0.0227, 8.00, 0.0085, 9.01, 0.0183, 10.02, 0.0258, 11.05, 0.0003, 12.06, 0.0061, 13.05, 0.0021, 14.10, 0.0089, 15.12, 0.0077, 16.16, 0.0016, 17.21, 0.0061, 18.23, 0.0011, 19.29, 0.0031, 20.36, 0.0031, 21.41, 0.0007, 22.48, 0.0013, 23.55, 0.0020, 24.64, 0.0004, 25.74, 0.0005, 26.81, 0.0006, 27.95, 0.0006, 29.03, 0.0001, 30.22, 0.0010, 31.30, 0.0004, 32.48, 0.0001, 33.60, 0.0002, 38.30, 0.0003], [1.00, 0.0674, 1.99, 0.0841, 2.98, 0.0920, 3.99, 0.0328, 4.99, 0.0368, 5.98, 0.0206, 6.99, 0.0246, 8.01, 0.0048, 9.01, 0.0218, 10.03, 0.0155, 11.05, 0.0048, 12.06, 0.0077, 13.00, 0.0020, 14.10, 0.0083, 15.15, 0.0084, 16.18, 0.0015, 17.22, 0.0039, 18.27, 0.0032, 19.34, 0.0026, 20.40, 0.0012, 21.47, 0.0009, 22.54, 0.0008, 23.62, 0.0016, 24.71, 0.0005, 25.82, 0.0004, 26.91, 0.0002, 28.03, 0.0008, 29.17, 0.0002, 30.32, 0.0028, 31.45, 0.0004, 32.61, 0.0005, 33.77, 0.0001, 36.14, 0.0003, 37.32, 0.0002, 38.54, 0.0005, 39.75, 0.0002, 42.23, 0.0002, 48.65, 0.0001], [1.01, 0.0423, 1.99, 0.0240, 2.98, 0.0517, 4.00, 0.0493, 5.00, 0.0324, 6.00, 0.0094, 6.99, 0.0449, 7.99, 0.0050, 9.00, 0.0197, 10.03, 0.0132, 11.03, 0.0009, 12.07, 0.0017, 13.08, 0.0023, 14.12, 0.0094, 15.16, 0.0071, 16.21, 0.0020, 17.25, 0.0005, 18.30, 0.0027, 19.04, 0.0004, 20.43, 0.0022, 21.51, 0.0002, 22.59, 0.0006, 23.72, 0.0018, 24.80, 0.0002, 25.88, 0.0002, 27.03, 0.0002, 28.09, 0.0006, 29.31, 0.0002, 30.46, 0.0004, 31.61, 0.0007, 32.78, 0.0005, 33.95, 0.0001, 36.34, 0.0002, 37.56, 0.0001, 38.80, 0.0001, 40.02, 0.0001, 44.14, 0.0001], [1.00, 0.0669, 1.99, 0.0909, 2.99, 0.0410, 3.98, 0.0292, 4.98, 0.0259, 5.98, 0.0148, 6.98, 0.0319, 7.99, 0.0076, 9.01, 0.0056, 10.02, 0.0206, 11.04, 0.0032, 12.05, 0.0085, 13.08, 0.0040, 14.12, 0.0037, 15.16, 0.0030, 16.20, 0.0013, 17.24, 0.0021, 18.30, 0.0010, 19.36, 0.0015, 20.44, 0.0013, 21.50, 0.0009, 22.60, 0.0015, 23.69, 0.0014, 24.80, 0.0006, 25.87, 0.0002, 27.02, 0.0006, 28.12, 0.0002, 29.28, 0.0003, 30.43, 0.0002, 31.59, 0.0007, 32.79, 0.0001, 35.14, 0.0001, 37.57, 0.0001, 40.03, 0.0002, 41.28, 0.0004, 44.10, 0.0001], [0.99, 0.0421, 1.99, 0.1541, 2.98, 0.0596, 3.98, 0.0309, 4.98, 0.0301, 5.99, 0.0103, 7.00, 0.0240, 8.01, 0.0073, 9.01, 0.0222, 10.04, 0.0140, 11.05, 0.0033, 12.08, 0.0045, 13.13, 0.0009, 14.13, 0.0015, 15.21, 0.0026, 16.24, 0.0003, 17.30, 0.0004, 18.35, 0.0010, 19.39, 0.0003, 20.50, 0.0015, 21.57, 0.0003, 22.68, 0.0011, 23.80, 0.0005, 24.90, 0.0008, 26.02, 0.0002, 27.16, 0.0001, 28.30, 0.0006, 29.48, 0.0002, 31.81, 0.0005, 33.00, 0.0003, 34.21, 0.0001, 37.89, 0.0001], [0.99, 0.0389, 2.00, 0.2095, 3.00, 0.0835, 3.99, 0.0289, 5.00, 0.0578, 5.99, 0.0363, 7.01, 0.0387, 8.01, 0.0056, 9.04, 0.0173, 10.05, 0.0175, 11.08, 0.0053, 12.10, 0.0056, 13.15, 0.0064, 14.19, 0.0036, 15.22, 0.0019, 16.29, 0.0010, 17.36, 0.0017, 18.43, 0.0018, 19.51, 0.0004, 20.60, 0.0011, 21.70, 0.0003, 22.82, 0.0003, 23.95, 0.0001, 25.05, 0.0004, 26.17, 0.0001, 28.50, 0.0003, 29.68, 0.0001, 32.07, 0.0003, 33.28, 0.0004, 34.52, 0.0001], [1.00, 0.1238, 1.99, 0.2270, 3.00, 0.0102, 3.99, 0.0181, 4.98, 0.0415, 6.00, 0.0165, 7.01, 0.0314, 8.02, 0.0148, 9.04, 0.0203, 10.05, 0.0088, 11.07, 0.0062, 12.11, 0.0070, 13.14, 0.0054, 14.19, 0.0028, 15.24, 0.0044, 16.30, 0.0029, 17.38, 0.0009, 18.45, 0.0026, 19.56, 0.0003, 20.65, 0.0025, 21.74, 0.0014, 22.87, 0.0013, 23.99, 0.0007, 25.15, 0.0002, 27.46, 0.0004, 28.39, 0.0006, 28.65, 0.0004, 29.85, 0.0001, 31.05, 0.0002, 32.27, 0.0003, 33.52, 0.0002, 34.76, 0.0003], [1.00, 0.1054, 2.00, 0.2598, 2.99, 0.0369, 3.98, 0.0523, 4.99, 0.0020, 5.99, 0.0051, 7.00, 0.0268, 8.01, 0.0027, 9.04, 0.0029, 10.05, 0.0081, 11.08, 0.0047, 12.12, 0.0051, 13.16, 0.0091, 14.19, 0.0015, 15.27, 0.0030, 16.34, 0.0017, 17.42, 0.0006, 18.51, 0.0003, 19.61, 0.0007, 20.72, 0.0003, 21.84, 0.0001, 22.99, 0.0010, 24.13, 0.0001, 28.44, 0.0001, 30.09, 0.0001], [0.99, 0.0919, 2.00, 0.0418, 2.99, 0.0498, 3.99, 0.0135, 4.99, 0.0026, 6.00, 0.0155, 7.01, 0.0340, 8.02, 0.0033, 9.04, 0.0218, 10.08, 0.0084, 11.11, 0.0057, 12.15, 0.0051, 13.21, 0.0043, 14.25, 0.0015, 15.31, 0.0023, 16.40, 0.0008, 17.48, 0.0004, 18.59, 0.0016, 19.71, 0.0010, 20.84, 0.0018, 21.98, 0.0002, 23.11, 0.0013, 24.26, 0.0003, 26.67, 0.0002, 29.12, 0.0002, 30.37, 0.0002, 31.62, 0.0003, 32.92, 0.0001], [0.99, 0.1174, 1.99, 0.1126, 2.99, 0.0370, 3.99, 0.0159, 5.01, 0.0472, 6.01, 0.0091, 7.03, 0.0211, 8.05, 0.0015, 9.07, 0.0098, 10.11, 0.0038, 11.15, 0.0042, 12.20, 0.0018, 13.24, 0.0041, 14.32, 0.0033, 15.41, 0.0052, 16.49, 0.0001, 17.61, 0.0004, 18.71, 0.0004, 19.84, 0.0004, 20.99, 0.0002, 22.14, 0.0006, 23.31, 0.0006, 24.50, 0.0004, 25.70, 0.0002, 28.09, 0.0002, 28.66, 0.0002, 32.00, 0.0001], [1.00, 0.1085, 2.00, 0.1400, 2.99, 0.0173, 3.99, 0.0229, 5.00, 0.0272, 6.02, 0.0077, 7.03, 0.0069, 8.04, 0.0017, 9.08, 0.0045, 10.10, 0.0030, 11.15, 0.0040, 12.20, 0.0007, 13.25, 0.0019, 14.32, 0.0008, 15.42, 0.0024, 16.50, 0.0002, 17.59, 0.0005, 18.71, 0.0003, 19.83, 0.0002, 20.98, 0.0005, 23.29, 0.0008], [1.00, 0.0985, 2.00, 0.1440, 2.99, 0.0364, 3.99, 0.0425, 5.00, 0.0190, 6.01, 0.0089, 7.03, 0.0278, 8.04, 0.0006, 9.07, 0.0083, 10.10, 0.0021, 11.14, 0.0050, 12.18, 0.0005, 13.26, 0.0036, 14.33, 0.0005, 15.41, 0.0026, 17.62, 0.0004, 18.75, 0.0004, 19.89, 0.0003, 21.04, 0.0012, 22.21, 0.0002, 23.38, 0.0004, 27.04, 0.0001], [0.99, 0.1273, 2.00, 0.1311, 2.99, 0.0120, 4.00, 0.0099, 5.00, 0.0235, 6.02, 0.0068, 7.03, 0.0162, 8.06, 0.0009, 9.08, 0.0083, 10.12, 0.0014, 11.17, 0.0050, 12.24, 0.0010, 13.29, 0.0013, 14.39, 0.0022, 15.48, 0.0011, 16.59, 0.0002, 17.70, 0.0003, 18.84, 0.0010, 20.00, 0.0003, 21.17, 0.0003, 23.56, 0.0004, 28.79, 0.0003], [1.00, 0.1018, 2.00, 0.1486, 3.00, 0.0165, 4.00, 0.0186, 5.01, 0.0194, 6.02, 0.0045, 7.04, 0.0083, 8.06, 0.0012, 9.10, 0.0066, 10.15, 0.0009, 11.19, 0.0008, 12.26, 0.0011, 13.34, 0.0028, 14.45, 0.0006, 15.53, 0.0009, 16.66, 0.0002, 17.79, 0.0006, 18.94, 0.0005, 20.11, 0.0003, 21.29, 0.0005, 22.49, 0.0003, 23.73, 0.0005, 26.22, 0.0001, 27.52, 0.0001, 28.88, 0.0002], [1.00, 0.1889, 1.99, 0.1822, 3.00, 0.0363, 4.00, 0.0047, 5.01, 0.0202, 6.03, 0.0053, 7.05, 0.0114, 8.01, 0.0002, 9.13, 0.0048, 10.17, 0.0010, 11.23, 0.0033, 12.30, 0.0010, 13.38, 0.0006, 14.50, 0.0002, 15.62, 0.0010, 20.27, 0.0001, 21.47, 0.0001], [1.00, 0.0522, 1.99, 0.0763, 2.99, 0.0404, 4.00, 0.0139, 5.01, 0.0185, 6.01, 0.0021, 7.06, 0.0045, 8.09, 0.0002, 9.11, 0.0003, 10.17, 0.0006, 11.25, 0.0004, 12.32, 0.0005, 13.40, 0.0003, 14.53, 0.0003, 15.65, 0.0007, 16.80, 0.0001, 17.95, 0.0002, 19.14, 0.0006, 20.34, 0.0002, 21.56, 0.0003], [0.99, 0.1821, 1.99, 0.0773, 3.00, 0.0125, 4.01, 0.0065, 5.01, 0.0202, 6.03, 0.0071, 7.05, 0.0090, 8.08, 0.0006, 9.13, 0.0008, 10.18, 0.0013, 11.25, 0.0010, 12.33, 0.0012, 13.42, 0.0006, 14.54, 0.0005, 15.65, 0.0004, 17.97, 0.0002, 19.15, 0.0001], [1.00, 0.1868, 2.00, 0.0951, 3.00, 0.0147, 4.01, 0.0134, 5.02, 0.0184, 6.04, 0.0132, 7.06, 0.0011, 8.11, 0.0008, 9.15, 0.0010, 10.22, 0.0012, 11.30, 0.0011, 12.40, 0.0003, 13.11, 0.0004, 13.49, 0.0002, 14.62, 0.0003, 15.77, 0.0001], [1.00, 0.1933, 2.00, 0.0714, 3.00, 0.0373, 4.00, 0.0108, 5.02, 0.0094, 6.02, 0.0010, 7.07, 0.0022, 8.11, 0.0002, 9.16, 0.0065, 10.23, 0.0015, 11.31, 0.0023, 12.40, 0.0003, 13.53, 0.0014, 14.66, 0.0002, 15.81, 0.0011, 18.20, 0.0002, 19.41, 0.0001], [0.99, 0.2113, 1.99, 0.0877, 3.00, 0.0492, 4.01, 0.0094, 5.02, 0.0144, 6.04, 0.0103, 7.07, 0.0117, 8.12, 0.0006, 9.19, 0.0019, 10.25, 0.0007, 11.35, 0.0017, 12.45, 0.0010, 13.58, 0.0003, 14.74, 0.0003, 15.91, 0.0003, 19.57, 0.0002], [0.99, 0.2455, 1.99, 0.0161, 3.00, 0.0215, 4.01, 0.0036, 5.03, 0.0049, 6.04, 0.0012, 7.09, 0.0036, 8.14, 0.0011, 9.21, 0.0009, 10.30, 0.0001, 11.40, 0.0012, 12.50, 0.0001, 13.66, 0.0005, 14.84, 0.0001], [1.00, 0.1132, 2.00, 0.0252, 3.00, 0.0292, 4.01, 0.0136, 5.03, 0.0045, 6.06, 0.0022, 7.11, 0.0101, 8.17, 0.0004, 9.23, 0.0010, 10.33, 0.0012, 11.44, 0.0013, 12.58, 0.0011, 13.75, 0.0002, 14.93, 0.0005, 16.14, 0.0002], [1.00, 0.1655, 2.00, 0.0445, 3.00, 0.0120, 4.00, 0.0038, 5.02, 0.0015, 6.07, 0.0038, 7.11, 0.0003, 8.19, 0.0002, 9.25, 0.0010, 10.36, 0.0011, 11.48, 0.0005, 12.63, 0.0002, 13.79, 0.0003, 16.24, 0.0002], [0.99, 0.3637, 1.99, 0.0259, 3.01, 0.0038, 4.01, 0.0057, 5.03, 0.0040, 6.07, 0.0067, 7.12, 0.0014, 8.19, 0.0004, 9.27, 0.0003, 10.38, 0.0002, 12.67, 0.0001], [1.00, 0.1193, 2.00, 0.0230, 3.00, 0.0104, 4.01, 0.0084, 5.04, 0.0047, 6.08, 0.0035, 7.13, 0.0041, 8.20, 0.0002, 9.29, 0.0005, 10.40, 0.0005, 11.53, 0.0003, 12.70, 0.0002, 13.91, 0.0002], [1.00, 0.0752, 2.00, 0.0497, 3.00, 0.0074, 4.02, 0.0076, 5.05, 0.0053, 6.09, 0.0043, 7.15, 0.0024, 8.22, 0.0001, 9.32, 0.0006, 10.45, 0.0002, 11.58, 0.0001, 12.78, 0.0001, 15.22, 0.0001], [1.00, 0.2388, 2.00, 0.0629, 3.01, 0.0159, 4.04, 0.0063, 5.07, 0.0051, 6.12, 0.0045, 7.19, 0.0026, 8.29, 0.0015, 9.43, 0.0001, 11.75, 0.0002], [1.00, 0.1919, 2.01, 0.0116, 3.01, 0.0031, 4.03, 0.0090, 5.07, 0.0061, 6.13, 0.0036, 7.19, 0.0013, 8.30, 0.0016, 9.13, 0.0001, 10.59, 0.0002, 11.78, 0.0002], [1.00, 0.1296, 2.00, 0.0135, 3.01, 0.0041, 4.04, 0.0045, 5.09, 0.0028, 6.14, 0.0046, 7.23, 0.0007, 8.32, 0.0007, 9.50, 0.0001], [1.00, 0.0692, 2.00, 0.0209, 3.02, 0.0025, 4.05, 0.0030, 5.09, 0.0047, 6.17, 0.0022, 7.25, 0.0015, 8.36, 0.0015, 9.53, 0.0010, 10.69, 0.0001, 13.40, 0.0001], [1.00, 0.1715, 2.00, 0.0142, 3.01, 0.0024, 4.03, 0.0015, 5.07, 0.0017, 6.13, 0.0018, 7.22, 0.0009, 8.33, 0.0014, 9.51, 0.0007, 10.69, 0.0002], [1.00, 0.1555, 2.01, 0.0148, 3.02, 0.0007, 4.06, 0.0006, 5.10, 0.0005, 6.16, 0.0008, 7.26, 0.0009, 8.39, 0.0008, 9.58, 0.0002], [1.00, 0.1357, 2.00, 0.0116, 3.02, 0.0026, 4.04, 0.0009, 5.09, 0.0004, 6.17, 0.0005, 7.27, 0.0002, 8.40, 0.0001], [1.00, 0.2185, 2.01, 0.0087, 3.03, 0.0018, 4.06, 0.0025, 5.11, 0.0020, 6.20, 0.0012, 7.32, 0.0005, 8.46, 0.0001, 9.66, 0.0003], [1.00, 0.2735, 2.00, 0.0038, 3.02, 0.0008, 4.06, 0.0012, 5.12, 0.0008, 6.22, 0.0011, 7.35, 0.0003, 8.50, 0.0002], [1.00, 0.1441, 1.99, 0.0062, 3.01, 0.0023, 4.05, 0.0011, 5.11, 0.0012, 6.20, 0.0003, 7.33, 0.0004, 8.50, 0.0001], [1.00, 0.0726, 2.01, 0.0293, 3.03, 0.0022, 5.14, 0.0005, 6.26, 0.0011, 7.41, 0.0002, 8.63, 0.0002], [1.00, 0.0516, 2.00, 0.0104, 3.02, 0.0029, 5.15, 0.0002, 6.27, 0.0001], [1.00, 0.0329, 2.00, 0.0033, 3.03, 0.0013, 4.10, 0.0005, 5.19, 0.0004, 6.32, 0.0002], [1.00, 0.0179, 1.99, 0.0012, 3.04, 0.0005, 4.10, 0.0017, 5.20, 0.0005, 6.35, 0.0001], [1.00, 0.0334, 2.01, 0.0033, 3.04, 0.0011, 4.13, 0.0003, 5.22, 0.0003], [0.99, 0.0161, 2.01, 0.0100, 3.04, 0.0020, 4.13, 0.0003], [1.00, 0.0475, 1.99, 0.0045, 3.03, 0.0035, 4.12, 0.0011], [1.00, 0.0593, 2.00, 0.0014, 4.17, 0.0002], [1.00, 0.0249, 2.01, 0.0016], [1.00, 0.0242, 2.00, 0.0038, 4.19, 0.0002], [1.00, 0.0170, 2.02, 0.0030], [1.00, 0.0381, 2.00, 0.0017, 3.09, 0.0002], [1.00, 0.0141, 2.03, 0.0005, 3.11, 0.0003, 4.26, 0.0001], [1.00, 0.0122, 2.03, 0.0024], [1.00, 0.0107, 2.07, 0.0007, 3.12, 0.0004], [1.00, 0.0250, 2.02, 0.0026, 3.15, 0.0002], [1.01, 0.0092], [1.01, 0.0102, 2.09, 0.0005], [1.00, 0.0080, 2.00, 0.0005, 3.19, 0.0001], [1.01, 0.0298, 2.01, 0.0005]] def lbj_piano(start, dur, freq, amp, *args) pfreq, degree, distance, reverb_amount = nil optkey(args, binding, [:pfreq, freq], [:degree, 45.0], [:distance, 1.0], [:reverb_amount, 0.0]) get_piano_partials = lambda do |frq| Piano_Spectra[(12 * (log(frq / 32.703) / log(2))).round] end make_piano_ampfun = lambda do |dr| release_amp = db2linear($clm_db_drop_per_second * dr) attack_time = $clm_piano_attack_duration * 100.0 / dr [0, 0, attack_time / 4, 1.0, attack_time, 1.0, 100, release_amp] end # This thing sounds pretty good down low, below middle c or so. # Unfortunately, there are some tens of partials down there and # we're using exponential envelopes. You're going to wait for a # long long time just to hear a single low note. The high notes # sound pretty rotten--they just don't sparkle; I have a feeling # that this is due to the low amplitude of the original data, and # the lack of mechanical noise. # # The only thing you can do to alter the sound of a piano note is to # set the pfreq parameter. Pfreq is used to look up the partials. # By default, it's set to the requested frequency. Setting it to a # neighboring freq is useful when you're repeating notes. Note that # there's no nyquist detection; a high freq with a low pfreq, will # give you fold over (hmmm...maybe I can get those high notes to # sparkle after all). partials = normalize_partials(get_piano_partials.call(pfreq)) newdur = dur + $clm_piano_attack_duration + $clm_piano_release_duration env1dur = newdur - $clm_piano_release_duration env1samples = (env1dur * @srate).floor siz = (partials.length / 2).floor oscils = Array.new(siz) alist = make_vct(siz) ampfun1 = make_piano_ampfun.call(env1dur) ampenv1 = make_env(:envelope, ampfun1, :scaler, amp, :duration, env1dur, :base, 10000.0) releaseamp = ampfun1.last ampenv2 = make_env(:envelope, [0, 1, 100, 0], :scaler, amp * releaseamp, :duration, env1dur, :base, 1.0) sktr = j = 0 0.step(partials.length - 1, 2) do |i| alist[j] = partials[i + 1] oscils[j] = make_oscil(:frequency, partials[i] * freq) j += 1 end run_instrument(start, newdur, :degree, degree, :distance, distance, :reverb_amount, reverb_amount) do sktr += 1 let(0.0) do |sum| oscils.each_with_index do |osc, i| sum = sum + oscil(osc) * alist[i] end sum * env(((sktr > env1samples) ? ampenv2 : ampenv1)) end end end def lbj_piano_test(start = 0.0, dur = 1.0) lbj_piano(start, dur, 440.0, 0.5) $now = start + dur + 0.24 + 0.2 end # RESFLT def resflt(start, dur, driver, ranfreq, noiamp, noifun, cosamp, cosfreq1, cosfreq0, cosnum, ampcosfun, freqcosfun, frq1, r1, g1, frq2, r2, g2, frq3, r3, g3, *args) degree, distance, reverb_amount = nil optkey(args, binding, [:degree, 0.0], [:distance, 1.0], [:reverb_amount, 0.005]) # driver=0 -- use sum of cosines to drive the filter, # driver=1 -- use white noise # if noise used, ranfreq=frequency of random number generator, # noiamp=amplitude thereof, # noifun=amplitude envelope on white noise # if sum-of-cosines (i.e. a band-limited pulse train), # cosamp=amplitude of pulse train, # cosfreq1=top frequency (given freqcosfun) # (i.e. pulse frequency) # cosfreq0=bottom frequency, # cosnum=number of cosines in the pulse, # ampcosfun=amplitude envelope on pulse train # freqcosfun=frequency envelope on pulse train # There are then 3 resonators, centered at frq1, frq2, frq3, # with pole-radius r1, r2, and r3 respectively, and # with gains of g1, g2, and g3. f1 = make_two_pole(frq1, r1) f2 = make_two_pole(frq2, r2) f3 = make_two_pole(frq3, r3) with_noise = (driver == 1) frqf = if with_noise nil else make_env(:envelope, freqcosfun, :duration, dur, :scaler, hz2radians(cosfreq1 - cosfreq0)) end ampf = if with_noise make_env(:envelope, noifun, :scaler, noiamp, :duration, dur) else make_env(:envelope, ampcosfun, :scaler, cosamp, :duration, dur) end rn = if with_noise make_rand(:frequency, ranfreq) else nil end cn = if with_noise nil else make_sum_of_cosines(:frequency, cosfreq0, :cosines, cosnum) end if with_noise run_instrument(start, dur, :distance, distance, :degree, degree, :reverb_amount, reverb_amount) do input1 = env(ampf) * rand(rn) two_pole(f1, input1 * g1) + two_pole(f2, input1 * g2) + two_pole(f3, input1 * g3) end else run_instrument(start, dur, :distance, distance, :degree, degree, :reverb_amount, reverb_amount) do input1 = env(ampf) * sum_of_cosines(cn, env(frqf)) two_pole(f1, input1 * g1) + two_pole(f2, input1 * g2) + two_pole(f3, input1 * g3) end end end def resflt_test(start = 0.0, dur = 1.0) $now = start resflt($now, dur, 0, 0, 0, nil, 0.1, 200, 230, 10, [0, 0, 50, 1, 100, 0], [0, 0, 100, 1], 500, 0.995, 0.1, 1000, 0.995, 0.1, 2000, 0.995, 0.1) $now += dur + 0.2 resflt($now, dur, 1, 10000, 0.01, [0, 0, 50, 1, 100, 0], 0, 0, 0, 0, nil, nil, 500, 0.995, 0.1, 1000, 0.995, 0.1, 2000, 0.995, 0.1) $now += dur + 0.2 end # SCRATCH def scratch(start, file, src_ratio, turntable) assert_type(File.exist?(file), file, 1, "an existing file") f = make_file2sample(file) turn_i = 1 turns = turntable.length cur_sample = seconds2samples(turntable[0]) turn_sample = seconds2samples(turntable[turn_i]) rd = make_src(:srate, src_ratio) forwards = (src_ratio > 0.0) set_mus_increment(rd, -src_ratio) if forwards and turn_sample < cur_sample turning = 0 last_val = last_val2 = 0.0 run_instrument(start, ws_duration(file)) do break if turn_i >= turns val = src(rd, 0.0, lambda do |dir| inval = file2sample(f, cur_sample) cur_sample += dir inval end) if turning.zero? # we past turn point going forwards if forwards and cur_sample >= turn_sample turning = 1 # we past turn point going backwards elsif (not forwards) and cur_sample <= turn_sample turning = -1 end else # wait for an inflection... if (last_val2 <= last_val and last_val >= val) or (last_val2 >= last_val and last_val <= val) turn_i += 1 if turn_i < turns turn_sample = seconds2samples(turntable[turn_i]) forwards = (not forwards) set_mus_increment(rd, -mus_increment(rd)) end turning = 0 end end last_val2, last_val = last_val, val val end mus_close(f) end def scratch_test(start = 0.0, dur = 1.0) scratch(start, "fyow.snd", [dur, 1.5].min, [0.0, 0.5, 0.25, 1.0]) $now = start + mus_sound_duration("fyow.snd") + 0.2 end # PINS # # spectral modeling (SMS) def pins(start, dur, file, amp, *args) assert_type(File.exist?(file), file, 2, "an existing file") transposition, time_scaler, fftsize, highest_bin, max_peaks, attack = nil optkey(args, binding, [:transposition, 1.0], # this can be used to transpose the sound [:time_scaler, 1.0], # this can make things happen faster # (< 1.0)/slower (> 1.0) in the output [:fftsize, 256], # should be a power of 2 # at 22050 srate, this is ok for # sounds above 300Hz or so, below that # you need 512 or 1024, at 44100, # probably best to double these sizes # -- it takes some searching # sometimes. [:highest_bin, 128], # how high in fft data should we search for pks [:max_peaks, 16], # how many spectral peaks to track at the max :attack) # whether to use original attack via time domain # splice do the sliding fft shuffle, # translate to polar coordinates, find # spectral peaks, match with current, # do some interesting transformation, # resynthesize using oscils All the # envelopes are created on the fly. # max-peaks is how many of these peaks # we are willing to track at any given # time. fil = make_file2sample(file) file_duration = ws_duration(file) fdr = make_vct(fftsize) fdi = make_vct(fftsize) window = make_fft_window(Blackman2_window, fftsize) fftamps = make_vct(fftsize) max_oscils = 2 * max_peaks current_peak_freqs = make_vct(max_oscils) last_peak_freqs = make_vct(max_oscils) current_peak_amps = make_vct(max_oscils) last_peak_amps = make_vct(max_oscils) peak_amps = make_vct(max_peaks) peak_freqs = make_vct(max_peaks) resynth_oscils = make_array(max_oscils) do make_oscil(:frequency, 0) end # run-time generated amplitude and frequency envelopes amps = make_vct(max_oscils) rates = make_vct(max_oscils) freqs = make_vct(max_oscils) sweeps = make_vct(max_oscils) lowest_magnitude = 0.001 hop = (fftsize / 4).floor outhop = (time_scaler * hop).floor ifreq = 1.0 / outhop ihifreq = hz2radians(ifreq) # integrate Blackman-Harris window = .42323*window fftscale = 1.0 / (fftsize * 0.42323) # width and shift by fftsize fft_mag = @srate / fftsize furthest_away_accepted = 0.1 filptr = 0 cur_oscils = max_oscils ramped = (attack or 0) splice_attack = attack.kind_of?(Numeric) attack_size = (attack or 1) ramp_ind = 0 ramped_attack = make_vct(attack_size) if (dur / time_scaler) > file_duration error("%s is %1.3f seconds long, \ but we'll need %1.3f seconds of data for this note", file, file_duration, dur / time_scaler) end trigger = outhop vct_scale!(window, fftscale) run_instrument(start, dur) do if splice_attack ramp = 1.0 / attack_size # my experience in translating SMS, and rumor via Greg Sandell # leads me to believe that there is in fact no way to model some # attacks successfully in this manner, so this block simply # splices the original attack on to the rest of the note. # "attack" is the number of samples to include bodily. out_val = amp * file2sample(fil, filptr) filptr += 1 if filptr > attack_size mult = 1.0 attack_size.times do |j| ramped_attack[j] = mult * file2sample(fil, filptr + j) mult -= ramp end splice_attack = false end # if out_val out_val else if trigger >= outhop peaks = 0 # get next block of data and apply window to it trigger = 0 fftsize.times do |j| fdr[j] = window[j] * file2sample(fil, filptr) filptr += 1 end vct_fill!(fdi, 0.0) filptr -= fftsize - hop # get the fft mus_fft(fdr, fdi, fftsize, 1) # change to polar coordinates (ignoring phases) highest_bin.times do |j| # no need to paw through the upper half # (so (<= highest-bin (floor fft-size 2))) x = fdr[j] y = fdi[j] fftamps[j] = 2.0 * sqrt(x * x + y * y) end max_oscils.times do |j| last_peak_freqs[j] = current_peak_freqs[j] last_peak_amps[j] = current_peak_amps[j] current_peak_amps[j] = 0.0 end vct_fill!(peak_amps, 0.0) ra = fftamps[0] la = ca = 0.0 # search for current peaks following Xavier Serra's recommendations in # "A System for Sound Analysis/Transformation/Synthesis # Based on a Deterministic Plus Stochastic Decomposition" highest_bin.times do |j| la, ca, ra = ca, ra, fftamps[j] if ca > lowest_magnitude and ca > ra and ca > la # found a local maximum above the current threshold # (its bin number is j-1) logla = log10(la) logca = log10(ca) logra = log10(ra) offset = (0.5 * (logla - logra)) / (logla + -2 * logca + logra) amp_1 = 10.0 ** (logca - (0.25 * (logla - logra) * offset)) freq = fft_mag * (j + offset - 1) if peaks == max_peaks # gotta either flush this peak, # or find current lowest and flush him minp = 0 minpeak = peak_amps[0] 1.upto(max_peaks - 1) do |k| if peak_amps[k] < minpeak minp = k minpeak = peak_amps[k] end end if amp_1 > minpeak peak_freqs[minp] = freq peak_amps[minp] = amp_1 end else peak_freqs[peaks] = freq peak_amps[peaks] = amp_1 peaks += 1 end end end # now we have the current peaks -- match them to the previous # set and do something interesting with the result the end # results are reflected in the updated values in the rates and # sweeps arrays. search for fits between last and current, # set rates/sweeps for those found try to go by largest amp # first peaks.times do |j| maxp = 0 maxpk = peak_amps[0] 1.upto(max_peaks - 1) do |k| if peak_amps[k] > maxpk maxp = k maxpk = peak_amps[k] end end # now maxp points to next largest unmatched peak if maxpk > 0.0 closestp = -1 closestamp = 10.0 current_freq = peak_freqs[maxp] icf = 1.0 / current_freq max_peaks.times do |k| if last_peak_amps[k] > 0.0 closeness = icf * (last_peak_freqs[k] - current_freq).abs if closeness < closestamp closestamp = closeness closestp = k end end end if closestamp < furthest_away_accepted # peak_amp is transferred to appropriate current_amp and zeroed, current_peak_amps[closestp] = peak_amps[maxp] peak_amps[maxp] = 0.0 current_peak_freqs[closestp] = current_freq end end end max_peaks.times do |j| if peak_amps[j] > 0.0 # find a place for a new oscil and start it up new_place = -1 max_oscils.times do |k| if last_peak_amps[k].zero? and current_peak_amps[k].zero? new_place = k break end end current_peak_amps[new_place] = peak_amps[j] peak_amps[j] = 0.0 current_peak_freqs[new_place] = peak_freqs[j] last_peak_freqs[new_place] = peak_freqs[j] set_mus_frequency(resynth_oscils[new_place], transposition * peak_freqs[j]) end end cur_oscils = 0 max_oscils.times do |j| rates[j] = ifreq * (current_peak_amps[j] - last_peak_amps[j]) if current_peak_amps[j].nonzero? or last_peak_amps[j].nonzero? cur_oscils = j end sweeps[j] = ihifreq * transposition * (current_peak_freqs[j] - last_peak_freqs[j]) end cur_oscils += 1 end # run oscils, update envelopes trigger += 1 if ramped.zero? sum = 0.0 else sum = ramped_attack[ramp_ind] ramp_ind += 1 ramped = 0 if ramp_ind == ramped end cur_oscils.times do |j| if amps[j].nonzero? or rates[j].nonzero? sum = sum + amps[j] * oscil(resynth_oscils[j], freqs[j]) amps[j] += rates[j] freqs[j] += sweeps[j] end end # else out_val amp * sum end end mus_close(fil) end def pins_test(start = 0.0, dur = 1.0) pins(start, dur, "fyow.snd", 1, :time_scaler, 2) $now = start + dur + 0.2 end # ZC def zc(start, dur, freq, amp, length1, length2, feedback) s = make_pulse_train(:frequency, freq) d0 = make_comb(:size, length1, :max_size, [length1, length2].max + 1, :scaler, feedback) zenv = make_env(:envelope, [0, 0, 1, 1], :scaler, length2 - length1, :duration, dur) run_instrument(start, dur) do comb(d0, amp * pulse_train(s), env(zenv)) end end def zc_test(start = 0.0, dur = 1.0) $now = start zc($now, dur, 100, 0.4, 20, 100, 0.95) $now += dur + 0.2 zc($now, dur, 100, 0.4, 100, 20, 0.95) $now += dur + 0.2 end # ZN # # notches are spaced at srate/len, feedforward sets depth thereof so # sweep of len from 20 to 100 sweeps the notches down from 1000 Hz to # ca 200 Hz so we hear our downward glissando beneath the pulses. def zn(start, dur, freq, amp, length1, length2, feedforward) s = make_pulse_train(:frequency, freq) d0 = make_notch(:size, length1, :max_size, [length1, length2].max + 1, :scaler, feedforward) zenv = make_env(:envelope, [0, 0, 1, 1], :scaler, length2 - length1, :duration, dur) run_instrument(start, dur) do notch(d0, amp * pulse_train(s), env(zenv)) end end def zn_test(start = 0.0, dur = 1.0) $now = start zn($now, dur, 100, 0.5, 20, 100, 0.95) $now += dur + 0.2 zn($now, dur, 100, 0.5, 100, 20, 0.95) $now += dur + 0.2 end # ZA def za(start, dur, freq, amp, length1, length2, feedback, feedforward) s = make_pulse_train(:frequency, freq) d0 = make_all_pass(:feedback, feedback, :feedforward, feedforward, :size, length1, :max_size, [length1, length2].max + 1) zenv = make_env(:envelope, [0, 0, 1, 1], :scaler, length2 - length1, :duration, dur) run_instrument(start, dur) do all_pass(d0, amp * pulse_train(s), env(zenv)) end end def za_test(start = 0.0, dur = 1.0) $now = start za($now, dur, 100, 0.3, 20, 100, 0.95, 0.95) $now += dur + 0.2 za($now, dur, 100, 0.3, 100, 20, 0.95, 0.95) $now += dur + 0.2 end # CLM-EXPSRC def clm_expsrc(start, dur, in_file, exp_ratio, src_ratio, amp, rev = false, start_in_file = 0) assert_type(File.exist?(in_file), in_file, 0, "an existing file") stf = (start_in_file * srate(in_file)).floor fda = make_readin(in_file, :channel, 0, :start, stf) exa = make_granulate(lambda do |dir| readin(fda) end, :expansion, exp_ratio) srca = make_src(lambda do |dir| granulate(exa) end, :srate, src_ratio) two_chans = (channels(in_file) == 2) and (channels(@ws_output) == 2) revit = @reverb and rev beg = seconds2samples(start) fin = seconds2samples(dur) + beg # to satisfy with_sound-option :info and :notehook with_sound_info(get_func_name, start, dur) if two_chans fdb = make_readin(in_file, :channel, 1, :srate, stf) exb = make_granulate(lambda do |dir| readin(fdb) end, :expansion, exp_ratio) srcb = make_src(lambda do |dir| granulate(exb) end, :srate, src_ratio) if revit rev_amp = rev * 0.5 (beg..fin).each do |i| vala = src(srca) * amp valb = src(srcb) * amp outa(i, vala, @ws_output) outb(i, valb, @ws_output) outa(i, (vala + valb) * rev_amp, @reverb) end else # !revit (beg..fin).each do |i| outa(i, src(srca) * amp, @ws_output) outb(i, src(srcb) * amp, @ws_output) end end # revit else # !two_chans if revit rev_amp = rev (beg..fin).each do |i| vala = src(srca) * amp outa(i, vala, @ws_output) outa(i, vala * rev_amp, @ws_reverb) end else # !revit (beg..fin).each do |i| outa(i, src(srca) * amp, @ws_output) end end # revit end # two_chans end def clm_expsrc_test(start = 0.0, dur = 1.0) clm_expsrc(start, dur, "oboe.snd", 2.0, 1.0, 1.0, 0.05) $now = start + dur + 0.2 end # EXP-SND # # granulate with envelopes on the expansion amount, segment envelope # shape, segment length, hop length, and input file resampling rate def exp_snd(file, start, dur, amp, exp_amt = 1.0, ramp = 0.4, seglen = 0.15, sr = 1.0, hop = 0.05, ampenv = nil) assert_type(File.exist?(file), file, 0, "an existing file") f0 = make_ws_reader(file, :start, 0) expenv = make_env(:envelope, (exp_amt.kind_of?(Array) ? exp_amt : [0, exp_amt, 1, exp_amt]), :duration, dur) lenenv = make_env(:envelope, (seglen.kind_of?(Array) ? seglen : [0, seglen, 1, seglen]), :duration, dur) max_seg_len, initial_seg_len = if seglen if seglen.kind_of?(Array) [max_envelope(seglen), seglen[1]] else [seglen, seglen] end else [0.15, 0.15] end scaler_amp = ((max_seg_len > 0.15) ? ((0.6 * 0.15) / max_seg_len) : 0.6) srenv = make_env(:envelope, (sr.kind_of?(Array) ? sr : [0, sr, 1, sr]), :duration, dur) rampdata = (ramp.kind_of?(Array) ? ramp : [0, ramp, 1, ramp]) rampenv = make_env(:envelope, rampdata, :duration, dur) initial_ramp_time = if ramp if ramp.kind_of?(Array) ramp[1] else ramp end else 0.4 end hopenv = make_env(:envelope, (hop.kind_of?(Array) ? hop : [0, hop, 1, hop]), :duration, dur) max_out_hop, initial_out_hop = if hop if hop.kind_of?(Array) [max_envelope(hop), hop[1]] else [hop, hop] end else [0.05, 0.05] end min_exp_amt, initial_exp_amt = if exp_amt if exp_amt.kind_of?(Array) [min_envelope(exp_amt), exp_amt[1]] else [exp_amt, exp_amt] end else [1.0, 1.0] end max_in_hop = max_out_hop / min_exp_amt.to_f max_len = (@srate * ([max_out_hop, max_in_hop].max + max_seg_len)).ceil ampe = make_env(:envelope, (ampenv or [0, 0, 0.5, 1, 1, 0]), :scaler, amp, :duration, dur) ex_a = make_granulate(:input, lambda do |dir| ws_readin(f0) end, :expansion, initial_exp_amt, :max_size, max_len, :ramp, initial_ramp_time, :hop, initial_out_hop, :length, initial_seg_len, :scaler, scaler_amp) ex_samp = next_samp = 0.0 vol = env(ampe) val_a0 = vol * granulate(ex_a) val_a1 = vol * granulate(ex_a) if min_envelope(rampdata) <= 0.0 or max_envelope(rampdata) >= 0.5 error("ramp argument to expand must always be between 0.0 and 0.5: %1.3f", ramp) else run_instrument(start, dur) do expa = env(expenv) # current expansion amount segl = env(lenenv) # current segment length resa = env(srenv) # current resampling increment rmpl = env(rampenv) # current ramp length (0 to 0.5) hp = env(hopenv) # current hop size # now we set the granulate generator internal state to reflect all # these envelopes sl = (segl * @srate).floor rl = (rmpl * sl).floor vol = env(ampe) set_mus_length(ex_a, sl) set_mus_ramp(ex_a, rl) set_mus_frequency(ex_a, hp) set_mus_increment(ex_a, expa) next_samp += resa if next_samp > (ex_samp + 1) (next_samp - ex_samp).floor.times do val_a0, val_a1 = val_a1, vol * granulate(ex_a) ex_samp += 1 end end if next_samp == ex_samp val_a0 else val_a0 + (next_samp - ex_samp) * (val_a1 - val_a0) end end close_ws_reader(f0) end end def exp_snd_test(start = 0.0, dur = 1.0) $now = start exp_snd("fyow.snd", $now, dur, 1, [0, 1, 1, 3], 0.4, 0.15, [0, 2, 1, 0.5], 0.05) $now += dur + 0.2 exp_snd("oboe.snd", $now, dur, 1, [0, 1, 1, 3], 0.4, 0.15, [0, 2, 1, 0.5], 0.2) $now += dur + 0.2 end # EXPFIL Grn = Struct.new("Grn", :rampval, :rampinc, :loc, :segctr, :whichseg, :ramplen, :steadylen, :trigger) def expfil(start, dur, hopsecs, rampsecs, steadysecs, file1, file2) assert_type(File.exist?(file1), file1, 5, "an existing file") assert_type(File.exist?(file2), file2, 6, "an existing file") fil1 = make_file2sample(file1) fil2 = make_file2sample(file2) hop = seconds2samples(hopsecs) ramplen = seconds2samples(rampsecs) steadylen = seconds2samples(steadysecs) grn1 = Grn.new(0.0, 1.0 / ramplen, 0, 0, 0, ramplen, steadylen, 0) grn2 = Grn.new(0.0, 1.0 / ramplen, 0, 0, 0, ramplen, steadylen, 0) beg = seconds2samples(start) out1 = beg out2 = hop + beg run_instrument(start, dur) do |i| val = 0.0 if i == out1 inval = ina(grn1.loc, fil1) grn1.loc += 1 if grn1.whichseg.zero? # ramp-up inval *= grn1.rampval grn1.rampval += grn1.rampinc grn1.segctr += 1 if grn1.segctr == grn1.ramplen grn1.segctr = 0 grn1.whichseg += 1 end else if grn1.whichseg == 1 # steady-state grn1.segctr += 1 if grn1.segctr == grn1.steadylen grn1.segctr = 0 grn1.whichseg += 1 end else # ramp-down inval *= grn1.rampval grn1.segctr += 1 grn1.rampval -= grn1.rampinc if grn1.segctr == grn1.ramplen grn1.segctr = 0 grn1.trigger = 1 grn1.whichseg = 0 grn1.rampval = 0.0 end end end val += inval out1 += 1 if grn1.trigger == 1 grn1.trigger = 0 out1 += hop end end if i == out2 inval = ina(grn2.loc, fil2) grn2.loc += 1 if grn2.whichseg.zero? # ramp-up inval *= grn2.rampval grn2.rampval += grn2.rampinc grn2.segctr += 1 if grn2.segctr == grn2.ramplen grn2.segctr = 0 grn2.whichseg += 1 end else if grn2.whichseg == 1 # steady-state grn2.segctr += 1 if grn2.segctr == grn2.steadylen grn2.segctr = 0 grn2.whichseg += 1 end else # ramp-down inval *= grn2.rampval grn2.segctr += 1 grn2.rampval -= grn2.rampinc if grn2.segctr == grn2.ramplen grn2.segctr = 0 grn2.trigger = 1 grn2.whichseg = 0 grn2.rampval = 0.0 end end end val += inval out2 += 1 if grn2.trigger == 1 grn2.trigger = 0 out2 += hop end end val end end def expfil_test(start = 0.0, dur = 1.0) expfil(start, dur, 0.2, 0.01, 0.1, "oboe.snd", "fyow.snd") $now = start + dur + 0.2 end # GRAPH-EQ # =begin From: Marco Trevisani This should work like a Graphic Equalizer.... Very easy to use. Just some note: "amp" & "amp-env" apply an enveloppe to the final result of the filtering. "dur" as ""standard"" in my instruments, when dur = 0 it will take the length of the sndfile input, otherwise the duration in seconds. "gain-freq-list" is a list of gains and frequencies to filter --in this order gain and frequencies--. There is no limit to the size of the list. Gain can be a number or an envelope. Unfortunatelly in this version they cant alternate, one should chose, all envelopes or all numbers i.e.: case 1 -> '( .1 440.0 .3 1500.0 .2 330.0 ...etc) or case 2 -> '((0 .1 1 .5) 440.0 (0 1 1 .01) 1500 (0 .3 1 .5) 330.0 ...etc) '( .1 440.0 (0 1 1 .01) 1500 ..etc) <<< again, this is not allowed .. "offset-gain" This apply to all the gains if case 1. It adds or subtracts an offset to all the gains in the list. This number can be positive or negative. In case the result is a negative number --let's say offset = -.4 and, like in case 1, the first gain is .1, the result would be -.3 -- the instrument will pass a gain equal to 0. "filt-gain-scale" & "filt-gain-base" will apply to the elements of the envelopes if we are in case 2, gains are envelopes. "stats" if #t --default-- prints the number of seconds processed, if nil doesnt print anything, which will speed up a bit the process. =end # def graph_eq(file, start, dur, *args) assert_type(File.exist?(file), file, 0, "an existing file") or_beg, amplitude, amp_env, amp_base, offset_gain = nil gain_freq_list, filt_gain_scale, filt_gain_base, a1 = nil optkey(args, binding, [:or_beg, 0], [:amplitude, 1], [:amp_env, [0, 1, 0.8, 1, 1, 0]], [:amp_base, 1], [:offset_gain, 0], [:gain_freq_list, [[0, 1, 1, 0], 440, [0, 0, 1, 1], 660]], [:filt_gain_scale, 1], [:filt_gain_base, 1], [:a1, 0.99]) durata = (dur.zero? ? ws_duration(file) : dur) len = seconds2samples(durata) or_start = (or_beg * ws_srate(file)).round rd_a = make_ws_reader(file, :start, or_start) half_list = gain_freq_list.length / 2 ampenv = make_env(:envelope, amp_env, :scaler, amplitude, :duration, durata, :base, amp_base) gain_list = [] 0.step(gain_freq_list.length - 1, 2) do |i| gain_list << gain_freq_list[i] end freq_list = [] 1.step(gain_freq_list.length - 1, 2) do |i| freq_list << gain_freq_list[i] end if_list_in_gain = gain_list[0].kind_of?(Array) env_size = (if_list_in_gain ? Array.new(freq_list.length) : nil) frm_size = Array.new(freq_list.length) gains = Vct.new(len, 1.0) half_list.times do |i| gval = gain_list[i] fval = freq_list[i] if gval.kind_of?(Array) env_size[i] = make_env(:envelope, gval, :scaler, filt_gain_scale, :duration, durata, :base, filt_gain_base) frm_size[i] = make_formant(fval, a1) else gains[i] = (offset_gain + gval < 0) ? 0 : (offset_gain + gain) frm_size[i] = make_formant(fval, a1) end end run_instrument(start, durata) do outval = 0.0 inval = ws_readin(rd_a) half_list.times do |j| if if_list_in_gain gains[j] = env(env_size[j]) * (1.0 - a1) end outval = outval + gains[j] * formant(frm_size[j], inval) end env(ampenv) * outval end close_ws_reader(rd_a) end def graph_eq_test(start = 0.0, dur = 1.0) graph_eq("oboe.snd", start, dur, :amplitude, 50.0) $now = start + dur + 0.2 end # ANOI # # a kind of noise reduction -- on-going average spectrum is squelched # to some extent obviously aimed at intermittent signal in background # noise # this is based on Perry Cook's Scrubber.m def anoi(infile, start, dur, fftsize = 128, amp_scaler = 1.0, r = TWO_PI) assert_type(File.exist?(infile), infile, 0, "an existing file") freq_inc = (fftsize / 2).floor fdi = make_vct(fftsize) fdr = make_vct(fftsize) spectr = make_vct(freq_inc, 1.0) scales = make_vct(freq_inc, 1.0) diffs = make_vct(freq_inc) win = make_fft_window(Blackman2_window, fftsize) k = 0 amp = 0.0 incr = amp_scaler * 4.0 / @srate file = make_file2sample(infile) radius = 1.0 - r / fftsize.to_f bin = @srate / fftsize fs = make_array(freq_inc) do |i| make_formant(i * bin, radius) end samp = 0 run_instrument(start, dur) do inval = file2sample(file, samp) samp += 1 fdr[k] = inval k += 1 amp += incr if amp < amp_scaler if k >= fftsize k = 0 spectrum(fdr, fdi, win, 1) freq_inc.times do |j| spectr[j] = 0.9 * spectr[j] + 0.1 * fdr[j] if spectr[j] >= fdr[j] diffs[j] = scales[j] / -fftsize else diffs[j] = ((fdr[j] - spectr[j]) / fdr[j] - scales[j]) / fftsize end end end outval = 0.0 1.upto(freq_inc - 1) do |j| cur_scale = scales[j] outval = outval + cur_scale * formant(fs[j], inval) scales[j] += diffs[j] end amp * outval end end def anoi_test(start = 0.0, dur = 1.0) anoi("fyow.snd", start, dur, 128, 2.0) $now = start + dur + 0.2 end =begin Date: Fri, 25 Sep 1998 09:56:41 +0300 From: Matti Koskinen To: linux-audio-dev@ginette.musique.umontreal.ca Subject: [linux-audio-dev] Announce: alpha version of denoising [...] I wrote a simple denoiser called anoi after it's parent clm-instrument anoi.ins. anoi tries to remove white noise like tape hiss from wav- files. Removing of noise succeeds ok, but depending of the original sound, some distortion can be audible. If someone is interested, http://www.sci.fi/~mjkoskin contains tarred and gzipped file. Now only monophonic wav-files can be denoised, but adding others isn't too difficult. -matti mjkoskin@sci.fi =end # FULLMIX # # ;; "matrix" can be a simple amplitude or a list of lists each inner # ;; list represents one input channel's amps into one output channel # ;; each element of the list can be a number, a list (turned into an # ;; env) or an env # ;; # ;; "srate" can be a negative number (read in reverse), or an envelope. def fullmix(in_file, start = 0.0, outdur = false, inbeg = 0.0, matrix = false, srate = false, reverb_amount = false) unless File.exist?(in_file) Snd.raise(:no_such_file, in_file, "no such file") end unless start start = 0.0 end unless inbeg inbeg = 0.0 end if number?(outdur) dur = outdur else sr = number?(srate) ? srate.abs : 1.0 dur = (mus_sound_duration(in_file) - inbeg) / sr end in_chans = channels(in_file) reversed = ((number?(srate) and srate.negative?) or (array?(srate) and srate.cadr.negative?)) inloc = (Float(inbeg) * mus_sound_srate(in_file)).round ochans = [in_chans, @channels].max if @ws_reverb and number?(reverb_amount) and reverb_amount.positive? rev_mx = Vct.new(in_chans * in_chans, reverb_amount) else rev_mx = false end dir = (reversed ? -1 : 1) if (not srate) or (number?(srate) and srate == 1.0) file = make_file2frample(in_file) else file = make_array(in_chans) do |i| make_readin(in_file, i, inloc, :direction, dir) end end envs = false if array?(srate) srcenv = make_env(srate, :duration, dur, :scaler, Float(dir)) else srcenv = false end case matrix when Array mx = Vct.new(ochans * ochans, 0.0) matrix.each_with_index do |inlist, inp| break if inp >= in_chans inlist.each_with_index do |outn, outp| break if outp >= @channels case outn when Numeric # mx[inp][outp] = outn mx[inp * ochans + outp] = outn when Array, Mus unless envs envs = Array.new(in_chans * @channels, false) end if env?(outn) envs[inp * @channels + outp] = outn else envs[inp * @channels + outp] = make_env(outn, :duration, dur) end else Snd.warning("unknown element in matrix: %p", outn) end end end when Numeric # ; matrix is a number in this case (a global scaler) mx = Vct.new(ochans * ochans, matrix) else mx = Vct.new(ochans * ochans, 1.0) end # to satisfy with_sound-option :info and :notehook with_sound_info(get_func_name, start, dur) beg = seconds2samples(start) samps = seconds2samples(dur) if (not array?(file)) mxe = envs if envs mxe = Array.new(in_chans) do |i| Array.new(@channels) do |j| envs[i * @channels + j] end end end if sound?(@ws_output) output = file_name(@ws_output) if sound?(@ws_reverb) revout = file_name(@ws_reverb) end else output = @ws_output revout = @ws_reverb end mus_file_mix(output, file, beg, samps, inloc, mx, mxe) if rev_mx mus_file_mix(revout, file, beg, samps, inloc, rev_mx) end else if sound?(@ws_output) Snd.raise(:wrong_type_arg, "don't use :to_snd true") end sr = (number?(srate) ? srate.abs : 0.0) srcs = Array.new(in_chans) do |i| make_src(:input, file[i], :srate, sr) end mus_file_mix_with_envs(file, beg, samps, mx, rev_mx, envs, srcs, srcenv, @ws_output, @ws_reverb) end end def fullmix_test(start = 0.0, dur = 1.0) $now = start fullmix("pistol.snd", $now, dur) $now += dur + 0.2 fullmix("oboe.snd", $now, dur, 0, [[0.1, make_env([0, 0, 1, 1], :duration, dur, :scaler, 0.5)]]) $now += dur + 0.2 end # Original header: # ;;; grani: a granular synthesis instrument # ;;; by Fernando Lopez-Lezcano # ;;; http://ccrma.stanford.edu/~nando/clm/grani/ # ;;; # ;;; Original grani.ins instrument written for the 220a Course by # ;;; Fernando Lopez-Lezcano & Juan Pampin, November 6 1996 # ;;; # ;;; Mar 21 1997: working with hop and grain-dur envelopes # ;;; Mar 22 1997: working with src envelope (grain wise) & src spread # ;;; Jan 26 1998: started work on new version # ;;; Nov 7 1998: input soundfile duration calculation wrong # ;;; Nov 10 1998: bug in in-samples (thanks to Kristopher D. Giesing for this one) # ;;; Dec 20 1998: added standard locsig code # ;;; Feb 19 1999: added "nil" as default value of where to avoid warning (by bill) # ;;; Jan 10 2000: added input-channel to select which channel of the input file # ;;; to process. # ;;; added grain-start-in-seconds to be able to specify input file # ;;; locations in seconds for the grain-start envelope # ;;; May 06 2002: fixed array passing of where-bins in clisp (reported by Charles # ;;; Nichols and jennifer l doering # ;;; Mar 27 2003: added option for sending grains to all channels (requested by # ;;; Oded Ben-Tal) # ;;; calculate a random spread around a center of 0 def random_spread(spread) spread.nonzero? ? (random(spread) - spread / 2.0) : 0.0 end # ;;; create a constant envelope if argument is a number def envelope_or_number(val) assert_type((number?(val) or array?(val) or vct?(val)), val, 0, "a number, an array or a vct") case val when Numeric [0, Float(val), 1, Float(val)] when Vct val.to_a when Array val end end # ;;; create a vct from an envelope def make_gr_env(env, length = 512) length_1 = (length - 1).to_f make_vct!(length) do |i| envelope_interp(i / length_1, env) end end # ;;; Grain envelopes def raised_cosine(*args) duty_cycle, length = nil optkey(args, binding, [:duty_cycle, 100], [:length, 128]) active = length * duty_cycle.to_f * 0.01 incr = PI / (active - 1.0) start = (length - active) / 2.0 fin = (length + active) / 2.0 s = -1 make_vct!(length) do |i| sine = if i >= start and i < fin s += 1 sin(s * incr) else 0.0 end sine * sine end end # ;;;============================================================================= # ;;; Granular synthesis instrument # ;;;============================================================================= # # ;;; input-channel: # ;;; from which channel in the input file are samples read # ;;; amp-envelope: # ;;; amplitude envelope for the note # ;;; grain-envelope: # ;;; grain-envelope-end: # ;;; envelopes for each individual grain. The envelope applied in the result # ;;; of interpolating both envelopes. The interpolation is controlled by # ;;; grain-envelope-trasition. If "grain-envelope-end" is nil interpolation # ;;; is turned off and only grain-envelope is applied to the grains. # ;;; grain-envelope-trasition: # ;;; an enveloper that controls the interpolation between the two grain envelopes # ;;; 0 -> selects "grain-envelope" # ;;; 1 -> selects "grain-envelope-end" # ;;; grain-envelope-array-size # ;;; size of the array passed to make-table-lookup # ;;; grain-duration: # ;;; envelope that controls grain duration in seconds # ;;; srate-linear: # ;;; t -> sample rate envelope is linear # ;;; nil -> sample rate envelope is exponential # ;;; srate: # ;;; envelope that controls sample rate conversion. The envelope is an # ;;; exponential envelope, the base and error bound of the conversion # ;;; are controlled by "srate-base" and "srate-error". # ;;; srate-spread: # ;;; random spread of sample rate conversion around "srate" # ;;; srate-base: # ;;; base for the exponential conversion # ;;; for example: base = (expt 2 (/ 12)) creates a semitone envelope # ;;; srate-error: # ;;; error bound for the exponential conversion. # ;;; grain-start: # ;;; envelope that determines the starting point of the current grain in # ;;; the input file. "y"->0 starts the grain at the beginning of the input # ;;; file. "y"->1 starts the grain at the end of the input file. # ;;; grain-start-spread: # ;;; random spread around the value of "grain-start" # ;;; grain-start-in-seconds: # ;;; nil -> grain-start y envelope expressed in percent of the duration of the input file # ;;; t -> grain-start y envelope expressed in seconds # ;;; grain-density: # ;;; envelope that controls the number of grains per second generated in the output file # ;;; grain-density-spread: Grani_to_locsig = 0 Grani_to_grain_duration = 1 Grani_to_grain_start = 2 Grani_to_grain_sample_rate = 3 Grani_to_grain_random = 4 Grani_to_grain_allchans = 5 def grani(start, dur, amp, file, *args) assert_type(File.exist?(file), file, 3, "an existing file") input_channel = nil grains, amp_envelope, grain_envelope, grain_envelope_end = nil grain_envelope_transition, grain_envelope_array_size, grain_duration = nil grain_duration_spread, grain_duration_limit, srate, srate_spread = nil srate_linear, srate_base, srate_error, grain_start, grain_start_spread = nil grain_start_in_seconds, grain_density, grain_density_spread = nil reverb_amount, reverse, where_to, where_bins, grain_distance = nil grain_distance_spread, grain_degree, grain_degree_spread = nil optkey(args, binding, [:input_channel, 0], [:grains, 0], [:amp_envelope, [0, 0, 0.3, 1, 0.7, 1, 1, 0]], [:grain_envelope, [0, 0, 0.3, 1, 0.7, 1, 1, 0]], [:grain_envelope_end, false], [:grain_envelope_transition, [0, 0, 1, 1]], [:grain_envelope_array_size, 512], [:grain_duration, 0.1], [:grain_duration_spread, 0.0], [:grain_duration_limit, 0.002], [:srate, 0.0], [:srate_spread, 0.0], [:srate_linear, false], [:srate_base, 2.0 ** (1.0 / 12)], [:srate_error, 0.01], [:grain_start, [0, 0, 1, 1]], [:grain_start_spread, 0.0], [:grain_start_in_seconds, false], [:grain_density, 10.0], [:grain_density_spread, 0.0], [:reverb_amount, 0.01], [:reverse, false], [:where_to, 0], [:where_bins, []], [:grain_distance, 1.0], [:grain_distance_spread, 0.0], [:grain_degree, 45.0], [:grain_degree_spread, 0.0]) beg, fin = times2samples(start, dur) in_file_channels = ws_channels(file) in_file_sr = ws_srate(file) in_file_dur = ws_duration(file) rd = make_ws_reader(file, :channel, [input_channel, in_file_channels - 1].min, :vct?, true) in_file_reader = make_src(:input, lambda do |dir| ws_readin(rd) end, :srate, 1.0) set_mus_increment(in_file_reader, -1) if reverse last_in_sample = (in_file_dur * in_file_sr).round srate_ratio = in_file_sr / mus_srate() sr_env = make_env(:envelope, if srate_linear envelope_or_number(srate) else exp_envelope(envelope_or_number(srate), :base, srate_base, :error, srate_error) end, :scaler, srate_ratio, :duration, dur) sr_spread_env = make_env(:envelope, envelope_or_number(srate_spread), :duration, dur) amp_env = make_env(:envelope, amp_envelope, :scaler, amp, :duration, dur) gr_dur = make_env(:envelope, envelope_or_number(grain_duration), :duration, dur) gr_dur_spread = make_env(:envelope, envelope_or_number(grain_duration_spread), :duration, dur) gr_start_scaler = (grain_start_in_seconds ? 1.0 : in_file_dur) gr_start = make_env(:envelope, envelope_or_number(grain_start), :duration, dur) gr_start_spread = make_env(:envelope, envelope_or_number(grain_start_spread), :duration, dur) gr_dens_env = make_env(:envelope, envelope_or_number(grain_density), :duration, dur) gr_dens_spread_env = make_env(:envelope, envelope_or_number(grain_density_spread), :duration, dur) if vct?(grain_envelope) ge = grain_envelope else ge = make_gr_env(grain_envelope, grain_envelope_array_size) end gr_env = make_table_lookup(:frequency, 1.0, :initial_phase, 0, :wave, ge) if grain_envelope_end if vct?(grain_envelope_end) ge = grain_envelope_end else ge = make_gr_env(grain_envelope_end, grain_envelope_array_size) end else ge = make_vct(512) end gr_env_end = make_table_lookup(:frequency, 1.0, :initial_phase, 0, :wave, ge) gr_int_env = make_env(:envelope, envelope_or_number(grain_envelope_transition), :duration, dur) gr_dist = make_env(:envelope, envelope_or_number(grain_distance), :duration, dur) gr_dist_spread = make_env(:envelope, envelope_or_number(grain_distance_spread), :duration, dur) gr_degree = make_env(:envelope, envelope_or_number(grain_degree), :duration, dur) gr_degree_spread = make_env(:envelope, envelope_or_number(grain_degree_spread), :duration, dur) gr_start_sample = beg gr_samples = 0 gr_offset = 1 gr_dens = 0.0 gr_dens_spread = 0.0 grain_counter = 0 samples = 0 first_grain = true case grain_duration when Numeric dur += grain_duration when Array dur += grain_duration.last end run_instrument(start, dur, :degree, 45.0) do if gr_offset < gr_samples gr_offset += 1 (if grain_envelope_end gr_where = env(gr_int_env) (1 - gr_where) * table_lookup(gr_env) + gr_where * table_lookup(gr_env_end) else table_lookup(gr_env) end) * env(amp_env) * src(in_file_reader) else if first_grain first_grain = false gr_start_sample = beg else gr_start_sample += seconds2samples(1.0 / (gr_dens + gr_dens_spread)) if (gr_start_sample > fin) or (grains.nonzero? and (grain_counter >= grains)) break end end gr_offset = 0 gr_from_beg = gr_start_sample - beg set_mus_location(amp_env, gr_from_beg) set_mus_location(gr_dur, gr_from_beg) set_mus_location(gr_dur_spread, gr_from_beg) set_mus_location(sr_env, gr_from_beg) set_mus_location(sr_spread_env, gr_from_beg) set_mus_location(gr_start, gr_from_beg) set_mus_location(gr_start_spread, gr_from_beg) set_mus_location(gr_dens_env, gr_from_beg) set_mus_location(gr_dens_spread_env, gr_from_beg) in_start_value = env(gr_start) * gr_start_scaler + random_spread(env(gr_start_spread) * gr_start_scaler) in_start = (in_start_value * in_file_sr).round gr_duration = [grain_duration_limit, env(gr_dur) + random_spread(env(gr_dur_spread))].max gr_samples = seconds2samples(gr_duration) gr_srate = if srate_linear env(sr_env) + random_spread(env(sr_spread_env)) else env(sr_env) * srate_base ** random_spread(env(sr_spread_env)) end set_mus_increment(in_file_reader, gr_srate) in_samples = (gr_samples / (1.0 / srate_ratio)).round set_mus_phase(gr_env, 0.0) set_mus_phase(gr_env_end, 0.0) set_mus_frequency(gr_env, 1.0 / gr_duration) set_mus_frequency(gr_env_end, 1.0 / gr_duration) gr_dens = env(gr_dens_env) gr_dens_spread = random_spread(env(gr_dens_spread_env)) samples += gr_samples grain_counter += 1 where = case where_to when Grani_to_grain_duration gr_duration when Grani_to_grain_start in_start_value when Grani_to_grain_sample_rate gr_srate when Grani_to_grain_random random(1.0) else Grani_to_locsig end if where.nonzero? and where_bins.length > 0 (where_bins.length - 1).times do |chn| locsig_set!(@locsig, chn, (where.between?(where_bins[chn], where_bins[chn + 1]) ? 1.0 : 0.0)) end else if where_to == Grani_to_grain_allchans @channels.times do |chn| locsig_set!(@locsig, chn, 1.0) end else set_mus_location(gr_dist, gr_from_beg) set_mus_location(gr_dist_spread, gr_from_beg) set_mus_location(gr_degree, gr_from_beg) set_mus_location(gr_degree_spread, gr_from_beg) deg = env(gr_degree) + random_spread(env(gr_degree_spread)) dist = env(gr_dist) + random_spread(env(gr_dist_spread)) dist_scl = 1.0 / [dist, 1.0].max if sample2file?(@ws_reverb) locsig_reverb_set!(@locsig, 0, reverb_amount * (1.0 / sqrt([dist, 1.0].max))) end if @channels == 1 locsig_set!(@locsig, 0, dist_scl) else if @channels == 2 frac = [90.0, [0.0, deg].max].min / 90.0 locsig_set!(@locsig, 0, dist_scl * (1.0 - frac)) locsig_set!(@locsig, 1, dist_scl * frac) else if @channels > 2 locsig_set!(@locsig, 0, if deg.between?(0, 90) dist_scl * ((90.0 - deg) / 90.0) else if deg.between?(270, 360) dist_scl * ((deg - 270.0) / 90.0) else 0.0 end end) locsig_set!(@locsig, 1, if deg.between?(90, 180) dist_scl * (180.0 - deg) / 90.0 else if deg.between?(0, 90) dist_scl * (deg / 90.0) else 0.0 end end) locsig_set!(@locsig, 2, if deg.between?(180, 270) dist_scl * (270.0 - deg) / 90.0 else if deg.between?(90, 180) dist_scl * (deg - 90.0) / 90.0 else 0.0 end end) if @channels > 3 locsig_set!(@locsig, 3, if deg.between?(270, 360) dist_scl * (360.0 - deg) / 90.0 else if deg.between?(180, 270) dist_scl * (deg - 180.0) / 90.0 else 0.0 end end) end end end end end end in_start = if (in_start + in_samples) > last_in_sample last_in_sample - in_samples else [in_start, 0].max end set_ws_location(rd, in_start) 0.0 end end close_ws_reader(rd) end def grani_test(start = 0.0, dur = 1.0) grani(start, dur, 5.0, "oboe.snd", :grain_envelope, raised_cosine()) $now = start + dur + 0.2 end # BES-FM def bes_fm(start, dur, freq, amp, ratio, index) car_ph = mod_ph = 0.0 car_incr = hz2radians(freq) mod_incr = ratio.to_f * car_incr ampenv = make_env(:envelope, [0, 0, 25, 1, 75, 1, 100, 0], :scaler, amp, :duration, dur) run_instrument(start, dur) do out_val = env(ampenv) * bes_j1(car_ph) car_ph = car_ph + car_incr + index.to_f * bes_j1(mod_ph) mod_ph += mod_incr out_val end end def bes_fm_test(start = 0.0, dur = 1.0) bes_fm(start, dur, 440, 10, 1, 4) $now = start + dur + 0.2 end # SSB_FM class Ssb_fm < Musgen def initialize(freq) super() @frequency = freq @osc1 = make_oscil(freq, 0) @osc2 = make_oscil(freq, HALF_PI) @osc3 = make_oscil(0, 0) @osc4 = make_oscil(0, HALF_PI) @hilbert = make_hilbert_transform(40) @delay = make_delay(40) end def inspect format("%s.new(%s)", self.class, @frequency) end def to_s format("#<%s freq: %s>", self.class, @frequency) end def run_func(val1 = 0.0, val2 = 0.0) ssb_fm(val1) end def ssb_fm(modsig) am0 = oscil(@osc1) am1 = oscil(@osc2) car0 = oscil(@osc3, hilbert_transform(@hilbert, modsig)) car1 = oscil(@osc4, delay(@delay, modsig)) am0 * car0 + am1 * car1 end end def make_ssb_fm(freq = 440.0) Ssb_fm.new(freq) end def ssb_fm?(obj) obj.kind_of?(Ssb_fm) end def ssb_fm(gen, modsig = 0.0) gen.ssb_fm(modsig) end # FM2 class Fm2 < Musgen def initialize(f1, f2, f3, f4, p1, p2, p3, p4) super() @osc1 = make_oscil(f1, p1) @osc2 = make_oscil(f2, p2) @osc3 = make_oscil(f3, p3) @osc4 = make_oscil(f4, p4) end def inspect format("%s.new(%s, %s, %s, %s, %s, %s, %s, %s)", self.class, @f1, @f2, @f3, @f4, @p1, @p2, @p3, @p4) end def to_s format("#<%s %1.3f, %1.3f, %1.3f, %1.3f, %1.3f, %1.3f, %1.3f, %1.3f>", self.class, @f1, @f2, @f3, @f4, @p1, @p2, @p3, @p4) end def run_func(val1 = 0.0, val2 = 0.0) fm2(val1) end def fm2(index) (oscil(@osc1, index * oscil(@osc2)) + oscil(@osc3, index * oscil(@osc4))) * 0.25 end end # make_fm2(1000, 100, 1000, 100, 0, 0, HALF_PI, HALF_PI) # make_fm2(1000, 100, 1000, 100, 0, 0, 0, HALF_PI) def make_fm2(f1, f2, f3, f4, p1, p2, p3, p4) Fm2.new(f1, f2, f3, f4, p1, p2, p3, p4) end def fm2?(obj) obj.kind_of?(Fm2) end def fm2(gen, index = 0.0) gen.fm2(index) end def clm_ins_test(start = 0.0, dur = 1.0) $now = start violin_test($now, dur) fm_violin_test($now, dur) pluck_test($now, dur) vox_test($now, dur) fofins_test($now, dur) fm_trumpet_test($now, dur) pqw_vox_test($now, dur) flute_test($now, dur) fm_bell_test($now, dur) fm_insect_test($now, dur) fm_drum_test($now, dur) gong_test($now, dur) attract_test($now, dur) pqw_test($now, dur) tubebell_test($now, dur) wurley_test($now, dur) rhodey_test($now, dur) hammondoid_test($now, dur) metal_test($now, dur) drone_canter_test($now, dur) reson_test($now, dur) cellon_test($now, dur) gran_synth_test($now, dur) touch_tone_test($now, dur) spectra_test($now, dur) two_tab_test($now, dur) lbj_piano_test($now, dur) resflt_test($now, dur) scratch_test($now, dur) pins_test($now, dur) zc_test($now, dur) zn_test($now, dur) za_test($now, dur) clm_expsrc_test($now, dur) exp_snd_test($now, dur) expfil_test($now, dur) graph_eq_test($now, dur) anoi_test($now, dur) fullmix_test($now, dur) grani_test($now, dur) bes_fm_test($now, dur) end # clm-ins.rb ends here