mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
more subtle optimisations
This commit is contained in:
@@ -12,6 +12,7 @@ private val IM0 = 1
|
||||
private val RE1 = -1
|
||||
private val IM1 = 0
|
||||
|
||||
private val mulBuf = FloatArray(2)
|
||||
@JvmInline value class ComplexArray(val reim: FloatArray) {
|
||||
|
||||
|
||||
@@ -21,12 +22,7 @@ private val IM1 = 0
|
||||
get() = reim.size / 2
|
||||
|
||||
operator fun times(other: ComplexArray): ComplexArray {
|
||||
val l = size
|
||||
// val re = FloatArray(l) { res[2*it+RE] * other.res[it] - ims[it] * other.ims[it] }
|
||||
// val im = FloatArray(l) { res[it] * other.ims[it] + ims[it] * other.res[it] }
|
||||
// return ComplexArray(re, im)
|
||||
|
||||
val out = FloatArray(l * 2) {
|
||||
val out = FloatArray(size * 2) {
|
||||
if (it % 2 == 0)
|
||||
reim[it+RE0] * other.reim[it+RE0] - reim[it+IM0] * other.reim[it+IM0]
|
||||
else
|
||||
@@ -37,6 +33,32 @@ private val IM1 = 0
|
||||
return ComplexArray(out)
|
||||
}
|
||||
|
||||
fun mult(other: ComplexArray, out: ComplexArray) {
|
||||
for (it in 0 until size * 2) {
|
||||
out.reim[it] =
|
||||
if (it % 2 == 0)
|
||||
reim[it+RE0] * other.reim[it+RE0] - reim[it+IM0] * other.reim[it+IM0]
|
||||
else
|
||||
reim[it+RE1] *other.reim[it+IM1] + reim[it+IM1] * other.reim[it+RE1]
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// this is actually slower that having a separate array for mult results
|
||||
/*fun inlineMult(other: ComplexArray) {
|
||||
for (it in 0 until size * 2) {
|
||||
mulBuf[it % 2] = if (it % 2 == 0)
|
||||
reim[it+RE0] * other.reim[it+RE0] - reim[it+IM0] * other.reim[it+IM0]
|
||||
else
|
||||
reim[it+RE1] *other.reim[it+IM1] + reim[it+IM1] * other.reim[it+RE1]
|
||||
|
||||
if (it % 2 == 1) {
|
||||
reim[it+RE1] = mulBuf[0]
|
||||
reim[it+IM1] = mulBuf[1]
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
fun getReal(): FloatArray {
|
||||
return FloatArray(size) { reim[it * 2] }
|
||||
}
|
||||
@@ -120,6 +142,10 @@ object FFT: Disposable {
|
||||
return ComplexArray(signal)
|
||||
}
|
||||
|
||||
fun fft(signal0: ComplexArray) {
|
||||
ffts[signal0.size]!!.complexForward(signal0.reim)
|
||||
}
|
||||
|
||||
// org.apache.commons.math3.transform.FastFouriesTransformer.java:404
|
||||
fun ifftAndGetReal(signal0: ComplexArray): FloatArray {
|
||||
// val re = FloatArray(signal0.size) { signal0.reim[it * 2] }
|
||||
|
||||
@@ -109,6 +109,10 @@ 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)
|
||||
|
||||
/**
|
||||
* https://thewolfsound.com/fast-convolution-fft-based-overlap-add-overlap-save-partitioned/
|
||||
*/
|
||||
@@ -119,10 +123,16 @@ class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() {
|
||||
|
||||
for (ch in outbuf.indices) {
|
||||
push(inbuf[ch].applyGain(gain), this.inbuf[ch])
|
||||
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)
|
||||
|
||||
for (i in 0 until fftLen) {
|
||||
fftIn.reim[i * 2] = this.inbuf[ch][i]
|
||||
fftIn.reim[i * 2 + 1] = 0f
|
||||
}
|
||||
|
||||
FFT.fft(fftIn)
|
||||
fftIn.mult(convFFT[ch], fftMult)
|
||||
FFT.ifftAndGetReal(fftMult, fftOut)
|
||||
System.arraycopy(fftOut, fftLen - BLOCKSIZE, outbuf[ch], 0, BLOCKSIZE)
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user