diff --git a/.idea/artifacts/TerrarumBuild.xml b/.idea/artifacts/TerrarumBuild.xml
index 15917597f..8deb76422 100644
--- a/.idea/artifacts/TerrarumBuild.xml
+++ b/.idea/artifacts/TerrarumBuild.xml
@@ -117,6 +117,8 @@
+
+
\ No newline at end of file
diff --git a/.idea/libraries/github_wendykierp_JTransforms.xml b/.idea/libraries/github_wendykierp_JTransforms.xml
new file mode 100644
index 000000000..9f56ee19c
--- /dev/null
+++ b/.idea/libraries/github_wendykierp_JTransforms.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TerrarumBuild.iml b/TerrarumBuild.iml
index f8b477537..41e651879 100644
--- a/TerrarumBuild.iml
+++ b/TerrarumBuild.iml
@@ -28,5 +28,6 @@
+
\ No newline at end of file
diff --git a/lib/JLargeArrays-1.5-sources.jar b/lib/JLargeArrays-1.5-sources.jar
new file mode 100644
index 000000000..aba76d48e
--- /dev/null
+++ b/lib/JLargeArrays-1.5-sources.jar
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b22995c404825bd16fc357867d6f0823a173173b8dd03d64306f41066edff127
+size 76637
diff --git a/lib/JLargeArrays-1.5.jar b/lib/JLargeArrays-1.5.jar
new file mode 100644
index 000000000..0965742ea
--- /dev/null
+++ b/lib/JLargeArrays-1.5.jar
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6dca5ab23e1fdb9190a257c04687a9ea19111c36b6ec9478bce6b2a128ca1aeb
+size 232470
diff --git a/lib/JTransforms-3.1-sources.jar b/lib/JTransforms-3.1-sources.jar
new file mode 100644
index 000000000..6cf780aed
--- /dev/null
+++ b/lib/JTransforms-3.1-sources.jar
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4fe7287b6464dd568dbe0cd2bf4082662ff4db28884e7ed9cbba6ca8512d5cc1
+size 269350
diff --git a/lib/JTransforms-3.1.jar b/lib/JTransforms-3.1.jar
new file mode 100644
index 000000000..4cab35df3
--- /dev/null
+++ b/lib/JTransforms-3.1.jar
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d9dffa3e27793040dccb97b054d95267df46e669c396bf1ca4f3b085069bc2d5
+size 1175798
diff --git a/src/net/torvald/terrarum/audio/AudioMixer.kt b/src/net/torvald/terrarum/audio/AudioMixer.kt
index cf579eeb7..15bdf5ecc 100644
--- a/src/net/torvald/terrarum/audio/AudioMixer.kt
+++ b/src/net/torvald/terrarum/audio/AudioMixer.kt
@@ -120,7 +120,7 @@ object AudioMixer: Disposable {
processingExecutor.submitAll(callables)
processingExecutor.join()*/
-
+
val threads = tracks.map { Thread {
if (!it.processor.paused) {
it.processor.run()
diff --git a/src/net/torvald/terrarum/audio/FFT.kt b/src/net/torvald/terrarum/audio/FFT.kt
index 204071495..4be7d5fbd 100644
--- a/src/net/torvald/terrarum/audio/FFT.kt
+++ b/src/net/torvald/terrarum/audio/FFT.kt
@@ -2,18 +2,37 @@ package net.torvald.terrarum.audio
import org.apache.commons.math3.transform.DftNormalization
import org.apache.commons.math3.transform.TransformType
+import org.jtransforms.fft.FloatFFT_1D
+
+
+class ComplexArray(val reim: FloatArray) {
+
+ private val RE0 = 0
+ private val IM0 = 1
+
+ private val RE1 = -1
+ private val IM1 = 0
-class ComplexArray(val res: FloatArray, val ims: FloatArray) {
val indices: IntProgression
get() = 0 until size
val size: Int
- get() = res.size
+ get() = reim.size / 2
operator fun times(other: ComplexArray): ComplexArray {
val l = size
- val re = FloatArray(l) { res[it] * 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 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)
+ 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]
+
+ }
+
+ return ComplexArray(out)
}
}
@@ -25,16 +44,77 @@ class ComplexArray(val res: FloatArray, val ims: FloatArray) {
object FFT {
// org.apache.commons.math3.transform.FastFouriesTransformer.java:370
- fun fft(signal: FloatArray): ComplexArray {
- val dataRI = ComplexArray(signal.copyOf(), FloatArray(signal.size))
- transformInPlace(dataRI, DftNormalization.STANDARD, TransformType.FORWARD)
- return dataRI
+ 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)
+
+ val plan = fftw_plan_dft_1d(signal0.size, signal, result, FFTW_FORWARD, FFTW_ESTIMATE) // wtf sigsegv
+
+ signal0.forEachIndexed { index, fl -> signal.put(index * 2L, fl.toDouble()) }
+
+ fftw_execute(plan)
+
+ val re = FloatArray(signal0.size) { result.get(it * 2L).toFloat() }
+ val im = FloatArray(signal0.size) { result.get(it * 2L + 1).toFloat() }
+
+ val retObj = ComplexArray(re, im)
+
+ fftw_destroy_plan(plan)
+
+ signal.deallocate()
+ result.deallocate()
+
+ return retObj*/
+
+
+ // USING JTRANSFORMS //
+ val signal = FloatArray(signal0.size * 2) { if (it % 2 == 0) signal0[it / 2] else 0f }
+ val fft = FloatFFT_1D(signal0.size.toLong())
+ fft.complexForward(signal)
+ return ComplexArray(signal)
}
// org.apache.commons.math3.transform.FastFouriesTransformer.java:404
- fun ifftAndGetReal(y: ComplexArray): FloatArray {
- transformInPlace(y, DftNormalization.STANDARD, TransformType.INVERSE)
- return y.res
+ 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)
+
+ val plan = fftwf_plan_dft_1d(signal0.size, signal, result, FFTW_BACKWARD, FFTW_ESTIMATE)
+
+ signal0.res.forEachIndexed { index, fl -> signal.put(index * 2L, fl) }
+ signal0.ims.forEachIndexed { index, fl -> signal.put(index * 2L, fl) }
+
+ fftwf_execute(plan)
+
+ val re = FloatArray(signal0.size) { result.get(it * 2L) }
+
+ fftwf_destroy_plan(plan)
+
+ signal.deallocate()
+ result.deallocate()
+
+ 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)
+ return FloatArray(signal0.size) { signal[it * 2] }
}
// org.apache.commons.math3.transform.FastFouriesTransformer.java:214
@@ -54,10 +134,7 @@ object FFT {
* @throws MathIllegalArgumentException if the number of data points is not
* a power of two
*/
- private fun transformInPlace(dataRI: ComplexArray, normalization: DftNormalization, type: TransformType) {
- val dataR = dataRI.res
- val dataI = dataRI.ims
- val n = dataR.size
+ private fun transformInPlace(dataR: FloatArray, dataI: FloatArray, n: Int, normalization: DftNormalization, type: TransformType) {
/*if (n == 1) {
return
@@ -186,7 +263,7 @@ object FFT {
lastLogN0 = logN0
}
- normalizeTransformedData(dataRI, normalization, type)
+ normalizeTransformedData(dataR, dataI, n, normalization, type)
}
@@ -198,12 +275,9 @@ object FFT {
* @param type the type of transform (forward, inverse) which resulted in the specified data
*/
private fun normalizeTransformedData(
- dataRI: ComplexArray,
+ dataR: FloatArray, dataI: FloatArray, n: Int,
normalization: DftNormalization, type: TransformType
) {
- val dataR = dataRI.res
- val dataI = dataRI.ims
- val n = dataR.size
// assert(dataI.size == n)
// when (normalization) {
// DftNormalization.STANDARD ->