Skip to content

Commit

Permalink
Fixed audio generation on Android
Browse files Browse the repository at this point in the history
  • Loading branch information
lemcoder committed Dec 8, 2024
1 parent 7bf63ba commit 526bb7f
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 35 deletions.
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[versions]
lib = "0.1.7"
lib = "0.1.8"

agp = "8.7.3"
kotlin = "2.1.0"
Expand Down
24 changes: 12 additions & 12 deletions midi/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ kotlin {
sourceSets {

commonMain.dependencies {
// implementation(projects.soundfont)
implementation(projects.soundfont)
implementation(libs.kotlinx.io)
}

Expand Down Expand Up @@ -115,15 +115,15 @@ mavenPublishing {

// Sign with default plugin
signing {
useInMemoryPgpKeys(
System.getenv("SIGNING_KEY"),
System.getenv("SIGNING_KEY_PASSWORD")
)
sign(publishing.publications)

// Temporary workaround, see https://github.com/gradle/gradle/issues/26091#issuecomment-1722947958
tasks.withType<AbstractPublishToMaven>().configureEach {
val signingTasks = tasks.withType<Sign>()
mustRunAfter(signingTasks)
}
// useInMemoryPgpKeys(
// System.getenv("SIGNING_KEY"),
// System.getenv("SIGNING_KEY_PASSWORD")
// )
// sign(publishing.publications)
//
// // Temporary workaround, see https://github.com/gradle/gradle/issues/26091#issuecomment-1722947958
// tasks.withType<AbstractPublishToMaven>().configureEach {
// val signingTasks = tasks.withType<Sign>()
// mustRunAfter(signingTasks)
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import io.github.lemcoder.mikrosoundfont.SoundFont
class MidiSequencer(
private val soundFont: SoundFont,
private val sampleRate: Int,
private val channels: Int
) {
private val sampleBlockSize: Int = 512
private val messages = mutableListOf<MidiMessage>()
Expand All @@ -24,16 +25,16 @@ class MidiSequencer(

while (targetTime > currentTime) {
currentTime += (sampleBlockSize * (1000.0 / sampleRate)).toInt()
audioBuffer += soundFont.renderFloat(sampleBlockSize, false)
audioBuffer += soundFont.renderFloat(sampleBlockSize, channels, false)
}
}

return audioBuffer
}

private fun MidiMessage.process() = when (this) {
is MidiVoiceMessage.NoteOff -> soundFont.channels[channel].noteOff(key)
is MidiVoiceMessage.NoteOn -> soundFont.channels[channel].noteOn(key, if (velocity == 0) 0f else 1f)
is MidiVoiceMessage.NoteOff -> soundFont.noteOff(channel, key)
is MidiVoiceMessage.NoteOn -> soundFont.noteOn(channel, key, velocity / 127.0f)
is MidiVoiceMessage.PitchBend -> soundFont.channels[channel].setPitchWheel(pitchBend)
is MidiVoiceMessage.ProgramChange -> soundFont.channels[channel].setPresetNumber(program, channel == 9)
is MidiVoiceMessage.ControlChange -> soundFont.channels[channel].setMidiControl(control, controlValue)
Expand Down
22 changes: 11 additions & 11 deletions soundfont/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,15 @@ mavenPublishing {

// Sign with default plugin
signing {
useInMemoryPgpKeys(
System.getenv("SIGNING_KEY"),
System.getenv("SIGNING_KEY_PASSWORD")
)
sign(publishing.publications)

// Temporary workaround, see https://github.com/gradle/gradle/issues/26091#issuecomment-1722947958
tasks.withType<AbstractPublishToMaven>().configureEach {
val signingTasks = tasks.withType<Sign>()
mustRunAfter(signingTasks)
}
// useInMemoryPgpKeys(
// System.getenv("SIGNING_KEY"),
// System.getenv("SIGNING_KEY_PASSWORD")
// )
// sign(publishing.publications)
//
// // Temporary workaround, see https://github.com/gradle/gradle/issues/26091#issuecomment-1722947958
// tasks.withType<AbstractPublishToMaven>().configureEach {
// val signingTasks = tasks.withType<Sign>()
// mustRunAfter(signingTasks)
// }
}
7 changes: 4 additions & 3 deletions soundfont/src/androidMain/cpp/mikro_sound_font_jni.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ JNIEXPORT void JNICALL Java_io_github_lemcoder_mikrosoundfont_internal_SoundFont
}
}

JNIEXPORT jfloatArray JNICALL Java_io_github_lemcoder_mikrosoundfont_internal_SoundFontDelegate_renderFloat(JNIEnv *env, jobject obj, jint samples, jboolean isMixing) {
JNIEXPORT jfloatArray JNICALL Java_io_github_lemcoder_mikrosoundfont_internal_SoundFontDelegate_renderFloat(JNIEnv *env, jobject obj, jint samples, jint channels, jboolean isMixing) {
if (g_tsf) {
int item_count = samples * 2;
float *buffer = malloc(item_count * sizeof(float) * 2);
int item_count = samples * channels;
float *buffer = malloc(item_count * sizeof(float) * channels);
tsf_render_float(g_tsf, buffer, samples, 0);

jfloatArray output = (*env)->NewFloatArray(env, item_count);
Expand All @@ -100,6 +100,7 @@ JNIEXPORT jfloatArray JNICALL Java_io_github_lemcoder_mikrosoundfont_internal_So

return output;
}

return NULL;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ internal class SoundFontDelegate : SoundFont {
external override fun noteOffAll()
external override fun activeVoiceCount(): Int
external override fun setBankPreset(channel: Int, bank: Int, presetNumber: Int)
external override fun renderFloat(samples: Int, isMixing: Boolean): FloatArray
external override fun renderFloat(samples: Int, channels: Int, isMixing: Boolean): FloatArray
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ interface SoundFont {
* Render output samples in F32 format
* @param isMixing: if false clear the buffer first, otherwise mix into existing data
*/
fun renderFloat(samples: Int, isMixing: Boolean): FloatArray
fun renderFloat(samples: Int, channels: Int, isMixing: Boolean): FloatArray

/**
* Supported output modes by the render methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ internal class SoundFontDelegate : SoundFont {
SoundFont.OutputMode.TSF_STEREO_UNWEAVED -> TSFOutputMode.TSF_STEREO_UNWEAVED
SoundFont.OutputMode.TSF_MONO -> TSFOutputMode.TSF_MONO
}
tsf_set_output(it.reinterpret(), tsfMode, sampleRate, globalGainDb)
}
}

Expand Down Expand Up @@ -148,9 +147,9 @@ internal class SoundFontDelegate : SoundFont {
}
}

override fun renderFloat(samples: Int, isMixing: Boolean): FloatArray {
override fun renderFloat(samples: Int, channels: Int, isMixing: Boolean): FloatArray {
return withSoundFont {
val buffer = FloatArray(samples * 2)
val buffer = FloatArray(samples * channels)
val flagMixing = if (isMixing) 1 else 0
tsf_render_float(it.reinterpret(), buffer.refTo(0), samples, flagMixing)
buffer
Expand Down

0 comments on commit 526bb7f

Please sign in to comment.