Skip to content

Refactor Kokoro TTS to use the new Generate API - #3363

Merged
csukuangfj merged 2 commits into
k2-fsa:masterfrom
csukuangfj:refactor-kokoro
Mar 19, 2026
Merged

csukuangfj merged 2 commits into
k2-fsa:masterfrom
csukuangfj:refactor-kokoro

Conversation

@csukuangfj

@csukuangfj csukuangfj commented Mar 19, 2026 •

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added a configurable silence scaling parameter for TTS generation.
    • Progress callbacks now provide explicit progress reporting during synthesis.
  • Refactor

    • TTS generation across all language bindings now uses a unified generation configuration object (encapsulating speaker, speed, and silence scaling) instead of separate positional parameters.

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Mar 19, 2026
@csukuangfj
csukuangfj requested a review from Copilot March 19, 2026 10:39
@coderabbitai

coderabbitai Bot commented Mar 19, 2026 •

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c4e6f293-8f2c-4e04-bca3-4cc13e3cb934

📥 Commits

Reviewing files that changed from the base of the PR and between 3055a43 and 18c73bb.

📒 Files selected for processing (2)
  • dotnet-examples/kokoro-tts-play/Program.cs
  • dotnet-examples/kokoro-tts/Program.cs

📝 Walkthrough

Walkthrough

This PR updates offline TTS generation examples across multiple language bindings (C, C++, Dart, .NET, Java, JavaScript, Pascal, Swift) to use a new GenerationConfig-based API instead of passing sid and speed parameters directly. It introduces a silenceScale parameter (defaulting to 0.2) and updates callback signatures accordingly. The core implementation is refactored to support the new config-based approach with a deprecated overload for backward compatibility.

Changes

Cohort / File(s) Summary
C API Examples
c-api-examples/kokoro-tts-en-c-api.c, c-api-examples/kokoro-tts-zh-en-c-api.c
Updated ProgressCallback signature to accept void *arg. Replaced SherpaOnnxOfflineTtsGenerate calls with SherpaOnnxOfflineTtsGenerateWithConfig by constructing SherpaOnnxGenerationConfig and setting silence_scale, sid, and speed.
C++ API Examples
cxx-api-examples/kokoro-tts-en-cxx-api.cc, cxx-api-examples/kokoro-tts-zh-en-cxx-api.cc
Replaced positional Generate(text, sid, speed) calls with Generate(text, gen_config) using a GenerationConfig containing sid, speed, and silence_scale = 0.2f.
Dart API Examples
dart-api-examples/tts/bin/kokoro-en.dart, dart-api-examples/tts/bin/kokoro-zh-en.dart
Removed lengthScale: 1 / speed from model config. Replaced tts.generate(text:, sid:, speed:) with tts.generateWithConfig(text:, config:) using OfflineTtsGenerationConfig that carries sid, speed, and silenceScale.
.NET Examples
dotnet-examples/kokoro-tts-play/Program.cs, dotnet-examples/kokoro-tts/Program.cs
Updated progress callback delegate to include an IntPtr arg parameter. Constructed OfflineTtsGenerationConfig with Sid, Speed, SilenceScale = 0.2f and switched calls to GenerateWithConfig(...), using OfflineTtsCallbackProgressWithArg.
Java API Examples
java-api-examples/NonStreamingTtsKokoroEn.java, java-api-examples/NonStreamingTtsKokoroZhEn.java
Constructed GenerationConfig with sid, speed, silenceScale = 0.2f and replaced tts.generate(text, sid, speed) with tts.generateWithConfigAndCallback(text, genConfig, callback).
Node.js Examples
nodejs-addon-examples/test_tts_non_streaming_kokoro_*.js, nodejs-examples/test-offline-tts-kokoro-*.js
Introduced sherpa_onnx.GenerationConfig objects (sid, speed, silenceScale: 0.2) and updated TTS calls to pass the config via generate/generateWithConfig instead of inline sid/speed.
Pascal API Examples
pascal-api-examples/tts/kokoro-*.pas
Adjusted generation callback signature to include Progress: cfloat and replaced positional Generate(Text, SpeakerId, Speed) with Generate(Text, GenerationConfig, ...) after initializing TSherpaOnnxGenerationConfig (SilenceScale := 0.2).
Swift API Examples
swift-api-examples/tts-kokoro-*.swift
Changed callback type to TtsProgressCallbackWithArg to include progress. Constructed SherpaOnnxGenerationConfigSwift with sid, speed, silenceScale and switched to generateWithConfig(..., config: genConfig, callback: ..., arg: ...).
Core Implementation
sherpa-onnx/csrc/offline-tts-kokoro-impl.h
Changed OfflineTtsKokoroImpl::Generate to accept GenerationConfig (replacing (sid, speed)), added debug logging of gen_config.ToString() when enabled, error-return for speed <= 0, language selection via gen_config.GetExtraString("lang"), and added Process overload with silence_scale. Kept and marked the old positional overload as [[deprecated]].

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Poem

