mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-12 19:44:05 +09:00
more subtle optimisations
This commit is contained in:
@@ -12,6 +12,7 @@ private val IM0 = 1
|
|||||||
private val RE1 = -1
|
private val RE1 = -1
|
||||||
private val IM1 = 0
|
private val IM1 = 0
|
||||||
|
|
||||||
|
private val mulBuf = FloatArray(2)
|
||||||
@JvmInline value class ComplexArray(val reim: FloatArray) {
|
@JvmInline value class ComplexArray(val reim: FloatArray) {
|
||||||
|
|
||||||
|
|
||||||
@@ -21,12 +22,7 @@ private val IM1 = 0
|
|||||||
get() = reim.size / 2
|
get() = reim.size / 2
|
||||||
|
|
||||||
operator fun times(other: ComplexArray): ComplexArray {
|
operator fun times(other: ComplexArray): ComplexArray {
|
||||||
val l = size
|
val out = FloatArray(size * 2) {
|
||||||
// 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) {
|
|
||||||
if (it % 2 == 0)
|
if (it % 2 == 0)
|
||||||
reim[it+RE0] * other.reim[it+RE0] - reim[it+IM0] * other.reim[it+IM0]
|
reim[it+RE0] * other.reim[it+RE0] - reim[it+IM0] * other.reim[it+IM0]
|
||||||
else
|
else
|
||||||
@@ -37,6 +33,32 @@ private val IM1 = 0
|
|||||||
return ComplexArray(out)
|
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 {
|
fun getReal(): FloatArray {
|
||||||
return FloatArray(size) { reim[it * 2] }
|
return FloatArray(size) { reim[it * 2] }
|
||||||
}
|
}
|
||||||
@@ -120,6 +142,10 @@ object FFT: Disposable {
|
|||||||
return ComplexArray(signal)
|
return ComplexArray(signal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun fft(signal0: ComplexArray) {
|
||||||
|
ffts[signal0.size]!!.complexForward(signal0.reim)
|
||||||
|
}
|
||||||
|
|
||||||
// org.apache.commons.math3.transform.FastFouriesTransformer.java:404
|
// org.apache.commons.math3.transform.FastFouriesTransformer.java:404
|
||||||
fun ifftAndGetReal(signal0: ComplexArray): FloatArray {
|
fun ifftAndGetReal(signal0: ComplexArray): FloatArray {
|
||||||
// val re = FloatArray(signal0.size) { signal0.reim[it * 2] }
|
// 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 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/
|
* 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) {
|
for (ch in outbuf.indices) {
|
||||||
push(inbuf[ch].applyGain(gain), this.inbuf[ch])
|
push(inbuf[ch].applyGain(gain), this.inbuf[ch])
|
||||||
val inputFFT = FFT.fft(this.inbuf[ch])
|
|
||||||
val Y = inputFFT * convFFT[ch]
|
for (i in 0 until fftLen) {
|
||||||
val y = FFT.ifftAndGetReal(Y)
|
fftIn.reim[i * 2] = this.inbuf[ch][i]
|
||||||
System.arraycopy(y, fftLen - BLOCKSIZE, outbuf[ch], 0, BLOCKSIZE)
|
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