Fangjun Kuang
Committed by GitHub

Support Android (#59)

正在显示 68 个修改的文件 包含 1380 行增加131 行删除
@@ -3,43 +3,43 @@ package com.k2fsa.sherpa.onnx @@ -3,43 +3,43 @@ package com.k2fsa.sherpa.onnx
3 import android.content.res.AssetManager 3 import android.content.res.AssetManager
4 4
5 fun main() { 5 fun main() {
6 - var featConfig = FeatureConfig(  
7 - sampleRate=16000.0f,  
8 - featureDim=80,  
9 - )  
10 -  
11 - var modelConfig = OnlineTransducerModelConfig(  
12 - encoder="./sherpa-onnx-streaming-zipformer-en-2023-02-21/encoder-epoch-99-avg-1.onnx",  
13 - decoder="./sherpa-onnx-streaming-zipformer-en-2023-02-21/decoder-epoch-99-avg-1.onnx",  
14 - joiner="./sherpa-onnx-streaming-zipformer-en-2023-02-21/joiner-epoch-99-avg-1.onnx",  
15 - numThreads=4,  
16 - debug=false,  
17 - )  
18 -  
19 - var endpointConfig = EndpointConfig()  
20 -  
21 - var config = OnlineRecognizerConfig(  
22 - modelConfig=modelConfig,  
23 - featConfig=featConfig,  
24 - endpointConfig=endpointConfig,  
25 - tokens="./sherpa-onnx-streaming-zipformer-en-2023-02-21/tokens.txt",  
26 - enableEndpoint=true,  
27 - )  
28 -  
29 - var model = SherpaOnnx(  
30 - assetManager = AssetManager(),  
31 - config = config,  
32 - )  
33 - var samples = WaveReader.readWave(  
34 - assetManager = AssetManager(),  
35 - filename = "./sherpa-onnx-streaming-zipformer-en-2023-02-21/test_wavs/1089-134686-0001.wav",  
36 - )  
37 -  
38 - model.decodeSamples(samples!!)  
39 -  
40 - var tail_paddings = FloatArray(8000) // 0.5 seconds  
41 - model.decodeSamples(tail_paddings)  
42 -  
43 - model.inputFinished()  
44 - println(model.text) 6 + var featConfig = FeatureConfig(
  7 + sampleRate = 16000.0f,
  8 + featureDim = 80,
  9 + )
  10 +
  11 + var modelConfig = OnlineTransducerModelConfig(
  12 + encoder = "./sherpa-onnx-streaming-zipformer-en-2023-02-21/encoder-epoch-99-avg-1.onnx",
  13 + decoder = "./sherpa-onnx-streaming-zipformer-en-2023-02-21/decoder-epoch-99-avg-1.onnx",
  14 + joiner = "./sherpa-onnx-streaming-zipformer-en-2023-02-21/joiner-epoch-99-avg-1.onnx",
  15 + tokens = "./sherpa-onnx-streaming-zipformer-en-2023-02-21/tokens.txt",
  16 + numThreads = 4,
  17 + debug = false,
  18 + )
  19 +
  20 + var endpointConfig = EndpointConfig()
  21 +
  22 + var config = OnlineRecognizerConfig(
  23 + modelConfig = modelConfig,
  24 + featConfig = featConfig,
  25 + endpointConfig = endpointConfig,
  26 + enableEndpoint = true,
  27 + )
  28 +
  29 + var model = SherpaOnnx(
  30 + assetManager = AssetManager(),
  31 + config = config,
  32 + )
  33 + var samples = WaveReader.readWave(
  34 + assetManager = AssetManager(),
  35 + filename = "./sherpa-onnx-streaming-zipformer-en-2023-02-21/test_wavs/1089-134686-0001.wav",
  36 + )
  37 +
  38 + model.decodeSamples(samples!!)
  39 +
  40 + var tail_paddings = FloatArray(8000) // 0.5 seconds
  41 + model.decodeSamples(tail_paddings)
  42 +
  43 + model.inputFinished()
  44 + println("results: ${model.text}")
45 } 45 }
  1 +../../android/SherpaOnnx/app/src/main/java/com/k2fsa/sherpa/onnx/SherpaOnnx.kt
  1 +../../android/SherpaOnnx/app/src/main/java/com/k2fsa/sherpa/onnx/WaveReader.kt
@@ -12,3 +12,9 @@ build-aarch64-linux-gnu @@ -12,3 +12,9 @@ build-aarch64-linux-gnu
12 sherpa-onnx-streaming-zipformer-* 12 sherpa-onnx-streaming-zipformer-*
13 sherpa-onnx-lstm-en-* 13 sherpa-onnx-lstm-en-*
14 sherpa-onnx-lstm-zh-* 14 sherpa-onnx-lstm-zh-*
  15 +build-android-arm64-v8a/
  16 +build-android-x86-64/
  17 +a.txt
  18 +run-bilingual*.sh
  19 +run-*-zipformer.sh
  20 +run-zh.sh
  1 +*.iml
  2 +.gradle
  3 +/local.properties
  4 +/.idea/caches
  5 +/.idea/libraries
  6 +/.idea/modules.xml
  7 +/.idea/workspace.xml
  8 +/.idea/navEditor.xml
  9 +/.idea/assetWizardSettings.xml
  10 +.DS_Store
  11 +/build
  12 +/captures
  13 +.externalNativeBuild
  14 +.cxx
  15 +local.properties
  1 +# Default ignored files
  2 +/shelf/
  3 +/workspace.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="CompilerConfiguration">
  4 + <bytecodeTargetLevel target="11" />
  5 + </component>
  6 +</project>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="deploymentTargetDropDown">
  4 + <runningDeviceTargetSelectedWithDropDown>
  5 + <Target>
  6 + <type value="RUNNING_DEVICE_TARGET" />
  7 + <deviceKey>
  8 + <Key>
  9 + <type value="SERIAL_NUMBER" />
  10 + <value value="50e6c115" />
  11 + </Key>
  12 + </deviceKey>
  13 + </Target>
  14 + </runningDeviceTargetSelectedWithDropDown>
  15 + <timeTargetWasSelectedWithDropDown value="2023-02-23T09:59:16.822185Z" />
  16 + </component>
  17 +</project>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="GradleSettings">
  4 + <option name="linkedExternalProjectsSettings">
  5 + <GradleProjectSettings>
  6 + <option name="testRunner" value="GRADLE" />
  7 + <option name="distributionType" value="DEFAULT_WRAPPED" />
  8 + <option name="externalProjectPath" value="$PROJECT_DIR$" />
  9 + <option name="modules">
  10 + <set>
  11 + <option value="$PROJECT_DIR$" />
  12 + <option value="$PROJECT_DIR$/app" />
  13 + </set>
  14 + </option>
  15 + </GradleProjectSettings>
  16 + </option>
  17 + </component>
  18 +</project>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="ExternalStorageConfigurationManager" enabled="true" />
  4 + <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
  5 + <output url="file://$PROJECT_DIR$/build/classes" />
  6 + </component>
  7 + <component name="ProjectType">
  8 + <option name="id" value="Android" />
  9 + </component>
  10 +</project>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="VcsDirectoryMappings">
  4 + <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
  5 + </component>
  6 +</project>
  1 +plugins {
  2 + id 'com.android.application'
  3 + id 'org.jetbrains.kotlin.android'
  4 +}
  5 +
  6 +android {
  7 + namespace 'com.k2fsa.sherpa.onnx'
  8 + compileSdk 32
  9 +
  10 + defaultConfig {
  11 + applicationId "com.k2fsa.sherpa.onnx"
  12 + minSdk 21
  13 + targetSdk 32
  14 + versionCode 1
  15 + versionName "1.0"
  16 +
  17 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
  18 + }
  19 +
  20 + buildTypes {
  21 + release {
  22 + minifyEnabled false
  23 + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
  24 + }
  25 + }
  26 + compileOptions {
  27 + sourceCompatibility JavaVersion.VERSION_1_8
  28 + targetCompatibility JavaVersion.VERSION_1_8
  29 + }
  30 + kotlinOptions {
  31 + jvmTarget = '1.8'
  32 + }
  33 +}
  34 +
  35 +dependencies {
  36 +
  37 + implementation 'androidx.core:core-ktx:1.7.0'
  38 + implementation 'androidx.appcompat:appcompat:1.5.1'
  39 + implementation 'com.google.android.material:material:1.7.0'
  40 + implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
  41 + testImplementation 'junit:junit:4.13.2'
  42 + androidTestImplementation 'androidx.test.ext:junit:1.1.4'
  43 + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
  44 +}
  1 +# Add project specific ProGuard rules here.
  2 +# You can control the set of applied configuration files using the
  3 +# proguardFiles setting in build.gradle.
  4 +#
  5 +# For more details, see
  6 +# http://developer.android.com/guide/developing/tools/proguard.html
  7 +
  8 +# If your project uses WebView with JS, uncomment the following
  9 +# and specify the fully qualified class name to the JavaScript interface
  10 +# class:
  11 +#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
  12 +# public *;
  13 +#}
  14 +
  15 +# Uncomment this to preserve the line number information for
  16 +# debugging stack traces.
  17 +#-keepattributes SourceFile,LineNumberTable
  18 +
  19 +# If you keep the line number information, uncomment this to
  20 +# hide the original source file name.
  21 +#-renamesourcefileattribute SourceFile
  1 +package com.k2fsa.sherpa.onnx
  2 +
  3 +import androidx.test.platform.app.InstrumentationRegistry
  4 +import androidx.test.ext.junit.runners.AndroidJUnit4
  5 +
  6 +import org.junit.Test
  7 +import org.junit.runner.RunWith
  8 +
  9 +import org.junit.Assert.*
  10 +
  11 +/**
  12 + * Instrumented test, which will execute on an Android device.
  13 + *
  14 + * See [testing documentation](http://d.android.com/tools/testing).
  15 + */
  16 +@RunWith(AndroidJUnit4::class)
  17 +class ExampleInstrumentedTest {
  18 + @Test
  19 + fun useAppContext() {
  20 + // Context of the app under test.
  21 + val appContext = InstrumentationRegistry.getInstrumentation().targetContext
  22 + assertEquals("com.k2fsa.sherpa.onnx", appContext.packageName)
  23 + }
  24 +}
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:tools="http://schemas.android.com/tools">
  4 +
  5 + <uses-permission android:name="android.permission.RECORD_AUDIO" />
  6 +
  7 + <application
  8 + android:allowBackup="true"
  9 + android:dataExtractionRules="@xml/data_extraction_rules"
  10 + android:fullBackupContent="@xml/backup_rules"
  11 + android:icon="@mipmap/ic_launcher"
  12 + android:label="@string/app_name"
  13 + android:roundIcon="@mipmap/ic_launcher_round"
  14 + android:supportsRtl="true"
  15 + android:theme="@style/Theme.SherpaOnnx"
  16 + tools:targetApi="31">
  17 + <activity
  18 + android:name=".MainActivity"
  19 + android:exported="true">
  20 + <intent-filter>
  21 + <action android:name="android.intent.action.MAIN" />
  22 +
  23 + <category android:name="android.intent.category.LAUNCHER" />
  24 + </intent-filter>
  25 +
  26 + <meta-data
  27 + android:name="android.app.lib_name"
  28 + android:value="" />
  29 + </activity>
  30 + </application>
  31 +
  32 +</manifest>
  1 +package com.k2fsa.sherpa.onnx
  2 +
  3 +import android.Manifest
  4 +import android.content.pm.PackageManager
  5 +import android.media.AudioFormat
  6 +import android.media.AudioRecord
  7 +import android.media.MediaRecorder
  8 +import android.os.Bundle
  9 +import android.text.method.ScrollingMovementMethod
  10 +import android.util.Log
  11 +import android.widget.Button
  12 +import android.widget.TextView
  13 +import androidx.appcompat.app.AppCompatActivity
  14 +import androidx.core.app.ActivityCompat
  15 +import com.k2fsa.sherpa.onnx.*
  16 +import kotlin.concurrent.thread
  17 +
  18 +private const val TAG = "sherpa-onnx"
  19 +private const val REQUEST_RECORD_AUDIO_PERMISSION = 200
  20 +
  21 +class MainActivity : AppCompatActivity() {
  22 + private val permissions: Array<String> = arrayOf(Manifest.permission.RECORD_AUDIO)
  23 +
  24 + // If there is a GPU and useGPU is true, we will use GPU
  25 + // If there is no GPU and useGPU is true, we won't use GPU
  26 + private val useGPU: Boolean = true
  27 +
  28 + private lateinit var model: SherpaOnnx
  29 + private var audioRecord: AudioRecord? = null
  30 + private lateinit var recordButton: Button
  31 + private lateinit var textView: TextView
  32 + private var recordingThread: Thread? = null
  33 +
  34 + private val audioSource = MediaRecorder.AudioSource.MIC
  35 + private val sampleRateInHz = 16000
  36 + private val channelConfig = AudioFormat.CHANNEL_IN_MONO
  37 +
  38 + // Note: We don't use AudioFormat.ENCODING_PCM_FLOAT
  39 + // since the AudioRecord.read(float[]) needs API level >= 23
  40 + // but we are targeting API level >= 21
  41 + private val audioFormat = AudioFormat.ENCODING_PCM_16BIT
  42 + private var idx: Int = 0
  43 + private var lastText: String = ""
  44 +
  45 + @Volatile
  46 + private var isRecording: Boolean = false
  47 +
  48 + override fun onRequestPermissionsResult(
  49 + requestCode: Int, permissions: Array<String>, grantResults: IntArray
  50 + ) {
  51 + super.onRequestPermissionsResult(requestCode, permissions, grantResults)
  52 + val permissionToRecordAccepted = if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) {
  53 + grantResults[0] == PackageManager.PERMISSION_GRANTED
  54 + } else {
  55 + false
  56 + }
  57 +
  58 + if (!permissionToRecordAccepted) {
  59 + Log.e(TAG, "Audio record is disallowed")
  60 + finish()
  61 + }
  62 +
  63 + Log.i(TAG, "Audio record is permitted")
  64 + }
  65 +
  66 + override fun onCreate(savedInstanceState: Bundle?) {
  67 + super.onCreate(savedInstanceState)
  68 + setContentView(R.layout.activity_main)
  69 +
  70 + ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION)
  71 +
  72 + Log.i(TAG, "Start to initialize model")
  73 + initModel()
  74 + Log.i(TAG, "Finished initializing model")
  75 +
  76 + recordButton = findViewById(R.id.record_button)
  77 + recordButton.setOnClickListener { onclick() }
  78 +
  79 + textView = findViewById(R.id.my_text)
  80 + textView.movementMethod = ScrollingMovementMethod()
  81 + }
  82 +
  83 + private fun onclick() {
  84 + if (!isRecording) {
  85 + val ret = initMicrophone()
  86 + if (!ret) {
  87 + Log.e(TAG, "Failed to initialize microphone")
  88 + return
  89 + }
  90 + Log.i(TAG, "state: ${audioRecord?.state}")
  91 + audioRecord!!.startRecording()
  92 + recordButton.setText(R.string.stop)
  93 + isRecording = true
  94 + model.reset()
  95 + textView.text = ""
  96 + lastText = ""
  97 + idx = 0
  98 +
  99 + recordingThread = thread(true) {
  100 + processSamples()
  101 + }
  102 + Log.i(TAG, "Started recording")
  103 + } else {
  104 + isRecording = false
  105 + audioRecord!!.stop()
  106 + audioRecord!!.release()
  107 + audioRecord = null
  108 + recordButton.setText(R.string.start)
  109 + Log.i(TAG, "Stopped recording")
  110 + }
  111 + }
  112 +
  113 + private fun processSamples() {
  114 + Log.i(TAG, "processing samples")
  115 +
  116 + val interval = 0.1 // i.e., 100 ms
  117 + val bufferSize = (interval * sampleRateInHz).toInt() // in samples
  118 + val buffer = ShortArray(bufferSize)
  119 +
  120 + while (isRecording) {
  121 + val ret = audioRecord?.read(buffer, 0, buffer.size)
  122 + if (ret != null && ret > 0) {
  123 + val samples = FloatArray(ret) { buffer[it] / 32768.0f }
  124 + model.decodeSamples(samples)
  125 + runOnUiThread {
  126 + val isEndpoint = model.isEndpoint()
  127 + val text = model.text
  128 +
  129 + if(text.isNotBlank()) {
  130 + if (lastText.isBlank()) {
  131 + textView.text = "${idx}: ${text}"
  132 + } else {
  133 + textView.text = "${lastText}\n${idx}: ${text}"
  134 + }
  135 + }
  136 +
  137 + if (isEndpoint) {
  138 + model.reset()
  139 + if (text.isNotBlank()) {
  140 + lastText = "${lastText}\n${idx}: ${text}"
  141 + idx += 1
  142 + }
  143 + }
  144 + }
  145 + }
  146 + }
  147 + }
  148 +
  149 + private fun initMicrophone(): Boolean {
  150 + if (ActivityCompat.checkSelfPermission(
  151 + this, Manifest.permission.RECORD_AUDIO
  152 + ) != PackageManager.PERMISSION_GRANTED
  153 + ) {
  154 + ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION)
  155 + return false
  156 + }
  157 +
  158 + val numBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat)
  159 + Log.i(
  160 + TAG, "buffer size in milliseconds: ${numBytes * 1000.0f / sampleRateInHz}"
  161 + )
  162 +
  163 + audioRecord = AudioRecord(
  164 + audioSource,
  165 + sampleRateInHz,
  166 + channelConfig,
  167 + audioFormat,
  168 + numBytes * 2 // a sample has two bytes as we are using 16-bit PCM
  169 + )
  170 + return true
  171 + }
  172 +
  173 + private fun initModel() {
  174 + val config = OnlineRecognizerConfig(
  175 + featConfig = getFeatureConfig(sampleRate = 16000.0f, featureDim = 80),
  176 + modelConfig = getModelConfig(type = 1)!!,
  177 + endpointConfig = getEndpointConfig(),
  178 + enableEndpoint = true
  179 + )
  180 +
  181 + model = SherpaOnnx(
  182 + assetManager = application.assets,
  183 + config = config,
  184 + )
  185 + /*
  186 + println("reading samples")
  187 + val samples = WaveReader.readWave(
  188 + assetManager = application.assets,
  189 + // filename = "sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/test_wavs/0.wav",
  190 + filename = "sherpa-onnx-lstm-zh-2023-02-20/test_wavs/0.wav",
  191 + // filename="sherpa-onnx-lstm-en-2023-02-17/test_wavs/1089-134686-0001.wav"
  192 + )
  193 + println("samples read done!")
  194 +
  195 + model.decodeSamples(samples!!)
  196 +
  197 + val tailPaddings = FloatArray(8000) // 0.5 seconds
  198 + model.decodeSamples(tailPaddings)
  199 +
  200 + println("result is: ${model.text}")
  201 + model.reset()
  202 + */
  203 + }
  204 +}
