|
- # maxf.rb -- CLM -> Snd/Ruby translation of maxf.ins
-
- # Translator/Author: Michael Scholz <mi-scholz@users.sourceforge.net>
- # Created: Mon Mar 24 11:24:23 CET 2003
- # Changed: Thu Oct 15 00:16:58 CEST 2009
-
- # It follows the original header of Juan Reyes.
-
- # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- # ;;
- # ;; maxf.ins
- # ;; This is Max Mathews (mvm) new filter (2002)
- # ;; High-Q, 2-Integrator, filter with
- # ;; Two Poles, and one Zero at the Origin
- # ;;
- # ;; It synthesizes equal-tempered frequencies
- # ;; integer & just scales out of a wide-band input
- # ;; signal.
- # ;; Based on Max's code (filter.cpp)
- # ;;
- # ;; This heuristic might be called Modal Synthesis.
- # ;; But as well it can also be additive synthesis in
- # ;; which a resonator is initialized to generate the
- # ;; exponentially decaying sinusoids at the desired
- # ;; phase.
- # ;;
- # ;; This implementation written by Juan Reyes with dsp
- # ;; assistance from JOS.
- # ;; This version Oct-30, 2002
- # ;;
- # ;; Change gain(att) of input file if clipping
- # ;;
- # ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- require "ws"
-
- CLM = Struct.new("CLM", :yy1, :yy2, :zz1, :zz2, :pp1, :pp2, :pp3, :out)
-
- add_help(:maxfilter, "maxfilter(file, start, *args)
- :att = 1.0
- :numf = 1
- :freqfactor = 1.0
- :amplitude = 1.0
- :amp-env = [0, 1, 100, 1]
- :degree = kernel_rand(90.0)
- :distance = 1.0
- :reverb_amount = 0.2
-
- This is Max Mathews (mvm) new filter (2002) High-Q, 2-Integrator,
- filter with Two Poles, and one Zero at the Origin
-
- It synthesizes equal-tempered frequencies integer & just scales
- out of a wide-band input signal.
- Based on Max's code (filter.cpp)
-
- This heuristic might be called Modal Synthesis. But as well it
- can also be additive synthesis in which a resonator is
- initialized to generate the exponentially decaying sinusoids at
- the desired phase.
-
- :att = 1 in-file attenuation
- :numf = 1 1 filter
- :numf = 4 4 filters
- :numf = 9 9 filters
- :numf = 12 12 filters
- :numf = 13 13 filters")
- def maxfilter(file, start = 0, *args)
- att, numf, freqfactor, amplitude, amp_env, degree, distance, reverb_amount = nil
- optkey(args, binding,
- [:att, 1.0],
- [:numf, 1],
- [:freqfactor, 1.0],
- [:amplitude, 1.0],
- [:amp_env, [0, 1, 100, 1]],
- [:degree, kernel_rand(90.0)],
- [:distance, 1.0],
- [:reverb_amount, 0.2])
- rda, snd = make_general_reader(file, :channel, 0)
- formfil = CLM.new(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
- dur = duration(file)
- ampf = make_env(:envelope, amp_env, :scaler, amplitude, :duration, dur)
- state_0 = make_array( 1) do make_array(3, 0.0) end
- state_1 = make_array(12) do make_array(3, 0.0) end
- state_2 = make_array( 9) do make_array(3, 0.0) end
- state_3 = make_array(13) do make_array(3, 0.0) end
- state_4 = make_array( 4) do make_array(3, 0.0) end
- state_5 = make_array( 2) do make_array(3, 0.0) end
- case numf
- when 1
- Snd.display "State 0 (default): One filter"
- state_0[0] = 7.54e-002, 2000.0 * freqfactor, 2.0
- when 2
- Snd.display "State 5: Two filters"
- state_5[0] = 7.54e-003, 200.0 * freqfactor, 4.0
- state_5[1] = 7.54e-004, 800.0 * freqfactor, 1.0
- when 4
- Snd.display "State 4: Four filters"
- state_4[0] = 7.54e-002, 1000.0 * freqfactor, 0.5
- state_4[1] = 3.225e-002, 400.0 * freqfactor, 3.0
- state_4[2] = 1.14e-002, 800.0 * freqfactor, 2.8
- state_4[3] = 7.54e-002, 1600.0 * freqfactor, 1.0
- when 9
- Snd.display "State 2: Streached overtone string 9 filters"
- state_2[0] = 1.07e-002, 100.0, 2.5
- state_2[1] = 1.07e-002, 202.0, 0.75
- state_2[2] = 1.07e-002, 305.0, 0.5
- state_2[3] = 7.077e-003, 408.0, 0.4
- state_2[4] = 1.07e-002, 501.0, 0.3
- state_2[5] = 1.07e-002, 612.0, 0.25
- state_2[6] = 1.07e-003, 715.0, 0.25
- state_2[7] = 1.07e-002, 817.0, 0.2
- state_2[8] = 1.07e-002, 920.0, 0.18
- when 12
- Snd.display "State 1: Risset bell long 12 filters"
- state_1[0] = 5.025e-002, 224.0, 3.7
- state_1[1] = 5.025e-002, 225.0, 3.3
- state_1[2] = 5.025e-002, 368.0, 2.8
- state_1[3] = 5.025e-002, 369.0, 2.4
- state_1[4] = 1.047e-002, 476.0, 1.9
- state_1[5] = 5.025e-002, 680.0, 1.7
- state_1[6] = 5.025e-002, 800.0, 1.5
- state_1[7] = 4.05e-002, 1096.0, 1.1
- state_1[8] = 4.05e-002, 1099.0, 0.9
- state_1[9] = 4.05e-002, 1200.0, 0.6
- state_1[10] = 3.78e-002, 1504.0, 0.4
- state_1[11] = 4.05e-002, 1628.0, 0.3
- when 13
- Snd.display "State 3: Open major chord with repeated octave 12 filters"
- state_3[0] = 5.025e-002, 100.0, 2.0
- state_3[1] = 5.025e-002, 251.0, 2.0
- state_3[2] = 5.025e-002, 299.0, 2.0
- state_3[3] = 5.025e-002, 401.0, 2.0
- state_3[4] = 5.025e-002, 199.0, 2.0
- state_3[5] = 5.025e-002, 501.0, 2.0
- state_3[6] = 5.025e-002, 599.0, 2.0
- state_3[7] = 5.025e-002, 801.0, 2.0
- state_3[8] = 5.025e-002, 201.0, 2.0
- state_3[9] = 5.025e-002, 749.0, 2.0
- state_3[10] = 5.025e-002, 900.0, 2.0
- state_3[11] = 5.025e-004, 1205.0, 2.0
- state_3[12] = 5.025e-004, 1205.0, 2.0
- else
- Snd.display "Please leave default or enter [1] [2] [4] [9] [12] [13]"
- numf = 1
- end
- mvmfilt = lambda do |b, sample|
- b[:yy2] = (b[:pp1] * b[:yy1] + b[:pp2] * b[:zz1]) - b[:pp3] * sample
- b[:zz2] = b[:zz1] - b[:pp2] * b[:yy2]
- b[:zz1] = b[:zz2]
- b[:yy1] = b[:yy2]
- b[:out] = b[:yy1]
- end
- set_coeffs = lambda do |b, ary|
- famp, ffreq, fdecay = ary
- tper = 1.0 / @srate
- centerfreq = (2.0 * PI * ffreq) / @srate
- maxdecay = (2.0 * tper) / (centerfreq * centerfreq)
- mindecay = tper / centerfreq
- fdecay = if fdecay >= maxdecay
- maxdecay
- else
- fdecay.to_f
- end
- fdecay = mindecay if fdecay <= mindecay
- b[:pp1] = 1.0 - 2.0 / (fdecay * @srate)
- b[:pp2] = (2.0 * PI * ffreq) / @srate
- b[:pp3] = b[:pp2] * famp
- end
- run_instrument(start, dur, :degree, degree, :distance, distance, :reverb_amount, reverb_amount) do
- outval_a = att * general_readin(rda)
- add_fl = 0.0
- numf.times do |j|
- case numf
- when 1
- set_coeffs.call(formfil, state_0[j])
- when 2
- set_coeffs.call(formfil, state_5[j])
- when 4
- set_coeffs.call(formfil, state_4[j])
- when 9
- set_coeffs.call(formfil, state_2[j])
- when 12
- set_coeffs.call(formfil, state_1[j])
- when 13
- set_coeffs.call(formfil, state_3[j])
- end
- filsig = mvmfilt.call(formfil, outval_a)
- add_fl += filsig
- end
- env(ampf) * add_fl
- end
- close_general_reader(snd, rda)
- end
-
- =begin
- ifile = "dog.snd"
- ofile = "rmax_dog.snd"
- stats = [1, 2, 4, 9, 12, 13]
- with_sound(:play, 1, :statistics, true, :channels, 4, :output, ofile, :reverb, :jc_reverb,
- :comment, format("maxfilter test, filters %s, source %s", stats.inspect, ifile)) do
- stats.each_with_index do |val, i| maxfilter(ifile, i, :numf, val) end
- end
-
- with_sound(:srate, 22050) do maxfilter("dog.snd", 0) end
- with_sound(:srate, 44100) do maxfilter("dog.snd", 0, :numf, 12) end
- with_sound(:srate, 44100) do maxfilter("dog.snd", 0, :numf, 13, :att, 0.75) end
- with_sound(:srate, 44100) do maxfilter("dog.snd", 0, :numf, 2, :att, 0.25, :freqfactor, 0.5) end
- =end
-
- # maxf.rb ends here
|