mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
slightly faster fft
This commit is contained in:
2
.idea/artifacts/TerrarumBuild.xml
generated
2
.idea/artifacts/TerrarumBuild.xml
generated
@@ -117,6 +117,8 @@
|
|||||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/junit-platform-launcher-1.0.0.jar" path-in-jar="/" />
|
<element id="extracted-dir" path="$PROJECT_DIR$/lib/junit-platform-launcher-1.0.0.jar" path-in-jar="/" />
|
||||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/surefire-api-2.19.1.jar" path-in-jar="/" />
|
<element id="extracted-dir" path="$PROJECT_DIR$/lib/surefire-api-2.19.1.jar" path-in-jar="/" />
|
||||||
<element id="extracted-dir" path="$PROJECT_DIR$/lib/common-java5-2.19.1.jar" path-in-jar="/" />
|
<element id="extracted-dir" path="$PROJECT_DIR$/lib/common-java5-2.19.1.jar" path-in-jar="/" />
|
||||||
|
<element id="extracted-dir" path="$PROJECT_DIR$/lib/JTransforms-3.1.jar" path-in-jar="/" />
|
||||||
|
<element id="extracted-dir" path="$PROJECT_DIR$/lib/JLargeArrays-1.5.jar" path-in-jar="/" />
|
||||||
</root>
|
</root>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
16
.idea/libraries/github_wendykierp_JTransforms.xml
generated
Normal file
16
.idea/libraries/github_wendykierp_JTransforms.xml
generated
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="github.wendykierp.JTransforms" type="repository">
|
||||||
|
<properties maven-id="com.github.wendykierp:JTransforms:3.1" />
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/JTransforms-3.1.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/commons-math3-3.5.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/JLargeArrays-1.5.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/JTransforms-3.1-sources.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/commons-math3-3.5-sources.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/JLargeArrays-1.5-sources.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</component>
|
||||||
@@ -28,5 +28,6 @@
|
|||||||
<orderEntry type="library" name="apache.commons.math3" level="project" />
|
<orderEntry type="library" name="apache.commons.math3" level="project" />
|
||||||
<orderEntry type="library" name="jetbrains.kotlinx.coroutines.core" level="project" />
|
<orderEntry type="library" name="jetbrains.kotlinx.coroutines.core" level="project" />
|
||||||
<orderEntry type="library" name="github.psambit9791.jdsp" level="project" />
|
<orderEntry type="library" name="github.psambit9791.jdsp" level="project" />
|
||||||
|
<orderEntry type="library" name="github.wendykierp.JTransforms" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
BIN
lib/JLargeArrays-1.5-sources.jar
LFS
Normal file
BIN
lib/JLargeArrays-1.5-sources.jar
LFS
Normal file
Binary file not shown.
BIN
lib/JLargeArrays-1.5.jar
LFS
Normal file
BIN
lib/JLargeArrays-1.5.jar
LFS
Normal file
Binary file not shown.
BIN
lib/JTransforms-3.1-sources.jar
LFS
Normal file
BIN
lib/JTransforms-3.1-sources.jar
LFS
Normal file
Binary file not shown.
BIN
lib/JTransforms-3.1.jar
LFS
Normal file
BIN
lib/JTransforms-3.1.jar
LFS
Normal file
Binary file not shown.
@@ -120,7 +120,7 @@ object AudioMixer: Disposable {
|
|||||||
processingExecutor.submitAll(callables)
|
processingExecutor.submitAll(callables)
|
||||||
processingExecutor.join()*/
|
processingExecutor.join()*/
|
||||||
|
|
||||||
|
|
||||||
val threads = tracks.map { Thread {
|
val threads = tracks.map { Thread {
|
||||||
if (!it.processor.paused) {
|
if (!it.processor.paused) {
|
||||||
it.processor.run()
|
it.processor.run()
|
||||||
|
|||||||
@@ -2,18 +2,37 @@ package net.torvald.terrarum.audio
|
|||||||
|
|
||||||
import org.apache.commons.math3.transform.DftNormalization
|
import org.apache.commons.math3.transform.DftNormalization
|
||||||
import org.apache.commons.math3.transform.TransformType
|
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
|
val indices: IntProgression
|
||||||
get() = 0 until size
|
get() = 0 until size
|
||||||
val size: Int
|
val size: Int
|
||||||
get() = res.size
|
get() = reim.size / 2
|
||||||
|
|
||||||
operator fun times(other: ComplexArray): ComplexArray {
|
operator fun times(other: ComplexArray): ComplexArray {
|
||||||
val l = size
|
val l = size
|
||||||
val re = FloatArray(l) { res[it] * other.res[it] - ims[it] * other.ims[it] }
|
// 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] }
|
// val im = FloatArray(l) { res[it] * other.ims[it] + ims[it] * other.res[it] }
|
||||||
return ComplexArray(re, im)
|
// 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 {
|
object FFT {
|
||||||
|
|
||||||
// org.apache.commons.math3.transform.FastFouriesTransformer.java:370
|
// org.apache.commons.math3.transform.FastFouriesTransformer.java:370
|
||||||
fun fft(signal: FloatArray): ComplexArray {
|
fun fft(signal0: FloatArray): ComplexArray {
|
||||||
val dataRI = ComplexArray(signal.copyOf(), FloatArray(signal.size))
|
// val dataRI = ComplexArray(signal0.copyOf(), FloatArray(signal0.size))
|
||||||
transformInPlace(dataRI, DftNormalization.STANDARD, TransformType.FORWARD)
|
// transformInPlace(dataRI, DftNormalization.STANDARD, TransformType.FORWARD)
|
||||||
return dataRI
|
// 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
|
// org.apache.commons.math3.transform.FastFouriesTransformer.java:404
|
||||||
fun ifftAndGetReal(y: ComplexArray): FloatArray {
|
fun ifftAndGetReal(signal0: ComplexArray): FloatArray {
|
||||||
transformInPlace(y, DftNormalization.STANDARD, TransformType.INVERSE)
|
// transformInPlace(signal0, DftNormalization.STANDARD, TransformType.INVERSE)
|
||||||
return y.res
|
// 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
|
// org.apache.commons.math3.transform.FastFouriesTransformer.java:214
|
||||||
@@ -54,10 +134,7 @@ object FFT {
|
|||||||
* @throws MathIllegalArgumentException if the number of data points is not
|
* @throws MathIllegalArgumentException if the number of data points is not
|
||||||
* a power of two
|
* a power of two
|
||||||
*/
|
*/
|
||||||
private fun transformInPlace(dataRI: ComplexArray, normalization: DftNormalization, type: TransformType) {
|
private fun transformInPlace(dataR: FloatArray, dataI: FloatArray, n: Int, normalization: DftNormalization, type: TransformType) {
|
||||||
val dataR = dataRI.res
|
|
||||||
val dataI = dataRI.ims
|
|
||||||
val n = dataR.size
|
|
||||||
|
|
||||||
/*if (n == 1) {
|
/*if (n == 1) {
|
||||||
return
|
return
|
||||||
@@ -186,7 +263,7 @@ object FFT {
|
|||||||
lastLogN0 = logN0
|
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
|
* @param type the type of transform (forward, inverse) which resulted in the specified data
|
||||||
*/
|
*/
|
||||||
private fun normalizeTransformedData(
|
private fun normalizeTransformedData(
|
||||||
dataRI: ComplexArray,
|
dataR: FloatArray, dataI: FloatArray, n: Int,
|
||||||
normalization: DftNormalization, type: TransformType
|
normalization: DftNormalization, type: TransformType
|
||||||
) {
|
) {
|
||||||
val dataR = dataRI.res
|
|
||||||
val dataI = dataRI.ims
|
|
||||||
val n = dataR.size
|
|
||||||
// assert(dataI.size == n)
|
// assert(dataI.size == n)
|
||||||
// when (normalization) {
|
// when (normalization) {
|
||||||
// DftNormalization.STANDARD ->
|
// DftNormalization.STANDARD ->
|
||||||
|
|||||||
Reference in New Issue
Block a user