mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-13 12:04:06 +09:00
yet another convolver optimisation
This commit is contained in:
@@ -146,6 +146,11 @@ object FFT: Disposable {
|
|||||||
ffts[signal0.size]!!.complexForward(signal0.reim)
|
ffts[signal0.size]!!.complexForward(signal0.reim)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun fftInto(signal0: ComplexArray, out: ComplexArray) {
|
||||||
|
System.arraycopy(signal0.reim, 0, out.reim, 0, signal0.reim.size)
|
||||||
|
ffts[signal0.size]!!.complexForward(out.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] }
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() {
|
|||||||
|
|
||||||
val fftLen: Int
|
val fftLen: Int
|
||||||
private val convFFT: Array<ComplexArray>
|
private val convFFT: Array<ComplexArray>
|
||||||
private val convFFTpartd: Array<Array<ComplexArray>> // index: Channel, partition, frequencies
|
private val inbuf: Array<ComplexArray>
|
||||||
private val inputPartd: Array<Array<FloatArray>> // index: Channel, partition, frequencies
|
|
||||||
private val inbuf: Array<FloatArray>
|
|
||||||
|
|
||||||
private val BLOCKSIZE = TerrarumAudioMixerTrack.BUFFER_SIZE / 4
|
private val BLOCKSIZE = TerrarumAudioMixerTrack.BUFFER_SIZE / 4
|
||||||
|
|
||||||
@@ -33,7 +31,7 @@ class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() {
|
|||||||
println("IR '${ir.path}' Sample Count = $sampleCount; FFT Length = $fftLen")
|
println("IR '${ir.path}' Sample Count = $sampleCount; FFT Length = $fftLen")
|
||||||
|
|
||||||
val conv = Array(2) { FloatArray(fftLen) }
|
val conv = Array(2) { FloatArray(fftLen) }
|
||||||
inbuf = Array(2) { FloatArray(fftLen) }
|
inbuf = Array(2) { ComplexArray(FloatArray(fftLen * 2)) }
|
||||||
|
|
||||||
ir.inputStream().let {
|
ir.inputStream().let {
|
||||||
for (i in 0 until sampleCount) {
|
for (i in 0 until sampleCount) {
|
||||||
@@ -70,42 +68,6 @@ class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() {
|
|||||||
}
|
}
|
||||||
partSizes = master0.toIntArray()
|
partSizes = master0.toIntArray()
|
||||||
partOffsets = master0.toIntArray().also { it[0] = 0 }
|
partOffsets = master0.toIntArray().also { it[0] = 0 }
|
||||||
|
|
||||||
|
|
||||||
convFFTpartd = Array(2) {
|
|
||||||
Array(partSizes.size) {
|
|
||||||
ComplexArray(FloatArray(2*partSizes[it]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inputPartd = Array(2) {
|
|
||||||
Array(partSizes.size) {
|
|
||||||
FloatArray(partSizes[it])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fillUnevenly(convFFT[0], convFFTpartd[0])
|
|
||||||
fillUnevenly(convFFT[1], convFFTpartd[1])
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun fillUnevenly(source: ComplexArray, dest: Array<ComplexArray>) {
|
|
||||||
for (i in partSizes.indices) {
|
|
||||||
val len = 2*partSizes[i]
|
|
||||||
val offset = 2*partOffsets[i]
|
|
||||||
System.arraycopy(source.reim, offset, dest[i].reim, 0, len)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private fun fillUnevenly(source: FloatArray, dest: Array<FloatArray>) {
|
|
||||||
for (i in partSizes.indices) {
|
|
||||||
val len = partSizes[i]
|
|
||||||
val offset = partOffsets[i]
|
|
||||||
System.arraycopy(source, offset, dest[i], 0, len)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private fun concatParts(source: List<ComplexArray>, dest: ComplexArray) {
|
|
||||||
for (i in partSizes.indices) {
|
|
||||||
val len = 2*partSizes[i]
|
|
||||||
val offset = 2*partOffsets[i]
|
|
||||||
System.arraycopy(source[i].reim, 0, dest.reim, offset, len)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val realtime = (BLOCKSIZE / TerrarumAudioMixerTrack.SAMPLING_RATEF * 1000000000L)
|
private val realtime = (BLOCKSIZE / TerrarumAudioMixerTrack.SAMPLING_RATEF * 1000000000L)
|
||||||
@@ -122,14 +84,9 @@ 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(gain, inbuf[ch], this.inbuf[ch])
|
||||||
|
|
||||||
for (i in 0 until fftLen) {
|
FFT.fftInto(this.inbuf[ch], fftIn)
|
||||||
fftIn.reim[i * 2] = this.inbuf[ch][i]
|
|
||||||
fftIn.reim[i * 2 + 1] = 0f
|
|
||||||
}
|
|
||||||
|
|
||||||
FFT.fft(fftIn)
|
|
||||||
fftIn.mult(convFFT[ch], fftMult)
|
fftIn.mult(convFFT[ch], fftMult)
|
||||||
FFT.ifftAndGetReal(fftMult, fftOut)
|
FFT.ifftAndGetReal(fftMult, fftOut)
|
||||||
System.arraycopy(fftOut, fftLen - BLOCKSIZE, outbuf[ch], 0, BLOCKSIZE)
|
System.arraycopy(fftOut, fftLen - BLOCKSIZE, outbuf[ch], 0, BLOCKSIZE)
|
||||||
@@ -141,4 +98,14 @@ class Convolv(ir: File, val gain: Float = 1f / 256f): TerrarumAudioFilter() {
|
|||||||
processingSpeed = realtime / ptime
|
processingSpeed = realtime / ptime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun push(gain: Float, samples: FloatArray, buf: ComplexArray) {
|
||||||
|
System.arraycopy(buf.reim, samples.size * 2, buf.reim, 0, buf.reim.size - samples.size * 2)
|
||||||
|
val baseI = buf.reim.size - samples.size * 2
|
||||||
|
samples.forEachIndexed { index, fl ->
|
||||||
|
buf.reim[baseI + index * 2 + 0] = fl * gain
|
||||||
|
buf.reim[baseI + index * 2 + 1] = 0f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user