Class: Deftones::Component::MultibandSplit

Inherits:
Deftones::Core::AudioNode show all
Defined in:
lib/deftones/component/multiband_split.rb

Defined Under Namespace

Classes: OutputTap

Instance Attribute Summary collapse

Attributes inherited from Deftones::Core::AudioNode

#context

Instance Method Summary collapse

Methods inherited from Deftones::Core::AudioNode

#>>, #attach_destination, #attach_source, #block_time, #chain, #channel_count, #channel_count_mode, #channel_interpretation, #connect, #connected?, #default_input_channels, #default_output_channels, #destination_for_connection, #detach_all_destinations, #detach_destination, #detach_source, #disconnect, #dispose, #disposed?, #fan, #get, #immediate, #input_for_index, #inputs, #mix_source_blocks, #multichannel_process?, #name, #normalize_connection_index, #normalize_output_block, #now, #number_of_inputs, #number_of_outputs, #output_for_connection, #output_for_index, #outputs, #process, #raise_connection_index_error!, #reaches_node?, #sample_time, #set, #to_destination, #to_frequency, #to_master, #to_midi, #to_output, #to_s, #to_seconds, #to_ticks, #uses_legacy_render_for_block?, #validate_connectable!, #validate_connection_index!

Constructor Details

#initialize(low_frequency: 400.0, high_frequency: 2_500.0, q: 1.0, context: Deftones.context) ⇒ MultibandSplit

Returns a new instance of MultibandSplit.



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/deftones/component/multiband_split.rb', line 8

def initialize(low_frequency: 400.0, high_frequency: 2_500.0, q: 1.0, context: Deftones.context)
  super(context: context)
  @input = Core::Gain.new(context: context)
  @output = self
  @low_frequency = Core::Signal.new(value: low_frequency, units: :frequency, context: context)
  @high_frequency = Core::Signal.new(value: high_frequency, units: :frequency, context: context)
  @q = Core::Signal.new(value: q, units: :number, context: context)
  @low = OutputTap.new(parent: self, band: :low, context: context)
  @mid = OutputTap.new(parent: self, band: :mid, context: context)
  @high = OutputTap.new(parent: self, band: :high, context: context)
  @low_filters = []
  @mid_highpasses = []
  @mid_lowpasses = []
  @high_filters = []
end

Instance Attribute Details

#highObject (readonly)

Returns the value of attribute high.



6
7
8
# File 'lib/deftones/component/multiband_split.rb', line 6

def high
  @high
end

#high_frequencyObject (readonly)

Returns the value of attribute high_frequency.



6
7
8
# File 'lib/deftones/component/multiband_split.rb', line 6

def high_frequency
  @high_frequency
end

#inputObject (readonly)

Returns the value of attribute input.



6
7
8
# File 'lib/deftones/component/multiband_split.rb', line 6

def input
  @input
end

#lowObject (readonly)

Returns the value of attribute low.



6
7
8
# File 'lib/deftones/component/multiband_split.rb', line 6

def low
  @low
end

#low_frequencyObject (readonly)

Returns the value of attribute low_frequency.



6
7
8
# File 'lib/deftones/component/multiband_split.rb', line 6

def low_frequency
  @low_frequency
end

#midObject (readonly)

Returns the value of attribute mid.



6
7
8
# File 'lib/deftones/component/multiband_split.rb', line 6

def mid
  @mid
end

#outputObject (readonly)

Returns the value of attribute output.



6
7
8
# File 'lib/deftones/component/multiband_split.rb', line 6

def output
  @output
end

#qObject (readonly)

Returns the value of attribute q.



6
7
8
# File 'lib/deftones/component/multiband_split.rb', line 6

def q
  @q
end

Instance Method Details

#ensure_filter_banks(channels) ⇒ Object (private)



106
107
108
109
110
111
112
113
114
# File 'lib/deftones/component/multiband_split.rb', line 106

def ensure_filter_banks(channels)
  required = [channels.to_i, 1].max
  while @low_filters.length < required
    @low_filters << DSP::Biquad.new
    @mid_highpasses << DSP::Biquad.new
    @mid_lowpasses << DSP::Biquad.new
    @high_filters << DSP::Biquad.new
  end
end