@@ -18,8 +18,9 @@ data class OnlineTransducerModelConfig( @@ -18,8 +18,9 @@ data class OnlineTransducerModelConfig(
18 var encoder: String, 18 var encoder: String,
19 var decoder: String, 19 var decoder: String,
20 var joiner: String, 20 var joiner: String,
21 - var numThreads: Int = 4,  
22 - var debug: Boolean = false, 21 + var tokens: String,
  22 + var numThreads: Int = 2,
  23 + var debug: Boolean = false,
23 ) 24 )
24 25
25 data class FeatureConfig( 26 data class FeatureConfig(
@@ -30,14 +31,12 @@ data class FeatureConfig( @@ -30,14 +31,12 @@ data class FeatureConfig(
30 data class OnlineRecognizerConfig( 31 data class OnlineRecognizerConfig(
31 var featConfig: FeatureConfig = FeatureConfig(), 32 var featConfig: FeatureConfig = FeatureConfig(),
32 var modelConfig: OnlineTransducerModelConfig, 33 var modelConfig: OnlineTransducerModelConfig,
33 - var tokens: String,  
34 var endpointConfig: EndpointConfig = EndpointConfig(), 34 var endpointConfig: EndpointConfig = EndpointConfig(),
35 var enableEndpoint: Boolean, 35 var enableEndpoint: Boolean,
36 ) 36 )
37 37
38 class SherpaOnnx( 38 class SherpaOnnx(
39 - assetManager: AssetManager,  
40 - var config: OnlineRecognizerConfig 39 + assetManager: AssetManager, var config: OnlineRecognizerConfig
41 ) { 40 ) {
42 private val ptr: Long 41 private val ptr: Long
43 42
@@ -80,10 +79,68 @@ class SherpaOnnx( @@ -80,10 +79,68 @@ class SherpaOnnx(
80 } 79 }
81 } 80 }
82 81
83 -fun getFeatureConfig(): FeatureConfig {  
84 - val featConfig = FeatureConfig()  
85 - featConfig.sampleRate = 16000.0f  
86 - featConfig.featureDim = 80 82 +fun getFeatureConfig(sampleRate: Float, featureDim: Int): FeatureConfig {
  83 + return FeatureConfig(sampleRate=sampleRate, featureDim=featureDim)
  84 +}
  85 +
  86 +/*
  87 +Please see
  88 +https://k2-fsa.github.io/sherpa/onnx/pretrained_models/index.html
  89 +for a list of pre-trained models.
  90 +
  91 +We only add a few here. Please change the following code
  92 +to add your own. (It should be straightforward to add a new model
  93 +by following the code)
  94 +
  95 +@param type
  96 +0 - sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20 (Bilingual, Chinese + English)
  97 + https://k2-fsa.github.io/sherpa/onnx/pretrained_models/zipformer-transducer-models.html#sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20-bilingual-chinese-english
  98 +
  99 +1 - csukuangfj/sherpa-onnx-lstm-zh-2023-02-20 (Chinese)
  100 +
  101 + https://k2-fsa.github.io/sherpa/onnx/pretrained_models/lstm-transducer-models.html#csukuangfj-sherpa-onnx-lstm-zh-2023-02-20-chinese
  102 +
  103 +2 - csukuangfj/sherpa-onnx-lstm-en-2023-02-17 (English)
  104 + https://k2-fsa.github.io/sherpa/onnx/pretrained_models/lstm-transducer-models.html#csukuangfj-sherpa-onnx-lstm-en-2023-02-17-english
  105 + */
  106 +fun getModelConfig(type: Int): OnlineTransducerModelConfig? {
  107 + when (type) {
  108 + 0 -> {
  109 + val modelDir = "sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20"
  110 + return OnlineTransducerModelConfig(
  111 + encoder = "$modelDir/encoder-epoch-99-avg-1.onnx",
  112 + decoder = "$modelDir/decoder-epoch-99-avg-1.onnx",
  113 + joiner = "$modelDir/joiner-epoch-99-avg-1.onnx",
  114 + tokens = "$modelDir/tokens.txt",
  115 + )
  116 + }
  117 + 1 -> {
  118 + val modelDir = "sherpa-onnx-lstm-zh-2023-02-20"
  119 + return OnlineTransducerModelConfig(
  120 + encoder = "$modelDir/encoder-epoch-11-avg-1.onnx",
  121 + decoder = "$modelDir/decoder-epoch-11-avg-1.onnx",
  122 + joiner = "$modelDir/joiner-epoch-11-avg-1.onnx",
  123 + tokens = "$modelDir/tokens.txt",
  124 + )
  125 + }
  126 +
  127 + 2 -> {
  128 + val modelDir = "sherpa-onnx-lstm-en-2023-02-17"
  129 + return OnlineTransducerModelConfig(
  130 + encoder = "$modelDir/encoder-epoch-99-avg-1.onnx",
  131 + decoder = "$modelDir/decoder-epoch-99-avg-1.onnx",
  132 + joiner = "$modelDir/joiner-epoch-99-avg-1.onnx",
  133 + tokens = "$modelDir/tokens.txt",
  134 + )
  135 + }
  136 + }
  137 + return null;
  138 +}
87 139
88 - return featConfig 140 +fun getEndpointConfig(): EndpointConfig {
  141 + return EndpointConfig(
  142 + rule1 = EndpointRule(false, 2.4f, 0.0f),
  143 + rule2 = EndpointRule(true, 1.4f, 0.0f),
  144 + rule3 = EndpointRule(false, 0.0f, 20.0f)
  145 + )
89 } 146 }
  1 +*.so
  2 +*.txt
  3 +*.onnx
  4 +*.wav
  1 +<vector xmlns:android="http://schemas.android.com/apk/res/android"
  2 + xmlns:aapt="http://schemas.android.com/aapt"
  3 + android:width="108dp"
  4 + android:height="108dp"
  5 + android:viewportWidth="108"
  6 + android:viewportHeight="108">
  7 + <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
  8 + <aapt:attr name="android:fillColor">
  9 + <gradient
  10 + android:endX="85.84757"
  11 + android:endY="92.4963"
  12 + android:startX="42.9492"
  13 + android:startY="49.59793"
  14 + android:type="linear">
  15 + <item
  16 + android:color="#44000000"
  17 + android:offset="0.0" />
  18 + <item
  19 + android:color="#00000000"
  20 + android:offset="1.0" />
  21 + </gradient>
  22 + </aapt:attr>
  23 + </path>
  24 + <path
  25 + android:fillColor="#FFFFFF"
  26 + android:fillType="nonZero"
  27 + android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
  28 + android:strokeWidth="1"
  29 + android:strokeColor="#00000000" />
  30 +</vector>
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<vector xmlns:android="http://schemas.android.com/apk/res/android"
  3 + android:width="108dp"
  4 + android:height="108dp"
  5 + android:viewportWidth="108"
  6 + android:viewportHeight="108">
  7 + <path
  8 + android:fillColor="#3DDC84"
  9 + android:pathData="M0,0h108v108h-108z" />
  10 + <path
  11 + android:fillColor="#00000000"
  12 + android:pathData="M9,0L9,108"
  13 + android:strokeWidth="0.8"
  14 + android:strokeColor="#33FFFFFF" />
  15 + <path
  16 + android:fillColor="#00000000"
  17 + android:pathData="M19,0L19,108"
  18 + android:strokeWidth="0.8"
  19 + android:strokeColor="#33FFFFFF" />
  20 + <path
  21 + android:fillColor="#00000000"
  22 + android:pathData="M29,0L29,108"
  23 + android:strokeWidth="0.8"
  24 + android:strokeColor="#33FFFFFF" />
  25 + <path
  26 + android:fillColor="#00000000"
  27 + android:pathData="M39,0L39,108"
  28 + android:strokeWidth="0.8"
  29 + android:strokeColor="#33FFFFFF" />
  30 + <path
  31 + android:fillColor="#00000000"
  32 + android:pathData="M49,0L49,108"
  33 + android:strokeWidth="0.8"
  34 + android:strokeColor="#33FFFFFF" />
  35 + <path
  36 + android:fillColor="#00000000"
  37 + android:pathData="M59,0L59,108"
  38 + android:strokeWidth="0.8"
  39 + android:strokeColor="#33FFFFFF" />
  40 + <path
  41 + android:fillColor="#00000000"
  42 + android:pathData="M69,0L69,108"
  43 + android:strokeWidth="0.8"
  44 + android:strokeColor="#33FFFFFF" />
  45 + <path
  46 + android:fillColor="#00000000"
  47 + android:pathData="M79,0L79,108"
  48 + android:strokeWidth="0.8"
  49 + android:strokeColor="#33FFFFFF" />
  50 + <path
  51 + android:fillColor="#00000000"
  52 + android:pathData="M89,0L89,108"
  53 + android:strokeWidth="0.8"
  54 + android:strokeColor="#33FFFFFF" />
  55 + <path
  56 + android:fillColor="#00000000"
  57 + android:pathData="M99,0L99,108"
  58 + android:strokeWidth="0.8"
  59 + android:strokeColor="#33FFFFFF" />
  60 + <path
  61 + android:fillColor="#00000000"
  62 + android:pathData="M0,9L108,9"
  63 + android:strokeWidth="0.8"
  64 + android:strokeColor="#33FFFFFF" />
  65 + <path
  66 + android:fillColor="#00000000"
  67 + android:pathData="M0,19L108,19"
  68 + android:strokeWidth="0.8"
  69 + android:strokeColor="#33FFFFFF" />
  70 + <path
  71 + android:fillColor="#00000000"
  72 + android:pathData="M0,29L108,29"
  73 + android:strokeWidth="0.8"
  74 + android:strokeColor="#33FFFFFF" />
  75 + <path
  76 + android:fillColor="#00000000"
  77 + android:pathData="M0,39L108,39"
  78 + android:strokeWidth="0.8"
  79 + android:strokeColor="#33FFFFFF" />
  80 + <path
  81 + android:fillColor="#00000000"
  82 + android:pathData="M0,49L108,49"
  83 + android:strokeWidth="0.8"
  84 + android:strokeColor="#33FFFFFF" />
  85 + <path
  86 + android:fillColor="#00000000"
  87 + android:pathData="M0,59L108,59"
  88 + android:strokeWidth="0.8"
  89 + android:strokeColor="#33FFFFFF" />
  90 + <path
  91 + android:fillColor="#00000000"
  92 + android:pathData="M0,69L108,69"
  93 + android:strokeWidth="0.8"
  94 + android:strokeColor="#33FFFFFF" />
  95 + <path
  96 + android:fillColor="#00000000"
  97 + android:pathData="M0,79L108,79"
  98 + android:strokeWidth="0.8"
  99 + android:strokeColor="#33FFFFFF" />
  100 + <path
  101 + android:fillColor="#00000000"
  102 + android:pathData="M0,89L108,89"
  103 + android:strokeWidth="0.8"
  104 + android:strokeColor="#33FFFFFF" />
  105 + <path
  106 + android:fillColor="#00000000"
  107 + android:pathData="M0,99L108,99"
  108 + android:strokeWidth="0.8"
  109 + android:strokeColor="#33FFFFFF" />
  110 + <path
  111 + android:fillColor="#00000000"
  112 + android:pathData="M19,29L89,29"
  113 + android:strokeWidth="0.8"
  114 + android:strokeColor="#33FFFFFF" />
  115 + <path
  116 + android:fillColor="#00000000"
  117 + android:pathData="M19,39L89,39"
  118 + android:strokeWidth="0.8"
  119 + android:strokeColor="#33FFFFFF" />
  120 + <path
  121 + android:fillColor="#00000000"
  122 + android:pathData="M19,49L89,49"
  123 + android:strokeWidth="0.8"
  124 + android:strokeColor="#33FFFFFF" />
  125 + <path
  126 + android:fillColor="#00000000"
  127 + android:pathData="M19,59L89,59"
  128 + android:strokeWidth="0.8"
  129 + android:strokeColor="#33FFFFFF" />
  130 + <path
  131 + android:fillColor="#00000000"
  132 + android:pathData="M19,69L89,69"
  133 + android:strokeWidth="0.8"
  134 + android:strokeColor="#33FFFFFF" />
  135 + <path
  136 + android:fillColor="#00000000"
  137 + android:pathData="M19,79L89,79"
  138 + android:strokeWidth="0.8"
  139 + android:strokeColor="#33FFFFFF" />
  140 + <path
  141 + android:fillColor="#00000000"
  142 + android:pathData="M29,19L29,89"
  143 + android:strokeWidth="0.8"
  144 + android:strokeColor="#33FFFFFF" />
  145 + <path
  146 + android:fillColor="#00000000"
  147 + android:pathData="M39,19L39,89"
  148 + android:strokeWidth="0.8"
  149 + android:strokeColor="#33FFFFFF" />
  150 + <path
  151 + android:fillColor="#00000000"
  152 + android:pathData="M49,19L49,89"
  153 + android:strokeWidth="0.8"
  154 + android:strokeColor="#33FFFFFF" />
  155 + <path
  156 + android:fillColor="#00000000"
  157 + android:pathData="M59,19L59,89"
  158 + android:strokeWidth="0.8"
  159 + android:strokeColor="#33FFFFFF" />
  160 + <path
  161 + android:fillColor="#00000000"
  162 + android:pathData="M69,19L69,89"
  163 + android:strokeWidth="0.8"
  164 + android:strokeColor="#33FFFFFF" />
  165 + <path
  166 + android:fillColor="#00000000"
  167 + android:pathData="M79,19L79,89"
  168 + android:strokeWidth="0.8"
  169 + android:strokeColor="#33FFFFFF" />
  170 +</vector>
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3 + xmlns:app="http://schemas.android.com/apk/res-auto"
  4 + xmlns:tools="http://schemas.android.com/tools"
  5 + android:layout_width="match_parent"
  6 + android:layout_height="match_parent"
  7 + tools:context=".MainActivity">
  8 +
  9 + <LinearLayout
  10 + android:layout_width="match_parent"
  11 + android:layout_height="match_parent"
  12 + android:gravity="center"
  13 + android:orientation="vertical">
  14 +
  15 + <TextView
  16 + android:id="@+id/my_text"
  17 + android:layout_width="match_parent"
  18 + android:layout_height="match_parent"
  19 + android:layout_weight="2.5"
  20 + android:padding="24dp"
  21 + android:scrollbars="vertical"
  22 + android:singleLine="false"
  23 + android:text="@string/hint"
  24 + app:layout_constraintBottom_toBottomOf="parent"
  25 + app:layout_constraintEnd_toEndOf="parent"
  26 + app:layout_constraintStart_toStartOf="parent"
  27 + app:layout_constraintTop_toTopOf="parent" />
  28 +
  29 + <Button
  30 + android:id="@+id/record_button"
  31 + android:layout_width="wrap_content"
  32 + android:layout_height="wrap_content"
  33 + android:layout_weight="0.5"
  34 + android:text="@string/start" />
  35 + </LinearLayout>
  36 +
  37 +
  38 +</androidx.constraintlayout.widget.ConstraintLayout>
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
  3 + <background android:drawable="@drawable/ic_launcher_background" />
  4 + <foreground android:drawable="@drawable/ic_launcher_foreground" />
  5 +</adaptive-icon>
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
  3 + <background android:drawable="@drawable/ic_launcher_background" />
  4 + <foreground android:drawable="@drawable/ic_launcher_foreground" />
  5 +</adaptive-icon>
  1 +<resources xmlns:tools="http://schemas.android.com/tools">
  2 + <!-- Base application theme. -->
  3 + <style name="Theme.SherpaOnnx" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
  4 + <!-- Primary brand color. -->
  5 + <item name="colorPrimary">@color/purple_200</item>
  6 + <item name="colorPrimaryVariant">@color/purple_700</item>
  7 + <item name="colorOnPrimary">@color/black</item>
  8 + <!-- Secondary brand color. -->
  9 + <item name="colorSecondary">@color/teal_200</item>
  10 + <item name="colorSecondaryVariant">@color/teal_200</item>
  11 + <item name="colorOnSecondary">@color/black</item>
  12 + <!-- Status bar color. -->
  13 + <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
  14 + <!-- Customize your theme here. -->
  15 + </style>
  16 +</resources>
  1 +<?xml version="1.0" encoding="utf-8"?>
  2 +<resources>
  3 + <color name="purple_200">#FFBB86FC</color>
  4 + <color name="purple_500">#FF6200EE</color>
  5 + <color name="purple_700">#FF3700B3</color>
  6 + <color name="teal_200">#FF03DAC5</color>
  7 + <color name="teal_700">#FF018786</color>
  8 + <color name="black">#FF000000</color>
  9 + <color name="white">#FFFFFFFF</color>
  10 +</resources>
  1 +<resources>
  2 + <string name="app_name">ASR with Next-gen Kaldi</string>
  3 + <string name="hint">Click the Start button to play speech-to-text with Next-gen Kaldi.
  4 + \n
  5 + \n\n\n
  6 + The source code and pre-trained models are publicly available.
  7 + Please see https://github.com/k2-fsa/sherpa-onnx for details.
  8 + </string>
  9 + <string name="start">Start</string>
  10 + <string name="stop">Stop</string>
  11 +</resources>
  1 +<resources xmlns:tools="http://schemas.android.com/tools">
  2 + <!-- Base application theme. -->
  3 + <style name="Theme.SherpaOnnx" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
  4 + <!-- Primary brand color. -->
  5 + <item name="colorPrimary">@color/purple_500</item>
  6 + <item name="colorPrimaryVariant">@color/purple_700</item>
  7 + <item name="colorOnPrimary">@color/white</item>
  8 + <!-- Secondary brand color. -->
  9 + <item name="colorSecondary">@color/teal_200</item>
  10 + <item name="colorSecondaryVariant">@color/teal_700</item>
  11 + <item name="colorOnSecondary">@color/black</item>
  12 + <!-- Status bar color. -->
  13 + <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
  14 + <!-- Customize your theme here. -->
  15 + </style>
  16 +</resources>
  1 +<?xml version="1.0" encoding="utf-8"?><!--
  2 + Sample backup rules file; uncomment and customize as necessary.
  3 + See https://developer.android.com/guide/topics/data/autobackup
  4 + for details.
  5 + Note: This file is ignored for devices older that API 31
  6 + See https://developer.android.com/about/versions/12/backup-restore
  7 +-->
  8 +<full-backup-content>
  9 + <!--
  10 + <include domain="sharedpref" path="."/>
  11 + <exclude domain="sharedpref" path="device.xml"/>
  12 +-->
  13 +</full-backup-content>
  1 +<?xml version="1.0" encoding="utf-8"?><!--
  2 + Sample data extraction rules file; uncomment and customize as necessary.
  3 + See https://developer.android.com/about/versions/12/backup-restore#xml-changes
  4 + for details.
  5 +-->
  6 +<data-extraction-rules>
  7 + <cloud-backup>
  8 + <!-- TODO: Use <include> and <exclude> to control what is backed up.
  9 + <include .../>
  10 + <exclude .../>
  11 + -->
  12 + </cloud-backup>
  13 + <!--
  14 + <device-transfer>
  15 + <include .../>
  16 + <exclude .../>
  17 + </device-transfer>
  18 + -->
  19 +</data-extraction-rules>
  1 +package com.k2fsa.sherpa.onnx
  2 +
  3 +import org.junit.Test
  4 +
  5 +import org.junit.Assert.*
  6 +
  7 +/**
  8 + * Example local unit test, which will execute on the development machine (host).
  9 + *
  10 + * See [testing documentation](http://d.android.com/tools/testing).
  11 + */
  12 +class ExampleUnitTest {
  13 + @Test
  14 + fun addition_isCorrect() {
  15 + assertEquals(4, 2 + 2)
  16 + }
  17 +}
  1 +// Top-level build file where you can add configuration options common to all sub-projects/modules.
  2 +plugins {
  3 + id 'com.android.application' version '7.3.1' apply false
  4 + id 'com.android.library' version '7.3.1' apply false
  5 + id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
  6 +}
  1 +# Project-wide Gradle settings.
  2 +# IDE (e.g. Android Studio) users:
  3 +# Gradle settings configured through the IDE *will override*
  4 +# any settings specified in this file.
  5 +# For more details on how to configure your build environment visit
  6 +# http://www.gradle.org/docs/current/userguide/build_environment.html
  7 +# Specifies the JVM arguments used for the daemon process.
  8 +# The setting is particularly useful for tweaking memory settings.
  9 +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
  10 +# When configured, Gradle will run in incubating parallel mode.
  11 +# This option should only be used with decoupled projects. More details, visit
  12 +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
  13 +# org.gradle.parallel=true
  14 +# AndroidX package structure to make it clearer which packages are bundled with the
  15 +# Android operating system, and which are packaged with your app's APK
  16 +# https://developer.android.com/topic/libraries/support-library/androidx-rn
  17 +android.useAndroidX=true
  18 +# Kotlin code style for this project: "official" or "obsolete":
  19 +kotlin.code.style=official
  20 +# Enables namespacing of each library's R class so that its R class includes only the
  21 +# resources declared in the library itself and none from the library's dependencies,
  22 +# thereby reducing the size of the R class for that library
  23 +android.nonTransitiveRClass=true
  1 +#Thu Feb 23 11:09:06 CST 2023
  2 +distributionBase=GRADLE_USER_HOME
  3 +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
  4 +distributionPath=wrapper/dists
  5 +zipStorePath=wrapper/dists
  6 +zipStoreBase=GRADLE_USER_HOME
  1 +#!/usr/bin/env sh
  2 +
  3 +#
  4 +# Copyright 2015 the original author or authors.
  5 +#
  6 +# Licensed under the Apache License, Version 2.0 (the "License");
  7 +# you may not use this file except in compliance with the License.
  8 +# You may obtain a copy of the License at
  9 +#
  10 +# https://www.apache.org/licenses/LICENSE-2.0
  11 +#
  12 +# Unless required by applicable law or agreed to in writing, software
  13 +# distributed under the License is distributed on an "AS IS" BASIS,
  14 +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15 +# See the License for the specific language governing permissions and
  16 +# limitations under the License.
  17 +#
  18 +
  19 +##############################################################################
  20 +##
  21 +## Gradle start up script for UN*X
  22 +##
  23 +##############################################################################
  24 +
  25 +# Attempt to set APP_HOME
  26 +# Resolve links: $0 may be a link
  27 +PRG="$0"
  28 +# Need this for relative symlinks.
  29 +while [ -h "$PRG" ] ; do
  30 + ls=`ls -ld "$PRG"`
  31 + link=`expr "$ls" : '.*-> \(.*\)$'`
  32 + if expr "$link" : '/.*' > /dev/null; then
  33 + PRG="$link"
  34 + else
  35 + PRG=`dirname "$PRG"`"/$link"
  36 + fi
  37 +done
  38 +SAVED="`pwd`"
  39 +cd "`dirname \"$PRG\"`/" >/dev/null
  40 +APP_HOME="`pwd -P`"
  41 +cd "$SAVED" >/dev/null
  42 +
  43 +APP_NAME="Gradle"
  44 +APP_BASE_NAME=`basename "$0"`
  45 +
  46 +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
  47 +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
  48 +
  49 +# Use the maximum available, or set MAX_FD != -1 to use that value.
  50 +MAX_FD="maximum"
  51 +
  52 +warn () {
  53 + echo "$*"
  54 +}
  55 +
  56 +die () {
  57 + echo
  58 + echo "$*"
  59 + echo
  60 + exit 1
  61 +}
  62 +
  63 +# OS specific support (must be 'true' or 'false').
  64 +cygwin=false
  65 +msys=false
  66 +darwin=false
  67 +nonstop=false
  68 +case "`uname`" in
  69 + CYGWIN* )
  70 + cygwin=true
  71 + ;;
  72 + Darwin* )
  73 + darwin=true
  74 + ;;
  75 + MINGW* )
  76 + msys=true
  77 + ;;
  78 + NONSTOP* )
  79 + nonstop=true
  80 + ;;
  81 +esac
  82 +
  83 +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
  84 +
  85 +
  86 +# Determine the Java command to use to start the JVM.
  87 +if [ -n "$JAVA_HOME" ] ; then
  88 + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
  89 + # IBM's JDK on AIX uses strange locations for the executables
  90 + JAVACMD="$JAVA_HOME/jre/sh/java"
  91 + else
  92 + JAVACMD="$JAVA_HOME/bin/java"
  93 + fi
  94 + if [ ! -x "$JAVACMD" ] ; then
  95 + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
  96 +
  97 +Please set the JAVA_HOME variable in your environment to match the
  98 +location of your Java installation."
  99 + fi
  100 +else
  101 + JAVACMD="java"
  102 + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
  103 +
  104 +Please set the JAVA_HOME variable in your environment to match the
  105 +location of your Java installation."
  106 +fi
  107 +
  108 +# Increase the maximum file descriptors if we can.
  109 +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
  110 + MAX_FD_LIMIT=`ulimit -H -n`
  111 + if [ $? -eq 0 ] ; then
  112 + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
  113 + MAX_FD="$MAX_FD_LIMIT"
  114 + fi
  115 + ulimit -n $MAX_FD
  116 + if [ $? -ne 0 ] ; then
  117 + warn "Could not set maximum file descriptor limit: $MAX_FD"
  118 + fi
  119 + else
  120 + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
  121 + fi
  122 +fi
  123 +
  124 +# For Darwin, add options to specify how the application appears in the dock
  125 +if $darwin; then
  126 + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
  127 +fi
  128 +
  129 +# For Cygwin or MSYS, switch paths to Windows format before running java
  130 +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
  131 + APP_HOME=`cygpath --path --mixed "$APP_HOME"`
  132 + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
  133 +
  134 + JAVACMD=`cygpath --unix "$JAVACMD"`
  135 +
  136 + # We build the pattern for arguments to be converted via cygpath
  137 + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
  138 + SEP=""
  139 + for dir in $ROOTDIRSRAW ; do
  140 + ROOTDIRS="$ROOTDIRS$SEP$dir"
  141 + SEP="|"
  142 + done
  143 + OURCYGPATTERN="(^($ROOTDIRS))"
  144 + # Add a user-defined pattern to the cygpath arguments
  145 + if [ "$GRADLE_CYGPATTERN" != "" ] ; then
  146 + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
  147 + fi
  148 + # Now convert the arguments - kludge to limit ourselves to /bin/sh
  149 + i=0
  150 + for arg in "$@" ; do
  151 + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
  152 + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
  153 +
  154 + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
  155 + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
  156 + else
  157 + eval `echo args$i`="\"$arg\""
  158 + fi
  159 + i=`expr $i + 1`
  160 + done
  161 + case $i in
  162 + 0) set -- ;;
  163 + 1) set -- "$args0" ;;
  164 + 2) set -- "$args0" "$args1" ;;
  165 + 3) set -- "$args0" "$args1" "$args2" ;;
  166 + 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
  167 + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
  168 + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
  169 + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
  170 + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
  171 + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
  172 + esac
  173 +fi
  174 +
  175 +# Escape application args
  176 +save () {
  177 + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
  178 + echo " "
  179 +}
  180 +APP_ARGS=`save "$@"`
  181 +
  182 +# Collect all arguments for the java command, following the shell quoting and substitution rules
  183 +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
  184 +
  185 +exec "$JAVACMD" "$@"
  1 +@rem
  2 +@rem Copyright 2015 the original author or authors.
  3 +@rem
  4 +@rem Licensed under the Apache License, Version 2.0 (the "License");
  5 +@rem you may not use this file except in compliance with the License.
  6 +@rem You may obtain a copy of the License at
  7 +@rem
  8 +@rem https://www.apache.org/licenses/LICENSE-2.0
  9 +@rem
  10 +@rem Unless required by applicable law or agreed to in writing, software
  11 +@rem distributed under the License is distributed on an "AS IS" BASIS,
  12 +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +@rem See the License for the specific language governing permissions and
  14 +@rem limitations under the License.
  15 +@rem
  16 +
  17 +@if "%DEBUG%" == "" @echo off
  18 +@rem ##########################################################################
  19 +@rem
  20 +@rem Gradle startup script for Windows
  21 +@rem
  22 +@rem ##########################################################################
  23 +
  24 +@rem Set local scope for the variables with windows NT shell
  25 +if "%OS%"=="Windows_NT" setlocal
  26 +
  27 +set DIRNAME=%~dp0
  28 +if "%DIRNAME%" == "" set DIRNAME=.
  29 +set APP_BASE_NAME=%~n0
  30 +set APP_HOME=%DIRNAME%
  31 +
  32 +@rem Resolve any "." and ".." in APP_HOME to make it shorter.
  33 +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
  34 +
  35 +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
  36 +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
  37 +
  38 +@rem Find java.exe
  39 +if defined JAVA_HOME goto findJavaFromJavaHome
  40 +
  41 +set JAVA_EXE=java.exe
  42 +%JAVA_EXE% -version >NUL 2>&1
  43 +if "%ERRORLEVEL%" == "0" goto execute
  44 +
  45 +echo.
  46 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
  47 +echo.
  48 +echo Please set the JAVA_HOME variable in your environment to match the
  49 +echo location of your Java installation.
  50 +
  51 +goto fail
  52 +
  53 +:findJavaFromJavaHome
  54 +set JAVA_HOME=%JAVA_HOME:"=%
  55 +set JAVA_EXE=%JAVA_HOME%/bin/java.exe
  56 +
  57 +if exist "%JAVA_EXE%" goto execute
  58 +
  59 +echo.
  60 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
  61 +echo.
  62 +echo Please set the JAVA_HOME variable in your environment to match the
  63 +echo location of your Java installation.
  64 +
  65 +goto fail
  66 +
  67 +:execute
  68 +@rem Setup the command line
  69 +
  70 +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
  71 +
  72 +
  73 +@rem Execute Gradle
  74 +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
  75 +
  76 +:end
  77 +@rem End local scope for the variables with windows NT shell
  78 +if "%ERRORLEVEL%"=="0" goto mainEnd
  79 +
  80 +:fail
  81 +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
  82 +rem the _cmd.exe /c_ return code!
  83 +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
  84 +exit /b 1
  85 +
  86 +:mainEnd
  87 +if "%OS%"=="Windows_NT" endlocal
  88 +
  89 +:omega
  1 +pluginManagement {
  2 + repositories {
  3 + gradlePluginPortal()
  4 + google()
  5 + mavenCentral()
  6 + }
  7 +}
  8 +dependencyResolutionManagement {
  9 + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
  10 + repositories {
  11 + google()
  12 + mavenCentral()
  13 + }
  14 +}
  15 +rootProject.name = "SherpaOnnx"
  16 +include ':app'
@@ -19,7 +19,6 @@ cd $dir @@ -19,7 +19,6 @@ cd $dir
19 # -g 19 # -g
20 # -DANDROID 20 # -DANDROID
21 21
22 -  
23 if [ -z $ANDROID_NDK ]; then 22 if [ -z $ANDROID_NDK ]; then
24 ANDROID_NDK=/ceph-fj/fangjun/software/android-sdk/ndk/21.0.6113669 23 ANDROID_NDK=/ceph-fj/fangjun/software/android-sdk/ndk/21.0.6113669
25 # or use 24 # or use
@@ -44,6 +43,29 @@ fi @@ -44,6 +43,29 @@ fi
44 echo "ANDROID_NDK: $ANDROID_NDK" 43 echo "ANDROID_NDK: $ANDROID_NDK"
45 sleep 1 44 sleep 1
46 45
  46 +if [ ! -f android-onnxruntime-libs/jni/arm64-v8a/libonnxruntime.so ]; then
  47 + GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/android-onnxruntime-libs
  48 + pushd android-onnxruntime-libs
  49 + git lfs pull --include "jni/arm64-v8a/libonnxruntime.so"
  50 + popd
  51 +fi
  52 +
  53 +ls -l ./android-onnxruntime-libs/jni/arm64-v8a/libonnxruntime.so
  54 +
  55 +# check filesize
  56 +filesize=$(ls -l ./android-onnxruntime-libs/jni/arm64-v8a/libonnxruntime.so | tr -s " " " " | cut -d " " -f 5)
  57 +if (( $filesize < 1000 )); then
  58 + ls -lh ./android-onnxruntime-libs/arm64-v8a/jni/libonnxruntime.so
  59 + echo "Please use: git lfs pull to download libonnxruntime.so"
  60 + exit 1
  61 +fi
  62 +
  63 +export SHERPA_ONNXRUNTIME_LIB_DIR=$PWD/android-onnxruntime-libs/jni/arm64-v8a/
  64 +export SHERPA_ONNXRUNTIME_INCLUDE_DIR=$PWD/android-onnxruntime-libs/headers/
  65 +
  66 +echo "SHERPA_ONNXRUNTIME_LIB_DIR: $SHERPA_ONNXRUNTIME_LIB_DIR"
  67 +echo "SHERPA_ONNXRUNTIME_INCLUDE_DIR $SHERPA_ONNXRUNTIME_INCLUDE_DIR"
  68 +
