Fangjun Kuang
Committed by GitHub

Add C++ API for streaming zipformer ASR on RK NPU (#1908)

正在显示 73 个修改的文件 包含 1909 行增加120 行删除
@@ -199,6 +199,7 @@ jobs: @@ -199,6 +199,7 @@ jobs:
199 timeout_seconds: 200 199 timeout_seconds: 200
200 shell: bash 200 shell: bash
201 command: | 201 command: |
  202 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
202 git config --global user.email "csukuangfj@gmail.com" 203 git config --global user.email "csukuangfj@gmail.com"
203 git config --global user.name "Fangjun Kuang" 204 git config --global user.name "Fangjun Kuang"
204 205
@@ -207,9 +208,10 @@ jobs: @@ -207,9 +208,10 @@ jobs:
207 GIT_LFS_SKIP_SMUDGE=1 git clone https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-libs huggingface 208 GIT_LFS_SKIP_SMUDGE=1 git clone https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
208 209
209 cd huggingface 210 cd huggingface
210 - mkdir -p aarch64 211 + dst=aarch64/$SHERPA_ONNX_VERSION
  212 + mkdir -p $dst
211 213
212 - cp -v ../sherpa-onnx-*-shared*.tar.bz2 ./aarch64 214 + cp -v ../sherpa-onnx-*-shared*.tar.bz2 $dst/
213 215
214 git status 216 git status
215 git lfs track "*.bz2" 217 git lfs track "*.bz2"
@@ -124,6 +124,7 @@ jobs: @@ -124,6 +124,7 @@ jobs:
124 timeout_seconds: 200 124 timeout_seconds: 200
125 shell: bash 125 shell: bash
126 command: | 126 command: |
  127 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
127 git config --global user.email "csukuangfj@gmail.com" 128 git config --global user.email "csukuangfj@gmail.com"
128 git config --global user.name "Fangjun Kuang" 129 git config --global user.name "Fangjun Kuang"
129 130
@@ -132,9 +133,10 @@ jobs: @@ -132,9 +133,10 @@ jobs:
132 GIT_LFS_SKIP_SMUDGE=1 git clone https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-libs huggingface 133 GIT_LFS_SKIP_SMUDGE=1 git clone https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
133 134
134 cd huggingface 135 cd huggingface
135 - mkdir -p aarch64 136 + dst=aarch64/$SHERPA_ONNX_VERSION
  137 + mkdir -p $dst
136 138
137 - cp -v ../sherpa-onnx-*-static.tar.bz2 ./aarch64 139 + cp -v ../sherpa-onnx-*-static.tar.bz2 $dst/
138 140
139 git status 141 git status
140 git lfs track "*.bz2" 142 git lfs track "*.bz2"
@@ -140,6 +140,7 @@ jobs: @@ -140,6 +140,7 @@ jobs:
140 timeout_seconds: 200 140 timeout_seconds: 200
141 shell: bash 141 shell: bash
142 command: | 142 command: |
  143 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
143 git config --global user.email "csukuangfj@gmail.com" 144 git config --global user.email "csukuangfj@gmail.com"
144 git config --global user.name "Fangjun Kuang" 145 git config --global user.name "Fangjun Kuang"
145 du -h -d1 . 146 du -h -d1 .
@@ -150,8 +151,10 @@ jobs: @@ -150,8 +151,10 @@ jobs:
150 GIT_LFS_SKIP_SMUDGE=1 git clone https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-libs huggingface 151 GIT_LFS_SKIP_SMUDGE=1 git clone https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
151 152
152 cd huggingface 153 cd huggingface
  154 + dst=$SHERPA_ONNX_VERSION
  155 + mkdir -p $dst
153 156
154 - cp -v ../sherpa-onnx-*-android*.tar.bz2 ./ 157 + cp -v ../sherpa-onnx-*-android*.tar.bz2 $dst/
155 158
156 git status 159 git status
157 git lfs track "*.bz2" 160 git lfs track "*.bz2"
@@ -263,6 +266,7 @@ jobs: @@ -263,6 +266,7 @@ jobs:
263 timeout_seconds: 200 266 timeout_seconds: 200
264 shell: bash 267 shell: bash
265 command: | 268 command: |
  269 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
266 git config --global user.email "csukuangfj@gmail.com" 270 git config --global user.email "csukuangfj@gmail.com"
267 git config --global user.name "Fangjun Kuang" 271 git config --global user.name "Fangjun Kuang"
268 du -h -d1 . 272 du -h -d1 .
@@ -273,7 +277,7 @@ jobs: @@ -273,7 +277,7 @@ jobs:
273 GIT_LFS_SKIP_SMUDGE=1 git clone https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-libs huggingface 277 GIT_LFS_SKIP_SMUDGE=1 git clone https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
274 278
275 cd huggingface 279 cd huggingface
276 - dst=android/aar 280 + dst=android/aar/$SHERPA_ONNX_VERSION
277 mkdir -p $dst 281 mkdir -p $dst
278 282
279 cp -v ../*.aar $dst 283 cp -v ../*.aar $dst
@@ -199,6 +199,7 @@ jobs: @@ -199,6 +199,7 @@ jobs:
199 timeout_seconds: 200 199 timeout_seconds: 200
200 shell: bash 200 shell: bash
201 command: | 201 command: |
  202 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
202 git config --global user.email "csukuangfj@gmail.com" 203 git config --global user.email "csukuangfj@gmail.com"
203 git config --global user.name "Fangjun Kuang" 204 git config --global user.name "Fangjun Kuang"
204 205
@@ -206,9 +207,10 @@ jobs: @@ -206,9 +207,10 @@ jobs:
206 GIT_LFS_SKIP_SMUDGE=1 git clone https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-libs huggingface 207 GIT_LFS_SKIP_SMUDGE=1 git clone https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
207 208
208 cd huggingface 209 cd huggingface
209 - mkdir -p arm32 210 + dst=arm32/$SHERPA_ONNX_VERSION
  211 + mkdir -p $dst
210 212
211 - cp -v ../sherpa-onnx-*.tar.bz2 ./arm32 213 + cp -v ../sherpa-onnx-*.tar.bz2 $dst/
212 214
213 git status 215 git status
214 git lfs track "*.bz2" 216 git lfs track "*.bz2"
@@ -83,6 +83,7 @@ jobs: @@ -83,6 +83,7 @@ jobs:
83 timeout_seconds: 200 83 timeout_seconds: 200
84 shell: bash 84 shell: bash
85 command: | 85 command: |
  86 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
86 git config --global user.email "csukuangfj@gmail.com" 87 git config --global user.email "csukuangfj@gmail.com"
87 git config --global user.name "Fangjun Kuang" 88 git config --global user.name "Fangjun Kuang"
88 89
@@ -95,9 +96,10 @@ jobs: @@ -95,9 +96,10 @@ jobs:
95 cd huggingface 96 cd huggingface
96 git fetch 97 git fetch
97 git pull 98 git pull
98 - mkdir -p windows-for-dotnet 99 + dst=windows-for-dotnet/$SHERPA_ONNX_VERSION
  100 + mkdir -p $dst
99 101
100 - cp -v ../sherpa-onnx-*.tar.bz2 ./windows-for-dotnet 102 + cp -v ../sherpa-onnx-*.tar.bz2 $dst/
101 103
102 git status 104 git status
103 git lfs track "*.bz2" 105 git lfs track "*.bz2"
@@ -138,6 +138,7 @@ jobs: @@ -138,6 +138,7 @@ jobs:
138 timeout_seconds: 200 138 timeout_seconds: 200
139 shell: bash 139 shell: bash
140 command: | 140 command: |
  141 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
141 git config --global user.email "csukuangfj@gmail.com" 142 git config --global user.email "csukuangfj@gmail.com"
142 git config --global user.name "Fangjun Kuang" 143 git config --global user.name "Fangjun Kuang"
143 144
@@ -146,10 +147,11 @@ jobs: @@ -146,10 +147,11 @@ jobs:
146 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface 147 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
147 148
148 cd huggingface 149 cd huggingface
149 - mkdir -p jni 150 + dst=jni/$SHERPA_ONNX_VERSION
  151 + mkdir -p $dst
150 152
151 - cp -v ../sherpa-onnx-*.tar.bz2 ./jni  
152 - cp -v ../*.jar ./jni 153 + cp -v ../sherpa-onnx-*.tar.bz2 $dst/
  154 + cp -v ../*.jar $dst/
153 155
154 git status 156 git status
155 git lfs track "*.bz2" 157 git lfs track "*.bz2"
@@ -197,6 +197,7 @@ jobs: @@ -197,6 +197,7 @@ jobs:
197 timeout_seconds: 200 197 timeout_seconds: 200
198 shell: bash 198 shell: bash
199 command: | 199 command: |
  200 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
200 git config --global user.email "csukuangfj@gmail.com" 201 git config --global user.email "csukuangfj@gmail.com"
201 git config --global user.name "Fangjun Kuang" 202 git config --global user.name "Fangjun Kuang"
202 203
@@ -205,10 +206,11 @@ jobs: @@ -205,10 +206,11 @@ jobs:
205 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface 206 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
206 207
207 cd huggingface 208 cd huggingface
208 - mkdir -p jni 209 + dst=jni/$SHERPA_ONNX_VERSION
  210 + mkdir -p $dst
209 211
210 - cp -v ../sherpa-onnx-*.tar.bz2 ./jni  
211 - cp -v ../*.jar ./jni 212 + cp -v ../sherpa-onnx-*.tar.bz2 $dst/
  213 + cp -v ../*.jar $dst/
212 214
213 git status 215 git status
214 git lfs track "*.bz2" 216 git lfs track "*.bz2"
@@ -113,6 +113,7 @@ jobs: @@ -113,6 +113,7 @@ jobs:
113 timeout_seconds: 200 113 timeout_seconds: 200
114 shell: bash 114 shell: bash
115 command: | 115 command: |
  116 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
116 git config --global user.email "csukuangfj@gmail.com" 117 git config --global user.email "csukuangfj@gmail.com"
117 git config --global user.name "Fangjun Kuang" 118 git config --global user.name "Fangjun Kuang"
118 119
@@ -121,9 +122,10 @@ jobs: @@ -121,9 +122,10 @@ jobs:
121 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface 122 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
122 123
123 cd huggingface 124 cd huggingface
124 - mkdir -p jni 125 + dst=jni/$SHERPA_ONNX_VERSION
  126 + mkdir -p $dst
125 127
126 - cp -v ../sherpa-onnx-*.tar.bz2 ./jni 128 + cp -v ../sherpa-onnx-*.tar.bz2 $dst
127 129
128 git status 130 git status
129 git lfs track "*.bz2" 131 git lfs track "*.bz2"
@@ -239,6 +239,7 @@ jobs: @@ -239,6 +239,7 @@ jobs:
239 timeout_seconds: 200 239 timeout_seconds: 200
240 shell: bash 240 shell: bash
241 command: | 241 command: |
  242 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
242 git config --global user.email "csukuangfj@gmail.com" 243 git config --global user.email "csukuangfj@gmail.com"
243 git config --global user.name "Fangjun Kuang" 244 git config --global user.name "Fangjun Kuang"
244 245
@@ -248,9 +249,10 @@ jobs: @@ -248,9 +249,10 @@ jobs:
248 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface 249 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
249 250
250 cd huggingface 251 cd huggingface
251 - mkdir -p riscv64 252 + dst=riscv64/$SHERPA_ONNX_VERSION
  253 + mkdir -p $dst
252 254
253 - cp -v ../sherpa-onnx-*-shared.tar.bz2 ./riscv64 255 + cp -v ../sherpa-onnx-*-shared.tar.bz2 $dst/
254 256
255 git status 257 git status
256 git lfs track "*.bz2" 258 git lfs track "*.bz2"
  1 +name: rknn-linux-aarch64
  2 +
  3 +on:
  4 + push:
  5 + branches:
  6 + - master
  7 + - rknn-c-api-2
  8 + tags:
  9 + - 'v[0-9]+.[0-9]+.[0-9]+*'
  10 + paths:
  11 + - '.github/workflows/rknn-linux-aarch64.yaml'
  12 + - 'cmake/**'
  13 + - 'sherpa-onnx/csrc/*'
  14 + - 'sherpa-onnx/csrc/rknn/*'
  15 + - 'sherpa-onnx/c-api/*'
  16 + - 'toolchains/aarch64-linux-gnu.toolchain.cmake'
  17 + pull_request:
  18 + branches:
  19 + - master
  20 + paths:
  21 + - '.github/workflows/rknn-linux-aarch64.yaml'
  22 + - 'cmake/**'
  23 + - 'sherpa-onnx/csrc/*'
  24 + - 'sherpa-onnx/csrc/rknn/*'
  25 + - 'sherpa-onnx/c-api/*'
  26 + - 'toolchains/aarch64-linux-gnu.toolchain.cmake'
  27 +
  28 + workflow_dispatch:
  29 +
  30 +concurrency:
  31 + group: aarch64-linux-gnu-shared-${{ github.ref }}
  32 + cancel-in-progress: true
  33 +
  34 +jobs:
  35 + rknn_linux_aarch64:
  36 + runs-on: ${{ matrix.os }}
  37 + name: rknn shared ${{ matrix.shared }}
  38 + strategy:
  39 + fail-fast: false
  40 + matrix:
  41 + include:
  42 + - os: ubuntu-22.04-arm
  43 + shared: ON
  44 + - os: ubuntu-22.04-arm
  45 + shared: OFF
  46 +
  47 + steps:
  48 + - uses: actions/checkout@v4
  49 + with:
  50 + fetch-depth: 0
  51 +
  52 + - name: ccache
  53 + uses: hendrikmuhs/ccache-action@v1.2
  54 + with:
  55 + key: ${{ matrix.os }}-${{ matrix.shared }}-rknn-linux-aarch64
  56 +
  57 + - name: Download rknn-toolkit2
  58 + shell: bash
  59 + run: |
  60 + git clone --depth 1 https://github.com/airockchip/rknn-toolkit2
  61 +
  62 + - name: Build sherpa-onnx
  63 + shell: bash
  64 + run: |
  65 + export CMAKE_CXX_COMPILER_LAUNCHER=ccache
  66 + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
  67 + cmake --version
  68 +
  69 + echo "config: ${{ matrix.config }}"
  70 + uname -a
  71 + which gcc
  72 +
  73 + gcc --version
  74 + g++ --version
  75 +
  76 + echo "pwd"
  77 +
  78 + ls -lh
  79 +
  80 + git clone --depth 1 --branch v1.2.12 https://github.com/alsa-project/alsa-lib
  81 + pushd alsa-lib
  82 + ./gitcompile
  83 + popd
  84 +
  85 + export SHERPA_ONNX_RKNN_TOOLKIT2_PATH=$PWD/rknn-toolkit2
  86 + export SHERPA_ONNX_RKNN_TOOLKIT2_LIB_DIR=$SHERPA_ONNX_RKNN_TOOLKIT2_PATH/rknpu2/runtime/Linux/librknn_api/aarch64
  87 + export CPLUS_INCLUDE_PATH=$SHERPA_ONNX_RKNN_TOOLKIT2_PATH/rknpu2/runtime/Linux/librknn_api/include:$CPLUS_INCLUDE_PATH
  88 + export CPLUS_INCLUDE_PATH=$PWD/alsa-lib/include:$CPLUS_INCLUDE_PATH
  89 + export SHERPA_ONNX_ALSA_LIB_DIR=$PWD/alsa-lib/src/.libs
  90 +
  91 + mkdir build
  92 + cd build
  93 +
  94 + BUILD_SHARED_LIBS=${{ matrix.shared }}
  95 +
  96 + cmake \
  97 + -DBUILD_SHARED_LIBS=ON \
  98 + -DCMAKE_INSTALL_PREFIX=./install \
  99 + -DSHERPA_ONNX_ENABLE_RKNN=ON \
  100 + -DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS \
  101 + ..
  102 +
  103 + make -j4 install
  104 +
  105 + rm -rf install/lib/pkgconfig
  106 + rm -fv install/lib/cargs.h
  107 + rm -fv install/lib/libcargs.so
  108 +
  109 + - name: Display system info
  110 + shell: bash
  111 + run: |
  112 + uname -a
  113 + gcc --version
  114 + g++ --version
  115 +
  116 + - name: Display generated files
  117 + shell: bash
  118 + run: |
  119 + export SHERPA_ONNX_RKNN_TOOLKIT2_PATH=$PWD/rknn-toolkit2
  120 + export LD_LIBRARY_PATH=$SHERPA_ONNX_RKNN_TOOLKIT2_PATH/rknpu2/runtime/Linux/librknn_api/aarch64:$LD_LIBRARY_PATH
  121 +
  122 + cd build/install
  123 +
  124 + ls -lh bin
  125 +
  126 + echo "---"
  127 +
  128 + ls -lh lib
  129 +
  130 + file bin/sherpa-onnx
  131 +
  132 + readelf -d bin/sherpa-onnx
  133 +
  134 + ldd bin/sherpa-onnx
  135 +
  136 + ./bin/sherpa-onnx --help
  137 +
  138 + - name: Copy files
  139 + shell: bash
  140 + run: |
  141 + SHERPA_ONNX_VERSION=v$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
  142 +
  143 + if [[ ${{ matrix.shared }} == ON ]]; then
  144 + suffix=shared
  145 + else
  146 + suffix=static
  147 + fi
  148 +
  149 + dst=sherpa-onnx-${SHERPA_ONNX_VERSION}-rknn-linux-aarch64-$suffix
  150 + mkdir $dst
  151 +
  152 + cp -a build/install/bin $dst/
  153 +
  154 + if [[ ${{ matrix.shared }} == ON ]]; then
  155 + cp -v build/install/lib/lib*.so $dst/
  156 + fi
  157 +
  158 + ls -lh build/install/lib
  159 + ls -lh build/install/bin
  160 +
  161 + ls -lh $dst/bin/
  162 + echo "strip"
  163 + strip $dst/bin/*
  164 +
  165 + echo "after strip"
  166 + ls -lh $dst/bin/
  167 +
  168 + tree $dst
  169 +
  170 + tar cjvf ${dst}.tar.bz2 $dst
  171 +
  172 + - uses: actions/upload-artifact@v4
  173 + with:
  174 + name: sherpa-onnx-linux-linux-aarch64-shared-${{ matrix.shared }}
  175 + path: sherpa-onnx-*linux-aarch64*.tar.bz2
  176 +
  177 + # https://huggingface.co/docs/hub/spaces-github-actions
  178 + - name: Publish to huggingface
  179 + if: (github.repository_owner == 'csukuangfj' || github.repository_owner == 'k2-fsa') && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
  180 + env:
  181 + HF_TOKEN: ${{ secrets.HF_TOKEN }}
  182 + uses: nick-fields/retry@v3
  183 + with:
  184 + max_attempts: 20
  185 + timeout_seconds: 200
  186 + shell: bash
  187 + command: |
  188 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
  189 +
  190 + git config --global user.email "csukuangfj@gmail.com"
  191 + git config --global user.name "Fangjun Kuang"
  192 +
  193 + rm -rf huggingface
  194 + export GIT_CLONE_PROTECTION_ACTIVE=false
  195 + GIT_LFS_SKIP_SMUDGE=1 git clone https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
  196 +
  197 + cd huggingface
  198 + dst=rknn-linux-aarch64/$SHERPA_ONNX_VERSION
  199 + mkdir -p $dst
  200 +
  201 + cp -v ../sherpa-onnx-*rknn*-*.tar.bz2 $dst
  202 +
  203 + git status
  204 + git lfs track "*.bz2"
  205 +
  206 + git add .
  207 +
  208 + git commit -m "upload sherpa-onnx-${SHERPA_ONNX_VERSION}-rknn-linux-aarch64.tar.bz2"
  209 +
  210 + git push https://csukuangfj:$HF_TOKEN@huggingface.co/csukuangfj/sherpa-onnx-libs main
  211 +
  212 + - name: Release pre-compiled binaries and libs for rknn linux aarch64
  213 + if: github.repository_owner == 'k2-fsa' && github.event_name == 'push' && contains(github.ref, 'refs/tags/')
  214 + uses: svenstaro/upload-release-action@v2
  215 + with:
  216 + file_glob: true
  217 + overwrite: true
  218 + file: sherpa-onnx-*linux-aarch64*.tar.bz2
  219 +
  220 + - name: Release pre-compiled binaries and libs for rknn linux aarch64
  221 + # if: github.repository_owner == 'csukuangfj' && github.event_name == 'push' && contains(github.ref, 'refs/tags/')
  222 + uses: svenstaro/upload-release-action@v2
  223 + with:
  224 + file_glob: true
  225 + overwrite: true
  226 + file: sherpa-onnx-*linux-aarch64*.tar.bz2
  227 + repo_name: k2-fsa/sherpa-onnx
  228 + repo_token: ${{ secrets.UPLOAD_GH_SHERPA_ONNX_TOKEN }}
  229 + tag: v1.10.45
  230 +
  231 + - name: Test offline Moonshine
  232 + if: matrix.build_type != 'Debug'
  233 + shell: bash
  234 + run: |
  235 + du -h -d1 .
  236 + export PATH=$PWD/build/install/bin:$PATH
  237 + export EXE=sherpa-onnx-offline
  238 +
  239 + readelf -d build/bin/sherpa-onnx-offline
  240 +
  241 + .github/scripts/test-offline-moonshine.sh
@@ -92,6 +92,7 @@ jobs: @@ -92,6 +92,7 @@ jobs:
92 timeout_seconds: 200 92 timeout_seconds: 200
93 shell: bash 93 shell: bash
94 command: | 94 command: |
  95 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
95 git config --global user.email "csukuangfj@gmail.com" 96 git config --global user.email "csukuangfj@gmail.com"
96 git config --global user.name "Fangjun Kuang" 97 git config --global user.name "Fangjun Kuang"
97 98
@@ -100,9 +101,10 @@ jobs: @@ -100,9 +101,10 @@ jobs:
100 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface 101 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
101 102
102 cd huggingface 103 cd huggingface
103 - mkdir -p jni 104 + dst=jni/$SHERPA_ONNX_VERSION
  105 + mkdir -p $dst
104 106
105 - cp -v ../sherpa-onnx-*.tar.bz2 ./jni 107 + cp -v ../sherpa-onnx-*.tar.bz2 $dst
106 108
107 git status 109 git status
108 git lfs track "*.bz2" 110 git lfs track "*.bz2"
@@ -128,6 +128,7 @@ jobs: @@ -128,6 +128,7 @@ jobs:
128 timeout_seconds: 200 128 timeout_seconds: 200
129 shell: bash 129 shell: bash
130 command: | 130 command: |
  131 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
131 git config --global user.email "csukuangfj@gmail.com" 132 git config --global user.email "csukuangfj@gmail.com"
132 git config --global user.name "Fangjun Kuang" 133 git config --global user.name "Fangjun Kuang"
133 134
@@ -136,9 +137,10 @@ jobs: @@ -136,9 +137,10 @@ jobs:
136 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface 137 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
137 138
138 cd huggingface 139 cd huggingface
139 - mkdir -p win64 140 + dst=win64/$SHERPA_ONNX_VERSION
  141 + mkdir -p $dst
140 142
141 - cp -v ../sherpa-onnx-*.tar.bz2 ./win64 143 + cp -v ../sherpa-onnx-*.tar.bz2 $dst
142 144
143 git status 145 git status
144 git lfs track "*.bz2" 146 git lfs track "*.bz2"
@@ -131,6 +131,7 @@ jobs: @@ -131,6 +131,7 @@ jobs:
131 timeout_seconds: 200 131 timeout_seconds: 200
132 shell: bash 132 shell: bash
133 command: | 133 command: |
  134 + SHERPA_ONNX_VERSION=$(grep "SHERPA_ONNX_VERSION" ./CMakeLists.txt | cut -d " " -f 2 | cut -d '"' -f 2)
134 git config --global user.email "csukuangfj@gmail.com" 135 git config --global user.email "csukuangfj@gmail.com"
135 git config --global user.name "Fangjun Kuang" 136 git config --global user.name "Fangjun Kuang"
136 137
@@ -139,7 +140,8 @@ jobs: @@ -139,7 +140,8 @@ jobs:
139 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface 140 GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-libs huggingface
140 141
141 cd huggingface 142 cd huggingface
142 - mkdir -p win32 143 + dst=win32/$SHERPA_ONNX_VERSION
  144 + mkdir -p $dst
143 145
144 cp -v ../sherpa-onnx-*.tar.bz2 ./win32 146 cp -v ../sherpa-onnx-*.tar.bz2 ./win32
145 147
@@ -45,6 +45,7 @@ option(SHERPA_ONNX_LINK_LIBSTDCPP_STATICALLY "True to link libstdc++ statically. @@ -45,6 +45,7 @@ option(SHERPA_ONNX_LINK_LIBSTDCPP_STATICALLY "True to link libstdc++ statically.
45 option(SHERPA_ONNX_USE_PRE_INSTALLED_ONNXRUNTIME_IF_AVAILABLE "True to use pre-installed onnxruntime if available" ON) 45 option(SHERPA_ONNX_USE_PRE_INSTALLED_ONNXRUNTIME_IF_AVAILABLE "True to use pre-installed onnxruntime if available" ON)
46 option(SHERPA_ONNX_ENABLE_SANITIZER "Whether to enable ubsan and asan" OFF) 46 option(SHERPA_ONNX_ENABLE_SANITIZER "Whether to enable ubsan and asan" OFF)
47 option(SHERPA_ONNX_BUILD_C_API_EXAMPLES "Whether to enable C API examples" ON) 47 option(SHERPA_ONNX_BUILD_C_API_EXAMPLES "Whether to enable C API examples" ON)
  48 +option(SHERPA_ONNX_ENABLE_RKNN "Whether to build for RKNN NPU " OFF)
48 49
49 set(SHERPA_ONNX_LINUX_ARM64_GPU_ONNXRUNTIME_VERSION "1.11.0" CACHE STRING "Used only for Linux ARM64 GPU. If you use Jetson nano b01, then please set it to 1.11.0. If you use Jetson Orin NX, then set it to 1.16.0.If you use NVIDIA Jetson Orin Nano Engineering Reference Developer Kit 50 set(SHERPA_ONNX_LINUX_ARM64_GPU_ONNXRUNTIME_VERSION "1.11.0" CACHE STRING "Used only for Linux ARM64 GPU. If you use Jetson nano b01, then please set it to 1.11.0. If you use Jetson Orin NX, then set it to 1.16.0.If you use NVIDIA Jetson Orin Nano Engineering Reference Developer Kit
50 Super - Jetpack 6.2 [L4T 36.4.3], then set it to 1.18.1") 51 Super - Jetpack 6.2 [L4T 36.4.3], then set it to 1.18.1")
@@ -155,6 +156,7 @@ message(STATUS "SHERPA_ONNX_LINK_LIBSTDCPP_STATICALLY ${SHERPA_ONNX_LINK_LIBSTDC @@ -155,6 +156,7 @@ message(STATUS "SHERPA_ONNX_LINK_LIBSTDCPP_STATICALLY ${SHERPA_ONNX_LINK_LIBSTDC
155 message(STATUS "SHERPA_ONNX_USE_PRE_INSTALLED_ONNXRUNTIME_IF_AVAILABLE ${SHERPA_ONNX_USE_PRE_INSTALLED_ONNXRUNTIME_IF_AVAILABLE}") 156 message(STATUS "SHERPA_ONNX_USE_PRE_INSTALLED_ONNXRUNTIME_IF_AVAILABLE ${SHERPA_ONNX_USE_PRE_INSTALLED_ONNXRUNTIME_IF_AVAILABLE}")
156 message(STATUS "SHERPA_ONNX_ENABLE_SANITIZER: ${SHERPA_ONNX_ENABLE_SANITIZER}") 157 message(STATUS "SHERPA_ONNX_ENABLE_SANITIZER: ${SHERPA_ONNX_ENABLE_SANITIZER}")
157 message(STATUS "SHERPA_ONNX_BUILD_C_API_EXAMPLES: ${SHERPA_ONNX_BUILD_C_API_EXAMPLES}") 158 message(STATUS "SHERPA_ONNX_BUILD_C_API_EXAMPLES: ${SHERPA_ONNX_BUILD_C_API_EXAMPLES}")
  159 +message(STATUS "SHERPA_ONNX_ENABLE_RKNN: ${SHERPA_ONNX_ENABLE_RKNN}")
158 160
159 if(BUILD_SHARED_LIBS OR SHERPA_ONNX_ENABLE_JNI) 161 if(BUILD_SHARED_LIBS OR SHERPA_ONNX_ENABLE_JNI)
160 set(CMAKE_CXX_VISIBILITY_PRESET hidden) 162 set(CMAKE_CXX_VISIBILITY_PRESET hidden)
@@ -199,7 +201,7 @@ if(SHERPA_ONNX_ENABLE_DIRECTML) @@ -199,7 +201,7 @@ if(SHERPA_ONNX_ENABLE_DIRECTML)
199 message(STATUS "DirectML is enabled") 201 message(STATUS "DirectML is enabled")
200 add_definitions(-DSHERPA_ONNX_ENABLE_DIRECTML=1) 202 add_definitions(-DSHERPA_ONNX_ENABLE_DIRECTML=1)
201 else() 203 else()
202 - message(WARNING "DirectML is disabled") 204 + message(STATUS "DirectML is disabled")
203 add_definitions(-DSHERPA_ONNX_ENABLE_DIRECTML=0) 205 add_definitions(-DSHERPA_ONNX_ENABLE_DIRECTML=0)
204 endif() 206 endif()
205 207
@@ -267,6 +269,10 @@ message(STATUS "C++ Standard version: ${CMAKE_CXX_STANDARD}") @@ -267,6 +269,10 @@ message(STATUS "C++ Standard version: ${CMAKE_CXX_STANDARD}")
267 269
268 include(CheckIncludeFileCXX) 270 include(CheckIncludeFileCXX)
269 271
  272 +if(SHERPA_ONNX_ENABLE_RKNN)
  273 + add_definitions(-DSHERPA_ONNX_ENABLE_RKNN=1)
  274 +endif()
  275 +
270 if(UNIX AND NOT APPLE AND NOT SHERPA_ONNX_ENABLE_WASM AND NOT CMAKE_SYSTEM_NAME STREQUAL Android AND NOT CMAKE_SYSTEM_NAME STREQUAL OHOS) 276 if(UNIX AND NOT APPLE AND NOT SHERPA_ONNX_ENABLE_WASM AND NOT CMAKE_SYSTEM_NAME STREQUAL Android AND NOT CMAKE_SYSTEM_NAME STREQUAL OHOS)
271 check_include_file_cxx(alsa/asoundlib.h SHERPA_ONNX_HAS_ALSA) 277 check_include_file_cxx(alsa/asoundlib.h SHERPA_ONNX_HAS_ALSA)
272 if(SHERPA_ONNX_HAS_ALSA) 278 if(SHERPA_ONNX_HAS_ALSA)
@@ -74,7 +74,7 @@ if [[ x"$BUILD_SHARED_LIBS" == x"" ]]; then @@ -74,7 +74,7 @@ if [[ x"$BUILD_SHARED_LIBS" == x"" ]]; then
74 fi 74 fi
75 75
76 if [[ x"$SHERPA_ONNX_ENABLE_GPU" == x"" ]]; then 76 if [[ x"$SHERPA_ONNX_ENABLE_GPU" == x"" ]]; then
77 - # By default, use CPU 77 + # By default, don't use CPU
78 SHERPA_ONNX_ENABLE_GPU=OFF 78 SHERPA_ONNX_ENABLE_GPU=OFF
79 fi 79 fi
80 80
  1 +#!/usr/bin/env bash
  2 +
  3 +set -ex
  4 +
  5 +# Before you run this file, make sure you have first cloned
  6 +# https://github.com/airockchip/rknn-toolkit2
  7 +# and set the environment variable SHERPA_ONNX_RKNN_TOOLKIT2_PATH
  8 +
  9 +if [ -z $SHERPA_ONNX_RKNN_TOOLKIT2_PATH ]; then
  10 + SHERPA_ONNX_RKNN_TOOLKIT2_PATH=/star-fj/fangjun/open-source/rknn-toolkit2
  11 +fi
  12 +
  13 +if [ ! -d $SHERPA_ONNX_RKNN_TOOLKIT2_PATH ]; then
  14 + echo "Please first clone https://github.com/airockchip/rknn-toolkit2"
  15 + echo "You can use"
  16 + echo " git clone --depth 1 https://github.com/airockchip/rknn-toolkit2"
  17 + echo " export SHERPA_ONNX_RKNN_TOOLKIT2_PATH=$PWD/rknn-toolkit2"
  18 +
  19 + exit 1
  20 +fi
  21 +
  22 +if [ ! -f $SHERPA_ONNX_RKNN_TOOLKIT2_PATH/rknpu2/runtime/Linux/librknn_api/include/rknn_api.h ]; then
  23 + echo "$SHERPA_ONNX_RKNN_TOOLKIT2_PATH/rknpu2/runtime/Linux/librknn_api/include/rknn_api.h does not exist"
  24 + exit 1
  25 +fi
  26 +
  27 +if [ ! -f $SHERPA_ONNX_RKNN_TOOLKIT2_PATH/rknpu2/runtime/Linux/librknn_api/aarch64/librknnrt.so ]; then
  28 + echo "$SHERPA_ONNX_RKNN_TOOLKIT2_PATH/rknpu2/runtime/Linux/librknn_api/aarch64/librknnrt.so does not exist"
  29 + exit 1
  30 +fi
  31 +
  32 +export SHERPA_ONNX_RKNN_TOOLKIT2_LIB_DIR=$SHERPA_ONNX_RKNN_TOOLKIT2_PATH/rknpu2/runtime/Linux/librknn_api/aarch64
  33 +
  34 +export CPLUS_INCLUDE_PATH=$SHERPA_ONNX_RKNN_TOOLKIT2_PATH/rknpu2/runtime/Linux/librknn_api/include:$CPLUS_INCLUDE_PATH
  35 +
  36 +if ! command -v aarch64-linux-gnu-gcc &> /dev/null; then
  37 + echo "Please install a toolchain for cross-compiling."
  38 + echo "You can refer to: "
  39 + echo " https://k2-fsa.github.io/sherpa/onnx/install/rknn-linux-aarch64.html"
  40 + echo "for help."
  41 + exit 1
  42 +fi
  43 +
  44 +
  45 +dir=$PWD/build-rknn-linux-aarch64
  46 +mkdir -p $dir
  47 +
  48 +cd $dir
  49 +
  50 +if [ ! -f alsa-lib/src/.libs/libasound.so ]; then
  51 + echo "Start to cross-compile alsa-lib"
  52 + if [ ! -d alsa-lib ]; then
  53 + git clone --depth 1 --branch v1.2.12 https://github.com/alsa-project/alsa-lib
  54 + fi
  55 + # If it shows:
  56 + # ./gitcompile: line 79: libtoolize: command not found
  57 + # Please use:
  58 + # sudo apt-get install libtool m4 automake
  59 + #
  60 + pushd alsa-lib
  61 + CC=aarch64-linux-gnu-gcc ./gitcompile --host=aarch64-linux-gnu
  62 + popd
  63 + echo "Finish cross-compiling alsa-lib"
  64 +fi
  65 +
  66 +export CPLUS_INCLUDE_PATH=$PWD/alsa-lib/include:$CPLUS_INCLUDE_PATH
  67 +export SHERPA_ONNX_ALSA_LIB_DIR=$PWD/alsa-lib/src/.libs
  68 +
  69 +if [[ x"$BUILD_SHARED_LIBS" == x"" ]]; then
  70 + # By default, use shared link
  71 + BUILD_SHARED_LIBS=ON
  72 +fi
  73 +
  74 +cmake \
  75 + -DBUILD_PIPER_PHONMIZE_EXE=OFF \
  76 + -DBUILD_PIPER_PHONMIZE_TESTS=OFF \
  77 + -DBUILD_ESPEAK_NG_EXE=OFF \
  78 + -DBUILD_ESPEAK_NG_TESTS=OFF \
  79 + -DCMAKE_INSTALL_PREFIX=./install \
  80 + -DCMAKE_BUILD_TYPE=Release \
  81 + -DSHERPA_ONNX_ENABLE_GPU=OFF \
  82 + -DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS \
  83 + -DSHERPA_ONNX_ENABLE_TESTS=OFF \
  84 + -DSHERPA_ONNX_ENABLE_PYTHON=OFF \
  85 + -DSHERPA_ONNX_ENABLE_CHECK=OFF \
  86 + -DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \
  87 + -DSHERPA_ONNX_ENABLE_JNI=OFF \
  88 + -DSHERPA_ONNX_ENABLE_C_API=ON \
  89 + -DSHERPA_ONNX_ENABLE_WEBSOCKET=ON \
  90 + -DSHERPA_ONNX_ENABLE_RKNN=ON \
  91 + -DCMAKE_TOOLCHAIN_FILE=../toolchains/aarch64-linux-gnu.toolchain.cmake \
  92 + ..
  93 +
  94 +make VERBOSE=1 -j4
  95 +make install/strip
  96 +
  97 +# Enable it if only needed
  98 +# cp -v $SHERPA_ONNX_ALSA_LIB_DIR/libasound.so* ./install/lib/
  99 +
  100 +# See also
  101 +# https://github.com/airockchip/rknn-toolkit2/blob/master/rknpu2/examples/rknn_api_demo/build-linux.sh
@@ -150,7 +150,7 @@ if [ ! -f $src_dir/windows-x86/sherpa-onnx-c-api.dll ]; then @@ -150,7 +150,7 @@ if [ ! -f $src_dir/windows-x86/sherpa-onnx-c-api.dll ]; then
150 if [ -f $windows_x86_wheel ]; then 150 if [ -f $windows_x86_wheel ]; then
151 cp -v $windows_x86_wheel . 151 cp -v $windows_x86_wheel .
152 else 152 else
153 - curl -OL https://$HF_MIRROR/csukuangfj/sherpa-onnx-libs/resolve/main/windows-for-dotnet/$windows_x86_wheel_filename 153 + curl -OL https://$HF_MIRROR/csukuangfj/sherpa-onnx-libs/resolve/main/windows-for-dotnet/$SHERPA_ONNX_VERSION/$windows_x86_wheel_filename
154 fi 154 fi
155 tar xvf $windows_x86_wheel_filename 155 tar xvf $windows_x86_wheel_filename
156 cp -v sherpa-onnx-${SHERPA_ONNX_VERSION}-win-x86/*dll ../ 156 cp -v sherpa-onnx-${SHERPA_ONNX_VERSION}-win-x86/*dll ../
@@ -169,7 +169,7 @@ if [ ! -f $src_dir/windows-arm64/sherpa-onnx-c-api.dll ]; then @@ -169,7 +169,7 @@ if [ ! -f $src_dir/windows-arm64/sherpa-onnx-c-api.dll ]; then
169 if [ -f $windows_arm64_wheel ]; then 169 if [ -f $windows_arm64_wheel ]; then
170 cp -v $windows_arm64_wheel . 170 cp -v $windows_arm64_wheel .
171 else 171 else
172 - curl -OL https://$HF_MIRROR/csukuangfj/sherpa-onnx-libs/resolve/main/windows-for-dotnet/$windows_arm64_wheel_filename 172 + curl -OL https://$HF_MIRROR/csukuangfj/sherpa-onnx-libs/resolve/main/windows-for-dotnet/$SHERPA_ONNX_VERSION/$windows_arm64_wheel_filename
173 fi 173 fi
174 tar xvf $windows_arm64_wheel_filename 174 tar xvf $windows_arm64_wheel_filename
175 cp -v sherpa-onnx-${SHERPA_ONNX_VERSION}-win-arm64/*dll ../ 175 cp -v sherpa-onnx-${SHERPA_ONNX_VERSION}-win-arm64/*dll ../
@@ -151,6 +151,14 @@ list(APPEND sources @@ -151,6 +151,14 @@ list(APPEND sources
151 online-punctuation-model-config.cc 151 online-punctuation-model-config.cc
152 online-punctuation.cc 152 online-punctuation.cc
153 ) 153 )
  154 +if(SHERPA_ONNX_ENABLE_RKNN)
  155 + list(APPEND sources
  156 + ./rknn/online-stream-rknn.cc
  157 + ./rknn/online-transducer-greedy-search-decoder-rknn.cc
  158 + ./rknn/online-zipformer-transducer-model-rknn.cc
  159 + )
  160 +
  161 +endif()
154 162
155 if(SHERPA_ONNX_ENABLE_TTS) 163 if(SHERPA_ONNX_ENABLE_TTS)
156 list(APPEND sources 164 list(APPEND sources
@@ -230,6 +238,14 @@ if(SHERPA_ONNX_ENABLE_GPU) @@ -230,6 +238,14 @@ if(SHERPA_ONNX_ENABLE_GPU)
230 ) 238 )
231 endif() 239 endif()
232 240
  241 +if(SHERPA_ONNX_ENABLE_RKNN)
  242 + if(DEFINED ENV{SHERPA_ONNX_RKNN_TOOLKIT2_LIB_DIR})
  243 + target_link_libraries(sherpa-onnx-core -L$ENV{SHERPA_ONNX_RKNN_TOOLKIT2_LIB_DIR} -lrknnrt)
  244 + else()
  245 + target_link_libraries(sherpa-onnx-core rknnrt)
  246 + endif()
  247 +endif()
  248 +
233 if(BUILD_SHARED_LIBS AND NOT DEFINED onnxruntime_lib_files) 249 if(BUILD_SHARED_LIBS AND NOT DEFINED onnxruntime_lib_files)
234 target_link_libraries(sherpa-onnx-core onnxruntime) 250 target_link_libraries(sherpa-onnx-core onnxruntime)
235 else() 251 else()
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
5 #include "sherpa-onnx/csrc/file-utils.h" 5 #include "sherpa-onnx/csrc/file-utils.h"
6 6
7 #include <fstream> 7 #include <fstream>
  8 +#include <memory>
8 #include <string> 9 #include <string>
9 10
10 #include "sherpa-onnx/csrc/macros.h" 11 #include "sherpa-onnx/csrc/macros.h"
@@ -22,4 +23,61 @@ void AssertFileExists(const std::string &filename) { @@ -22,4 +23,61 @@ void AssertFileExists(const std::string &filename) {
22 } 23 }
23 } 24 }
24 25
  26 +std::vector<char> ReadFile(const std::string &filename) {
  27 + std::ifstream input(filename, std::ios::binary);
  28 + std::vector<char> buffer(std::istreambuf_iterator<char>(input), {});
  29 + return buffer;
  30 +}
  31 +
  32 +#if __ANDROID_API__ >= 9
  33 +std::vector<char> ReadFile(AAssetManager *mgr, const std::string &filename) {
  34 + AAsset *asset = AAssetManager_open(mgr, filename.c_str(), AASSET_MODE_BUFFER);
  35 + if (!asset) {
  36 + __android_log_print(ANDROID_LOG_FATAL, "sherpa-onnx",
  37 + "Read binary file: Load %s failed", filename.c_str());
  38 + exit(-1);
  39 + }
  40 +
  41 + auto p = reinterpret_cast<const char *>(AAsset_getBuffer(asset));
  42 + size_t asset_length = AAsset_getLength(asset);
  43 +
  44 + std::vector<char> buffer(p, p + asset_length);
  45 + AAsset_close(asset);
  46 +
  47 + return buffer;
  48 +}
  49 +#endif
  50 +
  51 +#if __OHOS__
  52 +std::vector<char> ReadFile(NativeResourceManager *mgr,
  53 + const std::string &filename) {
  54 + std::unique_ptr<RawFile, decltype(&OH_ResourceManager_CloseRawFile)> fp(
  55 + OH_ResourceManager_OpenRawFile(mgr, filename.c_str()),
  56 + OH_ResourceManager_CloseRawFile);
  57 +
  58 + if (!fp) {
  59 + std::ostringstream os;
  60 + os << "Read file '" << filename << "' failed.";
  61 + SHERPA_ONNX_LOGE("%s", os.str().c_str());
  62 + return {};
  63 + }
  64 +
  65 + auto len = static_cast<int32_t>(OH_ResourceManager_GetRawFileSize(fp.get()));
  66 +
  67 + std::vector<char> buffer(len);
  68 +
  69 + int32_t n = OH_ResourceManager_ReadRawFile(fp.get(), buffer.data(), len);
  70 +
  71 + if (n != len) {
  72 + std::ostringstream os;
  73 + os << "Read file '" << filename << "' failed. Number of bytes read: " << n
  74 + << ". Expected bytes to read: " << len;
  75 + SHERPA_ONNX_LOGE("%s", os.str().c_str());
  76 + return {};
  77 + }
  78 +
  79 + return buffer;
  80 +}
  81 +#endif
  82 +
25 } // namespace sherpa_onnx 83 } // namespace sherpa_onnx
@@ -7,6 +7,16 @@ @@ -7,6 +7,16 @@
7 7
8 #include <fstream> 8 #include <fstream>
9 #include <string> 9 #include <string>
  10 +#include <vector>
  11 +
  12 +#if __ANDROID_API__ >= 9
  13 +#include "android/asset_manager.h"
  14 +#include "android/asset_manager_jni.h"
  15 +#endif
  16 +
  17 +#if __OHOS__
  18 +#include "rawfile/raw_file_manager.h"
  19 +#endif
10 20
11 namespace sherpa_onnx { 21 namespace sherpa_onnx {
12 22
@@ -23,6 +33,17 @@ bool FileExists(const std::string &filename); @@ -23,6 +33,17 @@ bool FileExists(const std::string &filename);
23 */ 33 */
24 void AssertFileExists(const std::string &filename); 34 void AssertFileExists(const std::string &filename);
25 35
  36 +std::vector<char> ReadFile(const std::string &filename);
  37 +
  38 +#if __ANDROID_API__ >= 9
  39 +std::vector<char> ReadFile(AAssetManager *mgr, const std::string &filename);
  40 +#endif
  41 +
  42 +#if __OHOS__
  43 +std::vector<char> ReadFile(NativeResourceManager *mgr,
  44 + const std::string &filename);
  45 +#endif
  46 +
26 } // namespace sherpa_onnx 47 } // namespace sherpa_onnx
27 48
28 #endif // SHERPA_ONNX_CSRC_FILE_UTILS_H_ 49 #endif // SHERPA_ONNX_CSRC_FILE_UTILS_H_
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 #include "rawfile/raw_file_manager.h" 17 #include "rawfile/raw_file_manager.h"
18 #endif 18 #endif
19 19
  20 +#include "sherpa-onnx/csrc/file-utils.h"
20 #include "sherpa-onnx/csrc/macros.h" 21 #include "sherpa-onnx/csrc/macros.h"
21 #include "sherpa-onnx/csrc/onnx-utils.h" 22 #include "sherpa-onnx/csrc/onnx-utils.h"
22 #include "sherpa-onnx/csrc/session.h" 23 #include "sherpa-onnx/csrc/session.h"
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
  10 +#include "sherpa-onnx/csrc/file-utils.h"
10 #include "sherpa-onnx/csrc/onnx-utils.h" 11 #include "sherpa-onnx/csrc/onnx-utils.h"
11 #include "sherpa-onnx/csrc/session.h" 12 #include "sherpa-onnx/csrc/session.h"
12 #include "sherpa-onnx/csrc/text-utils.h" 13 #include "sherpa-onnx/csrc/text-utils.h"
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
  10 +#include "sherpa-onnx/csrc/file-utils.h"
10 #include "sherpa-onnx/csrc/onnx-utils.h" 11 #include "sherpa-onnx/csrc/onnx-utils.h"
11 #include "sherpa-onnx/csrc/session.h" 12 #include "sherpa-onnx/csrc/session.h"
12 #include "sherpa-onnx/csrc/text-utils.h" 13 #include "sherpa-onnx/csrc/text-utils.h"
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 #include "rawfile/raw_file_manager.h" 18 #include "rawfile/raw_file_manager.h"
19 #endif 19 #endif
20 20
  21 +#include "sherpa-onnx/csrc/file-utils.h"
21 #include "sherpa-onnx/csrc/macros.h" 22 #include "sherpa-onnx/csrc/macros.h"
22 #include "sherpa-onnx/csrc/offline-nemo-enc-dec-ctc-model.h" 23 #include "sherpa-onnx/csrc/offline-nemo-enc-dec-ctc-model.h"
23 #include "sherpa-onnx/csrc/offline-tdnn-ctc-model.h" 24 #include "sherpa-onnx/csrc/offline-tdnn-ctc-model.h"
@@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
20 #include "rawfile/raw_file_manager.h" 20 #include "rawfile/raw_file_manager.h"
21 #endif 21 #endif
22 22
  23 +#include "sherpa-onnx/csrc/file-utils.h"
23 #include "sherpa-onnx/csrc/macros.h" 24 #include "sherpa-onnx/csrc/macros.h"
24 #include "sherpa-onnx/csrc/onnx-utils.h" 25 #include "sherpa-onnx/csrc/onnx-utils.h"
25 #include "sherpa-onnx/csrc/session.h" 26 #include "sherpa-onnx/csrc/session.h"
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 #include "rawfile/raw_file_manager.h" 17 #include "rawfile/raw_file_manager.h"
18 #endif 18 #endif
19 19
  20 +#include "sherpa-onnx/csrc/file-utils.h"
20 #include "sherpa-onnx/csrc/macros.h" 21 #include "sherpa-onnx/csrc/macros.h"
21 #include "sherpa-onnx/csrc/onnx-utils.h" 22 #include "sherpa-onnx/csrc/onnx-utils.h"
22 #include "sherpa-onnx/csrc/session.h" 23 #include "sherpa-onnx/csrc/session.h"
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 #include "rawfile/raw_file_manager.h" 13 #include "rawfile/raw_file_manager.h"
14 #endif 14 #endif
15 15
  16 +#include "sherpa-onnx/csrc/file-utils.h"
16 #include "sherpa-onnx/csrc/macros.h" 17 #include "sherpa-onnx/csrc/macros.h"
17 #include "sherpa-onnx/csrc/onnx-utils.h" 18 #include "sherpa-onnx/csrc/onnx-utils.h"
18 #include "sherpa-onnx/csrc/session.h" 19 #include "sherpa-onnx/csrc/session.h"
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 #include "rawfile/raw_file_manager.h" 17 #include "rawfile/raw_file_manager.h"
18 #endif 18 #endif
19 19
  20 +#include "sherpa-onnx/csrc/file-utils.h"
20 #include "sherpa-onnx/csrc/macros.h" 21 #include "sherpa-onnx/csrc/macros.h"
21 #include "sherpa-onnx/csrc/onnx-utils.h" 22 #include "sherpa-onnx/csrc/onnx-utils.h"
22 #include "sherpa-onnx/csrc/session.h" 23 #include "sherpa-onnx/csrc/session.h"
@@ -22,6 +22,7 @@ @@ -22,6 +22,7 @@
22 #include "fst/extensions/far/far.h" 22 #include "fst/extensions/far/far.h"
23 #include "kaldifst/csrc/kaldi-fst-io.h" 23 #include "kaldifst/csrc/kaldi-fst-io.h"
24 #include "onnxruntime_cxx_api.h" // NOLINT 24 #include "onnxruntime_cxx_api.h" // NOLINT
  25 +#include "sherpa-onnx/csrc/file-utils.h"
25 #include "sherpa-onnx/csrc/macros.h" 26 #include "sherpa-onnx/csrc/macros.h"
26 #include "sherpa-onnx/csrc/offline-recognizer-ctc-impl.h" 27 #include "sherpa-onnx/csrc/offline-recognizer-ctc-impl.h"
27 #include "sherpa-onnx/csrc/offline-recognizer-fire-red-asr-impl.h" 28 #include "sherpa-onnx/csrc/offline-recognizer-fire-red-asr-impl.h"
@@ -31,7 +32,6 @@ @@ -31,7 +32,6 @@
31 #include "sherpa-onnx/csrc/offline-recognizer-transducer-impl.h" 32 #include "sherpa-onnx/csrc/offline-recognizer-transducer-impl.h"
32 #include "sherpa-onnx/csrc/offline-recognizer-transducer-nemo-impl.h" 33 #include "sherpa-onnx/csrc/offline-recognizer-transducer-nemo-impl.h"
33 #include "sherpa-onnx/csrc/offline-recognizer-whisper-impl.h" 34 #include "sherpa-onnx/csrc/offline-recognizer-whisper-impl.h"
34 -#include "sherpa-onnx/csrc/onnx-utils.h"  
35 #include "sherpa-onnx/csrc/text-utils.h" 35 #include "sherpa-onnx/csrc/text-utils.h"
36 36
37 namespace sherpa_onnx { 37 namespace sherpa_onnx {
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 #endif 18 #endif
19 19
20 #include "onnxruntime_cxx_api.h" // NOLINT 20 #include "onnxruntime_cxx_api.h" // NOLINT
  21 +#include "sherpa-onnx/csrc/file-utils.h"
21 #include "sherpa-onnx/csrc/macros.h" 22 #include "sherpa-onnx/csrc/macros.h"
22 #include "sherpa-onnx/csrc/onnx-utils.h" 23 #include "sherpa-onnx/csrc/onnx-utils.h"
23 #include "sherpa-onnx/csrc/session.h" 24 #include "sherpa-onnx/csrc/session.h"
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 #include "rawfile/raw_file_manager.h" 17 #include "rawfile/raw_file_manager.h"
18 #endif 18 #endif
19 19
  20 +#include "sherpa-onnx/csrc/file-utils.h"
20 #include "sherpa-onnx/csrc/macros.h" 21 #include "sherpa-onnx/csrc/macros.h"
21 #include "sherpa-onnx/csrc/onnx-utils.h" 22 #include "sherpa-onnx/csrc/onnx-utils.h"
22 #include "sherpa-onnx/csrc/session.h" 23 #include "sherpa-onnx/csrc/session.h"
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 #include "rawfile/raw_file_manager.h" 17 #include "rawfile/raw_file_manager.h"
18 #endif 18 #endif
19 19
  20 +#include "sherpa-onnx/csrc/file-utils.h"
20 #include "sherpa-onnx/csrc/onnx-utils.h" 21 #include "sherpa-onnx/csrc/onnx-utils.h"
21 #include "sherpa-onnx/csrc/session.h" 22 #include "sherpa-onnx/csrc/session.h"
22 23
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 #include "rawfile/raw_file_manager.h" 15 #include "rawfile/raw_file_manager.h"
16 #endif 16 #endif
17 17
  18 +#include "sherpa-onnx/csrc/file-utils.h"
18 #include "sherpa-onnx/csrc/macros.h" 19 #include "sherpa-onnx/csrc/macros.h"
19 #include "sherpa-onnx/csrc/onnx-utils.h" 20 #include "sherpa-onnx/csrc/onnx-utils.h"
20 #include "sherpa-onnx/csrc/session.h" 21 #include "sherpa-onnx/csrc/session.h"
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 #include "rawfile/raw_file_manager.h" 13 #include "rawfile/raw_file_manager.h"
14 #endif 14 #endif
15 15
  16 +#include "sherpa-onnx/csrc/file-utils.h"
16 #include "sherpa-onnx/csrc/macros.h" 17 #include "sherpa-onnx/csrc/macros.h"
17 #include "sherpa-onnx/csrc/onnx-utils.h" 18 #include "sherpa-onnx/csrc/onnx-utils.h"
18 #include "sherpa-onnx/csrc/session.h" 19 #include "sherpa-onnx/csrc/session.h"
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 #include "rawfile/raw_file_manager.h" 17 #include "rawfile/raw_file_manager.h"
18 #endif 18 #endif
19 19
  20 +#include "sherpa-onnx/csrc/file-utils.h"
20 #include "sherpa-onnx/csrc/macros.h" 21 #include "sherpa-onnx/csrc/macros.h"
21 #include "sherpa-onnx/csrc/offline-transducer-decoder.h" 22 #include "sherpa-onnx/csrc/offline-transducer-decoder.h"
22 #include "sherpa-onnx/csrc/onnx-utils.h" 23 #include "sherpa-onnx/csrc/onnx-utils.h"
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 #include "rawfile/raw_file_manager.h" 18 #include "rawfile/raw_file_manager.h"
19 #endif 19 #endif
20 20
  21 +#include "sherpa-onnx/csrc/file-utils.h"
21 #include "sherpa-onnx/csrc/macros.h" 22 #include "sherpa-onnx/csrc/macros.h"
22 #include "sherpa-onnx/csrc/offline-transducer-decoder.h" 23 #include "sherpa-onnx/csrc/offline-transducer-decoder.h"
23 #include "sherpa-onnx/csrc/onnx-utils.h" 24 #include "sherpa-onnx/csrc/onnx-utils.h"
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 #include "rawfile/raw_file_manager.h" 18 #include "rawfile/raw_file_manager.h"
19 #endif 19 #endif
20 20
  21 +#include "sherpa-onnx/csrc/file-utils.h"
21 #include "sherpa-onnx/csrc/macros.h" 22 #include "sherpa-onnx/csrc/macros.h"
22 #include "sherpa-onnx/csrc/onnx-utils.h" 23 #include "sherpa-onnx/csrc/onnx-utils.h"
23 #include "sherpa-onnx/csrc/session.h" 24 #include "sherpa-onnx/csrc/session.h"
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 #include "rawfile/raw_file_manager.h" 18 #include "rawfile/raw_file_manager.h"
19 #endif 19 #endif
20 20
  21 +#include "sherpa-onnx/csrc/file-utils.h"
21 #include "sherpa-onnx/csrc/macros.h" 22 #include "sherpa-onnx/csrc/macros.h"
22 #include "sherpa-onnx/csrc/onnx-utils.h" 23 #include "sherpa-onnx/csrc/onnx-utils.h"
23 #include "sherpa-onnx/csrc/session.h" 24 #include "sherpa-onnx/csrc/session.h"
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 #include "rawfile/raw_file_manager.h" 18 #include "rawfile/raw_file_manager.h"
19 #endif 19 #endif
20 20
  21 +#include "sherpa-onnx/csrc/file-utils.h"
21 #include "sherpa-onnx/csrc/macros.h" 22 #include "sherpa-onnx/csrc/macros.h"
22 #include "sherpa-onnx/csrc/onnx-utils.h" 23 #include "sherpa-onnx/csrc/onnx-utils.h"
23 #include "sherpa-onnx/csrc/session.h" 24 #include "sherpa-onnx/csrc/session.h"
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 #include "rawfile/raw_file_manager.h" 13 #include "rawfile/raw_file_manager.h"
14 #endif 14 #endif
15 15
  16 +#include "sherpa-onnx/csrc/file-utils.h"
16 #include "sherpa-onnx/csrc/macros.h" 17 #include "sherpa-onnx/csrc/macros.h"
17 #include "sherpa-onnx/csrc/onnx-utils.h" 18 #include "sherpa-onnx/csrc/onnx-utils.h"
18 #include "sherpa-onnx/csrc/session.h" 19 #include "sherpa-onnx/csrc/session.h"
@@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
20 #include "rawfile/raw_file_manager.h" 20 #include "rawfile/raw_file_manager.h"
21 #endif 21 #endif
22 22
  23 +#include "sherpa-onnx/csrc/file-utils.h"
23 #include "sherpa-onnx/csrc/macros.h" 24 #include "sherpa-onnx/csrc/macros.h"
24 #include "sherpa-onnx/csrc/onnx-utils.h" 25 #include "sherpa-onnx/csrc/onnx-utils.h"
25 #include "sherpa-onnx/csrc/session.h" 26 #include "sherpa-onnx/csrc/session.h"
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
  10 +#include "sherpa-onnx/csrc/file-utils.h"
10 #include "sherpa-onnx/csrc/onnx-utils.h" 11 #include "sherpa-onnx/csrc/onnx-utils.h"
11 #include "sherpa-onnx/csrc/session.h" 12 #include "sherpa-onnx/csrc/session.h"
12 #include "sherpa-onnx/csrc/text-utils.h" 13 #include "sherpa-onnx/csrc/text-utils.h"
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 #include "rawfile/raw_file_manager.h" 15 #include "rawfile/raw_file_manager.h"
16 #endif 16 #endif
17 17
  18 +#include "sherpa-onnx/csrc/file-utils.h"
18 #include "sherpa-onnx/csrc/macros.h" 19 #include "sherpa-onnx/csrc/macros.h"
19 #include "sherpa-onnx/csrc/onnx-utils.h" 20 #include "sherpa-onnx/csrc/onnx-utils.h"
20 #include "sherpa-onnx/csrc/session.h" 21 #include "sherpa-onnx/csrc/session.h"
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
  10 +#include "sherpa-onnx/csrc/file-utils.h"
10 #include "sherpa-onnx/csrc/onnx-utils.h" 11 #include "sherpa-onnx/csrc/onnx-utils.h"
11 #include "sherpa-onnx/csrc/session.h" 12 #include "sherpa-onnx/csrc/session.h"
12 #include "sherpa-onnx/csrc/text-utils.h" 13 #include "sherpa-onnx/csrc/text-utils.h"
@@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
23 23
24 #include "onnxruntime_cxx_api.h" // NOLINT 24 #include "onnxruntime_cxx_api.h" // NOLINT
25 #include "sherpa-onnx/csrc/cat.h" 25 #include "sherpa-onnx/csrc/cat.h"
  26 +#include "sherpa-onnx/csrc/file-utils.h"
26 #include "sherpa-onnx/csrc/macros.h" 27 #include "sherpa-onnx/csrc/macros.h"
27 #include "sherpa-onnx/csrc/online-transducer-decoder.h" 28 #include "sherpa-onnx/csrc/online-transducer-decoder.h"
28 #include "sherpa-onnx/csrc/onnx-utils.h" 29 #include "sherpa-onnx/csrc/onnx-utils.h"
@@ -22,6 +22,7 @@ @@ -22,6 +22,7 @@
22 22
23 #include "onnxruntime_cxx_api.h" // NOLINT 23 #include "onnxruntime_cxx_api.h" // NOLINT
24 #include "sherpa-onnx/csrc/cat.h" 24 #include "sherpa-onnx/csrc/cat.h"
  25 +#include "sherpa-onnx/csrc/file-utils.h"
25 #include "sherpa-onnx/csrc/macros.h" 26 #include "sherpa-onnx/csrc/macros.h"
26 #include "sherpa-onnx/csrc/online-transducer-decoder.h" 27 #include "sherpa-onnx/csrc/online-transducer-decoder.h"
27 #include "sherpa-onnx/csrc/onnx-utils.h" 28 #include "sherpa-onnx/csrc/onnx-utils.h"
@@ -51,9 +51,20 @@ void OnlineModelConfig::Register(ParseOptions *po) { @@ -51,9 +51,20 @@ void OnlineModelConfig::Register(ParseOptions *po) {
51 } 51 }
52 52
53 bool OnlineModelConfig::Validate() const { 53 bool OnlineModelConfig::Validate() const {
54 - if (num_threads < 1) {  
55 - SHERPA_ONNX_LOGE("num_threads should be > 0. Given %d", num_threads);  
56 - return false; 54 + // For RK NPU, we reinterpret num_threads:
  55 + //
  56 + // For RK3588 only
  57 + // num_threads == 1 -> Select a core randomly
  58 + // num_threads == 0 -> Use NPU core 0
  59 + // num_threads == -1 -> Use NPU core 1
  60 + // num_threads == -2 -> Use NPU core 2
  61 + // num_threads == -3 -> Use NPU core 0 and core 1
  62 + // num_threads == -4 -> Use NPU core 0, core 1, and core 2
  63 + if (provider_config.provider != "rknn") {
  64 + if (num_threads < 1) {
  65 + SHERPA_ONNX_LOGE("num_threads should be > 0. Given %d", num_threads);
  66 + return false;
  67 + }
57 } 68 }
58 69
59 if (!tokens_buf.empty() && FileExists(tokens)) { 70 if (!tokens_buf.empty() && FileExists(tokens)) {
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 #endif 18 #endif
19 19
20 #include "sherpa-onnx/csrc/cat.h" 20 #include "sherpa-onnx/csrc/cat.h"
  21 +#include "sherpa-onnx/csrc/file-utils.h"
21 #include "sherpa-onnx/csrc/macros.h" 22 #include "sherpa-onnx/csrc/macros.h"
22 #include "sherpa-onnx/csrc/onnx-utils.h" 23 #include "sherpa-onnx/csrc/onnx-utils.h"
23 #include "sherpa-onnx/csrc/session.h" 24 #include "sherpa-onnx/csrc/session.h"
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 #include "rawfile/raw_file_manager.h" 17 #include "rawfile/raw_file_manager.h"
18 #endif 18 #endif
19 19
  20 +#include "sherpa-onnx/csrc/file-utils.h"
20 #include "sherpa-onnx/csrc/macros.h" 21 #include "sherpa-onnx/csrc/macros.h"
21 #include "sherpa-onnx/csrc/onnx-utils.h" 22 #include "sherpa-onnx/csrc/onnx-utils.h"
22 #include "sherpa-onnx/csrc/session.h" 23 #include "sherpa-onnx/csrc/session.h"
1 // sherpa-onnx/csrc/online-recognizer-impl.cc 1 // sherpa-onnx/csrc/online-recognizer-impl.cc
2 // 2 //
3 -// Copyright (c) 2023 Xiaomi Corporation 3 +// Copyright (c) 2023-2025 Xiaomi Corporation
4 4
5 #include "sherpa-onnx/csrc/online-recognizer-impl.h" 5 #include "sherpa-onnx/csrc/online-recognizer-impl.h"
6 6
@@ -26,10 +26,31 @@ @@ -26,10 +26,31 @@
26 #include "sherpa-onnx/csrc/onnx-utils.h" 26 #include "sherpa-onnx/csrc/onnx-utils.h"
27 #include "sherpa-onnx/csrc/text-utils.h" 27 #include "sherpa-onnx/csrc/text-utils.h"
28 28
  29 +#if SHERPA_ONNX_ENABLE_RKNN
  30 +#include "sherpa-onnx/csrc/rknn/online-recognizer-transducer-rknn-impl.h"
  31 +#endif
  32 +
29 namespace sherpa_onnx { 33 namespace sherpa_onnx {
30 34
31 std::unique_ptr<OnlineRecognizerImpl> OnlineRecognizerImpl::Create( 35 std::unique_ptr<OnlineRecognizerImpl> OnlineRecognizerImpl::Create(
32 const OnlineRecognizerConfig &config) { 36 const OnlineRecognizerConfig &config) {
  37 + if (config.model_config.provider_config.provider == "rknn") {
  38 +#if SHERPA_ONNX_ENABLE_RKNN
  39 + // Currently, only zipformer v1 is suported for rknn
  40 + if (config.model_config.transducer.encoder.empty()) {
  41 + SHERPA_ONNX_LOGE(
  42 + "Only Zipformer transducers are currently supported by rknn. "
  43 + "Fallback to CPU");
  44 + } else {
  45 + return std::make_unique<OnlineRecognizerTransducerRknnImpl>(config);
  46 + }
  47 +#else
  48 + SHERPA_ONNX_LOGE(
  49 + "Please rebuild sherpa-onnx with -DSHERPA_ONNX_ENABLE_RKNN=ON if you "
  50 + "want to use rknn. Fallback to CPU");
  51 +#endif
  52 + }
  53 +
33 if (!config.model_config.transducer.encoder.empty()) { 54 if (!config.model_config.transducer.encoder.empty()) {
34 Ort::Env env(ORT_LOGGING_LEVEL_ERROR); 55 Ort::Env env(ORT_LOGGING_LEVEL_ERROR);
35 56
@@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
11 #include <vector> 11 #include <vector>
12 12
13 #include "onnxruntime_cxx_api.h" // NOLINT 13 #include "onnxruntime_cxx_api.h" // NOLINT
  14 +#include "sherpa-onnx/csrc/file-utils.h"
14 #include "sherpa-onnx/csrc/macros.h" 15 #include "sherpa-onnx/csrc/macros.h"
15 #include "sherpa-onnx/csrc/onnx-utils.h" 16 #include "sherpa-onnx/csrc/onnx-utils.h"
16 #include "sherpa-onnx/csrc/session.h" 17 #include "sherpa-onnx/csrc/session.h"
@@ -23,7 +23,8 @@ class OnlineStream { @@ -23,7 +23,8 @@ class OnlineStream {
23 public: 23 public:
24 explicit OnlineStream(const FeatureExtractorConfig &config = {}, 24 explicit OnlineStream(const FeatureExtractorConfig &config = {},
25 ContextGraphPtr context_graph = nullptr); 25 ContextGraphPtr context_graph = nullptr);
26 - ~OnlineStream(); 26 +
  27 + virtual ~OnlineStream();
27 28
28 /** 29 /**
29 @param sampling_rate The sampling_rate of the input waveform. If it does 30 @param sampling_rate The sampling_rate of the input waveform. If it does
@@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
18 #include <sstream> 18 #include <sstream>
19 #include <string> 19 #include <string>
20 20
  21 +#include "sherpa-onnx/csrc/file-utils.h"
21 #include "sherpa-onnx/csrc/macros.h" 22 #include "sherpa-onnx/csrc/macros.h"
22 #include "sherpa-onnx/csrc/online-conformer-transducer-model.h" 23 #include "sherpa-onnx/csrc/online-conformer-transducer-model.h"
23 #include "sherpa-onnx/csrc/online-lstm-transducer-model.h" 24 #include "sherpa-onnx/csrc/online-lstm-transducer-model.h"
@@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
25 #endif 25 #endif
26 26
27 #include "sherpa-onnx/csrc/cat.h" 27 #include "sherpa-onnx/csrc/cat.h"
  28 +#include "sherpa-onnx/csrc/file-utils.h"
28 #include "sherpa-onnx/csrc/macros.h" 29 #include "sherpa-onnx/csrc/macros.h"
29 #include "sherpa-onnx/csrc/online-transducer-decoder.h" 30 #include "sherpa-onnx/csrc/online-transducer-decoder.h"
30 #include "sherpa-onnx/csrc/onnx-utils.h" 31 #include "sherpa-onnx/csrc/onnx-utils.h"
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 #include "rawfile/raw_file_manager.h" 17 #include "rawfile/raw_file_manager.h"
18 #endif 18 #endif
19 19
  20 +#include "sherpa-onnx/csrc/file-utils.h"
20 #include "sherpa-onnx/csrc/macros.h" 21 #include "sherpa-onnx/csrc/macros.h"
21 #include "sherpa-onnx/csrc/onnx-utils.h" 22 #include "sherpa-onnx/csrc/onnx-utils.h"
22 #include "sherpa-onnx/csrc/session.h" 23 #include "sherpa-onnx/csrc/session.h"
@@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
23 23
24 #include "onnxruntime_cxx_api.h" // NOLINT 24 #include "onnxruntime_cxx_api.h" // NOLINT
25 #include "sherpa-onnx/csrc/cat.h" 25 #include "sherpa-onnx/csrc/cat.h"
  26 +#include "sherpa-onnx/csrc/file-utils.h"
26 #include "sherpa-onnx/csrc/macros.h" 27 #include "sherpa-onnx/csrc/macros.h"
27 #include "sherpa-onnx/csrc/online-transducer-decoder.h" 28 #include "sherpa-onnx/csrc/online-transducer-decoder.h"
28 #include "sherpa-onnx/csrc/onnx-utils.h" 29 #include "sherpa-onnx/csrc/onnx-utils.h"
@@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
20 #endif 20 #endif
21 21
22 #include "sherpa-onnx/csrc/cat.h" 22 #include "sherpa-onnx/csrc/cat.h"
  23 +#include "sherpa-onnx/csrc/file-utils.h"
23 #include "sherpa-onnx/csrc/macros.h" 24 #include "sherpa-onnx/csrc/macros.h"
24 #include "sherpa-onnx/csrc/onnx-utils.h" 25 #include "sherpa-onnx/csrc/onnx-utils.h"
25 #include "sherpa-onnx/csrc/session.h" 26 #include "sherpa-onnx/csrc/session.h"
@@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
25 25
26 #include "onnxruntime_cxx_api.h" // NOLINT 26 #include "onnxruntime_cxx_api.h" // NOLINT
27 #include "sherpa-onnx/csrc/cat.h" 27 #include "sherpa-onnx/csrc/cat.h"
  28 +#include "sherpa-onnx/csrc/file-utils.h"
28 #include "sherpa-onnx/csrc/macros.h" 29 #include "sherpa-onnx/csrc/macros.h"
29 #include "sherpa-onnx/csrc/online-transducer-decoder.h" 30 #include "sherpa-onnx/csrc/online-transducer-decoder.h"
30 #include "sherpa-onnx/csrc/onnx-utils.h" 31 #include "sherpa-onnx/csrc/onnx-utils.h"
@@ -13,15 +13,8 @@ @@ -13,15 +13,8 @@
13 #include <string> 13 #include <string>
14 #include <vector> 14 #include <vector>
15 15
16 -#include "sherpa-onnx/csrc/macros.h"  
17 -  
18 -#if __ANDROID_API__ >= 9  
19 -#include "android/asset_manager.h"  
20 -#include "android/asset_manager_jni.h"  
21 -#include "android/log.h"  
22 -#endif  
23 -  
24 #include "onnxruntime_cxx_api.h" // NOLINT 16 #include "onnxruntime_cxx_api.h" // NOLINT
  17 +#include "sherpa-onnx/csrc/macros.h"
25 18
26 namespace sherpa_onnx { 19 namespace sherpa_onnx {
27 20
@@ -305,63 +298,6 @@ void Print4D(const Ort::Value *v) { @@ -305,63 +298,6 @@ void Print4D(const Ort::Value *v) {
305 fprintf(stderr, "\n"); 298 fprintf(stderr, "\n");
306 } 299 }
307 300
308 -std::vector<char> ReadFile(const std::string &filename) {  
309 - std::ifstream input(filename, std::ios::binary);  
310 - std::vector<char> buffer(std::istreambuf_iterator<char>(input), {});  
311 - return buffer;  
312 -}  
313 -  
314 -#if __ANDROID_API__ >= 9  
315 -std::vector<char> ReadFile(AAssetManager *mgr, const std::string &filename) {  
316 - AAsset *asset = AAssetManager_open(mgr, filename.c_str(), AASSET_MODE_BUFFER);  
317 - if (!asset) {  
318 - __android_log_print(ANDROID_LOG_FATAL, "sherpa-onnx",  
319 - "Read binary file: Load %s failed", filename.c_str());  
320 - exit(-1);  
321 - }  
322 -  
323 - auto p = reinterpret_cast<const char *>(AAsset_getBuffer(asset));  
324 - size_t asset_length = AAsset_getLength(asset);  
325 -  
326 - std::vector<char> buffer(p, p + asset_length);  
327 - AAsset_close(asset);  
328 -  
329 - return buffer;  
330 -}  
331 -#endif  
332 -  
333 -#if __OHOS__  
334 -std::vector<char> ReadFile(NativeResourceManager *mgr,  
335 - const std::string &filename) {  
336 - std::unique_ptr<RawFile, decltype(&OH_ResourceManager_CloseRawFile)> fp(  
337 - OH_ResourceManager_OpenRawFile(mgr, filename.c_str()),  
338 - OH_ResourceManager_CloseRawFile);  
339 -  
340 - if (!fp) {  
341 - std::ostringstream os;  
342 - os << "Read file '" << filename << "' failed.";  
343 - SHERPA_ONNX_LOGE("%s", os.str().c_str());  
344 - return {};  
345 - }  
346 -  
347 - auto len = static_cast<int32_t>(OH_ResourceManager_GetRawFileSize(fp.get()));  
348 -  
349 - std::vector<char> buffer(len);  
350 -  
351 - int32_t n = OH_ResourceManager_ReadRawFile(fp.get(), buffer.data(), len);  
352 -  
353 - if (n != len) {  
354 - std::ostringstream os;  
355 - os << "Read file '" << filename << "' failed. Number of bytes read: " << n  
356 - << ". Expected bytes to read: " << len;  
357 - SHERPA_ONNX_LOGE("%s", os.str().c_str());  
358 - return {};  
359 - }  
360 -  
361 - return buffer;  
362 -}  
363 -#endif  
364 -  
365 Ort::Value Repeat(OrtAllocator *allocator, Ort::Value *cur_encoder_out, 301 Ort::Value Repeat(OrtAllocator *allocator, Ort::Value *cur_encoder_out,
366 const std::vector<int32_t> &hyps_num_split) { 302 const std::vector<int32_t> &hyps_num_split) {
367 std::vector<int64_t> cur_encoder_out_shape = 303 std::vector<int64_t> cur_encoder_out_shape =
@@ -17,15 +17,6 @@ @@ -17,15 +17,6 @@
17 #include <utility> 17 #include <utility>
18 #include <vector> 18 #include <vector>
19 19
20 -#if __ANDROID_API__ >= 9  
21 -#include "android/asset_manager.h"  
22 -#include "android/asset_manager_jni.h"  
23 -#endif  
24 -  
25 -#if __OHOS__  
26 -#include "rawfile/raw_file_manager.h"  
27 -#endif  
28 -  
29 #include "onnxruntime_cxx_api.h" // NOLINT 20 #include "onnxruntime_cxx_api.h" // NOLINT
30 21
31 namespace sherpa_onnx { 22 namespace sherpa_onnx {
@@ -101,17 +92,6 @@ void Fill(Ort::Value *tensor, T value) { @@ -101,17 +92,6 @@ void Fill(Ort::Value *tensor, T value) {
101 std::fill(p, p + n, value); 92 std::fill(p, p + n, value);
102 } 93 }
103 94
104 -std::vector<char> ReadFile(const std::string &filename);  
105 -  
106 -#if __ANDROID_API__ >= 9  
107 -std::vector<char> ReadFile(AAssetManager *mgr, const std::string &filename);  
108 -#endif  
109 -  
110 -#if __OHOS__  
111 -std::vector<char> ReadFile(NativeResourceManager *mgr,  
112 - const std::string &filename);  
113 -#endif  
114 -  
115 // TODO(fangjun): Document it 95 // TODO(fangjun): Document it
116 Ort::Value Repeat(OrtAllocator *allocator, Ort::Value *cur_encoder_out, 96 Ort::Value Repeat(OrtAllocator *allocator, Ort::Value *cur_encoder_out,
117 const std::vector<int32_t> &hyps_num_split); 97 const std::vector<int32_t> &hyps_num_split);
  1 +// sherpa-onnx/csrc/macros.h
  2 +//
  3 +// Copyright 2025 Xiaomi Corporation
  4 +
  5 +#ifndef SHERPA_ONNX_CSRC_RKNN_MACROS_H_
  6 +#define SHERPA_ONNX_CSRC_RKNN_MACROS_H_
  7 +
  8 +#include "sherpa-onnx/csrc/macros.h"
  9 +
  10 +#define SHERPA_ONNX_RKNN_CHECK(ret, msg, ...) \
  11 + do { \
  12 + if (ret != RKNN_SUCC) { \
  13 + SHERPA_ONNX_LOGE("Return code is: %d", ret); \
  14 + SHERPA_ONNX_LOGE(msg, ##__VA_ARGS__); \
  15 + SHERPA_ONNX_EXIT(-1); \
  16 + } \
  17 + } while (0)
  18 +
  19 +#endif // SHERPA_ONNX_CSRC_RKNN_MACROS_H_
  1 +// sherpa-onnx/csrc/rknn/online-recognizer-transducer-rknn-impl.h
  2 +//
  3 +// Copyright (c) 2025 Xiaomi Corporation
  4 +
  5 +#ifndef SHERPA_ONNX_CSRC_RKNN_ONLINE_RECOGNIZER_TRANSDUCER_RKNN_IMPL_H_
  6 +#define SHERPA_ONNX_CSRC_RKNN_ONLINE_RECOGNIZER_TRANSDUCER_RKNN_IMPL_H_
  7 +
  8 +#include <algorithm>
  9 +#include <memory>
  10 +#include <sstream>
  11 +#include <string>
  12 +#include <utility>
  13 +#include <vector>
  14 +
  15 +#include "sherpa-onnx/csrc/macros.h"
  16 +#include "sherpa-onnx/csrc/online-recognizer-impl.h"
  17 +#include "sherpa-onnx/csrc/online-recognizer.h"
  18 +#include "sherpa-onnx/csrc/rknn/online-stream-rknn.h"
  19 +#include "sherpa-onnx/csrc/rknn/online-transducer-greedy-search-decoder-rknn.h"
  20 +#include "sherpa-onnx/csrc/rknn/online-zipformer-transducer-model-rknn.h"
  21 +#include "sherpa-onnx/csrc/symbol-table.h"
  22 +
  23 +namespace sherpa_onnx {
  24 +
  25 +OnlineRecognizerResult Convert(const OnlineTransducerDecoderResultRknn &src,
  26 + const SymbolTable &sym_table,
  27 + float frame_shift_ms, int32_t subsampling_factor,
  28 + int32_t segment, int32_t frames_since_start) {
  29 + OnlineRecognizerResult r;
  30 + r.tokens.reserve(src.tokens.size());
  31 + r.timestamps.reserve(src.tokens.size());
  32 +
  33 + std::string text;
  34 + for (auto i : src.tokens) {
  35 + auto sym = sym_table[i];
  36 +
  37 + text.append(sym);
  38 +
  39 + if (sym.size() == 1 && (sym[0] < 0x20 || sym[0] > 0x7e)) {
  40 + // for bpe models with byte_fallback
  41 + // (but don't rewrite printable characters 0x20..0x7e,
  42 + // which collide with standard BPE units)
  43 + std::ostringstream os;
  44 + os << "<0x" << std::hex << std::uppercase
  45 + << (static_cast<int32_t>(sym[0]) & 0xff) << ">";
  46 + sym = os.str();
  47 + }
  48 +
  49 + r.tokens.push_back(std::move(sym));
  50 + }
  51 +
  52 + if (sym_table.IsByteBpe()) {
  53 + text = sym_table.DecodeByteBpe(text);
  54 + }
  55 +
  56 + r.text = std::move(text);
  57 +
  58 + float frame_shift_s = frame_shift_ms / 1000. * subsampling_factor;
  59 + for (auto t : src.timestamps) {
  60 + float time = frame_shift_s * t;
  61 + r.timestamps.push_back(time);
  62 + }
  63 +
  64 + r.segment = segment;
  65 + r.start_time = frames_since_start * frame_shift_ms / 1000.;
  66 +
  67 + return r;
  68 +}
  69 +
  70 +class OnlineRecognizerTransducerRknnImpl : public OnlineRecognizerImpl {
  71 + public:
  72 + explicit OnlineRecognizerTransducerRknnImpl(
  73 + const OnlineRecognizerConfig &config)
  74 + : OnlineRecognizerImpl(config),
  75 + config_(config),
  76 + endpoint_(config_.endpoint_config),
  77 + model_(std::make_unique<OnlineZipformerTransducerModelRknn>(
  78 + config.model_config)) {
  79 + if (!config.model_config.tokens_buf.empty()) {
  80 + sym_ = SymbolTable(config.model_config.tokens_buf, false);
  81 + } else {
  82 + /// assuming tokens_buf and tokens are guaranteed not being both empty
  83 + sym_ = SymbolTable(config.model_config.tokens, true);
  84 + }
  85 +
  86 + if (sym_.Contains("<unk>")) {
  87 + unk_id_ = sym_["<unk>"];
  88 + }
  89 +
  90 + decoder_ = std::make_unique<OnlineTransducerGreedySearchDecoderRknn>(
  91 + model_.get(), unk_id_);
  92 + }
  93 +
  94 + template <typename Manager>
  95 + explicit OnlineRecognizerTransducerRknnImpl(
  96 + Manager *mgr, const OnlineRecognizerConfig &config)
  97 + : OnlineRecognizerImpl(mgr, config),
  98 + config_(config),
  99 + endpoint_(config_.endpoint_config),
  100 + model_(
  101 + std::make_unique<OnlineZipformerTransducerModelRknn>(mgr, config)) {
  102 + // TODO(fangjun): Support Android
  103 + }
  104 +
  105 + std::unique_ptr<OnlineStream> CreateStream() const override {
  106 + auto stream = std::make_unique<OnlineStreamRknn>(config_.feat_config);
  107 + auto r = decoder_->GetEmptyResult();
  108 + stream->SetZipformerResult(std::move(r));
  109 + stream->SetZipformerEncoderStates(model_->GetEncoderInitStates());
  110 + return stream;
  111 + }
  112 +
  113 + std::unique_ptr<OnlineStream> CreateStream(
  114 + const std::string &hotwords) const override {
  115 + SHERPA_ONNX_LOGE("Hotwords for RKNN is not supported now.");
  116 + return CreateStream();
  117 + }
  118 +
  119 + bool IsReady(OnlineStream *s) const override {
  120 + return s->GetNumProcessedFrames() + model_->ChunkSize() <
  121 + s->NumFramesReady();
  122 + }
  123 +
  124 + // Warmping up engine with wp: warm_up count and max-batch-size
  125 +
  126 + void DecodeStreams(OnlineStream **ss, int32_t n) const override {
  127 + for (int32_t i = 0; i < n; ++i) {
  128 + DecodeStream(reinterpret_cast<OnlineStreamRknn *>(ss[i]));
  129 + }
  130 + }
  131 +
  132 + OnlineRecognizerResult GetResult(OnlineStream *s) const override {
  133 + OnlineTransducerDecoderResultRknn decoder_result =
  134 + reinterpret_cast<OnlineStreamRknn *>(s)->GetZipformerResult();
  135 + decoder_->StripLeadingBlanks(&decoder_result);
  136 + // TODO(fangjun): Remember to change these constants if needed
  137 + int32_t frame_shift_ms = 10;
  138 + int32_t subsampling_factor = 4;
  139 + auto r = Convert(decoder_result, sym_, frame_shift_ms, subsampling_factor,
  140 + s->GetCurrentSegment(), s->GetNumFramesSinceStart());
  141 + r.text = ApplyInverseTextNormalization(std::move(r.text));
  142 + return r;
  143 + }
  144 +
  145 + bool IsEndpoint(OnlineStream *s) const override {
  146 + if (!config_.enable_endpoint) {
  147 + return false;
  148 + }
  149 +
  150 + int32_t num_processed_frames = s->GetNumProcessedFrames();
  151 +
  152 + // frame shift is 10 milliseconds
  153 + float frame_shift_in_seconds = 0.01;
  154 +
  155 + // subsampling factor is 4
  156 + int32_t trailing_silence_frames = reinterpret_cast<OnlineStreamRknn *>(s)
  157 + ->GetZipformerResult()
  158 + .num_trailing_blanks *
  159 + 4;
  160 +
  161 + return endpoint_.IsEndpoint(num_processed_frames, trailing_silence_frames,
  162 + frame_shift_in_seconds);
  163 + }
  164 +
  165 + void Reset(OnlineStream *s) const override {
  166 + int32_t context_size = model_->ContextSize();
  167 +
  168 + {
  169 + // segment is incremented only when the last
  170 + // result is not empty, contains non-blanks and longer than context_size)
  171 + const auto &r =
  172 + reinterpret_cast<OnlineStreamRknn *>(s)->GetZipformerResult();
  173 + if (!r.tokens.empty() && r.tokens.back() != 0 &&
  174 + r.tokens.size() > context_size) {
  175 + s->GetCurrentSegment() += 1;
  176 + }
  177 + }
  178 +
  179 + // reset encoder states
  180 + // reinterpret_cast<OnlineStreamRknn*>(s)->SetZipformerEncoderStates(model_->GetEncoderInitStates());
  181 + auto r = decoder_->GetEmptyResult();
  182 + auto last_result =
  183 + reinterpret_cast<OnlineStreamRknn *>(s)->GetZipformerResult();
  184 +
  185 + // if last result is not empty, then
  186 + // preserve last tokens as the context for next result
  187 + if (static_cast<int32_t>(last_result.tokens.size()) > context_size) {
  188 + r.tokens = {last_result.tokens.end() - context_size,
  189 + last_result.tokens.end()};
  190 + }
  191 + reinterpret_cast<OnlineStreamRknn *>(s)->SetZipformerResult(std::move(r));
  192 +
  193 + // Note: We only update counters. The underlying audio samples
  194 + // are not discarded.
  195 + s->Reset();
  196 + }
  197 +
  198 + private:
  199 + void DecodeStream(OnlineStreamRknn *s) const {
  200 + int32_t chunk_size = model_->ChunkSize();
  201 + int32_t chunk_shift = model_->ChunkShift();
  202 +
  203 + int32_t feature_dim = s->FeatureDim();
  204 +
  205 + const auto num_processed_frames = s->GetNumProcessedFrames();
  206 +
  207 + std::vector<float> features =
  208 + s->GetFrames(num_processed_frames, chunk_size);
  209 + s->GetNumProcessedFrames() += chunk_shift;
  210 +
  211 + auto &states = s->GetZipformerEncoderStates();
  212 +
  213 + auto p = model_->RunEncoder(features, std::move(states));
  214 + states = std::move(p.second);
  215 +
  216 + auto &r = s->GetZipformerResult();
  217 + decoder_->Decode(std::move(p.first), &r);
  218 + }
  219 +
  220 + private:
  221 + OnlineRecognizerConfig config_;
  222 + SymbolTable sym_;
  223 + Endpoint endpoint_;
  224 + int32_t unk_id_ = -1;
  225 + std::unique_ptr<OnlineZipformerTransducerModelRknn> model_;
  226 + std::unique_ptr<OnlineTransducerGreedySearchDecoderRknn> decoder_;
  227 +};
  228 +
  229 +} // namespace sherpa_onnx
  230 +
  231 +#endif // SHERPA_ONNX_CSRC_RKNN_ONLINE_RECOGNIZER_TRANSDUCER_RKNN_IMPL_H_
  1 +// sherpa-onnx/csrc/rknn/online-stream-rknn.cc
  2 +//
  3 +// Copyright (c) 2025 Xiaomi Corporation
  4 +
  5 +#include "sherpa-onnx/csrc/rknn/online-stream-rknn.h"
  6 +
  7 +#include <utility>
  8 +#include <vector>
  9 +
  10 +namespace sherpa_onnx {
  11 +
  12 +class OnlineStreamRknn::Impl {
  13 + public:
  14 + void SetZipformerEncoderStates(std::vector<std::vector<uint8_t>> states) {
  15 + states_ = std::move(states);
  16 + }
  17 +
  18 + std::vector<std::vector<uint8_t>> &GetZipformerEncoderStates() {
  19 + return states_;
  20 + }
  21 +
  22 + void SetZipformerResult(OnlineTransducerDecoderResultRknn r) {
  23 + result_ = std::move(r);
  24 + }
  25 +
  26 + OnlineTransducerDecoderResultRknn &GetZipformerResult() { return result_; }
  27 +
  28 + private:
  29 + std::vector<std::vector<uint8_t>> states_;
  30 + OnlineTransducerDecoderResultRknn result_;
  31 +};
  32 +
  33 +OnlineStreamRknn::OnlineStreamRknn(
  34 + const FeatureExtractorConfig &config /*= {}*/,
  35 + ContextGraphPtr context_graph /*= nullptr*/)
  36 + : OnlineStream(config, context_graph), impl_(std::make_unique<Impl>()) {}
  37 +
  38 +OnlineStreamRknn::~OnlineStreamRknn() = default;
  39 +
  40 +void OnlineStreamRknn::SetZipformerEncoderStates(
  41 + std::vector<std::vector<uint8_t>> states) const {
  42 + impl_->SetZipformerEncoderStates(std::move(states));
  43 +}
  44 +
  45 +std::vector<std::vector<uint8_t>> &OnlineStreamRknn::GetZipformerEncoderStates()
  46 + const {
  47 + return impl_->GetZipformerEncoderStates();
  48 +}
  49 +
  50 +void OnlineStreamRknn::SetZipformerResult(
  51 + OnlineTransducerDecoderResultRknn r) const {
  52 + impl_->SetZipformerResult(std::move(r));
  53 +}
  54 +
  55 +OnlineTransducerDecoderResultRknn &OnlineStreamRknn::GetZipformerResult()
  56 + const {
  57 + return impl_->GetZipformerResult();
  58 +}
  59 +
  60 +} // namespace sherpa_onnx
  1 +// sherpa-onnx/csrc/rknn/online-stream-rknn.h
  2 +//
  3 +// Copyright (c) 2025 Xiaomi Corporation
  4 +#ifndef SHERPA_ONNX_CSRC_RKNN_ONLINE_STREAM_RKNN_H_
  5 +#define SHERPA_ONNX_CSRC_RKNN_ONLINE_STREAM_RKNN_H_
  6 +#include <memory>
  7 +#include <vector>
  8 +
  9 +#include "rknn_api.h" // NOLINT
  10 +#include "sherpa-onnx/csrc/online-stream.h"
  11 +#include "sherpa-onnx/csrc/rknn/online-transducer-greedy-search-decoder-rknn.h"
  12 +
  13 +namespace sherpa_onnx {
  14 +
  15 +class OnlineStreamRknn : public OnlineStream {
  16 + public:
  17 + explicit OnlineStreamRknn(const FeatureExtractorConfig &config = {},
  18 + ContextGraphPtr context_graph = nullptr);
  19 +
  20 + ~OnlineStreamRknn();
  21 +
  22 + void SetZipformerEncoderStates(
  23 + std::vector<std::vector<uint8_t>> states) const;
  24 +
  25 + std::vector<std::vector<uint8_t>> &GetZipformerEncoderStates() const;
  26 +
  27 + void SetZipformerResult(OnlineTransducerDecoderResultRknn r) const;
  28 +
  29 + OnlineTransducerDecoderResultRknn &GetZipformerResult() const;
  30 +
  31 + private:
  32 + class Impl;
  33 + std::unique_ptr<Impl> impl_;
  34 +};
  35 +
  36 +} // namespace sherpa_onnx
  37 +
  38 +#endif // SHERPA_ONNX_CSRC_RKNN_ONLINE_STREAM_RKNN_H_
  1 +// sherpa-onnx/csrc/rknn/online-transducer-greedy-search-decoder-rknn.cc
  2 +//
  3 +// Copyright (c) 2025 Xiaomi Corporation
  4 +
  5 +#include "sherpa-onnx/csrc/rknn/online-transducer-greedy-search-decoder-rknn.h"
  6 +
  7 +#include <algorithm>
  8 +#include <utility>
  9 +#include <vector>
  10 +
  11 +#include "sherpa-onnx/csrc/macros.h"
  12 +
  13 +namespace sherpa_onnx {
  14 +
  15 +OnlineTransducerDecoderResultRknn
  16 +OnlineTransducerGreedySearchDecoderRknn::GetEmptyResult() const {
  17 + int32_t context_size = model_->ContextSize();
  18 + int32_t blank_id = 0; // always 0
  19 + OnlineTransducerDecoderResultRknn r;
  20 + r.tokens.resize(context_size, -1);
  21 + r.tokens.back() = blank_id;
  22 +
  23 + return r;
  24 +}
  25 +
  26 +void OnlineTransducerGreedySearchDecoderRknn::StripLeadingBlanks(
  27 + OnlineTransducerDecoderResultRknn *r) const {
  28 + int32_t context_size = model_->ContextSize();
  29 +
  30 + auto start = r->tokens.begin() + context_size;
  31 + auto end = r->tokens.end();
  32 +
  33 + r->tokens = std::vector<int64_t>(start, end);
  34 +}
  35 +
  36 +void OnlineTransducerGreedySearchDecoderRknn::Decode(
  37 + std::vector<float> encoder_out,
  38 + OnlineTransducerDecoderResultRknn *result) const {
  39 + auto &r = result[0];
  40 + auto attr = model_->GetEncoderOutAttr();
  41 + int32_t num_frames = attr.dims[1];
  42 + int32_t encoder_out_dim = attr.dims[2];
  43 +
  44 + int32_t vocab_size = model_->VocabSize();
  45 + int32_t context_size = model_->ContextSize();
  46 +
  47 + std::vector<int64_t> decoder_input;
  48 + std::vector<float> decoder_out;
  49 +
  50 + if (r.previous_decoder_out.empty()) {
  51 + decoder_input = {r.tokens.begin() + (r.tokens.size() - context_size),
  52 + r.tokens.end()};
  53 + decoder_out = model_->RunDecoder(std::move(decoder_input));
  54 +
  55 + } else {
  56 + decoder_out = std::move(r.previous_decoder_out);
  57 + }
  58 +
  59 + const float *p_encoder_out = encoder_out.data();
  60 + for (int32_t t = 0; t != num_frames; ++t) {
  61 + auto logit = model_->RunJoiner(p_encoder_out, decoder_out.data());
  62 + p_encoder_out += encoder_out_dim;
  63 +
  64 + bool emitted = false;
  65 + if (blank_penalty_ > 0.0) {
  66 + logit[0] -= blank_penalty_; // assuming blank id is 0
  67 + }
  68 +
  69 + auto y = static_cast<int32_t>(std::distance(
  70 + logit.data(),
  71 + std::max_element(logit.data(), logit.data() + vocab_size)));
  72 + // blank id is hardcoded to 0
  73 + // also, it treats unk as blank
  74 + if (y != 0 && y != unk_id_) {
  75 + emitted = true;
  76 + r.tokens.push_back(y);
  77 + r.timestamps.push_back(t + r.frame_offset);
  78 + r.num_trailing_blanks = 0;
  79 + } else {
  80 + ++r.num_trailing_blanks;
  81 + }
  82 +
  83 + if (emitted) {
  84 + decoder_input = {r.tokens.begin() + (r.tokens.size() - context_size),
  85 + r.tokens.end()};
  86 + decoder_out = model_->RunDecoder(std::move(decoder_input));
  87 + }
  88 + }
  89 +
  90 + r.frame_offset += num_frames;
  91 + r.previous_decoder_out = std::move(decoder_out);
  92 +}
  93 +
  94 +} // namespace sherpa_onnx
  1 +// sherpa-onnx/csrc/rknn/online-transducer-greedy-search-decoder-rknn.h
  2 +//
  3 +// Copyright (c) 2025 Xiaomi Corporation
  4 +
  5 +#ifndef SHERPA_ONNX_CSRC_RKNN_ONLINE_TRANSDUCER_GREEDY_SEARCH_DECODER_RKNN_H_
  6 +#define SHERPA_ONNX_CSRC_RKNN_ONLINE_TRANSDUCER_GREEDY_SEARCH_DECODER_RKNN_H_
  7 +
  8 +#include <vector>
  9 +
  10 +#include "sherpa-onnx/csrc/rknn/online-zipformer-transducer-model-rknn.h"
  11 +
  12 +namespace sherpa_onnx {
  13 +
  14 +struct OnlineTransducerDecoderResultRknn {
  15 + /// Number of frames after subsampling we have decoded so far
  16 + int32_t frame_offset = 0;
  17 +
  18 + /// The decoded token IDs so far
  19 + std::vector<int64_t> tokens;
  20 +
  21 + /// number of trailing blank frames decoded so far
  22 + int32_t num_trailing_blanks = 0;
  23 +
  24 + /// timestamps[i] contains the output frame index where tokens[i] is decoded.
  25 + std::vector<int32_t> timestamps;
  26 +
  27 + std::vector<float> previous_decoder_out;
  28 +};
  29 +
  30 +class OnlineTransducerGreedySearchDecoderRknn {
  31 + public:
  32 + explicit OnlineTransducerGreedySearchDecoderRknn(
  33 + OnlineZipformerTransducerModelRknn *model, int32_t unk_id = 2,
  34 + float blank_penalty = 0.0)
  35 + : model_(model), unk_id_(unk_id), blank_penalty_(blank_penalty) {}
  36 +
  37 + OnlineTransducerDecoderResultRknn GetEmptyResult() const;
  38 +
  39 + void StripLeadingBlanks(OnlineTransducerDecoderResultRknn *r) const;
  40 +
  41 + void Decode(std::vector<float> encoder_out,
  42 + OnlineTransducerDecoderResultRknn *result) const;
  43 +
  44 + private:
  45 + OnlineZipformerTransducerModelRknn *model_; // Not owned
  46 + int32_t unk_id_;
  47 + float blank_penalty_;
  48 +};
  49 +
  50 +} // namespace sherpa_onnx
  51 +
  52 +#endif // SHERPA_ONNX_CSRC_RKNN_ONLINE_TRANSDUCER_GREEDY_SEARCH_DECODER_RKNN_H_
  1 +// sherpa-onnx/csrc/rknn/online-zipformer-transducer-model-rknn.cc
  2 +//
  3 +// Copyright (c) 2023 Xiaomi Corporation
  4 +
  5 +#include "sherpa-onnx/csrc/rknn/online-zipformer-transducer-model-rknn.h"
  6 +
  7 +#include <memory>
  8 +#include <sstream>
  9 +#include <string>
  10 +#include <unordered_map>
  11 +#include <utility>
  12 +#include <vector>
  13 +
  14 +#if __ANDROID_API__ >= 9
  15 +#include "android/asset_manager.h"
  16 +#include "android/asset_manager_jni.h"
  17 +#endif
  18 +
  19 +#if __OHOS__
  20 +#include "rawfile/raw_file_manager.h"
  21 +#endif
  22 +
  23 +#include "sherpa-onnx/csrc/file-utils.h"
  24 +#include "sherpa-onnx/csrc/rknn/macros.h"
  25 +#include "sherpa-onnx/csrc/text-utils.h"
  26 +
  27 +namespace sherpa_onnx {
  28 +
  29 +// chw -> hwc
  30 +static void Transpose(const float *src, int32_t n, int32_t channel,
  31 + int32_t height, int32_t width, float *dst) {
  32 + for (int32_t i = 0; i < n; ++i) {
  33 + for (int32_t h = 0; h < height; ++h) {
  34 + for (int32_t w = 0; w < width; ++w) {
  35 + for (int32_t c = 0; c < channel; ++c) {
  36 + // dst[h, w, c] = src[c, h, w]
  37 + dst[i * height * width * channel + h * width * channel + w * channel +
  38 + c] = src[i * height * width * channel + c * height * width +
  39 + h * width + w];
  40 + }
  41 + }
  42 + }
  43 + }
  44 +}
  45 +
  46 +static std::string ToString(const rknn_tensor_attr &attr) {
  47 + std::ostringstream os;
  48 + os << "{";
  49 + os << attr.index;
  50 + os << ", name: " << attr.name;
  51 + os << ", shape: (";
  52 + std::string sep;
  53 + for (int32_t i = 0; i < static_cast<int32_t>(attr.n_dims); ++i) {
  54 + os << sep << attr.dims[i];
  55 + sep = ",";
  56 + }
  57 + os << ")";
  58 + os << ", n_elems: " << attr.n_elems;
  59 + os << ", size: " << attr.size;
  60 + os << ", fmt: " << get_format_string(attr.fmt);
  61 + os << ", type: " << get_type_string(attr.type);
  62 + os << ", pass_through: " << (attr.pass_through ? "true" : "false");
  63 + os << "}";
  64 + return os.str();
  65 +}
  66 +
  67 +static std::unordered_map<std::string, std::string> Parse(
  68 + const rknn_custom_string &custom_string) {
  69 + std::unordered_map<std::string, std::string> ans;
  70 + std::vector<std::string> fields;
  71 + SplitStringToVector(custom_string.string, ";", false, &fields);
  72 +
  73 + std::vector<std::string> tmp;
  74 + for (const auto &f : fields) {
  75 + SplitStringToVector(f, "=", false, &tmp);
  76 + if (tmp.size() != 2) {
  77 + SHERPA_ONNX_LOGE("Invalid custom string %s for %s", custom_string.string,
  78 + f.c_str());
  79 + SHERPA_ONNX_EXIT(-1);
  80 + }
  81 + ans[std::move(tmp[0])] = std::move(tmp[1]);
  82 + }
  83 +
  84 + return ans;
  85 +}
  86 +
  87 +class OnlineZipformerTransducerModelRknn::Impl {
  88 + public:
  89 + ~Impl() {
  90 + auto ret = rknn_destroy(encoder_ctx_);
  91 + if (ret != RKNN_SUCC) {
  92 + SHERPA_ONNX_LOGE("Failed to destroy the encoder context");
  93 + }
  94 +
  95 + ret = rknn_destroy(decoder_ctx_);
  96 + if (ret != RKNN_SUCC) {
  97 + SHERPA_ONNX_LOGE("Failed to destroy the decoder context");
  98 + }
  99 +
  100 + ret = rknn_destroy(joiner_ctx_);
  101 + if (ret != RKNN_SUCC) {
  102 + SHERPA_ONNX_LOGE("Failed to destroy the joiner context");
  103 + }
  104 + }
  105 +
  106 + explicit Impl(const OnlineModelConfig &config) : config_(config) {
  107 + {
  108 + auto buf = ReadFile(config.transducer.encoder);
  109 + InitEncoder(buf.data(), buf.size());
  110 + }
  111 +
  112 + {
  113 + auto buf = ReadFile(config.transducer.decoder);
  114 + InitDecoder(buf.data(), buf.size());
  115 + }
  116 +
  117 + {
  118 + auto buf = ReadFile(config.transducer.joiner);
  119 + InitJoiner(buf.data(), buf.size());
  120 + }
  121 +
  122 + // Now select which core to run for RK3588
  123 + int32_t ret_encoder = RKNN_SUCC;
  124 + int32_t ret_decoder = RKNN_SUCC;
  125 + int32_t ret_joiner = RKNN_SUCC;
  126 + switch (config_.num_threads) {
  127 + case 1:
  128 + ret_encoder = rknn_set_core_mask(encoder_ctx_, RKNN_NPU_CORE_AUTO);
  129 + ret_decoder = rknn_set_core_mask(decoder_ctx_, RKNN_NPU_CORE_AUTO);
  130 + ret_joiner = rknn_set_core_mask(joiner_ctx_, RKNN_NPU_CORE_AUTO);
  131 + break;
  132 + case 0:
  133 + ret_encoder = rknn_set_core_mask(encoder_ctx_, RKNN_NPU_CORE_0);
  134 + ret_decoder = rknn_set_core_mask(decoder_ctx_, RKNN_NPU_CORE_0);
  135 + ret_joiner = rknn_set_core_mask(joiner_ctx_, RKNN_NPU_CORE_0);
  136 + break;
  137 + case -1:
  138 + ret_encoder = rknn_set_core_mask(encoder_ctx_, RKNN_NPU_CORE_1);
  139 + ret_decoder = rknn_set_core_mask(decoder_ctx_, RKNN_NPU_CORE_1);
  140 + ret_joiner = rknn_set_core_mask(joiner_ctx_, RKNN_NPU_CORE_1);
  141 + break;
  142 + case -2:
  143 + ret_encoder = rknn_set_core_mask(encoder_ctx_, RKNN_NPU_CORE_2);
  144 + ret_decoder = rknn_set_core_mask(decoder_ctx_, RKNN_NPU_CORE_2);
  145 + ret_joiner = rknn_set_core_mask(joiner_ctx_, RKNN_NPU_CORE_2);
  146 + break;
  147 + case -3:
  148 + ret_encoder = rknn_set_core_mask(encoder_ctx_, RKNN_NPU_CORE_0_1);
  149 + ret_decoder = rknn_set_core_mask(decoder_ctx_, RKNN_NPU_CORE_0_1);
  150 + ret_joiner = rknn_set_core_mask(joiner_ctx_, RKNN_NPU_CORE_0_1);
  151 + break;
  152 + case -4:
  153 + ret_encoder = rknn_set_core_mask(encoder_ctx_, RKNN_NPU_CORE_0_1_2);
  154 + ret_decoder = rknn_set_core_mask(decoder_ctx_, RKNN_NPU_CORE_0_1_2);
  155 + ret_joiner = rknn_set_core_mask(joiner_ctx_, RKNN_NPU_CORE_0_1_2);
  156 + break;
  157 + default:
  158 + SHERPA_ONNX_LOGE(
  159 + "Valid num_threads for rk npu is 1 (auto), 0 (core 0), -1 (core "
  160 + "1), -2 (core 2), -3 (core 0_1), -4 (core 0_1_2). Given: %d",
  161 + config_.num_threads);
  162 + break;
  163 + }
  164 + if (ret_encoder != RKNN_SUCC) {
  165 + SHERPA_ONNX_LOGE(
  166 + "Failed to select npu core to run encoder (You can ignore it if you "
  167 + "are not using RK3588.");
  168 + }
  169 +
  170 + if (ret_decoder != RKNN_SUCC) {
  171 + SHERPA_ONNX_LOGE(
  172 + "Failed to select npu core to run decoder (You can ignore it if you "
  173 + "are not using RK3588.");
  174 + }
  175 +
  176 + if (ret_decoder != RKNN_SUCC) {
  177 + SHERPA_ONNX_LOGE(
  178 + "Failed to select npu core to run joiner (You can ignore it if you "
  179 + "are not using RK3588.");
  180 + }
  181 + }
  182 +
  183 + // TODO(fangjun): Support Android
  184 +
  185 + std::vector<std::vector<uint8_t>> GetEncoderInitStates() const {
  186 + // encoder_input_attrs_[0] is for the feature
  187 + // encoder_input_attrs_[1:] is for states
  188 + // so we use -1 here
  189 + std::vector<std::vector<uint8_t>> states(encoder_input_attrs_.size() - 1);
  190 +
  191 + int32_t i = -1;
  192 + for (auto &attr : encoder_input_attrs_) {
  193 + i += 1;
  194 + if (i == 0) {
  195 + // skip processing the attr for features.
  196 + continue;
  197 + }
  198 +
  199 + if (attr.type == RKNN_TENSOR_FLOAT16) {
  200 + states[i - 1].resize(attr.n_elems * sizeof(float));
  201 + } else if (attr.type == RKNN_TENSOR_INT64) {
  202 + states[i - 1].resize(attr.n_elems * sizeof(int64_t));
  203 + } else {
  204 + SHERPA_ONNX_LOGE("Unsupported tensor type: %d, %s", attr.type,
  205 + get_type_string(attr.type));
  206 + SHERPA_ONNX_EXIT(-1);
  207 + }
  208 + }
  209 +
  210 + return states;
  211 + }
  212 +
  213 + std::pair<std::vector<float>, std::vector<std::vector<uint8_t>>> RunEncoder(
  214 + std::vector<float> features,
  215 + std::vector<std::vector<uint8_t>> states) const {
  216 + std::vector<rknn_input> inputs(encoder_input_attrs_.size());
  217 +
  218 + for (int32_t i = 0; i < static_cast<int32_t>(inputs.size()); ++i) {
  219 + auto &input = inputs[i];
  220 + auto &attr = encoder_input_attrs_[i];
  221 + input.index = attr.index;
  222 +
  223 + if (attr.type == RKNN_TENSOR_FLOAT16) {
  224 + input.type = RKNN_TENSOR_FLOAT32;
  225 + } else if (attr.type == RKNN_TENSOR_INT64) {
  226 + input.type = RKNN_TENSOR_INT64;
  227 + } else {
  228 + SHERPA_ONNX_LOGE("Unsupported tensor type %d, %s", attr.type,
  229 + get_type_string(attr.type));
  230 + SHERPA_ONNX_EXIT(-1);
  231 + }
  232 +
  233 + input.fmt = attr.fmt;
  234 + if (i == 0) {
  235 + input.buf = reinterpret_cast<void *>(features.data());
  236 + input.size = features.size() * sizeof(float);
  237 + } else {
  238 + input.buf = reinterpret_cast<void *>(states[i - 1].data());
  239 + input.size = states[i - 1].size();
  240 + }
  241 + }
  242 +
  243 + std::vector<float> encoder_out(encoder_output_attrs_[0].n_elems);
  244 +
  245 + // Note(fangjun): We can reuse the memory from input argument `states`
  246 + // auto next_states = GetEncoderInitStates();
  247 + auto &next_states = states;
  248 +
  249 + std::vector<rknn_output> outputs(encoder_output_attrs_.size());
  250 + for (int32_t i = 0; i < outputs.size(); ++i) {
  251 + auto &output = outputs[i];
  252 + auto &attr = encoder_output_attrs_[i];
  253 + output.index = attr.index;
  254 + output.is_prealloc = 1;
  255 +
  256 + if (attr.type == RKNN_TENSOR_FLOAT16) {
  257 + output.want_float = 1;
  258 + } else if (attr.type == RKNN_TENSOR_INT64) {
  259 + output.want_float = 0;
  260 + } else {
  261 + SHERPA_ONNX_LOGE("Unsupported tensor type %d, %s", attr.type,
  262 + get_type_string(attr.type));
  263 + SHERPA_ONNX_EXIT(-1);
  264 + }
  265 +
  266 + if (i == 0) {
  267 + output.size = encoder_out.size() * sizeof(float);
  268 + output.buf = reinterpret_cast<void *>(encoder_out.data());
  269 + } else {
  270 + output.size = next_states[i - 1].size();
  271 + output.buf = reinterpret_cast<void *>(next_states[i - 1].data());
  272 + }
  273 + }
  274 +
  275 + auto ret = rknn_inputs_set(encoder_ctx_, inputs.size(), inputs.data());
  276 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to set encoder inputs");
  277 +
  278 + ret = rknn_run(encoder_ctx_, nullptr);
  279 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to run encoder");
  280 +
  281 + ret =
  282 + rknn_outputs_get(encoder_ctx_, outputs.size(), outputs.data(), nullptr);
  283 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to get encoder output");
  284 +
  285 + for (int32_t i = 0; i < next_states.size(); ++i) {
  286 + const auto &attr = encoder_input_attrs_[i + 1];
  287 + if (attr.n_dims == 4) {
  288 + // TODO(fangjun): The transpose is copied from
  289 + // https://github.com/airockchip/rknn_model_zoo/blob/main/examples/zipformer/cpp/process.cc#L22
  290 + // I don't understand why we need to do that.
  291 + std::vector<uint8_t> dst(next_states[i].size());
  292 + int32_t n = attr.dims[0];
  293 + int32_t h = attr.dims[1];
  294 + int32_t w = attr.dims[2];
  295 + int32_t c = attr.dims[3];
  296 + Transpose(reinterpret_cast<const float *>(next_states[i].data()), n, c,
  297 + h, w, reinterpret_cast<float *>(dst.data()));
  298 + next_states[i] = std::move(dst);
  299 + }
  300 + }
  301 +
  302 + return {std::move(encoder_out), std::move(next_states)};
  303 + }
  304 +
  305 + std::vector<float> RunDecoder(std::vector<int64_t> decoder_input) const {
  306 + auto &attr = decoder_input_attrs_[0];
  307 + rknn_input input;
  308 +
  309 + input.index = 0;
  310 + input.type = RKNN_TENSOR_INT64;
  311 + input.fmt = attr.fmt;
  312 + input.buf = decoder_input.data();
  313 + input.size = decoder_input.size() * sizeof(int64_t);
  314 +
  315 + std::vector<float> decoder_out(decoder_output_attrs_[0].n_elems);
  316 + rknn_output output;
  317 + output.index = decoder_output_attrs_[0].index;
  318 + output.is_prealloc = 1;
  319 + output.want_float = 1;
  320 + output.size = decoder_out.size() * sizeof(float);
  321 + output.buf = decoder_out.data();
  322 +
  323 + auto ret = rknn_inputs_set(decoder_ctx_, 1, &input);
  324 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to set decoder inputs");
  325 +
  326 + ret = rknn_run(decoder_ctx_, nullptr);
  327 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to run decoder");
  328 +
  329 + ret = rknn_outputs_get(decoder_ctx_, 1, &output, nullptr);
  330 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to get decoder output");
  331 +
  332 + return decoder_out;
  333 + }
  334 +
  335 + std::vector<float> RunJoiner(const float *encoder_out,
  336 + const float *decoder_out) const {
  337 + std::vector<rknn_input> inputs(2);
  338 + inputs[0].index = 0;
  339 + inputs[0].type = RKNN_TENSOR_FLOAT32;
  340 + inputs[0].fmt = joiner_input_attrs_[0].fmt;
  341 + inputs[0].buf = const_cast<float *>(encoder_out);
  342 + inputs[0].size = joiner_input_attrs_[0].n_elems * sizeof(float);
  343 +
  344 + inputs[1].index = 1;
  345 + inputs[1].type = RKNN_TENSOR_FLOAT32;
  346 + inputs[1].fmt = joiner_input_attrs_[1].fmt;
  347 + inputs[1].buf = const_cast<float *>(decoder_out);
  348 + inputs[1].size = joiner_input_attrs_[1].n_elems * sizeof(float);
  349 +
  350 + std::vector<float> joiner_out(joiner_output_attrs_[0].n_elems);
  351 + rknn_output output;
  352 + output.index = joiner_output_attrs_[0].index;
  353 + output.is_prealloc = 1;
  354 + output.want_float = 1;
  355 + output.size = joiner_out.size() * sizeof(float);
  356 + output.buf = joiner_out.data();
  357 +
  358 + auto ret = rknn_inputs_set(joiner_ctx_, inputs.size(), inputs.data());
  359 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to set joiner inputs");
  360 +
  361 + ret = rknn_run(joiner_ctx_, nullptr);
  362 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to run joiner");
  363 +
  364 + ret = rknn_outputs_get(joiner_ctx_, 1, &output, nullptr);
  365 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to get joiner output");
  366 +
  367 + return joiner_out;
  368 + }
  369 +
  370 + int32_t ContextSize() const { return context_size_; }
  371 +
  372 + int32_t ChunkSize() const { return T_; }
  373 +
  374 + int32_t ChunkShift() const { return decode_chunk_len_; }
  375 +
  376 + int32_t VocabSize() const { return vocab_size_; }
  377 +
  378 + rknn_tensor_attr GetEncoderOutAttr() const {
  379 + return encoder_output_attrs_[0];
  380 + }
  381 +
  382 + private:
  383 + void InitEncoder(void *model_data, size_t model_data_length) {
  384 + auto ret =
  385 + rknn_init(&encoder_ctx_, model_data, model_data_length, 0, nullptr);
  386 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to init encoder '%s'",
  387 + config_.transducer.encoder.c_str());
  388 +
  389 + if (config_.debug) {
  390 + rknn_sdk_version v;
  391 + ret = rknn_query(encoder_ctx_, RKNN_QUERY_SDK_VERSION, &v, sizeof(v));
  392 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to get rknn sdk version");
  393 +
  394 + SHERPA_ONNX_LOGE("sdk api version: %s, driver version: %s", v.api_version,
  395 + v.drv_version);
  396 + }
  397 +
  398 + rknn_input_output_num io_num;
  399 + ret = rknn_query(encoder_ctx_, RKNN_QUERY_IN_OUT_NUM, &io_num,
  400 + sizeof(io_num));
  401 + SHERPA_ONNX_RKNN_CHECK(ret,
  402 + "Failed to get I/O information for the encoder");
  403 +
  404 + if (config_.debug) {
  405 + SHERPA_ONNX_LOGE("encoder: %d inputs, %d outputs",
  406 + static_cast<int32_t>(io_num.n_input),
  407 + static_cast<int32_t>(io_num.n_output));
  408 + }
  409 +
  410 + encoder_input_attrs_.resize(io_num.n_input);
  411 + encoder_output_attrs_.resize(io_num.n_output);
  412 +
  413 + int32_t i = 0;
  414 + for (auto &attr : encoder_input_attrs_) {
  415 + memset(&attr, 0, sizeof(attr));
  416 + attr.index = i;
  417 + ret =
  418 + rknn_query(encoder_ctx_, RKNN_QUERY_INPUT_ATTR, &attr, sizeof(attr));
  419 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to get attr for encoder input %d", i);
  420 + i += 1;
  421 + }
  422 +
  423 + if (config_.debug) {
  424 + std::ostringstream os;
  425 + std::string sep;
  426 + for (auto &attr : encoder_input_attrs_) {
  427 + os << sep << ToString(attr);
  428 + sep = "\n";
  429 + }
  430 + SHERPA_ONNX_LOGE("\n----------Encoder inputs info----------\n%s",
  431 + os.str().c_str());
  432 + }
  433 +
  434 + i = 0;
  435 + for (auto &attr : encoder_output_attrs_) {
  436 + memset(&attr, 0, sizeof(attr));
  437 + attr.index = i;
  438 + ret =
  439 + rknn_query(encoder_ctx_, RKNN_QUERY_OUTPUT_ATTR, &attr, sizeof(attr));
  440 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to get attr for encoder output %d",
  441 + i);
  442 + i += 1;
  443 + }
  444 +
  445 + if (config_.debug) {
  446 + std::ostringstream os;
  447 + std::string sep;
  448 + for (auto &attr : encoder_output_attrs_) {
  449 + os << sep << ToString(attr);
  450 + sep = "\n";
  451 + }
  452 + SHERPA_ONNX_LOGE("\n----------Encoder outputs info----------\n%s",
  453 + os.str().c_str());
  454 + }
  455 +
  456 + rknn_custom_string custom_string;
  457 + ret = rknn_query(encoder_ctx_, RKNN_QUERY_CUSTOM_STRING, &custom_string,
  458 + sizeof(custom_string));
  459 + SHERPA_ONNX_RKNN_CHECK(
  460 + ret, "Failed to read custom string from the encoder model");
  461 + if (config_.debug) {
  462 + SHERPA_ONNX_LOGE("customs string: %s", custom_string.string);
  463 + }
  464 + auto meta = Parse(custom_string);
  465 +
  466 + for (const auto &p : meta) {
  467 + SHERPA_ONNX_LOGE("%s: %s", p.first.c_str(), p.second.c_str());
  468 + }
  469 +
  470 + if (meta.count("encoder_dims")) {
  471 + SplitStringToIntegers(meta.at("encoder_dims"), ",", false,
  472 + &encoder_dims_);
  473 + }
  474 +
  475 + if (meta.count("attention_dims")) {
  476 + SplitStringToIntegers(meta.at("attention_dims"), ",", false,
  477 + &attention_dims_);
  478 + }
  479 +
  480 + if (meta.count("num_encoder_layers")) {
  481 + SplitStringToIntegers(meta.at("num_encoder_layers"), ",", false,
  482 + &num_encoder_layers_);
  483 + }
  484 +
  485 + if (meta.count("cnn_module_kernels")) {
  486 + SplitStringToIntegers(meta.at("cnn_module_kernels"), ",", false,
  487 + &cnn_module_kernels_);
  488 + }
  489 +
  490 + if (meta.count("left_context_len")) {
  491 + SplitStringToIntegers(meta.at("left_context_len"), ",", false,
  492 + &left_context_len_);
  493 + }
  494 +
  495 + if (meta.count("T")) {
  496 + T_ = atoi(meta.at("T").c_str());
  497 + }
  498 +
  499 + if (meta.count("decode_chunk_len")) {
  500 + decode_chunk_len_ = atoi(meta.at("decode_chunk_len").c_str());
  501 + }
  502 +
  503 + if (meta.count("context_size")) {
  504 + context_size_ = atoi(meta.at("context_size").c_str());
  505 + }
  506 +
  507 + if (config_.debug) {
  508 + auto print = [](const std::vector<int32_t> &v, const char *name) {
  509 + std::ostringstream os;
  510 + os << name << ": ";
  511 + for (auto i : v) {
  512 + os << i << " ";
  513 + }
  514 +#if __OHOS__
  515 + SHERPA_ONNX_LOGE("%{public}s\n", os.str().c_str());
  516 +#else
  517 + SHERPA_ONNX_LOGE("%s\n", os.str().c_str());
  518 +#endif
  519 + };
  520 + print(encoder_dims_, "encoder_dims");
  521 + print(attention_dims_, "attention_dims");
  522 + print(num_encoder_layers_, "num_encoder_layers");
  523 + print(cnn_module_kernels_, "cnn_module_kernels");
  524 + print(left_context_len_, "left_context_len");
  525 +#if __OHOS__
  526 + SHERPA_ONNX_LOGE("T: %{public}d", T_);
  527 + SHERPA_ONNX_LOGE("decode_chunk_len_: %{public}d", decode_chunk_len_);
  528 + SHERPA_ONNX_LOGE("context_size: %{public}d", context_size_);
  529 +#else
  530 + SHERPA_ONNX_LOGE("T: %d", T_);
  531 + SHERPA_ONNX_LOGE("decode_chunk_len_: %d", decode_chunk_len_);
  532 + SHERPA_ONNX_LOGE("context_size: %d", context_size_);
  533 +#endif
  534 + }
  535 + }
  536 +
  537 + void InitDecoder(void *model_data, size_t model_data_length) {
  538 + auto ret =
  539 + rknn_init(&decoder_ctx_, model_data, model_data_length, 0, nullptr);
  540 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to init decoder '%s'",
  541 + config_.transducer.decoder.c_str());
  542 +
  543 + rknn_input_output_num io_num;
  544 + ret = rknn_query(decoder_ctx_, RKNN_QUERY_IN_OUT_NUM, &io_num,
  545 + sizeof(io_num));
  546 + SHERPA_ONNX_RKNN_CHECK(ret,
  547 + "Failed to get I/O information for the decoder");
  548 +
  549 + if (io_num.n_input != 1) {
  550 + SHERPA_ONNX_LOGE("Expect only 1 decoder input. Given %d",
  551 + static_cast<int32_t>(io_num.n_input));
  552 + SHERPA_ONNX_EXIT(-1);
  553 + }
  554 +
  555 + if (io_num.n_output != 1) {
  556 + SHERPA_ONNX_LOGE("Expect only 1 decoder output. Given %d",
  557 + static_cast<int32_t>(io_num.n_output));
  558 + SHERPA_ONNX_EXIT(-1);
  559 + }
  560 +
  561 + if (config_.debug) {
  562 + SHERPA_ONNX_LOGE("decoder: %d inputs, %d outputs",
  563 + static_cast<int32_t>(io_num.n_input),
  564 + static_cast<int32_t>(io_num.n_output));
  565 + }
  566 +
  567 + decoder_input_attrs_.resize(io_num.n_input);
  568 + decoder_output_attrs_.resize(io_num.n_output);
  569 +
  570 + int32_t i = 0;
  571 + for (auto &attr : decoder_input_attrs_) {
  572 + memset(&attr, 0, sizeof(attr));
  573 + attr.index = i;
  574 + ret =
  575 + rknn_query(decoder_ctx_, RKNN_QUERY_INPUT_ATTR, &attr, sizeof(attr));
  576 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to get attr for decoder input %d", i);
  577 + i += 1;
  578 + }
  579 +
  580 + if (config_.debug) {
  581 + std::ostringstream os;
  582 + std::string sep;
  583 + for (auto &attr : decoder_input_attrs_) {
  584 + os << sep << ToString(attr);
  585 + sep = "\n";
  586 + }
  587 + SHERPA_ONNX_LOGE("\n----------Decoder inputs info----------\n%s",
  588 + os.str().c_str());
  589 + }
  590 +
  591 + if (decoder_input_attrs_[0].type != RKNN_TENSOR_INT64) {
  592 + SHERPA_ONNX_LOGE("Expect int64 for decoder input. Given: %d, %s",
  593 + decoder_input_attrs_[0].type,
  594 + get_type_string(decoder_input_attrs_[0].type));
  595 + SHERPA_ONNX_EXIT(-1);
  596 + }
  597 +
  598 + i = 0;
  599 + for (auto &attr : decoder_output_attrs_) {
  600 + memset(&attr, 0, sizeof(attr));
  601 + attr.index = i;
  602 + ret =
  603 + rknn_query(decoder_ctx_, RKNN_QUERY_OUTPUT_ATTR, &attr, sizeof(attr));
  604 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to get attr for decoder output %d",
  605 + i);
  606 + i += 1;
  607 + }
  608 +
  609 + if (config_.debug) {
  610 + std::ostringstream os;
  611 + std::string sep;
  612 + for (auto &attr : decoder_output_attrs_) {
  613 + os << sep << ToString(attr);
  614 + sep = "\n";
  615 + }
  616 + SHERPA_ONNX_LOGE("\n----------Decoder outputs info----------\n%s",
  617 + os.str().c_str());
  618 + }
  619 + }
  620 +
  621 + void InitJoiner(void *model_data, size_t model_data_length) {
  622 + auto ret =
  623 + rknn_init(&joiner_ctx_, model_data, model_data_length, 0, nullptr);
  624 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to init joiner '%s'",
  625 + config_.transducer.joiner.c_str());
  626 +
  627 + rknn_input_output_num io_num;
  628 + ret =
  629 + rknn_query(joiner_ctx_, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num));
  630 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to get I/O information for the joiner");
  631 +
  632 + if (config_.debug) {
  633 + SHERPA_ONNX_LOGE("joiner: %d inputs, %d outputs",
  634 + static_cast<int32_t>(io_num.n_input),
  635 + static_cast<int32_t>(io_num.n_output));
  636 + }
  637 +
  638 + joiner_input_attrs_.resize(io_num.n_input);
  639 + joiner_output_attrs_.resize(io_num.n_output);
  640 +
  641 + int32_t i = 0;
  642 + for (auto &attr : joiner_input_attrs_) {
  643 + memset(&attr, 0, sizeof(attr));
  644 + attr.index = i;
  645 + ret = rknn_query(joiner_ctx_, RKNN_QUERY_INPUT_ATTR, &attr, sizeof(attr));
  646 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to get attr for joiner input %d", i);
  647 + i += 1;
  648 + }
  649 +
  650 + if (config_.debug) {
  651 + std::ostringstream os;
  652 + std::string sep;
  653 + for (auto &attr : joiner_input_attrs_) {
  654 + os << sep << ToString(attr);
  655 + sep = "\n";
  656 + }
  657 + SHERPA_ONNX_LOGE("\n----------Joiner inputs info----------\n%s",
  658 + os.str().c_str());
  659 + }
  660 +
  661 + i = 0;
  662 + for (auto &attr : joiner_output_attrs_) {
  663 + memset(&attr, 0, sizeof(attr));
  664 + attr.index = i;
  665 + ret =
  666 + rknn_query(joiner_ctx_, RKNN_QUERY_OUTPUT_ATTR, &attr, sizeof(attr));
  667 + SHERPA_ONNX_RKNN_CHECK(ret, "Failed to get attr for joiner output %d", i);
  668 + i += 1;
  669 + }
  670 +
  671 + if (config_.debug) {
  672 + std::ostringstream os;
  673 + std::string sep;
  674 + for (auto &attr : joiner_output_attrs_) {
  675 + os << sep << ToString(attr);
  676 + sep = "\n";
  677 + }
  678 + SHERPA_ONNX_LOGE("\n----------Joiner outputs info----------\n%s",
  679 + os.str().c_str());
  680 + }
  681 +
  682 + vocab_size_ = joiner_output_attrs_[0].dims[1];
  683 + if (config_.debug) {
  684 + SHERPA_ONNX_LOGE("vocab_size: %d", vocab_size_);
  685 + }
  686 + }
  687 +
  688 + private:
  689 + OnlineModelConfig config_;
  690 + rknn_context encoder_ctx_ = 0;
  691 + rknn_context decoder_ctx_ = 0;
  692 + rknn_context joiner_ctx_ = 0;
  693 +
  694 + std::vector<rknn_tensor_attr> encoder_input_attrs_;
  695 + std::vector<rknn_tensor_attr> encoder_output_attrs_;
  696 +
  697 + std::vector<rknn_tensor_attr> decoder_input_attrs_;
  698 + std::vector<rknn_tensor_attr> decoder_output_attrs_;
  699 +
  700 + std::vector<rknn_tensor_attr> joiner_input_attrs_;
  701 + std::vector<rknn_tensor_attr> joiner_output_attrs_;
  702 +
  703 + std::vector<int32_t> encoder_dims_;
  704 + std::vector<int32_t> attention_dims_;
  705 + std::vector<int32_t> num_encoder_layers_;
  706 + std::vector<int32_t> cnn_module_kernels_;
  707 + std::vector<int32_t> left_context_len_;
  708 +
  709 + int32_t T_ = 0;
  710 + int32_t decode_chunk_len_ = 0;
  711 +
  712 + int32_t context_size_ = 2;
  713 + int32_t vocab_size_ = 0;
  714 +};
  715 +
  716 +OnlineZipformerTransducerModelRknn::~OnlineZipformerTransducerModelRknn() =
  717 + default;
  718 +
  719 +OnlineZipformerTransducerModelRknn::OnlineZipformerTransducerModelRknn(
  720 + const OnlineModelConfig &config)
  721 + : impl_(std::make_unique<Impl>(config)) {}
  722 +
  723 +template <typename Manager>
  724 +OnlineZipformerTransducerModelRknn::OnlineZipformerTransducerModelRknn(
  725 + Manager *mgr, const OnlineModelConfig &config)
  726 + : impl_(std::make_unique<OnlineZipformerTransducerModelRknn>(mgr, config)) {
  727 +}
  728 +
  729 +std::vector<std::vector<uint8_t>>
  730 +OnlineZipformerTransducerModelRknn::GetEncoderInitStates() const {
  731 + return impl_->GetEncoderInitStates();
  732 +}
  733 +
  734 +std::pair<std::vector<float>, std::vector<std::vector<uint8_t>>>
  735 +OnlineZipformerTransducerModelRknn::RunEncoder(
  736 + std::vector<float> features,
  737 + std::vector<std::vector<uint8_t>> states) const {
  738 + return impl_->RunEncoder(std::move(features), std::move(states));
  739 +}
  740 +
  741 +std::vector<float> OnlineZipformerTransducerModelRknn::RunDecoder(
  742 + std::vector<int64_t> decoder_input) const {
  743 + return impl_->RunDecoder(std::move(decoder_input));
  744 +}
  745 +
  746 +std::vector<float> OnlineZipformerTransducerModelRknn::RunJoiner(
  747 + const float *encoder_out, const float *decoder_out) const {
  748 + return impl_->RunJoiner(encoder_out, decoder_out);
  749 +}
  750 +
  751 +int32_t OnlineZipformerTransducerModelRknn::ContextSize() const {
  752 + return impl_->ContextSize();
  753 +}
  754 +
  755 +int32_t OnlineZipformerTransducerModelRknn::ChunkSize() const {
  756 + return impl_->ChunkSize();
  757 +}
  758 +
  759 +int32_t OnlineZipformerTransducerModelRknn::ChunkShift() const {
  760 + return impl_->ChunkShift();
  761 +}
  762 +
  763 +int32_t OnlineZipformerTransducerModelRknn::VocabSize() const {
  764 + return impl_->VocabSize();
  765 +}
  766 +
  767 +rknn_tensor_attr OnlineZipformerTransducerModelRknn::GetEncoderOutAttr() const {
  768 + return impl_->GetEncoderOutAttr();
  769 +}
  770 +
  771 +#if __ANDROID_API__ >= 9
  772 +template OnlineZipformerTransducerModelRknn::OnlineZipformerTransducerModelRknn(
  773 + AAssetManager *mgr, const OnlineModelConfig &config);
  774 +#endif
  775 +
  776 +#if __OHOS__
  777 +template OnlineZipformerTransducerModelRknn::OnlineZipformerTransducerModelRknn(
  778 + NativeResourceManager *mgr, const OnlineModelConfig &config);
  779 +#endif
  780 +
  781 +} // namespace sherpa_onnx
  1 +// sherpa-onnx/csrc/rknn/online-zipformer-transducer-model-rknn.h
  2 +//
  3 +// Copyright (c) 2025 Xiaomi Corporation
  4 +#ifndef SHERPA_ONNX_CSRC_RKNN_ONLINE_ZIPFORMER_TRANSDUCER_MODEL_RKNN_H_
  5 +#define SHERPA_ONNX_CSRC_RKNN_ONLINE_ZIPFORMER_TRANSDUCER_MODEL_RKNN_H_
  6 +
  7 +#include <memory>
  8 +#include <utility>
  9 +#include <vector>
  10 +
  11 +#include "rknn_api.h" // NOLINT
  12 +#include "sherpa-onnx/csrc/online-model-config.h"
  13 +#include "sherpa-onnx/csrc/online-transducer-model.h"
  14 +
  15 +namespace sherpa_onnx {
  16 +
  17 +// this is for zipformer v1, i.e., the folder
  18 +// pruned_transducer_statelss7_streaming from icefall
  19 +class OnlineZipformerTransducerModelRknn {
  20 + public:
  21 + ~OnlineZipformerTransducerModelRknn();
  22 +
  23 + explicit OnlineZipformerTransducerModelRknn(const OnlineModelConfig &config);
  24 +
  25 + template <typename Manager>
  26 + OnlineZipformerTransducerModelRknn(Manager *mgr,
  27 + const OnlineModelConfig &config);
  28 +
  29 + std::vector<std::vector<uint8_t>> GetEncoderInitStates() const;
  30 +
  31 + std::pair<std::vector<float>, std::vector<std::vector<uint8_t>>> RunEncoder(
  32 + std::vector<float> features,
  33 + std::vector<std::vector<uint8_t>> states) const;
  34 +
  35 + std::vector<float> RunDecoder(std::vector<int64_t> decoder_input) const;
  36 +
  37 + std::vector<float> RunJoiner(const float *encoder_out,
  38 + const float *decoder_out) const;
  39 +
  40 + int32_t ContextSize() const;
  41 +
  42 + int32_t ChunkSize() const;
  43 +
  44 + int32_t ChunkShift() const;
  45 +
  46 + int32_t VocabSize() const;
  47 +
  48 + rknn_tensor_attr GetEncoderOutAttr() const;
  49 +
  50 + private:
  51 + class Impl;
  52 + std::unique_ptr<Impl> impl_;
  53 +};
  54 +
  55 +} // namespace sherpa_onnx
  56 +
  57 +#endif // SHERPA_ONNX_CSRC_RKNN_ONLINE_ZIPFORMER_TRANSDUCER_MODEL_RKNN_H_
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 #include "rawfile/raw_file_manager.h" 17 #include "rawfile/raw_file_manager.h"
18 #endif 18 #endif
19 19
  20 +#include "sherpa-onnx/csrc/file-utils.h"
20 #include "sherpa-onnx/csrc/macros.h" 21 #include "sherpa-onnx/csrc/macros.h"
21 #include "sherpa-onnx/csrc/onnx-utils.h" 22 #include "sherpa-onnx/csrc/onnx-utils.h"
22 #include "sherpa-onnx/csrc/session.h" 23 #include "sherpa-onnx/csrc/session.h"
@@ -12,6 +12,7 @@ @@ -12,6 +12,7 @@
12 #include "rawfile/raw_file_manager.h" 12 #include "rawfile/raw_file_manager.h"
13 #endif 13 #endif
14 14
  15 +#include "sherpa-onnx/csrc/file-utils.h"
15 #include "sherpa-onnx/csrc/macros.h" 16 #include "sherpa-onnx/csrc/macros.h"
16 #include "sherpa-onnx/csrc/onnx-utils.h" 17 #include "sherpa-onnx/csrc/onnx-utils.h"
17 #include "sherpa-onnx/csrc/speaker-embedding-extractor-general-impl.h" 18 #include "sherpa-onnx/csrc/speaker-embedding-extractor-general-impl.h"
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 #include "rawfile/raw_file_manager.h" 17 #include "rawfile/raw_file_manager.h"
18 #endif 18 #endif
19 19
  20 +#include "sherpa-onnx/csrc/file-utils.h"
20 #include "sherpa-onnx/csrc/macros.h" 21 #include "sherpa-onnx/csrc/macros.h"
21 #include "sherpa-onnx/csrc/onnx-utils.h" 22 #include "sherpa-onnx/csrc/onnx-utils.h"
22 #include "sherpa-onnx/csrc/session.h" 23 #include "sherpa-onnx/csrc/session.h"
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
17 #include "rawfile/raw_file_manager.h" 17 #include "rawfile/raw_file_manager.h"
18 #endif 18 #endif
19 19
  20 +#include "sherpa-onnx/csrc/file-utils.h"
20 #include "sherpa-onnx/csrc/macros.h" 21 #include "sherpa-onnx/csrc/macros.h"
21 #include "sherpa-onnx/csrc/onnx-utils.h" 22 #include "sherpa-onnx/csrc/onnx-utils.h"
22 #include "sherpa-onnx/csrc/session.h" 23 #include "sherpa-onnx/csrc/session.h"
@@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
10 #include "android/asset_manager_jni.h" 10 #include "android/asset_manager_jni.h"
11 #endif 11 #endif
12 12
  13 +#include "sherpa-onnx/csrc/file-utils.h"
13 #include "sherpa-onnx/csrc/macros.h" 14 #include "sherpa-onnx/csrc/macros.h"
14 #include "sherpa-onnx/csrc/onnx-utils.h" 15 #include "sherpa-onnx/csrc/onnx-utils.h"
15 #include "sherpa-onnx/csrc/spoken-language-identification-whisper-impl.h" 16 #include "sherpa-onnx/csrc/spoken-language-identification-whisper-impl.h"