react-native-sherpa-onnx 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -111,6 +111,46 @@ internal class SherpaOnnxTtsHelper(
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
/**
|
|
115
|
+
* libsherpa-onnx-jni looks up `invoke([F)Ljava/lang/Integer` (see sherpa-onnx `offline-tts.cc` CallCallback).
|
|
116
|
+
* Kotlin `Function1<*, Int>` compiles to `invoke([F)I`, so GetMethodID fails and JNI aborts.
|
|
117
|
+
* Using [java.lang.Integer] as the type parameter yields the boxed JVM signature the JNI expects.
|
|
118
|
+
* The cast is only for the Kotlin API (`generateWithCallback` still declares `Function1<FloatArray, Int>`).
|
|
119
|
+
*/
|
|
120
|
+
/** Box for JNI: must be real [java.lang.Integer], not Kotlin [Int] (primitive `invoke([F)I` breaks sherpa JNI). */
|
|
121
|
+
@Suppress("DEPRECATION")
|
|
122
|
+
private fun boxForTtsJni(n: Int): java.lang.Integer = java.lang.Integer(n)
|
|
123
|
+
|
|
124
|
+
@Suppress("UNCHECKED_CAST")
|
|
125
|
+
private fun ttsChunkCallbackForJni(
|
|
126
|
+
sentenceChunkSizes: MutableList<Int>
|
|
127
|
+
): kotlin.Function1<FloatArray, Int> {
|
|
128
|
+
val boxed =
|
|
129
|
+
object : kotlin.jvm.functions.Function1<FloatArray, java.lang.Integer> {
|
|
130
|
+
override fun invoke(chunk: FloatArray): java.lang.Integer {
|
|
131
|
+
sentenceChunkSizes.add(chunk.size)
|
|
132
|
+
return boxForTtsJni(chunk.size)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return boxed as kotlin.Function1<FloatArray, Int>
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@Suppress("UNCHECKED_CAST")
|
|
139
|
+
private fun ttsStreamChunkCallbackForJni(
|
|
140
|
+
cancelled: AtomicBoolean,
|
|
141
|
+
onChunk: (FloatArray) -> Unit
|
|
142
|
+
): kotlin.Function1<FloatArray, Int> {
|
|
143
|
+
val boxed =
|
|
144
|
+
object : kotlin.jvm.functions.Function1<FloatArray, java.lang.Integer> {
|
|
145
|
+
override fun invoke(chunk: FloatArray): java.lang.Integer {
|
|
146
|
+
if (cancelled.get()) return boxForTtsJni(0)
|
|
147
|
+
onChunk(chunk)
|
|
148
|
+
return boxForTtsJni(chunk.size)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return boxed as kotlin.Function1<FloatArray, Int>
|
|
152
|
+
}
|
|
153
|
+
|
|
114
154
|
/** Single-thread executor for TTS init so the RN bridge thread is not blocked (avoids Inspector/dev WebSocket races in debug builds). */
|
|
115
155
|
private val ttsInitExecutor = Executors.newSingleThreadExecutor()
|
|
116
156
|
|
|
@@ -453,6 +493,7 @@ internal class SherpaOnnxTtsHelper(
|
|
|
453
493
|
}
|
|
454
494
|
val sid = getSid(options)
|
|
455
495
|
val speed = getSpeed(options)
|
|
496
|
+
val sentenceChunkSizes = mutableListOf<Int>()
|
|
456
497
|
val audio = when {
|
|
457
498
|
hasReferenceAudio(options) && (inst.isZipvoice || inst.isPocket) -> {
|
|
458
499
|
if (inst.isZipvoice) {
|
|
@@ -467,7 +508,11 @@ internal class SherpaOnnxTtsHelper(
|
|
|
467
508
|
}
|
|
468
509
|
}
|
|
469
510
|
val config = parseGenerationConfig(options) ?: GenerationConfig(speed = speed, sid = sid)
|
|
470
|
-
inst.tts!!.
|
|
511
|
+
inst.tts!!.generateWithConfigAndCallback(
|
|
512
|
+
text,
|
|
513
|
+
config,
|
|
514
|
+
ttsChunkCallbackForJni(sentenceChunkSizes)
|
|
515
|
+
)
|
|
471
516
|
}
|
|
472
517
|
hasReferenceAudio(options) -> {
|
|
473
518
|
Log.e("SherpaOnnxTts", "TTS_GENERATE_ERROR: Reference audio is not supported for this TTS model type")
|
|
@@ -485,12 +530,15 @@ internal class SherpaOnnxTtsHelper(
|
|
|
485
530
|
)
|
|
486
531
|
return
|
|
487
532
|
}
|
|
488
|
-
else ->
|
|
489
|
-
|
|
533
|
+
else -> {
|
|
534
|
+
val tts = inst.tts
|
|
535
|
+
if (tts == null) {
|
|
490
536
|
Log.e("SherpaOnnxTts", "TTS_GENERATE_ERROR: TTS not initialized")
|
|
491
537
|
promise.reject("TTS_GENERATE_ERROR", "TTS not initialized")
|
|
492
538
|
return
|
|
493
539
|
}
|
|
540
|
+
tts.generateWithCallback(text, sid, speed, ttsChunkCallbackForJni(sentenceChunkSizes))
|
|
541
|
+
}
|
|
494
542
|
}
|
|
495
543
|
val map = Arguments.createMap()
|
|
496
544
|
val samplesArray = Arguments.createArray()
|
|
@@ -564,18 +612,23 @@ internal class SherpaOnnxTtsHelper(
|
|
|
564
612
|
when {
|
|
565
613
|
hasReferenceAudio(options) && inst.isPocket -> {
|
|
566
614
|
val config = parseGenerationConfig(options) ?: GenerationConfig(speed = speed, sid = sid)
|
|
567
|
-
inst.tts!!.generateWithConfigAndCallback(
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
chunk
|
|
571
|
-
|
|
615
|
+
inst.tts!!.generateWithConfigAndCallback(
|
|
616
|
+
text,
|
|
617
|
+
config,
|
|
618
|
+
ttsStreamChunkCallbackForJni(inst.ttsStreamCancelled) { chunk ->
|
|
619
|
+
emitChunk(instanceId, requestId, chunk, sampleRate, 0f, false)
|
|
620
|
+
}
|
|
621
|
+
)
|
|
572
622
|
}
|
|
573
623
|
else -> {
|
|
574
|
-
inst.tts!!.generateWithCallback(
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
624
|
+
inst.tts!!.generateWithCallback(
|
|
625
|
+
text,
|
|
626
|
+
sid,
|
|
627
|
+
speed,
|
|
628
|
+
ttsStreamChunkCallbackForJni(inst.ttsStreamCancelled) { chunk ->
|
|
629
|
+
emitChunk(instanceId, requestId, chunk, sampleRate, 0f, false)
|
|
630
|
+
}
|
|
631
|
+
)
|
|
579
632
|
}
|
|
580
633
|
}
|
|
581
634
|
if (!inst.ttsStreamCancelled.get()) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-sherpa-onnx",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Offline Speech-to-text, text-to-speech, speaker diarization, speech enhancement, source separation, and VAD with sherpa-onnx for React NativeSpeech-to-Text with sherpa-onnx for React Native",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|