🐰 A config's born, the examples cheer,
Speaker ID and speed held dear,
Now wrapped in structures, clean and tight,
With silence scaling set just right,
Kokoro songs in every tongue take flight! 🎵

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: refactoring Kokoro TTS examples and implementation to use a new GenerationConfig-based Generate API instead of direct parameter passing.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request streamlines the Text-to-Speech (TTS) generation process for Kokoro models by introducing a standardized GenerationConfig object. This change consolidates various generation parameters into a single, structured configuration, enhancing consistency and simplifying the API across multiple language bindings. The update affects example implementations in C, C++, Dart, C#, Java, Node.js, Pascal, and Swift, ensuring all examples leverage the new, more robust generation interface.

Highlights

  • Unified Generation API: Refactored Kokoro TTS examples across C, C++, Dart, C#, Java, Node.js, Pascal, and Swift to use a new GenerationConfig API, centralizing parameters like speaker ID, speed, and silence scale.
  • Callback Signature Update: Updated the ProgressCallback signature in C, C#, Pascal, and Swift examples to include an arg parameter, aligning with the new API design.
  • Deprecation of Old API: The previous Generate methods that directly accepted sid and speed parameters have been deprecated in favor of the new GenerationConfig based API.
  • Silence Scale Handling: Introduced silence_scale as a configurable parameter within GenerationConfig, allowing more granular control over pauses in generated audio.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
swift-api-examples/tts-kokoro-zh-en.swift (1)

31-42: Unused progress parameter in callback.

The callback signature now includes a progress parameter (third argument), but it's not being used in the callback body. Consider logging or utilizing the progress value for user feedback, similar to how the C examples print progress.

