1
1
package io.github.lemcoder.mikrosoundfont.internal
2
2
3
+ import io.github.lemcoder.mikrosoundfont.Channel
4
+ import io.github.lemcoder.mikrosoundfont.SoundFont
3
5
import kotlinx.cinterop.CPointer
4
6
import kotlinx.cinterop.ExperimentalForeignApi
5
- import kotlinx.cinterop.refTo
7
+ import kotlinx.cinterop.memScoped
8
+ import kotlinx.cinterop.readBytes
6
9
import kotlinx.cinterop.reinterpret
7
10
import kotlinx.cinterop.toCValues
8
11
import kotlinx.cinterop.toKString
9
- import io.github.lemcoder.mikrosoundfont.Channel
10
- import io.github.lemcoder.mikrosoundfont.SoundFont
12
+ import platform.posix.malloc
11
13
import tinySoundFont.TSFOutputMode
12
14
import tinySoundFont.tsf_active_voice_count
13
15
import tinySoundFont.tsf_bank_get_presetname
@@ -87,9 +89,11 @@ internal class SoundFontDelegate : SoundFont {
87
89
return withSoundFont {
88
90
val tsfMode = when (outputMode) {
89
91
SoundFont .OutputMode .TSF_STEREO_INTERLEAVED -> TSFOutputMode .TSF_STEREO_INTERLEAVED
90
- SoundFont .OutputMode .TSF_STEREO_UNWEAVED -> TSFOutputMode .TSF_STEREO_UNWEAVED
91
- SoundFont .OutputMode .TSF_MONO -> TSFOutputMode .TSF_MONO
92
+ SoundFont .OutputMode .TSF_STEREO_UNWEAVED -> TSFOutputMode .TSF_STEREO_UNWEAVED
93
+ SoundFont .OutputMode .TSF_MONO -> TSFOutputMode .TSF_MONO
92
94
}
95
+
96
+ tsf_set_output(it.reinterpret(), tsfMode, sampleRate, globalGainDb)
93
97
}
94
98
}
95
99
@@ -149,13 +153,28 @@ internal class SoundFontDelegate : SoundFont {
149
153
150
154
override fun renderFloat (samples : Int , channels : Int , isMixing : Boolean ): FloatArray {
151
155
return withSoundFont {
152
- val buffer = FloatArray (samples * channels)
153
- val flagMixing = if (isMixing) 1 else 0
154
- tsf_render_float(it.reinterpret(), buffer.refTo(0 ), samples, flagMixing)
155
- buffer
156
+ memScoped {
157
+ val buffer = malloc((samples * channels * Float .SIZE_BYTES ).toULong()) ? : return @withSoundFont floatArrayOf()
158
+ val flagMixing = if (isMixing) 1 else 0
159
+ tsf_render_float(it.reinterpret(), buffer.reinterpret(), samples, flagMixing)
160
+
161
+ val bytes = buffer.readBytes(samples * channels * Float .SIZE_BYTES )
162
+
163
+ bytes.toFloatArray()
164
+ }
156
165
}
157
166
}
158
167
159
168
private fun <T > withSoundFont (block : (soundFont: CPointer <* >) -> T ): T =
160
169
this .soundFont.let (block) ? : throw IllegalStateException (" SoundFont not loaded" )
170
+
171
+ private fun ByteArray.toFloatArray (): FloatArray {
172
+ return FloatArray (size / Float .SIZE_BYTES ) { index ->
173
+ val intBits = (this [index * Float .SIZE_BYTES ].toInt() and 0xFF ) or
174
+ ((this [index * Float .SIZE_BYTES + 1 ].toInt() and 0xFF ) shl 8 ) or
175
+ ((this [index * Float .SIZE_BYTES + 2 ].toInt() and 0xFF ) shl 16 ) or
176
+ ((this [index * Float .SIZE_BYTES + 3 ].toInt() and 0xFF ) shl 24 )
177
+ Float .fromBits(intBits)
178
+ }
179
+ }
161
180
}
0 commit comments