diff --git a/.github/workflows/test-dart.yaml b/.github/workflows/test-dart.yaml index 580071b81..1803af9c4 100644 --- a/.github/workflows/test-dart.yaml +++ b/.github/workflows/test-dart.yaml @@ -8,6 +8,7 @@ on: - '.github/workflows/test-dart.yaml' - '.github/scripts/test-dart.sh' - 'dart-api-examples/**' + - 'flutter/**' pull_request: branches: - master @@ -15,6 +16,7 @@ on: - '.github/workflows/test-dart.yaml' - '.github/scripts/test-dart.sh' - 'dart-api-examples/**' + - 'flutter/**' workflow_dispatch: @@ -29,7 +31,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest] + os: [ubuntu-latest, macos-latest] #, windows-latest] steps: - uses: actions/checkout@v4 @@ -75,16 +77,29 @@ jobs: -DSHERPA_ONNX_ENABLE_BINARY=OFF \ -DCMAKE_INSTALL_PREFIX=./install \ .. - make -j install + + cmake --build . --target install --config Release - name: Copy libs shell: bash run: | - cp -v build/install/lib/lib* ./sherpa-onnx/flutter/linux/ + if [[ ${{ matrix.os }} == ubuntu-latest ]]; then + os=linux + elif [[ ${{ matrix.os }} == macos-latest ]]; then + os=macos + elif [[ ${{ matrix.os }} == windows-latest ]]; then + os=windows + fi + + if [[ $os == windows ]]; then + cp -fv build/install/lib/*.dll ./flutter/sherpa_onnx_$os/$os + else + cp -fv build/install/lib/lib* ./flutter/sherpa_onnx_$os/$os + fi echo "--------------------" - ls -lh ./sherpa-onnx/flutter/linux/ + ls -lh ./flutter/sherpa_onnx_$os/$os - name: Run tests shell: bash @@ -93,5 +108,6 @@ jobs: cp scripts/dart/non-streaming-asr-pubspec.yaml dart-api-examples/non-streaming-asr/pubspec.yaml cp scripts/dart/streaming-asr-pubspec.yaml dart-api-examples/streaming-asr/pubspec.yaml cp scripts/dart/tts-pubspec.yaml dart-api-examples/tts/pubspec.yaml + cp scripts/dart/sherpa-onnx-pubspec.yaml flutter/sherpa_onnx/pubspec.yaml .github/scripts/test-dart.sh diff --git a/build-android-arm64-v8a.sh b/build-android-arm64-v8a.sh index 2f9be5a4b..b48b5b246 100755 --- a/build-android-arm64-v8a.sh +++ b/build-android-arm64-v8a.sh @@ -67,6 +67,14 @@ if [ -z $SHERPA_ONNX_ENABLE_BINARY ]; then SHERPA_ONNX_ENABLE_BINARY=OFF fi +if [ -z $SHERPA_ONNX_ENABLE_C_API ]; then + SHERPA_ONNX_ENABLE_C_API=OFF +fi + +if [ -z $SHERPA_ONNX_ENABLE_JNI ]; then + SHERPA_ONNX_ENABLE_JNI=ON +fi + cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \ -DSHERPA_ONNX_ENABLE_TTS=$SHERPA_ONNX_ENABLE_TTS \ -DSHERPA_ONNX_ENABLE_BINARY=$SHERPA_ONNX_ENABLE_BINARY \ @@ -80,8 +88,8 @@ cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" -DSHERPA_ONNX_ENABLE_TESTS=OFF \ -DSHERPA_ONNX_ENABLE_CHECK=OFF \ -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \ - -DSHERPA_ONNX_ENABLE_JNI=ON \ - -DSHERPA_ONNX_ENABLE_C_API=OFF \ + -DSHERPA_ONNX_ENABLE_JNI=$SHERPA_ONNX_ENABLE_JNI \ + -DSHERPA_ONNX_ENABLE_C_API=$SHERPA_ONNX_ENABLE_C_API \ -DCMAKE_INSTALL_PREFIX=./install \ -DANDROID_ABI="arm64-v8a" \ -DANDROID_PLATFORM=android-21 .. diff --git a/build-android-armv7-eabi.sh b/build-android-armv7-eabi.sh index a574b8f66..b9f28b195 100755 --- a/build-android-armv7-eabi.sh +++ b/build-android-armv7-eabi.sh @@ -68,6 +68,14 @@ if [ -z $SHERPA_ONNX_ENABLE_BINARY ]; then SHERPA_ONNX_ENABLE_BINARY=OFF fi +if [ -z $SHERPA_ONNX_ENABLE_C_API ]; then + SHERPA_ONNX_ENABLE_C_API=OFF +fi + +if [ -z $SHERPA_ONNX_ENABLE_JNI ]; then + SHERPA_ONNX_ENABLE_JNI=ON +fi + cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \ -DSHERPA_ONNX_ENABLE_TTS=$SHERPA_ONNX_ENABLE_TTS \ -DSHERPA_ONNX_ENABLE_BINARY=$SHERPA_ONNX_ENABLE_BINARY \ @@ -81,8 +89,8 @@ cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" -DSHERPA_ONNX_ENABLE_TESTS=OFF \ -DSHERPA_ONNX_ENABLE_CHECK=OFF \ -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \ - -DSHERPA_ONNX_ENABLE_JNI=ON \ - -DSHERPA_ONNX_ENABLE_C_API=OFF \ + -DSHERPA_ONNX_ENABLE_JNI=$SHERPA_ONNX_ENABLE_JNI \ + -DSHERPA_ONNX_ENABLE_C_API=$SHERPA_ONNX_ENABLE_C_API \ -DCMAKE_INSTALL_PREFIX=./install \ -DANDROID_ABI="armeabi-v7a" -DANDROID_ARM_NEON=ON \ -DANDROID_PLATFORM=android-21 .. diff --git a/build-android-x86-64.sh b/build-android-x86-64.sh index 8119834d5..b88836749 100755 --- a/build-android-x86-64.sh +++ b/build-android-x86-64.sh @@ -68,6 +68,14 @@ if [ -z $SHERPA_ONNX_ENABLE_BINARY ]; then SHERPA_ONNX_ENABLE_BINARY=OFF fi +if [ -z $SHERPA_ONNX_ENABLE_C_API ]; then + SHERPA_ONNX_ENABLE_C_API=OFF +fi + +if [ -z $SHERPA_ONNX_ENABLE_JNI ]; then + SHERPA_ONNX_ENABLE_JNI=ON +fi + cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \ -DSHERPA_ONNX_ENABLE_TTS=$SHERPA_ONNX_ENABLE_TTS \ -DSHERPA_ONNX_ENABLE_BINARY=$SHERPA_ONNX_ENABLE_BINARY \ @@ -81,10 +89,10 @@ cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" -DSHERPA_ONNX_ENABLE_TESTS=OFF \ -DSHERPA_ONNX_ENABLE_CHECK=OFF \ -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \ - -DSHERPA_ONNX_ENABLE_JNI=ON \ + -DSHERPA_ONNX_ENABLE_JNI=$SHERPA_ONNX_ENABLE_JNI \ -DCMAKE_INSTALL_PREFIX=./install \ -DANDROID_ABI="x86_64" \ - -DSHERPA_ONNX_ENABLE_C_API=OFF \ + -DSHERPA_ONNX_ENABLE_C_API=$SHERPA_ONNX_ENABLE_C_API \ -DSHERPA_ONNX_ENABLE_WEBSOCKET=OFF \ -DANDROID_PLATFORM=android-21 .. diff --git a/build-android-x86.sh b/build-android-x86.sh index 4499fc396..657ae9a42 100755 --- a/build-android-x86.sh +++ b/build-android-x86.sh @@ -68,6 +68,14 @@ if [ -z $SHERPA_ONNX_ENABLE_BINARY ]; then SHERPA_ONNX_ENABLE_BINARY=OFF fi +if [ -z $SHERPA_ONNX_ENABLE_C_API ]; then + SHERPA_ONNX_ENABLE_C_API=OFF +fi + +if [ -z $SHERPA_ONNX_ENABLE_JNI ]; then + SHERPA_ONNX_ENABLE_JNI=ON +fi + cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" \ -DSHERPA_ONNX_ENABLE_TTS=$SHERPA_ONNX_ENABLE_TTS \ -DSHERPA_ONNX_ENABLE_BINARY=$SHERPA_ONNX_ENABLE_BINARY \ @@ -81,10 +89,10 @@ cmake -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK/build/cmake/android.toolchain.cmake" -DSHERPA_ONNX_ENABLE_TESTS=OFF \ -DSHERPA_ONNX_ENABLE_CHECK=OFF \ -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \ - -DSHERPA_ONNX_ENABLE_JNI=ON \ + -DSHERPA_ONNX_ENABLE_JNI=$SHERPA_ONNX_ENABLE_JNI \ -DCMAKE_INSTALL_PREFIX=./install \ -DANDROID_ABI="x86" \ - -DSHERPA_ONNX_ENABLE_C_API=OFF \ + -DSHERPA_ONNX_ENABLE_C_API=$SHERPA_ONNX_ENABLE_C_API \ -DSHERPA_ONNX_ENABLE_WEBSOCKET=OFF \ -DANDROID_PLATFORM=android-21 .. diff --git a/dart-api-examples/vad/bin/init.dart b/dart-api-examples/vad/bin/init.dart index 09f24793c..dc4d1ee4e 100644 --- a/dart-api-examples/vad/bin/init.dart +++ b/dart-api-examples/vad/bin/init.dart @@ -5,14 +5,6 @@ import 'package:path/path.dart' as p; import 'package:sherpa_onnx/sherpa_onnx.dart' as sherpa_onnx; Future initSherpaOnnx() async { - var uri = await Isolate.resolvePackageUri( - Uri.parse('package:sherpa_onnx/sherpa_onnx.dart')); - - if (uri == null) { - print('File not found'); - exit(1); - } - String platform = ''; if (Platform.isMacOS) { @@ -25,6 +17,14 @@ Future initSherpaOnnx() async { throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}'); } + var uri = await Isolate.resolvePackageUri( + Uri.parse('package:sherpa_onnx_$platform/any_path_is_ok_here.dart')); + + if (uri == null) { + print('File not found'); + exit(1); + } + final libPath = p.join(p.dirname(p.fromUri(uri)), '..', platform); sherpa_onnx.initBindings(libPath); } diff --git a/flutter-examples/.gitignore b/flutter-examples/.gitignore new file mode 100644 index 000000000..c21169b36 --- /dev/null +++ b/flutter-examples/.gitignore @@ -0,0 +1,138 @@ +# Do not remove or rename entries in this file, only add new ones +# See https://github.com/flutter/flutter/issues/128635 for more context. + +# Miscellaneous +*.class +*.lock +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# Visual Studio Code related +.classpath +.project +.settings/ +.vscode/* + +# Flutter repo-specific +/bin/cache/ +/bin/internal/bootstrap.bat +/bin/internal/bootstrap.sh +/bin/mingit/ +/dev/benchmarks/mega_gallery/ +/dev/bots/.recipe_deps +/dev/bots/android_tools/ +/dev/devicelab/ABresults*.json +/dev/docs/doc/ +/dev/docs/api_docs.zip +/dev/docs/flutter.docs.zip +/dev/docs/lib/ +/dev/docs/pubspec.yaml +/dev/integration_tests/**/xcuserdata +/dev/integration_tests/**/Pods +/packages/flutter/coverage/ +version +analysis_benchmark.json + +# packages file containing multi-root paths +.packages.generated + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +**/generated_plugin_registrant.dart +.packages +.pub-preload-cache/ +.pub-cache/ +.pub/ +build/ +flutter_*.png +linked_*.ds +unlinked.ds +unlinked_spec.ds + +# Android related +**/android/**/gradle-wrapper.jar +.gradle/ +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java +**/android/key.properties +*.jks + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/.last_build_id +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Flutter.podspec +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/ephemeral +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# macOS +**/Flutter/ephemeral/ +**/Pods/ +**/macos/Flutter/GeneratedPluginRegistrant.swift +**/macos/Flutter/ephemeral +**/xcuserdata/ + +# Windows +**/windows/flutter/generated_plugin_registrant.cc +**/windows/flutter/generated_plugin_registrant.h +**/windows/flutter/generated_plugins.cmake + +# Linux +**/linux/flutter/generated_plugin_registrant.cc +**/linux/flutter/generated_plugin_registrant.h +**/linux/flutter/generated_plugins.cmake + +# Coverage +coverage/ + +# Symbols +app.*.symbols + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +!/dev/ci/**/Gemfile.lock +!.vscode/settings.json diff --git a/flutter-examples/README.md b/flutter-examples/README.md index 66684ef62..ffc1ea592 100644 --- a/flutter-examples/README.md +++ b/flutter-examples/README.md @@ -7,4 +7,119 @@ This directory contains flutter examples of `sherpa-onnx`. flutter create --platforms windows,macos streaming_asr cd streaming_asr flutter pub get + +# to support a new platform, e.g., android, use + +cd streaming_asr +flutter create --platforms --org com.k2fsa.sherpa.onnx android ./ +``` + +To run with android, first use +``` +(py38) fangjuns-MacBook-Pro:streaming_asr fangjun$ flutter run devices +No devices found yet. Checking for wireless devices... + +No supported devices found with name or id matching 'android-arm64'. + +The following devices were found: +Mi 10 (mobile) • 61106679 • android-arm64 • Android 12 (API 31) +macOS (desktop) • macos • darwin-x64 • macOS 13.1 22C65 darwin-x64 +Chrome (web) • chrome • web-javascript • Google Chrome 126.0.6478.127 +``` +to find available devices. I have attached my Android phone (Xiaomi 10) to my computer +and it shows the device ID of my Android phone is `61106679`, so I use + +```bash +(py38) fangjuns-MacBook-Pro:streaming_asr fangjun$ flutter run -d 61106679 +``` + +to run it. + +If you get the following errors and hint: + +``` +BUILD FAILED in 2m 43s +Running Gradle task 'assembleDebug'... 165.3s + +┌─ Flutter Fix ───────────────────────────────────────────────────────────────────────────────────────────────────┐ +│ The plugin record_android requires a higher Android SDK version. │ +│ Fix this issue by adding the following to the file │ +│ /Users/fangjun/open-source/sherpa-onnx/flutter-examples/streaming_asr/android/app/build.gradle: │ +│ android { │ +│ defaultConfig { │ +│ minSdkVersion 23 │ +│ } │ +│ } │ +│ │ +│ │ +│ Following this change, your app will not be available to users running Android SDKs below 23. │ +│ Consider searching for a version of this plugin that supports these lower versions of the Android SDK instead. │ +│ For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration │ +└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +Error: Gradle task assembleDebug failed with exit code 1 +``` + +Please use the following changes: + +```diff +--- a/flutter-examples/streaming_asr/android/app/build.gradle ++++ b/flutter-examples/streaming_asr/android/app/build.gradle +@@ -38,7 +38,7 @@ android { + applicationId = "com.k2fsa.sherpa.onnx.streaming_asr" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. +- minSdk = flutter.minSdkVersion ++ minSdk = 23 + targetSdk = flutter.targetSdkVersion + versionCode = flutterVersionCode.toInteger() + versionName = flutterVersionName +``` + +If you get the following errors: + +``` +Launching lib/main.dart on Mi 10 in debug mode... +ERROR:/Users/fangjun/open-source/sherpa-onnx/flutter-examples/streaming_asr/build/record_android/intermediates/runtime_library_classes_jar/debug/clas +ses.jar: D8: com.android.tools.r8.internal.Hc: Sealed classes are not supported as program classes + +FAILURE: Build failed with an exception. + +* What went wrong: +Execution failed for task ':app:mergeLibDexDebug'. +> Could not resolve all files for configuration ':app:debugRuntimeClasspath'. + > Failed to transform classes.jar (project :record_android) to match attributes {artifactType=android-dex, asm-transformed-variant=NONE, com.andro +id.build.api.attributes.AgpVersionAttr=7.3.0, com.android.build.api.attributes.BuildTypeAttr=debug, com.android.build.gradle.internal.attributes.Vari +antAttr=debug, dexing-enable-desugaring=true, dexing-enable-jacoco-instrumentation=false, dexing-is-debuggable=true, dexing-min-sdk=23, org.gradle.ca +tegory=library, org.gradle.jvm.environment=android, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime, org.jetbrains.kotlin.platform.type +=androidJvm}. + > Execution failed for DexingWithClasspathTransform: /Users/fangjun/open-source/sherpa-onnx/flutter-examples/streaming_asr/build/record_android +/intermediates/runtime_library_classes_jar/debug/classes.jar. + > Error while dexing. + +* Try: +> Run with --stacktrace option to get the stack trace. +> Run with --info or --debug option to get more log output. +> Run with --scan to get full insights. + +* Get more help at https://help.gradle.org + +BUILD FAILED in 2m 10s +``` + +Please refer to +to make the following changes + +```diff +diff --git a/flutter-examples/streaming_asr/android/settings.gradle b/flutter-examples/streaming_asr/android/settings.gradle +index 536165d3..9b1a1012 100644 +--- a/flutter-examples/streaming_asr/android/settings.gradle ++++ b/flutter-examples/streaming_asr/android/settings.gradle +@@ -18,7 +18,7 @@ pluginManagement { + + plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" +- id "com.android.application" version "7.3.0" apply false ++ id "com.android.application" version "7.4.2" apply false + id "org.jetbrains.kotlin.android" version "1.7.10" apply false + } ``` diff --git a/flutter-examples/streaming_asr/.metadata b/flutter-examples/streaming_asr/.metadata index 2d2fe6b62..65a4a371c 100644 --- a/flutter-examples/streaming_asr/.metadata +++ b/flutter-examples/streaming_asr/.metadata @@ -15,10 +15,7 @@ migration: - platform: root create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 - - platform: macos - create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 - base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 - - platform: windows + - platform: android create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 diff --git a/flutter-examples/streaming_asr/android/.gitignore b/flutter-examples/streaming_asr/android/.gitignore new file mode 100644 index 000000000..6f568019d --- /dev/null +++ b/flutter-examples/streaming_asr/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/flutter-examples/streaming_asr/android/app/build.gradle b/flutter-examples/streaming_asr/android/app/build.gradle new file mode 100644 index 000000000..c63ee2874 --- /dev/null +++ b/flutter-examples/streaming_asr/android/app/build.gradle @@ -0,0 +1,58 @@ +plugins { + id "com.android.application" + id "kotlin-android" + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file("local.properties") +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader("UTF-8") { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty("flutter.versionCode") +if (flutterVersionCode == null) { + flutterVersionCode = "1" +} + +def flutterVersionName = localProperties.getProperty("flutter.versionName") +if (flutterVersionName == null) { + flutterVersionName = "1.0" +} + +android { + namespace = "com.k2fsa.sherpa.onnx.streaming_asr" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.k2fsa.sherpa.onnx.streaming_asr" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdk = 23 + targetSdk = flutter.targetSdkVersion + versionCode = flutterVersionCode.toInteger() + versionName = flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.debug + } + } +} + +flutter { + source = "../.." +} diff --git a/flutter-examples/streaming_asr/android/app/src/debug/AndroidManifest.xml b/flutter-examples/streaming_asr/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..399f6981d --- /dev/null +++ b/flutter-examples/streaming_asr/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/flutter-examples/streaming_asr/android/app/src/main/AndroidManifest.xml b/flutter-examples/streaming_asr/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..67823487b --- /dev/null +++ b/flutter-examples/streaming_asr/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/flutter-examples/streaming_asr/android/app/src/main/kotlin/com/k2fsa/sherpa/onnx/streaming_asr/MainActivity.kt b/flutter-examples/streaming_asr/android/app/src/main/kotlin/com/k2fsa/sherpa/onnx/streaming_asr/MainActivity.kt new file mode 100644 index 000000000..04af06c62 --- /dev/null +++ b/flutter-examples/streaming_asr/android/app/src/main/kotlin/com/k2fsa/sherpa/onnx/streaming_asr/MainActivity.kt @@ -0,0 +1,5 @@ +package com.k2fsa.sherpa.onnx.streaming_asr + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() diff --git a/flutter-examples/streaming_asr/android/app/src/main/res/drawable-v21/launch_background.xml b/flutter-examples/streaming_asr/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 000000000..f74085f3f --- /dev/null +++ b/flutter-examples/streaming_asr/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/flutter-examples/streaming_asr/android/app/src/main/res/drawable/launch_background.xml b/flutter-examples/streaming_asr/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000..304732f88 --- /dev/null +++ b/flutter-examples/streaming_asr/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..db77bb4b7 Binary files /dev/null and b/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..17987b79b Binary files /dev/null and b/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..09d439148 Binary files /dev/null and b/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..d5f1c8d34 Binary files /dev/null and b/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..4d6372eeb Binary files /dev/null and b/flutter-examples/streaming_asr/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/flutter-examples/streaming_asr/android/app/src/main/res/values-night/styles.xml b/flutter-examples/streaming_asr/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 000000000..06952be74 --- /dev/null +++ b/flutter-examples/streaming_asr/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/flutter-examples/streaming_asr/android/app/src/main/res/values/styles.xml b/flutter-examples/streaming_asr/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..cb1ef8805 --- /dev/null +++ b/flutter-examples/streaming_asr/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/flutter-examples/streaming_asr/android/app/src/profile/AndroidManifest.xml b/flutter-examples/streaming_asr/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000..399f6981d --- /dev/null +++ b/flutter-examples/streaming_asr/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/flutter-examples/streaming_asr/android/build.gradle b/flutter-examples/streaming_asr/android/build.gradle new file mode 100644 index 000000000..d2ffbffa4 --- /dev/null +++ b/flutter-examples/streaming_asr/android/build.gradle @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = "../build" +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/flutter-examples/streaming_asr/android/gradle.properties b/flutter-examples/streaming_asr/android/gradle.properties new file mode 100644 index 000000000..3b5b324f6 --- /dev/null +++ b/flutter-examples/streaming_asr/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError +android.useAndroidX=true +android.enableJetifier=true diff --git a/flutter-examples/streaming_asr/android/gradle/wrapper/gradle-wrapper.properties b/flutter-examples/streaming_asr/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..e1ca574ef --- /dev/null +++ b/flutter-examples/streaming_asr/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip diff --git a/flutter-examples/streaming_asr/android/settings.gradle b/flutter-examples/streaming_asr/android/settings.gradle new file mode 100644 index 000000000..9b1a10123 --- /dev/null +++ b/flutter-examples/streaming_asr/android/settings.gradle @@ -0,0 +1,25 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "7.4.2" apply false + id "org.jetbrains.kotlin.android" version "1.7.10" apply false +} + +include ":app" diff --git a/flutter-examples/streaming_asr/pubspec.lock b/flutter-examples/streaming_asr/pubspec.lock index 9cd8d6c5f..2e74e21f1 100644 --- a/flutter-examples/streaming_asr/pubspec.lock +++ b/flutter-examples/streaming_asr/pubspec.lock @@ -291,10 +291,11 @@ packages: sherpa_onnx: dependency: "direct main" description: - path: "../../sherpa-onnx/flutter" - relative: true - source: path - version: "1.9.29" + name: sherpa_onnx + sha256: b797a1297e1445d62ed73d23a044bd4407e9133f616b64339ba2d249f4b66743 + url: "https://pub.dev" + source: hosted + version: "1.10.2" sky_engine: dependency: transitive description: flutter diff --git a/flutter-examples/streaming_asr/pubspec.yaml b/flutter-examples/streaming_asr/pubspec.yaml index 558690ba3..6ffe37657 100644 --- a/flutter-examples/streaming_asr/pubspec.yaml +++ b/flutter-examples/streaming_asr/pubspec.yaml @@ -31,6 +31,8 @@ dependencies: url_launcher: ^6.2.6 sherpa_onnx: ^1.10.0 + # sherpa_onnx: + # path: ../../flutter/sherpa_onnx dev_dependencies: flutter_test: diff --git a/flutter/.gitignore b/flutter/.gitignore new file mode 100644 index 000000000..c21169b36 --- /dev/null +++ b/flutter/.gitignore @@ -0,0 +1,138 @@ +# Do not remove or rename entries in this file, only add new ones +# See https://github.com/flutter/flutter/issues/128635 for more context. + +# Miscellaneous +*.class +*.lock +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# Visual Studio Code related +.classpath +.project +.settings/ +.vscode/* + +# Flutter repo-specific +/bin/cache/ +/bin/internal/bootstrap.bat +/bin/internal/bootstrap.sh +/bin/mingit/ +/dev/benchmarks/mega_gallery/ +/dev/bots/.recipe_deps +/dev/bots/android_tools/ +/dev/devicelab/ABresults*.json +/dev/docs/doc/ +/dev/docs/api_docs.zip +/dev/docs/flutter.docs.zip +/dev/docs/lib/ +/dev/docs/pubspec.yaml +/dev/integration_tests/**/xcuserdata +/dev/integration_tests/**/Pods +/packages/flutter/coverage/ +version +analysis_benchmark.json + +# packages file containing multi-root paths +.packages.generated + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +**/generated_plugin_registrant.dart +.packages +.pub-preload-cache/ +.pub-cache/ +.pub/ +build/ +flutter_*.png +linked_*.ds +unlinked.ds +unlinked_spec.ds + +# Android related +**/android/**/gradle-wrapper.jar +.gradle/ +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java +**/android/key.properties +*.jks + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/.last_build_id +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Flutter.podspec +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/ephemeral +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# macOS +**/Flutter/ephemeral/ +**/Pods/ +**/macos/Flutter/GeneratedPluginRegistrant.swift +**/macos/Flutter/ephemeral +**/xcuserdata/ + +# Windows +**/windows/flutter/generated_plugin_registrant.cc +**/windows/flutter/generated_plugin_registrant.h +**/windows/flutter/generated_plugins.cmake + +# Linux +**/linux/flutter/generated_plugin_registrant.cc +**/linux/flutter/generated_plugin_registrant.h +**/linux/flutter/generated_plugins.cmake + +# Coverage +coverage/ + +# Symbols +app.*.symbols + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +!/dev/ci/**/Gemfile.lock +!.vscode/settings.json diff --git a/flutter/README.md b/flutter/README.md new file mode 100644 index 000000000..e2f7335c5 --- /dev/null +++ b/flutter/README.md @@ -0,0 +1,10 @@ +# Introduction + +This directory contains the source code of the flutter +package [sherpa-onnx](https://github.com/k2-fsa/sherpa-onnx) + +Caution: You are not expected to use this directory directly. + +This directory is for developers only. + +For common users, please use our package at diff --git a/flutter/notes.md b/flutter/notes.md new file mode 100644 index 000000000..cff211600 --- /dev/null +++ b/flutter/notes.md @@ -0,0 +1,34 @@ +# Introduction + +This file keeps some notes about how packages in this directory +are created. + +1. Create `sherpa_onnx`. + +```bash +flutter create --template plugin sherpa_onnx +``` + +2. Create `sherpa_onnx_macos` + +```bash +flutter create --template plugin_ffi --platforms macos sherpa_onnx_macos +``` + +3. Create `sherpa_onnx_linux + +```bash +flutter create --template plugin_ffi --platforms linux sherpa_onnx_linux +``` + +4. Create `sherpa_onnx_windows + +```bash +flutter create --template plugin_ffi --platforms linux sherpa_onnx_windows +``` + +5. Create `sherpa_onnx_android + +```bash +flutter create --template plugin_ffi --platforms android --org com.k2fsa.sherpa.onnx sherpa_onnx_android +``` diff --git a/flutter/sherpa_onnx/.gitignore b/flutter/sherpa_onnx/.gitignore new file mode 100644 index 000000000..ac5aa9893 --- /dev/null +++ b/flutter/sherpa_onnx/.gitignore @@ -0,0 +1,29 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +build/ diff --git a/flutter/sherpa_onnx/.metadata b/flutter/sherpa_onnx/.metadata new file mode 100644 index 000000000..1437de85f --- /dev/null +++ b/flutter/sherpa_onnx/.metadata @@ -0,0 +1,27 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "5dcb86f68f239346676ceb1ed1ea385bd215fba1" + channel: "stable" + +project_type: plugin + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/flutter/sherpa_onnx/CHANGELOG.md b/flutter/sherpa_onnx/CHANGELOG.md new file mode 100644 index 000000000..93b72c105 --- /dev/null +++ b/flutter/sherpa_onnx/CHANGELOG.md @@ -0,0 +1,35 @@ +## 1.10.7 + +* Support Android + +## 1.10.2 + +* Fix passing C# string to C++ + +## 1.10.1 + +* Enable to stop TTS generation + +## 1.10.0 + +* Add inverse text normalization + +## 1.9.30 + +* Add TTS + +## 1.9.29 + +* Publish with CI + +## 0.0.3 + +* Fix path separator on Windows. + +## 0.0.2 + +* Support specifying lib path. + +## 0.0.1 + +* Initial release. diff --git a/flutter/sherpa_onnx/README.md b/flutter/sherpa_onnx/README.md new file mode 100644 index 000000000..783f54dc3 --- /dev/null +++ b/flutter/sherpa_onnx/README.md @@ -0,0 +1,3 @@ +# sherpa_onnx + +Please see diff --git a/flutter/sherpa_onnx/analysis_options.yaml b/flutter/sherpa_onnx/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/flutter/sherpa_onnx/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/flutter/sherpa_onnx/example/.gitignore b/flutter/sherpa_onnx/example/.gitignore new file mode 100644 index 000000000..29a3a5017 --- /dev/null +++ b/flutter/sherpa_onnx/example/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/flutter/sherpa_onnx/example/README.md b/flutter/sherpa_onnx/example/README.md new file mode 100644 index 000000000..c97c78739 --- /dev/null +++ b/flutter/sherpa_onnx/example/README.md @@ -0,0 +1,9 @@ +# Introduction + +Please find examples at + +https://github.com/k2-fsa/sherpa-onnx/tree/master/flutter-examples + +and + +https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples diff --git a/flutter/sherpa_onnx/example/example.md b/flutter/sherpa_onnx/example/example.md new file mode 100644 index 000000000..465b0d517 --- /dev/null +++ b/flutter/sherpa_onnx/example/example.md @@ -0,0 +1,20 @@ +# sherpa-onnx app example + +See also + +## Streaming speech recognition + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/streaming-asr + +## Non-streaming speech recognition + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/non-streaming-asr + +## Text to speech (TTS) + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/tts + +## Voice activity detection (VAD) + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/vad + diff --git a/flutter/sherpa_onnx/lib/sherpa_onnx.dart b/flutter/sherpa_onnx/lib/sherpa_onnx.dart new file mode 100644 index 000000000..5f146050c --- /dev/null +++ b/flutter/sherpa_onnx/lib/sherpa_onnx.dart @@ -0,0 +1,56 @@ +// Copyright (c) 2024 Xiaomi Corporation +import 'dart:io'; +import 'dart:ffi'; + +export 'src/feature_config.dart'; +export 'src/offline_recognizer.dart'; +export 'src/offline_stream.dart'; +export 'src/online_recognizer.dart'; +export 'src/online_stream.dart'; +export 'src/speaker_identification.dart'; +export 'src/tts.dart'; +export 'src/vad.dart'; +export 'src/wave_reader.dart'; +export 'src/wave_writer.dart'; + +import 'src/sherpa_onnx_bindings.dart'; + +String? _path; + +// see also +// https://github.com/flutter/codelabs/blob/main/ffigen_codelab/step_05/lib/ffigen_app.dart +final DynamicLibrary _dylib = () { + if (Platform.isIOS) { + throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}'); + } + if (Platform.isMacOS) { + if (_path == null) { + return DynamicLibrary.open('libsherpa-onnx-c-api.dylib'); + } else { + return DynamicLibrary.open('$_path/libsherpa-onnx-c-api.dylib'); + } + } + + if (Platform.isAndroid || Platform.isLinux) { + if (_path == null) { + return DynamicLibrary.open('libsherpa-onnx-c-api.so'); + } else { + return DynamicLibrary.open('$_path/libsherpa-onnx-c-api.so'); + } + } + + if (Platform.isWindows) { + if (_path == null) { + return DynamicLibrary.open('sherpa-onnx-c-api.dll'); + } else { + return DynamicLibrary.open('$_path\\sherpa-onnx-c-api.dll'); + } + } + + throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}'); +}(); + +void initBindings([String? p]) { + _path ??= p; + SherpaOnnxBindings.init(_dylib); +} diff --git a/flutter/sherpa_onnx/lib/src/feature_config.dart b/flutter/sherpa_onnx/lib/src/feature_config.dart new file mode 100644 index 000000000..2af7f2cc4 --- /dev/null +++ b/flutter/sherpa_onnx/lib/src/feature_config.dart @@ -0,0 +1,13 @@ +// Copyright (c) 2024 Xiaomi Corporation + +class FeatureConfig { + const FeatureConfig({this.sampleRate = 16000, this.featureDim = 80}); + + @override + String toString() { + return 'FeatureConfig(sampleRate: $sampleRate, featureDim: $featureDim)'; + } + + final int sampleRate; + final int featureDim; +} diff --git a/flutter/sherpa_onnx/lib/src/offline_recognizer.dart b/flutter/sherpa_onnx/lib/src/offline_recognizer.dart new file mode 100644 index 000000000..b5619e3e0 --- /dev/null +++ b/flutter/sherpa_onnx/lib/src/offline_recognizer.dart @@ -0,0 +1,302 @@ +// Copyright (c) 2024 Xiaomi Corporation +import 'dart:convert'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import './feature_config.dart'; +import './offline_stream.dart'; +import './sherpa_onnx_bindings.dart'; + +class OfflineTransducerModelConfig { + const OfflineTransducerModelConfig({ + this.encoder = '', + this.decoder = '', + this.joiner = '', + }); + + @override + String toString() { + return 'OfflineTransducerModelConfig(encoder: $encoder, decoder: $decoder, joiner: $joiner)'; + } + + final String encoder; + final String decoder; + final String joiner; +} + +class OfflineParaformerModelConfig { + const OfflineParaformerModelConfig({this.model = ''}); + + @override + String toString() { + return 'OfflineParaformerModelConfig(model: $model)'; + } + + final String model; +} + +class OfflineNemoEncDecCtcModelConfig { + const OfflineNemoEncDecCtcModelConfig({this.model = ''}); + + @override + String toString() { + return 'OfflineNemoEncDecCtcModelConfig(model: $model)'; + } + + final String model; +} + +class OfflineWhisperModelConfig { + const OfflineWhisperModelConfig( + {this.encoder = '', + this.decoder = '', + this.language = '', + this.task = '', + this.tailPaddings = -1}); + + @override + String toString() { + return 'OfflineWhisperModelConfig(encoder: $encoder, decoder: $decoder, language: $language, task: $task, tailPaddings: $tailPaddings)'; + } + + final String encoder; + final String decoder; + final String language; + final String task; + final int tailPaddings; +} + +class OfflineTdnnModelConfig { + const OfflineTdnnModelConfig({this.model = ''}); + + @override + String toString() { + return 'OfflineTdnnModelConfig(model: $model)'; + } + + final String model; +} + +class OfflineLMConfig { + const OfflineLMConfig({this.model = '', this.scale = 1.0}); + + @override + String toString() { + return 'OfflineLMConfig(model: $model, scale: $scale)'; + } + + final String model; + final double scale; +} + +class OfflineModelConfig { + const OfflineModelConfig({ + this.transducer = const OfflineTransducerModelConfig(), + this.paraformer = const OfflineParaformerModelConfig(), + this.nemoCtc = const OfflineNemoEncDecCtcModelConfig(), + this.whisper = const OfflineWhisperModelConfig(), + this.tdnn = const OfflineTdnnModelConfig(), + required this.tokens, + this.numThreads = 1, + this.debug = true, + this.provider = 'cpu', + this.modelType = '', + this.modelingUnit = '', + this.bpeVocab = '', + this.telespeechCtc = '', + }); + + @override + String toString() { + return 'OfflineModelConfig(transducer: $transducer, paraformer: $paraformer, nemoCtc: $nemoCtc, whisper: $whisper, tdnn: $tdnn, tokens: $tokens, numThreads: $numThreads, debug: $debug, provider: $provider, modelType: $modelType, modelingUnit: $modelingUnit, bpeVocab: $bpeVocab, telespeechCtc: $telespeechCtc)'; + } + + final OfflineTransducerModelConfig transducer; + final OfflineParaformerModelConfig paraformer; + final OfflineNemoEncDecCtcModelConfig nemoCtc; + final OfflineWhisperModelConfig whisper; + final OfflineTdnnModelConfig tdnn; + + final String tokens; + final int numThreads; + final bool debug; + final String provider; + final String modelType; + final String modelingUnit; + final String bpeVocab; + final String telespeechCtc; +} + +class OfflineRecognizerConfig { + const OfflineRecognizerConfig({ + this.feat = const FeatureConfig(), + required this.model, + this.lm = const OfflineLMConfig(), + this.decodingMethod = 'greedy_search', + this.maxActivePaths = 4, + this.hotwordsFile = '', + this.hotwordsScore = 1.5, + this.ruleFsts = '', + this.ruleFars = '', + }); + + @override + String toString() { + return 'OfflineRecognizerConfig(feat: $feat, model: $model, lm: $lm, decodingMethod: $decodingMethod, maxActivePaths: $maxActivePaths, hotwordsFile: $hotwordsFile, hotwordsScore: $hotwordsScore, ruleFsts: $ruleFsts, ruleFars: $ruleFars)'; + } + + final FeatureConfig feat; + final OfflineModelConfig model; + final OfflineLMConfig lm; + final String decodingMethod; + + final int maxActivePaths; + + final String hotwordsFile; + + final double hotwordsScore; + + final String ruleFsts; + final String ruleFars; +} + +class OfflineRecognizerResult { + OfflineRecognizerResult( + {required this.text, required this.tokens, required this.timestamps}); + + @override + String toString() { + return 'OfflineRecognizerResult(text: $text, tokens: $tokens, timestamps: $timestamps)'; + } + + final String text; + final List tokens; + final List timestamps; +} + +class OfflineRecognizer { + OfflineRecognizer._({required this.ptr, required this.config}); + + void free() { + SherpaOnnxBindings.destroyOfflineRecognizer?.call(ptr); + ptr = nullptr; + } + + /// The user is responsible to call the OfflineRecognizer.free() + /// method of the returned instance to avoid memory leak. + factory OfflineRecognizer(OfflineRecognizerConfig config) { + final c = calloc(); + + c.ref.feat.sampleRate = config.feat.sampleRate; + c.ref.feat.featureDim = config.feat.featureDim; + + // transducer + c.ref.model.transducer.encoder = + config.model.transducer.encoder.toNativeUtf8(); + c.ref.model.transducer.decoder = + config.model.transducer.decoder.toNativeUtf8(); + c.ref.model.transducer.joiner = + config.model.transducer.joiner.toNativeUtf8(); + + // paraformer + c.ref.model.paraformer.model = config.model.paraformer.model.toNativeUtf8(); + + // nemoCtc + c.ref.model.nemoCtc.model = config.model.nemoCtc.model.toNativeUtf8(); + + // whisper + c.ref.model.whisper.encoder = config.model.whisper.encoder.toNativeUtf8(); + + c.ref.model.whisper.decoder = config.model.whisper.decoder.toNativeUtf8(); + + c.ref.model.whisper.language = config.model.whisper.language.toNativeUtf8(); + + c.ref.model.whisper.task = config.model.whisper.task.toNativeUtf8(); + + c.ref.model.whisper.tailPaddings = config.model.whisper.tailPaddings; + + c.ref.model.tdnn.model = config.model.tdnn.model.toNativeUtf8(); + + c.ref.model.tokens = config.model.tokens.toNativeUtf8(); + + c.ref.model.numThreads = config.model.numThreads; + c.ref.model.debug = config.model.debug ? 1 : 0; + c.ref.model.provider = config.model.provider.toNativeUtf8(); + c.ref.model.modelType = config.model.modelType.toNativeUtf8(); + c.ref.model.modelingUnit = config.model.modelingUnit.toNativeUtf8(); + c.ref.model.bpeVocab = config.model.bpeVocab.toNativeUtf8(); + c.ref.model.telespeechCtc = config.model.telespeechCtc.toNativeUtf8(); + + c.ref.lm.model = config.lm.model.toNativeUtf8(); + c.ref.lm.scale = config.lm.scale; + + c.ref.decodingMethod = config.decodingMethod.toNativeUtf8(); + c.ref.maxActivePaths = config.maxActivePaths; + + c.ref.hotwordsFile = config.hotwordsFile.toNativeUtf8(); + c.ref.hotwordsScore = config.hotwordsScore; + + c.ref.ruleFsts = config.ruleFsts.toNativeUtf8(); + c.ref.ruleFars = config.ruleFars.toNativeUtf8(); + + final ptr = SherpaOnnxBindings.createOfflineRecognizer?.call(c) ?? nullptr; + + calloc.free(c.ref.ruleFars); + calloc.free(c.ref.ruleFsts); + calloc.free(c.ref.hotwordsFile); + calloc.free(c.ref.decodingMethod); + calloc.free(c.ref.lm.model); + calloc.free(c.ref.model.telespeechCtc); + calloc.free(c.ref.model.bpeVocab); + calloc.free(c.ref.model.modelingUnit); + calloc.free(c.ref.model.modelType); + calloc.free(c.ref.model.provider); + calloc.free(c.ref.model.tokens); + calloc.free(c.ref.model.tdnn.model); + calloc.free(c.ref.model.whisper.task); + calloc.free(c.ref.model.whisper.language); + calloc.free(c.ref.model.whisper.decoder); + calloc.free(c.ref.model.whisper.encoder); + calloc.free(c.ref.model.nemoCtc.model); + calloc.free(c.ref.model.paraformer.model); + calloc.free(c.ref.model.transducer.encoder); + calloc.free(c.ref.model.transducer.decoder); + calloc.free(c.ref.model.transducer.joiner); + calloc.free(c); + + return OfflineRecognizer._(ptr: ptr, config: config); + } + + /// The user has to invoke stream.free() on the returned instance + /// to avoid memory leak + OfflineStream createStream() { + final p = SherpaOnnxBindings.createOfflineStream?.call(ptr) ?? nullptr; + return OfflineStream(ptr: p); + } + + void decode(OfflineStream stream) { + SherpaOnnxBindings.decodeOfflineStream?.call(ptr, stream.ptr); + } + + OfflineRecognizerResult getResult(OfflineStream stream) { + final json = + SherpaOnnxBindings.getOfflineStreamResultAsJson?.call(stream.ptr) ?? + nullptr; + if (json == nullptr) { + return OfflineRecognizerResult(text: '', tokens: [], timestamps: []); + } + + final parsedJson = jsonDecode(json.toDartString()); + + SherpaOnnxBindings.destroyOfflineStreamResultJson?.call(json); + + return OfflineRecognizerResult( + text: parsedJson['text'], + tokens: List.from(parsedJson['tokens']), + timestamps: List.from(parsedJson['timestamps'])); + } + + Pointer ptr; + OfflineRecognizerConfig config; +} diff --git a/flutter/sherpa_onnx/lib/src/offline_stream.dart b/flutter/sherpa_onnx/lib/src/offline_stream.dart new file mode 100644 index 000000000..0b6f9c866 --- /dev/null +++ b/flutter/sherpa_onnx/lib/src/offline_stream.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2024 Xiaomi Corporation +import 'dart:ffi'; +import 'dart:typed_data'; +import 'package:ffi/ffi.dart'; + +import './sherpa_onnx_bindings.dart'; + +class OfflineStream { + /// The user has to call OfflineStream.free() to avoid memory leak. + OfflineStream({required this.ptr}); + + void free() { + SherpaOnnxBindings.destroyOfflineStream?.call(ptr); + ptr = nullptr; + } + + /// If you have List data, then you can use + /// Float32List.fromList(data) to convert data to Float32List + /// + /// See + /// https://api.flutter.dev/flutter/dart-core/List-class.html + /// and + /// https://api.flutter.dev/flutter/dart-typed_data/Float32List-class.html + void acceptWaveform({required Float32List samples, required int sampleRate}) { + final n = samples.length; + final Pointer p = calloc(n); + + final pList = p.asTypedList(n); + pList.setAll(0, samples); + + SherpaOnnxBindings.acceptWaveformOffline?.call(ptr, sampleRate, p, n); + + calloc.free(p); + } + + Pointer ptr; +} diff --git a/flutter/sherpa_onnx/lib/src/online_recognizer.dart b/flutter/sherpa_onnx/lib/src/online_recognizer.dart new file mode 100644 index 000000000..49ca3d2e8 --- /dev/null +++ b/flutter/sherpa_onnx/lib/src/online_recognizer.dart @@ -0,0 +1,297 @@ +// Copyright (c) 2024 Xiaomi Corporation +import 'dart:convert'; +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import './feature_config.dart'; +import './online_stream.dart'; +import './sherpa_onnx_bindings.dart'; + +class OnlineTransducerModelConfig { + const OnlineTransducerModelConfig({ + this.encoder = '', + this.decoder = '', + this.joiner = '', + }); + + @override + String toString() { + return 'OnlineTransducerModelConfig(encoder: $encoder, decoder: $decoder, joiner: $joiner)'; + } + + final String encoder; + final String decoder; + final String joiner; +} + +class OnlineParaformerModelConfig { + const OnlineParaformerModelConfig({this.encoder = '', this.decoder = ''}); + + @override + String toString() { + return 'OnlineParaformerModelConfig(encoder: $encoder, decoder: $decoder)'; + } + + final String encoder; + final String decoder; +} + +class OnlineZipformer2CtcModelConfig { + const OnlineZipformer2CtcModelConfig({this.model = ''}); + + @override + String toString() { + return 'OnlineZipformer2CtcModelConfig(model: $model)'; + } + + final String model; +} + +class OnlineModelConfig { + const OnlineModelConfig({ + this.transducer = const OnlineTransducerModelConfig(), + this.paraformer = const OnlineParaformerModelConfig(), + this.zipformer2Ctc = const OnlineZipformer2CtcModelConfig(), + required this.tokens, + this.numThreads = 1, + this.provider = 'cpu', + this.debug = true, + this.modelType = '', + this.modelingUnit = '', + this.bpeVocab = '', + }); + + @override + String toString() { + return 'OnlineModelConfig(transducer: $transducer, paraformer: $paraformer, zipformer2Ctc: $zipformer2Ctc, tokens: $tokens, numThreads: $numThreads, provider: $provider, debug: $debug, modelType: $modelType, modelingUnit: $modelingUnit, bpeVocab: $bpeVocab)'; + } + + final OnlineTransducerModelConfig transducer; + final OnlineParaformerModelConfig paraformer; + final OnlineZipformer2CtcModelConfig zipformer2Ctc; + + final String tokens; + + final int numThreads; + + final String provider; + + final bool debug; + + final String modelType; + + final String modelingUnit; + + final String bpeVocab; +} + +class OnlineCtcFstDecoderConfig { + const OnlineCtcFstDecoderConfig({this.graph = '', this.maxActive = 3000}); + + @override + String toString() { + return 'OnlineCtcFstDecoderConfig(graph: $graph, maxActive: $maxActive)'; + } + + final String graph; + final int maxActive; +} + +class OnlineRecognizerConfig { + const OnlineRecognizerConfig({ + this.feat = const FeatureConfig(), + required this.model, + this.decodingMethod = 'greedy_search', + this.maxActivePaths = 4, + this.enableEndpoint = true, + this.rule1MinTrailingSilence = 2.4, + this.rule2MinTrailingSilence = 1.2, + this.rule3MinUtteranceLength = 20, + this.hotwordsFile = '', + this.hotwordsScore = 1.5, + this.ctcFstDecoderConfig = const OnlineCtcFstDecoderConfig(), + this.ruleFsts = '', + this.ruleFars = '', + }); + + @override + String toString() { + return 'OnlineRecognizerConfig(feat: $feat, model: $model, decodingMethod: $decodingMethod, maxActivePaths: $maxActivePaths, enableEndpoint: $enableEndpoint, rule1MinTrailingSilence: $rule1MinTrailingSilence, rule2MinTrailingSilence: $rule2MinTrailingSilence, rule3MinUtteranceLength: $rule3MinUtteranceLength, hotwordsFile: $hotwordsFile, hotwordsScore: $hotwordsScore, ctcFstDecoderConfig: $ctcFstDecoderConfig, ruleFsts: $ruleFsts, ruleFars: $ruleFars)'; + } + + final FeatureConfig feat; + final OnlineModelConfig model; + final String decodingMethod; + + final int maxActivePaths; + + final bool enableEndpoint; + + final double rule1MinTrailingSilence; + + final double rule2MinTrailingSilence; + + final double rule3MinUtteranceLength; + + final String hotwordsFile; + + final double hotwordsScore; + + final OnlineCtcFstDecoderConfig ctcFstDecoderConfig; + final String ruleFsts; + final String ruleFars; +} + +class OnlineRecognizerResult { + OnlineRecognizerResult( + {required this.text, required this.tokens, required this.timestamps}); + + @override + String toString() { + return 'OnlineRecognizerResult(text: $text, tokens: $tokens, timestamps: $timestamps)'; + } + + final String text; + final List tokens; + final List timestamps; +} + +class OnlineRecognizer { + OnlineRecognizer._({required this.ptr, required this.config}); + + /// The user is responsible to call the OnlineRecognizer.free() + /// method of the returned instance to avoid memory leak. + factory OnlineRecognizer(OnlineRecognizerConfig config) { + final c = calloc(); + c.ref.feat.sampleRate = config.feat.sampleRate; + c.ref.feat.featureDim = config.feat.featureDim; + + // transducer + c.ref.model.transducer.encoder = + config.model.transducer.encoder.toNativeUtf8(); + c.ref.model.transducer.decoder = + config.model.transducer.decoder.toNativeUtf8(); + c.ref.model.transducer.joiner = + config.model.transducer.joiner.toNativeUtf8(); + + // paraformer + c.ref.model.paraformer.encoder = + config.model.paraformer.encoder.toNativeUtf8(); + c.ref.model.paraformer.decoder = + config.model.paraformer.decoder.toNativeUtf8(); + + // zipformer2Ctc + c.ref.model.zipformer2Ctc.model = + config.model.zipformer2Ctc.model.toNativeUtf8(); + + c.ref.model.tokens = config.model.tokens.toNativeUtf8(); + c.ref.model.numThreads = config.model.numThreads; + c.ref.model.provider = config.model.provider.toNativeUtf8(); + c.ref.model.debug = config.model.debug ? 1 : 0; + c.ref.model.modelType = config.model.modelType.toNativeUtf8(); + c.ref.model.modelingUnit = config.model.modelingUnit.toNativeUtf8(); + c.ref.model.bpeVocab = config.model.bpeVocab.toNativeUtf8(); + + c.ref.decodingMethod = config.decodingMethod.toNativeUtf8(); + c.ref.maxActivePaths = config.maxActivePaths; + c.ref.enableEndpoint = config.enableEndpoint ? 1 : 0; + c.ref.rule1MinTrailingSilence = config.rule1MinTrailingSilence; + c.ref.rule2MinTrailingSilence = config.rule2MinTrailingSilence; + c.ref.rule3MinUtteranceLength = config.rule3MinUtteranceLength; + c.ref.hotwordsFile = config.hotwordsFile.toNativeUtf8(); + c.ref.hotwordsScore = config.hotwordsScore; + + c.ref.ctcFstDecoderConfig.graph = + config.ctcFstDecoderConfig.graph.toNativeUtf8(); + c.ref.ctcFstDecoderConfig.maxActive = config.ctcFstDecoderConfig.maxActive; + c.ref.ruleFsts = config.ruleFsts.toNativeUtf8(); + c.ref.ruleFars = config.ruleFars.toNativeUtf8(); + + final ptr = SherpaOnnxBindings.createOnlineRecognizer?.call(c) ?? nullptr; + + calloc.free(c.ref.ruleFars); + calloc.free(c.ref.ruleFsts); + calloc.free(c.ref.ctcFstDecoderConfig.graph); + calloc.free(c.ref.hotwordsFile); + calloc.free(c.ref.decodingMethod); + calloc.free(c.ref.model.bpeVocab); + calloc.free(c.ref.model.modelingUnit); + calloc.free(c.ref.model.modelType); + calloc.free(c.ref.model.provider); + calloc.free(c.ref.model.tokens); + calloc.free(c.ref.model.zipformer2Ctc.model); + calloc.free(c.ref.model.paraformer.encoder); + calloc.free(c.ref.model.paraformer.decoder); + + calloc.free(c.ref.model.transducer.encoder); + calloc.free(c.ref.model.transducer.decoder); + calloc.free(c.ref.model.transducer.joiner); + calloc.free(c); + + return OnlineRecognizer._(ptr: ptr, config: config); + } + + void free() { + SherpaOnnxBindings.destroyOnlineRecognizer?.call(ptr); + ptr = nullptr; + } + + /// The user has to invoke stream.free() on the returned instance + /// to avoid memory leak + OnlineStream createStream({String hotwords = ''}) { + if (hotwords == '') { + final p = SherpaOnnxBindings.createOnlineStream?.call(ptr) ?? nullptr; + return OnlineStream(ptr: p); + } + + final utf8 = hotwords.toNativeUtf8(); + final p = + SherpaOnnxBindings.createOnlineStreamWithHotwords?.call(ptr, utf8) ?? + nullptr; + calloc.free(utf8); + return OnlineStream(ptr: p); + } + + bool isReady(OnlineStream stream) { + int ready = + SherpaOnnxBindings.isOnlineStreamReady?.call(ptr, stream.ptr) ?? 0; + + return ready == 1; + } + + OnlineRecognizerResult getResult(OnlineStream stream) { + final json = + SherpaOnnxBindings.getOnlineStreamResultAsJson?.call(ptr, stream.ptr) ?? + nullptr; + if (json == nullptr) { + return OnlineRecognizerResult(text: '', tokens: [], timestamps: []); + } + + final parsedJson = jsonDecode(json.toDartString()); + + SherpaOnnxBindings.destroyOnlineStreamResultJson?.call(json); + + return OnlineRecognizerResult( + text: parsedJson['text'], + tokens: List.from(parsedJson['tokens']), + timestamps: List.from(parsedJson['timestamps'])); + } + + void reset(OnlineStream stream) { + SherpaOnnxBindings.reset?.call(ptr, stream.ptr); + } + + void decode(OnlineStream stream) { + SherpaOnnxBindings.decodeOnlineStream?.call(ptr, stream.ptr); + } + + bool isEndpoint(OnlineStream stream) { + int yes = SherpaOnnxBindings.isEndpoint?.call(ptr, stream.ptr) ?? 0; + + return yes == 1; + } + + Pointer ptr; + OnlineRecognizerConfig config; +} diff --git a/flutter/sherpa_onnx/lib/src/online_stream.dart b/flutter/sherpa_onnx/lib/src/online_stream.dart new file mode 100644 index 000000000..e1f61e15c --- /dev/null +++ b/flutter/sherpa_onnx/lib/src/online_stream.dart @@ -0,0 +1,41 @@ +// Copyright (c) 2024 Xiaomi Corporation +import 'dart:ffi'; +import 'dart:typed_data'; +import 'package:ffi/ffi.dart'; + +import './sherpa_onnx_bindings.dart'; + +class OnlineStream { + /// The user has to call OnlineStream.free() to avoid memory leak. + OnlineStream({required this.ptr}); + + void free() { + SherpaOnnxBindings.destroyOnlineStream?.call(ptr); + ptr = nullptr; + } + + /// If you have List data, then you can use + /// Float32List.fromList(data) to convert data to Float32List + /// + /// See + /// https://api.flutter.dev/flutter/dart-core/List-class.html + /// and + /// https://api.flutter.dev/flutter/dart-typed_data/Float32List-class.html + void acceptWaveform({required Float32List samples, required int sampleRate}) { + final n = samples.length; + final Pointer p = calloc(n); + + final pList = p.asTypedList(n); + pList.setAll(0, samples); + + SherpaOnnxBindings.onlineStreamAcceptWaveform?.call(ptr, sampleRate, p, n); + + calloc.free(p); + } + + void inputFinished() { + SherpaOnnxBindings.onlineStreamInputFinished?.call(ptr); + } + + Pointer ptr; +} diff --git a/flutter/sherpa_onnx/lib/src/sherpa_onnx_bindings.dart b/flutter/sherpa_onnx/lib/src/sherpa_onnx_bindings.dart new file mode 100644 index 000000000..ac7a241ee --- /dev/null +++ b/flutter/sherpa_onnx/lib/src/sherpa_onnx_bindings.dart @@ -0,0 +1,1231 @@ +// Copyright (c) 2024 Xiaomi Corporation +import 'dart:ffi'; +import 'package:ffi/ffi.dart'; + +final class SherpaOnnxOfflineTtsVitsModelConfig extends Struct { + external Pointer model; + external Pointer lexicon; + external Pointer tokens; + external Pointer dataDir; + + @Float() + external double noiseScale; + + @Float() + external double noiseScaleW; + + @Float() + external double lengthScale; + + external Pointer dictDir; +} + +final class SherpaOnnxOfflineTtsModelConfig extends Struct { + external SherpaOnnxOfflineTtsVitsModelConfig vits; + @Int32() + external int numThreads; + + @Int32() + external int debug; + + external Pointer provider; +} + +final class SherpaOnnxOfflineTtsConfig extends Struct { + external SherpaOnnxOfflineTtsModelConfig model; + external Pointer ruleFsts; + + @Int32() + external int maxNumSenetences; + + external Pointer ruleFars; +} + +final class SherpaOnnxGeneratedAudio extends Struct { + external Pointer samples; + + @Int32() + external int n; + + @Int32() + external int sampleRate; +} + +final class SherpaOnnxFeatureConfig extends Struct { + @Int32() + external int sampleRate; + + @Int32() + external int featureDim; +} + +final class SherpaOnnxOfflineTransducerModelConfig extends Struct { + external Pointer encoder; + external Pointer decoder; + external Pointer joiner; +} + +final class SherpaOnnxOfflineParaformerModelConfig extends Struct { + external Pointer model; +} + +final class SherpaOnnxOfflineNemoEncDecCtcModelConfig extends Struct { + external Pointer model; +} + +final class SherpaOnnxOfflineWhisperModelConfig extends Struct { + external Pointer encoder; + external Pointer decoder; + external Pointer language; + external Pointer task; + + @Int32() + external int tailPaddings; +} + +final class SherpaOnnxOfflineTdnnModelConfig extends Struct { + external Pointer model; +} + +final class SherpaOnnxOfflineLMConfig extends Struct { + external Pointer model; + + @Float() + external double scale; +} + +final class SherpaOnnxOfflineModelConfig extends Struct { + external SherpaOnnxOfflineTransducerModelConfig transducer; + external SherpaOnnxOfflineParaformerModelConfig paraformer; + external SherpaOnnxOfflineNemoEncDecCtcModelConfig nemoCtc; + external SherpaOnnxOfflineWhisperModelConfig whisper; + external SherpaOnnxOfflineTdnnModelConfig tdnn; + + external Pointer tokens; + + @Int32() + external int numThreads; + + @Int32() + external int debug; + + external Pointer provider; + + external Pointer modelType; + external Pointer modelingUnit; + external Pointer bpeVocab; + external Pointer telespeechCtc; +} + +final class SherpaOnnxOfflineRecognizerConfig extends Struct { + external SherpaOnnxFeatureConfig feat; + external SherpaOnnxOfflineModelConfig model; + external SherpaOnnxOfflineLMConfig lm; + external Pointer decodingMethod; + + @Int32() + external int maxActivePaths; + + external Pointer hotwordsFile; + + @Float() + external double hotwordsScore; + + external Pointer ruleFsts; + external Pointer ruleFars; +} + +final class SherpaOnnxOnlineTransducerModelConfig extends Struct { + external Pointer encoder; + external Pointer decoder; + external Pointer joiner; +} + +final class SherpaOnnxOnlineParaformerModelConfig extends Struct { + external Pointer encoder; + external Pointer decoder; +} + +final class SherpaOnnxOnlineZipformer2CtcModelConfig extends Struct { + external Pointer model; +} + +final class SherpaOnnxOnlineModelConfig extends Struct { + external SherpaOnnxOnlineTransducerModelConfig transducer; + external SherpaOnnxOnlineParaformerModelConfig paraformer; + external SherpaOnnxOnlineZipformer2CtcModelConfig zipformer2Ctc; + + external Pointer tokens; + + @Int32() + external int numThreads; + + external Pointer provider; + + @Int32() + external int debug; + + external Pointer modelType; + + external Pointer modelingUnit; + + external Pointer bpeVocab; +} + +final class SherpaOnnxOnlineCtcFstDecoderConfig extends Struct { + external Pointer graph; + + @Int32() + external int maxActive; +} + +final class SherpaOnnxOnlineRecognizerConfig extends Struct { + external SherpaOnnxFeatureConfig feat; + external SherpaOnnxOnlineModelConfig model; + external Pointer decodingMethod; + + @Int32() + external int maxActivePaths; + + @Int32() + external int enableEndpoint; + + @Float() + external double rule1MinTrailingSilence; + + @Float() + external double rule2MinTrailingSilence; + + @Float() + external double rule3MinUtteranceLength; + + external Pointer hotwordsFile; + + @Float() + external double hotwordsScore; + + external SherpaOnnxOnlineCtcFstDecoderConfig ctcFstDecoderConfig; + + external Pointer ruleFsts; + external Pointer ruleFars; +} + +final class SherpaOnnxSileroVadModelConfig extends Struct { + external Pointer model; + + @Float() + external double threshold; + + @Float() + external double minSilenceDuration; + + @Float() + external double minSpeechDuration; + + @Int32() + external int windowSize; +} + +final class SherpaOnnxVadModelConfig extends Struct { + external SherpaOnnxSileroVadModelConfig sileroVad; + + @Int32() + external int sampleRate; + + @Int32() + external int numThreads; + + external Pointer provider; + + @Int32() + external int debug; +} + +final class SherpaOnnxSpeechSegment extends Struct { + @Int32() + external int start; + + external Pointer samples; + + @Int32() + external int n; +} + +final class SherpaOnnxWave extends Struct { + external Pointer samples; + + @Int32() + external int sampleRate; + + @Int32() + external int numSamples; +} + +final class SherpaOnnxSpeakerEmbeddingExtractorConfig extends Struct { + external Pointer model; + + @Int32() + external int numThreads; + + @Int32() + external int debug; + + external Pointer provider; +} + +final class SherpaOnnxOfflineTts extends Opaque {} + +final class SherpaOnnxCircularBuffer extends Opaque {} + +final class SherpaOnnxVoiceActivityDetector extends Opaque {} + +final class SherpaOnnxOnlineStream extends Opaque {} + +final class SherpaOnnxOnlineRecognizer extends Opaque {} + +final class SherpaOnnxOfflineRecognizer extends Opaque {} + +final class SherpaOnnxOfflineStream extends Opaque {} + +final class SherpaOnnxSpeakerEmbeddingExtractor extends Opaque {} + +final class SherpaOnnxSpeakerEmbeddingManager extends Opaque {} + +typedef SherpaOnnxCreateOfflineTtsNative = Pointer + Function(Pointer); + +typedef SherpaOnnxCreateOfflineTts = SherpaOnnxCreateOfflineTtsNative; + +typedef SherpaOnnxDestroyOfflineTtsNative = Void Function( + Pointer); + +typedef SherpaOnnxDestroyOfflineTts = void Function( + Pointer); + +typedef SherpaOnnxOfflineTtsSampleRateNative = Int32 Function( + Pointer); + +typedef SherpaOnnxOfflineTtsSampleRate = int Function( + Pointer); + +typedef SherpaOnnxOfflineTtsNumSpeakersNative = Int32 Function( + Pointer); + +typedef SherpaOnnxOfflineTtsNumSpeakers = int Function( + Pointer); + +typedef SherpaOnnxOfflineTtsGenerateNative = Pointer + Function(Pointer, Pointer, Int32, Float); + +typedef SherpaOnnxOfflineTtsGenerate = Pointer + Function(Pointer, Pointer, int, double); + +typedef SherpaOnnxDestroyOfflineTtsGeneratedAudioNative = Void Function( + Pointer); + +typedef SherpaOnnxDestroyOfflineTtsGeneratedAudio = void Function( + Pointer); + +typedef SherpaOnnxGeneratedAudioCallbackNative = Int Function( + Pointer, Int32); + +typedef SherpaOnnxOfflineTtsGenerateWithCallbackNative + = Pointer Function( + Pointer, + Pointer, + Int32, + Float, + Pointer>); + +typedef SherpaOnnxOfflineTtsGenerateWithCallback + = Pointer Function( + Pointer, + Pointer, + int, + double, + Pointer>); + +typedef CreateOfflineRecognizerNative = Pointer + Function(Pointer); + +typedef CreateOfflineRecognizer = CreateOfflineRecognizerNative; + +typedef DestroyOfflineRecognizerNative = Void Function( + Pointer); + +typedef DestroyOfflineRecognizer = void Function( + Pointer); + +typedef CreateOfflineStreamNative = Pointer Function( + Pointer); + +typedef CreateOfflineStream = CreateOfflineStreamNative; + +typedef DestroyOfflineStreamNative = Void Function( + Pointer); + +typedef DestroyOfflineStream = void Function(Pointer); + +typedef AcceptWaveformOfflineNative = Void Function( + Pointer, Int32, Pointer, Int32); + +typedef AcceptWaveformOffline = void Function( + Pointer, int, Pointer, int); + +typedef DecodeOfflineStreamNative = Void Function( + Pointer, Pointer); + +typedef DecodeOfflineStream = void Function( + Pointer, Pointer); + +typedef GetOfflineStreamResultAsJsonNative = Pointer Function( + Pointer); + +typedef GetOfflineStreamResultAsJson = GetOfflineStreamResultAsJsonNative; + +typedef DestroyOfflineStreamResultJsonNative = Void Function(Pointer); + +typedef DestroyOfflineStreamResultJson = void Function(Pointer); + +typedef CreateOnlineRecognizerNative = Pointer + Function(Pointer); + +typedef CreateOnlineRecognizer = CreateOnlineRecognizerNative; + +typedef DestroyOnlineRecognizerNative = Void Function( + Pointer); + +typedef DestroyOnlineRecognizer = void Function( + Pointer); + +typedef CreateOnlineStreamNative = Pointer Function( + Pointer); + +typedef CreateOnlineStream = CreateOnlineStreamNative; + +typedef CreateOnlineStreamWithHotwordsNative = Pointer + Function(Pointer, Pointer); + +typedef CreateOnlineStreamWithHotwords = CreateOnlineStreamWithHotwordsNative; + +typedef IsOnlineStreamReadyNative = Int32 Function( + Pointer, Pointer); + +typedef IsOnlineStreamReady = int Function( + Pointer, Pointer); + +typedef DecodeOnlineStreamNative = Void Function( + Pointer, Pointer); + +typedef DecodeOnlineStream = void Function( + Pointer, Pointer); + +typedef GetOnlineStreamResultAsJsonNative = Pointer Function( + Pointer, Pointer); + +typedef GetOnlineStreamResultAsJson = GetOnlineStreamResultAsJsonNative; + +typedef ResetNative = Void Function( + Pointer, Pointer); + +typedef Reset = void Function( + Pointer, Pointer); + +typedef IsEndpointNative = Int32 Function( + Pointer, Pointer); + +typedef IsEndpoint = int Function( + Pointer, Pointer); + +typedef DestroyOnlineStreamResultJsonNative = Void Function(Pointer); + +typedef DestroyOnlineStreamResultJson = void Function(Pointer); + +typedef SherpaOnnxCreateVoiceActivityDetectorNative + = Pointer Function( + Pointer, Float); + +typedef SherpaOnnxCreateVoiceActivityDetector + = Pointer Function( + Pointer, double); + +typedef SherpaOnnxDestroyVoiceActivityDetectorNative = Void Function( + Pointer); + +typedef SherpaOnnxDestroyVoiceActivityDetector = void Function( + Pointer); + +typedef SherpaOnnxVoiceActivityDetectorAcceptWaveformNative = Void Function( + Pointer, Pointer, Int32); + +typedef SherpaOnnxVoiceActivityDetectorAcceptWaveform = void Function( + Pointer, Pointer, int); + +typedef SherpaOnnxVoiceActivityDetectorEmptyNative = Int32 Function( + Pointer); + +typedef SherpaOnnxVoiceActivityDetectorEmpty = int Function( + Pointer); + +typedef SherpaOnnxVoiceActivityDetectorDetectedNative = Int32 Function( + Pointer); + +typedef SherpaOnnxVoiceActivityDetectorDetected = int Function( + Pointer); + +typedef SherpaOnnxVoiceActivityDetectorPopNative = Void Function( + Pointer); + +typedef SherpaOnnxVoiceActivityDetectorPop = void Function( + Pointer); + +typedef SherpaOnnxVoiceActivityDetectorClearNative = Void Function( + Pointer); + +typedef SherpaOnnxVoiceActivityDetectorClear = void Function( + Pointer); + +typedef SherpaOnnxVoiceActivityDetectorResetNative = Void Function( + Pointer); + +typedef SherpaOnnxVoiceActivityDetectorReset = void Function( + Pointer); + +typedef SherpaOnnxVoiceActivityDetectorFrontNative + = Pointer Function( + Pointer); + +typedef SherpaOnnxVoiceActivityDetectorFront + = SherpaOnnxVoiceActivityDetectorFrontNative; + +typedef SherpaOnnxDestroySpeechSegmentNative = Void Function( + Pointer); + +typedef SherpaOnnxDestroySpeechSegment = void Function( + Pointer); + +typedef SherpaOnnxCreateCircularBufferNative = Pointer + Function(Int32); + +typedef SherpaOnnxCreateCircularBuffer = Pointer + Function(int); + +typedef SherpaOnnxDestroyCircularBufferNative = Void Function( + Pointer); + +typedef SherpaOnnxDestroyCircularBuffer = void Function( + Pointer); + +typedef SherpaOnnxCircularBufferPushNative = Void Function( + Pointer, Pointer, Int32); + +typedef SherpaOnnxCircularBufferPush = void Function( + Pointer, Pointer, int); + +typedef SherpaOnnxCircularBufferGetNative = Pointer Function( + Pointer, Int32, Int32); + +typedef SherpaOnnxCircularBufferGet = Pointer Function( + Pointer, int, int); + +typedef SherpaOnnxCircularBufferFreeNative = Void Function(Pointer); + +typedef SherpaOnnxCircularBufferFree = void Function(Pointer); + +typedef SherpaOnnxCircularBufferPopNative = Void Function( + Pointer, Int32); + +typedef SherpaOnnxCircularBufferPop = void Function( + Pointer, int); + +typedef SherpaOnnxCircularBufferSizeNative = Int32 Function( + Pointer); + +typedef SherpaOnnxCircularBufferSize = int Function( + Pointer); + +typedef SherpaOnnxCircularBufferHeadNative = Int32 Function( + Pointer); + +typedef SherpaOnnxCircularBufferHead = int Function( + Pointer); + +typedef SherpaOnnxCircularBufferResetNative = Void Function( + Pointer); + +typedef SherpaOnnxCircularBufferReset = void Function( + Pointer); + +typedef SherpaOnnxCreateSpeakerEmbeddingManagerNative + = Pointer Function(Int32); + +typedef SherpaOnnxCreateSpeakerEmbeddingManager + = Pointer Function(int); + +typedef SherpaOnnxDestroySpeakerEmbeddingManagerNative = Void Function( + Pointer); + +typedef SherpaOnnxDestroySpeakerEmbeddingManager = void Function( + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingManagerAddNative = Int32 Function( + Pointer, Pointer, Pointer); + +typedef SherpaOnnxSpeakerEmbeddingManagerAdd = int Function( + Pointer, Pointer, Pointer); + +typedef SherpaOnnxSpeakerEmbeddingManagerAddListFlattenedNative + = Int32 Function(Pointer, Pointer, + Pointer, Int32); + +typedef SherpaOnnxSpeakerEmbeddingManagerAddListFlattened = int Function( + Pointer, + Pointer, + Pointer, + int); + +typedef SherpaOnnxSpeakerEmbeddingManagerRemoveNative = Int32 Function( + Pointer, Pointer); + +typedef SherpaOnnxSpeakerEmbeddingManagerRemove = int Function( + Pointer, Pointer); + +typedef SherpaOnnxSpeakerEmbeddingManagerContainsNative = Int32 Function( + Pointer, Pointer); + +typedef SherpaOnnxSpeakerEmbeddingManagerContains = int Function( + Pointer, Pointer); + +typedef SherpaOnnxSpeakerEmbeddingManagerSearchNative = Pointer Function( + Pointer, Pointer, Float); + +typedef SherpaOnnxSpeakerEmbeddingManagerSearch = Pointer Function( + Pointer, Pointer, double); + +typedef SherpaOnnxSpeakerEmbeddingManagerFreeSearchNative = Void Function( + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingManagerFreeSearch = void Function( + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingManagerNumSpeakersNative = Int32 Function( + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingManagerNumSpeakers = int Function( + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingManagerVerifyNative = Int32 Function( + Pointer, + Pointer, + Pointer, + Float); + +typedef SherpaOnnxSpeakerEmbeddingManagerVerify = int Function( + Pointer, + Pointer, + Pointer, + double); + +typedef SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakersNative + = Pointer> Function( + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakers + = SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakersNative; + +typedef SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakersNative = Void Function( + Pointer>); + +typedef SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakers = void Function( + Pointer>); + +typedef SherpaOnnxCreateSpeakerEmbeddingExtractorNative + = Pointer Function( + Pointer); + +typedef SherpaOnnxCreateSpeakerEmbeddingExtractor + = SherpaOnnxCreateSpeakerEmbeddingExtractorNative; + +typedef SherpaOnnxDestroySpeakerEmbeddingExtractorNative = Void Function( + Pointer); + +typedef SherpaOnnxDestroySpeakerEmbeddingExtractor = void Function( + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingExtractorDimNative = Int32 Function( + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingExtractorDim = int Function( + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingExtractorCreateStreamNative + = Pointer Function( + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingExtractorCreateStream + = SherpaOnnxSpeakerEmbeddingExtractorCreateStreamNative; + +typedef DestroyOnlineStreamNative = Void Function( + Pointer); + +typedef DestroyOnlineStream = void Function(Pointer); + +typedef OnlineStreamAcceptWaveformNative = Void Function( + Pointer, Int32, Pointer, Int32); + +typedef OnlineStreamAcceptWaveform = void Function( + Pointer, int, Pointer, int); + +typedef OnlineStreamInputFinishedNative = Void Function( + Pointer); + +typedef OnlineStreamInputFinished = void Function( + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingExtractorIsReadyNative = Int32 Function( + Pointer, + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingExtractorIsReady = int Function( + Pointer, + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingExtractorComputeEmbeddingNative + = Pointer Function(Pointer, + Pointer); + +typedef SherpaOnnxSpeakerEmbeddingExtractorComputeEmbedding + = SherpaOnnxSpeakerEmbeddingExtractorComputeEmbeddingNative; + +typedef SherpaOnnxSpeakerEmbeddingExtractorDestroyEmbeddingNative = Void + Function(Pointer); + +typedef SherpaOnnxSpeakerEmbeddingExtractorDestroyEmbedding = void Function( + Pointer); + +typedef SherpaOnnxReadWaveNative = Pointer Function( + Pointer); + +typedef SherpaOnnxReadWave = SherpaOnnxReadWaveNative; + +typedef SherpaOnnxWriteWaveNative = Int32 Function( + Pointer, Int32, Int32, Pointer); + +typedef SherpaOnnxWriteWave = int Function( + Pointer, int, int, Pointer); + +typedef SherpaOnnxFreeWaveNative = Void Function(Pointer); + +typedef SherpaOnnxFreeWave = void Function(Pointer); + +class SherpaOnnxBindings { + static SherpaOnnxCreateOfflineTts? createOfflineTts; + static SherpaOnnxDestroyOfflineTts? destroyOfflineTts; + static SherpaOnnxOfflineTtsSampleRate? offlineTtsSampleRate; + static SherpaOnnxOfflineTtsNumSpeakers? offlineTtsNumSpeakers; + static SherpaOnnxOfflineTtsGenerate? offlineTtsGenerate; + static SherpaOnnxDestroyOfflineTtsGeneratedAudio? + destroyOfflineTtsGeneratedAudio; + static SherpaOnnxOfflineTtsGenerateWithCallback? + offlineTtsGenerateWithCallback; + + static CreateOfflineRecognizer? createOfflineRecognizer; + static DestroyOfflineRecognizer? destroyOfflineRecognizer; + static CreateOfflineStream? createOfflineStream; + static DestroyOfflineStream? destroyOfflineStream; + static AcceptWaveformOffline? acceptWaveformOffline; + static DecodeOfflineStream? decodeOfflineStream; + static GetOfflineStreamResultAsJson? getOfflineStreamResultAsJson; + static DestroyOfflineStreamResultJson? destroyOfflineStreamResultJson; + + static CreateOnlineRecognizer? createOnlineRecognizer; + + static DestroyOnlineRecognizer? destroyOnlineRecognizer; + + static CreateOnlineStream? createOnlineStream; + + static CreateOnlineStreamWithHotwords? createOnlineStreamWithHotwords; + + static IsOnlineStreamReady? isOnlineStreamReady; + + static DecodeOnlineStream? decodeOnlineStream; + + static GetOnlineStreamResultAsJson? getOnlineStreamResultAsJson; + + static Reset? reset; + + static IsEndpoint? isEndpoint; + + static DestroyOnlineStreamResultJson? destroyOnlineStreamResultJson; + + static SherpaOnnxCreateVoiceActivityDetector? createVoiceActivityDetector; + + static SherpaOnnxDestroyVoiceActivityDetector? destroyVoiceActivityDetector; + + static SherpaOnnxVoiceActivityDetectorAcceptWaveform? + voiceActivityDetectorAcceptWaveform; + + static SherpaOnnxVoiceActivityDetectorEmpty? voiceActivityDetectorEmpty; + + static SherpaOnnxVoiceActivityDetectorDetected? voiceActivityDetectorDetected; + + static SherpaOnnxVoiceActivityDetectorPop? voiceActivityDetectorPop; + + static SherpaOnnxVoiceActivityDetectorClear? voiceActivityDetectorClear; + + static SherpaOnnxVoiceActivityDetectorFront? voiceActivityDetectorFront; + + static SherpaOnnxDestroySpeechSegment? destroySpeechSegment; + + static SherpaOnnxVoiceActivityDetectorReset? voiceActivityDetectorReset; + + static SherpaOnnxCreateCircularBuffer? createCircularBuffer; + + static SherpaOnnxDestroyCircularBuffer? destroyCircularBuffer; + + static SherpaOnnxCircularBufferPush? circularBufferPush; + + static SherpaOnnxCircularBufferGet? circularBufferGet; + + static SherpaOnnxCircularBufferFree? circularBufferFree; + + static SherpaOnnxCircularBufferPop? circularBufferPop; + + static SherpaOnnxCircularBufferSize? circularBufferSize; + + static SherpaOnnxCircularBufferHead? circularBufferHead; + + static SherpaOnnxCircularBufferReset? circularBufferReset; + + static SherpaOnnxCreateSpeakerEmbeddingExtractor? + createSpeakerEmbeddingExtractor; + + static SherpaOnnxDestroySpeakerEmbeddingExtractor? + destroySpeakerEmbeddingExtractor; + + static SherpaOnnxSpeakerEmbeddingExtractorDim? speakerEmbeddingExtractorDim; + + static SherpaOnnxSpeakerEmbeddingExtractorCreateStream? + speakerEmbeddingExtractorCreateStream; + + static SherpaOnnxSpeakerEmbeddingExtractorComputeEmbedding? + speakerEmbeddingExtractorComputeEmbedding; + + static SherpaOnnxSpeakerEmbeddingExtractorDestroyEmbedding? + speakerEmbeddingExtractorDestroyEmbedding; + + static DestroyOnlineStream? destroyOnlineStream; + + static OnlineStreamAcceptWaveform? onlineStreamAcceptWaveform; + + static OnlineStreamInputFinished? onlineStreamInputFinished; + + static SherpaOnnxSpeakerEmbeddingExtractorIsReady? + speakerEmbeddingExtractorIsReady; + + static SherpaOnnxCreateSpeakerEmbeddingManager? createSpeakerEmbeddingManager; + + static SherpaOnnxDestroySpeakerEmbeddingManager? + destroySpeakerEmbeddingManager; + + static SherpaOnnxSpeakerEmbeddingManagerAdd? speakerEmbeddingManagerAdd; + + static SherpaOnnxSpeakerEmbeddingManagerAddListFlattened? + speakerEmbeddingManagerAddListFlattened; + + static SherpaOnnxSpeakerEmbeddingManagerRemove? speakerEmbeddingManagerRemove; + + static SherpaOnnxSpeakerEmbeddingManagerContains? + speakerEmbeddingManagerContains; + + static SherpaOnnxSpeakerEmbeddingManagerSearch? speakerEmbeddingManagerSearch; + + static SherpaOnnxSpeakerEmbeddingManagerFreeSearch? + speakerEmbeddingManagerFreeSearch; + + static SherpaOnnxSpeakerEmbeddingManagerNumSpeakers? + speakerEmbeddingManagerNumSpeakers; + + static SherpaOnnxSpeakerEmbeddingManagerVerify? speakerEmbeddingManagerVerify; + + static SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakers? + speakerEmbeddingManagerGetAllSpeakers; + + static SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakers? + speakerEmbeddingManagerFreeAllSpeakers; + + static SherpaOnnxReadWave? readWave; + + static SherpaOnnxWriteWave? writeWave; + + static SherpaOnnxFreeWave? freeWave; + + static void init(DynamicLibrary dynamicLibrary) { + createOfflineTts ??= dynamicLibrary + .lookup>( + 'SherpaOnnxCreateOfflineTts') + .asFunction(); + + destroyOfflineTts ??= dynamicLibrary + .lookup>( + 'SherpaOnnxDestroyOfflineTts') + .asFunction(); + + offlineTtsSampleRate ??= dynamicLibrary + .lookup>( + 'SherpaOnnxOfflineTtsSampleRate') + .asFunction(); + + offlineTtsNumSpeakers ??= dynamicLibrary + .lookup>( + 'SherpaOnnxOfflineTtsNumSpeakers') + .asFunction(); + + offlineTtsGenerate ??= dynamicLibrary + .lookup>( + 'SherpaOnnxOfflineTtsGenerate') + .asFunction(); + + destroyOfflineTtsGeneratedAudio ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxDestroyOfflineTtsGeneratedAudioNative>>( + 'SherpaOnnxDestroyOfflineTtsGeneratedAudio') + .asFunction(); + + offlineTtsGenerateWithCallback ??= dynamicLibrary + .lookup>( + 'SherpaOnnxOfflineTtsGenerateWithCallback') + .asFunction(); + + createOfflineRecognizer ??= dynamicLibrary + .lookup>( + 'CreateOfflineRecognizer') + .asFunction(); + + destroyOfflineRecognizer ??= dynamicLibrary + .lookup>( + 'DestroyOfflineRecognizer') + .asFunction(); + + createOfflineStream ??= dynamicLibrary + .lookup>( + 'CreateOfflineStream') + .asFunction(); + + destroyOfflineStream ??= dynamicLibrary + .lookup>( + 'DestroyOfflineStream') + .asFunction(); + + acceptWaveformOffline ??= dynamicLibrary + .lookup>( + 'AcceptWaveformOffline') + .asFunction(); + + decodeOfflineStream ??= dynamicLibrary + .lookup>( + 'DecodeOfflineStream') + .asFunction(); + + getOfflineStreamResultAsJson ??= dynamicLibrary + .lookup>( + 'GetOfflineStreamResultAsJson') + .asFunction(); + + destroyOfflineStreamResultJson ??= dynamicLibrary + .lookup>( + 'DestroyOfflineStreamResultJson') + .asFunction(); + + createOnlineRecognizer ??= dynamicLibrary + .lookup>( + 'CreateOnlineRecognizer') + .asFunction(); + + destroyOnlineRecognizer ??= dynamicLibrary + .lookup>( + 'DestroyOnlineRecognizer') + .asFunction(); + + createOnlineStream ??= dynamicLibrary + .lookup>('CreateOnlineStream') + .asFunction(); + + createOnlineStreamWithHotwords ??= dynamicLibrary + .lookup>( + 'CreateOnlineStreamWithHotwords') + .asFunction(); + + isOnlineStreamReady ??= dynamicLibrary + .lookup>( + 'IsOnlineStreamReady') + .asFunction(); + + decodeOnlineStream ??= dynamicLibrary + .lookup>('DecodeOnlineStream') + .asFunction(); + + getOnlineStreamResultAsJson ??= dynamicLibrary + .lookup>( + 'GetOnlineStreamResultAsJson') + .asFunction(); + + reset ??= dynamicLibrary + .lookup>('Reset') + .asFunction(); + + isEndpoint ??= dynamicLibrary + .lookup>('IsEndpoint') + .asFunction(); + + destroyOnlineStreamResultJson ??= dynamicLibrary + .lookup>( + 'DestroyOnlineStreamResultJson') + .asFunction(); + + createVoiceActivityDetector ??= dynamicLibrary + .lookup>( + 'SherpaOnnxCreateVoiceActivityDetector') + .asFunction(); + + destroyVoiceActivityDetector ??= dynamicLibrary + .lookup>( + 'SherpaOnnxDestroyVoiceActivityDetector') + .asFunction(); + + voiceActivityDetectorAcceptWaveform ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxVoiceActivityDetectorAcceptWaveformNative>>( + 'SherpaOnnxVoiceActivityDetectorAcceptWaveform') + .asFunction(); + + voiceActivityDetectorEmpty ??= dynamicLibrary + .lookup>( + 'SherpaOnnxVoiceActivityDetectorEmpty') + .asFunction(); + + voiceActivityDetectorDetected ??= dynamicLibrary + .lookup>( + 'SherpaOnnxVoiceActivityDetectorDetected') + .asFunction(); + + voiceActivityDetectorPop ??= dynamicLibrary + .lookup>( + 'SherpaOnnxVoiceActivityDetectorPop') + .asFunction(); + + voiceActivityDetectorClear ??= dynamicLibrary + .lookup>( + 'SherpaOnnxVoiceActivityDetectorClear') + .asFunction(); + + voiceActivityDetectorFront ??= dynamicLibrary + .lookup>( + 'SherpaOnnxVoiceActivityDetectorFront') + .asFunction(); + + destroySpeechSegment ??= dynamicLibrary + .lookup>( + 'SherpaOnnxDestroySpeechSegment') + .asFunction(); + + voiceActivityDetectorReset ??= dynamicLibrary + .lookup>( + 'SherpaOnnxVoiceActivityDetectorReset') + .asFunction(); + + createCircularBuffer ??= dynamicLibrary + .lookup>( + 'SherpaOnnxCreateCircularBuffer') + .asFunction(); + + destroyCircularBuffer ??= dynamicLibrary + .lookup>( + 'SherpaOnnxDestroyCircularBuffer') + .asFunction(); + + circularBufferPush ??= dynamicLibrary + .lookup>( + 'SherpaOnnxCircularBufferPush') + .asFunction(); + + circularBufferGet ??= dynamicLibrary + .lookup>( + 'SherpaOnnxCircularBufferGet') + .asFunction(); + + circularBufferFree ??= dynamicLibrary + .lookup>( + 'SherpaOnnxCircularBufferFree') + .asFunction(); + + circularBufferPop ??= dynamicLibrary + .lookup>( + 'SherpaOnnxCircularBufferPop') + .asFunction(); + + circularBufferSize ??= dynamicLibrary + .lookup>( + 'SherpaOnnxCircularBufferSize') + .asFunction(); + + circularBufferHead ??= dynamicLibrary + .lookup>( + 'SherpaOnnxCircularBufferHead') + .asFunction(); + + circularBufferReset ??= dynamicLibrary + .lookup>( + 'SherpaOnnxCircularBufferReset') + .asFunction(); + + createSpeakerEmbeddingExtractor ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxCreateSpeakerEmbeddingExtractorNative>>( + 'SherpaOnnxCreateSpeakerEmbeddingExtractor') + .asFunction(); + + destroySpeakerEmbeddingExtractor ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxDestroySpeakerEmbeddingExtractorNative>>( + 'SherpaOnnxDestroySpeakerEmbeddingExtractor') + .asFunction(); + + speakerEmbeddingExtractorDim ??= dynamicLibrary + .lookup>( + 'SherpaOnnxSpeakerEmbeddingExtractorDim') + .asFunction(); + + speakerEmbeddingExtractorCreateStream ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxSpeakerEmbeddingExtractorCreateStreamNative>>( + 'SherpaOnnxSpeakerEmbeddingExtractorCreateStream') + .asFunction(); + + speakerEmbeddingExtractorComputeEmbedding ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxSpeakerEmbeddingExtractorComputeEmbeddingNative>>( + 'SherpaOnnxSpeakerEmbeddingExtractorComputeEmbedding') + .asFunction(); + + speakerEmbeddingExtractorDestroyEmbedding ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxSpeakerEmbeddingExtractorDestroyEmbeddingNative>>( + 'SherpaOnnxSpeakerEmbeddingExtractorDestroyEmbedding') + .asFunction(); + + destroyOnlineStream ??= dynamicLibrary + .lookup>( + 'DestroyOnlineStream') + .asFunction(); + + onlineStreamAcceptWaveform ??= dynamicLibrary + .lookup>( + 'AcceptWaveform') + .asFunction(); + + onlineStreamInputFinished ??= dynamicLibrary + .lookup>( + 'InputFinished') + .asFunction(); + + speakerEmbeddingExtractorIsReady ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxSpeakerEmbeddingExtractorIsReadyNative>>( + 'SherpaOnnxSpeakerEmbeddingExtractorIsReady') + .asFunction(); + + createSpeakerEmbeddingManager ??= dynamicLibrary + .lookup>( + 'SherpaOnnxCreateSpeakerEmbeddingManager') + .asFunction(); + + destroySpeakerEmbeddingManager ??= dynamicLibrary + .lookup>( + 'SherpaOnnxDestroySpeakerEmbeddingManager') + .asFunction(); + + speakerEmbeddingManagerAdd ??= dynamicLibrary + .lookup>( + 'SherpaOnnxSpeakerEmbeddingManagerAdd') + .asFunction(); + + speakerEmbeddingManagerAddListFlattened ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxSpeakerEmbeddingManagerAddListFlattenedNative>>( + 'SherpaOnnxSpeakerEmbeddingManagerAddListFlattened') + .asFunction(); + + speakerEmbeddingManagerRemove ??= dynamicLibrary + .lookup>( + 'SherpaOnnxSpeakerEmbeddingManagerRemove') + .asFunction(); + + speakerEmbeddingManagerContains ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxSpeakerEmbeddingManagerContainsNative>>( + 'SherpaOnnxSpeakerEmbeddingManagerContains') + .asFunction(); + + speakerEmbeddingManagerSearch ??= dynamicLibrary + .lookup>( + 'SherpaOnnxSpeakerEmbeddingManagerSearch') + .asFunction(); + + speakerEmbeddingManagerFreeSearch ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxSpeakerEmbeddingManagerFreeSearchNative>>( + 'SherpaOnnxSpeakerEmbeddingManagerFreeSearch') + .asFunction(); + + speakerEmbeddingManagerNumSpeakers ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxSpeakerEmbeddingManagerNumSpeakersNative>>( + 'SherpaOnnxSpeakerEmbeddingManagerNumSpeakers') + .asFunction(); + + speakerEmbeddingManagerVerify ??= dynamicLibrary + .lookup>( + 'SherpaOnnxSpeakerEmbeddingManagerVerify') + .asFunction(); + + speakerEmbeddingManagerGetAllSpeakers ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakersNative>>( + 'SherpaOnnxSpeakerEmbeddingManagerGetAllSpeakers') + .asFunction(); + + speakerEmbeddingManagerFreeAllSpeakers ??= dynamicLibrary + .lookup< + NativeFunction< + SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakersNative>>( + 'SherpaOnnxSpeakerEmbeddingManagerFreeAllSpeakers') + .asFunction(); + + readWave ??= dynamicLibrary + .lookup>('SherpaOnnxReadWave') + .asFunction(); + + writeWave ??= dynamicLibrary + .lookup>( + 'SherpaOnnxWriteWave') + .asFunction(); + + freeWave ??= dynamicLibrary + .lookup>('SherpaOnnxFreeWave') + .asFunction(); + } +} diff --git a/flutter/sherpa_onnx/lib/src/speaker_identification.dart b/flutter/sherpa_onnx/lib/src/speaker_identification.dart new file mode 100644 index 000000000..5c2e10744 --- /dev/null +++ b/flutter/sherpa_onnx/lib/src/speaker_identification.dart @@ -0,0 +1,268 @@ +// Copyright (c) 2024 Xiaomi Corporation +import 'dart:ffi'; +import 'dart:typed_data'; +import 'package:ffi/ffi.dart'; + +import './online_stream.dart'; +import './sherpa_onnx_bindings.dart'; + +class SpeakerEmbeddingExtractorConfig { + const SpeakerEmbeddingExtractorConfig( + {required this.model, + this.numThreads = 1, + this.debug = true, + this.provider = 'cpu'}); + + @override + String toString() { + return 'SpeakerEmbeddingExtractorConfig(model: $model, numThreads: $numThreads, debug: $debug, provider: $provider)'; + } + + final String model; + final int numThreads; + final bool debug; + final String provider; +} + +class SpeakerEmbeddingExtractor { + SpeakerEmbeddingExtractor._({required this.ptr, required this.dim}); + + /// The user is responsible to call the SpeakerEmbeddingExtractor.free() + /// method of the returned instance to avoid memory leak. + factory SpeakerEmbeddingExtractor( + {required SpeakerEmbeddingExtractorConfig config}) { + final c = calloc(); + + final modelPtr = config.model.toNativeUtf8(); + c.ref.model = modelPtr; + + c.ref.numThreads = config.numThreads; + c.ref.debug = config.debug ? 1 : 0; + + final providerPtr = config.provider.toNativeUtf8(); + c.ref.provider = providerPtr; + + final ptr = + SherpaOnnxBindings.createSpeakerEmbeddingExtractor?.call(c) ?? nullptr; + + calloc.free(providerPtr); + calloc.free(modelPtr); + calloc.free(c); + + final dim = SherpaOnnxBindings.speakerEmbeddingExtractorDim?.call(ptr) ?? 0; + + return SpeakerEmbeddingExtractor._(ptr: ptr, dim: dim); + } + + void free() { + SherpaOnnxBindings.destroySpeakerEmbeddingExtractor?.call(ptr); + ptr = nullptr; + } + + /// The user has to invoke stream.free() on the returned instance + /// to avoid memory leak + OnlineStream createStream() { + final p = + SherpaOnnxBindings.speakerEmbeddingExtractorCreateStream?.call(ptr) ?? + nullptr; + + return OnlineStream(ptr: p); + } + + bool isReady(OnlineStream stream) { + final int ready = SherpaOnnxBindings.speakerEmbeddingExtractorIsReady + ?.call(ptr, stream.ptr) ?? + 0; + return ready == 1; + } + + Float32List compute(OnlineStream stream) { + final Pointer embedding = SherpaOnnxBindings + .speakerEmbeddingExtractorComputeEmbedding + ?.call(ptr, stream.ptr) ?? + nullptr; + + if (embedding == nullptr) { + return Float32List(0); + } + + final embeddingList = embedding.asTypedList(dim); + final ans = Float32List(dim); + ans.setAll(0, embeddingList); + + SherpaOnnxBindings.speakerEmbeddingExtractorDestroyEmbedding + ?.call(embedding); + + return ans; + } + + Pointer ptr; + final int dim; +} + +class SpeakerEmbeddingManager { + SpeakerEmbeddingManager._({required this.ptr, required this.dim}); + + // The user has to use SpeakerEmbeddingManager.free() to avoid memory leak + factory SpeakerEmbeddingManager(int dim) { + final p = + SherpaOnnxBindings.createSpeakerEmbeddingManager?.call(dim) ?? nullptr; + return SpeakerEmbeddingManager._(ptr: p, dim: dim); + } + + void free() { + SherpaOnnxBindings.destroySpeakerEmbeddingManager?.call(ptr); + ptr = nullptr; + } + + /// Return true if added successfully; return false otherwise + bool add({required String name, required Float32List embedding}) { + assert(embedding.length == dim, '${embedding.length} vs $dim'); + + final Pointer namePtr = name.toNativeUtf8(); + final int n = embedding.length; + + final Pointer p = calloc(n); + final pList = p.asTypedList(n); + pList.setAll(0, embedding); + + final int ok = + SherpaOnnxBindings.speakerEmbeddingManagerAdd?.call(ptr, namePtr, p) ?? + 0; + + calloc.free(p); + calloc.free(namePtr); + + return ok == 1; + } + + bool addMulti( + {required String name, required List embeddingList}) { + final Pointer namePtr = name.toNativeUtf8(); + final int n = embeddingList.length; + + final Pointer p = calloc(n * dim); + final pList = p.asTypedList(n * dim); + + int offset = 0; + for (final e in embeddingList) { + assert(e.length == dim, '${e.length} vs $dim'); + + pList.setAll(offset, e); + offset += dim; + } + + final int ok = SherpaOnnxBindings.speakerEmbeddingManagerAddListFlattened + ?.call(ptr, namePtr, p, n) ?? + 0; + + calloc.free(p); + calloc.free(namePtr); + + return ok == 1; + } + + bool contains(String name) { + final Pointer namePtr = name.toNativeUtf8(); + + final int found = SherpaOnnxBindings.speakerEmbeddingManagerContains + ?.call(ptr, namePtr) ?? + 0; + + calloc.free(namePtr); + + return found == 1; + } + + bool remove(String name) { + final Pointer namePtr = name.toNativeUtf8(); + + final int ok = + SherpaOnnxBindings.speakerEmbeddingManagerRemove?.call(ptr, namePtr) ?? + 0; + + calloc.free(namePtr); + + return ok == 1; + } + + /// Return an empty string if no speaker is found + String search({required Float32List embedding, required double threshold}) { + assert(embedding.length == dim); + + final Pointer p = calloc(dim); + final pList = p.asTypedList(dim); + pList.setAll(0, embedding); + + final Pointer name = SherpaOnnxBindings.speakerEmbeddingManagerSearch + ?.call(ptr, p, threshold) ?? + nullptr; + + calloc.free(p); + + if (name == nullptr) { + return ''; + } + + final String ans = name.toDartString(); + + SherpaOnnxBindings.speakerEmbeddingManagerFreeSearch?.call(name); + + return ans; + } + + bool verify( + {required String name, + required Float32List embedding, + required double threshold}) { + assert(embedding.length == dim); + + final Pointer namePtr = name.toNativeUtf8(); + + final Pointer p = calloc(dim); + final pList = p.asTypedList(dim); + pList.setAll(0, embedding); + + final int ok = SherpaOnnxBindings.speakerEmbeddingManagerVerify + ?.call(ptr, namePtr, p, threshold) ?? + 0; + + calloc.free(p); + calloc.free(namePtr); + + return ok == 1; + } + + int get numSpeakers => + SherpaOnnxBindings.speakerEmbeddingManagerNumSpeakers?.call(ptr) ?? 0; + + List get allSpeakerNames { + int n = numSpeakers; + if (n == 0) { + return []; + } + + final Pointer> names = + SherpaOnnxBindings.speakerEmbeddingManagerGetAllSpeakers?.call(ptr) ?? + nullptr; + + if (names == nullptr) { + return []; + } + + final ans = []; + + // see https://api.flutter.dev/flutter/dart-ffi/PointerPointer.html + for (int i = 0; i != n; ++i) { + String name = names[i].toDartString(); + ans.add(name); + } + + SherpaOnnxBindings.speakerEmbeddingManagerFreeAllSpeakers?.call(names); + + return ans; + } + + Pointer ptr; + final int dim; +} diff --git a/flutter/sherpa_onnx/lib/src/tts.dart b/flutter/sherpa_onnx/lib/src/tts.dart new file mode 100644 index 000000000..f779188b7 --- /dev/null +++ b/flutter/sherpa_onnx/lib/src/tts.dart @@ -0,0 +1,193 @@ +// Copyright (c) 2024 Xiaomi Corporation +import 'dart:ffi'; +import 'dart:typed_data'; + +import 'package:ffi/ffi.dart'; + +import './sherpa_onnx_bindings.dart'; + +class OfflineTtsVitsModelConfig { + const OfflineTtsVitsModelConfig({ + required this.model, + this.lexicon = '', + required this.tokens, + this.dataDir = '', + this.noiseScale = 0.667, + this.noiseScaleW = 0.8, + this.lengthScale = 1.0, + this.dictDir = '', + }); + + @override + String toString() { + return 'OfflineTtsVitsModelConfig(model: $model, lexicon: $lexicon, tokens: $tokens, dataDir: $dataDir, noiseScale: $noiseScale, noiseScaleW: $noiseScaleW, lengthScale: $lengthScale, dictDir: $dictDir)'; + } + + final String model; + final String lexicon; + final String tokens; + final String dataDir; + final double noiseScale; + final double noiseScaleW; + final double lengthScale; + final String dictDir; +} + +class OfflineTtsModelConfig { + const OfflineTtsModelConfig({ + required this.vits, + this.numThreads = 1, + this.debug = true, + this.provider = 'cpu', + }); + + @override + String toString() { + return 'OfflineTtsModelConfig(vits: $vits, numThreads: $numThreads, debug: $debug, provider: $provider)'; + } + + final OfflineTtsVitsModelConfig vits; + final int numThreads; + final bool debug; + final String provider; +} + +class OfflineTtsConfig { + const OfflineTtsConfig({ + required this.model, + this.ruleFsts = '', + this.maxNumSenetences = 1, + this.ruleFars = '', + }); + + @override + String toString() { + return 'OfflineTtsConfig(model: $model, ruleFsts: $ruleFsts, maxNumSenetences: $maxNumSenetences, ruleFars: $ruleFars)'; + } + + final OfflineTtsModelConfig model; + final String ruleFsts; + final int maxNumSenetences; + final String ruleFars; +} + +class GeneratedAudio { + GeneratedAudio({ + required this.samples, + required this.sampleRate, + }); + + final Float32List samples; + final int sampleRate; +} + +class OfflineTts { + OfflineTts._({required this.ptr, required this.config}); + + /// The user is responsible to call the OfflineTts.free() + /// method of the returned instance to avoid memory leak. + factory OfflineTts(OfflineTtsConfig config) { + final c = calloc(); + c.ref.model.vits.model = config.model.vits.model.toNativeUtf8(); + c.ref.model.vits.lexicon = config.model.vits.lexicon.toNativeUtf8(); + c.ref.model.vits.tokens = config.model.vits.tokens.toNativeUtf8(); + c.ref.model.vits.dataDir = config.model.vits.dataDir.toNativeUtf8(); + c.ref.model.vits.noiseScale = config.model.vits.noiseScale; + c.ref.model.vits.noiseScaleW = config.model.vits.noiseScaleW; + c.ref.model.vits.lengthScale = config.model.vits.lengthScale; + c.ref.model.vits.dictDir = config.model.vits.dictDir.toNativeUtf8(); + + c.ref.model.numThreads = config.model.numThreads; + c.ref.model.debug = config.model.debug ? 1 : 0; + c.ref.model.provider = config.model.provider.toNativeUtf8(); + + c.ref.ruleFsts = config.ruleFsts.toNativeUtf8(); + c.ref.maxNumSenetences = config.maxNumSenetences; + c.ref.ruleFars = config.ruleFars.toNativeUtf8(); + + final ptr = SherpaOnnxBindings.createOfflineTts?.call(c) ?? nullptr; + + calloc.free(c.ref.ruleFars); + calloc.free(c.ref.ruleFsts); + calloc.free(c.ref.model.provider); + calloc.free(c.ref.model.vits.dictDir); + calloc.free(c.ref.model.vits.dataDir); + calloc.free(c.ref.model.vits.tokens); + calloc.free(c.ref.model.vits.lexicon); + calloc.free(c.ref.model.vits.model); + + return OfflineTts._(ptr: ptr, config: config); + } + + void free() { + SherpaOnnxBindings.destroyOfflineTts?.call(ptr); + ptr = nullptr; + } + + GeneratedAudio generate( + {required String text, int sid = 0, double speed = 1.0}) { + final Pointer textPtr = text.toNativeUtf8(); + final p = + SherpaOnnxBindings.offlineTtsGenerate?.call(ptr, textPtr, sid, speed) ?? + nullptr; + calloc.free(textPtr); + + if (p == nullptr) { + return GeneratedAudio(samples: Float32List(0), sampleRate: 0); + } + + final samples = p.ref.samples.asTypedList(p.ref.n); + final sampleRate = p.ref.sampleRate; + final newSamples = Float32List.fromList(samples); + + SherpaOnnxBindings.destroyOfflineTtsGeneratedAudio?.call(p); + + return GeneratedAudio(samples: newSamples, sampleRate: sampleRate); + } + + GeneratedAudio generateWithCallback( + {required String text, + int sid = 0, + double speed = 1.0, + required int Function(Float32List samples) callback}) { + // see + // https://github.com/dart-lang/sdk/issues/54276#issuecomment-1846109285 + // https://stackoverflow.com/questions/69537440/callbacks-in-dart-dartffi-only-supports-calling-static-dart-functions-from-nat + // https://github.com/dart-lang/sdk/blob/main/tests/ffi/isolate_local_function_callbacks_test.dart#L46 + final wrapper = + NativeCallable.isolateLocal( + (Pointer samples, int n) { + final s = samples.asTypedList(n); + final newSamples = Float32List.fromList(s); + return callback(newSamples); + }, exceptionalReturn: 0); + + final Pointer textPtr = text.toNativeUtf8(); + final p = SherpaOnnxBindings.offlineTtsGenerateWithCallback + ?.call(ptr, textPtr, sid, speed, wrapper.nativeFunction) ?? + nullptr; + + calloc.free(textPtr); + wrapper.close(); + + if (p == nullptr) { + return GeneratedAudio(samples: Float32List(0), sampleRate: 0); + } + + final samples = p.ref.samples.asTypedList(p.ref.n); + final sampleRate = p.ref.sampleRate; + final newSamples = Float32List.fromList(samples); + + SherpaOnnxBindings.destroyOfflineTtsGeneratedAudio?.call(p); + + return GeneratedAudio(samples: newSamples, sampleRate: sampleRate); + } + + int get sampleRate => SherpaOnnxBindings.offlineTtsSampleRate?.call(ptr) ?? 0; + + int get numSpeakers => + SherpaOnnxBindings.offlineTtsNumSpeakers?.call(ptr) ?? 0; + + Pointer ptr; + OfflineTtsConfig config; +} diff --git a/flutter/sherpa_onnx/lib/src/vad.dart b/flutter/sherpa_onnx/lib/src/vad.dart new file mode 100644 index 000000000..6c36cd8f0 --- /dev/null +++ b/flutter/sherpa_onnx/lib/src/vad.dart @@ -0,0 +1,212 @@ +// Copyright (c) 2024 Xiaomi Corporation +import 'dart:ffi'; +import 'dart:typed_data'; +import 'package:ffi/ffi.dart'; + +import './sherpa_onnx_bindings.dart'; + +class SileroVadModelConfig { + const SileroVadModelConfig( + {this.model = '', + this.threshold = 0.5, + this.minSilenceDuration = 0.5, + this.minSpeechDuration = 0.25, + this.windowSize = 512}); + + @override + String toString() { + return 'SileroVadModelConfig(model: $model, threshold: $threshold, minSilenceDuration: $minSilenceDuration, minSpeechDuration: $minSpeechDuration, windowSize: $windowSize)'; + } + + final String model; + final double threshold; + final double minSilenceDuration; + final double minSpeechDuration; + final int windowSize; +} + +class VadModelConfig { + VadModelConfig( + {this.sileroVad = const SileroVadModelConfig(), + this.sampleRate = 16000, + this.numThreads = 1, + this.provider = 'cpu', + this.debug = true}); + + @override + String toString() { + return 'VadModelConfig(sileroVad: $sileroVad, sampleRate: $sampleRate, numThreads: $numThreads, provider: $provider, debug: $debug)'; + } + + final SileroVadModelConfig sileroVad; + final int sampleRate; + final int numThreads; + final String provider; + final bool debug; +} + +class SpeechSegment { + SpeechSegment({required this.samples, required this.start}); + final Float32List samples; + final int start; +} + +class CircularBuffer { + CircularBuffer._({required this.ptr}); + + /// The user has to invoke CircularBuffer.free() on the returned instance + /// to avoid memory leak. + factory CircularBuffer({required int capacity}) { + assert(capacity > 0, 'capacity is $capacity'); + final p = + SherpaOnnxBindings.createCircularBuffer?.call(capacity) ?? nullptr; + + return CircularBuffer._(ptr: p); + } + + void free() { + SherpaOnnxBindings.destroyCircularBuffer?.call(ptr); + ptr = nullptr; + } + + void push(Float32List data) { + final n = data.length; + final Pointer p = calloc(n); + + final pList = p.asTypedList(n); + pList.setAll(0, data); + + SherpaOnnxBindings.circularBufferPush?.call(ptr, p, n); + + calloc.free(p); + } + + Float32List get({required int startIndex, required int n}) { + final Pointer p = + SherpaOnnxBindings.circularBufferGet?.call(ptr, startIndex, n) ?? + nullptr; + + if (p == nullptr) { + return Float32List(0); + } + + final pList = p.asTypedList(n); + final Float32List ans = Float32List.fromList(pList); + + SherpaOnnxBindings.circularBufferFree?.call(p); + + return ans; + } + + void pop(int n) { + SherpaOnnxBindings.circularBufferPop?.call(ptr, n); + } + + void reset() { + SherpaOnnxBindings.circularBufferReset?.call(ptr); + } + + int get size => SherpaOnnxBindings.circularBufferSize?.call(ptr) ?? 0; + int get head => SherpaOnnxBindings.circularBufferHead?.call(ptr) ?? 0; + + Pointer ptr; +} + +class VoiceActivityDetector { + VoiceActivityDetector._({required this.ptr, required this.config}); + + // The user has to invoke VoiceActivityDetector.free() to avoid memory leak. + factory VoiceActivityDetector( + {required VadModelConfig config, required double bufferSizeInSeconds}) { + final c = calloc(); + + final modelPtr = config.sileroVad.model.toNativeUtf8(); + c.ref.sileroVad.model = modelPtr; + + c.ref.sileroVad.threshold = config.sileroVad.threshold; + c.ref.sileroVad.minSilenceDuration = config.sileroVad.minSilenceDuration; + c.ref.sileroVad.minSpeechDuration = config.sileroVad.minSpeechDuration; + c.ref.sileroVad.windowSize = config.sileroVad.windowSize; + + c.ref.sampleRate = config.sampleRate; + c.ref.numThreads = config.numThreads; + + final providerPtr = config.provider.toNativeUtf8(); + c.ref.provider = providerPtr; + + c.ref.debug = config.debug ? 1 : 0; + + final ptr = SherpaOnnxBindings.createVoiceActivityDetector + ?.call(c, bufferSizeInSeconds) ?? + nullptr; + + calloc.free(providerPtr); + calloc.free(modelPtr); + calloc.free(c); + + return VoiceActivityDetector._(ptr: ptr, config: config); + } + + void free() { + SherpaOnnxBindings.destroyVoiceActivityDetector?.call(ptr); + ptr = nullptr; + } + + void acceptWaveform(Float32List samples) { + final n = samples.length; + final Pointer p = calloc(n); + + final pList = p.asTypedList(n); + pList.setAll(0, samples); + + SherpaOnnxBindings.voiceActivityDetectorAcceptWaveform?.call(ptr, p, n); + + calloc.free(p); + } + + bool isEmpty() { + final int empty = + SherpaOnnxBindings.voiceActivityDetectorEmpty?.call(ptr) ?? 0; + + return empty == 1; + } + + bool isDetected() { + final int detected = + SherpaOnnxBindings.voiceActivityDetectorDetected?.call(ptr) ?? 0; + + return detected == 1; + } + + void pop() { + SherpaOnnxBindings.voiceActivityDetectorPop?.call(ptr); + } + + void clear() { + SherpaOnnxBindings.voiceActivityDetectorClear?.call(ptr); + } + + SpeechSegment front() { + final Pointer segment = + SherpaOnnxBindings.voiceActivityDetectorFront?.call(ptr) ?? nullptr; + if (segment == nullptr) { + return SpeechSegment(samples: Float32List(0), start: 0); + } + + final sampleList = segment.ref.samples.asTypedList(segment.ref.n); + final start = segment.ref.start; + + final samples = Float32List.fromList(sampleList); + + SherpaOnnxBindings.destroySpeechSegment?.call(segment); + + return SpeechSegment(samples: samples, start: start); + } + + void reset() { + SherpaOnnxBindings.voiceActivityDetectorReset?.call(ptr); + } + + Pointer ptr; + final VadModelConfig config; +} diff --git a/flutter/sherpa_onnx/lib/src/wave_reader.dart b/flutter/sherpa_onnx/lib/src/wave_reader.dart new file mode 100644 index 000000000..200da4055 --- /dev/null +++ b/flutter/sherpa_onnx/lib/src/wave_reader.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2024 Xiaomi Corporation +import 'dart:ffi'; +import 'dart:typed_data'; +import 'package:ffi/ffi.dart'; + +import './sherpa_onnx_bindings.dart'; + +class WaveData { + WaveData({required this.samples, required this.sampleRate}); + + /// normalized to [-1, 1] + Float32List samples; + int sampleRate; +} + +WaveData readWave(String filename) { + final Pointer str = filename.toNativeUtf8(); + Pointer wave = + SherpaOnnxBindings.readWave?.call(str) ?? nullptr; + calloc.free(str); + + if (wave == nullptr) { + return WaveData(samples: Float32List(0), sampleRate: 0); + } + + final samples = wave.ref.samples.asTypedList(wave.ref.numSamples); + + final newSamples = Float32List.fromList(samples); + int sampleRate = wave.ref.sampleRate; + SherpaOnnxBindings.freeWave?.call(wave); + + return WaveData(samples: newSamples, sampleRate: sampleRate); +} diff --git a/flutter/sherpa_onnx/lib/src/wave_writer.dart b/flutter/sherpa_onnx/lib/src/wave_writer.dart new file mode 100644 index 000000000..bd6c0bbad --- /dev/null +++ b/flutter/sherpa_onnx/lib/src/wave_writer.dart @@ -0,0 +1,27 @@ +// Copyright (c) 2024 Xiaomi Corporation +import 'dart:ffi'; +import 'dart:typed_data'; +import 'package:ffi/ffi.dart'; + +import './sherpa_onnx_bindings.dart'; + +bool writeWave( + {required String filename, + required Float32List samples, + required int sampleRate}) { + final Pointer filenamePtr = filename.toNativeUtf8(); + + final n = samples.length; + final Pointer p = calloc(n); + + final pList = p.asTypedList(n); + pList.setAll(0, samples); + + int ok = + SherpaOnnxBindings.writeWave?.call(p, n, sampleRate, filenamePtr) ?? 0; + + calloc.free(p); + calloc.free(filenamePtr); + + return ok == 1; +} diff --git a/flutter/sherpa_onnx/pubspec.yaml b/flutter/sherpa_onnx/pubspec.yaml new file mode 100644 index 000000000..9abcdcd20 --- /dev/null +++ b/flutter/sherpa_onnx/pubspec.yaml @@ -0,0 +1,58 @@ +name: sherpa_onnx + +description: > + Speech recognition, speech synthesis, and speaker recognition using next-gen Kaldi + with onnxruntime without Internet connection. + +repository: https://github.com/k2-fsa/sherpa-onnx/tree/master/sherpa-onnx/flutter + +issue_tracker: https://github.com/k2-fsa/sherpa-onnx/issues +documentation: https://k2-fsa.github.io/sherpa/onnx/ + +topics: + - speech-recognition + - speech-synthesis + - speaker-identification + - audio-tagging + - voice-activity-detection + +# remember to change the version in ../sherpa_onnx_macos/macos/sherpa_onnx.podspec +version: 1.10.7 + +homepage: https://github.com/k2-fsa/sherpa-onnx + +environment: + sdk: '>=3.4.0 <4.0.0' + flutter: '>=3.3.0' + +dependencies: + ffi: ^2.1.0 + flutter: + sdk: flutter + + sherpa_onnx_android: + # path: ../sherpa_onnx_android + + sherpa_onnx_macos: + # path: ../sherpa_onnx_macos + + sherpa_onnx_linux: + # path: ../sherpa_onnx_linux + # + sherpa_onnx_windows: + # path: ../sherpa_onnx_windows + +flutter: + plugin: + platforms: + android: + default_package: sherpa_onnx_android + + macos: + default_package: sherpa_onnx_macos + + linux: + default_package: sherpa_onnx_linux + + windows: + default_package: sherpa_onnx_windows diff --git a/flutter/sherpa_onnx_android/.gitignore b/flutter/sherpa_onnx_android/.gitignore new file mode 100644 index 000000000..ac5aa9893 --- /dev/null +++ b/flutter/sherpa_onnx_android/.gitignore @@ -0,0 +1,29 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +build/ diff --git a/flutter/sherpa_onnx_android/.metadata b/flutter/sherpa_onnx_android/.metadata new file mode 100644 index 000000000..8dd5c0dc2 --- /dev/null +++ b/flutter/sherpa_onnx_android/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "5dcb86f68f239346676ceb1ed1ea385bd215fba1" + channel: "stable" + +project_type: plugin_ffi + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + - platform: android + create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/flutter/sherpa_onnx_android/README.md b/flutter/sherpa_onnx_android/README.md new file mode 100644 index 000000000..2b3d35137 --- /dev/null +++ b/flutter/sherpa_onnx_android/README.md @@ -0,0 +1,7 @@ +# sherpa_onnx_android + +This is a sub project of [sherpa-onnx](https://github.com/k2-fsa/sherpa-onnx). + +You are not expected to use this package directly. + +Please see the entry point at . diff --git a/flutter/sherpa_onnx_android/analysis_options.yaml b/flutter/sherpa_onnx_android/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/flutter/sherpa_onnx_android/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/flutter/sherpa_onnx_android/android/.gitignore b/flutter/sherpa_onnx_android/android/.gitignore new file mode 100644 index 000000000..161bdcdaf --- /dev/null +++ b/flutter/sherpa_onnx_android/android/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.cxx diff --git a/flutter/sherpa_onnx_android/android/build.gradle b/flutter/sherpa_onnx_android/android/build.gradle new file mode 100644 index 000000000..1cf3c2bcf --- /dev/null +++ b/flutter/sherpa_onnx_android/android/build.gradle @@ -0,0 +1,48 @@ +// The Android Gradle Plugin builds the native code with the Android NDK. + +group = "com.k2fsa.sherpa.onnx.sherpa_onnx_android" +version = "1.0" + +buildscript { + repositories { + google() + mavenCentral() + } + + dependencies { + // The Android Gradle Plugin knows how to build native code with the NDK. + classpath("com.android.tools.build:gradle:7.3.0") + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: "com.android.library" + +android { + namespace 'com.k2fsa.sherpa.onnx' + + // Bumping the plugin compileSdk version requires all clients of this plugin + // to bump the version in their app. + compileSdk = 34 + + // Use the NDK version + // declared in /android/app/build.gradle file of the Flutter project. + // Replace it with a version number if this plugin requires a specific NDK version. + // (e.g. ndkVersion "23.1.7779620") + ndkVersion = android.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + defaultConfig { + minSdk = 21 + } +} diff --git a/flutter/sherpa_onnx_android/android/settings.gradle b/flutter/sherpa_onnx_android/android/settings.gradle new file mode 100644 index 000000000..9e98ed9ba --- /dev/null +++ b/flutter/sherpa_onnx_android/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'sherpa_onnx_android' diff --git a/flutter/sherpa_onnx_android/android/src/main/AndroidManifest.xml b/flutter/sherpa_onnx_android/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..8b785d2fe --- /dev/null +++ b/flutter/sherpa_onnx_android/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/flutter/sherpa_onnx_android/android/src/main/jniLibs/README.md b/flutter/sherpa_onnx_android/android/src/main/jniLibs/README.md new file mode 100644 index 000000000..8c99d0c37 --- /dev/null +++ b/flutter/sherpa_onnx_android/android/src/main/jniLibs/README.md @@ -0,0 +1,23 @@ +# Introduction + +Pre-built libs are not checked-in. + +Please use + + - https://github.com/k2-fsa/sherpa-onnx/blob/master/build-android-arm64-v8a.sh + - https://github.com/k2-fsa/sherpa-onnx/blob/master/build-android-armv7-eabi.sh + - https://github.com/k2-fsa/sherpa-onnx/blob/master/build-android-x86-64.sh + - https://github.com/k2-fsa/sherpa-onnx/blob/master/build-android-x86.sh + +The following is an example for `arm64-v8a`: + +```bash +git clone https://github.com/k2-fsa/sherpa-onnx +cd sherpa-onnx + +export SHERPA_ONNX_ENABLE_JNI=OFF +export SHERPA_ONNX_ENABLE_C_API=ON +./build-android-arm64-v8a.sh + +cp -v build-android-arm64-v8a/install/lib/*.so flutter/sherpa_onnx_android/android/src/main/jniLibs/arm64-v8a/ +``` diff --git a/flutter/sherpa_onnx_android/android/src/main/jniLibs/arm64-v8a/.gitkeep b/flutter/sherpa_onnx_android/android/src/main/jniLibs/arm64-v8a/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/flutter/sherpa_onnx_android/android/src/main/jniLibs/armeabi-v7a/.gitkeep b/flutter/sherpa_onnx_android/android/src/main/jniLibs/armeabi-v7a/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/flutter/sherpa_onnx_android/android/src/main/jniLibs/x86/.gitkeep b/flutter/sherpa_onnx_android/android/src/main/jniLibs/x86/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/flutter/sherpa_onnx_android/android/src/main/jniLibs/x86_64/.gitkeep b/flutter/sherpa_onnx_android/android/src/main/jniLibs/x86_64/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/flutter/sherpa_onnx_android/example/.gitignore b/flutter/sherpa_onnx_android/example/.gitignore new file mode 100644 index 000000000..29a3a5017 --- /dev/null +++ b/flutter/sherpa_onnx_android/example/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/flutter/sherpa_onnx_android/example/README.md b/flutter/sherpa_onnx_android/example/README.md new file mode 100644 index 000000000..c97c78739 --- /dev/null +++ b/flutter/sherpa_onnx_android/example/README.md @@ -0,0 +1,9 @@ +# Introduction + +Please find examples at + +https://github.com/k2-fsa/sherpa-onnx/tree/master/flutter-examples + +and + +https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples diff --git a/flutter/sherpa_onnx_android/example/example.md b/flutter/sherpa_onnx_android/example/example.md new file mode 100644 index 000000000..3f8957b2e --- /dev/null +++ b/flutter/sherpa_onnx_android/example/example.md @@ -0,0 +1,18 @@ +# sherpa-onnx app example + +## Streaming speech recognition + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/streaming-asr + +## Non-streaming speech recognition + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/non-streaming-asr + +## Text to speech (TTS) + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/tts + +## Voice activity detection (VAD) + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/vad + diff --git a/flutter/sherpa_onnx_android/lib/.gitkeep b/flutter/sherpa_onnx_android/lib/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/flutter/sherpa_onnx_android/pubspec.yaml b/flutter/sherpa_onnx_android/pubspec.yaml new file mode 100644 index 000000000..42f8ae5c0 --- /dev/null +++ b/flutter/sherpa_onnx_android/pubspec.yaml @@ -0,0 +1,18 @@ +name: sherpa_onnx_android +description: "A new Flutter FFI plugin project." +version: 0.0.1 +homepage: + +environment: + sdk: '>=3.4.0 <4.0.0' + flutter: '>=3.3.0' + +dependencies: + flutter: + sdk: flutter + +flutter: + plugin: + platforms: + android: + ffiPlugin: true diff --git a/flutter/sherpa_onnx_linux/.gitignore b/flutter/sherpa_onnx_linux/.gitignore new file mode 100644 index 000000000..ac5aa9893 --- /dev/null +++ b/flutter/sherpa_onnx_linux/.gitignore @@ -0,0 +1,29 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +build/ diff --git a/flutter/sherpa_onnx_linux/.metadata b/flutter/sherpa_onnx_linux/.metadata new file mode 100644 index 000000000..4147421f4 --- /dev/null +++ b/flutter/sherpa_onnx_linux/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "5dcb86f68f239346676ceb1ed1ea385bd215fba1" + channel: "stable" + +project_type: plugin_ffi + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + - platform: linux + create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/flutter/sherpa_onnx_linux/README.md b/flutter/sherpa_onnx_linux/README.md new file mode 100644 index 000000000..1334c2564 --- /dev/null +++ b/flutter/sherpa_onnx_linux/README.md @@ -0,0 +1,7 @@ +# sherpa_onnx_linux + +This is a sub project of [sherpa-onnx](https://github.com/k2-fsa/sherpa-onnx). + +You are not expected to use this package directly. + +Please see the entry point at . diff --git a/flutter/sherpa_onnx_linux/analysis_options.yaml b/flutter/sherpa_onnx_linux/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/flutter/sherpa_onnx_linux/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/flutter/sherpa_onnx_linux/example/.gitignore b/flutter/sherpa_onnx_linux/example/.gitignore new file mode 100644 index 000000000..29a3a5017 --- /dev/null +++ b/flutter/sherpa_onnx_linux/example/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/flutter/sherpa_onnx_linux/example/README.md b/flutter/sherpa_onnx_linux/example/README.md new file mode 100644 index 000000000..c97c78739 --- /dev/null +++ b/flutter/sherpa_onnx_linux/example/README.md @@ -0,0 +1,9 @@ +# Introduction + +Please find examples at + +https://github.com/k2-fsa/sherpa-onnx/tree/master/flutter-examples + +and + +https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples diff --git a/flutter/sherpa_onnx_linux/example/example.md b/flutter/sherpa_onnx_linux/example/example.md new file mode 100644 index 000000000..3f8957b2e --- /dev/null +++ b/flutter/sherpa_onnx_linux/example/example.md @@ -0,0 +1,18 @@ +# sherpa-onnx app example + +## Streaming speech recognition + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/streaming-asr + +## Non-streaming speech recognition + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/non-streaming-asr + +## Text to speech (TTS) + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/tts + +## Voice activity detection (VAD) + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/vad + diff --git a/flutter/sherpa_onnx_linux/lib/.gitkeep b/flutter/sherpa_onnx_linux/lib/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/flutter/sherpa_onnx_linux/linux/CMakeLists.txt b/flutter/sherpa_onnx_linux/linux/CMakeLists.txt new file mode 100644 index 000000000..5b3cc73b7 --- /dev/null +++ b/flutter/sherpa_onnx_linux/linux/CMakeLists.txt @@ -0,0 +1,27 @@ +# The Flutter tooling requires that developers have CMake 3.10 or later +# installed. You should not increase this version, as doing so will cause +# the plugin to fail to compile for some customers of the plugin. +cmake_minimum_required(VERSION 3.10) + +# Project-level configuration. +set(PROJECT_NAME "sherpa_onnx_linux") +project(${PROJECT_NAME} LANGUAGES CXX) + +# List of absolute paths to libraries that should be bundled with the plugin. +# This list could contain prebuilt libraries, or libraries created by an +# external build triggered from this build file. +set(sherpa_onnx_linux_bundled_libraries + "${CMAKE_CURRENT_SOURCE_DIR}/libsherpa-onnx-c-api.so" + "${CMAKE_CURRENT_SOURCE_DIR}/libsherpa-onnx-core.so" + "${CMAKE_CURRENT_SOURCE_DIR}/libkaldi-decoder-core.so" + "${CMAKE_CURRENT_SOURCE_DIR}/libsherpa-onnx-kaldifst-core.so" + "${CMAKE_CURRENT_SOURCE_DIR}/libsherpa-onnx-fstfar.so" + "${CMAKE_CURRENT_SOURCE_DIR}/libsherpa-onnx-fst.so" + "${CMAKE_CURRENT_SOURCE_DIR}/libkaldi-native-fbank-core.so" + "${CMAKE_CURRENT_SOURCE_DIR}/libpiper_phonemize.so" + "${CMAKE_CURRENT_SOURCE_DIR}/libespeak-ng.so" + "${CMAKE_CURRENT_SOURCE_DIR}/libucd.so" + "${CMAKE_CURRENT_SOURCE_DIR}/libonnxruntime.so" + "${CMAKE_CURRENT_SOURCE_DIR}/libssentencepiece_core.so" + PARENT_SCOPE +) diff --git a/flutter/sherpa_onnx_linux/linux/README.md b/flutter/sherpa_onnx_linux/linux/README.md new file mode 100644 index 000000000..ba607d663 --- /dev/null +++ b/flutter/sherpa_onnx_linux/linux/README.md @@ -0,0 +1,5 @@ +# Introduction + +`*.so` files are generated dynamically using GitHub actions during a new release. + +We don't check-in pre-built library files into git. diff --git a/flutter/sherpa_onnx_linux/pubspec.yaml b/flutter/sherpa_onnx_linux/pubspec.yaml new file mode 100644 index 000000000..c1575d3d0 --- /dev/null +++ b/flutter/sherpa_onnx_linux/pubspec.yaml @@ -0,0 +1,18 @@ +name: sherpa_onnx_linux +description: "A new Flutter FFI plugin project." +version: 0.0.1 +homepage: + +environment: + sdk: '>=3.4.0 <4.0.0' + flutter: '>=3.3.0' + +dependencies: + flutter: + sdk: flutter + +flutter: + plugin: + platforms: + linux: + ffiPlugin: true diff --git a/flutter/sherpa_onnx_macos/.gitignore b/flutter/sherpa_onnx_macos/.gitignore new file mode 100644 index 000000000..ac5aa9893 --- /dev/null +++ b/flutter/sherpa_onnx_macos/.gitignore @@ -0,0 +1,29 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +build/ diff --git a/flutter/sherpa_onnx_macos/.metadata b/flutter/sherpa_onnx_macos/.metadata new file mode 100644 index 000000000..29dbcf198 --- /dev/null +++ b/flutter/sherpa_onnx_macos/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "5dcb86f68f239346676ceb1ed1ea385bd215fba1" + channel: "stable" + +project_type: plugin_ffi + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + - platform: macos + create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/flutter/sherpa_onnx_macos/README.md b/flutter/sherpa_onnx_macos/README.md new file mode 100644 index 000000000..1334c2564 --- /dev/null +++ b/flutter/sherpa_onnx_macos/README.md @@ -0,0 +1,7 @@ +# sherpa_onnx_linux + +This is a sub project of [sherpa-onnx](https://github.com/k2-fsa/sherpa-onnx). + +You are not expected to use this package directly. + +Please see the entry point at . diff --git a/flutter/sherpa_onnx_macos/analysis_options.yaml b/flutter/sherpa_onnx_macos/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/flutter/sherpa_onnx_macos/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/flutter/sherpa_onnx_macos/example/README.md b/flutter/sherpa_onnx_macos/example/README.md new file mode 100644 index 000000000..c97c78739 --- /dev/null +++ b/flutter/sherpa_onnx_macos/example/README.md @@ -0,0 +1,9 @@ +# Introduction + +Please find examples at + +https://github.com/k2-fsa/sherpa-onnx/tree/master/flutter-examples + +and + +https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples diff --git a/flutter/sherpa_onnx_macos/example/example.md b/flutter/sherpa_onnx_macos/example/example.md new file mode 100644 index 000000000..3f8957b2e --- /dev/null +++ b/flutter/sherpa_onnx_macos/example/example.md @@ -0,0 +1,18 @@ +# sherpa-onnx app example + +## Streaming speech recognition + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/streaming-asr + +## Non-streaming speech recognition + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/non-streaming-asr + +## Text to speech (TTS) + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/tts + +## Voice activity detection (VAD) + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/vad + diff --git a/flutter/sherpa_onnx_macos/lib/.gitkeep b/flutter/sherpa_onnx_macos/lib/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/flutter/sherpa_onnx_macos/macos/README.md b/flutter/sherpa_onnx_macos/macos/README.md new file mode 100644 index 000000000..70a55fc7a --- /dev/null +++ b/flutter/sherpa_onnx_macos/macos/README.md @@ -0,0 +1,5 @@ +# Introduction + +`*.dylib` files are generated dynamically using GitHub actions during a new release. + +We don't check-in pre-built library files into git. diff --git a/flutter/sherpa_onnx_macos/macos/sherpa_onnx_macos.podspec b/flutter/sherpa_onnx_macos/macos/sherpa_onnx_macos.podspec new file mode 100644 index 000000000..12d7ac782 --- /dev/null +++ b/flutter/sherpa_onnx_macos/macos/sherpa_onnx_macos.podspec @@ -0,0 +1,27 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint sherpa_onnx_macos.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'sherpa_onnx_macos' + s.version = '1.10.6' + s.summary = 'sherpa-onnx Flutter FFI plugin project.' + s.description = <<-DESC +sherpa-onnx Flutter FFI plugin project. + DESC + s.homepage = 'https://github.com/k2-fsa/sherpa-onnx' + s.license = { :file => '../LICENSE' } + s.author = { 'Fangjun Kuang' => 'csukuangfj@gmail.com' } + + # This will ensure the source files in Classes/ are included in the native + # builds of apps using this FFI plugin. Podspec does not support relative + # paths, so Classes contains a forwarder C file that relatively imports + # `../src/*` so that the C sources can be shared among all target platforms. + s.source = { :path => '.' } + s.dependency 'FlutterMacOS' + s.vendored_libraries = '*.dylib' + + s.platform = :osx, '10.11' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.swift_version = '5.0' +end diff --git a/flutter/sherpa_onnx_macos/pubspec.yaml b/flutter/sherpa_onnx_macos/pubspec.yaml new file mode 100644 index 000000000..92099f264 --- /dev/null +++ b/flutter/sherpa_onnx_macos/pubspec.yaml @@ -0,0 +1,18 @@ +name: sherpa_onnx_macos +description: "A new Flutter FFI plugin project." +version: 0.0.1 +homepage: + +environment: + sdk: '>=3.4.0 <4.0.0' + flutter: '>=3.3.0' + +dependencies: + flutter: + sdk: flutter + +flutter: + plugin: + platforms: + macos: + ffiPlugin: true diff --git a/flutter/sherpa_onnx_windows/.gitignore b/flutter/sherpa_onnx_windows/.gitignore new file mode 100644 index 000000000..ac5aa9893 --- /dev/null +++ b/flutter/sherpa_onnx_windows/.gitignore @@ -0,0 +1,29 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +build/ diff --git a/flutter/sherpa_onnx_windows/.metadata b/flutter/sherpa_onnx_windows/.metadata new file mode 100644 index 000000000..20b50462d --- /dev/null +++ b/flutter/sherpa_onnx_windows/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "5dcb86f68f239346676ceb1ed1ea385bd215fba1" + channel: "stable" + +project_type: plugin_ffi + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + - platform: windows + create_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + base_revision: 5dcb86f68f239346676ceb1ed1ea385bd215fba1 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/flutter/sherpa_onnx_windows/README.md b/flutter/sherpa_onnx_windows/README.md new file mode 100644 index 000000000..1334c2564 --- /dev/null +++ b/flutter/sherpa_onnx_windows/README.md @@ -0,0 +1,7 @@ +# sherpa_onnx_linux + +This is a sub project of [sherpa-onnx](https://github.com/k2-fsa/sherpa-onnx). + +You are not expected to use this package directly. + +Please see the entry point at . diff --git a/flutter/sherpa_onnx_windows/analysis_options.yaml b/flutter/sherpa_onnx_windows/analysis_options.yaml new file mode 100644 index 000000000..a5744c1cf --- /dev/null +++ b/flutter/sherpa_onnx_windows/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/flutter/sherpa_onnx_windows/example/.gitignore b/flutter/sherpa_onnx_windows/example/.gitignore new file mode 100644 index 000000000..29a3a5017 --- /dev/null +++ b/flutter/sherpa_onnx_windows/example/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/flutter/sherpa_onnx_windows/example/README.md b/flutter/sherpa_onnx_windows/example/README.md new file mode 100644 index 000000000..c97c78739 --- /dev/null +++ b/flutter/sherpa_onnx_windows/example/README.md @@ -0,0 +1,9 @@ +# Introduction + +Please find examples at + +https://github.com/k2-fsa/sherpa-onnx/tree/master/flutter-examples + +and + +https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples diff --git a/flutter/sherpa_onnx_windows/example/example.md b/flutter/sherpa_onnx_windows/example/example.md new file mode 100644 index 000000000..3f8957b2e --- /dev/null +++ b/flutter/sherpa_onnx_windows/example/example.md @@ -0,0 +1,18 @@ +# sherpa-onnx app example + +## Streaming speech recognition + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/streaming-asr + +## Non-streaming speech recognition + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/non-streaming-asr + +## Text to speech (TTS) + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/tts + +## Voice activity detection (VAD) + +Please see https://github.com/k2-fsa/sherpa-onnx/tree/master/dart-api-examples/vad + diff --git a/flutter/sherpa_onnx_windows/lib/.gitkeep b/flutter/sherpa_onnx_windows/lib/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/flutter/sherpa_onnx_windows/pubspec.yaml b/flutter/sherpa_onnx_windows/pubspec.yaml new file mode 100644 index 000000000..dac101c21 --- /dev/null +++ b/flutter/sherpa_onnx_windows/pubspec.yaml @@ -0,0 +1,18 @@ +name: sherpa_onnx_windows +description: "A new Flutter FFI plugin project." +version: 0.0.1 +homepage: + +environment: + sdk: '>=3.4.0 <4.0.0' + flutter: '>=3.3.0' + +dependencies: + flutter: + sdk: flutter + +flutter: + plugin: + platforms: + windows: + ffiPlugin: true diff --git a/flutter/sherpa_onnx_windows/windows/.gitignore b/flutter/sherpa_onnx_windows/windows/.gitignore new file mode 100644 index 000000000..b3eb2be16 --- /dev/null +++ b/flutter/sherpa_onnx_windows/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/flutter/sherpa_onnx_windows/windows/CMakeLists.txt b/flutter/sherpa_onnx_windows/windows/CMakeLists.txt new file mode 100644 index 000000000..811931ed1 --- /dev/null +++ b/flutter/sherpa_onnx_windows/windows/CMakeLists.txt @@ -0,0 +1,28 @@ +# The Flutter tooling requires that developers have a version of Visual Studio +# installed that includes CMake 3.14 or later. You should not increase this +# version, as doing so will cause the plugin to fail to compile for some +# customers of the plugin. +cmake_minimum_required(VERSION 3.14) + +# Project-level configuration. +set(PROJECT_NAME "sherpa_onnx_windows") +project(${PROJECT_NAME} LANGUAGES CXX) + +# List of absolute paths to libraries that should be bundled with the plugin. +# This list could contain prebuilt libraries, or libraries created by an +# external build triggered from this build file. +set(sherpa_onnx_windows_bundled_libraries + "${CMAKE_CURRENT_SOURCE_DIR}/sherpa-onnx-c-api.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/sherpa-onnx-core.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/kaldi-decoder-core.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/sherpa-onnx-kaldifst-core.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/sherpa-onnx-fstfar.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/sherpa-onnx-fst.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/kaldi-native-fbank-core.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/piper_phonemize.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/espeak-ng.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/ucd.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/onnxruntime.dll" + "${CMAKE_CURRENT_SOURCE_DIR}/ssentencepiece_core.dll" + PARENT_SCOPE +) diff --git a/flutter/sherpa_onnx_windows/windows/README.md b/flutter/sherpa_onnx_windows/windows/README.md new file mode 100644 index 000000000..c44a915f2 --- /dev/null +++ b/flutter/sherpa_onnx_windows/windows/README.md @@ -0,0 +1,5 @@ +# Introduction + +`*.dll` files are generated dynamically using GitHub actions during a new release. + +We don't check-in pre-built library files into git. diff --git a/scripts/dart/non-streaming-asr-pubspec.yaml b/scripts/dart/non-streaming-asr-pubspec.yaml index 8d389f38f..eaf65315c 100644 --- a/scripts/dart/non-streaming-asr-pubspec.yaml +++ b/scripts/dart/non-streaming-asr-pubspec.yaml @@ -10,7 +10,7 @@ environment: # Add regular dependencies here. dependencies: sherpa_onnx: - path: ../../sherpa-onnx/flutter + path: ../../flutter/sherpa_onnx path: ^1.9.0 args: ^2.5.0 diff --git a/scripts/dart/sherpa-onnx-pubspec.yaml b/scripts/dart/sherpa-onnx-pubspec.yaml new file mode 100644 index 000000000..6dc338ad5 --- /dev/null +++ b/scripts/dart/sherpa-onnx-pubspec.yaml @@ -0,0 +1,58 @@ +name: sherpa_onnx + +description: > + Speech recognition, speech synthesis, and speaker recognition using next-gen Kaldi + with onnxruntime without Internet connection. + +repository: https://github.com/k2-fsa/sherpa-onnx/tree/master/sherpa-onnx/flutter + +issue_tracker: https://github.com/k2-fsa/sherpa-onnx/issues +documentation: https://k2-fsa.github.io/sherpa/onnx/ + +topics: + - speech-recognition + - speech-synthesis + - speaker-identification + - audio-tagging + - voice-activity-detection + +# remember to change the version in ../sherpa_onnx_macos/macos/sherpa_onnx.podspec +version: 1.10.6 + +homepage: https://github.com/k2-fsa/sherpa-onnx + +environment: + sdk: '>=3.4.0 <4.0.0' + flutter: '>=3.3.0' + +dependencies: + ffi: ^2.1.0 + flutter: + sdk: flutter + + sherpa_onnx_android: + path: ../sherpa_onnx_android + + sherpa_onnx_macos: + path: ../sherpa_onnx_macos + + sherpa_onnx_linux: + path: ../sherpa_onnx_linux + + sherpa_onnx_windows: + path: ../sherpa_onnx_windows + +flutter: + plugin: + platforms: + android: + default_package: sherpa_onnx_android + + macos: + default_package: sherpa_onnx_macos + + linux: + default_package: sherpa_onnx_linux + + windows: + default_package: sherpa_onnx_windows diff --git a/scripts/dart/streaming-asr-pubspec.yaml b/scripts/dart/streaming-asr-pubspec.yaml index c9ee9e3ce..1ad4cb5cf 100644 --- a/scripts/dart/streaming-asr-pubspec.yaml +++ b/scripts/dart/streaming-asr-pubspec.yaml @@ -12,7 +12,8 @@ environment: # Add regular dependencies here. dependencies: sherpa_onnx: - path: ../../sherpa-onnx/flutter + path: ../../flutter/sherpa_onnx + path: ^1.9.0 args: ^2.5.0 diff --git a/scripts/dart/tts-pubspec.yaml b/scripts/dart/tts-pubspec.yaml index 0bbb3fcb7..c5364c411 100644 --- a/scripts/dart/tts-pubspec.yaml +++ b/scripts/dart/tts-pubspec.yaml @@ -9,7 +9,8 @@ environment: # Add regular dependencies here. dependencies: sherpa_onnx: - path: ../../sherpa-onnx/flutter + path: ../../flutter/sherpa_onnx + path: ^1.9.0 args: ^2.5.0 diff --git a/scripts/dart/vad-pubspec.yaml b/scripts/dart/vad-pubspec.yaml index 2d9758df1..d43465ff8 100644 --- a/scripts/dart/vad-pubspec.yaml +++ b/scripts/dart/vad-pubspec.yaml @@ -10,7 +10,8 @@ environment: dependencies: sherpa_onnx: - path: ../../sherpa-onnx/flutter + path: ../../flutter/sherpa_onnx + path: ^1.9.0 args: ^2.5.0