class AudioStream::Fx::ConvolutionReverb
Public Class Methods
new(impulse, dry: 0.5, wet: 0.5)
click to toggle source
# File lib/audio_stream/fx/convolution_reverb.rb, line 4 def initialize(impulse, dry: 0.5, wet: 0.5) impulse_bufs = impulse.to_a @impulse_size = impulse_bufs.size @channels = impulse_bufs[0].channels @window_size = impulse_bufs[0].window_size @dry_gain = dry @wet_gain = wet zero_buf = Buffer.create(@window_size, @channels) impulse_bufs = [zero_buf.clone] + impulse_bufs @impulse_ffts = [] @impulse_size.times {|i| na = NArray.float(@channels, @window_size*2) impulse_bufs[i].to_float_na(na, 0) impulse_bufs[i+1].to_float_na(na, @window_size) @impulse_ffts << FFTW3.fft(na, FFTW3::FORWARD) / na.length } @impulse_max_gain = @impulse_ffts.map{|c| c.real**2 + c.imag**2}.map(&:sum).max / @channels @wet_ffts = RingBuffer.new(@impulse_size) { Array.new(@impulse_size, NArray.float(@channels, @window_size*2)) } @prev_input = zero_buf.clone end
Public Instance Methods
process(input)
click to toggle source
# File lib/audio_stream/fx/convolution_reverb.rb, line 32 def process(input) if @window_size!=input.window_size raise "window size is not match: impulse.size=#{@window_size} input.size=#{input.window_size}" end if @channels!=input.channels raise "channels is not match: impulse.channels=#{@channels} input.channels=#{input.channels}" end # current dry to wet na = NArray.float(@channels, @window_size*2) @prev_input.to_float_na(na, 0) input.to_float_na(na, @window_size) input_fft = FFTW3.fft(na, FFTW3::FORWARD) / na.length @wet_ffts.current = @impulse_ffts.map {|impulse_fft| input_fft * impulse_fft } @wet_ffts.rotate @prev_input = input.clone # calc wet matrix sum wet_fft = NArray.complex(@channels, @window_size*2) @wet_ffts.each_with_index {|wet, i| wet_fft += wet[@impulse_size-i-1] } wet_na = FFTW3.fft(wet_fft, FFTW3::BACKWARD)[(@channels*@window_size)...(@channels*@window_size*2)] * (@wet_gain / @impulse_max_gain) # current dry + wet matrix sum src0 = input.streams[0] src1 = input.streams[1] case @channels when 1 output = Buffer.create_mono(@window_size) dst0 = output.streams[0] @window_size.times {|i| dry = src0[i] * @dry_gain wet = wet_na[i].real dst0[i] = dry + wet } when 2 output = Buffer.create_stereo(@window_size) dst0 = output.streams[0] dst1 = output.streams[1] @window_size.times {|i| # dry dry0 = src0[i] * @dry_gain dry1 = src1[i] * @dry_gain # wet wet0 = wet_na[i*2].real wet1 = wet_na[(i*2)+1].real dst0[i] = dry0 + wet0 dst1[i] = dry1 + wet1 } end output end