diff --git a/.github/workflows/apk-spoken-language-identification.yaml b/.github/workflows/apk-spoken-language-identification.yaml new file mode 100644 index 00000000..39e1e1b7 --- /dev/null +++ b/.github/workflows/apk-spoken-language-identification.yaml @@ -0,0 +1,174 @@ +name: apk-slid + +on: + push: + tags: + - '*' + + workflow_dispatch: + +concurrency: + group: apk-slid-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: write + +jobs: + apk_slid: + if: github.repository_owner == 'csukuangfj' || github.repository_owner == 'k2-fsa' + runs-on: ${{ matrix.os }} + name: apk for slid ${{ matrix.index }}/${{ matrix.total }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + total: ["1"] + index: ["0"] + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + # https://github.com/actions/setup-java + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '21' + + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ matrix.os }}-android + + - name: Display NDK HOME + shell: bash + run: | + echo "ANDROID_NDK_LATEST_HOME: ${ANDROID_NDK_LATEST_HOME}" + ls -lh ${ANDROID_NDK_LATEST_HOME} + + - name: Install Python dependencies + shell: bash + run: | + python3 -m pip install --upgrade pip jinja2 + + - name: Setup build tool version variable + shell: bash + run: | + echo "---" + ls -lh /usr/local/lib/android/ + echo "---" + + ls -lh /usr/local/lib/android/sdk + echo "---" + + ls -lh /usr/local/lib/android/sdk/build-tools + echo "---" + + BUILD_TOOL_VERSION=$(ls /usr/local/lib/android/sdk/build-tools/ | tail -n 1) + echo "BUILD_TOOL_VERSION=$BUILD_TOOL_VERSION" >> $GITHUB_ENV + echo "Last build tool version is: $BUILD_TOOL_VERSION" + + - name: Generate build script + shell: bash + run: | + cd scripts/apk + + total=${{ matrix.total }} + index=${{ matrix.index }} + + ./generate-slid-apk-script.py --total $total --index $index + + chmod +x build-apk-slid.sh + mv -v ./build-apk-slid.sh ../.. + + - name: build APK + shell: bash + run: | + export CMAKE_CXX_COMPILER_LAUNCHER=ccache + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + cmake --version + + export ANDROID_NDK=$ANDROID_NDK_LATEST_HOME + ./build-apk-slid.sh + + - name: Display APK + shell: bash + run: | + ls -lh ./apks/ + du -h -d1 . + + # https://github.com/marketplace/actions/sign-android-release + - uses: r0adkll/sign-android-release@v1 + name: Sign app APK + with: + releaseDirectory: ./apks + signingKeyBase64: ${{ secrets.ANDROID_SIGNING_KEY }} + alias: ${{ secrets.ANDROID_SIGNING_KEY_ALIAS }} + keyStorePassword: ${{ secrets.ANDROID_SIGNING_KEY_STORE_PASSWORD }} + env: + BUILD_TOOLS_VERSION: ${{ env.BUILD_TOOL_VERSION }} + + - name: Display APK for slid after signing + shell: bash + run: | + ls -lh ./apks/ + du -h -d1 . + + - name: Rename APK for slid after signing + shell: bash + run: | + cd apks + rm -fv signingKey.jks + rm -fv *.apk.idsig + rm -fv *-aligned.apk + + all_apks=$(ls -1 *-signed.apk) + echo "----" + echo $all_apks + echo "----" + for apk in ${all_apks[@]}; do + n=$(echo $apk | sed -e s/-signed//) + mv -v $apk $n + done + + cd .. + + ls -lh ./apks/ + du -h -d1 . + + - name: Display APK after rename + shell: bash + run: | + ls -lh ./apks/ + du -h -d1 . + + - name: Publish to huggingface + env: + HF_TOKEN: ${{ secrets.HF_TOKEN }} + uses: nick-fields/retry@v3 + with: + max_attempts: 20 + timeout_seconds: 200 + shell: bash + command: | + git config --global user.email "csukuangfj@gmail.com" + git config --global user.name "Fangjun Kuang" + + rm -rf huggingface + export GIT_LFS_SKIP_SMUDGE=1 + + git clone https://huggingface.co/csukuangfj/sherpa-onnx-apk huggingface + cd huggingface + git fetch + git pull + git merge -m "merge remote" --ff origin main + + mkdir -p slid + cp -v ../apks/*.apk ./slid/ + git status + git lfs track "*.apk" + git add . + git commit -m "add more apks" + git push https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-apk main diff --git a/android/SherpaOnnxSpokenLanguageIdentification/.gitignore b/android/SherpaOnnxSpokenLanguageIdentification/.gitignore new file mode 100644 index 00000000..aa724b77 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/.gitignore b/android/SherpaOnnxSpokenLanguageIdentification/app/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/build.gradle.kts b/android/SherpaOnnxSpokenLanguageIdentification/app/build.gradle.kts new file mode 100644 index 00000000..63858267 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/build.gradle.kts @@ -0,0 +1,69 @@ +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "com.k2fsa.sherpa.onnx.slid" + compileSdk = 34 + + defaultConfig { + applicationId = "com.k2fsa.sherpa.onnx.slid" + minSdk = 21 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.5.1" + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} + +dependencies { + + implementation("androidx.core:core-ktx:1.12.0") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0") + implementation("androidx.activity:activity-compose:1.8.2") + implementation(platform("androidx.compose:compose-bom:2023.08.00")) + implementation("androidx.compose.ui:ui") + implementation("androidx.compose.ui:ui-graphics") + implementation("androidx.compose.ui:ui-tooling-preview") + implementation("androidx.compose.material3:material3") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.5") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + androidTestImplementation(platform("androidx.compose:compose-bom:2023.08.00")) + androidTestImplementation("androidx.compose.ui:ui-test-junit4") + debugImplementation("androidx.compose.ui:ui-tooling") + debugImplementation("androidx.compose.ui:ui-test-manifest") +} \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/proguard-rules.pro b/android/SherpaOnnxSpokenLanguageIdentification/app/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/androidTest/java/com/k2fsa/sherpa/onnx/slid/ExampleInstrumentedTest.kt b/android/SherpaOnnxSpokenLanguageIdentification/app/src/androidTest/java/com/k2fsa/sherpa/onnx/slid/ExampleInstrumentedTest.kt new file mode 100644 index 00000000..5cb3e238 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/androidTest/java/com/k2fsa/sherpa/onnx/slid/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.k2fsa.sherpa.onnx.slid + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.k2fsa.sherpa.onnx.slid", appContext.packageName) + } +} \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/AndroidManifest.xml b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..df44766e --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/assets/.gitignore b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/assets/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/Home.kt b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/Home.kt new file mode 100644 index 00000000..018e3913 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/Home.kt @@ -0,0 +1,171 @@ +@file:OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) + +package com.k2fsa.sherpa.onnx.slid + +import android.Manifest +import android.app.Activity +import android.content.pm.PackageManager +import android.media.AudioFormat +import android.media.AudioRecord +import android.media.MediaRecorder +import android.util.Log +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.ui.Modifier +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.app.ActivityCompat +import kotlin.concurrent.thread + +@Composable +fun Home() { + Scaffold( + topBar = { + CenterAlignedTopAppBar( + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.primaryContainer, + titleContentColor = MaterialTheme.colorScheme.primary, + ), + title = { + Text( + "Next-gen Kaldi: Spoken language identification", + fontWeight = FontWeight.Bold, + fontSize = 13.sp, + ) + }, + ) + }, + content = { + MyApp(it) + }, + ) +} + +private var audioRecord: AudioRecord? = null +private val sampleRateInHz = 16000 + +@Composable +fun MyApp(padding: PaddingValues) { + val activity = LocalContext.current as Activity + var isStarted by remember { mutableStateOf(false) } + var result by remember { mutableStateOf("") } + + val onButtonClick: () -> Unit = { + isStarted = !isStarted + if (isStarted) { + result = "" + if (ActivityCompat.checkSelfPermission( + activity, + Manifest.permission.RECORD_AUDIO + ) != PackageManager.PERMISSION_GRANTED + ) { + Log.i(TAG, "Recording is not allowed") + } else { + val audioSource = MediaRecorder.AudioSource.MIC + val channelConfig = AudioFormat.CHANNEL_IN_MONO + val audioFormat = AudioFormat.ENCODING_PCM_16BIT + val numBytes = + AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat) + + audioRecord = AudioRecord( + audioSource, + sampleRateInHz, + AudioFormat.CHANNEL_IN_MONO, + AudioFormat.ENCODING_PCM_16BIT, + numBytes * 2 // a sample has two bytes as we are using 16-bit PCM + ) + + thread(true) { + Log.i(TAG, "processing samples") + val interval = 0.1 // i.e., 100 ms + val bufferSize = (interval * sampleRateInHz).toInt() // in samples + val buffer = ShortArray(bufferSize) + val sampleList = ArrayList() + audioRecord?.let { + it.startRecording() + while (isStarted) { + val ret = it.read(buffer, 0, buffer.size) + ret.let { n -> + val samples = FloatArray(n) { buffer[it] / 32768.0f } + sampleList.add(samples) + } + } + } + Log.i(TAG, "Stop recording") + Log.i(TAG, "Start recognition") + val samples = Flatten(sampleList) + val stream = Slid.slid.createStream() + stream.acceptWaveform(samples, sampleRateInHz) + val lang = Slid.slid.compute(stream) + + result = Slid.localeMap.get(lang) ?: lang + + stream.release() + } + } + } + } + + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.TopCenter + ) { + Column( + Modifier.padding(padding), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Spacer(modifier = Modifier.height(16.dp)) + Button(onClick = onButtonClick) { + if (isStarted) { + Text("Stop") + } else { + Text("Start") + } + } + + Spacer(modifier = Modifier.height(16.dp)) + if (result.isNotEmpty() && result.isNotBlank()) { + Text("Detected language: $result") + } + } + } +} + +fun Flatten(sampleList: ArrayList): FloatArray { + var totalSamples = 0 + for (a in sampleList) { + totalSamples += a.size + } + var i = 0 + val samples = FloatArray(totalSamples) + for (a in sampleList) { + for (s in a) { + samples[i] = s + i += 1 + } + } + Log.i(TAG, "$i, $totalSamples") + + return samples +} \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/MainActivity.kt b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/MainActivity.kt new file mode 100644 index 00000000..dfbcba16 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/MainActivity.kt @@ -0,0 +1,74 @@ +package com.k2fsa.sherpa.onnx.slid + +import android.Manifest +import android.content.pm.PackageManager +import android.os.Bundle +import android.util.Log +import android.widget.Toast +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.core.app.ActivityCompat +import com.k2fsa.sherpa.onnx.SpokenLanguageIdentification +import com.k2fsa.sherpa.onnx.slid.ui.theme.SherpaOnnxSpokenLanguageIdentificationTheme + +const val TAG = "sherpa-onnx" +private const val REQUEST_RECORD_AUDIO_PERMISSION = 200 + +class MainActivity : ComponentActivity() { + private val permissions: Array = arrayOf(Manifest.permission.RECORD_AUDIO) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + SpokenLanguageIdentificationApp() + } + ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION) + Slid.initSlid(this.assets) + } + @Suppress("DEPRECATION") + @Deprecated("Deprecated in Java") + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + val permissionToRecordAccepted = if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) { + grantResults[0] == PackageManager.PERMISSION_GRANTED + } else { + false + } + + if (!permissionToRecordAccepted) { + Log.e(TAG, "Audio record is disallowed") + Toast.makeText( + this, + "This App needs access to the microphone", + Toast.LENGTH_SHORT + ) + .show() + finish() + } + Log.i(TAG, "Audio record is permitted") + } +} + +@Composable +fun SpokenLanguageIdentificationApp() { + SherpaOnnxSpokenLanguageIdentificationTheme { + // A surface container using the 'background' color from the theme + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background + ) { + Home() + } + } +} \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/OfflineStream.kt b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/OfflineStream.kt new file mode 120000 index 00000000..1a5dfc31 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/OfflineStream.kt @@ -0,0 +1 @@ +../../../../../../../../../../SherpaOnnxAudioTagging/app/src/main/java/com/k2fsa/sherpa/onnx/audio/tagging/OfflineStream.kt \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/SpokenLanguageIdentification.kt b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/SpokenLanguageIdentification.kt new file mode 100644 index 00000000..fedf9d65 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/SpokenLanguageIdentification.kt @@ -0,0 +1,102 @@ +package com.k2fsa.sherpa.onnx + +import android.content.res.AssetManager +import android.util.Log + +private val TAG = "sherpa-onnx" + +data class SpokenLanguageIdentificationWhisperConfig ( + var encoder: String, + var decoder: String, + var tailPaddings: Int = -1, +) + +data class SpokenLanguageIdentificationConfig ( + var whisper: SpokenLanguageIdentificationWhisperConfig, + var numThreads: Int = 1, + var debug: Boolean = false, + var provider: String = "cpu", +) + +class SpokenLanguageIdentification ( + assetManager: AssetManager? = null, + config: SpokenLanguageIdentificationConfig, +) { + private var ptr: Long + + init { + ptr = if (assetManager != null) { + newFromAsset(assetManager, config) + } else { + newFromFile(config) + } + } + + protected fun finalize() { + if (ptr != 0L) { + delete(ptr) + ptr = 0 + } + } + + fun release() = finalize() + + fun createStream(): OfflineStream { + val p = createStream(ptr) + return OfflineStream(p) + } + + fun compute(stream: OfflineStream) = compute(ptr, stream.ptr) + + private external fun newFromAsset( + assetManager: AssetManager, + config: SpokenLanguageIdentificationConfig, + ): Long + + private external fun newFromFile( + config: SpokenLanguageIdentificationConfig, + ): Long + + private external fun delete(ptr: Long) + + private external fun createStream(ptr: Long): Long + + private external fun compute(ptr: Long, streamPtr: Long): String + + companion object { + init { + System.loadLibrary("sherpa-onnx-jni") + } + } +} +// please refer to +// https://k2-fsa.github.io/sherpa/onnx/spolken-language-identification/pretrained_models.html#whisper +// to download more models +fun getSpokenLanguageIdentificationConfig(type: Int, numThreads: Int=1): SpokenLanguageIdentificationConfig? { + when (type) { + 0 -> { + val modelDir = "sherpa-onnx-whisper-tiny" + return SpokenLanguageIdentificationConfig( + whisper = SpokenLanguageIdentificationWhisperConfig( + encoder = "$modelDir/tiny-encoder.int8.onnx", + decoder = "$modelDir/tiny-decoder.int8.onnx", + ), + numThreads = numThreads, + debug = true, + ) + } + + 1 -> { + val modelDir = "sherpa-onnx-whisper-base" + return SpokenLanguageIdentificationConfig( + whisper = SpokenLanguageIdentificationWhisperConfig( + encoder = "$modelDir/tiny-encoder.int8.onnx", + decoder = "$modelDir/tiny-decoder.int8.onnx", + ), + numThreads = 1, + debug = true, + ) + } + } + return null +} diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/slid.kt b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/slid.kt new file mode 100644 index 00000000..60c51170 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/slid.kt @@ -0,0 +1,42 @@ +package com.k2fsa.sherpa.onnx.slid + +import android.content.res.AssetManager +import android.util.Log +import com.k2fsa.sherpa.onnx.SpokenLanguageIdentification +import com.k2fsa.sherpa.onnx.getSpokenLanguageIdentificationConfig +import java.util.Locale + + +object Slid { + private var _slid: SpokenLanguageIdentification? = null + + private var _localeMap = mutableMapOf() + val slid: SpokenLanguageIdentification + get() { + return _slid!! + } + val localeMap : Map + get() { + return _localeMap + } + + fun initSlid(assetManager: AssetManager? = null, numThreads: Int = 1) { + synchronized(this) { + if (_slid == null) { + + Log.i(TAG, "Initializing slid") + val config = + getSpokenLanguageIdentificationConfig(type = 0, numThreads = numThreads)!! + _slid = SpokenLanguageIdentification(assetManager, config) + } + + if (_localeMap.isEmpty()) { + val allLang = Locale.getISOLanguages(); + for (lang in allLang) { + val locale = Locale(lang) + _localeMap[lang] = locale.displayName + } + } + } + } +} \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/ui/theme/Color.kt b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/ui/theme/Color.kt new file mode 100644 index 00000000..cbfdfd17 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.k2fsa.sherpa.onnx.slid.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/ui/theme/Theme.kt b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/ui/theme/Theme.kt new file mode 100644 index 00000000..02f83371 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/ui/theme/Theme.kt @@ -0,0 +1,70 @@ +package com.k2fsa.sherpa.onnx.slid.ui.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat + +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun SherpaOnnxSpokenLanguageIdentificationTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = colorScheme.primary.toArgb() + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + } + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/ui/theme/Type.kt b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/ui/theme/Type.kt new file mode 100644 index 00000000..48bb5ae9 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/java/com/k2fsa/sherpa/onnx/slid/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package com.k2fsa.sherpa.onnx.slid.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/jniLibs/arm64-v8a/.gitignore b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/jniLibs/arm64-v8a/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/jniLibs/armeabi-v7a/.gitignore b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/jniLibs/armeabi-v7a/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/jniLibs/x86/.gitignore b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/jniLibs/x86/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/jniLibs/x86_64/.gitignore b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/jniLibs/x86_64/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 00000000..2b068d11 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/drawable/ic_launcher_background.xml b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..07d5da9c --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000..6f3b755b --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000..6f3b755b --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 00000000..c209e78e Binary files /dev/null and b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 00000000..b2dfe3d1 Binary files /dev/null and b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 00000000..4f0f1d64 Binary files /dev/null and b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 00000000..62b611da Binary files /dev/null and b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 00000000..948a3070 Binary files /dev/null and b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 00000000..1b9a6956 Binary files /dev/null and b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 00000000..28d4b77f Binary files /dev/null and b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 00000000..9287f508 Binary files /dev/null and b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 00000000..aa7d6427 Binary files /dev/null and b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 00000000..9126ae37 Binary files /dev/null and b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/values/colors.xml b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/values/colors.xml new file mode 100644 index 00000000..f8c6127d --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/values/strings.xml b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/values/strings.xml new file mode 100644 index 00000000..f0a3e3a4 --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + SherpaOnnxSpokenLanguageIdentification + \ No newline at end of file diff --git a/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/values/themes.xml b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/values/themes.xml new file mode 100644 index 00000000..07b6588b --- /dev/null +++ b/android/SherpaOnnxSpokenLanguageIdentification/app/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +