Skip to content

Commit 01c7607

Browse files
committed
Added android target (no tests)
1 parent 031b928 commit 01c7607

File tree

17 files changed

+365
-33
lines changed

17 files changed

+365
-33
lines changed

app/src/nativeMain/kotlin/Main.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ fun main(args: Array<String>) {
8989
}
9090
}
9191
}
92-
// val file = Buffer()
93-
//
94-
// file.write(bytes, 0, bytes.size)
95-
//
96-
// SystemFileSystem.sink(Path("./output.wav")).write(file, file.size)
97-
//
98-
// sleep(5u)
92+
val file = Buffer()
93+
94+
file.write(bytes, 0, bytes.size)
95+
96+
SystemFileSystem.sink(Path("./output.wav")).write(file, file.size)
97+
98+
sleep(5u)
9999
}

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
plugins {
22
alias(libs.plugins.kotlinMultiplatform).apply(false)
3+
alias(libs.plugins.androidLibrary).apply(false)
34
}

core/build.gradle.kts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,21 @@ import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
22

33
plugins {
44
alias(libs.plugins.kotlinMultiplatform)
5+
alias(libs.plugins.androidLibrary)
6+
}
7+
8+
android {
9+
defaultConfig {
10+
compileSdk = libs.versions.android.compileSdk.get().toInt()
11+
minSdk = libs.versions.android.minSdk.get().toInt()
12+
}
513
}
614

