Class: Deftones::Component::Convolver
Instance Attribute Summary collapse
#wet
Instance Method Summary
collapse
#multichannel_process?, #normalize_channel_output, #process, #process_effect
Constructor Details
#initialize(source = nil, wet: 1.0, normalize: false, context: Deftones.context, &onload) ⇒ Convolver
Returns a new instance of Convolver.
9
10
11
12
13
14
15
16
|
# File 'lib/deftones/component/convolver.rb', line 9
def initialize(source = nil, wet: 1.0, normalize: false, context: Deftones.context, &onload)
super(wet: wet, context: context)
@normalize = normalize
@buffer = nil
@kernels = [[1.0]]
@histories = []
load(source, &onload) if source
end
|
Instance Attribute Details
#buffer ⇒ Object
Returns the value of attribute buffer.
6
7
8
|
# File 'lib/deftones/component/convolver.rb', line 6
def buffer
@buffer
end
|
#normalize ⇒ Object
Returns the value of attribute normalize.
7
8
9
|
# File 'lib/deftones/component/convolver.rb', line 7
def normalize
@normalize
end
|
Instance Method Details
#coerce_buffer(source) ⇒ Object
70
71
72
73
74
|
# File 'lib/deftones/component/convolver.rb', line 70
def coerce_buffer(source)
return source if source.is_a?(IO::Buffer)
IO::Buffer.load(source)
end
|
#convolve(history, kernel) ⇒ Object
61
62
63
64
65
66
67
68
|
# File 'lib/deftones/component/convolver.rb', line 61
def convolve(history, kernel)
kernel.each_with_index.sum do |coefficient, offset|
history_index = history.length - 1 - offset
next 0.0 if history_index.negative?
coefficient * history[history_index]
end
end
|
#ensure_history(channel_index, kernel_length) ⇒ Object
87
88
89
90
91
92
93
94
95
96
|
# File 'lib/deftones/component/convolver.rb', line 87
def ensure_history(channel_index, kernel_length)
required = [channel_index.to_i, 0].max
while @histories.length <= required
@histories << Array.new([kernel_length - 1, 0].max, 0.0)
end
if @histories[required].length != [kernel_length - 1, 0].max
@histories[required] = Array.new([kernel_length - 1, 0].max, 0.0)
end
@histories[required]
end
|
#load(source) {|_self| ... } ⇒ Object
22
23
24
25
26
27
28
|
# File 'lib/deftones/component/convolver.rb', line 22
def load(source)
@buffer = coerce_buffer(source)
@kernels = normalize_kernels(@buffer.to_array)
@histories = []
yield self if block_given?
self
end
|
#normalize_kernels(channel_arrays) ⇒ Object
76
77
78
79
80
81
82
83
84
85
|
# File 'lib/deftones/component/convolver.rb', line 76
def normalize_kernels(channel_arrays)
kernels = channel_arrays.map { |channel| channel.map(&:to_f) }.reject(&:empty?)
return [[1.0]] if kernels.empty?
return kernels unless @normalize
peak = kernels.flatten.map(&:abs).max || 0.0
return kernels if peak.zero?
kernels.map { |kernel| kernel.map { |sample| sample / peak } }
end
|
#passthrough? ⇒ Boolean
57
58
59
|
# File 'lib/deftones/component/convolver.rb', line 57
def passthrough?
@buffer.nil? || (@kernels.length == 1 && @kernels.first.length == 1 && @kernels.first.first == 1.0)
end
|
#process_effect_block(input_block, num_frames, _start_frame, _cache) ⇒ Object
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
# File 'lib/deftones/component/convolver.rb', line 32
def process_effect_block(input_block, num_frames, _start_frame, _cache)
return input_block if passthrough?
output_channels = [input_block.channels, @kernels.length].max
source = input_block.fit_channels([input_block.channels, 1].max)
output = Array.new(output_channels) { Array.new(num_frames, 0.0) }
output_channels.times do |channel_index|
kernel = @kernels[channel_index % @kernels.length]
history = ensure_history(channel_index, kernel.length).dup
input_channel = source.channel_data[[channel_index, source.channels - 1].min]
output[channel_index] = Array.new(num_frames) do |frame_index|
history << input_channel[frame_index]
sample = convolve(history, kernel)
history.shift while history.length > kernel.length
sample
end
@histories[channel_index] = history
end
Core::AudioBlock.from_channel_data(output)
end
|