class SynthBlocks::Fx::GVerb
GVerb
is a relatively simple reverb implementation
Public Class Methods
new(srate, max_room_size: 120.0, room_size: 50.0, rev_time: 2.0, damping: 0.3, spread: 15.0, input_bandwidth: 1.5, early_level: 0.8, tail_level: 0.5, mix: 0.2)
click to toggle source
Create new GVerb
instance
max_room_size is the maximum room size you'll use
room_size is the current room size
# File lib/synth_blocks/fx/g_verb.rb, line 90 def initialize(srate, max_room_size: 120.0, room_size: 50.0, rev_time: 2.0, damping: 0.3, spread: 15.0, input_bandwidth: 1.5, early_level: 0.8, tail_level: 0.5, mix: 0.2) @rate = srate @damping = damping @max_room_size = max_room_size @room_size = room_size @rev_time = rev_time @early_level = early_level @tail_level = tail_level @mix = mix @max_delay = @rate * @max_room_size / 340.0 @largest_delay = @rate * @room_size / 340.0 @input_bandwidth = input_bandwidth; @input_damper = Damper.new(1.0 - @input_bandwidth) @fdndels = FDNORDER.times.map do |i| FixedDelay.new(@max_delay + 1000) end @fdngains = Array.new(FDNORDER) @fdnlens = Array.new(FDNORDER) @fdndamps = FDNORDER.times.map do |i| Damper.new(@damping) end ga = 60.0; gt = @rev_time; ga = 10.0 ** (-ga / 20.0) n = @rate * gt @alpha = ga ** (1.0 / n) gb = 0.0; FDNORDER.times do |i| gb = 1.000000*@largest_delay if (i == 0) gb = 0.816490*@largest_delay if (i == 1) gb = 0.707100*@largest_delay if (i == 2) gb = 0.632450*@largest_delay if (i == 3) @fdnlens[i] = nearest_prime(gb, 0.5); @fdnlens[i] = gb.round; @fdngains[i] = -(@alpha ** @fdnlens[i]) end @d = Array.new(FDNORDER) @u = Array.new(FDNORDER) @f = Array.new(FDNORDER) # DIFFUSER SECTION diffscale = @fdnlens[3].to_f/(210+159+562+410); spread1 = spread.to_f spread2 = 3.0*spread b = 210 r = 0.125541 a = spread1*r c = 210+159+a cc = c-b r = 0.854046 a = spread2*r d = 210+159+562+a dd = d-c e = 1341-d @ldifs = [ Diffuser.new((diffscale*b),0.75), Diffuser.new((diffscale*cc),0.75), Diffuser.new((diffscale*dd),0.625), Diffuser.new((diffscale*e),0.625) ] b = 210 r = -0.568366 a = spread1*r c = 210+159+a cc = c-b r = -0.126815; a = spread2*r d = 210+159+562+a dd = d-c e = 1341-d @rdifs = [ Diffuser.new((diffscale*b),0.75), Diffuser.new((diffscale*cc),0.75), Diffuser.new((diffscale*dd),0.625), Diffuser.new((diffscale*e),0.625) ] # Tapped delay section */ @tapdelay = FixedDelay.new(44000) @taps = Array.new(FDNORDER) @tapgains = Array.new(FDNORDER) @taps[0] = 5+0.410*@largest_delay @taps[1] = 5+0.300*@largest_delay @taps[2] = 5+0.155*@largest_delay @taps[3] = 5+0.000*@largest_delay FDNORDER.times do |i| @tapgains[i] = @alpha ** @taps[i] end end
Public Instance Methods
run(x)
click to toggle source
runs a value through the reverb, returns the reverberated signal mixed with the original.
# File lib/synth_blocks/fx/g_verb.rb, line 199 def run(x) if x.nan? || x.abs > 100000.0 x = 0.0 end z = @input_damper.run(x) z = @ldifs[0].run(z) FDNORDER.times do |i| @u[i] = @tapgains[i] * @tapdelay.read(@taps[i]) end @tapdelay.write(z) FDNORDER.times do |i| @d[i] = @fdndamps[i].run(@fdngains[i] * @fdndels[i].read(@fdnlens[i])) end sum = 0.0 sign = 1.0 FDNORDER.times do |i| sum += sign * (@tail_level * @d[i] + @early_level * @u[i]) sign = -sign end sum += x* @early_level lsum = sum # rsum = sum @f = fdn_matrix(@d) FDNORDER.times do |i| @fdndels[i].write(@u[i] + @f[i]) end lsum = @ldifs[1].run(lsum) lsum = @ldifs[2].run(lsum) lsum = @ldifs[3].run(lsum) # rsum = @rdifs[1].run(rsum) # rsum = @rdifs[2].run(rsum) # rsum = @rdifs[3].run(rsum) lsum = x * (1.0 - @mix) + lsum * @mix # rsum = x * (1.0 - mix) + rsum * mix return lsum end
Private Instance Methods
fdn_matrix(a)
click to toggle source
# File lib/synth_blocks/fx/g_verb.rb, line 262 def fdn_matrix(a) b = Array.new(FDNORDER) dl0 = a[0] dl1 = a[1] dl2 = a[2] dl3 = a[3] b[0] = 0.5*(dl0 + dl1 - dl2 - dl3); b[1] = 0.5*(dl0 - dl1 - dl2 + dl3); b[2] = 0.5*(-dl0 + dl1 - dl2 + dl3); b[3] = 0.5*(dl0 + dl1 + dl2 + dl3); b end
nearest_prime(n_f, rerror)
click to toggle source
# File lib/synth_blocks/fx/g_verb.rb, line 250 def nearest_prime(n_f, rerror) n = n_f.to_i return n if Prime.prime?(n) # assume n is large enough and n*rerror enough smaller than n */ bound = n*rerror; 1.upto(bound) do |k| return n+k if Prime.prime?(n+k) return n-k if Prime.prime?(n-k) end return -1 end