Class: Deftones::Effects::AutoWah

Inherits:
Core::Effect show all
Defined in:
lib/deftones/effect/auto_wah.rb

Defined Under Namespace

Classes: FollowerSettings

Instance Attribute Summary collapse

Attributes inherited from Core::Effect

#wet

Instance Method Summary collapse

Methods inherited from Core::Effect

#multichannel_process?, #normalize_channel_output, #process, #process_effect_block

Constructor Details

#initialize(base_frequency: 200.0, octaves: 4.0, sensitivity: 0.0, q: 2.0, gain: 2.0, follower: {}, context: Deftones.context, **options) ⇒ AutoWah

Returns a new instance of AutoWah.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/deftones/effect/auto_wah.rb', line 11

def initialize(
  base_frequency: 200.0,
  octaves: 4.0,
  sensitivity: 0.0,
  q: 2.0,
  gain: 2.0,
  follower: {},
  context: Deftones.context,
  **options
)
  super(context: context, wet: 1.0, **options)
  @base_frequency = base_frequency.to_f
  @octaves = octaves.to_f
  @sensitivity = sensitivity.to_f
  @q = q.to_f
  @gain = gain.to_f
  @envelopes = []
  @filters = []
  @follower = resolve_follower(follower)
end

Instance Attribute Details

#base_frequencyObject

Returns the value of attribute base_frequency.



8
9
10
# File 'lib/deftones/effect/auto_wah.rb', line 8

def base_frequency
  @base_frequency
end

#followerObject (readonly)

Returns the value of attribute follower.



9
10
11
# File 'lib/deftones/effect/auto_wah.rb', line 9

def follower
  @follower
end

#gainObject

Returns the value of attribute gain.



8
9
10
# File 'lib/deftones/effect/auto_wah.rb', line 8

def gain
  @gain
end

#octavesObject

Returns the value of attribute octaves.



8
9
10
# File 'lib/deftones/effect/auto_wah.rb', line 8

def octaves
  @octaves
end

#qObject

Returns the value of attribute q.



8
9
10
# File 'lib/deftones/effect/auto_wah.rb', line 8

def q
  @q
end

#sensitivityObject

Returns the value of attribute sensitivity.



8
9
10
# File 'lib/deftones/effect/auto_wah.rb', line 8

def sensitivity
  @sensitivity
end

Instance Method Details

#ensure_tracking_state(channel_index) ⇒ Object (private)



89
90
91
92
93
94
95
# File 'lib/deftones/effect/auto_wah.rb', line 89

def ensure_tracking_state(channel_index)
  required = [channel_index.to_i, 0].max
  @envelopes.fill(0.0, @envelopes.length..required)
  while @filters.length <= required
    @filters << DSP::Biquad.new
  end
end

#follower_coefficient(duration) ⇒ Object (private)



61
62
63
64
65
# File 'lib/deftones/effect/auto_wah.rb', line 61

def follower_coefficient(duration)
  return 0.0 if duration.to_f <= 0.0

  Math.exp(-1.0 / (duration.to_f * context.sample_rate))
end

#openness_for(level) ⇒ Object (private)



67
68
69
70
71
72
73
# File 'lib/deftones/effect/auto_wah.rb', line 67

def openness_for(level)
  level_db = level.positive? ? Deftones.gain_to_db(level) : -100.0
  threshold = [@sensitivity.to_f, -99.0].max
  return level.clamp(0.0, 1.0) if threshold >= 0.0

  ((level_db - threshold) / -threshold).clamp(0.0, 1.0)
end

#output_gain(openness) ⇒ Object (private)



75
76
77
# File 'lib/deftones/effect/auto_wah.rb', line 75

def output_gain(openness)
  1.0 + ((@gain - 1.0) * openness)
end

#process_effect(input_buffer, num_frames, _start_frame, _cache, channel_index: 0) ⇒ Object (private)



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/deftones/effect/auto_wah.rb', line 34

def process_effect(input_buffer, num_frames, _start_frame, _cache, channel_index: 0)
  ensure_tracking_state(channel_index)
  envelope = @envelopes[channel_index]
  filter = @filters[channel_index]

  Array.new(num_frames) do |index|
    sample = input_buffer[index]
    envelope = track_envelope(sample.abs, envelope)
    openness = openness_for(envelope)
    cutoff = @base_frequency * (2.0**(@octaves * openness))
    filter.update(type: :bandpass, frequency: cutoff, q: @q, gain_db: 0.0, sample_rate: context.sample_rate)
    filter.process_sample(sample) * output_gain(openness)
  end
ensure
  @envelopes[channel_index] = envelope
end

#resolve_follower(follower) ⇒ Object (private)



79
80
81
82
83
84
85
86
87
# File 'lib/deftones/effect/auto_wah.rb', line 79

def resolve_follower(follower)
  return follower if follower.is_a?(FollowerSettings)

  settings = follower.respond_to?(:to_h) ? follower.to_h : {}
  FollowerSettings.new(
    attack: settings.fetch(:attack, 0.3).to_f,
    release: settings.fetch(:release, 0.5).to_f
  )
end

#track_envelope(level, current_envelope) ⇒ Object (private)



51
52
53
54
55
56
57
58
59
# File 'lib/deftones/effect/auto_wah.rb', line 51

def track_envelope(level, current_envelope)
  smoothing =
    if level >= current_envelope
      follower_coefficient(@follower.attack)
    else
      follower_coefficient(@follower.release)
    end
  (smoothing * current_envelope) + ((1.0 - smoothing) * level)
end