From 2cab9723c996298c3ceded8c94fc55b8d92ea51d Mon Sep 17 00:00:00 2001 From: minjaesong Date: Wed, 20 Dec 2023 20:51:29 +0900 Subject: [PATCH] the correct way to convolve a stereo audio --- src/net/torvald/terrarum/audio/dsp/Convolv.kt | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/net/torvald/terrarum/audio/dsp/Convolv.kt b/src/net/torvald/terrarum/audio/dsp/Convolv.kt index bb1a94c99..180e0422c 100644 --- a/src/net/torvald/terrarum/audio/dsp/Convolv.kt +++ b/src/net/torvald/terrarum/audio/dsp/Convolv.kt @@ -6,7 +6,7 @@ import net.torvald.terrarum.audio.* import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE import java.io.File -class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() { +class Convolv(ir: File, val gain: Float = 1f / 512f): TerrarumAudioFilter() { val fftLen: Int private val convFFT: Array @@ -72,26 +72,40 @@ class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() { private val realtime = (BLOCKSIZE / TerrarumAudioMixerTrack.SAMPLING_RATEF * 1000000000L) private val fftIn = ComplexArray(FloatArray(fftLen * 2)) private val fftMult = ComplexArray(FloatArray(fftLen * 2)) - private val fftOut = FloatArray(fftLen) + private val fftOut_lL = FloatArray(fftLen) // small l/r: input audio + private val fftOut_rL = FloatArray(fftLen) // large L/R: impulse response + private val fftOut_lR = FloatArray(fftLen) + private val fftOut_rR = FloatArray(fftLen) + + private fun convolve(x: ComplexArray, h: ComplexArray, output: FloatArray) { + FFT.fftInto(x, fftIn) + fftIn.mult(h, fftMult) + FFT.ifftAndGetReal(fftMult, output) + } /** * https://thewolfsound.com/fast-convolution-fft-based-overlap-add-overlap-save-partitioned/ */ override fun thru(inbuf: List, outbuf: List) { - val t1 = System.nanoTime() - for (ch in outbuf.indices) { - push(gain, inbuf[ch], this.inbuf[ch]) - FFT.fftInto(this.inbuf[ch], fftIn) - fftIn.mult(convFFT[ch], fftMult) - FFT.ifftAndGetReal(fftMult, fftOut) - System.arraycopy(fftOut, fftLen - BLOCKSIZE, outbuf[ch], 0, BLOCKSIZE) + push(gain, inbuf[0], this.inbuf[0]) + push(gain, inbuf[1], this.inbuf[1]) + + convolve(this.inbuf[0], convFFT[0], fftOut_lL) + convolve(this.inbuf[1], convFFT[0], fftOut_rL) + convolve(this.inbuf[0], convFFT[1], fftOut_lR) + convolve(this.inbuf[1], convFFT[1], fftOut_rR) + + for (i in 0 until BLOCKSIZE) { + outbuf[0][i] = fftOut_lL[fftLen - BLOCKSIZE + i] + fftOut_rL[fftLen - BLOCKSIZE + i] + outbuf[1][i] = fftOut_rR[fftLen - BLOCKSIZE + i] + fftOut_lR[fftLen - BLOCKSIZE + i] } + val ptime = System.nanoTime() - t1 setDebugTime("audio.convolve", ptime) processingSpeed = realtime / ptime