|
- # Translator: Michael Scholz <mi-scholz@users.sourceforge.net>
- # Created: 02/11/20 02:24:34
- # Changed: 14/11/23 03:36:55
-
- # fm_violin(start, dur, freq, amp, *args)
- # play_fm_violin(start, dur, freq, amp, *args)
- # make_fm_violin(start, dur, freq, amp, *args)
- # jc_reverb(*args)
-
- require "ws"
-
- v_opts_str = "fm_violin(start=0.0, dur=1.0, freq=440.0, amp=0.5, *args)
- :fm_index = 1.0
- :amp_env = [0, 0, 25, 1, 75, 1, 100, 0]
- :periodic_vibrato_rate = 5.0
- :random_vibrato_rate = 16.0
- :periodic_vibrato_amp = 0.0025
- :random_vibrato_amp = 0.005
- :noise_amount = 0.0
- :noise_freq = 1000.0
- :ind_noise_freq = 10.0
- :ind_noise_amount = 0.0
- :amp_noise_freq = 20.0
- :amp_noise_amount = 0.0
- :gliss_env = [0, 0, 100, 0]
- :gliss_amount = 0.0
- :fm1_env = [0, 1, 25, 0.4, 75, 0.6, 100, 0]
- :fm2_env = [0, 1, 25, 0.4, 75, 0.6, 100, 0]
- :fm3_env = [0, 1, 25, 0.4, 75, 0.6, 100, 0]
- :fm1_rat = 1.0
- :fm2_rat = 3.0
- :fm3_rat = 4.0
- :fm1_index = false
- :fm2_index = false
- :fm3_index = false
- :base = 1.0
- :index_type = :violin"
-
- add_help(:fm_violin,
- "#{v_opts_str}
- :reverb_amount = 0.01
- :degree = kernel_rand(90.0)
- :distance = 1.0
- Ruby: fm_violin(0, 1, 440, 0.1, :fm_index, 2.0)
- Scheme: (fm-violin 0 1 440 0.1 :fm-index 2.0)
- Example: with_sound do fm_violin(0, 1, 440, 0.1, :fm_index, 2.0) end")
- def fm_violin(start = 0.0, dur = 1.0, freq = 440.0, amp = 0.5, *args)
- r = get_args(args, :reverb_amount, 0.01)
- d = get_args(args, :degree, kernel_rand(90.0))
- s = get_args(args, :distance, 1.0)
- fm_vln = make_fm_violin_gen(start, dur, freq, amp, *args)
- run_instrument(start, dur, :reverb_amount, r, :degree, d, :distance, s) do
- fm_vln.call(0)
- end
- end
-
- add_help(:play_fm_violin,
- "play_#{v_opts_str}
- Returns a fm_violin proc with no arg for play(proc).
- v = play_fm_violin(0, 1, 440, 0.5)
- play(v)
- or
- play(play_fm_violin(0, 1, 440, 0.5))")
- def play_fm_violin(start = 0.0, dur = 1.0, freq = 440.0, amp = 0.5, *args)
- fm_vln = make_fm_violin_gen(start, dur, freq, amp, *args)
- len = seconds2samples(dur)
- lambda do
- (len -= 1).positive? and fm_vln.call(0)
- end
- end
-
- #
- # make_fm_violin: returns lambda do |y| ... end
- #
- add_help(:make_fm_violin,
- "make_#{v_opts_str}
- Returns a proc with one arg for map_channel()
- *args are like fm_violin's
- ins = new_sound(:file, \"fmv.snd\", :srate, 22050, :channels, 2)
- # proc with one arg
- fmv1 = make_fm_violin(0, 1, 440, 0.5)
- map_channel(fmv1, 0, 22050, ins, 1)")
- def make_fm_violin(start = 0.0, dur = 1.0, freq = 440.0, amp = 1.0, *args)
- make_fm_violin_gen(start, dur, freq, amp, *args)
- end
-
- def make_fm_violin_gen(start, dur, freq, amp, *args)
- fm_index, amp_env, periodic_vibrato_rate, random_vibrato_rate = nil
- periodic_vibrato_amp, random_vibrato_amp, noise_amount, noise_freq = nil
- ind_noise_freq, ind_noise_amount, amp_noise_freq, amp_noise_amount = nil
- gliss_env, gliss_amount = nil
- fm1_env, fm2_env, fm3_env, fm1_rat, fm2_rat, fm3_rat = nil
- fm1_index, fm2_index, fm3_index, base, index_type = nil
- optkey(args, binding,
- [:fm_index, 1.0],
- [:amp_env, [0, 0, 25, 1, 75, 1, 100, 0]],
- [:periodic_vibrato_rate, 5.0],
- [:random_vibrato_rate, 16.0],
- [:periodic_vibrato_amp, 0.0025],
- [:random_vibrato_amp, 0.005],
- [:noise_amount, 0.0],
- [:noise_freq, 1000.0],
- [:ind_noise_freq, 10.0],
- [:ind_noise_amount, 0.0],
- [:amp_noise_freq, 20.0],
- [:amp_noise_amount, 0.0],
- [:gliss_env, [0, 0, 100, 0]],
- [:gliss_amount, 0.0],
- [:fm1_env, [0, 1, 25, 0.4, 75, 0.6, 100, 0]],
- [:fm2_env, [0, 1, 25, 0.4, 75, 0.6, 100, 0]],
- [:fm3_env, [0, 1, 25, 0.4, 75, 0.6, 100, 0]],
- [:fm1_rat, 1.0],
- [:fm2_rat, 3.0],
- [:fm3_rat, 4.0],
- [:fm1_index, false],
- [:fm2_index, false],
- [:fm3_index, false],
- [:base, 1.0],
- [:index_type, :violin])
- frq_scl = hz2radians(freq)
- modulate = fm_index.nonzero?
- maxdev = frq_scl * fm_index
- vln = (index_type == :violin or index_type == 1)
- logfreq = log(freq)
- sqrtfreq = sqrt(freq)
- index1 = (fm1_index or [PI, maxdev * (vln ? 5.0 : 7.5) / logfreq].min)
- index2 = (fm2_index or [PI, maxdev * 3.0 *
- (vln ? ((8.5 - logfreq) / (3.0 + freq * 0.001)) :
- (15.0 / sqrtfreq))].min)
- index3 = (fm3_index or [PI, maxdev * (vln ? 4.0 : 8.0) / sqrtfreq].min)
- easy_case = (noise_amount.zero? and
- (fm1_env == fm2_env) and
- (fm1_env == fm3_env) and
- (fm1_rat - fm1_rat.floor).zero? and
- (fm2_rat - fm2_rat.floor).zero? and
- (fm3_rat - fm3_rat.floor).zero?)
- norm = ((easy_case and modulate and 1.0) or index1)
- carrier = make_oscil(freq)
- fmosc1 = fmosc2 = fmosc3 = false
- indf1 = indf2 = indf3 = false
- if modulate
- indf1 = make_env(fm1_env, norm, dur)
- if easy_case
- a = [fm1_rat.to_i, index1,
- (fm2_rat / fm1_rat).floor, index2,
- (fm3_rat / fm1_rat).floor, index3]
- coe = partials2polynomial(a)
- fmosc1 = make_polyshape(:frequency, fm1_rat * freq, :coeffs, coe)
- else
- indf2 = make_env(fm2_env, index2, dur)
- indf3 = make_env(fm3_env, index3, dur)
- if (fm1_rat * freq * 2.0) > mus_srate
- fmosc1 = make_oscil(:frequency, freq)
- else
- fmosc1 = make_oscil(:frequency, fm1_rat * freq)
- end
- if (fm2_rat * freq * 2.0) > mus_srate
- fmosc2 = make_oscil(:frequency, freq)
- else
- fmosc2 = make_oscil(:frequency, fm2_rat * freq)
- end
- if (fm3_rat * freq * 2.0) > mus_srate
- fmosc3 = make_oscil(:frequency, freq)
- else
- fmosc3 = make_oscil(:frequency, fm3_rat * freq)
- end
- end
- end
- ampf = make_env(amp_env, amp, dur, 0.0, base)
- frqf = make_env(gliss_env, gliss_amount * frq_scl, dur)
- pervib = make_triangle_wave(periodic_vibrato_rate,
- periodic_vibrato_amp * frq_scl)
- ranvib = make_rand_interp(random_vibrato_rate,
- random_vibrato_amp * frq_scl)
- fm_noi = if noise_amount.nonzero?
- make_rand(noise_freq, PI * noise_amount)
- else
- false
- end
- ind_noi = if ind_noise_amount.nonzero? and ind_noise_freq.nonzero?
- make_rand_interp(ind_noise_freq, ind_noise_amount)
- else
- false
- end
- amp_noi = if amp_noise_amount.nonzero? and amp_noise_freq.nonzero?
- make_rand_interp(amp_noise_freq, amp_noise_amount)
- else
- false
- end
- fuzz = modulation = 0.0
- ind_fuzz = amp_fuzz = 1.0
- if modulate
- if easy_case
- lambda do |y|
- vib = env(frqf) + triangle_wave(pervib) + rand_interp(ranvib)
- ind_fuzz = 1.0 + rand_interp(ind_noi) if ind_noi
- amp_fuzz = 1.0 + rand_interp(amp_noi) if amp_noi
- modulation = env(indf1) * polyshape(fmosc1, 1.0, vib)
- env(ampf) * amp_fuzz * oscil(carrier, vib + ind_fuzz * modulation)
- end
- else
- lambda do |y|
- fuzz = rand(fm_noi) if fm_noi
- vib = env(frqf) + triangle_wave(pervib) + rand_interp(ranvib)
- ind_fuzz = 1.0 + rand_interp(ind_noi) if ind_noi
- amp_fuzz = 1.0 + rand_interp(amp_noi) if amp_noi
- modulation = (env(indf1) * oscil(fmosc1, fm1_rat * vib + fuzz) +
- env(indf2) * oscil(fmosc2, fm2_rat * vib + fuzz) +
- env(indf3) * oscil(fmosc3, fm3_rat * vib + fuzz))
- env(ampf) * amp_fuzz * oscil(carrier, vib + ind_fuzz * modulation)
- end
- end
- else
- lambda do |y|
- vib = env(frqf) + triangle_wave(pervib) + rand_interp(ranvib)
- ind_fuzz = 1.0 + rand_interp(ind_noi) if ind_noi
- amp_fuzz = 1.0 + rand_interp(amp_noi) if amp_noi
- env(ampf) * amp_fuzz * oscil(carrier, vib + ind_fuzz)
- end
- end
- end
-
- add_help(:jc_reverb,
- "jc_reverb(*args)
- :volume = 1.0
- :delay1 = 0.013
- :delay2 = 0.011
- :delay3 = 0.015
- :delay4 = 0.017
- :low_pass = false
- :double = false
- :amp_env = false
- Chowning reverb")
- def jc_reverb(*args)
- low_pass, volume, amp_env, delay1, delay2, delay3, delay4, double = nil
- optkey(args, binding,
- [:volume, 1.0],
- [:delay1, 0.013],
- [:delay2, 0.011],
- [:delay3, 0.015],
- [:delay4, 0.017],
- [:low_pass, false],
- [:double, false],
- [:amp_env, false])
- chan2 = (@channels > 1)
- chan4 = (@channels == 4)
- if double and chan4
- error("%s: not set up for doubled reverb in quad", get_func_name)
- end
- allpass1 = make_all_pass(-0.7, 0.7, 1051)
- allpass2 = make_all_pass(-0.7, 0.7, 337)
- allpass3 = make_all_pass(-0.7, 0.7, 113)
- comb1 = make_comb(0.742, 4799)
- comb2 = make_comb(0.733, 4999)
- comb3 = make_comb(0.715, 5399)
- comb4 = make_comb(0.697, 5801)
- outdel1 = make_delay((delay1 * @srate).round)
- outdel2 = (chan2 ? make_delay((delay2 * @srate).round) : false)
- outdel3 = ((chan4 or double) ? make_delay((delay3 * @srate).round) : false)
- outdel4 = ((chan4 or (double and chan2)) ?
- make_delay((delay4 * @srate).round) : false)
- envA = if amp_env
- make_env(:envelope, amp_env,
- :scaler, volume,
- :duration, ws_duration(@revfile) + @decay_time)
- else
- false
- end
- comb_sum_1 = comb_sum = 0.0
- out_frample = Vct.new(@channels)
- run_reverb() do |ho, i|
- allpass_sum = all_pass(allpass3, all_pass(allpass2,
- all_pass(allpass1, ho)))
- comb_sum_2, comb_sum_1 = comb_sum_1, comb_sum
- comb_sum = (comb(comb1, allpass_sum) + comb(comb2, allpass_sum) +
- comb(comb3, allpass_sum) + comb(comb4, allpass_sum))
- all_sums = if low_pass
- 0.25 * (comb_sum + comb_sum_2) + 0.5 * comb_sum_1
- else
- comb_sum
- end
- delA = delay(outdel1, all_sums)
- if double
- delA += delay(outdel3, all_sums)
- end
- if envA
- volume = env(envA)
- end
- out_frample[0] = volume * delA
- if chan2
- delB = delay(outdel2, all_sums)
- if double
- delB += delay(outdel4, all_sums)
- end
- out_frample[1] = volume * delB
- if chan4
- out_frample[2] = volume * delay(outdel3, all_sums)
- out_frample[3] = volume * delay(outdel4, all_sums)
- end
- end
- out_frample
- end
- end
-
- # v.rb ends here
|