Skip to content

Commit 2aafc63

Browse files
authored
Add OfflineDiacritization JAVA bindings (k2-fsa#3669)
1 parent 0d1f98e commit 2aafc63

10 files changed

Lines changed: 355 additions & 0 deletions

File tree

.github/workflows/run-java-test.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,14 @@ jobs:
252252
# Delete model files to save space
253253
rm -rf sherpa-onnx-punct-*
254254
255+
- name: Run java test (Offline add diacritics)
256+
shell: bash
257+
run: |
258+
cd ./java-api-examples
259+
./run-offline-add-diacritics.sh
260+
# Delete model files to save space
261+
rm -rf catt_eo_model_onnx
262+
255263
- name: Run java test (speaker diarization)
256264
shell: bash
257265
run: |
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2026 Matias Lin
2+
3+
// This file shows how to use a CATT diacritization model to add diacritics to Arabic text.
4+
import com.k2fsa.sherpa.onnx.*;
5+
6+
public class OfflineAddDiacritics {
7+
public static void main(String[] args) {
8+
// please download the model from
9+
// https://github.com/abjadai/catt/releases/download/v2/eo_model_onnx.zip
10+
String cattEncoder = "./catt_eo_model_onnx/encoder.onnx";
11+
String cattDecoder = "./catt_eo_model_onnx/decoder.onnx";
12+
OfflineDiacritizationModelConfig modelConfig =
13+
OfflineDiacritizationModelConfig.builder()
14+
.setCattEncoder(cattEncoder)
15+
.setCattDecoder(cattDecoder)
16+
.setNumThreads(1)
17+
.setDebug(true)
18+
.build();
19+
OfflineDiacritizationConfig config =
20+
OfflineDiacritizationConfig.builder().setModel(modelConfig).build();
21+
22+
OfflineDiacritization diacrt = new OfflineDiacritization(config);
23+
24+
String[] sentences =
25+
new String[] {
26+
"وقالت مجلة نيوزويك الأمريكية التحديث الجديد ل إنستجرام يمكن أن يساهم في إيقاف وكشف الحسابات المزورة بسهولة شديدة",
27+
"اللغة العربية من أقدم اللغات السامية",
28+
};
29+
30+
System.out.println("---");
31+
for (String text : sentences) {
32+
String out = diacrt.addDiacritics(text);
33+
System.out.printf("Input: %s\n", text);
34+
System.out.printf("Output: %s\n", out);
35+
System.out.println("---");
36+
}
37+
}
38+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env bash
2+
3+
set -ex
4+
5+
if [[ ! -f ../build/lib/libsherpa-onnx-jni.dylib && ! -f ../build/lib/libsherpa-onnx-jni.so ]]; then
6+
mkdir -p ../build
7+
pushd ../build
8+
cmake \
9+
-DSHERPA_ONNX_ENABLE_PYTHON=OFF \
10+
-DSHERPA_ONNX_ENABLE_TESTS=OFF \
11+
-DSHERPA_ONNX_ENABLE_CHECK=OFF \
12+
-DBUILD_SHARED_LIBS=ON \
13+
-DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \
14+
-DSHERPA_ONNX_ENABLE_JNI=ON \
15+
..
16+
17+
make -j4
18+
ls -lh lib
19+
popd
20+
fi
21+
22+
if [ ! -f ../sherpa-onnx/java-api/build/sherpa-onnx.jar ]; then
23+
pushd ../sherpa-onnx/java-api
24+
make
25+
popd
26+
fi
27+
28+
if [[ ! -f "./catt_eo_model_onnx/encoder.onnx" || ! -f "./catt_eo_model_onnx/decoder.onnx" ]]; then
29+
curl -SL -O https://github.com/abjadai/catt/releases/download/v2/eo_model_onnx.zip
30+
unzip eo_model_onnx.zip -d catt_eo_model_onnx
31+
rm eo_model_onnx.zip
32+
fi
33+
34+
java \
35+
-Djava.library.path=$PWD/../build/lib \
36+
-cp ../sherpa-onnx/java-api/build/sherpa-onnx.jar \
37+
./OfflineAddDiacritics.java

sherpa-onnx/java-api/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ java_files += OfflineSpeechDenoiser.java
117117
java_files += OnlineSpeechDenoiserConfig.java
118118
java_files += OnlineSpeechDenoiser.java
119119

120+
java_files += OfflineDiacritizationModelConfig.java
121+
java_files += OfflineDiacritizationConfig.java
122+
java_files += OfflineDiacritization.java
123+
120124
class_files := $(java_files:%.java=%.class)
121125

122126
java_files := $(addprefix src/main/java/$(package_dir)/,$(java_files))
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2026 Matias Lin
2+
3+
package com.k2fsa.sherpa.onnx;
4+
5+
public class OfflineDiacritization {
6+
private long ptr = 0;
7+
8+
public OfflineDiacritization(OfflineDiacritizationConfig config) {
9+
LibraryLoader.maybeLoad();
10+
ptr = newFromFile(config);
11+
if (ptr == 0) {
12+
throw new IllegalArgumentException("Invalid OfflineDiacritizationConfig: failed to create native OfflineDiacritization");
13+
}
14+
}
15+
16+
public String addDiacritics(String text) {
17+
return addDiacritics(ptr, text);
18+
}
19+
20+
@Override
21+
protected void finalize() throws Throwable {
22+
release();
23+
}
24+
25+
// You'd better call it manually if it is not used anymore
26+
public void release() {
27+
if (this.ptr == 0) {
28+
return;
29+
}
30+
delete(this.ptr);
31+
this.ptr = 0;
32+
}
33+
34+
private native void delete(long ptr);
35+
36+
private native long newFromFile(OfflineDiacritizationConfig config);
37+
38+
private native String addDiacritics(long ptr, String text);
39+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2026 Matias Lin
2+
3+
package com.k2fsa.sherpa.onnx;
4+
5+
public class OfflineDiacritizationConfig {
6+
private final OfflineDiacritizationModelConfig model;
7+
8+
private OfflineDiacritizationConfig(Builder builder) {
9+
this.model = builder.model;
10+
}
11+
12+
public static Builder builder() {
13+
return new Builder();
14+
}
15+
16+
public OfflineDiacritizationModelConfig getModel() {
17+
return model;
18+
}
19+
20+
public static class Builder {
21+
private OfflineDiacritizationModelConfig model = OfflineDiacritizationModelConfig.builder().build();
22+
23+
public OfflineDiacritizationConfig build() {
24+
return new OfflineDiacritizationConfig(this);
25+
}
26+
27+
public Builder setModel(OfflineDiacritizationModelConfig model) {
28+
this.model = model;
29+
return this;
30+
}
31+
}
32+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2026 Matias Lin
2+
3+
package com.k2fsa.sherpa.onnx;
4+
5+
public class OfflineDiacritizationModelConfig {
6+
private final String cattEncoder;
7+
private final String cattDecoder;
8+
private final int numThreads;
9+
private final boolean debug;
10+
private final String provider;
11+
12+
private OfflineDiacritizationModelConfig(Builder builder) {
13+
this.cattEncoder = builder.cattEncoder;
14+
this.cattDecoder = builder.cattDecoder;
15+
this.numThreads = builder.numThreads;
16+
this.debug = builder.debug;
17+
this.provider = builder.provider;
18+
}
19+
20+
public static Builder builder() {
21+
return new Builder();
22+
}
23+
24+
public String getCattEncoder() {
25+
return cattEncoder;
26+
}
27+
28+
public String getCattDecoder() {
29+
return cattDecoder;
30+
}
31+
32+
public static class Builder {
33+
private String cattEncoder = "";
34+
private String cattDecoder = "";
35+
private int numThreads = 1;
36+
private boolean debug = true;
37+
private String provider = "cpu";
38+
39+
public OfflineDiacritizationModelConfig build() {
40+
return new OfflineDiacritizationModelConfig(this);
41+
}
42+
43+
public Builder setCattEncoder(String cattEncoder) {
44+
this.cattEncoder = cattEncoder;
45+
return this;
46+
}
47+
48+
public Builder setCattDecoder(String cattDecoder) {
49+
this.cattDecoder = cattDecoder;
50+
return this;
51+
}
52+
53+
public Builder setNumThreads(int numThreads) {
54+
this.numThreads = numThreads;
55+
return this;
56+
}
57+
58+
public Builder setDebug(boolean debug) {
59+
this.debug = debug;
60+
return this;
61+
}
62+
63+
public Builder setProvider(String provider) {
64+
this.provider = provider;
65+
return this;
66+
}
67+
}
68+
}

sherpa-onnx/jni/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ set(sources
1515
common.cc
1616
jni.cc
1717
keyword-spotter.cc
18+
offline-diacritization.cc
1819
offline-punctuation.cc
1920
offline-recognizer.cc
2021
offline-speech-denoiser.cc
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// sherpa-onnx/jni/offline-diacritization.cc
2+
//
3+
// Copyright (c) 2026 Matias Lin
4+
5+
#include "sherpa-onnx/csrc/offline-diacritization.h"
6+
7+
#include <string>
8+
9+
#include "sherpa-onnx/csrc/macros.h"
10+
#include "sherpa-onnx/jni/common.h"
11+
12+
namespace sherpa_onnx {
13+
14+
static OfflineDiacritizationConfig GetOfflineDiacritizationConfig(
15+
JNIEnv *env, jobject config, bool *ok) {
16+
OfflineDiacritizationConfig ans;
17+
18+
jclass cls = env->GetObjectClass(config);
19+
jfieldID fid;
20+
21+
fid = env->GetFieldID(
22+
cls, "model", "Lcom/k2fsa/sherpa/onnx/OfflineDiacritizationModelConfig;");
23+
jobject model_config = env->GetObjectField(config, fid);
24+
jclass model_config_cls = env->GetObjectClass(model_config);
25+
26+
SHERPA_ONNX_JNI_READ_STRING(ans.model.catt_encoder, cattEncoder,
27+
model_config_cls, model_config);
28+
29+
SHERPA_ONNX_JNI_READ_STRING(ans.model.catt_decoder, cattDecoder,
30+
model_config_cls, model_config);
31+
32+
SHERPA_ONNX_JNI_READ_INT(ans.model.num_threads, numThreads, model_config_cls,
33+
model_config);
34+
35+
SHERPA_ONNX_JNI_READ_BOOL(ans.model.debug, debug, model_config_cls,
36+
model_config);
37+
38+
SHERPA_ONNX_JNI_READ_STRING(ans.model.provider, provider, model_config_cls,
39+
model_config);
40+
41+
*ok = true;
42+
return ans;
43+
}
44+
45+
} // namespace sherpa_onnx
46+
47+
SHERPA_ONNX_EXTERN_C
48+
JNIEXPORT jlong JNICALL
49+
Java_com_k2fsa_sherpa_onnx_OfflineDiacritization_newFromAsset(
50+
JNIEnv *env, jobject /*obj*/, jobject asset_manager, jobject _config) {
51+
#if __ANDROID_API__ >= 9
52+
AAssetManager *mgr = AAssetManager_fromJava(env, asset_manager);
53+
if (!mgr) {
54+
SHERPA_ONNX_LOGE("Failed to get asset manager: %p", mgr);
55+
return 0;
56+
}
57+
#endif
58+
bool ok = false;
59+
auto config = sherpa_onnx::GetOfflineDiacritizationConfig(env, _config, &ok);
60+
61+
if (!ok) {
62+
SHERPA_ONNX_LOGE("Please read the error message carefully");
63+
return 0;
64+
}
65+
66+
SHERPA_ONNX_LOGE("config:\n%s", config.ToString().c_str());
67+
68+
auto model = new sherpa_onnx::OfflineDiacritization(
69+
#if __ANDROID_API__ >= 9
70+
mgr,
71+
#endif
72+
config);
73+
74+
return (jlong)model;
75+
}
76+
77+
SHERPA_ONNX_EXTERN_C
78+
JNIEXPORT jlong JNICALL
79+
Java_com_k2fsa_sherpa_onnx_OfflineDiacritization_newFromFile(JNIEnv *env,
80+
jobject /*obj*/,
81+
jobject _config) {
82+
bool ok = false;
83+
auto config = sherpa_onnx::GetOfflineDiacritizationConfig(env, _config, &ok);
84+
85+
if (!ok) {
86+
SHERPA_ONNX_LOGE("Please read the error message carefully");
87+
return 0;
88+
}
89+
90+
SHERPA_ONNX_LOGE("config:\n%s", config.ToString().c_str());
91+
92+
if (!config.Validate()) {
93+
SHERPA_ONNX_LOGE("Errors found in config!");
94+
return 0;
95+
}
96+
97+
auto model = new sherpa_onnx::OfflineDiacritization(config);
98+
99+
return (jlong)model;
100+
}
101+
102+
SHERPA_ONNX_EXTERN_C
103+
JNIEXPORT void JNICALL Java_com_k2fsa_sherpa_onnx_OfflineDiacritization_delete(
104+
JNIEnv * /*env*/, jobject /*obj*/, jlong ptr) {
105+
delete reinterpret_cast<sherpa_onnx::OfflineDiacritization *>(ptr);
106+
}
107+
108+
SHERPA_ONNX_EXTERN_C
109+
JNIEXPORT jstring JNICALL
110+
Java_com_k2fsa_sherpa_onnx_OfflineDiacritization_addDiacritics(JNIEnv *env,
111+
jobject /*obj*/,
112+
jlong ptr,
113+
jstring text) {
114+
auto diacrt =
115+
reinterpret_cast<const sherpa_onnx::OfflineDiacritization *>(ptr);
116+
117+
const char *ptext = env->GetStringUTFChars(text, nullptr);
118+
119+
std::string result = diacrt->AddDiacritics(ptext);
120+
121+
env->ReleaseStringUTFChars(text, ptext);
122+
123+
return SafeNewStringUTF(env, result);
124+
}

sherpa-onnx/jni/sherpa-onnx-symbols.exp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ _Java_com_k2fsa_sherpa_onnx_KeywordSpotter_isReady
1313
_Java_com_k2fsa_sherpa_onnx_KeywordSpotter_newFromAsset
1414
_Java_com_k2fsa_sherpa_onnx_KeywordSpotter_newFromFile
1515
_Java_com_k2fsa_sherpa_onnx_KeywordSpotter_reset
16+
_Java_com_k2fsa_sherpa_onnx_OfflineDiacritization_addDiacritics
17+
_Java_com_k2fsa_sherpa_onnx_OfflineDiacritization_delete
18+
_Java_com_k2fsa_sherpa_onnx_OfflineDiacritization_newFromAsset
19+
_Java_com_k2fsa_sherpa_onnx_OfflineDiacritization_newFromFile
1620
_Java_com_k2fsa_sherpa_onnx_OfflinePunctuation_addPunctuation
1721
_Java_com_k2fsa_sherpa_onnx_OfflinePunctuation_delete
1822
_Java_com_k2fsa_sherpa_onnx_OfflinePunctuation_newFromAsset

0 commit comments

Comments
 (0)