47 cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \ 69 cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \
48 -DCMAKE_BUILD_TYPE=Release \ 70 -DCMAKE_BUILD_TYPE=Release \
49 -DBUILD_SHARED_LIBS=ON \ 71 -DBUILD_SHARED_LIBS=ON \
@@ -55,7 +77,8 @@ cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" @@ -55,7 +77,8 @@ cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake"
55 -DCMAKE_INSTALL_PREFIX=./install \ 77 -DCMAKE_INSTALL_PREFIX=./install \
56 -DANDROID_ABI="arm64-v8a" \ 78 -DANDROID_ABI="arm64-v8a" \
57 -DANDROID_PLATFORM=android-21 .. 79 -DANDROID_PLATFORM=android-21 ..
  80 +
58 # make VERBOSE=1 -j4 81 # make VERBOSE=1 -j4
59 make -j4 82 make -j4
60 make install/strip 83 make install/strip
61 - 84 +cp -fv android-onnxruntime-libs/jni/arm64-v8a/libonnxruntime.so install/lib
  1 +#!/usr/bin/env bash
  2 +set -ex
  3 +
  4 +dir=build-android-x86-64
  5 +
  6 +mkdir -p $dir
  7 +cd $dir
  8 +
  9 +# Note from https://github.com/Tencent/ncnn/wiki/how-to-build#build-for-android
  10 +# (optional) remove the hardcoded debug flag in Android NDK android-ndk
  11 +# issue: https://github.com/android/ndk/issues/243
  12 +#
  13 +# open $ANDROID_NDK/build/cmake/android.toolchain.cmake for ndk < r23
  14 +# or $ANDROID_NDK/build/cmake/android-legacy.toolchain.cmake for ndk >= r23
  15 +#
  16 +# delete "-g" line
  17 +#
  18 +# list(APPEND ANDROID_COMPILER_FLAGS
  19 +# -g
  20 +# -DANDROID
  21 +
  22 +if [ -z $ANDROID_NDK ]; then
  23 + ANDROID_NDK=/ceph-fj/fangjun/software/android-sdk/ndk/21.0.6113669
  24 + # or use
  25 + # ANDROID_NDK=/ceph-fj/fangjun/software/android-ndk
  26 + #
  27 + # Inside the $ANDROID_NDK directory, you can find a binary ndk-build
  28 + # and some other files like the file "build/cmake/android.toolchain.cmake"
  29 +
  30 + if [ ! -d $ANDROID_NDK ]; then
  31 + # For macOS, I have installed Android Studio, select the menu
  32 + # Tools -> SDK manager -> Android SDK
  33 + # and set "Android SDK location" to /Users/fangjun/software/my-android
  34 + ANDROID_NDK=/Users/fangjun/software/my-android/ndk/22.1.7171670
  35 + fi
  36 +fi
  37 +
  38 +if [ ! -d $ANDROID_NDK ]; then
  39 + echo Please set the environment variable ANDROID_NDK before you run this script
  40 + exit 1
  41 +fi
  42 +
  43 +echo "ANDROID_NDK: $ANDROID_NDK"
  44 +sleep 1
  45 +
  46 +if [ ! -f android-onnxruntime-libs/jni/x86_64/libonnxruntime.so ]; then
  47 + GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/android-onnxruntime-libs
  48 + pushd android-onnxruntime-libs
  49 + git lfs pull --include "jni/x86_64/libonnxruntime.so"
  50 + popd
  51 +fi
  52 +
  53 +ls -l ./android-onnxruntime-libs/jni/x86_64/libonnxruntime.so
  54 +
  55 +# check filesize
  56 +filesize=$(ls -l ./android-onnxruntime-libs/jni/x86_64/libonnxruntime.so | tr -s " " " " | cut -d " " -f 5)
  57 +if (( $filesize < 1000 )); then
  58 + ls -lh ./android-onnxruntime-libs/jni/x86_64/libonnxruntime.so
  59 + echo "Please use: git lfs pull to download libonnxruntime.so"
  60 + exit 1
  61 +fi
  62 +
  63 +export SHERPA_ONNXRUNTIME_LIB_DIR=$PWD/android-onnxruntime-libs/jni/x86_64/
  64 +export SHERPA_ONNXRUNTIME_INCLUDE_DIR=$PWD/android-onnxruntime-libs/headers/
  65 +
  66 +echo "SHERPA_ONNXRUNTIME_LIB_DIR: $SHERPA_ONNXRUNTIME_LIB_DIR"
  67 +echo "SHERPA_ONNXRUNTIME_INCLUDE_DIR $SHERPA_ONNXRUNTIME_INCLUDE_DIR"
  68 +
  69 +cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \
  70 + -DCMAKE_BUILD_TYPE=Release \
  71 + -DBUILD_SHARED_LIBS=ON \
  72 + -DSHERPA_ONNX_ENABLE_PYTHON=OFF \
  73 + -DSHERPA_ONNX_ENABLE_TESTS=OFF \
  74 + -DSHERPA_ONNX_ENABLE_CHECK=OFF \
  75 + -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \
  76 + -DSHERPA_ONNX_ENABLE_JNI=ON \
  77 + -DCMAKE_INSTALL_PREFIX=./install \
  78 + -DANDROID_ABI="x86_64" \
  79 + -DANDROID_PLATFORM=android-21 ..
  80 +
  81 +# make VERBOSE=1 -j4
  82 +make -j4
  83 +make install/strip
  84 +cp -fv android-onnxruntime-libs/jni/x86_64/libonnxruntime.so install/lib