715
kotlin {
16+
androidTarget().apply {
17+
publishAllLibraryVariants()
18+
}
19+
820
mingwX64()
921
linuxX64()
1022

@@ -18,7 +30,6 @@ kotlin {
1830
commonMain.dependencies {
1931
implementation(libs.coroutines.core)
2032
implementation(projects.tinySoundFont)
21-
implementation(libs.mikroaudio)
2233
}
2334

2435
commonTest.dependencies {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package pl.lemanski.pandamidi.io.wav
2+
3+
actual fun WavFileHeader.toByteArray(): ByteArray {
4+
TODO("Not yet implemented")
5+
}

gradle/libs.versions.toml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
[versions]
2+
agp = "8.7.0"
23
kotlin = "2.0.0"
34
coroutines = "1.9.0-RC"
4-
pandaMidi = "0.0.1"
55
kotlinxIo = "0.5.1"
6-
mikroaudio = "0.0.1"
6+
mikroaudio = "0.0.2"
7+
8+
android-compileSdk = "34"
9+
android-minSdk = "24"
710

811
[libraries]
912
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
1013
kotlinx-io = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.ref = "kotlinxIo" }
1114
coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
12-
mikroaudio = { module = "pl.lemanski.mikroaudio:core", version.ref = "mikroaudio" }
1315

1416
[plugins]
15-
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
17+
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
18+
androidLibrary = { id = "com.android.library", version.ref = "agp" }
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Tue Jun 11 22:41:30 CEST 2024
1+
#Sat Oct 05 16:28:08 CEST 2024
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
4-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
4+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
55
zipStoreBase=GRADLE_USER_HOME
66
zipStorePath=wrapper/dists

tinySoundFont/build.gradle.kts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,33 @@ import pl.lemanski.plugin.KonanPluginExtension
55

66
plugins {
77
alias(libs.plugins.kotlinMultiplatform)
8+
alias(libs.plugins.androidLibrary)
89
id("maven-publish")
910
id("pl.lemanski.plugin")
1011
}
1112

1213
group = "pl.lemanski.tinySoundFont"
1314
version = "0.0.1"
1415

16+
android {
17+
namespace = "pl.lemanski.tinySoundFont"
18+
defaultConfig {
19+
compileSdk = libs.versions.android.compileSdk.get().toInt()
20+
minSdk = libs.versions.android.minSdk.get().toInt()
21+
}
22+
23+
externalNativeBuild {
24+
cmake {
25+
path = file("src/androidMain/cpp/CMakeLists.txt")
26+
}
27+
}
28+
}
29+
1530
kotlin {
31+
androidTarget().apply {
32+
publishAllLibraryVariants()
33+
}
34+
1635
listOf(
1736
mingwX64(),
1837
linuxX64()
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
cmake_minimum_required(VERSION 3.10)
2+
3+
# Project name
4+
project(core_native_lib)
5+
6+
# Add the shared native library
7+
add_library(
8+
tinySoundFontJNI # Name of the native library
9+
SHARED
10+
${CMAKE_SOURCE_DIR}/mikromidi.c
11+
)
12+
13+
# Include the shared header files from the project root's 'native/include' directory
14+
include_directories(
15+
${CMAKE_SOURCE_DIR}/../../../../native/src
16+
)
17+
18+
# Find necessary libraries, e.g., the Android log library
19+
find_library(
20+
log-lib
21+
log
22+
)
23+
24+
# Link your native library against Android log library (or other required libraries)
25+
target_link_libraries(
26+
tinySoundFontJNI
27+
${log-lib}
28+
)
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
#include <jni.h>
2+
3+
#define TSF_IMPLEMENTATION
4+
5+
#include "tsf.h"
6+
7+
// Declare global tsf (TinySoundFont) object
8+
static struct tsf *g_tsf = NULL;
9+
10+
// Function to reset the SoundFont (stop all notes, reset parameters)
11+
JNIEXPORT void JNICALL Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_reset(JNIEnv *env, jobject obj) {
12+
if (g_tsf) {
13+
tsf_reset(g_tsf);
14+
}
15+
}
16+
17+
// Get preset index
18+
JNIEXPORT jint JNICALL Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_getPresetIndex(JNIEnv *env, jobject obj, jint bank, jint presetNumber) {
19+
if (g_tsf) {
20+
return tsf_get_presetindex(g_tsf, bank, presetNumber);
21+
}
22+
return -1;
23+
}
24+
25+
// Get number of presets
26+
JNIEXPORT jint JNICALL Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_getPresetsCount(JNIEnv *env, jobject obj) {
27+
if (g_tsf) {
28+
return tsf_get_presetcount(g_tsf);
29+
}
30+
return 0;
31+
}
32+
33+
// Get the name of a preset by index
34+
JNIEXPORT jstring JNICALL Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_getPresetName(JNIEnv *env, jobject obj, jint presetIndex) {
35+
if (g_tsf) {
36+
const char *name = tsf_get_presetname(g_tsf, presetIndex);
37+
return (*env)->NewStringUTF(env, name);
38+
}
39+
return (*env)->NewStringUTF(env, "");
40+
}
41+
42+
// Set output parameters
43+
JNIEXPORT void JNICALL Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_setOutput(JNIEnv *env, jobject obj, jobject outputMode, jint sampleRate, jfloat globalGainDb) {
44+
if (g_tsf) {
45+
jclass outputModeClass = (*env)->GetObjectClass(env, outputMode);
46+
47+
jmethodID ordinalMethod = (*env)->GetMethodID(env, outputModeClass, "ordinal", "()I");
48+
jint ordinal = (*env)->CallIntMethod(env, outputMode, ordinalMethod);
49+
enum TSFOutputMode outMode;
50+
switch (ordinal) {
51+
case 0:
52+
outMode = TSF_STEREO_INTERLEAVED;
53+
case 1:
54+
outMode = TSF_STEREO_UNWEAVED;
55+
default:
56+
outMode = TSF_MONO; // Default or error handling
57+
}
58+
59+
tsf_set_output(g_tsf, outMode, sampleRate, globalGainDb);
60+
}
61+
}
62+
63+
// Set volume
64+
JNIEXPORT void JNICALL Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_setVolume(JNIEnv *env, jobject obj, jfloat globalGain) {
65+
if (g_tsf) {
66+
tsf_set_volume(g_tsf, globalGain);
67+
}
68+
}
69+
70+
// Set max voices
71+
JNIEXPORT void JNICALL Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_setMaxVoices(JNIEnv *env, jobject obj, jint maxVoices) {
72+
if (g_tsf) {
73+
tsf_set_max_voices(g_tsf, maxVoices);
74+
}
75+
}
76+
77+
// Start playing a note
78+
JNIEXPORT void JNICALL Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_noteOn(JNIEnv *env, jobject obj, jint presetIndex, jint key, jfloat velocity) {
79+
if (g_tsf) {
80+
tsf_note_on(g_tsf, presetIndex, key, velocity);
81+
}
82+
}
83+
84+
// Stop playing a note
85+
JNIEXPORT void JNICALL Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_noteOff(JNIEnv *env, jobject obj, jint presetIndex, jint key) {
86+
if (g_tsf) {
87+
tsf_note_off(g_tsf, presetIndex, key);
88+
}
89+
}
90+
91+
// Render audio (this is a simplified example)
92+
JNIEXPORT jfloatArray JNICALL Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_renderFloat(JNIEnv *env, jobject obj, jint samples, jboolean isMixing) {
93+
if (g_tsf) {
94+
float buffer[samples];
95+
tsf_render_float(g_tsf, buffer, samples, isMixing);
96+
97+
jfloatArray output = (*env)->NewFloatArray(env, samples);
98+
(*env)->SetFloatArrayRegion(env, output, 0, samples, buffer);
99+
return output;
100+
}
101+
return NULL;
102+
}
103+
104+
JNIEXPORT jboolean JNICALL
105+
Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_loadMemory(JNIEnv *env, jobject thiz, jbyteArray memory, jint size) {
106+
// Get pointer to the memory array
107+
jbyte* memoryBuffer = (*env)->GetByteArrayElements(env, memory, NULL);
108+
109+
if (g_tsf) {
110+
tsf_close(g_tsf); // Close the existing SoundFont if loaded
111+
}
112+
113+
// Load the SoundFont from memory
114+
g_tsf = tsf_load_memory(memoryBuffer, size);
115+
116+
// Release the memory array
117+
(*env)->ReleaseByteArrayElements(env, memory, memoryBuffer, 0);
118+
119+
// Return true if the SoundFont was loaded successfully
120+
return g_tsf != NULL ? JNI_TRUE : JNI_FALSE;
121+
}
122+
123+
JNIEXPORT jboolean JNICALL
124+
Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_loadFilename(JNIEnv *env, jobject thiz, jstring path) {
125+
// Convert the jstring path to a C-style string
126+
const char *filePath = (*env)->GetStringUTFChars(env, path, NULL);
127+
128+
if (g_tsf) {
129+
tsf_close(g_tsf); // Close the existing SoundFont if loaded
130+
}
131+
132+
// Load the SoundFont from the file
133+
g_tsf = tsf_load_filename(filePath);
134+
135+
// Release the C-style string
136+
(*env)->ReleaseStringUTFChars(env, path, filePath);
137+
138+
// Return true if the SoundFont was loaded successfully
139+
return g_tsf != NULL ? JNI_TRUE : JNI_FALSE;
140+
}
141+
142+
JNIEXPORT void JNICALL
143+
Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_bankNoteOn(JNIEnv *env, jobject thiz, jint bank, jint preset_number, jint key, jfloat velocity) {
144+
if (g_tsf) {
145+
tsf_bank_note_on(g_tsf, bank, preset_number, key, velocity);
146+
}
147+
}
148+
149+
JNIEXPORT void JNICALL
150+
Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_bankNoteOff(JNIEnv *env, jobject thiz, jint bank, jint preset_number, jint key) {
151+
if (g_tsf) {
152+
tsf_bank_note_off(g_tsf, bank, preset_number, key);
153+
}
154+
}
155+
156+
JNIEXPORT void JNICALL
157+
Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_noteOffAll(JNIEnv *env, jobject thiz) {
158+
if (g_tsf) {
159+
tsf_note_off_all(g_tsf);
160+
}
161+
}
162+
163+
JNIEXPORT jint JNICALL
164+
Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_activeVoiceCount(JNIEnv *env, jobject thiz) {
165+
if (g_tsf) {
166+
return tsf_active_voice_count(g_tsf);
167+
}
168+
return 0; // Return 0 if no active SoundFont
169+
}
170+
171+
JNIEXPORT void JNICALL
172+
Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_setBankPreset(JNIEnv *env, jobject thiz, jint channel, jint bank, jint preset_number) {
173+
if (g_tsf) {
174+
tsf_channel_set_bank_preset(g_tsf, channel, bank, preset_number);
175+
}
176+
}
177+
178+
JNIEXPORT jstring JNICALL
179+
Java_pl_lemanski_tinySoundFont_internal_TinySoundFontImpl_bankGetPresetName(JNIEnv *env, jobject thiz, jint bank, jint preset_number) {
180+
if (g_tsf) {
181+
const char* presetName = tsf_bank_get_presetname(g_tsf, bank, preset_number);
182+
if (presetName) {
183+
return (*env)->NewStringUTF(env, presetName);
184+
}
185+
}
186+
return (*env)->NewStringUTF(env, ""); // Return empty string if not found
187+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package pl.lemanski.tinySoundFont
2+
3+
actual object MikroSoundFont {
4+
actual fun load(path: String): SoundFont {
5+
TODO("Not yet implemented")
6+
}
7+
8+
actual fun load(memory: ByteArray): SoundFont {
9+
TODO("Not yet implemented")
10+
}
11+
}

0 commit comments

Comments
 (0)