#render(num_frames, start_frame = 0, cache = {}) ⇒ Object



24
25
26
# File 'lib/deftones/component/multiband_split.rb', line 24

def render(num_frames, start_frame = 0, cache = {})
  render_block(num_frames, start_frame, cache).mono
end

#render_band(band, num_frames, start_frame = 0, cache = {}) ⇒ Object



28
29
30
# File 'lib/deftones/component/multiband_split.rb', line 28

def render_band(band, num_frames, start_frame = 0, cache = {})
  render_band_block(band, num_frames, start_frame, cache).mono
end

#render_band_block(band, num_frames, start_frame = 0, cache = {}) ⇒ Object



45
46
47
# File 'lib/deftones/component/multiband_split.rb', line 45

def render_band_block(band, num_frames, start_frame = 0, cache = {})
  render_bands_block(num_frames, start_frame, cache).fetch(band).dup
end

#render_bands_block(num_frames, start_frame, cache) ⇒ Object (private)



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/deftones/component/multiband_split.rb', line 58

def render_bands_block(num_frames, start_frame, cache)
  cache_key = [object_id, :bands_block, start_frame, num_frames]
  return cache.fetch(cache_key) if cache.key?(cache_key)

  input_block = @input.send(:render_block, num_frames, start_frame, cache)
  update_filters(input_block.channels, start_frame)

  low = Array.new(input_block.channels) { Array.new(num_frames, 0.0) }
  mid = Array.new(input_block.channels) { Array.new(num_frames, 0.0) }
  high = Array.new(input_block.channels) { Array.new(num_frames, 0.0) }

  input_block.channel_data.each_with_index do |channel, channel_index|
    num_frames.times do |index|
      sample = channel[index]
      low[channel_index][index] = @low_filters[channel_index].process_sample(sample)
      mid[channel_index][index] =
        @mid_lowpasses[channel_index].process_sample(@mid_highpasses[channel_index].process_sample(sample))
      high[channel_index][index] = @high_filters[channel_index].process_sample(sample)
    end
  end

  cache[cache_key] = {
    low: Core::AudioBlock.from_channel_data(low),
    mid: Core::AudioBlock.from_channel_data(mid),
    high: Core::AudioBlock.from_channel_data(high)
  }
end

#render_block(num_frames, start_frame = 0, cache = {}) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/deftones/component/multiband_split.rb', line 32

def render_block(num_frames, start_frame = 0, cache = {})
  cache_key = [object_id, :block, start_frame, num_frames]
  return cache.fetch(cache_key).dup if cache.key?(cache_key)

  bands = render_bands_block(num_frames, start_frame, cache)
  channels = bands[:low].channels
  output = Core::AudioBlock.silent(num_frames, channels)
  output.mix!(bands[:low]).mix!(bands[:mid]).mix!(bands[:high])

  cache[cache_key] = output
  output.dup
end

#reset!Object



49
50
51
52
53
54
# File 'lib/deftones/component/multiband_split.rb', line 49

def reset!
  [@low_filters, @mid_highpasses, @mid_lowpasses, @high_filters].each do |filters|
    filters.each(&:reset!)
  end
  self
end

#update_filters(channels, start_frame) ⇒ Object (private)



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/deftones/component/multiband_split.rb', line 86

def update_filters(channels, start_frame)
  ensure_filter_banks(channels)
  current_low_frequency = @low_frequency.process(1, start_frame).first
  current_high_frequency = @high_frequency.process(1, start_frame).first
  current_q = @q.process(1, start_frame).first

  @low_filters.each do |filter|
    filter.update(type: :lowpass, frequency: current_low_frequency, q: current_q, gain_db: 0.0, sample_rate: context.sample_rate)
  end
  @mid_highpasses.each do |filter|
    filter.update(type: :highpass, frequency: current_low_frequency, q: current_q, gain_db: 0.0, sample_rate: context.sample_rate)
  end
  @mid_lowpasses.each do |filter|
    filter.update(type: :lowpass, frequency: current_high_frequency, q: current_q, gain_db: 0.0, sample_rate: context.sample_rate)
  end
  @high_filters.each do |filter|
    filter.update(type: :highpass, frequency: current_high_frequency, q: current_q, gain_db: 0.0, sample_rate: context.sample_rate)
  end
end