1 function(download_onnxruntime) 1 function(download_onnxruntime)
2 include(FetchContent) 2 include(FetchContent)
3 3
4 - message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")  
5 - message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")  
6 -  
7 if(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64) 4 if(CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64)
8 # For embedded systems 5 # For embedded systems
9 set(possible_file_locations 6 set(possible_file_locations
@@ -93,15 +90,11 @@ function(download_onnxruntime) @@ -93,15 +90,11 @@ function(download_onnxruntime)
93 endif() 90 endif()
94 message(STATUS "onnxruntime is downloaded to ${onnxruntime_SOURCE_DIR}") 91 message(STATUS "onnxruntime is downloaded to ${onnxruntime_SOURCE_DIR}")
95 92
96 - if(ANDROID)  
97 - set(location_onnxruntime ${onnxruntime_SOURCE_DIR}/lib/libonnxruntime.so)  
98 - else()  
99 - find_library(location_onnxruntime onnxruntime  
100 - PATHS  
101 - "${onnxruntime_SOURCE_DIR}/lib"  
102 - NO_CMAKE_SYSTEM_PATH  
103 - )  
104 - endif() 93 + find_library(location_onnxruntime onnxruntime
  94 + PATHS
  95 + "${onnxruntime_SOURCE_DIR}/lib"
  96 + NO_CMAKE_SYSTEM_PATH
  97 + )
105 98
106 message(STATUS "location_onnxruntime: ${location_onnxruntime}") 99 message(STATUS "location_onnxruntime: ${location_onnxruntime}")
107 100
@@ -123,7 +116,6 @@ function(download_onnxruntime) @@ -123,7 +116,6 @@ function(download_onnxruntime)
123 ) 116 )
124 endif() 117 endif()
125 118
126 -  
127 if(UNIX AND NOT APPLE) 119 if(UNIX AND NOT APPLE)
128 file(GLOB onnxruntime_lib_files "${onnxruntime_SOURCE_DIR}/lib/lib*") 120 file(GLOB onnxruntime_lib_files "${onnxruntime_SOURCE_DIR}/lib/lib*")
129 elseif(APPLE) 121 elseif(APPLE)
@@ -139,19 +131,32 @@ endfunction() @@ -139,19 +131,32 @@ endfunction()
139 # First, we try to locate the header and the lib if the use has already 131 # First, we try to locate the header and the lib if the use has already
140 # installed onnxruntime. Otherwise, we will download the pre-compiled lib 132 # installed onnxruntime. Otherwise, we will download the pre-compiled lib
141 133
142 -find_path(location_onnxruntime_header_dir onnxruntime_cxx_api.h  
143 - PATHS  
144 - /usr/include  
145 - /usr/local/include  
146 -) 134 +message(STATUS "CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}")
  135 +message(STATUS "CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
  136 +
  137 +if(ANDROID)
  138 + set(location_onnxruntime_header_dir $ENV{SHERPA_ONNXRUNTIME_INCLUDE_DIR})
  139 +else()
  140 + find_path(location_onnxruntime_header_dir onnxruntime_cxx_api.h
  141 + PATHS
  142 + /usr/include
  143 + /usr/local/include
  144 + )
  145 +endif()
  146 +
147 message(STATUS "location_onnxruntime_header_dir: ${location_onnxruntime_header_dir}") 147 message(STATUS "location_onnxruntime_header_dir: ${location_onnxruntime_header_dir}")
148 148
149 -find_library(location_onnxruntime_lib onnxruntime  
150 - PATHS  
151 - /lib  
152 - /usr/lib  
153 - /usr/local/lib  
154 -) 149 +if(ANDROID)
  150 + set(location_onnxruntime_lib $ENV{SHERPA_ONNXRUNTIME_LIB_DIR}/libonnxruntime.so)
  151 +else()
  152 + find_library(location_onnxruntime_lib onnxruntime
  153 + PATHS
  154 + /lib
  155 + /usr/lib
  156 + /usr/local/lib
  157 + )
  158 +endif()
  159 +
155 message(STATUS "location_onnxruntime_lib: ${location_onnxruntime_lib}") 160 message(STATUS "location_onnxruntime_lib: ${location_onnxruntime_lib}")
156 161
157 if(location_onnxruntime_header_dir AND location_onnxruntime_lib) 162 if(location_onnxruntime_header_dir AND location_onnxruntime_lib)
@@ -164,4 +169,3 @@ else() @@ -164,4 +169,3 @@ else()
164 message(STATUS "Could not find a pre-installed onnxruntime. Downloading pre-compiled onnxruntime") 169 message(STATUS "Could not find a pre-installed onnxruntime. Downloading pre-compiled onnxruntime")
165 download_onnxruntime() 170 download_onnxruntime()
166 endif() 171 endif()
167 -  
@@ -5,6 +5,23 @@ @@ -5,6 +5,23 @@
5 5
6 #ifndef SHERPA_ONNX_CSRC_MACROS_H_ 6 #ifndef SHERPA_ONNX_CSRC_MACROS_H_
7 #define SHERPA_ONNX_CSRC_MACROS_H_ 7 #define SHERPA_ONNX_CSRC_MACROS_H_
  8 +#include <stdio.h>
  9 +
  10 +#if __ANDROID_API__ >= 8
  11 +#include "android/log.h"
  12 +#define SHERPA_ONNX_LOGE(...) \
  13 + do { \
  14 + fprintf(stderr, ##__VA_ARGS__); \
  15 + fprintf(stderr, "\n"); \
  16 + __android_log_print(ANDROID_LOG_WARN, "sherpa-onnx", ##__VA_ARGS__); \
  17 + } while (0)
  18 +#else
  19 +#define SHERPA_ONNX_LOGE(...) \
  20 + do { \
  21 + fprintf(stderr, ##__VA_ARGS__); \
  22 + fprintf(stderr, "\n"); \
  23 + } while (0)
  24 +#endif
8 25
9 #define SHERPA_ONNX_READ_META_DATA(dst, src_key) \ 26 #define SHERPA_ONNX_READ_META_DATA(dst, src_key) \
10 do { \ 27 do { \
@@ -37,7 +37,6 @@ std::string OnlineRecognizerConfig::ToString() const { @@ -37,7 +37,6 @@ std::string OnlineRecognizerConfig::ToString() const {
37 os << "OnlineRecognizerConfig("; 37 os << "OnlineRecognizerConfig(";
38 os << "feat_config=" << feat_config.ToString() << ", "; 38 os << "feat_config=" << feat_config.ToString() << ", ";
39 os << "model_config=" << model_config.ToString() << ", "; 39 os << "model_config=" << model_config.ToString() << ", ";
40 - os << "tokens=\"" << tokens << "\", ";  
41 os << "endpoint_config=" << endpoint_config.ToString() << ", "; 40 os << "endpoint_config=" << endpoint_config.ToString() << ", ";
42 os << "enable_endpoint=" << (enable_endpoint ? "True" : "False") << ")"; 41 os << "enable_endpoint=" << (enable_endpoint ? "True" : "False") << ")";
43 42
@@ -49,7 +48,7 @@ class OnlineRecognizer::Impl { @@ -49,7 +48,7 @@ class OnlineRecognizer::Impl {
49 explicit Impl(const OnlineRecognizerConfig &config) 48 explicit Impl(const OnlineRecognizerConfig &config)
50 : config_(config), 49 : config_(config),
51 model_(OnlineTransducerModel::Create(config.model_config)), 50 model_(OnlineTransducerModel::Create(config.model_config)),
52 - sym_(config.tokens), 51 + sym_(config.model_config.tokens),
53 endpoint_(config_.endpoint_config) { 52 endpoint_(config_.endpoint_config) {
54 decoder_ = 53 decoder_ =
55 std::make_unique<OnlineTransducerGreedySearchDecoder>(model_.get()); 54 std::make_unique<OnlineTransducerGreedySearchDecoder>(model_.get());
@@ -59,7 +58,7 @@ class OnlineRecognizer::Impl { @@ -59,7 +58,7 @@ class OnlineRecognizer::Impl {
59 explicit Impl(AAssetManager *mgr, const OnlineRecognizerConfig &config) 58 explicit Impl(AAssetManager *mgr, const OnlineRecognizerConfig &config)
60 : config_(config), 59 : config_(config),
61 model_(OnlineTransducerModel::Create(mgr, config.model_config)), 60 model_(OnlineTransducerModel::Create(mgr, config.model_config)),
62 - sym_(mgr, config.tokens), 61 + sym_(mgr, config.model_config.tokens),
63 endpoint_(config_.endpoint_config) { 62 endpoint_(config_.endpoint_config) {
64 decoder_ = 63 decoder_ =
65 std::make_unique<OnlineTransducerGreedySearchDecoder>(model_.get()); 64 std::make_unique<OnlineTransducerGreedySearchDecoder>(model_.get());
@@ -27,7 +27,6 @@ struct OnlineRecognizerResult { @@ -27,7 +27,6 @@ struct OnlineRecognizerResult {
27 struct OnlineRecognizerConfig { 27 struct OnlineRecognizerConfig {
28 FeatureExtractorConfig feat_config; 28 FeatureExtractorConfig feat_config;
29 OnlineTransducerModelConfig model_config; 29 OnlineTransducerModelConfig model_config;
30 - std::string tokens;  
31 EndpointConfig endpoint_config; 30 EndpointConfig endpoint_config;
32 bool enable_endpoint; 31 bool enable_endpoint;
33 32
@@ -35,12 +34,10 @@ struct OnlineRecognizerConfig { @@ -35,12 +34,10 @@ struct OnlineRecognizerConfig {
35 34
36 OnlineRecognizerConfig(const FeatureExtractorConfig &feat_config, 35 OnlineRecognizerConfig(const FeatureExtractorConfig &feat_config,
37 const OnlineTransducerModelConfig &model_config, 36 const OnlineTransducerModelConfig &model_config,
38 - const std::string &tokens,  
39 const EndpointConfig &endpoint_config, 37 const EndpointConfig &endpoint_config,
40 bool enable_endpoint) 38 bool enable_endpoint)
41 : feat_config(feat_config), 39 : feat_config(feat_config),
42 model_config(model_config), 40 model_config(model_config),
43 - tokens(tokens),  
44 endpoint_config(endpoint_config), 41 endpoint_config(endpoint_config),
45 enable_endpoint(enable_endpoint) {} 42 enable_endpoint(enable_endpoint) {}
46 43
@@ -14,6 +14,7 @@ std::string OnlineTransducerModelConfig::ToString() const { @@ -14,6 +14,7 @@ std::string OnlineTransducerModelConfig::ToString() const {
14 os << "encoder_filename=\"" << encoder_filename << "\", "; 14 os << "encoder_filename=\"" << encoder_filename << "\", ";
15 os << "decoder_filename=\"" << decoder_filename << "\", "; 15 os << "decoder_filename=\"" << decoder_filename << "\", ";
16 os << "joiner_filename=\"" << joiner_filename << "\", "; 16 os << "joiner_filename=\"" << joiner_filename << "\", ";
  17 + os << "tokens=\"" << tokens << "\", ";
17 os << "num_threads=" << num_threads << ", "; 18 os << "num_threads=" << num_threads << ", ";
18 os << "debug=" << (debug ? "True" : "False") << ")"; 19 os << "debug=" << (debug ? "True" : "False") << ")";
19 20
@@ -12,6 +12,7 @@ struct OnlineTransducerModelConfig { @@ -12,6 +12,7 @@ struct OnlineTransducerModelConfig {
12 std::string encoder_filename; 12 std::string encoder_filename;
13 std::string decoder_filename; 13 std::string decoder_filename;
14 std::string joiner_filename; 14 std::string joiner_filename;
  15 + std::string tokens;
15 int32_t num_threads; 16 int32_t num_threads;
16 bool debug = false; 17 bool debug = false;
17 18
@@ -19,10 +20,12 @@ struct OnlineTransducerModelConfig { @@ -19,10 +20,12 @@ struct OnlineTransducerModelConfig {
19 OnlineTransducerModelConfig(const std::string &encoder_filename, 20 OnlineTransducerModelConfig(const std::string &encoder_filename,
20 const std::string &decoder_filename, 21 const std::string &decoder_filename,
21 const std::string &joiner_filename, 22 const std::string &joiner_filename,
22 - int32_t num_threads, bool debug) 23 + const std::string &tokens, int32_t num_threads,
  24 + bool debug)
23 : encoder_filename(encoder_filename), 25 : encoder_filename(encoder_filename),
24 decoder_filename(decoder_filename), 26 decoder_filename(decoder_filename),
25 joiner_filename(joiner_filename), 27 joiner_filename(joiner_filename),
  28 + tokens(tokens),
26 num_threads(num_threads), 29 num_threads(num_threads),
27 debug(debug) {} 30 debug(debug) {}
28 31
@@ -141,9 +141,8 @@ std::vector<char> ReadFile(AAssetManager *mgr, const std::string &filename) { @@ -141,9 +141,8 @@ std::vector<char> ReadFile(AAssetManager *mgr, const std::string &filename) {
141 auto p = reinterpret_cast<const char *>(AAsset_getBuffer(asset)); 141 auto p = reinterpret_cast<const char *>(AAsset_getBuffer(asset));
142 size_t asset_length = AAsset_getLength(asset); 142 size_t asset_length = AAsset_getLength(asset);
143 143
144 - AAsset_close(asset);  
145 -  
146 std::vector<char> buffer(p, p + asset_length); 144 std::vector<char> buffer(p, p + asset_length);
  145 + AAsset_close(asset);
147 146
148 return buffer; 147 return buffer;
149 } 148 }
@@ -65,7 +65,7 @@ as the device_name. @@ -65,7 +65,7 @@ as the device_name.
65 65
66 sherpa_onnx::OnlineRecognizerConfig config; 66 sherpa_onnx::OnlineRecognizerConfig config;
67 67
68 - config.tokens = argv[1]; 68 + config.model_config.tokens = argv[1];
69 69
70 config.model_config.debug = false; 70 config.model_config.debug = false;
71 config.model_config.encoder_filename = argv[2]; 71 config.model_config.encoder_filename = argv[2];
@@ -58,7 +58,7 @@ for a list of pre-trained models to download. @@ -58,7 +58,7 @@ for a list of pre-trained models to download.
58 signal(SIGINT, Handler); 58 signal(SIGINT, Handler);
59 59
60 sherpa_onnx::OnlineRecognizerConfig config; 60 sherpa_onnx::OnlineRecognizerConfig config;
61 - config.tokens = argv[1]; 61 + config.model_config.tokens = argv[1];
62 62
63 config.model_config.debug = false; 63 config.model_config.debug = false;
64 config.model_config.encoder_filename = argv[2]; 64 config.model_config.encoder_filename = argv[2];
@@ -35,7 +35,7 @@ for a list of pre-trained models to download. @@ -35,7 +35,7 @@ for a list of pre-trained models to download.
35 35
36 sherpa_onnx::OnlineRecognizerConfig config; 36 sherpa_onnx::OnlineRecognizerConfig config;
37 37
38 - config.tokens = argv[1]; 38 + config.model_config.tokens = argv[1];
39 39
40 config.model_config.debug = false; 40 config.model_config.debug = false;
41 config.model_config.encoder_filename = argv[2]; 41 config.model_config.encoder_filename = argv[2];
@@ -19,23 +19,9 @@ @@ -19,23 +19,9 @@
19 #include <fstream> 19 #include <fstream>
20 #endif 20 #endif
21 21
22 -#if __ANDROID_API__ >= 8  
23 -#include "android/log.h"  
24 -#define SHERPA_ONNX_LOGE(...) \  
25 - do { \  
26 - fprintf(stderr, ##__VA_ARGS__); \  
27 - fprintf(stderr, "\n"); \  
28 - __android_log_print(ANDROID_LOG_WARN, "sherpa-onnx", ##__VA_ARGS__); \  
29 - } while (0)  
30 -#else  
31 -#define SHERPA_ONNX_LOGE(...) \  
32 - do { \  
33 - fprintf(stderr, ##__VA_ARGS__); \  
34 - fprintf(stderr, "\n"); \  
35 - } while (0)  
36 -#endif  
37 - 22 +#include "sherpa-onnx/csrc/macros.h"
38 #include "sherpa-onnx/csrc/online-recognizer.h" 23 #include "sherpa-onnx/csrc/online-recognizer.h"
  24 +#include "sherpa-onnx/csrc/onnx-utils.h"
39 #include "sherpa-onnx/csrc/wave-reader.h" 25 #include "sherpa-onnx/csrc/wave-reader.h"
40 26
41 #define SHERPA_ONNX_EXTERN_C extern "C" 27 #define SHERPA_ONNX_EXTERN_C extern "C"
@@ -160,14 +146,6 @@ static OnlineRecognizerConfig GetConfig(JNIEnv *env, jobject config) { @@ -160,14 +146,6 @@ static OnlineRecognizerConfig GetConfig(JNIEnv *env, jobject config) {
160 ans.endpoint_config.rule3.min_utterance_length = 146 ans.endpoint_config.rule3.min_utterance_length =
161 env->GetFloatField(rule3, fid); 147 env->GetFloatField(rule3, fid);
162 148
163 - //---------- tokens ----------  
164 -  
165 - fid = env->GetFieldID(cls, "tokens", "Ljava/lang/String;");  
166 - jstring s = (jstring)env->GetObjectField(config, fid);  
167 - const char *p = env->GetStringUTFChars(s, nullptr);  
168 - ans.tokens = p;  
169 - env->ReleaseStringUTFChars(s, p);  
170 -  
171 //---------- model config ---------- 149 //---------- model config ----------
172 fid = env->GetFieldID(cls, "modelConfig", 150 fid = env->GetFieldID(cls, "modelConfig",
173 "Lcom/k2fsa/sherpa/onnx/OnlineTransducerModelConfig;"); 151 "Lcom/k2fsa/sherpa/onnx/OnlineTransducerModelConfig;");
@@ -175,8 +153,8 @@ static OnlineRecognizerConfig GetConfig(JNIEnv *env, jobject config) { @@ -175,8 +153,8 @@ static OnlineRecognizerConfig GetConfig(JNIEnv *env, jobject config) {
175 jclass model_config_cls = env->GetObjectClass(model_config); 153 jclass model_config_cls = env->GetObjectClass(model_config);
176 154
177 fid = env->GetFieldID(model_config_cls, "encoder", "Ljava/lang/String;"); 155 fid = env->GetFieldID(model_config_cls, "encoder", "Ljava/lang/String;");
178 - s = (jstring)env->GetObjectField(model_config, fid);  
179 - p = env->GetStringUTFChars(s, nullptr); 156 + jstring s = (jstring)env->GetObjectField(model_config, fid);
  157 + const char *p = env->GetStringUTFChars(s, nullptr);
180 ans.model_config.encoder_filename = p; 158 ans.model_config.encoder_filename = p;
181 env->ReleaseStringUTFChars(s, p); 159 env->ReleaseStringUTFChars(s, p);
182 160
@@ -192,6 +170,12 @@ static OnlineRecognizerConfig GetConfig(JNIEnv *env, jobject config) { @@ -192,6 +170,12 @@ static OnlineRecognizerConfig GetConfig(JNIEnv *env, jobject config) {
192 ans.model_config.joiner_filename = p; 170 ans.model_config.joiner_filename = p;
193 env->ReleaseStringUTFChars(s, p); 171 env->ReleaseStringUTFChars(s, p);
194 172
  173 + fid = env->GetFieldID(model_config_cls, "tokens", "Ljava/lang/String;");
  174 + s = (jstring)env->GetObjectField(model_config, fid);
  175 + p = env->GetStringUTFChars(s, nullptr);
  176 + ans.model_config.tokens = p;
  177 + env->ReleaseStringUTFChars(s, p);
  178 +
195 fid = env->GetFieldID(model_config_cls, "numThreads", "I"); 179 fid = env->GetFieldID(model_config_cls, "numThreads", "I");
196 ans.model_config.num_threads = env->GetIntField(model_config, fid); 180 ans.model_config.num_threads = env->GetIntField(model_config, fid);
197 181
@@ -226,7 +210,6 @@ JNIEXPORT jlong JNICALL Java_com_k2fsa_sherpa_onnx_SherpaOnnx_new( @@ -226,7 +210,6 @@ JNIEXPORT jlong JNICALL Java_com_k2fsa_sherpa_onnx_SherpaOnnx_new(
226 SHERPA_ONNX_EXTERN_C 210 SHERPA_ONNX_EXTERN_C
227 JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_SherpaOnnx_delete( 211 JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_SherpaOnnx_delete(
228 JNIEnv *env, jobject /*obj*/, jlong ptr) { 212 JNIEnv *env, jobject /*obj*/, jlong ptr) {
229 - SHERPA_ONNX_LOGE("freed!");  
230 delete reinterpret_cast<sherpa_onnx::SherpaOnnx *>(ptr); 213 delete reinterpret_cast<sherpa_onnx::SherpaOnnx *>(ptr);
231 } 214 }
232 215
@@ -286,12 +269,9 @@ Java_com_k2fsa_sherpa_onnx_WaveReader_00024Companion_readWave( @@ -286,12 +269,9 @@ Java_com_k2fsa_sherpa_onnx_WaveReader_00024Companion_readWave(
286 return nullptr; 269 return nullptr;
287 } 270 }
288 271
289 - AAsset *asset = AAssetManager_open(mgr, p_filename, AASSET_MODE_BUFFER);  
290 - size_t asset_length = AAsset_getLength(asset);  
291 - std::vector<char> buffer(asset_length);  
292 - AAsset_read(asset, buffer.data(), asset_length); 272 + std::vector<char> buffer = sherpa_onnx::ReadFile(mgr, p_filename);
293 273
294 - std::istrstream is(buffer.data(), asset_length); 274 + std::istrstream is(buffer.data(), buffer.size());
295 #else 275 #else
296 std::ifstream is(p_filename, std::ios::binary); 276 std::ifstream is(p_filename, std::ios::binary);
297 #endif 277 #endif
@@ -300,9 +280,6 @@ Java_com_k2fsa_sherpa_onnx_WaveReader_00024Companion_readWave( @@ -300,9 +280,6 @@ Java_com_k2fsa_sherpa_onnx_WaveReader_00024Companion_readWave(
300 std::vector<float> samples = 280 std::vector<float> samples =
301 sherpa_onnx::ReadWave(is, expected_sample_rate, &is_ok); 281 sherpa_onnx::ReadWave(is, expected_sample_rate, &is_ok);
302 282
303 -#if __ANDROID_API__ >= 9  
304 - AAsset_close(asset);  
305 -#endif  
306 env->ReleaseStringUTFChars(filename, p_filename); 283 env->ReleaseStringUTFChars(filename, p_filename);
307 284
308 if (!is_ok) { 285 if (!is_ok) {
@@ -21,13 +21,12 @@ static void PybindOnlineRecognizerConfig(py::module *m) { @@ -21,13 +21,12 @@ static void PybindOnlineRecognizerConfig(py::module *m) {
21 using PyClass = OnlineRecognizerConfig; 21 using PyClass = OnlineRecognizerConfig;
22 py::class_<PyClass>(*m, "OnlineRecognizerConfig") 22 py::class_<PyClass>(*m, "OnlineRecognizerConfig")
23 .def(py::init<const FeatureExtractorConfig &, 23 .def(py::init<const FeatureExtractorConfig &,
24 - const OnlineTransducerModelConfig &, const std::string &,  
25 - const EndpointConfig &, bool>(),  
26 - py::arg("feat_config"), py::arg("model_config"), py::arg("tokens"), 24 + const OnlineTransducerModelConfig &, const EndpointConfig &,
  25 + bool>(),
  26 + py::arg("feat_config"), py::arg("model_config"),
27 py::arg("endpoint_config"), py::arg("enable_endpoint")) 27 py::arg("endpoint_config"), py::arg("enable_endpoint"))
28 .def_readwrite("feat_config", &PyClass::feat_config) 28 .def_readwrite("feat_config", &PyClass::feat_config)
29 .def_readwrite("model_config", &PyClass::model_config) 29 .def_readwrite("model_config", &PyClass::model_config)
30 - .def_readwrite("tokens", &PyClass::tokens)  
31 .def_readwrite("endpoint_config", &PyClass::endpoint_config) 30 .def_readwrite("endpoint_config", &PyClass::endpoint_config)
32 .def_readwrite("enable_endpoint", &PyClass::enable_endpoint) 31 .def_readwrite("enable_endpoint", &PyClass::enable_endpoint)
33 .def("__str__", &PyClass::ToString); 32 .def("__str__", &PyClass::ToString);
@@ -14,13 +14,14 @@ void PybindOnlineTransducerModelConfig(py::module *m) { @@ -14,13 +14,14 @@ void PybindOnlineTransducerModelConfig(py::module *m) {
14 using PyClass = OnlineTransducerModelConfig; 14 using PyClass = OnlineTransducerModelConfig;
15 py::class_<PyClass>(*m, "OnlineTransducerModelConfig") 15 py::class_<PyClass>(*m, "OnlineTransducerModelConfig")
16 .def(py::init<const std::string &, const std::string &, 16 .def(py::init<const std::string &, const std::string &,
17 - const std::string &, int32_t, bool>(), 17 + const std::string &, const std::string &, int32_t, bool>(),
18 py::arg("encoder_filename"), py::arg("decoder_filename"), 18 py::arg("encoder_filename"), py::arg("decoder_filename"),
19 - py::arg("joiner_filename"), py::arg("num_threads"),  
20 - py::arg("debug") = false) 19 + py::arg("joiner_filename"), py::arg("tokens"),
  20 + py::arg("num_threads"), py::arg("debug") = false)
21 .def_readwrite("encoder_filename", &PyClass::encoder_filename) 21 .def_readwrite("encoder_filename", &PyClass::encoder_filename)
22 .def_readwrite("decoder_filename", &PyClass::decoder_filename) 22 .def_readwrite("decoder_filename", &PyClass::decoder_filename)
23 .def_readwrite("joiner_filename", &PyClass::joiner_filename) 23 .def_readwrite("joiner_filename", &PyClass::joiner_filename)
  24 + .def_readwrite("tokens", &PyClass::tokens)
24 .def_readwrite("num_threads", &PyClass::num_threads) 25 .def_readwrite("num_threads", &PyClass::num_threads)
25 .def_readwrite("debug", &PyClass::debug) 26 .def_readwrite("debug", &PyClass::debug)
26 .def("__str__", &PyClass::ToString); 27 .def("__str__", &PyClass::ToString);
@@ -85,6 +85,7 @@ class OnlineRecognizer(object): @@ -85,6 +85,7 @@ class OnlineRecognizer(object):
85 encoder_filename=encoder, 85 encoder_filename=encoder,
86 decoder_filename=decoder, 86 decoder_filename=decoder,
87 joiner_filename=joiner, 87 joiner_filename=joiner,
  88 + tokens=tokens,
88 num_threads=num_threads, 89 num_threads=num_threads,
89 ) 90 )
90 91
@@ -102,7 +103,6 @@ class OnlineRecognizer(object): @@ -102,7 +103,6 @@ class OnlineRecognizer(object):
102 recognizer_config = OnlineRecognizerConfig( 103 recognizer_config = OnlineRecognizerConfig(
103 feat_config=feat_config, 104 feat_config=feat_config,
104 model_config=model_config, 105 model_config=model_config,
105 - tokens=tokens,  
106 endpoint_config=endpoint_config, 106 endpoint_config=endpoint_config,
107 enable_endpoint=enable_endpoint_detection, 107 enable_endpoint=enable_endpoint_detection,
108 ) 108 )