diff --git a/.idea/libraries/bytedeco_fftw.xml b/.idea/libraries/bytedeco_fftw.xml
new file mode 100644
index 000000000..5d28fc619
--- /dev/null
+++ b/.idea/libraries/bytedeco_fftw.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/bytedeco_fftw_platform.xml b/.idea/libraries/bytedeco_fftw_platform.xml
new file mode 100644
index 000000000..dec9cdbeb
--- /dev/null
+++ b/.idea/libraries/bytedeco_fftw_platform.xml
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/net/torvald/terrarum/audio/AudioMixer.kt b/src/net/torvald/terrarum/audio/AudioMixer.kt
index db1df039e..612fbad31 100644
--- a/src/net/torvald/terrarum/audio/AudioMixer.kt
+++ b/src/net/torvald/terrarum/audio/AudioMixer.kt
@@ -129,19 +129,6 @@ object AudioMixer: Disposable {
}
catch (_: InterruptedException) {}
catch (e: Throwable) { e.printStackTrace() }
-
-
- /*processingSubthreads = tracks.map { Thread {
- if (!it.processor.paused) {
- it.processor.run()
- }
- }.also { it.priority = MAX_PRIORITY } }
-
- try {
- processingSubthreads.forEach { it.start() }
- processingSubthreads.forEach { it.join() }
- }
- catch (e: InterruptedException) {}*/
}
while (processing && !masterTrack.pcmQueue.isEmpty) {
diff --git a/src/net/torvald/terrarum/audio/FFT.kt b/src/net/torvald/terrarum/audio/FFT.kt
index 4be7d5fbd..b195cafda 100644
--- a/src/net/torvald/terrarum/audio/FFT.kt
+++ b/src/net/torvald/terrarum/audio/FFT.kt
@@ -1,8 +1,14 @@
package net.torvald.terrarum.audio
+import com.badlogic.gdx.utils.Disposable
+import net.torvald.terrarum.App
+import net.torvald.terrarum.lock
import org.apache.commons.math3.transform.DftNormalization
import org.apache.commons.math3.transform.TransformType
+import org.bytedeco.fftw.global.fftw3.*
+import org.bytedeco.javacpp.Loader
import org.jtransforms.fft.FloatFFT_1D
+import java.util.concurrent.locks.ReentrantLock
class ComplexArray(val reim: FloatArray) {
@@ -41,36 +47,56 @@ class ComplexArray(val reim: FloatArray) {
*
* Created by minjaesong on 2023-11-25.
*/
-object FFT {
+object FFT: Disposable {
+
+ init {
+ Loader.load(org.bytedeco.fftw.global.fftw3::class.java)
+
+ App.disposables.add(this)
+ }
+
+ private val reLock = ReentrantLock(true)
+
+ private fun getForwardPlan(n: Int, inn: FloatArray, out: FloatArray): fftwf_plan {
+ return fftwf_plan_dft_1d(n, inn, out, FFTW_FORWARD, FFTW_ESTIMATE)
+ }
+ private fun getBackwardPlan(n: Int, inn: FloatArray, out: FloatArray): fftwf_plan {
+ return fftwf_plan_dft_1d(n, inn, out, FFTW_BACKWARD, FFTW_ESTIMATE)
+ }
+ private fun destroyPlan(plan: fftwf_plan) {
+ fftwf_destroy_plan(plan)
+ }
+
+ override fun dispose() {
+ }
// org.apache.commons.math3.transform.FastFouriesTransformer.java:370
- fun fft(signal0: FloatArray): ComplexArray {
+ @Synchronized fun fft(signal0: FloatArray): ComplexArray {
// val dataRI = ComplexArray(signal0.copyOf(), FloatArray(signal0.size))
// transformInPlace(dataRI, DftNormalization.STANDARD, TransformType.FORWARD)
// return dataRI
// USING FFTW //
- /*Loader.load(fftw3::class.java)
- val signal = DoublePointer(2L * signal0.size)
- val result = DoublePointer(2L * signal0.size)
+ /*lateinit var retObj: ComplexArray
+ reLock.lock {
+ fftw_init_threads()
- val plan = fftw_plan_dft_1d(signal0.size, signal, result, FFTW_FORWARD, FFTW_ESTIMATE) // wtf sigsegv
+ val signal = FloatArray(2 * signal0.size)
+ val result = FloatArray(2 * signal0.size)
- signal0.forEachIndexed { index, fl -> signal.put(index * 2L, fl.toDouble()) }
+ val plan = getForwardPlan(signal0.size, signal, result)
- fftw_execute(plan)
+ signal0.forEachIndexed { index, fl -> signal[index * 2] = fl }
- val re = FloatArray(signal0.size) { result.get(it * 2L).toFloat() }
- val im = FloatArray(signal0.size) { result.get(it * 2L + 1).toFloat() }
+ fftwf_execute(plan)
- val retObj = ComplexArray(re, im)
+ retObj = ComplexArray(result)
- fftw_destroy_plan(plan)
-
- signal.deallocate()
- result.deallocate()
+ destroyPlan(plan)
+ fftwf_cleanup_threads()
+ }
return retObj*/
@@ -82,35 +108,33 @@ object FFT {
}
// org.apache.commons.math3.transform.FastFouriesTransformer.java:404
- fun ifftAndGetReal(signal0: ComplexArray): FloatArray {
+ @Synchronized fun ifftAndGetReal(signal0: ComplexArray): FloatArray {
// transformInPlace(signal0, DftNormalization.STANDARD, TransformType.INVERSE)
// return signal0.res
// USING FFTW //
- /*Loader.load(fftw3::class.java)
- val signal = FloatPointer(2L * signal0.size)
- val result = FloatPointer(2L * signal0.size)
+ /*lateinit var re: FloatArray
+ reLock.lock {
+ fftw_init_threads()
- val plan = fftwf_plan_dft_1d(signal0.size, signal, result, FFTW_BACKWARD, FFTW_ESTIMATE)
+ val signal = signal0.reim
+ val result = FloatArray(2 * signal0.size)
- signal0.res.forEachIndexed { index, fl -> signal.put(index * 2L, fl) }
- signal0.ims.forEachIndexed { index, fl -> signal.put(index * 2L, fl) }
+ val plan = getBackwardPlan(signal0.size, signal, result)
- fftwf_execute(plan)
+ fftwf_execute(plan)
- val re = FloatArray(signal0.size) { result.get(it * 2L) }
+ re = FloatArray(signal0.size) { result[it * 2] }
- fftwf_destroy_plan(plan)
-
- signal.deallocate()
- result.deallocate()
+ destroyPlan(plan)
+ fftwf_cleanup_threads()
+ }
return re*/
// USING JTRANSFORMS //
-// val signal = FloatArray(signal0.size * 2) { if (it % 2 == 0) signal0.res[it / 2] else signal0.ims[it / 2] }
val signal = signal0.reim
val fft = FloatFFT_1D(signal0.size.toLong())
fft.complexInverse(signal, true)