From 6059ba92ac31eeda32809ee48dd0030def321042 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Tue, 28 Nov 2023 19:25:42 +0900 Subject: [PATCH] further convolving optimisaions --- src/net/torvald/terrarum/audio/FFT.kt | 28 +++++++++--- src/net/torvald/terrarum/audio/dsp/Convolv.kt | 44 +++++-------------- 2 files changed, 35 insertions(+), 37 deletions(-) diff --git a/src/net/torvald/terrarum/audio/FFT.kt b/src/net/torvald/terrarum/audio/FFT.kt index 9c1906e70..f1ca165cf 100644 --- a/src/net/torvald/terrarum/audio/FFT.kt +++ b/src/net/torvald/terrarum/audio/FFT.kt @@ -49,6 +49,20 @@ private val IM1 = 0 */ object FFT: Disposable { + private val ffts = hashMapOf( + 128 to FloatFFT_1D(128), + 256 to FloatFFT_1D(256), + 512 to FloatFFT_1D(512), + 1024 to FloatFFT_1D(1024), + 2048 to FloatFFT_1D(2048), + 4096 to FloatFFT_1D(4096), + 8192 to FloatFFT_1D(8192), + 16384 to FloatFFT_1D(16384), + 32768 to FloatFFT_1D(32768), + 65536 to FloatFFT_1D(65536), + ) + + init { // Loader.load(org.bytedeco.fftw.global.fftw3::class.java) @@ -102,8 +116,7 @@ object FFT: Disposable { // USING JTRANSFORMS // val signal = FloatArray(signal0.size * 2) { if (it % 2 == 0) signal0[it / 2] else 0f } - val fft = FloatFFT_1D(signal0.size.toLong()) - fft.complexForward(signal) + ffts[signal0.size]!!.complexForward(signal) return ComplexArray(signal) } @@ -137,12 +150,17 @@ object FFT: Disposable { // USING JTRANSFORMS // - val signal = signal0.reim - val fft = FloatFFT_1D(signal0.size.toLong()) - fft.complexInverse(signal, true) + ffts[signal0.size]!!.complexInverse(signal0.reim, true) return signal0.getReal() } + fun ifftAndGetReal(signal0: ComplexArray, output: FloatArray) { + ffts[signal0.size]!!.complexInverse(signal0.reim, true) + for (i in 0 until signal0.size) { + output[i] = signal0.reim[i * 2] + } + } + // org.apache.commons.math3.transform.FastFouriesTransformer.java:214 /** * Computes the standard transform of the specified complex data. The diff --git a/src/net/torvald/terrarum/audio/dsp/Convolv.kt b/src/net/torvald/terrarum/audio/dsp/Convolv.kt index 9f773a7cd..46f994cb1 100644 --- a/src/net/torvald/terrarum/audio/dsp/Convolv.kt +++ b/src/net/torvald/terrarum/audio/dsp/Convolv.kt @@ -2,6 +2,7 @@ package net.torvald.terrarum.audio.dsp import com.jme3.math.FastMath import net.torvald.terrarum.App.measureDebugTime +import net.torvald.terrarum.App.setDebugTime import net.torvald.terrarum.audio.* import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.BUFFER_SIZE import java.io.File @@ -107,47 +108,26 @@ class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() { } } - - private val targetY = ComplexArray(FloatArray(fftLen * 2)) - + private val realtime = (BLOCKSIZE / TerrarumAudioMixerTrack.SAMPLING_RATEF * 1000000000L) /** * https://thewolfsound.com/fast-convolution-fft-based-overlap-add-overlap-save-partitioned/ */ override fun thru(inbuf: List, outbuf: List) { -// println("Convolv thru") val t1 = System.nanoTime() + + for (ch in outbuf.indices) { push(inbuf[ch].applyGain(gain), this.inbuf[ch]) - lateinit var u: FloatArray - - - measureDebugTime("audio.convolve") { - val inputFFT = FFT.fft(this.inbuf[ch]) - val Y = inputFFT * convFFT[ch] - val y = FFT.ifftAndGetReal(Y) - u = y.takeLast(BLOCKSIZE).toFloatArray() - } - - - // doesn't work AND slightly slower than the lines above - /*measureDebugTime("audio.convolve") { - // orthodox uneven-partitioning - fillUnevenly(this.inbuf[ch], inputPartd[ch]) - val partY = inputPartd[ch].mapIndexed { i, inputSamples -> - FFT.fft(inputSamples) * convFFTpartd[ch][i] - } - concatParts(partY, targetY) - val y = FFT.ifftAndGetReal(targetY) - u = y.takeLast(BLOCKSIZE).toFloatArray() - }*/ - - - System.arraycopy(u, 0, outbuf[ch], 0, BLOCKSIZE) + val inputFFT = FFT.fft(this.inbuf[ch]) + val Y = inputFFT * convFFT[ch] + val y = FFT.ifftAndGetReal(Y) + System.arraycopy(y, fftLen - BLOCKSIZE, outbuf[ch], 0, BLOCKSIZE) } - val t2 = System.nanoTime() - val ptime = (t2 - t1).toFloat() - val realtime = BLOCKSIZE / TerrarumAudioMixerTrack.SAMPLING_RATEF * 1000000000L + + + val ptime = System.nanoTime() - t1 + setDebugTime("audio.convolve", ptime) processingSpeed = realtime / ptime }