💡 Optional: Log progress
   let callback: TtsProgressCallbackWithArg = { samples, n, progress, arg in
     let o = Unmanaged<MyClass>.fromOpaque(arg!).takeUnretainedValue()
+    print("Progress: \(progress * 100)%")
     var savedSamples: [Float] = []
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@swift-api-examples/tts-kokoro-zh-en.swift` around lines 31 - 42, The
TtsProgressCallbackWithArg closure currently ignores its third parameter
progress; update the callback body (the closure assigned to callback) to use
progress (e.g., call a logging/UI method or pass it into MyClass) so callers get
feedback: extract o via
Unmanaged<MyClass>.fromOpaque(arg!).takeUnretainedValue(), then either log or
forward the progress value (e.g., o.updateProgress(progress) or o.log("progress:
\(progress)") before assembling savedSamples and calling o.playSamples(samples:
savedSamples); keep returning 1 to continue generation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@sherpa-onnx/csrc/offline-tts-kokoro-impl.h`:
- Around line 465-467: The check treating 0.2f as a sentinel causes ambiguity
because GenerationConfig::silence_scale (and the Generate() parameter) can be
explicitly set to 0.2; change the logic to distinguish "unset" from an explicit
value by either (a) switching GenerationConfig::silence_scale default to an
out-of-band sentinel (e.g., -1.0f) and update callers, then replace the if
(silence_scale == 0.2f) branch in offline-tts-kokoro-impl.h to check for the new
sentinel (e.g., silence_scale < 0.0f) and fall back to config_.silence_scale, or
(b) make silence_scale an std::optional<float> on the Generate() API and in
GenerationConfig, and use has_value() to decide whether to use the config
default; update references to config_.silence_scale and the Generate() signature
accordingly so an explicit 0.2 is honored.

---

Nitpick comments:
In `@swift-api-examples/tts-kokoro-zh-en.swift`:
- Around line 31-42: The TtsProgressCallbackWithArg closure currently ignores
its third parameter progress; update the callback body (the closure assigned to
callback) to use progress (e.g., call a logging/UI method or pass it into
MyClass) so callers get feedback: extract o via
Unmanaged<MyClass>.fromOpaque(arg!).takeUnretainedValue(), then either log or
forward the progress value (e.g., o.updateProgress(progress) or o.log("progress:
\(progress)") before assembling savedSamples and calling o.playSamples(samples:
savedSamples); keep returning 1 to continue generation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c006a582-5eff-4ad6-b2a8-872730e3c8d6

📥 Commits

Reviewing files that changed from the base of the PR and between b3624a8 and 3055a43.

📒 Files selected for processing (21)
  • c-api-examples/kokoro-tts-en-c-api.c
  • c-api-examples/kokoro-tts-zh-en-c-api.c
  • cxx-api-examples/kokoro-tts-en-cxx-api.cc
  • cxx-api-examples/kokoro-tts-zh-en-cxx-api.cc
  • dart-api-examples/tts/bin/kokoro-en.dart
  • dart-api-examples/tts/bin/kokoro-zh-en.dart
  • dotnet-examples/kokoro-tts-play/Program.cs
  • dotnet-examples/kokoro-tts/Program.cs
  • java-api-examples/NonStreamingTtsKokoroEn.java
  • java-api-examples/NonStreamingTtsKokoroZhEn.java
  • nodejs-addon-examples/test_tts_non_streaming_kokoro_en.js
  • nodejs-addon-examples/test_tts_non_streaming_kokoro_zh_en.js
  • nodejs-examples/test-offline-tts-kokoro-en.js
  • nodejs-examples/test-offline-tts-kokoro-zh-en.js
  • pascal-api-examples/tts/kokoro-en-playback.pas
  • pascal-api-examples/tts/kokoro-en.pas
  • pascal-api-examples/tts/kokoro-zh-en-playback.pas
  • pascal-api-examples/tts/kokoro-zh-en.pas
  • sherpa-onnx/csrc/offline-tts-kokoro-impl.h
  • swift-api-examples/tts-kokoro-en.swift
  • swift-api-examples/tts-kokoro-zh-en.swift

Comment on lines +465 to +467
if (silence_scale == 0.2f) {
silence_scale = config_.silence_scale;
}

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:

#!/bin/bash
# Check the default value of silence_scale in GenerationConfig
rg -n "silence_scale\s*=" sherpa-onnx/csrc/offline-tts.h -A2 -B2

# Check how other TTS implementations handle silence_scale
ast-grep --pattern 'silence_scale == $_'

Repository: k2-fsa/sherpa-onnx

Length of output: 421


🏁 Script executed:

#!/bin/bash
# Get full context around the problematic code
cat -n sherpa-onnx/csrc/offline-tts-kokoro-impl.h | sed -n '450,480p'

Repository: k2-fsa/sherpa-onnx

Length of output: 1101


🏁 Script executed:

#!/bin/bash
# Find the function containing this code to understand how silence_scale is passed
rg -n "silence_scale" sherpa-onnx/csrc/offline-tts-kokoro-impl.h -B5 -A5 | head -100

Repository: k2-fsa/sherpa-onnx

Length of output: 2923


🏁 Script executed:

#!/bin/bash
# Check if silence_scale is ever set explicitly to 0.2 anywhere in call sites
rg -n "silence_scale\s*=" sherpa-onnx/csrc/ --type cpp --type h | grep -v "0\.2" | head -20

Repository: k2-fsa/sherpa-onnx

Length of output: 804


🏁 Script executed:

#!/bin/bash
# Look for optional or sentinel value patterns used elsewhere in the codebase
rg -n "std::optional" sherpa-onnx/csrc/ | head -10

Repository: k2-fsa/sherpa-onnx

Length of output: 497


Sentinel value 0.2f creates ambiguity—user cannot explicitly set silence_scale to 0.2.

The GenerationConfig::silence_scale defaults to 0.2 and the code checks for this value as a sentinel to mean "unset/use config default." This creates an impossible situation: if a user explicitly sets silence_scale = 0.2 when calling Generate(), the code incorrectly treats it as "unset" and overrides it with config_.silence_scale.

The documentation at line 156–157 even acknowledges this pattern ("If left at 0.2, it falls back..."), but this is problematic API design. Other TTS backends in the codebase (kitten, matcha, vits) avoid this by directly using the config value without sentinel checks.

Use a different sentinel (e.g., a negative value like -1.0f or a guard value outside the valid range) or switch to std::optional<float> to properly distinguish "explicitly set" from "unset."

💡 Suggested fix using a negative sentinel

Change the default in GenerationConfig to a sentinel like -1.0f, then:

-    if (silence_scale == 0.2f) {
+    if (silence_scale < 0) {
       silence_scale = config_.silence_scale;
     }

This would require updating GenerationConfig::silence_scale default from 0.2 to -1.0f in offline-tts.h, and updating all call sites that rely on the default.

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

In `@sherpa-onnx/csrc/offline-tts-kokoro-impl.h` around lines 465 - 467, The check
treating 0.2f as a sentinel causes ambiguity because
GenerationConfig::silence_scale (and the Generate() parameter) can be explicitly
set to 0.2; change the logic to distinguish "unset" from an explicit value by
either (a) switching GenerationConfig::silence_scale default to an out-of-band
sentinel (e.g., -1.0f) and update callers, then replace the if (silence_scale ==
0.2f) branch in offline-tts-kokoro-impl.h to check for the new sentinel (e.g.,
silence_scale < 0.0f) and fall back to config_.silence_scale, or (b) make
silence_scale an std::optional<float> on the Generate() API and in
GenerationConfig, and use has_value() to decide whether to use the config
default; update references to config_.silence_scale and the Generate() signature
accordingly so an explicit 0.2 is honored.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request consistently refactors the Kokoro TTS examples and implementation across various languages to adopt a new GenerationConfig-based API, which is a good step towards a more extensible interface. My review focuses on improving code clarity in the examples and points out a potential design issue in the C++ implementation concerning how default parameter values are handled.

Comment on lines +63 to +66
SherpaOnnxGenerationConfig cfg = {0};
cfg.silence_scale = 0.2f;
cfg.sid = sid;
cfg.speed = speed;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The initialization of SherpaOnnxGenerationConfig can be made more concise and readable by using C99 designated initializers. This avoids initializing the struct to zero and then assigning members individually.

Suggested change
SherpaOnnxGenerationConfig cfg = {0};
cfg.silence_scale = 0.2f;
cfg.sid = sid;
cfg.speed = speed;
SherpaOnnxGenerationConfig cfg = {.silence_scale = 0.2f, .sid = sid, .speed = speed};

Comment on lines +61 to +64
SherpaOnnxGenerationConfig cfg = {0};
cfg.silence_scale = 0.2f;
cfg.sid = sid;
cfg.speed = speed;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The initialization of SherpaOnnxGenerationConfig can be made more concise and readable by using C99 designated initializers. This avoids initializing the struct to zero and then assigning members individually.

Suggested change
SherpaOnnxGenerationConfig cfg = {0};
cfg.silence_scale = 0.2f;
cfg.sid = sid;
cfg.speed = speed;
SherpaOnnxGenerationConfig cfg = {.silence_scale = 0.2f, .sid = sid, .speed = speed};

Comment on lines 58 to +63
int32_t sid = 0;
float speed = 1.0; // larger -> faster in speech speed
GenerationConfig gen_config;
gen_config.sid = sid;
gen_config.speed = speed;
gen_config.silence_scale = 0.2f;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The sid and speed variables are only used to initialize gen_config and are then discarded. You can make the code more direct by removing these intermediate variables and assigning the values directly to the gen_config members.

Suggested change
int32_t sid = 0;
float speed = 1.0; // larger -> faster in speech speed
GenerationConfig gen_config;
gen_config.sid = sid;
gen_config.speed = speed;
gen_config.silence_scale = 0.2f;
GenerationConfig gen_config;
gen_config.sid = 0;
gen_config.speed = 1.0; // larger -> faster in speech speed
gen_config.silence_scale = 0.2f;

Comment on lines 59 to +64
int32_t sid = 50;
float speed = 1.0; // larger -> faster in speech speed
GenerationConfig gen_config;
gen_config.sid = sid;
gen_config.speed = speed;
gen_config.silence_scale = 0.2f;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The sid and speed variables are only used to initialize gen_config and are then discarded. You can make the code more direct by removing these intermediate variables and assigning the values directly to the gen_config members.

Suggested change
int32_t sid = 50;
float speed = 1.0; // larger -> faster in speech speed
GenerationConfig gen_config;
gen_config.sid = sid;
gen_config.speed = speed;
gen_config.silence_scale = 0.2f;
GenerationConfig gen_config;
gen_config.sid = 50;
gen_config.speed = 1.0; // larger -> faster in speech speed
gen_config.silence_scale = 0.2f;

Comment on lines +41 to +43
OfflineTtsGenerationConfig genConfig = new OfflineTtsGenerationConfig();
genConfig.Sid = sid;
genConfig.Speed = speed;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

For more concise and idiomatic C# code, you can use an object initializer to set the properties of OfflineTtsGenerationConfig upon instantiation.

    var genConfig = new OfflineTtsGenerationConfig { Sid = sid, Speed = speed };

Comment on lines 39 to +44
int sid = 0;
float speed = 1.0f;
GenerationConfig genConfig = new GenerationConfig();
genConfig.setSid(sid);
genConfig.setSpeed(speed);
genConfig.setSilenceScale(0.2f);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The sid and speed variables are only used for initializing genConfig. You can simplify the code by removing these variables and setting the values directly.

Suggested change
int sid = 0;
float speed = 1.0f;
GenerationConfig genConfig = new GenerationConfig();
genConfig.setSid(sid);
genConfig.setSpeed(speed);
genConfig.setSilenceScale(0.2f);
GenerationConfig genConfig = new GenerationConfig();
genConfig.setSid(0);
genConfig.setSpeed(1.0f);
genConfig.setSilenceScale(0.2f);

Comment on lines 41 to +46
int sid = 0; // this model has 53 speakers. You can use sid in the range 0-52
float speed = 1.0f;
GenerationConfig genConfig = new GenerationConfig();
genConfig.setSid(sid);
genConfig.setSpeed(speed);
genConfig.setSilenceScale(0.2f);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The sid and speed variables are only used for initializing genConfig. You can simplify the code by removing these variables and setting the values directly. The comment for sid can be moved to clarify the direct assignment.

Suggested change
int sid = 0; // this model has 53 speakers. You can use sid in the range 0-52
float speed = 1.0f;
GenerationConfig genConfig = new GenerationConfig();
genConfig.setSid(sid);
genConfig.setSpeed(speed);
genConfig.setSilenceScale(0.2f);
// this model has 53 speakers. You can use sid in the range 0-52
GenerationConfig genConfig = new GenerationConfig();
genConfig.setSid(0);
genConfig.setSpeed(1.0f);
genConfig.setSilenceScale(0.2f);

Comment on lines +31 to +35
const generationConfig = {
sid: speakerId,
speed: speed,
silenceScale: 0.2,
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

You can use ES6 property value shorthand for speed to make the object initialization more concise.

Suggested change
const generationConfig = {
sid: speakerId,
speed: speed,
silenceScale: 0.2,
};
const generationConfig = {
sid: speakerId,
speed,
silenceScale: 0.2,
};

Comment on lines +33 to +37
const generationConfig = {
sid: speakerId,
speed: speed,
silenceScale: 0.2,
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

You can use ES6 property value shorthand for speed to make the object initialization more concise.

Suggested change
const generationConfig = {
sid: speakerId,
speed: speed,
silenceScale: 0.2,
};
const generationConfig = {
sid: speakerId,
speed,
silenceScale: 0.2,
};

Comment on lines +465 to +467
if (silence_scale == 0.2f) {
silence_scale = config_.silence_scale;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using 0.2f as a magic number to detect if silence_scale was set by the user is fragile. If a user explicitly wants to set silence_scale to 0.2f, their value will be unexpectedly overridden by config_.silence_scale. A more robust approach would be to use a sentinel value (e.g., a negative number, since scale must be non-negative) or std::optional<float> in GenerationConfig to represent an unset value. This would make the intent clearer and avoid potential bugs.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Refactors Kokoro offline TTS examples and implementation to use the new “Generate with GenerationConfig” API (and updated progress-callback signatures) across multiple language bindings.

Changes:

  • Updated Swift/Node.js/Java/.NET/Dart/C/C++/Pascal examples to construct and pass a GenerationConfig instead of (sid, speed) arguments.
  • Extended Kokoro TTS backend to accept GenerationConfig, add extra option lang, and route silence_scale through processing.
  • Kept backward compatibility by adding a deprecated overload that adapts legacy parameters into GenerationConfig.

Reviewed changes

Copilot reviewed 19 out of 21 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
swift-api-examples/tts-kokoro-zh-en.swift Migrates Swift example to generateWithConfig + progress callback w/ arg
swift-api-examples/tts-kokoro-en.swift Migrates Swift example to generateWithConfig + progress callback w/ arg
sherpa-onnx/csrc/offline-tts-kokoro-impl.h Implements Generate(text, GenerationConfig, callback), adds lang extra and silence_scale plumbing
pascal-api-examples/tts/kokoro-zh-en.pas Updates Pascal example to pass TSherpaOnnxGenerationConfig
pascal-api-examples/tts/kokoro-zh-en-playback.pas Updates Pascal playback example callback signature + config-based generation
pascal-api-examples/tts/kokoro-en.pas Updates Pascal example to pass TSherpaOnnxGenerationConfig
pascal-api-examples/tts/kokoro-en-playback.pas Updates Pascal playback example callback signature + config-based generation
nodejs-examples/test-offline-tts-kokoro-zh-en.js Switches Node.js example to generateWithConfig
nodejs-examples/test-offline-tts-kokoro-en.js Switches Node.js example to generateWithConfig
nodejs-addon-examples/test_tts_non_streaming_kokoro_zh_en.js Uses addon GenerationConfig and passes it to generate
nodejs-addon-examples/test_tts_non_streaming_kokoro_en.js Uses addon GenerationConfig and passes it to generate
java-api-examples/NonStreamingTtsKokoroZhEn.java Uses GenerationConfig and config-based generate API
java-api-examples/NonStreamingTtsKokoroEn.java Uses GenerationConfig and config-based generate API
dotnet-examples/kokoro-tts/Program.cs Migrates .NET example to config-based generation + callback-with-arg
dotnet-examples/kokoro-tts-play/Program.cs Migrates .NET playback example to config-based generation + callback-with-arg
dart-api-examples/tts/bin/kokoro-zh-en.dart Switches Dart example to OfflineTtsGenerationConfig + generateWithConfig
dart-api-examples/tts/bin/kokoro-en.dart Switches Dart example to OfflineTtsGenerationConfig + generateWithConfig
cxx-api-examples/kokoro-tts-zh-en-cxx-api.cc Updates C++ example to pass GenerationConfig
cxx-api-examples/kokoro-tts-en-cxx-api.cc Updates C++ example to pass GenerationConfig
c-api-examples/kokoro-tts-zh-en-c-api.c Updates C example to SherpaOnnxGenerationConfig + new callback signature
c-api-examples/kokoro-tts-en-c-api.c Updates C example to SherpaOnnxGenerationConfig + new callback signature

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +465 to +467
if (silence_scale == 0.2f) {
silence_scale = config_.silence_scale;
}
const std::string &_text, const GenerationConfig &gen_config,
GeneratedAudioCallback callback = nullptr) const override {
if (config_.model.debug) {
SHERPA_ONNX_LOGE("%s", gen_config.ToString().c_str());
var MyCallback = (IntPtr samples, int n, float progress) =>
OfflineTtsGenerationConfig genConfig = new OfflineTtsGenerationConfig();
genConfig.Sid = sid;
genConfig.Speed = speed;
@csukuangfj
csukuangfj merged commit ed5127c into k2-fsa:master Mar 19, 2026
23 of 27 checks passed
@csukuangfj
csukuangfj deleted the refactor-kokoro branch March 19, 2026 10:57
@coderabbitai coderabbitai Bot mentioned this pull request Mar 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants