Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 17 additions & 23 deletions .github/workflows/pascal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- master
- pascal-api
- pascal
paths:
- '.github/workflows/pascal.yaml'
Expand Down Expand Up @@ -60,18 +61,16 @@ jobs:
brew install fpc
# brew install --cask lazarus
#
- name: Install Free pascal compiler (windows)
# See https://github.com/gcarreno/setup-lazarus
- uses: gcarreno/setup-lazarus@v3.3.1
if: matrix.os == 'windows-2022'
shell: bash
run: |
choco install lazarus

ls -lh /c/lazarus/fpc/3.2.2/bin/x86_64-win64/
with:
lazarus-version: "stable"
with-cache: false

- name: FPC info
shell: bash
run: |
export PATH=/c/lazarus/fpc/3.2.2/bin/x86_64-win64:$PATH
which fpc
fpc -i

Expand Down Expand Up @@ -133,11 +132,20 @@ jobs:
cp -v ../sherpa-onnx/pascal-api/*.pas ../pascal-api-examples/vad-with-non-streaming-asr
fi

- name: Run Speech Enhancement test
- name: Run Pascal test (Cohere Transcribe)
shell: bash
run: |
export PATH=/c/lazarus/fpc/3.2.2/bin/x86_64-win64:$PATH
cd ./pascal-api-examples

pushd non-streaming-asr
./run-cohere-transcribe.sh
rm -rf sherpa-onnx-cohere-transcribe-*
echo "---"
popd

- name: Run Speech Enhancement test
shell: bash
run: |
cd ./pascal-api-examples

pushd speech-enhancement-gtcrn
Expand All @@ -163,8 +171,6 @@ jobs:
- name: Run Pascal test (TTS)
shell: bash
run: |
export PATH=/c/lazarus/fpc/3.2.2/bin/x86_64-win64:$PATH

cd ./pascal-api-examples
pushd tts

Expand Down Expand Up @@ -224,8 +230,6 @@ jobs:
- name: Run Pascal test (Non Streaming ASR)
shell: bash
run: |
export PATH=/c/lazarus/fpc/3.2.2/bin/x86_64-win64:$PATH

cd ./pascal-api-examples

pushd non-streaming-asr
Expand Down Expand Up @@ -315,8 +319,6 @@ jobs:
- name: Run Pascal test (Streaming ASR)
shell: bash
run: |
export PATH=/c/lazarus/fpc/3.2.2/bin/x86_64-win64:$PATH

cd ./pascal-api-examples

pushd streaming-asr
Expand Down Expand Up @@ -352,8 +354,6 @@ jobs:
- name: Run Pascal test (VAD test)
shell: bash
run: |
export PATH=/c/lazarus/fpc/3.2.2/bin/x86_64-win64:$PATH

cd ./pascal-api-examples

pushd vad
Expand All @@ -373,8 +373,6 @@ jobs:
- name: Run Pascal test (Speaker diarization)
shell: bash
run: |
export PATH=/c/lazarus/fpc/3.2.2/bin/x86_64-win64:$PATH

cd ./pascal-api-examples
pushd speaker-diarization

Expand All @@ -388,8 +386,6 @@ jobs:
- name: Run Pascal test (VAD + non-streaming ASR)
shell: bash
run: |
export PATH=/c/lazarus/fpc/3.2.2/bin/x86_64-win64:$PATH

cd ./pascal-api-examples

pushd vad-with-non-streaming-asr
Expand Down Expand Up @@ -421,8 +417,6 @@ jobs:
- name: Run Pascal test (Read wav test)
shell: bash
run: |
export PATH=/c/lazarus/fpc/3.2.2/bin/x86_64-win64:$PATH

cd ./pascal-api-examples

pushd read-wav
Expand Down
75 changes: 75 additions & 0 deletions pascal-api-examples/non-streaming-asr/cohere_transcribe.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{ Copyright (c) 2026 Xiaomi Corporation }

{
This file shows how to use a non-streaming Cohere Transcribe model
to decode files.

You can download the model files from
https://github.com/k2-fsa/sherpa-onnx/releases/tag/asr-models
}

program cohere_transcribe;

{$mode objfpc}

uses
sherpa_onnx,
DateUtils,
SysUtils;

var
Wave: TSherpaOnnxWave;
WaveFilename: AnsiString;

Config: TSherpaOnnxOfflineRecognizerConfig;
Recognizer: TSherpaOnnxOfflineRecognizer;
Stream: TSherpaOnnxOfflineStream;
RecognitionResult: TSherpaOnnxOfflineRecognizerResult;

Start: TDateTime;
Stop: TDateTime;

Elapsed: Single;
Duration: Single;
RealTimeFactor: Single;
begin
Initialize(Config);

Config.ModelConfig.CohereTranscribe.Encoder := './sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/encoder.int8.onnx';
Config.ModelConfig.CohereTranscribe.Decoder := './sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/decoder.int8.onnx';
Config.ModelConfig.CohereTranscribe.UsePunct := True;
Config.ModelConfig.CohereTranscribe.UseItn := True;
Config.ModelConfig.Tokens := './sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/tokens.txt';
Config.ModelConfig.Provider := 'cpu';
Config.ModelConfig.NumThreads := 1;
Config.ModelConfig.Debug := True;

WaveFilename := './sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/test_wavs/en.wav';

Wave := SherpaOnnxReadWave(WaveFilename);

Recognizer := TSherpaOnnxOfflineRecognizer.Create(Config);
Stream := Recognizer.CreateStream();
Stream.SetOption('language', 'en');
Start := Now;

Stream.AcceptWaveform(Wave.Samples, Wave.SampleRate);
Recognizer.Decode(Stream);

RecognitionResult := Recognizer.GetResult(Stream);

Stop := Now;

Elapsed := MilliSecondsBetween(Stop, Start) / 1000;
Duration := Length(Wave.Samples) / Wave.SampleRate;
RealTimeFactor := Elapsed / Duration;
Comment on lines +49 to +65

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fail fast when the input WAV cannot be read.

SherpaOnnxReadWave() returns SampleRate := 0 on failure in sherpa-onnx/pascal-api/sherpa_onnx.pas, Lines 1637-1643. Lines 56 and 64-65 then use that value immediately, so a missing/corrupt or empty en.wav turns this example into an AcceptWaveform call plus a divide-by-zero in the RTF math instead of a clear error.

💡 Proposed fix
   Wave := SherpaOnnxReadWave(WaveFilename);
+
+  if Wave.SampleRate <= 0 then
+  begin
+    WriteLn(Format('Failed to read wave: %s', [WaveFilename]));
+    Halt(1);
+  end;
+
+  if Length(Wave.Samples) = 0 then
+  begin
+    WriteLn(Format('Wave has no samples: %s', [WaveFilename]));
+    Halt(1);
+  end;
 
   Recognizer := TSherpaOnnxOfflineRecognizer.Create(Config);
   Stream := Recognizer.CreateStream();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Wave := SherpaOnnxReadWave(WaveFilename);
Recognizer := TSherpaOnnxOfflineRecognizer.Create(Config);
Stream := Recognizer.CreateStream();
Stream.SetOption('language', 'en');
Start := Now;
Stream.AcceptWaveform(Wave.Samples, Wave.SampleRate);
Recognizer.Decode(Stream);
RecognitionResult := Recognizer.GetResult(Stream);
Stop := Now;
Elapsed := MilliSecondsBetween(Stop, Start) / 1000;
Duration := Length(Wave.Samples) / Wave.SampleRate;
RealTimeFactor := Elapsed / Duration;
Wave := SherpaOnnxReadWave(WaveFilename);
if Wave.SampleRate <= 0 then
begin
WriteLn(Format('Failed to read wave: %s', [WaveFilename]));
Halt(1);
end;
if Length(Wave.Samples) = 0 then
begin
WriteLn(Format('Wave has no samples: %s', [WaveFilename]));
Halt(1);
end;
Recognizer := TSherpaOnnxOfflineRecognizer.Create(Config);
Stream := Recognizer.CreateStream();
Stream.SetOption('language', 'en');
Start := Now;
Stream.AcceptWaveform(Wave.Samples, Wave.SampleRate);
Recognizer.Decode(Stream);
RecognitionResult := Recognizer.GetResult(Stream);
Stop := Now;
Elapsed := MilliSecondsBetween(Stop, Start) / 1000;
Duration := Length(Wave.Samples) / Wave.SampleRate;
RealTimeFactor := Elapsed / Duration;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pascal-api-examples/non-streaming-asr/cohere_transcribe.pas` around lines 49
- 65, SherpaOnnxReadWave can return Wave.SampleRate = 0 on failure, but the
example proceeds to call Stream.AcceptWaveform and compute RealTimeFactor (using
Length(Wave.Samples) / Wave.SampleRate) which leads to divide-by-zero; add an
immediate check after SherpaOnnxReadWave: if Wave.SampleRate = 0 then report a
clear error (e.g., write to stderr or use the program logger) and exit/raise
before calling Stream.AcceptWaveform, Recognizer.Decode, or computing
Elapsed/RealTimeFactor so the example fails fast on missing/corrupt/empty WAV
input.


WriteLn(RecognitionResult.ToString);
WriteLn(Format('NumThreads %d', [Config.ModelConfig.NumThreads]));
WriteLn(Format('Elapsed %.3f s', [Elapsed]));
WriteLn(Format('Wave duration %.3f s', [Duration]));
WriteLn(Format('RTF = %.3f/%.3f = %.3f', [Elapsed, Duration, RealTimeFactor]));

FreeAndNil(Stream);
FreeAndNil(Recognizer);
end.
43 changes: 43 additions & 0 deletions pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash

set -ex

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
SHERPA_ONNX_DIR=$(cd $SCRIPT_DIR/../.. && pwd)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "run-cohere-transcribe.sh" 2>/dev/null

Repository: k2-fsa/sherpa-onnx

Length of output: 126


🏁 Script executed:

cat -n ./pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh

Repository: k2-fsa/sherpa-onnx

Length of output: 1874


Quote variable expansions to handle checkout paths with spaces.

Line 6 and lines 36-37 use unquoted variable expansions that will break if the repository is checked out under a path containing spaces. Line 5 in the same script already demonstrates proper quoting practices for this scenario.

💡 Proposed fix
-SHERPA_ONNX_DIR=$(cd $SCRIPT_DIR/../.. && pwd)
+SHERPA_ONNX_DIR=$(cd "$SCRIPT_DIR/../.." && pwd)
@@
 fpc \
   -dSHERPA_ONNX_USE_SHARED_LIBS \
-  -Fu$SHERPA_ONNX_DIR/sherpa-onnx/pascal-api \
-  -Fl$SHERPA_ONNX_DIR/build/install/lib \
+  "-Fu$SHERPA_ONNX_DIR/sherpa-onnx/pascal-api" \
+  "-Fl$SHERPA_ONNX_DIR/build/install/lib" \
   ./cohere_transcribe.pas
🧰 Tools
🪛 Shellcheck (0.11.0)

[info] 6-6: Double quote to prevent globbing and word splitting.

(SC2086)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh` at line 6,
The unquoted variable expansions for SHERPA_ONNX_DIR and other uses of
SCRIPT_DIR (lines showing SHERPA_ONNX_DIR=$(cd $SCRIPT_DIR/../.. && pwd) and the
expansions at lines 36-37) will break on paths with spaces; update these to use
quoted expansions (e.g., "$SCRIPT_DIR") wherever SCRIPT_DIR or SHERPA_ONNX_DIR
is expanded, and ensure the subshell cd uses the quoted path so the computed
SHERPA_ONNX_DIR is correct even when the repo is checked out under a path with
spaces.


echo "SHERPA_ONNX_DIR: $SHERPA_ONNX_DIR"

if [[ ! -f ../../build/install/lib/libsherpa-onnx-c-api.dylib && ! -f ../../build/install/lib/libsherpa-onnx-c-api.so && ! -f ../../build/install/lib/sherpa-onnx-c-api.dll ]]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's locate and examine the file
fd -t f "run-cohere-transcribe.sh" | head -5

Repository: k2-fsa/sherpa-onnx

Length of output: 124


🏁 Script executed:

# Read the specific file to see the actual content
if [ -f "pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh" ]; then
  cat -n "pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh"
fi

Repository: k2-fsa/sherpa-onnx

Length of output: 1874


🏁 Script executed:

# Also check if there are similar scripts to understand the pattern
fd -t f "run-.*\.sh$" | grep -E "(non-streaming|streaming)" | head -10

Repository: k2-fsa/sherpa-onnx

Length of output: 616


🏁 Script executed:

# Look for C API examples in other languages
fd -t f "run-.*\.sh$" | xargs grep -l "sherpa-onnx-c-api" | head -5

Repository: k2-fsa/sherpa-onnx

Length of output: 358


🏁 Script executed:

# Check C examples specifically
fd -t f "run-.*\.sh$" c-api-examples/ 2>/dev/null | head -5

Repository: k2-fsa/sherpa-onnx

Length of output: 44


🏁 Script executed:

# Look at another example of how library paths are handled
fd -t f "run-.*\.sh$" c-api-examples/ 2>/dev/null -exec grep -A 5 "export.*LIBRARY_PATH" {} + | head -30

Repository: k2-fsa/sherpa-onnx

Length of output: 44


🏁 Script executed:

# Search for any case statements or Windows-specific handling in scripts
rg "MINGW|MSYS|CYGWIN|uname" --type sh

Repository: k2-fsa/sherpa-onnx

Length of output: 44


🏁 Script executed:

# Check if any scripts set PATH for libraries
rg "export PATH.*lib" --type sh

Repository: k2-fsa/sherpa-onnx

Length of output: 44


🏁 Script executed:

# Look at all pascal examples to see if they have similar issues
fd -t f "run-.*\.sh$" pascal-api-examples/ -exec cat -n {} + | grep -A 10 -B 2 "LIBRARY_PATH"

Repository: k2-fsa/sherpa-onnx

Length of output: 292


🏁 Script executed:

# Look for PowerShell scripts or Windows batch files
fd -t f "\.(ps1|bat|cmd)$"

Repository: k2-fsa/sherpa-onnx

Length of output: 780


🏁 Script executed:

# Read the pascal examples to see the pattern
cat pascal-api-examples/non-streaming-asr/run-dolphin-ctc.sh

Repository: k2-fsa/sherpa-onnx

Length of output: 1504


🏁 Script executed:

# Check if there's documentation about Windows support
fd -t f "README|WINDOWS|readme" | head -3 | xargs cat 2>/dev/null | head -50

Repository: k2-fsa/sherpa-onnx

Length of output: 2276


Add PATH export for Windows DLL discovery.

Line 10 checks for sherpa-onnx-c-api.dll, but lines 40-41 only set LD_LIBRARY_PATH and DYLD_LIBRARY_PATH. On Windows, the executable won't find the DLL at runtime without PATH being set. This is a recurring pattern across all pascal example scripts.

Proposed fix
-export LD_LIBRARY_PATH=$SHERPA_ONNX_DIR/build/install/lib:$LD_LIBRARY_PATH
-export DYLD_LIBRARY_PATH=$SHERPA_ONNX_DIR/build/install/lib:$DYLD_LIBRARY_PATH
+case "$(uname -s)" in
+  Darwin*)
+    export DYLD_LIBRARY_PATH="$SHERPA_ONNX_DIR/build/install/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}"
+    ;;
+  MINGW*|MSYS*|CYGWIN*)
+    export PATH="$SHERPA_ONNX_DIR/build/install/lib:$PATH"
+    ;;
+  *)
+    export LD_LIBRARY_PATH="$SHERPA_ONNX_DIR/build/install/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
+    ;;
+esac
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pascal-api-examples/non-streaming-asr/run-cohere-transcribe.sh` at line 10,
The script checks for sherpa-onnx-c-api.dll but never updates PATH for Windows
DLL resolution; update run-cohere-transcribe.sh to export PATH to include the
native lib dir (../../build/install/lib) when setting LD_LIBRARY_PATH and
DYLD_LIBRARY_PATH so Windows processes can find sherpa-onnx-c-api.dll at
runtime—modify the section that sets LD_LIBRARY_PATH and DYLD_LIBRARY_PATH to
also prepend or append the same directory to PATH when the DLL file
(sherpa-onnx-c-api.dll) is present.

mkdir -p ../../build
pushd ../../build
cmake \
-DCMAKE_INSTALL_PREFIX=./install \
-DSHERPA_ONNX_ENABLE_PYTHON=OFF \
-DSHERPA_ONNX_ENABLE_TESTS=OFF \
-DSHERPA_ONNX_ENABLE_CHECK=OFF \
-DBUILD_SHARED_LIBS=ON \
-DSHERPA_ONNX_ENABLE_PORTAUDIO=OFF \
..

cmake --build . --target install --config Release
ls -lh lib
popd
fi

if [ ! -f ./sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01/encoder.int8.onnx ]; then
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
tar xvf sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
rm sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01.tar.bz2
ls -lh sherpa-onnx-cohere-transcribe-14-lang-int8-2026-04-01
fi

fpc \
-dSHERPA_ONNX_USE_SHARED_LIBS \
-Fu$SHERPA_ONNX_DIR/sherpa-onnx/pascal-api \
-Fl$SHERPA_ONNX_DIR/build/install/lib \
./cohere_transcribe.pas

export LD_LIBRARY_PATH=$SHERPA_ONNX_DIR/build/install/lib:$LD_LIBRARY_PATH
export DYLD_LIBRARY_PATH=$SHERPA_ONNX_DIR/build/install/lib:$DYLD_LIBRARY_PATH

./cohere_transcribe
2 changes: 1 addition & 1 deletion sherpa-onnx/csrc/session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Ort::SessionOptions GetSessionOptionsImpl(
}

if (config.find("ProfilingFilePrefix") != config.end()) {
sess_opts.EnableProfiling(config["ProfilingFilePrefix"].c_str());
sess_opts.EnableProfiling(SHERPA_ONNX_TO_ORT_PATH(config["ProfilingFilePrefix"]));
config.erase("ProfilingFilePrefix");
}

Expand Down
Loading
Loading