zhaomingwork
Committed by GitHub

add java wrapper suppport (#117)

@@ -7,3 +7,104 @@ Standard: Cpp11 @@ -7,3 +7,104 @@ Standard: Cpp11
7 DerivePointerAlignment: false 7 DerivePointerAlignment: false
8 PointerAlignment: Right 8 PointerAlignment: Right
9 --- 9 ---
  10 +Language: Java
  11 +JavaImportGroups: [ 'java', 'javax', 'javafx', 'org', 'io', 'com', 'de.gsi' ]
  12 +AccessModifierOffset: -4
  13 +AlignAfterOpenBracket: DontAlign
  14 +AlignConsecutiveAssignments: false
  15 +AlignConsecutiveDeclarations: false
  16 +AlignEscapedNewlines: DontAlign
  17 +AlignTrailingComments: false
  18 +AllowAllParametersOfDeclarationOnNextLine: true
  19 +AllowShortLambdasOnASingleLine: None
  20 +AllowShortCaseLabelsOnASingleLine: false
  21 +AllowShortFunctionsOnASingleLine: None
  22 +AllowShortIfStatementsOnASingleLine: Never
  23 +AllowShortLoopsOnASingleLine: false
  24 +AlwaysBreakAfterReturnType: None
  25 +AlwaysBreakBeforeMultilineStrings: false
  26 +AlwaysBreakTemplateDeclarations: Yes
  27 +BinPackArguments: true
  28 +BinPackParameters: true
  29 +BraceWrapping:
  30 + AfterClass: false
  31 + AfterControlStatement: Never
  32 + AfterEnum: false
  33 + AfterFunction: false
  34 + AfterNamespace: false
  35 + AfterObjCDeclaration: false
  36 + AfterStruct: false
  37 + AfterUnion: false
  38 + BeforeCatch: false
  39 + BeforeElse: false
  40 + IndentBraces: false
  41 + SplitEmptyFunction: true
  42 + SplitEmptyRecord: true
  43 + SplitEmptyNamespace: true
  44 +BreakBeforeBinaryOperators: All
  45 +BreakBeforeBraces: Custom
  46 +BreakBeforeInheritanceComma: false
  47 +BreakBeforeTernaryOperators: true
  48 +BreakConstructorInitializersBeforeComma: false
  49 +BreakConstructorInitializers: BeforeComma
  50 +BreakAfterJavaFieldAnnotations: true
  51 +BreakStringLiterals: true
  52 +ColumnLimit: 0
  53 +CommentPragmas: '^ IWYU pragma:'
  54 +CompactNamespaces: false
  55 +ConstructorInitializerAllOnOneLineOrOnePerLine: false
  56 +ConstructorInitializerIndentWidth: 4
  57 +ContinuationIndentWidth: 8
  58 +Cpp11BracedListStyle: false
  59 +DerivePointerAlignment: false
  60 +DisableFormat: false
  61 +ExperimentalAutoDetectBinPacking: false
  62 +FixNamespaceComments: true
  63 +ForEachMacros:
  64 + - forever # avoids { wrapped to next line
  65 + - foreach
  66 + - Q_FOREACH
  67 + - BOOST_FOREACH
  68 +IncludeCategories:
  69 + - Regex: '^<Q.*'
  70 + Priority: 200
  71 +IncludeIsMainRegex: '(Test)?$'
  72 +IndentCaseLabels: false
  73 +IndentWidth: 4
  74 +IndentWrappedFunctionNames: false
  75 +JavaScriptQuotes: Leave
  76 +JavaScriptWrapImports: true
  77 +KeepEmptyLinesAtTheStartOfBlocks: false
  78 +# Do not add QT_BEGIN_NAMESPACE/QT_END_NAMESPACE as this will indent lines in between.
  79 +MacroBlockBegin: ""
  80 +MacroBlockEnd: ""
  81 +MaxEmptyLinesToKeep: 1
  82 +NamespaceIndentation: None
  83 +ObjCBlockIndentWidth: 4
  84 +ObjCSpaceAfterProperty: false
  85 +ObjCSpaceBeforeProtocolList: true
  86 +PenaltyBreakAssignment: 150
  87 +PenaltyBreakBeforeFirstCallParameter: 300
  88 +PenaltyBreakComment: 500
  89 +PenaltyBreakFirstLessLess: 400
  90 +PenaltyBreakString: 600
  91 +PenaltyExcessCharacter: 50
  92 +PenaltyReturnTypeOnItsOwnLine: 300
  93 +PointerAlignment: Right
  94 +ReflowComments: true
  95 +SortIncludes: true
  96 +SortUsingDeclarations: true
  97 +SpaceAfterCStyleCast: true
  98 +SpaceAfterTemplateKeyword: false
  99 +SpaceBeforeAssignmentOperators: true
  100 +SpaceBeforeParens: ControlStatements
  101 +SpaceInEmptyParentheses: false
  102 +SpacesBeforeTrailingComments: 1
  103 +SpacesInAngles: false
  104 +SpacesInContainerLiterals: false
  105 +SpacesInCStyleCastParentheses: false
  106 +SpacesInParentheses: false
  107 +SpacesInSquareBrackets: false
  108 +Standard: c++17
  109 +TabWidth: 4
  110 +UseTab: Never
  1 +
  2 +ENTRY_POINT = ./
  3 +
  4 +LIB_SRC_DIR := ../sherpa-onnx/java-api/src/com/k2fsa/sherpa/onnx
  5 +
  6 +LIB_FILES = \
  7 + $(LIB_SRC_DIR)/EndpointRule.java \
  8 + $(LIB_SRC_DIR)/EndpointConfig.java \
  9 + $(LIB_SRC_DIR)/FeatureConfig.java \
  10 + $(LIB_SRC_DIR)/OnlineTransducerModelConfig.java \
  11 + $(LIB_SRC_DIR)/OnlineRecognizerConfig.java \
  12 + $(LIB_SRC_DIR)/OnlineStream.java \
  13 + $(LIB_SRC_DIR)/OnlineRecognizer.java \
  14 +
  15 +LIB_BUILD_DIR = ./lib
  16 +
  17 +
  18 +EXAMPLE_FILE = DecodeFile.java
  19 +
  20 +JAVAC = javac
  21 +
  22 +BUILD_DIR = build
  23 +
  24 +
  25 +RUNJFLAGS = -Dfile.encoding=utf-8
  26 +
  27 +
  28 +vpath %.class $(BUILD_DIR)
  29 +vpath %.java src
  30 +
  31 +
  32 +buildexample:
  33 + $(JAVAC) -cp lib/sherpaonnx.jar -d $(BUILD_DIR) -encoding UTF-8 src/$(EXAMPLE_FILE)
  34 +
  35 +rebuild: clean all
  36 +
  37 +.PHONY: clean run
  38 +
  39 +clean:
  40 + rm -frv $(BUILD_DIR)/*
  41 + rm -frv $(LIB_BUILD_DIR)/*
  42 + mkdir -p $(BUILD_DIR)
  43 + mkdir -p ./lib
  44 +
  45 +
  46 +run:
  47 +
  48 + java -cp ./lib/sherpaonnx.jar:build $(RUNJFLAGS) DecodeFile
  49 +
  50 +
  51 +buildlib: $(LIB_FILES:.java=.class)
  52 +
  53 +
  54 +%.class: %.java
  55 +
  56 + $(JAVAC) -cp $(BUILD_DIR) -d $(BUILD_DIR) -encoding UTF-8 $<
  57 +
  58 +packjar:
  59 + jar cvfe lib/sherpaonnx.jar . -C $(BUILD_DIR) .
  60 +
  61 +all: clean buildlib packjar buildexample run
  1 +
  2 +0.Introduction
  3 +---
  4 +Java wrapper `com.k2fsa.sherpaonnx.OnlineRecognizer` for `sherpa-onnx`. Java is a cross-platform language; you can build jni .so lib according to your system, and then use the same java api for all your platform.
  5 +``` xml
  6 +Depend on:
  7 + Openjdk 1.8
  8 +```
  9 +---
  10 +1.Compile libsherpa-onnx-jni.so
  11 +---
  12 +Compile sherpa-onnx/jni/jni.cc according to your system.
  13 +Example for Ubuntu 18.04 LTS, Openjdk 1.8.0_362:
  14 +``` xml
  15 + git clone https://github.com/k2-fsa/sherpa-onnx
  16 + cd sherpa-onnx
  17 + mkdir build
  18 + cd build
  19 + cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DSHERPA_ONNX_ENABLE_JNI=ON ..
  20 + make -j6
  21 +```
  22 +---
  23 +2.Download asr model files
  24 +---
  25 +[click here for more detail](https://k2-fsa.github.io/sherpa/onnx/pretrained_models/index.html)
  26 +---
  27 +3.Config model config.cfg
  28 +---
  29 +``` xml
  30 + #model config
  31 + sample_rate=16000
  32 + feature_dim=80
  33 + rule1_min_trailing_silence=2.4
  34 + rule2_min_trailing_silence=1.2
  35 + rule3_min_utterance_length=20
  36 + encoder=/sherpa-onnx/build/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/encoder-epoch-99-avg-1.onnx
  37 + decoder=/sherpa-onnx/build/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/decoder-epoch-99-avg-1.onnx
  38 + joiner=/sherpa-onnx/build/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/joiner-epoch-99-avg-1.onnx
  39 + tokens=/sherpa-onnx/build/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/tokens.txt
  40 + num_threads=4
  41 + enable_endpoint_detection=false
  42 + decoding_method=greedy_search
  43 + max_active_paths=4
  44 +```
  45 +---
  46 +4.A simple java example
  47 +---
  48 +refer to [java_api_example](https://github.com/k2-fsa/sherpa-onnx/blob/master/java-api-examples/src/DecodeFile.java) for more detail.
  49 +``` java
  50 + import com.k2fsa.sherpa.onnx.OnlineRecognizer;
  51 + import com.k2fsa.sherpa.onnx.OnlineStream;
  52 + String cfgpath=appdir+"/modelconfig.cfg";
  53 + OnlineRecognizer.setSoPath(soPath); //set so lib path
  54 +
  55 + OnlineRecognizer rcgOjb = new OnlineRecognizer(); //create a recognizer
  56 + rcgOjb = new OnlineRecognizer(cfgFile); //set model config file
  57 + CreateStream streamObj=rcgOjb.CreateStream(); //create a stream for read wav data
  58 + float[] buffer = rcgOjb.readWavFile(wavfilename); // read data from file
  59 + streamObj.acceptWaveform(buffer); // feed stream with data
  60 + streamObj.inputFinished(); // tell engine you done with all data
  61 + OnlineStream ssObj[] = new OnlineStream[1];
  62 + while (rcgOjb.isReady(streamObj)) { // engine is ready for unprocessed data
  63 + ssObj[0] = streamObj;
  64 + rcgOjb.decodeStreams(ssObj); // decode for multiple stream
  65 + // rcgOjb.DecodeStream(streamObj); // decode for single stream
  66 + }
  67 +
  68 + String recText = "simple:" + rcgOjb.getResult(streamObj) + "\n";
  69 + byte[] utf8Data = recText.getBytes(StandardCharsets.UTF_8);
  70 + System.out.println(new String(utf8Data));
  71 + rcgOjb.reSet(streamObj);
  72 + rcgOjb.releaseStream(streamObj); // release stream
  73 + rcgOjb.release(); // release recognizer
  74 +
  75 +
  76 +```
  77 +---
  78 +5.Makefile
  79 +---
  80 +package jar and run app example
  81 +package path: /sherpa-onnx/java-api-examples/lib/sherpaonnx.jar
  82 +``` bash
  83 + cd sherpa-onnx/java-api-examples
  84 + make all
  85 +
  86 + ```
  87 +
  88 +
  1 +#model config
  2 +sample_rate=16000
  3 +feature_dim=80
  4 +rule1_min_trailing_silence=2.4
  5 +rule2_min_trailing_silence=1.2
  6 +rule3_min_utterance_length=20
  7 +encoder=/sherpa-onnx/build_old/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/encoder-epoch-99-avg-1.onnx
  8 +decoder=/sherpa-onnx/build_old/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/decoder-epoch-99-avg-1.onnx
  9 +joiner=/sherpa-onnx/build_old/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/joiner-epoch-99-avg-1.onnx
  10 +tokens=/sherpa-onnx/build_old/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/tokens.txt
  11 +num_threads=4
  12 +enable_endpoint_detection=false
  13 +decoding_method=modified_beam_search
  14 +max_active_paths=4
  1 +/*
  2 + * // Copyright 2022-2023 by zhaoming
  3 + */
  4 +/*
  5 +Config modelconfig.cfg
  6 + sample_rate=16000
  7 + feature_dim=80
  8 + rule1_min_trailing_silence=2.4
  9 + rule2_min_trailing_silence=1.2
  10 + rule3_min_utterance_length=20
  11 + encoder=/sherpa-onnx/build/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/encoder-epoch-99-avg-1.onnx
  12 + decoder=/sherpa-onnx/build/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/decoder-epoch-99-avg-1.onnx
  13 + joiner=/sherpa-onnx/build/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/joiner-epoch-99-avg-1.onnx
  14 + tokens=/sherpa-onnx/build/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/tokens.txt
  15 + num_threads=4
  16 + enable_endpoint_detection=false
  17 + decoding_method=greedy_search
  18 + max_active_paths=4
  19 +*/
  20 +
  21 +import com.k2fsa.sherpa.onnx.OnlineRecognizer;
  22 +import com.k2fsa.sherpa.onnx.OnlineStream;
  23 +import java.io.*;
  24 +import java.nio.charset.StandardCharsets;
  25 +
  26 +public class DecodeFile {
  27 + OnlineRecognizer rcgOjb;
  28 + OnlineStream streamObj;
  29 + String wavfilename;
  30 +
  31 + public DecodeFile(String fileName) {
  32 + wavfilename = fileName;
  33 + }
  34 +
  35 + public void initModelWithPara() {
  36 + try {
  37 + String modelDir =
  38 + "/sherpa-onnx/build_old/bin/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20";
  39 + String encoder = modelDir + "/encoder-epoch-99-avg-1.onnx";
  40 + String decoder = modelDir + "/decoder-epoch-99-avg-1.onnx";
  41 + String joiner = modelDir + "/joiner-epoch-99-avg-1.onnx";
  42 + String tokens = modelDir + "/tokens.txt";
  43 + int numThreads = 4;
  44 + int sampleRate = 16000;
  45 + int featureDim = 80;
  46 + boolean enableEndpointDetection = false;
  47 + float rule1MinTrailingSilence = 2.4F;
  48 + float rule2MinTrailingSilence = 1.2F;
  49 + float rule3MinUtteranceLength = 20F;
  50 + String decodingMethod = "greedy_search";
  51 + int maxActivePaths = 4;
  52 +
  53 + rcgOjb =
  54 + new OnlineRecognizer(
  55 + tokens,
  56 + encoder,
  57 + decoder,
  58 + joiner,
  59 + numThreads,
  60 + sampleRate,
  61 + featureDim,
  62 + enableEndpointDetection,
  63 + rule1MinTrailingSilence,
  64 + rule2MinTrailingSilence,
  65 + rule3MinUtteranceLength,
  66 + decodingMethod,
  67 + maxActivePaths);
  68 + streamObj = rcgOjb.createStream();
  69 + } catch (Exception e) {
  70 + System.err.println(e);
  71 + e.printStackTrace();
  72 + }
  73 + }
  74 +
  75 + public void initModelWithCfg(String cfgFile) {
  76 + try {
  77 + // you should set setCfgPath() before running this
  78 + rcgOjb = new OnlineRecognizer(cfgFile);
  79 + streamObj = rcgOjb.createStream();
  80 + } catch (Exception e) {
  81 + System.err.println(e);
  82 + e.printStackTrace();
  83 + }
  84 + }
  85 +
  86 + public void simpleExample() {
  87 + try {
  88 + float[] buffer = rcgOjb.readWavFile(wavfilename); // read data from file
  89 + streamObj.acceptWaveform(buffer); // feed stream with data
  90 + streamObj.inputFinished(); // tell engine you done with all data
  91 + OnlineStream ssObj[] = new OnlineStream[1];
  92 + while (rcgOjb.isReady(streamObj)) { // engine is ready for unprocessed data
  93 + ssObj[0] = streamObj;
  94 + rcgOjb.decodeStreams(ssObj); // decode for multiple stream
  95 + // rcgOjb.DecodeStream(streamObj); // decode for single stream
  96 + }
  97 +
  98 + String recText = "simple:" + rcgOjb.getResult(streamObj) + "\n";
  99 + byte[] utf8Data = recText.getBytes(StandardCharsets.UTF_8);
  100 + System.out.println(new String(utf8Data));
  101 + rcgOjb.reSet(streamObj);
  102 + rcgOjb.releaseStream(streamObj); // release stream
  103 + rcgOjb.release(); // release recognizer
  104 +
  105 + } catch (Exception e) {
  106 + System.err.println(e);
  107 + e.printStackTrace();
  108 + }
  109 + }
  110 +
  111 + public void streamExample() {
  112 + try {
  113 + float[] buffer = rcgOjb.readWavFile(wavfilename); // read data from file
  114 + float[] chunk = new float[1600]; // //each time read 1600(0.1s) data
  115 + int chunkIndex = 0;
  116 + for (int i = 0; i < buffer.length; i++) // total wav length loop
  117 + {
  118 + chunk[chunkIndex] = buffer[i];
  119 + chunkIndex++;
  120 + if (chunkIndex >= 1600 || i == (buffer.length - 1)) {
  121 + chunkIndex = 0;
  122 + streamObj.acceptWaveform(chunk); // feed chunk
  123 + if (rcgOjb.isReady(streamObj)) {
  124 + rcgOjb.decodeStream(streamObj);
  125 + }
  126 + String testDate = rcgOjb.getResult(streamObj);
  127 + byte[] utf8Data = testDate.getBytes(StandardCharsets.UTF_8);
  128 +
  129 + if (utf8Data.length > 0) {
  130 + System.out.println(Float.valueOf((float) i / 16000) + ":" + new String(utf8Data));
  131 + }
  132 + }
  133 + }
  134 + streamObj.inputFinished();
  135 + while (rcgOjb.isReady(streamObj)) {
  136 + rcgOjb.decodeStream(streamObj);
  137 + }
  138 +
  139 + String recText = "stream:" + rcgOjb.getResult(streamObj) + "\n";
  140 + byte[] utf8Data = recText.getBytes(StandardCharsets.UTF_8);
  141 + System.out.println(new String(utf8Data));
  142 + rcgOjb.reSet(streamObj);
  143 + rcgOjb.releaseStream(streamObj); // release stream
  144 + rcgOjb.release(); // release recognizer
  145 +
  146 + } catch (Exception e) {
  147 + System.err.println(e);
  148 + e.printStackTrace();
  149 + }
  150 + }
  151 +
  152 + public static void main(String[] args) {
  153 + try {
  154 + String appDir = System.getProperty("user.dir");
  155 + System.out.println("appdir=" + appDir);
  156 + String fileName = appDir + "/test.wav";
  157 + String cfgPath = appDir + "/modelconfig.cfg";
  158 + String soPath = appDir + "/../build/lib/libsherpa-onnx-jni.so";
  159 + OnlineRecognizer.setSoPath(soPath);
  160 + DecodeFile rcgDemo = new DecodeFile(fileName);
  161 +
  162 + // ***************** */
  163 + rcgDemo.initModelWithCfg(cfgPath);
  164 + rcgDemo.streamExample();
  165 + // **************** */
  166 + rcgDemo.initModelWithCfg(cfgPath);
  167 + rcgDemo.simpleExample();
  168 +
  169 + } catch (Exception e) {
  170 + System.err.println(e);
  171 + e.printStackTrace();
  172 + }
  173 + }
  174 +}
不能预览此文件类型
  1 +/*
  2 + * // Copyright 2022-2023 by zhaoming
  3 + */
  4 +
  5 +package com.k2fsa.sherpa.onnx;
  6 +
  7 +public class EndpointConfig {
  8 + private final EndpointRule rule1;
  9 + private final EndpointRule rule2;
  10 + private final EndpointRule rule3;
  11 +
  12 + public EndpointConfig(EndpointRule rule1, EndpointRule rule2, EndpointRule rule3) {
  13 + this.rule1 = rule1;
  14 + this.rule2 = rule2;
  15 + this.rule3 = rule3;
  16 + }
  17 +
  18 + public EndpointRule getRule1() {
  19 + return rule1;
  20 + }
  21 +
  22 + public EndpointRule getRule2() {
  23 + return rule2;
  24 + }
  25 +
  26 + public EndpointRule getRule3() {
  27 + return rule3;
  28 + }
  29 +}
  1 +/*
  2 + * // Copyright 2022-2023 by zhaoming
  3 + */
  4 +
  5 +package com.k2fsa.sherpa.onnx;
  6 +
  7 +public class EndpointRule {
  8 + private final boolean mustContainNonSilence;
  9 + private final float minTrailingSilence;
  10 + private final float minUtteranceLength;
  11 +
  12 + public EndpointRule(
  13 + boolean mustContainNonSilence, float minTrailingSilence, float minUtteranceLength) {
  14 + this.mustContainNonSilence = mustContainNonSilence;
  15 + this.minTrailingSilence = minTrailingSilence;
  16 + this.minUtteranceLength = minUtteranceLength;
  17 + }
  18 +
  19 + public float getMinTrailingSilence() {
  20 + return minTrailingSilence;
  21 + }
  22 +
  23 + public float getMinUtteranceLength() {
  24 + return minUtteranceLength;
  25 + }
  26 +
  27 + public boolean getMustContainNonSilence() {
  28 + return mustContainNonSilence;
  29 + }
  30 +}
  1 +/*
  2 + * // Copyright 2022-2023 by zhaoming
  3 + */
  4 +
  5 +package com.k2fsa.sherpa.onnx;
  6 +
  7 +public class FeatureConfig {
  8 + private final int sampleRate;
  9 + private final int featureDim;
  10 +
  11 + public FeatureConfig(int sampleRate, int featureDim) {
  12 + this.sampleRate = sampleRate;
  13 + this.featureDim = featureDim;
  14 + }
  15 +
  16 + public int getSampleRate() {
  17 + return sampleRate;
  18 + }
  19 +
  20 + public int getFeatureDim() {
  21 + return featureDim;
  22 + }
  23 +}
  1 +/*
  2 + * // Copyright 2022-2023 by zhaoming
  3 + * // the online recognizer for sherpa-onnx, it can load config from a file
  4 + * // or by argument
  5 + */
  6 +/*
  7 +usage example:
  8 +
  9 + String cfgpath=appdir+"/modelconfig.cfg";
  10 + OnlineRecognizer.setSoPath(soPath); //set so lib path
  11 +
  12 + OnlineRecognizer rcgOjb = new OnlineRecognizer(); //create a recognizer
  13 + rcgOjb = new OnlineRecognizer(cfgFile); //set model config file
  14 + CreateStream streamObj=rcgOjb.CreateStream(); //create a stream for read wav data
  15 + float[] buffer = rcgOjb.readWavFile(wavfilename); // read data from file
  16 + streamObj.acceptWaveform(buffer); // feed stream with data
  17 + streamObj.inputFinished(); // tell engine you done with all data
  18 + OnlineStream ssObj[] = new OnlineStream[1];
  19 + while (rcgOjb.isReady(streamObj)) { // engine is ready for unprocessed data
  20 + ssObj[0] = streamObj;
  21 + rcgOjb.decodeStreams(ssObj); // decode for multiple stream
  22 + // rcgOjb.DecodeStream(streamObj); // decode for single stream
  23 + }
  24 +
  25 + String recText = "simple:" + rcgOjb.getResult(streamObj) + "\n";
  26 + byte[] utf8Data = recText.getBytes(StandardCharsets.UTF_8);
  27 + System.out.println(new String(utf8Data));
  28 + rcgOjb.reSet(streamObj);
  29 + rcgOjb.releaseStream(streamObj); // release stream
  30 + rcgOjb.release(); // release recognizer
  31 +
  32 +*/
  33 +package com.k2fsa.sherpa.onnx;
  34 +
  35 +import java.io.*;
  36 +import java.util.*;
  37 +
  38 +public class OnlineRecognizer {
  39 + private long ptr = 0; // this is the asr engine ptrss
  40 +
  41 + private int sampleRate = 16000;
  42 + // load config file for OnlineRecognizer
  43 + public OnlineRecognizer(String modelCfgPath) {
  44 + Map<String, String> proMap = this.readProperties(modelCfgPath);
  45 + try {
  46 + int sampleRate = Integer.parseInt(proMap.get("sample_rate").trim());
  47 + this.sampleRate = sampleRate;
  48 + EndpointRule rule1 =
  49 + new EndpointRule(
  50 + false, Float.parseFloat(proMap.get("rule1_min_trailing_silence").trim()), 0.0F);
  51 + EndpointRule rule2 =
  52 + new EndpointRule(
  53 + true, Float.parseFloat(proMap.get("rule2_min_trailing_silence").trim()), 0.0F);
  54 + EndpointRule rule3 =
  55 + new EndpointRule(
  56 + false, 0.0F, Float.parseFloat(proMap.get("rule3_min_utterance_length").trim()));
  57 + EndpointConfig endCfg = new EndpointConfig(rule1, rule2, rule3);
  58 + OnlineTransducerModelConfig modelCfg =
  59 + new OnlineTransducerModelConfig(
  60 + proMap.get("encoder").trim(),
  61 + proMap.get("decoder").trim(),
  62 + proMap.get("joiner").trim(),
  63 + proMap.get("tokens").trim(),
  64 + Integer.parseInt(proMap.get("num_threads").trim()),
  65 + false);
  66 + FeatureConfig featConfig =
  67 + new FeatureConfig(sampleRate, Integer.parseInt(proMap.get("feature_dim").trim()));
  68 + OnlineRecognizerConfig rcgCfg =
  69 + new OnlineRecognizerConfig(
  70 + featConfig,
  71 + modelCfg,
  72 + endCfg,
  73 + Boolean.parseBoolean(proMap.get("enable_endpoint_detection").trim()),
  74 + proMap.get("decoding_method").trim(),
  75 + Integer.parseInt(proMap.get("max_active_paths").trim()));
  76 + // create a new Recognizer, first parameter kept for android asset_manager ANDROID_API__ >= 9
  77 + this.ptr = createOnlineRecognizer(new Object(), rcgCfg);
  78 +
  79 + } catch (Exception e) {
  80 + System.err.println(e);
  81 + }
  82 + }
  83 +
  84 + // use for android asset_manager ANDROID_API__ >= 9
  85 + public OnlineRecognizer(Object assetManager, String modelCfgPath) {
  86 + Map<String, String> proMap = this.readProperties(modelCfgPath);
  87 + try {
  88 + int sampleRate = Integer.parseInt(proMap.get("sample_rate").trim());
  89 + this.sampleRate = sampleRate;
  90 + EndpointRule rule1 =
  91 + new EndpointRule(
  92 + false, Float.parseFloat(proMap.get("rule1_min_trailing_silence").trim()), 0.0F);
  93 + EndpointRule rule2 =
  94 + new EndpointRule(
  95 + true, Float.parseFloat(proMap.get("rule2_min_trailing_silence").trim()), 0.0F);
  96 + EndpointRule rule3 =
  97 + new EndpointRule(
  98 + false, 0.0F, Float.parseFloat(proMap.get("rule3_min_utterance_length").trim()));
  99 + EndpointConfig endCfg = new EndpointConfig(rule1, rule2, rule3);
  100 + OnlineTransducerModelConfig modelCfg =
  101 + new OnlineTransducerModelConfig(
  102 + proMap.get("encoder").trim(),
  103 + proMap.get("decoder").trim(),
  104 + proMap.get("joiner").trim(),
  105 + proMap.get("tokens").trim(),
  106 + Integer.parseInt(proMap.get("num_threads").trim()),
  107 + false);
  108 + FeatureConfig featConfig =
  109 + new FeatureConfig(sampleRate, Integer.parseInt(proMap.get("feature_dim").trim()));
  110 + OnlineRecognizerConfig rcgCfg =
  111 + new OnlineRecognizerConfig(
  112 + featConfig,
  113 + modelCfg,
  114 + endCfg,
  115 + Boolean.parseBoolean(proMap.get("enable_endpoint_detection").trim()),
  116 + proMap.get("decoding_method").trim(),
  117 + Integer.parseInt(proMap.get("max_active_paths").trim()));
  118 + // create a new Recognizer, first parameter kept for android asset_manager ANDROID_API__ >= 9
  119 + this.ptr = createOnlineRecognizer(assetManager, rcgCfg);
  120 +
  121 + } catch (Exception e) {
  122 + System.err.println(e);
  123 + }
  124 + }
  125 +
  126 + // set onlineRecognizer by parameter
  127 + public OnlineRecognizer(
  128 + String tokens,
  129 + String encoder,
  130 + String decoder,
  131 + String joiner,
  132 + int numThreads,
  133 + int sampleRate,
  134 + int featureDim,
  135 + boolean enableEndpointDetection,
  136 + float rule1MinTrailingSilence,
  137 + float rule2MinTrailingSilence,
  138 + float rule3MinUtteranceLength,
  139 + String decodingMethod,
  140 + int maxActivePaths) {
  141 + this.sampleRate = sampleRate;
  142 + EndpointRule rule1 = new EndpointRule(false, rule1MinTrailingSilence, 0.0F);
  143 + EndpointRule rule2 = new EndpointRule(true, rule2MinTrailingSilence, 0.0F);
  144 + EndpointRule rule3 = new EndpointRule(false, 0.0F, rule3MinUtteranceLength);
  145 + EndpointConfig endCfg = new EndpointConfig(rule1, rule2, rule3);
  146 + OnlineTransducerModelConfig modelCfg =
  147 + new OnlineTransducerModelConfig(encoder, decoder, joiner, tokens, numThreads, false);
  148 + FeatureConfig featConfig = new FeatureConfig(sampleRate, featureDim);
  149 + OnlineRecognizerConfig rcgCfg =
  150 + new OnlineRecognizerConfig(
  151 + featConfig,
  152 + modelCfg,
  153 + endCfg,
  154 + enableEndpointDetection,
  155 + decodingMethod,
  156 + maxActivePaths);
  157 + // create a new Recognizer, first parameter kept for android asset_manager ANDROID_API__ >= 9
  158 + this.ptr = createOnlineRecognizer(new Object(), rcgCfg);
  159 + }
  160 +
  161 + private Map<String, String> readProperties(String modelCfgPath) {
  162 + // read and parse config file
  163 + Properties props = new Properties();
  164 + Map<String, String> proMap = new HashMap<>();
  165 + try {
  166 + File file = new File(modelCfgPath);
  167 + if (!file.exists()) {
  168 + System.out.println("model cfg file not exists!");
  169 + System.exit(0);
  170 + }
  171 + InputStream in = new BufferedInputStream(new FileInputStream(modelCfgPath));
  172 + props.load(in);
  173 + Enumeration en = props.propertyNames();
  174 + while (en.hasMoreElements()) {
  175 + String key = (String) en.nextElement();
  176 + String Property = props.getProperty(key);
  177 + proMap.put(key, Property);
  178 + // System.out.println(key+"="+Property);
  179 + }
  180 +
  181 + } catch (Exception e) {
  182 + e.printStackTrace();
  183 + }
  184 + return proMap;
  185 + }
  186 +
  187 + public void decodeStream(OnlineStream s) throws Exception {
  188 + if (this.ptr == 0) throw new Exception("null exception for recognizer ptr");
  189 + long streamPtr = s.getPtr();
  190 + if (streamPtr == 0) throw new Exception("null exception for stream ptr");
  191 + // when feeded samples to engine, call DecodeStream to let it process
  192 + decodeStream(this.ptr, streamPtr);
  193 + }
  194 +
  195 + public void decodeStreams(OnlineStream[] ssOjb) throws Exception {
  196 + if (this.ptr == 0) throw new Exception("null exception for recognizer ptr");
  197 + // decode for multiple streams
  198 + long[] ss = new long[ssOjb.length];
  199 + for (int i = 0; i < ssOjb.length; i++) {
  200 + ss[i] = ssOjb[i].getPtr();
  201 + if (ss[i] == 0) throw new Exception("null exception for stream ptr");
  202 + }
  203 + decodeStreams(this.ptr, ss);
  204 + }
  205 +
  206 + public boolean isReady(OnlineStream s) throws Exception {
  207 + // whether the engine is ready for decode
  208 + if (this.ptr == 0) throw new Exception("null exception for recognizer ptr");
  209 + long streamPtr = s.getPtr();
  210 + if (streamPtr == 0) throw new Exception("null exception for stream ptr");
  211 + return isReady(this.ptr, streamPtr);
  212 + }
  213 +
  214 + public String getResult(OnlineStream s) throws Exception {
  215 + // get text from the engine
  216 + if (this.ptr == 0) throw new Exception("null exception for recognizer ptr");
  217 + long streamPtr = s.getPtr();
  218 + if (streamPtr == 0) throw new Exception("null exception for stream ptr");
  219 + return getResult(this.ptr, streamPtr);
  220 + }
  221 +
  222 + public boolean isEndpoint(OnlineStream s) throws Exception {
  223 + if (this.ptr == 0) throw new Exception("null exception for recognizer ptr");
  224 + long streamPtr = s.getPtr();
  225 + if (streamPtr == 0) throw new Exception("null exception for stream ptr");
  226 + return isEndpoint(this.ptr, streamPtr);
  227 + }
  228 +
  229 + public void reSet(OnlineStream s) throws Exception {
  230 + if (this.ptr == 0) throw new Exception("null exception for recognizer ptr");
  231 + long streamPtr = s.getPtr();
  232 + if (streamPtr == 0) throw new Exception("null exception for stream ptr");
  233 + reSet(this.ptr, streamPtr);
  234 + }
  235 +
  236 + public OnlineStream createStream() throws Exception {
  237 + // create one stream for data to feed in
  238 + if (this.ptr == 0) throw new Exception("null exception for recognizer ptr");
  239 + long streamPtr = createStream(this.ptr);
  240 + OnlineStream stream = new OnlineStream(streamPtr, this.sampleRate);
  241 + return stream;
  242 + }
  243 +
  244 + public float[] readWavFile(String fileName) {
  245 + // read data from the filename
  246 + Object[] wavdata = readWave(fileName);
  247 + Object data = wavdata[0]; // data[0] is float data, data[1] sample rate
  248 +
  249 + float[] floatData = (float[]) data;
  250 +
  251 + return floatData;
  252 + }
  253 +
  254 + // load the libsherpa-onnx-jni.so lib
  255 + public static void loadSoLib(String soPath) {
  256 + // load libsherpa-onnx-jni.so lib from the path
  257 +
  258 + System.out.println("so lib path=" + soPath + "\n");
  259 + System.load(soPath.trim());
  260 + }
  261 +
  262 + public static void setSoPath(String soPath) {
  263 + OnlineRecognizer.loadSoLib(soPath);
  264 + OnlineStream.loadSoLib(soPath);
  265 + }
  266 +
  267 + protected void finalize() throws Throwable {
  268 + release();
  269 + }
  270 +
  271 + // recognizer release, you'd better call it manually if not use anymore
  272 + public void release() {
  273 + if (this.ptr == 0) return;
  274 + deleteOnlineRecognizer(this.ptr);
  275 + this.ptr = 0;
  276 + }
  277 +
  278 + // stream release, you'd better call it manually if not use anymore
  279 + public void releaseStream(OnlineStream s) {
  280 + s.release();
  281 + }
  282 + // JNI interface libsherpa-onnx-jni.so
  283 +
  284 + private native Object[] readWave(String fileName);
  285 +
  286 + private native String getResult(long ptr, long streamPtr);
  287 +
  288 + private native void decodeStream(long ptr, long streamPtr);
  289 +
  290 + private native void decodeStreams(long ptr, long[] ssPtr);
  291 +
  292 + private native boolean isReady(long ptr, long streamPtr);
  293 +
  294 + // first parameter keep for android asset_manager ANDROID_API__ >= 9
  295 + private native long createOnlineRecognizer(Object asset, OnlineRecognizerConfig config);
  296 +
  297 + private native long createStream(long ptr);
  298 +
  299 + private native void deleteOnlineRecognizer(long ptr);
  300 +
  301 + private native boolean isEndpoint(long ptr, long streamPtr);
  302 +
  303 + private native void reSet(long ptr, long streamPtr);
  304 +}
  1 +/*
  2 + * // Copyright 2022-2023 by zhaoming
  3 + */
  4 +
  5 +package com.k2fsa.sherpa.onnx;
  6 +
  7 +public class OnlineRecognizerConfig {
  8 + private final FeatureConfig featConfig;
  9 + private final OnlineTransducerModelConfig modelConfig;
  10 + private final EndpointConfig endpointConfig;
  11 + private final boolean enableEndpoint;
  12 + private final String decodingMethod;
  13 + private final int maxActivePaths;
  14 +
  15 + public OnlineRecognizerConfig(
  16 + FeatureConfig featConfig,
  17 + OnlineTransducerModelConfig modelConfig,
  18 + EndpointConfig endpointConfig,
  19 + boolean enableEndpoint,
  20 + String decodingMethod,
  21 + int maxActivePaths) {
  22 + this.featConfig = featConfig;
  23 + this.modelConfig = modelConfig;
  24 + this.endpointConfig = endpointConfig;
  25 + this.enableEndpoint = enableEndpoint;
  26 + this.decodingMethod = decodingMethod;
  27 + this.maxActivePaths = maxActivePaths;
  28 + }
  29 +
  30 + public FeatureConfig getFeatConfig() {
  31 + return featConfig;
  32 + }
  33 +
  34 + public OnlineTransducerModelConfig getModelConfig() {
  35 + return modelConfig;
  36 + }
  37 +
  38 + public EndpointConfig getEndpointConfig() {
  39 + return endpointConfig;
  40 + }
  41 +
  42 + public boolean isEnableEndpoint() {
  43 + return enableEndpoint;
  44 + }
  45 +
  46 + public String getDecodingMethod() {
  47 + return decodingMethod;
  48 + }
  49 +
  50 + public int getMaxActivePaths() {
  51 + return maxActivePaths;
  52 + }
  53 +}
  1 +/*
  2 + * // Copyright 2022-2023 by zhaoming
  3 + */
  4 +// Stream is used for feeding data to the asr engine
  5 +package com.k2fsa.sherpa.onnx;
  6 +
  7 +import java.io.*;
  8 +import java.util.*;
  9 +
  10 +public class OnlineStream {
  11 + private long ptr = 0; // this is the stream ptr
  12 +
  13 + private int sampleRate = 16000;
  14 + // assign ptr to this stream in construction
  15 + public OnlineStream(long ptr, int sampleRate) {
  16 + this.ptr = ptr;
  17 + this.sampleRate = sampleRate;
  18 + }
  19 +
  20 + public long getPtr() {
  21 + return ptr;
  22 + }
  23 +
  24 + public void acceptWaveform(float[] samples) throws Exception {
  25 + if (this.ptr == 0) throw new Exception("null exception for stream ptr");
  26 +
  27 + // feed wave data to asr engine
  28 + acceptWaveform(this.ptr, this.sampleRate, samples);
  29 + }
  30 +
  31 + public void inputFinished() {
  32 + // add some tail padding
  33 + int padLen = (int) (this.sampleRate * 0.3); // 0.3 seconds at 16 kHz sample rate
  34 + float tailPaddings[] = new float[padLen]; // default value is 0
  35 + acceptWaveform(this.ptr, this.sampleRate, tailPaddings);
  36 +
  37 + // tell the engine all data are feeded
  38 + inputFinished(this.ptr);
  39 + }
  40 +
  41 + public static void loadSoLib(String soPath) {
  42 + // load .so lib from the path
  43 + System.load(soPath.trim()); // ("sherpa-onnx-jni-java");
  44 + }
  45 +
  46 + public void release() {
  47 + // stream object must be release after used
  48 + if (this.ptr == 0) return;
  49 + deleteStream(this.ptr);
  50 + this.ptr = 0;
  51 + }
  52 +
  53 + protected void finalize() throws Throwable {
  54 + release();
  55 + }
  56 +
  57 + public boolean isLastFrame() throws Exception {
  58 + if (this.ptr == 0) throw new Exception("null exception for stream ptr");
  59 + return isLastFrame(this.ptr);
  60 + }
  61 +
  62 + public void reSet() throws Exception {
  63 + if (this.ptr == 0) throw new Exception("null exception for stream ptr");
  64 + reSet(this.ptr);
  65 + }
  66 +
  67 + public int featureDim() throws Exception {
  68 + if (this.ptr == 0) throw new Exception("null exception for stream ptr");
  69 + return featureDim(this.ptr);
  70 + }
  71 +
  72 + // JNI interface libsherpa-onnx-jni.so
  73 + private native void acceptWaveform(long ptr, int sampleRate, float[] samples);
  74 +
  75 + private native void inputFinished(long ptr);
  76 +
  77 + private native void deleteStream(long ptr);
  78 +
  79 + private native int numFramesReady(long ptr);
  80 +
  81 + private native boolean isLastFrame(long ptr);
  82 +
  83 + private native void reSet(long ptr);
  84 +
  85 + private native int featureDim(long ptr);
  86 +}
  1 +/*
  2 + * // Copyright 2022-2023 by zhaoming
  3 + */
  4 +
  5 +package com.k2fsa.sherpa.onnx;
  6 +
  7 +public class OnlineTransducerModelConfig {
  8 + private final String encoder;
  9 + private final String decoder;
  10 + private final String joiner;
  11 + private final String tokens;
  12 + private final int numThreads;
  13 + private final boolean debug;
  14 +
  15 + public OnlineTransducerModelConfig(
  16 + String encoder, String decoder, String joiner, String tokens, int numThreads, boolean debug) {
  17 + this.encoder = encoder;
  18 + this.decoder = decoder;
  19 + this.joiner = joiner;
  20 + this.tokens = tokens;
  21 + this.numThreads = numThreads;
  22 + this.debug = debug;
  23 + }
  24 +
  25 + public String getEncoder() {
  26 + return encoder;
  27 + }
  28 +
  29 + public String getDecoder() {
  30 + return decoder;
  31 + }
  32 +
  33 + public String getJoiner() {
  34 + return joiner;
  35 + }
  36 +
  37 + public String getTokens() {
  38 + return tokens;
  39 + }
  40 +
  41 + public int getNumThreads() {
  42 + return numThreads;
  43 + }
  44 +
  45 + public boolean getDebug() {
  46 + return debug;
  47 + }
  48 +}
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 // 2 //
3 // Copyright (c) 2022-2023 Xiaomi Corporation 3 // Copyright (c) 2022-2023 Xiaomi Corporation
4 // 2022 Pingfeng Luo 4 // 2022 Pingfeng Luo
  5 +// 2023 Zhaoming
5 6
6 // TODO(fangjun): Add documentation to functions/methods in this file 7 // TODO(fangjun): Add documentation to functions/methods in this file
7 // and also show how to use them with kotlin, possibly with java. 8 // and also show how to use them with kotlin, possibly with java.
@@ -12,7 +13,6 @@ @@ -12,7 +13,6 @@
12 13
13 #include <strstream> 14 #include <strstream>
14 #include <utility> 15 #include <utility>
15 -  
16 #if __ANDROID_API__ >= 9 16 #if __ANDROID_API__ >= 9
17 #include "android/asset_manager.h" 17 #include "android/asset_manager.h"
18 #include "android/asset_manager_jni.h" 18 #include "android/asset_manager_jni.h"
@@ -207,7 +207,6 @@ JNIEXPORT jlong JNICALL Java_com_k2fsa_sherpa_onnx_SherpaOnnx_new( @@ -207,7 +207,6 @@ JNIEXPORT jlong JNICALL Java_com_k2fsa_sherpa_onnx_SherpaOnnx_new(
207 SHERPA_ONNX_LOGE("Failed to get asset manager: %p", mgr); 207 SHERPA_ONNX_LOGE("Failed to get asset manager: %p", mgr);
208 } 208 }
209 #endif 209 #endif
210 -  
211 auto config = sherpa_onnx::GetConfig(env, _config); 210 auto config = sherpa_onnx::GetConfig(env, _config);
212 SHERPA_ONNX_LOGE("config:\n%s", config.ToString().c_str()); 211 SHERPA_ONNX_LOGE("config:\n%s", config.ToString().c_str());
213 auto model = new sherpa_onnx::SherpaOnnx( 212 auto model = new sherpa_onnx::SherpaOnnx(
@@ -301,7 +300,7 @@ Java_com_k2fsa_sherpa_onnx_WaveReader_00024Companion_readWave( @@ -301,7 +300,7 @@ Java_com_k2fsa_sherpa_onnx_WaveReader_00024Companion_readWave(
301 SHERPA_ONNX_LOGE("Failed to get asset manager: %p", mgr); 300 SHERPA_ONNX_LOGE("Failed to get asset manager: %p", mgr);
302 exit(-1); 301 exit(-1);
303 } 302 }
304 - 303 + SHERPA_ONNX_LOGE("Failed to read %s", p_filename);
305 std::vector<char> buffer = sherpa_onnx::ReadFile(mgr, p_filename); 304 std::vector<char> buffer = sherpa_onnx::ReadFile(mgr, p_filename);
306 305
307 std::istrstream is(buffer.data(), buffer.size()); 306 std::istrstream is(buffer.data(), buffer.size());
@@ -332,3 +331,186 @@ Java_com_k2fsa_sherpa_onnx_WaveReader_00024Companion_readWave( @@ -332,3 +331,186 @@ Java_com_k2fsa_sherpa_onnx_WaveReader_00024Companion_readWave(
332 331
333 return obj_arr; 332 return obj_arr;
334 } 333 }
  334 +
  335 +// ******warpper for OnlineRecognizer*******
  336 +
  337 +// wav reader for java interface
  338 +SHERPA_ONNX_EXTERN_C
  339 +JNIEXPORT jobjectArray JNICALL
  340 +Java_com_k2fsa_sherpa_onnx_OnlineRecognizer_readWave(JNIEnv *env,
  341 + jclass /*cls*/,
  342 + jstring filename) {
  343 + auto data = Java_com_k2fsa_sherpa_onnx_WaveReader_00024Companion_readWave(
  344 + env, nullptr, nullptr, filename);
  345 + return data;
  346 +}
  347 +
  348 +SHERPA_ONNX_EXTERN_C
  349 +JNIEXPORT jlong JNICALL
  350 +
  351 +Java_com_k2fsa_sherpa_onnx_OnlineRecognizer_createOnlineRecognizer(
  352 +
  353 + JNIEnv *env, jobject /*obj*/, jobject asset_manager, jobject _config) {
  354 +#if __ANDROID_API__ >= 9
  355 + AAssetManager *mgr = AAssetManager_fromJava(env, asset_manager);
  356 + if (!mgr) {
  357 + SHERPA_ONNX_LOGE("Failed to get asset manager: %p", mgr);
  358 + }
  359 +#endif
  360 + sherpa_onnx::OnlineRecognizerConfig config =
  361 + sherpa_onnx::GetConfig(env, _config);
  362 + SHERPA_ONNX_LOGE("config:\n%s", config.ToString().c_str());
  363 + auto p_recognizer = new sherpa_onnx::OnlineRecognizer(
  364 +#if __ANDROID_API__ >= 9
  365 + mgr,
  366 +#endif
  367 + config);
  368 + return (jlong)p_recognizer;
  369 +}
  370 +
  371 +SHERPA_ONNX_EXTERN_C
  372 +JNIEXPORT void JNICALL
  373 +Java_com_k2fsa_sherpa_onnx_OnlineRecognizer_deleteOnlineRecognizer(
  374 + JNIEnv *env, jobject /*obj*/, jlong ptr) {
  375 + delete reinterpret_cast<sherpa_onnx::OnlineRecognizer *>(ptr);
  376 +}
  377 +
  378 +SHERPA_ONNX_EXTERN_C
  379 +JNIEXPORT jlong JNICALL
  380 +Java_com_k2fsa_sherpa_onnx_OnlineRecognizer_createStream(JNIEnv *env,
  381 + jobject /*obj*/,
  382 + jlong ptr) {
  383 + std::unique_ptr<sherpa_onnx::OnlineStream> s =
  384 + reinterpret_cast<sherpa_onnx::OnlineRecognizer *>(ptr)->CreateStream();
  385 + sherpa_onnx::OnlineStream *p_stream = s.release();
  386 + return reinterpret_cast<jlong>(p_stream);
  387 +}
  388 +
  389 +SHERPA_ONNX_EXTERN_C
  390 +JNIEXPORT bool JNICALL Java_com_k2fsa_sherpa_onnx_OnlineRecognizer_isReady(
  391 + JNIEnv *env, jobject /*obj*/, jlong ptr, jlong s_ptr) {
  392 + sherpa_onnx::OnlineRecognizer *model =
  393 + reinterpret_cast<sherpa_onnx::OnlineRecognizer *>(ptr);
  394 + sherpa_onnx::OnlineStream *s =
  395 + reinterpret_cast<sherpa_onnx::OnlineStream *>(s_ptr);
  396 + return model->IsReady(s);
  397 +}
  398 +
  399 +SHERPA_ONNX_EXTERN_C
  400 +JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_OnlineRecognizer_decodeStream(
  401 + JNIEnv *env, jobject /*obj*/, jlong ptr, jlong s_ptr) {
  402 + sherpa_onnx::OnlineRecognizer *model =
  403 + reinterpret_cast<sherpa_onnx::OnlineRecognizer *>(ptr);
  404 + sherpa_onnx::OnlineStream *s =
  405 + reinterpret_cast<sherpa_onnx::OnlineStream *>(s_ptr);
  406 + model->DecodeStream(s);
  407 +}
  408 +
  409 +SHERPA_ONNX_EXTERN_C
  410 +JNIEXPORT void JNICALL
  411 +Java_com_k2fsa_sherpa_onnx_OnlineRecognizer_decodeStreams(JNIEnv *env,
  412 + jobject /*obj*/,
  413 + jlong ptr,
  414 + jlongArray ss_ptr,
  415 + jint stream_size) {
  416 + sherpa_onnx::OnlineRecognizer *model =
  417 + reinterpret_cast<sherpa_onnx::OnlineRecognizer *>(ptr);
  418 + jlong *p = env->GetLongArrayElements(ss_ptr, nullptr);
  419 + jsize n = env->GetArrayLength(ss_ptr);
  420 + std::vector<sherpa_onnx::OnlineStream *> p_ss(n);
  421 + for (int32_t i = 0; i != n; ++i) {
  422 + p_ss[i] = reinterpret_cast<sherpa_onnx::OnlineStream *>(p[i]);
  423 + }
  424 +
  425 + model->DecodeStreams(p_ss.data(), n);
  426 + env->ReleaseLongArrayElements(ss_ptr, p, JNI_ABORT);
  427 +}
  428 +
  429 +SHERPA_ONNX_EXTERN_C
  430 +JNIEXPORT jstring JNICALL Java_com_k2fsa_sherpa_onnx_OnlineRecognizer_getResult(
  431 + JNIEnv *env, jobject /*obj*/, jlong ptr, jlong s_ptr) {
  432 + sherpa_onnx::OnlineRecognizer *model =
  433 + reinterpret_cast<sherpa_onnx::OnlineRecognizer *>(ptr);
  434 + sherpa_onnx::OnlineStream *s =
  435 + reinterpret_cast<sherpa_onnx::OnlineStream *>(s_ptr);
  436 + sherpa_onnx::OnlineRecognizerResult result = model->GetResult(s);
  437 + return env->NewStringUTF(result.ToString().c_str());
  438 +}
  439 +
  440 +SHERPA_ONNX_EXTERN_C
  441 +JNIEXPORT bool JNICALL Java_com_k2fsa_sherpa_onnx_OnlineRecognizer_isEndpoint(
  442 + JNIEnv *env, jobject /*obj*/, jlong ptr, jlong s_ptr) {
  443 + sherpa_onnx::OnlineRecognizer *model =
  444 + reinterpret_cast<sherpa_onnx::OnlineRecognizer *>(ptr);
  445 + sherpa_onnx::OnlineStream *s =
  446 + reinterpret_cast<sherpa_onnx::OnlineStream *>(s_ptr);
  447 + return model->IsEndpoint(s);
  448 +}
  449 +
  450 +SHERPA_ONNX_EXTERN_C
  451 +JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_OnlineRecognizer_reSet(
  452 + JNIEnv *env, jobject /*obj*/, jlong ptr, jlong s_ptr) {
  453 + sherpa_onnx::OnlineRecognizer *model =
  454 + reinterpret_cast<sherpa_onnx::OnlineRecognizer *>(ptr);
  455 + sherpa_onnx::OnlineStream *s =
  456 + reinterpret_cast<sherpa_onnx::OnlineStream *>(s_ptr);
  457 + model->Reset(s);
  458 +}
  459 +
  460 +// *********for OnlineStream *********
  461 +SHERPA_ONNX_EXTERN_C
  462 +JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_OnlineStream_acceptWaveform(
  463 + JNIEnv *env, jobject /*obj*/, jlong s_ptr, jint sample_rate,
  464 + jfloatArray waveform) {
  465 + sherpa_onnx::OnlineStream *s =
  466 + reinterpret_cast<sherpa_onnx::OnlineStream *>(s_ptr);
  467 + jfloat *p = env->GetFloatArrayElements(waveform, nullptr);
  468 + jsize n = env->GetArrayLength(waveform);
  469 + s->AcceptWaveform(sample_rate, p, n);
  470 + env->ReleaseFloatArrayElements(waveform, p, JNI_ABORT);
  471 +}
  472 +
  473 +SHERPA_ONNX_EXTERN_C
  474 +JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_OnlineStream_inputFinished(
  475 + JNIEnv *env, jobject /*obj*/, jlong s_ptr) {
  476 + sherpa_onnx::OnlineStream *s =
  477 + reinterpret_cast<sherpa_onnx::OnlineStream *>(s_ptr);
  478 + s->InputFinished();
  479 +}
  480 +
  481 +SHERPA_ONNX_EXTERN_C
  482 +JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_OnlineStream_deleteStream(
  483 + JNIEnv *env, jobject /*obj*/, jlong s_ptr) {
  484 + delete reinterpret_cast<sherpa_onnx::OnlineStream *>(s_ptr);
  485 +}
  486 +
  487 +SHERPA_ONNX_EXTERN_C
  488 +JNIEXPORT jint JNICALL Java_com_k2fsa_sherpa_onnx_OnlineStream_numFramesReady(
  489 + JNIEnv *env, jobject /*obj*/, jlong s_ptr) {
  490 + sherpa_onnx::OnlineStream *s =
  491 + reinterpret_cast<sherpa_onnx::OnlineStream *>(s_ptr);
  492 + return s->NumFramesReady();
  493 +}
  494 +
  495 +SHERPA_ONNX_EXTERN_C
  496 +JNIEXPORT bool JNICALL Java_com_k2fsa_sherpa_onnx_OnlineStream_isLastFrame(
  497 + JNIEnv *env, jobject /*obj*/, jlong s_ptr, jint frame) {
  498 + sherpa_onnx::OnlineStream *s =
  499 + reinterpret_cast<sherpa_onnx::OnlineStream *>(s_ptr);
  500 + return s->IsLastFrame(frame);
  501 +}
  502 +SHERPA_ONNX_EXTERN_C
  503 +JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_OnlineStream_reSet(
  504 + JNIEnv *env, jobject /*obj*/, jlong s_ptr) {
  505 + sherpa_onnx::OnlineStream *s =
  506 + reinterpret_cast<sherpa_onnx::OnlineStream *>(s_ptr);
  507 + s->Reset();
  508 +}
  509 +
  510 +SHERPA_ONNX_EXTERN_C
  511 +JNIEXPORT jint JNICALL Java_com_k2fsa_sherpa_onnx_OnlineStream_featureDim(
  512 + JNIEnv *env, jobject /*obj*/, jlong s_ptr) {
  513 + sherpa_onnx::OnlineStream *s =
  514 + reinterpret_cast<sherpa_onnx::OnlineStream *>(s_ptr);
  515 + return s->FeatureDim();
  516 +}