The C++ Basic TTS Sample
The C++ TTS sample, nvigi.basic.tts.cxx, demonstrates text-to-speech synthesis using the NVIGI SDK with modern C++ interfaces. It uses the Chatterbox TTS plugin and showcases speaker-embedding voice cloning, real-time audio playback, and both synchronous and asynchronous generation modes with support for multiple backends.
NOTE: This sample supports multiple backends (D3D12, CUDA, and Vulkan), allowing it to run on various hardware configurations.
For the full Chatterbox API and behavior reference, see the TTS Chatterbox Programming Guide.
Features
Voice Cloning: Use any voice via a speaker embedding JSON
Real-Time Playback: Play generated audio in real-time using DirectSound (Windows)
WAV File Output: Save generated speech to WAV files
Async/Polling API: Non-blocking operations perfect for game loops
Multiple Backends: D3D12, CUDA, or Vulkan backends
Two Model Types: Chatterbox Turbo (English) and Chatterbox Multilingual (23 languages)
Download Required Models
The TTS sample requires one of the following Chatterbox models:
Plugin |
Model Name |
GUID |
|---|---|---|
nvigi.plugin.tts.chatterbox-ggml.* |
Chatterbox Turbo (English) |
019BD494-0D97-7223-B9D5-C9286933B8B7 |
nvigi.plugin.tts.chatterbox-ggml.* |
Chatterbox Multilingual (23 langs) |
A60EB5CF-9551-4B86-865B-CDC3CDBE61C4 |
Important: You also need a speaker embedding JSON file. The SDK test data includes sample embeddings in <SDK_TEST>/nvigi.tts/chatterbox/spk_emb/. Turbo speakers (e.g. aaron_turbo.json) must be used with the Turbo model, and multilingual speakers (e.g. french.json) with the Multilingual model — mismatches are rejected at instance creation.
See the top-level documentation that shipped with your development pack for information on how to download these models and test data.
These instructions use the following path placeholders, which refer to locations that differ between a binary developer pack and a GitHub source tree:
<SDK_ROOT>: the root of the SDK Plugins tree, which contains thebindirectory for the SDK.<SDK_MODELS>: the root of the models tree for the SDK plugins, normallydata/nvigi.models<SDK_TEST>: the root of the test data tree for the SDK plugins, normallydata/nvigi.test<SDK_PLATFORM>: the target CPU architecture. See Platform Support for information on supported platforms.
How to Use the TTS Sample
Basic Speech Generation
Open a command prompt in
<SDK_ROOT>Run the command:
bin\<SDK_PLATFORM>\<Configuration>\nvigi.basic.tts.cxx.exe --models <SDK_MODELS> --sdk bin\<SDK_PLATFORM>\<Configuration> --speaker <SDK_TEST>/nvigi.tts/chatterbox/spk_emb/aaron_turbo.json
In a standard layout binary development pack or GitHub source tree:
bin\<SDK_PLATFORM>\<Configuration>\nvigi.basic.tts.cxx.exe --models data/nvigi.models --sdk bin\<SDK_PLATFORM>\<Configuration> --speaker data/nvigi.test/nvigi.tts/chatterbox/spk_emb/aaron_turbo.json
The sample will generate speech for the default text and save it to
output.wavYou can play the generated WAV file to hear the synthesized speech
Real-Time Playback Mode
To hear the generated speech in real-time as it’s being generated:
bin\<SDK_PLATFORM>\<Configuration>\nvigi.basic.tts.cxx.exe --models data/nvigi.models --sdk bin\<SDK_PLATFORM>\<Configuration> --speaker data/nvigi.test/nvigi.tts/chatterbox/spk_emb/aaron_turbo.json --play
Async Mode (Non-Blocking)
For game integration or when you need to continue other processing:
bin\<SDK_PLATFORM>\<Configuration>\nvigi.basic.tts.cxx.exe --models data/nvigi.models --sdk bin\<SDK_PLATFORM>\<Configuration> --speaker data/nvigi.test/nvigi.tts/chatterbox/spk_emb/aaron_turbo.json --async --play
Command Line Options
Usage: nvigi.basic.tts.cxx [options]
--sdk sdk location, if none provided assuming exe location
--plugin plugin location, if none provided assuming sdk location
-m, --models model repo location (REQUIRED)
-t, --threads number of threads (default: 8)
--backend backend to use - d3d12, cuda, vulkan (default: d3d12)
--guid TTS model guid in registry format, in quotes (default: "{019BD494-0D97-7223-B9D5-C9286933B8B7}")
--vram the amount of vram to use in MB (default: 4096)
--log-level logging level 0-2 (default: 0)
--text text to synthesize (default: "Hello! This is a test of the text to speech system.")
--speaker path to speaker embedding JSON (REQUIRED)
--output output WAV file path (default: output.wav)
--multilingual use the multilingual model (default: turbo)
--language language code for the multilingual model (en, fr, zh, ja, ko, ...) (default: en)
--async use async mode (polled, non-blocking)
--play play audio in real-time using DirectSound
--print-system-info print system information
NOTE: In PowerShell, always quote the
--guidvalue (e.g."{A60EB5CF-9551-4B86-865B-CDC3CDBE61C4}"); an unquoted{...}is parsed as a script block.
Examples
Generate speech with custom text:
bin\<SDK_PLATFORM>\<Configuration>\nvigi.basic.tts.cxx.exe --models data/nvigi.models --sdk bin\<SDK_PLATFORM>\<Configuration> --speaker data/nvigi.test/nvigi.tts/chatterbox/spk_emb/aaron_turbo.json --text "Welcome to the NVIGI SDK text to speech system."
Use a different voice:
bin\<SDK_PLATFORM>\<Configuration>\nvigi.basic.tts.cxx.exe --models data/nvigi.models --sdk bin\<SDK_PLATFORM>\<Configuration> --speaker data/nvigi.test/nvigi.tts/chatterbox/spk_emb/lucy_turbo.json --text "Hello world!"
Use Vulkan backend:
bin\<SDK_PLATFORM>\<Configuration>\nvigi.basic.tts.cxx.exe --models data/nvigi.models --sdk bin\<SDK_PLATFORM>\<Configuration> --speaker data/nvigi.test/nvigi.tts/chatterbox/spk_emb/aaron_turbo.json --backend vulkan
Use CUDA backend:
bin\<SDK_PLATFORM>\<Configuration>\nvigi.basic.tts.cxx.exe --models data/nvigi.models --sdk bin\<SDK_PLATFORM>\<Configuration> --speaker data/nvigi.test/nvigi.tts/chatterbox/spk_emb/aaron_turbo.json --backend cuda
Multilingual model (French):
The multilingual model requires the multilingual GUID, --multilingual, a --language code, and a matching multilingual speaker JSON. The default --vram 4096 budget is sufficient (Multilingual requires ~3072 MB).
bin\<SDK_PLATFORM>\<Configuration>\nvigi.basic.tts.cxx.exe --models data/nvigi.models --sdk bin\<SDK_PLATFORM>\<Configuration> --guid "{A60EB5CF-9551-4B86-865B-CDC3CDBE61C4}" --multilingual --language fr --speaker data/nvigi.test/nvigi.tts/chatterbox/spk_emb/french.json --text "Bonjour, ceci est un test."
Save to custom output file:
bin\<SDK_PLATFORM>\<Configuration>\nvigi.basic.tts.cxx.exe --models data/nvigi.models --sdk bin\<SDK_PLATFORM>\<Configuration> --speaker data/nvigi.test/nvigi.tts/chatterbox/spk_emb/aaron_turbo.json --output my_speech.wav
Audio Format
The generated audio uses the following format:
Sample Rate: 24000 Hz (24 kHz)
Bit Depth: 16-bit PCM
Channels: Mono
API Patterns Demonstrated
Synchronous (Blocking) Generation
The sample demonstrates a simple blocking pattern where generation blocks until complete:
instance->generate(
text,
speaker_path,
config,
[&wav_writer](const int16_t* audio, size_t samples, ExecutionState state) -> ExecutionState {
if (state == ExecutionState::DataPending || state == ExecutionState::Done) {
// Write audio chunk to file
wav_writer.write_samples(audio, samples);
// Optionally play in real-time
AudioPlayer::play_audio(audio, samples);
}
return state; // Continue
}
);
Asynchronous (Non-Blocking) Generation
The sample also demonstrates a polling-based async pattern perfect for game loops:
auto op = instance->generate_async(text, speaker_path, config);
// Game loop
while (!op.is_complete()) {
// Try to get results (non-blocking)
if (auto result = op.try_get_results()) {
if (!result->audio.empty()) {
// Write audio chunk to file
wav_writer.write_samples(result->audio.data(), result->audio.size());
// Play in real-time
AudioPlayer::play_audio(result->audio.data(), result->audio.size());
if (result->state == ExecutionState::Done) {
break;
}
}
}
// Continue game logic
render_frame();
update_physics();
process_input();
// Small sleep to avoid busy-wait
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
Voice Cloning
Voice cloning is achieved using speaker embedding JSON files. These files contain the speaker conditioning data for the voice you want to reproduce. The SDK test data includes several sample voices in <SDK_TEST>/nvigi.tts/chatterbox/spk_emb/:
Turbo (English):
aaron_turbo.json,lucy_turbo.jsonMultilingual (per-language):
french.json,german.json,spanish.json,chinese.json,japanese.json, … and additional voices such asethan_multilingual.json,meera_multilingual.json.
To use a different voice, change the --speaker parameter to point to a different embedding JSON. Multilingual voices require a multilingual speaker JSON (not interchangeable with Turbo speakers).
To clone your own voice, extract a speaker embedding from a short reference recording using the bundled toolkit at data/nvigi.test/nvigi.tts/chatterbox/voice_cloning/ (run setup_venv.ps1, then get_voice_embeddings.py). See Creating Custom Speaker Embeddings in the programming guide.
IMPORTANT: The speaker JSON must match the selected model. A Turbo speaker with
--multilingual(or a multilingual speaker without it) is rejected withkResultInvalidParameterat instance creation.
Model Selection: Turbo vs Multilingual
Turbo (default, GUID
{019BD494-...}): English-only, ~2x faster, supports paralinguistic tags ([laugh],[sigh],[gasp], …).--languageand CFG weight are ignored.Multilingual (
--multilingual, GUID{A60EB5CF-...}): 23 languages with always-on CFG-based speech pacing and language-specific preprocessing.--languageis required. Does not support paralinguistic tags.
See the Model Feature Comparison for the full breakdown.
Troubleshooting
“Failed to create TTS instance”
Verify the model GUID exists in your models directory
Check that you have sufficient VRAM. Multilingual needs ~3072 MB; if
--vramis set below the model’s declared requirement the model is filtered out and creation fails. The default--vram 4096is sufficient for both models.Ensure the backend is properly installed (e.g., D3D12 requires Windows 10+)
Speaker / model mismatch
A Turbo speaker JSON used with
--multilingual(or a multilingual speaker used without it) is rejected. Use a speaker JSON that matches the selected model.
Missing speaker JSON
Verify the path to the speaker JSON is correct
Check that the test data has been downloaded
Use an absolute path if relative paths aren’t working
No audio playback with --play
Real-time playback only works on Windows with DirectSound
Check that your audio output device is working
Try without
--playand verify the WAV file is generated correctly
Out of memory errors
Close other GPU-intensive applications
Try a smaller text input
Note: reducing
--vrambelow a model’s requirement will prevent it from loading
Poor audio quality
Provide complete, grammatically correct sentences with standard punctuation (see the programming guide’s input-quality guidance)
For the multilingual model, ensure
--languagematches your textVery short inputs (1-2 words) are more likely to produce artifacts
Programming Notes
This sample demonstrates:
Modern C++ wrapper interfaces (
nvigi::tts::Instance)Blocking generation with streaming callbacks
Non-blocking async operations with polling (perfect for games)
Real-time audio playback using DirectSound
WAV file writing with proper headers
Builder pattern for runtime configuration
RAII-based resource management
std::expectedfor error handling
Building the Sample
The sample is built as part of the SDK build process. For full build instructions, see Building and Debugging. After building, stage the binaries:
copy_sdk_binaries.bat [-x64|-arm64] [Release|Debug|Production]
This ensures all DLLs and the executable are in the same directory (bin\<SDK_PLATFORM>\<Configuration>, where <SDK_PLATFORM> is the target CPU architecture and
Run in Debugger
For the general procedure and background, see the Building and Debugging guide. The settings specific to this sample are:
Property |
Value |
|---|---|
VS Project |
|
Command |
|
Command Arguments |
|
Working Directory |
|