mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-10 02:24:05 +09:00
the correct way to convolve a stereo audio
This commit is contained in:
@@ -6,7 +6,7 @@ import net.torvald.terrarum.audio.*
|
|||||||
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE
|
import net.torvald.terrarum.audio.TerrarumAudioMixerTrack.Companion.AUDIO_BUFFER_SIZE
|
||||||
import java.io.File
|
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
|
val fftLen: Int
|
||||||
private val convFFT: Array<ComplexArray>
|
private val convFFT: Array<ComplexArray>
|
||||||
@@ -72,26 +72,40 @@ class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() {
|
|||||||
private val realtime = (BLOCKSIZE / TerrarumAudioMixerTrack.SAMPLING_RATEF * 1000000000L)
|
private val realtime = (BLOCKSIZE / TerrarumAudioMixerTrack.SAMPLING_RATEF * 1000000000L)
|
||||||
private val fftIn = ComplexArray(FloatArray(fftLen * 2))
|
private val fftIn = ComplexArray(FloatArray(fftLen * 2))
|
||||||
private val fftMult = 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/
|
* https://thewolfsound.com/fast-convolution-fft-based-overlap-add-overlap-save-partitioned/
|
||||||
*/
|
*/
|
||||||
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
|
override fun thru(inbuf: List<FloatArray>, outbuf: List<FloatArray>) {
|
||||||
|
|
||||||
val t1 = System.nanoTime()
|
val t1 = System.nanoTime()
|
||||||
|
|
||||||
|
|
||||||
for (ch in outbuf.indices) {
|
|
||||||
push(gain, inbuf[ch], this.inbuf[ch])
|
|
||||||
|
|
||||||
FFT.fftInto(this.inbuf[ch], fftIn)
|
push(gain, inbuf[0], this.inbuf[0])
|
||||||
fftIn.mult(convFFT[ch], fftMult)
|
push(gain, inbuf[1], this.inbuf[1])
|
||||||
FFT.ifftAndGetReal(fftMult, fftOut)
|
|
||||||
System.arraycopy(fftOut, fftLen - BLOCKSIZE, outbuf[ch], 0, BLOCKSIZE)
|
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
|
val ptime = System.nanoTime() - t1
|
||||||
setDebugTime("audio.convolve", ptime)
|
setDebugTime("audio.convolve", ptime)
|
||||||
processingSpeed = realtime / ptime
|
processingSpeed = realtime / ptime
|
||||||
|
|||||||
Reference in New Issue
Block a user