mirror of
https://github.com/k2-fsa/sherpa-onnx.git
synced 2026-11-10 13:04:05 +08:00
Add C/CXX API for VoxLock (#4104)
This commit is contained in:
1 parent
cc92083394
commit
1ec9807f1e
17 files changed
+1217
-1
No files matched your search
@@ -1717,3 +1717,171 @@ jobs:
|
||||
ls -lh
|
||||
./run.sh
|
||||
rm -rf sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20
|
||||
|
||||
test-speech-enhancement:
|
||||
name: Test Speech Enhancement ${{ matrix.os }}
|
||||
needs: build
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, ubuntu-22.04-arm]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-${{ matrix.os }}
|
||||
path: build/install
|
||||
|
||||
- name: Set up library path
|
||||
shell: bash
|
||||
run: |
|
||||
echo "LD_LIBRARY_PATH=$PWD/build/install/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV
|
||||
echo "DYLD_LIBRARY_PATH=$PWD/build/install/lib:$DYLD_LIBRARY_PATH" >> $GITHUB_ENV
|
||||
|
||||
- name: Test version
|
||||
shell: bash
|
||||
run: |
|
||||
name=version-c-api
|
||||
gcc -o $name ./c-api-examples/$name.c \
|
||||
-I ./build/install/include \
|
||||
-L ./build/install/lib/ \
|
||||
-l sherpa-onnx-c-api \
|
||||
-l onnxruntime
|
||||
|
||||
ls -lh $name
|
||||
./$name
|
||||
- name: Test speech enhancement (VoxLock)
|
||||
shell: bash
|
||||
run: |
|
||||
name=speech-enhancement-voxlock-c-api
|
||||
gcc -o $name ./c-api-examples/$name.c \
|
||||
-I ./build/install/include \
|
||||
-L ./build/install/lib/ \
|
||||
-l sherpa-onnx-c-api \
|
||||
-l onnxruntime
|
||||
|
||||
ls -lh $name
|
||||
|
||||
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
rm sherpa-onnx-voxlock-int8.tar.bz2
|
||||
|
||||
export LD_LIBRARY_PATH=$PWD/build/install/lib:$LD_LIBRARY_PATH
|
||||
export DYLD_LIBRARY_PATH=$PWD/build/install/lib:$DYLD_LIBRARY_PATH
|
||||
|
||||
./$name
|
||||
|
||||
rm $name
|
||||
mkdir -p $name
|
||||
mv -v voxlock-enhanced-16k.wav $name/
|
||||
cp -v sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav $name/
|
||||
|
||||
rm -rf sherpa-onnx-voxlock-int8
|
||||
|
||||
- name: Test speech enhancement (VoxLock, with voice sample)
|
||||
shell: bash
|
||||
run: |
|
||||
name=speech-enhancement-voxlock-with-voice-sample-c-api
|
||||
gcc -o $name ./c-api-examples/$name.c \
|
||||
-I ./build/install/include \
|
||||
-L ./build/install/lib/ \
|
||||
-l sherpa-onnx-c-api \
|
||||
-l onnxruntime
|
||||
|
||||
ls -lh $name
|
||||
|
||||
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
rm sherpa-onnx-voxlock-int8.tar.bz2
|
||||
|
||||
export LD_LIBRARY_PATH=$PWD/build/install/lib:$LD_LIBRARY_PATH
|
||||
export DYLD_LIBRARY_PATH=$PWD/build/install/lib:$DYLD_LIBRARY_PATH
|
||||
|
||||
./$name
|
||||
|
||||
rm $name
|
||||
mkdir -p $name
|
||||
mv -v voxlock-enhanced-with-voice-sample-16k.wav $name/
|
||||
cp -v sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav $name/
|
||||
cp -v sherpa-onnx-voxlock-int8/test_wavs/en-voice-sample-f.wav $name/
|
||||
|
||||
rm -rf sherpa-onnx-voxlock-int8
|
||||
|
||||
- name: Test online speech enhancement (VoxLock)
|
||||
shell: bash
|
||||
run: |
|
||||
name=online-speech-enhancement-voxlock-c-api
|
||||
gcc -o $name ./c-api-examples/$name.c \
|
||||
-I ./build/install/include \
|
||||
-L ./build/install/lib/ \
|
||||
-l sherpa-onnx-c-api \
|
||||
-l onnxruntime
|
||||
|
||||
ls -lh $name
|
||||
|
||||
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
rm sherpa-onnx-voxlock-int8.tar.bz2
|
||||
|
||||
export LD_LIBRARY_PATH=$PWD/build/install/lib:$LD_LIBRARY_PATH
|
||||
export DYLD_LIBRARY_PATH=$PWD/build/install/lib:$DYLD_LIBRARY_PATH
|
||||
|
||||
./$name
|
||||
|
||||
rm $name
|
||||
mkdir -p $name
|
||||
mv -v voxlock-enhanced-online-16k.wav $name/
|
||||
cp -v sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav $name/
|
||||
|
||||
rm -rf sherpa-onnx-voxlock-int8
|
||||
|
||||
- name: Test online speech enhancement (VoxLock, with voice sample)
|
||||
shell: bash
|
||||
run: |
|
||||
name=online-speech-enhancement-voxlock-with-voice-sample-c-api
|
||||
gcc -o $name ./c-api-examples/$name.c \
|
||||
-I ./build/install/include \
|
||||
-L ./build/install/lib/ \
|
||||
-l sherpa-onnx-c-api \
|
||||
-l onnxruntime
|
||||
|
||||
ls -lh $name
|
||||
|
||||
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
rm sherpa-onnx-voxlock-int8.tar.bz2
|
||||
|
||||
export LD_LIBRARY_PATH=$PWD/build/install/lib:$LD_LIBRARY_PATH
|
||||
export DYLD_LIBRARY_PATH=$PWD/build/install/lib:$DYLD_LIBRARY_PATH
|
||||
|
||||
./$name
|
||||
|
||||
rm $name
|
||||
mkdir -p $name
|
||||
mv -v voxlock-enhanced-online-with-voice-sample-16k.wav $name/
|
||||
cp -v sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav $name/
|
||||
cp -v sherpa-onnx-voxlock-int8/test_wavs/en-voice-sample-f.wav $name/
|
||||
|
||||
rm -rf sherpa-onnx-voxlock-int8
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: speech-enhancement-voxlock-c-api-${{ matrix.os }}
|
||||
path: speech-enhancement-voxlock-c-api
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: speech-enhancement-voxlock-with-voice-sample-c-api-${{ matrix.os }}
|
||||
path: speech-enhancement-voxlock-with-voice-sample-c-api
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: online-speech-enhancement-voxlock-c-api-${{ matrix.os }}
|
||||
path: online-speech-enhancement-voxlock-c-api
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: online-speech-enhancement-voxlock-with-voice-sample-c-api-${{ matrix.os }}
|
||||
path: online-speech-enhancement-voxlock-with-voice-sample-c-api
|
||||
@@ -1430,3 +1430,164 @@ jobs:
|
||||
|
||||
rm -rf sherpa-onnx-whisper-tiny
|
||||
rm -v ./$name
|
||||
|
||||
test-speech-enhancement:
|
||||
name: Test Speech Enhancement ${{ matrix.os }}
|
||||
needs: build
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, ubuntu-22.04-arm]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-${{ matrix.os }}
|
||||
path: build/install
|
||||
|
||||
- name: Set up library path
|
||||
shell: bash
|
||||
run: |
|
||||
echo "LD_LIBRARY_PATH=$PWD/build/install/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV
|
||||
echo "DYLD_LIBRARY_PATH=$PWD/build/install/lib:$DYLD_LIBRARY_PATH" >> $GITHUB_ENV
|
||||
|
||||
- name: Test version
|
||||
shell: bash
|
||||
run: |
|
||||
name=version-cxx-api
|
||||
g++ -std=c++17 -o $name ./cxx-api-examples/$name.cc \
|
||||
-I ./build/install/include \
|
||||
-L ./build/install/lib/ \
|
||||
-l sherpa-onnx-cxx-api \
|
||||
-l sherpa-onnx-c-api \
|
||||
-l onnxruntime
|
||||
|
||||
ls -lh $name
|
||||
./$name
|
||||
- name: Test Speech Enhancement (VoxLock)
|
||||
shell: bash
|
||||
run: |
|
||||
name=speech-enhancement-voxlock-cxx-api
|
||||
g++ -std=c++17 -o $name ./cxx-api-examples/$name.cc \
|
||||
-I ./build/install/include \
|
||||
-L ./build/install/lib/ \
|
||||
-l sherpa-onnx-cxx-api \
|
||||
-l sherpa-onnx-c-api \
|
||||
-l onnxruntime
|
||||
|
||||
ls -lh $name
|
||||
|
||||
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
rm sherpa-onnx-voxlock-int8.tar.bz2
|
||||
|
||||
./$name
|
||||
|
||||
rm $name
|
||||
mkdir -p $name
|
||||
mv -v voxlock-enhanced-16k.wav $name/
|
||||
cp -v sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav $name/
|
||||
|
||||
rm -rf sherpa-onnx-voxlock-int8
|
||||
|
||||
- name: Test Speech Enhancement (VoxLock, with voice sample)
|
||||
shell: bash
|
||||
run: |
|
||||
name=speech-enhancement-voxlock-with-voice-sample-cxx-api
|
||||
g++ -std=c++17 -o $name ./cxx-api-examples/$name.cc \
|
||||
-I ./build/install/include \
|
||||
-L ./build/install/lib/ \
|
||||
-l sherpa-onnx-cxx-api \
|
||||
-l sherpa-onnx-c-api \
|
||||
-l onnxruntime
|
||||
|
||||
ls -lh $name
|
||||
|
||||
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
rm sherpa-onnx-voxlock-int8.tar.bz2
|
||||
|
||||
./$name
|
||||
|
||||
rm $name
|
||||
mkdir -p $name
|
||||
mv -v voxlock-enhanced-with-voice-sample-16k.wav $name/
|
||||
cp -v sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav $name/
|
||||
cp -v sherpa-onnx-voxlock-int8/test_wavs/en-voice-sample-f.wav $name/
|
||||
|
||||
rm -rf sherpa-onnx-voxlock-int8
|
||||
|
||||
- name: Test Online Speech Enhancement (VoxLock)
|
||||
shell: bash
|
||||
run: |
|
||||
name=online-speech-enhancement-voxlock-cxx-api
|
||||
g++ -std=c++17 -o $name ./cxx-api-examples/$name.cc \
|
||||
-I ./build/install/include \
|
||||
-L ./build/install/lib/ \
|
||||
-l sherpa-onnx-cxx-api \
|
||||
-l sherpa-onnx-c-api \
|
||||
-l onnxruntime
|
||||
|
||||
ls -lh $name
|
||||
|
||||
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
rm sherpa-onnx-voxlock-int8.tar.bz2
|
||||
|
||||
./$name
|
||||
|
||||
rm $name
|
||||
mkdir -p $name
|
||||
mv -v voxlock-enhanced-online-16k.wav $name/
|
||||
cp -v sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav $name/
|
||||
|
||||
rm -rf sherpa-onnx-voxlock-int8
|
||||
|
||||
- name: Test Online Speech Enhancement (VoxLock, with voice sample)
|
||||
shell: bash
|
||||
run: |
|
||||
name=online-speech-enhancement-voxlock-with-voice-sample-cxx-api
|
||||
g++ -std=c++17 -o $name ./cxx-api-examples/$name.cc \
|
||||
-I ./build/install/include \
|
||||
-L ./build/install/lib/ \
|
||||
-l sherpa-onnx-cxx-api \
|
||||
-l sherpa-onnx-c-api \
|
||||
-l onnxruntime
|
||||
|
||||
ls -lh $name
|
||||
|
||||
curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
rm sherpa-onnx-voxlock-int8.tar.bz2
|
||||
|
||||
./$name
|
||||
|
||||
rm $name
|
||||
mkdir -p $name
|
||||
mv -v voxlock-enhanced-online-with-voice-sample-16k.wav $name/
|
||||
cp -v sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav $name/
|
||||
cp -v sherpa-onnx-voxlock-int8/test_wavs/en-voice-sample-f.wav $name/
|
||||
|
||||
rm -rf sherpa-onnx-voxlock-int8
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: speech-enhancement-voxlock-cxx-api-${{ matrix.os }}
|
||||
path: speech-enhancement-voxlock-cxx-api
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: speech-enhancement-voxlock-with-voice-sample-cxx-api-${{ matrix.os }}
|
||||
path: speech-enhancement-voxlock-with-voice-sample-cxx-api
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: online-speech-enhancement-voxlock-cxx-api-${{ matrix.os }}
|
||||
path: online-speech-enhancement-voxlock-cxx-api
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: online-speech-enhancement-voxlock-with-voice-sample-cxx-api-${{ matrix.os }}
|
||||
path: online-speech-enhancement-voxlock-with-voice-sample-cxx-api
|
||||
@@ -28,6 +28,24 @@ add_executable(online-speech-enhancement-dpdfnet-c-api
|
||||
online-speech-enhancement-dpdfnet-c-api.c)
|
||||
target_link_libraries(online-speech-enhancement-dpdfnet-c-api sherpa-onnx-c-api)
|
||||
|
||||
add_executable(speech-enhancement-voxlock-c-api
|
||||
speech-enhancement-voxlock-c-api.c)
|
||||
target_link_libraries(speech-enhancement-voxlock-c-api sherpa-onnx-c-api)
|
||||
|
||||
add_executable(speech-enhancement-voxlock-with-voice-sample-c-api
|
||||
speech-enhancement-voxlock-with-voice-sample-c-api.c)
|
||||
target_link_libraries(speech-enhancement-voxlock-with-voice-sample-c-api
|
||||
sherpa-onnx-c-api)
|
||||
|
||||
add_executable(online-speech-enhancement-voxlock-c-api
|
||||
online-speech-enhancement-voxlock-c-api.c)
|
||||
target_link_libraries(online-speech-enhancement-voxlock-c-api sherpa-onnx-c-api)
|
||||
|
||||
add_executable(online-speech-enhancement-voxlock-with-voice-sample-c-api
|
||||
online-speech-enhancement-voxlock-with-voice-sample-c-api.c)
|
||||
target_link_libraries(online-speech-enhancement-voxlock-with-voice-sample-c-api
|
||||
sherpa-onnx-c-api)
|
||||
|
||||
if(SHERPA_ONNX_ENABLE_TTS)
|
||||
add_executable(offline-tts-c-api offline-tts-c-api.c)
|
||||
target_link_libraries(offline-tts-c-api sherpa-onnx-c-api)
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
// c-api-examples/online-speech-enhancement-voxlock-c-api.c
|
||||
//
|
||||
// Copyright (c) 2026 Xiaomi Corporation
|
||||
//
|
||||
// VoxLock is a target-speaker voice isolation model. It keeps the voice of
|
||||
// one speaker, e.g., the caller in a phone call, and removes the other
|
||||
// voices.
|
||||
//
|
||||
// The model is from https://github.com/arbazsiddiqui/voxlock
|
||||
//
|
||||
// This example does not provide a voice sample, so VoxLock passes the audio
|
||||
// through unchanged until it has heard 3 seconds of speech, takes that speech
|
||||
// as the speaker to keep, and isolates from then on. See
|
||||
// ./online-speech-enhancement-voxlock-with-voice-sample-c-api.c if you have a
|
||||
// voice sample of the speaker.
|
||||
//
|
||||
// We assume you have pre-downloaded the model from
|
||||
// https://github.com/k2-fsa/sherpa-onnx/releases/tag/speech-enhancement-models
|
||||
//
|
||||
// An example command to download
|
||||
// clang-format off
|
||||
/*
|
||||
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
*/
|
||||
// clang-format on
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
static int32_t AppendSamples(float **samples, int32_t *num_samples,
|
||||
const SherpaOnnxDenoisedAudio *audio) {
|
||||
float *p = NULL;
|
||||
|
||||
if (!audio || audio->n == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
p = (float *)realloc(*samples, sizeof(float) * (*num_samples + audio->n));
|
||||
if (!p) {
|
||||
fprintf(stderr, "Failed to allocate memory for output samples\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(p + *num_samples, audio->samples, sizeof(float) * audio->n);
|
||||
*samples = p;
|
||||
*num_samples += audio->n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t main() {
|
||||
SherpaOnnxOnlineSpeechDenoiserConfig config;
|
||||
const char *enroll_model = "./sherpa-onnx-voxlock-int8/enroll.onnx";
|
||||
const char *chunk_model = "./sherpa-onnx-voxlock-int8/chunk_int8.onnx";
|
||||
const char *wav_filename =
|
||||
"./sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav";
|
||||
const char *out_wave_filename = "./voxlock-enhanced-online-16k.wav";
|
||||
float *samples = NULL;
|
||||
int32_t num_samples = 0;
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.model.voxlock.enroll_model = enroll_model;
|
||||
config.model.voxlock.chunk_model = chunk_model;
|
||||
|
||||
const SherpaOnnxOnlineSpeechDenoiser *sd =
|
||||
SherpaOnnxCreateOnlineSpeechDenoiser(&config);
|
||||
if (!sd) {
|
||||
fprintf(stderr, "Please check your config\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const SherpaOnnxWave *wave = SherpaOnnxReadWave(wav_filename);
|
||||
if (!wave) {
|
||||
SherpaOnnxDestroyOnlineSpeechDenoiser(sd);
|
||||
fprintf(stderr, "Failed to read %s\n", wav_filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t frame_shift = SherpaOnnxOnlineSpeechDenoiserGetFrameShiftInSamples(sd);
|
||||
for (int32_t start = 0; start < wave->num_samples; start += frame_shift) {
|
||||
int32_t n = frame_shift;
|
||||
if (start + n > wave->num_samples) {
|
||||
n = wave->num_samples - start;
|
||||
}
|
||||
|
||||
const SherpaOnnxDenoisedAudio *audio = SherpaOnnxOnlineSpeechDenoiserRun(
|
||||
sd, wave->samples + start, n, wave->sample_rate);
|
||||
int32_t ok = AppendSamples(&samples, &num_samples, audio);
|
||||
SherpaOnnxDestroyDenoisedAudio(audio);
|
||||
if (!ok) {
|
||||
free(samples);
|
||||
SherpaOnnxFreeWave(wave);
|
||||
SherpaOnnxDestroyOnlineSpeechDenoiser(sd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const SherpaOnnxDenoisedAudio *tail = SherpaOnnxOnlineSpeechDenoiserFlush(sd);
|
||||
int32_t sample_rate = tail ? tail->sample_rate
|
||||
: SherpaOnnxOnlineSpeechDenoiserGetSampleRate(sd);
|
||||
int32_t ok = AppendSamples(&samples, &num_samples, tail);
|
||||
SherpaOnnxDestroyDenoisedAudio(tail);
|
||||
if (!ok) {
|
||||
free(samples);
|
||||
SherpaOnnxFreeWave(wave);
|
||||
SherpaOnnxDestroyOnlineSpeechDenoiser(sd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (num_samples == 0) {
|
||||
fprintf(stderr, "No denoised samples were produced\n");
|
||||
free(samples);
|
||||
SherpaOnnxFreeWave(wave);
|
||||
SherpaOnnxDestroyOnlineSpeechDenoiser(sd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SherpaOnnxWriteWave(samples, num_samples, sample_rate, out_wave_filename);
|
||||
|
||||
free(samples);
|
||||
SherpaOnnxFreeWave(wave);
|
||||
SherpaOnnxDestroyOnlineSpeechDenoiser(sd);
|
||||
|
||||
fprintf(stdout, "Saved to %s\n", out_wave_filename);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
// c-api-examples/online-speech-enhancement-voxlock-with-voice-sample-c-api.c
|
||||
//
|
||||
// Copyright (c) 2026 Xiaomi Corporation
|
||||
//
|
||||
// VoxLock is a target-speaker voice isolation model. It keeps the voice of
|
||||
// one speaker, e.g., the caller in a phone call, and removes the other
|
||||
// voices.
|
||||
//
|
||||
// The model is from https://github.com/arbazsiddiqui/voxlock
|
||||
//
|
||||
// This example provides a voice sample of the speaker to keep, so VoxLock
|
||||
// isolates that speaker from the first sample. The voice sample must have at
|
||||
// least 3 seconds of the speaker's voice; from a longer file, VoxLock uses
|
||||
// the loudest 3 seconds within its first 30 seconds. See
|
||||
// ./online-speech-enhancement-voxlock-c-api.c if you don't have a voice
|
||||
// sample.
|
||||
//
|
||||
// We assume you have pre-downloaded the model from
|
||||
// https://github.com/k2-fsa/sherpa-onnx/releases/tag/speech-enhancement-models
|
||||
//
|
||||
// An example command to download
|
||||
// clang-format off
|
||||
/*
|
||||
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
*/
|
||||
// clang-format on
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
static int32_t AppendSamples(float **samples, int32_t *num_samples,
|
||||
const SherpaOnnxDenoisedAudio *audio) {
|
||||
float *p = NULL;
|
||||
|
||||
if (!audio || audio->n == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
p = (float *)realloc(*samples, sizeof(float) * (*num_samples + audio->n));
|
||||
if (!p) {
|
||||
fprintf(stderr, "Failed to allocate memory for output samples\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(p + *num_samples, audio->samples, sizeof(float) * audio->n);
|
||||
*samples = p;
|
||||
*num_samples += audio->n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t main() {
|
||||
SherpaOnnxOnlineSpeechDenoiserConfig config;
|
||||
const char *enroll_model = "./sherpa-onnx-voxlock-int8/enroll.onnx";
|
||||
const char *chunk_model = "./sherpa-onnx-voxlock-int8/chunk_int8.onnx";
|
||||
const char *voice_sample =
|
||||
"./sherpa-onnx-voxlock-int8/test_wavs/en-voice-sample-f.wav";
|
||||
const char *wav_filename =
|
||||
"./sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav";
|
||||
const char *out_wave_filename =
|
||||
"./voxlock-enhanced-online-with-voice-sample-16k.wav";
|
||||
float *samples = NULL;
|
||||
int32_t num_samples = 0;
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.model.voxlock.enroll_model = enroll_model;
|
||||
config.model.voxlock.chunk_model = chunk_model;
|
||||
config.model.voxlock.voice_sample = voice_sample;
|
||||
|
||||
const SherpaOnnxOnlineSpeechDenoiser *sd =
|
||||
SherpaOnnxCreateOnlineSpeechDenoiser(&config);
|
||||
if (!sd) {
|
||||
fprintf(stderr, "Please check your config\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const SherpaOnnxWave *wave = SherpaOnnxReadWave(wav_filename);
|
||||
if (!wave) {
|
||||
SherpaOnnxDestroyOnlineSpeechDenoiser(sd);
|
||||
fprintf(stderr, "Failed to read %s\n", wav_filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t frame_shift = SherpaOnnxOnlineSpeechDenoiserGetFrameShiftInSamples(sd);
|
||||
for (int32_t start = 0; start < wave->num_samples; start += frame_shift) {
|
||||
int32_t n = frame_shift;
|
||||
if (start + n > wave->num_samples) {
|
||||
n = wave->num_samples - start;
|
||||
}
|
||||
|
||||
const SherpaOnnxDenoisedAudio *audio = SherpaOnnxOnlineSpeechDenoiserRun(
|
||||
sd, wave->samples + start, n, wave->sample_rate);
|
||||
int32_t ok = AppendSamples(&samples, &num_samples, audio);
|
||||
SherpaOnnxDestroyDenoisedAudio(audio);
|
||||
if (!ok) {
|
||||
free(samples);
|
||||
SherpaOnnxFreeWave(wave);
|
||||
SherpaOnnxDestroyOnlineSpeechDenoiser(sd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const SherpaOnnxDenoisedAudio *tail = SherpaOnnxOnlineSpeechDenoiserFlush(sd);
|
||||
int32_t sample_rate = tail ? tail->sample_rate
|
||||
: SherpaOnnxOnlineSpeechDenoiserGetSampleRate(sd);
|
||||
int32_t ok = AppendSamples(&samples, &num_samples, tail);
|
||||
SherpaOnnxDestroyDenoisedAudio(tail);
|
||||
if (!ok) {
|
||||
free(samples);
|
||||
SherpaOnnxFreeWave(wave);
|
||||
SherpaOnnxDestroyOnlineSpeechDenoiser(sd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (num_samples == 0) {
|
||||
fprintf(stderr, "No denoised samples were produced\n");
|
||||
free(samples);
|
||||
SherpaOnnxFreeWave(wave);
|
||||
SherpaOnnxDestroyOnlineSpeechDenoiser(sd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SherpaOnnxWriteWave(samples, num_samples, sample_rate, out_wave_filename);
|
||||
|
||||
free(samples);
|
||||
SherpaOnnxFreeWave(wave);
|
||||
SherpaOnnxDestroyOnlineSpeechDenoiser(sd);
|
||||
|
||||
fprintf(stdout, "Saved to %s\n", out_wave_filename);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// c-api-examples/speech-enhancement-voxlock-c-api.c
|
||||
//
|
||||
// Copyright (c) 2026 Xiaomi Corporation
|
||||
//
|
||||
// VoxLock is a target-speaker voice isolation model. It keeps the voice of
|
||||
// one speaker, e.g., the caller in a phone call, and removes the other
|
||||
// voices.
|
||||
//
|
||||
// The model is from https://github.com/arbazsiddiqui/voxlock
|
||||
//
|
||||
// This example does not provide a voice sample, so VoxLock takes the loudest
|
||||
// 3 seconds in the first 15 seconds of the input as the speaker to keep. See
|
||||
// ./speech-enhancement-voxlock-with-voice-sample-c-api.c if you have a voice
|
||||
// sample of the speaker.
|
||||
//
|
||||
// We assume you have pre-downloaded the model from
|
||||
// https://github.com/k2-fsa/sherpa-onnx/releases/tag/speech-enhancement-models
|
||||
//
|
||||
// An example command to download
|
||||
// clang-format off
|
||||
/*
|
||||
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
*/
|
||||
// clang-format on
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
int32_t main() {
|
||||
SherpaOnnxOfflineSpeechDenoiserConfig config;
|
||||
const char *enroll_model = "./sherpa-onnx-voxlock-int8/enroll.onnx";
|
||||
const char *chunk_model = "./sherpa-onnx-voxlock-int8/chunk_int8.onnx";
|
||||
const char *wav_filename =
|
||||
"./sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav";
|
||||
const char *out_wave_filename = "./voxlock-enhanced-16k.wav";
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.model.voxlock.enroll_model = enroll_model;
|
||||
config.model.voxlock.chunk_model = chunk_model;
|
||||
|
||||
const SherpaOnnxOfflineSpeechDenoiser *sd =
|
||||
SherpaOnnxCreateOfflineSpeechDenoiser(&config);
|
||||
if (!sd) {
|
||||
fprintf(stderr, "Please check your config");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const SherpaOnnxWave *wave = SherpaOnnxReadWave(wav_filename);
|
||||
if (wave == NULL) {
|
||||
SherpaOnnxDestroyOfflineSpeechDenoiser(sd);
|
||||
fprintf(stderr, "Failed to read %s\n", wav_filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const SherpaOnnxDenoisedAudio *denoised = SherpaOnnxOfflineSpeechDenoiserRun(
|
||||
sd, wave->samples, wave->num_samples, wave->sample_rate);
|
||||
|
||||
SherpaOnnxWriteWave(denoised->samples, denoised->n, denoised->sample_rate,
|
||||
out_wave_filename);
|
||||
|
||||
SherpaOnnxDestroyDenoisedAudio(denoised);
|
||||
SherpaOnnxFreeWave(wave);
|
||||
SherpaOnnxDestroyOfflineSpeechDenoiser(sd);
|
||||
|
||||
fprintf(stdout, "Saved to %s\n", out_wave_filename);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
// c-api-examples/speech-enhancement-voxlock-with-voice-sample-c-api.c
|
||||
//
|
||||
// Copyright (c) 2026 Xiaomi Corporation
|
||||
//
|
||||
// VoxLock is a target-speaker voice isolation model. It keeps the voice of
|
||||
// one speaker, e.g., the caller in a phone call, and removes the other
|
||||
// voices.
|
||||
//
|
||||
// The model is from https://github.com/arbazsiddiqui/voxlock
|
||||
//
|
||||
// This example provides a voice sample of the speaker to keep, so VoxLock
|
||||
// isolates that speaker from the first sample. The voice sample must have at
|
||||
// least 3 seconds of the speaker's voice; from a longer file, VoxLock uses
|
||||
// the loudest 3 seconds within its first 30 seconds. See
|
||||
// ./speech-enhancement-voxlock-c-api.c if you don't have a voice sample.
|
||||
//
|
||||
// We assume you have pre-downloaded the model from
|
||||
// https://github.com/k2-fsa/sherpa-onnx/releases/tag/speech-enhancement-models
|
||||
//
|
||||
// An example command to download
|
||||
// clang-format off
|
||||
/*
|
||||
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
*/
|
||||
// clang-format on
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sherpa-onnx/c-api/c-api.h"
|
||||
|
||||
int32_t main() {
|
||||
SherpaOnnxOfflineSpeechDenoiserConfig config;
|
||||
const char *enroll_model = "./sherpa-onnx-voxlock-int8/enroll.onnx";
|
||||
const char *chunk_model = "./sherpa-onnx-voxlock-int8/chunk_int8.onnx";
|
||||
const char *voice_sample =
|
||||
"./sherpa-onnx-voxlock-int8/test_wavs/en-voice-sample-f.wav";
|
||||
const char *wav_filename =
|
||||
"./sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav";
|
||||
const char *out_wave_filename =
|
||||
"./voxlock-enhanced-with-voice-sample-16k.wav";
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.model.voxlock.enroll_model = enroll_model;
|
||||
config.model.voxlock.chunk_model = chunk_model;
|
||||
config.model.voxlock.voice_sample = voice_sample;
|
||||
|
||||
const SherpaOnnxOfflineSpeechDenoiser *sd =
|
||||
SherpaOnnxCreateOfflineSpeechDenoiser(&config);
|
||||
if (!sd) {
|
||||
fprintf(stderr, "Please check your config");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const SherpaOnnxWave *wave = SherpaOnnxReadWave(wav_filename);
|
||||
if (wave == NULL) {
|
||||
SherpaOnnxDestroyOfflineSpeechDenoiser(sd);
|
||||
fprintf(stderr, "Failed to read %s\n", wav_filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const SherpaOnnxDenoisedAudio *denoised = SherpaOnnxOfflineSpeechDenoiserRun(
|
||||
sd, wave->samples, wave->num_samples, wave->sample_rate);
|
||||
|
||||
SherpaOnnxWriteWave(denoised->samples, denoised->n, denoised->sample_rate,
|
||||
out_wave_filename);
|
||||
|
||||
SherpaOnnxDestroyDenoisedAudio(denoised);
|
||||
SherpaOnnxFreeWave(wave);
|
||||
SherpaOnnxDestroyOfflineSpeechDenoiser(sd);
|
||||
|
||||
fprintf(stdout, "Saved to %s\n", out_wave_filename);
|
||||
}
|
||||
@@ -37,6 +37,25 @@ add_executable(online-speech-enhancement-dpdfnet-cxx-api
|
||||
target_link_libraries(online-speech-enhancement-dpdfnet-cxx-api
|
||||
sherpa-onnx-cxx-api)
|
||||
|
||||
add_executable(speech-enhancement-voxlock-cxx-api
|
||||
./speech-enhancement-voxlock-cxx-api.cc)
|
||||
target_link_libraries(speech-enhancement-voxlock-cxx-api sherpa-onnx-cxx-api)
|
||||
|
||||
add_executable(speech-enhancement-voxlock-with-voice-sample-cxx-api
|
||||
./speech-enhancement-voxlock-with-voice-sample-cxx-api.cc)
|
||||
target_link_libraries(speech-enhancement-voxlock-with-voice-sample-cxx-api
|
||||
sherpa-onnx-cxx-api)
|
||||
|
||||
add_executable(online-speech-enhancement-voxlock-cxx-api
|
||||
./online-speech-enhancement-voxlock-cxx-api.cc)
|
||||
target_link_libraries(online-speech-enhancement-voxlock-cxx-api
|
||||
sherpa-onnx-cxx-api)
|
||||
|
||||
add_executable(online-speech-enhancement-voxlock-with-voice-sample-cxx-api
|
||||
./online-speech-enhancement-voxlock-with-voice-sample-cxx-api.cc)
|
||||
target_link_libraries(online-speech-enhancement-voxlock-with-voice-sample-cxx-api
|
||||
sherpa-onnx-cxx-api)
|
||||
|
||||
add_executable(kws-cxx-api ./kws-cxx-api.cc)
|
||||
target_link_libraries(kws-cxx-api sherpa-onnx-cxx-api)
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
// cxx-api-examples/online-speech-enhancement-voxlock-cxx-api.cc
|
||||
//
|
||||
// Copyright (c) 2026 Xiaomi Corporation
|
||||
//
|
||||
// VoxLock is a target-speaker voice isolation model. It keeps the voice of
|
||||
// one speaker, e.g., the caller in a phone call, and removes the other
|
||||
// voices.
|
||||
//
|
||||
// The model is from https://github.com/arbazsiddiqui/voxlock
|
||||
//
|
||||
// This example does not provide a voice sample, so VoxLock passes the audio
|
||||
// through unchanged until it has heard 3 seconds of speech, takes that speech
|
||||
// as the speaker to keep, and isolates from then on. See
|
||||
// ./online-speech-enhancement-voxlock-with-voice-sample-cxx-api.cc if you
|
||||
// have a voice sample of the speaker.
|
||||
//
|
||||
// We assume you have pre-downloaded the model from
|
||||
// https://github.com/k2-fsa/sherpa-onnx/releases/tag/speech-enhancement-models
|
||||
//
|
||||
// An example command to download:
|
||||
// clang-format off
|
||||
/*
|
||||
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
*/
|
||||
// clang-format on
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono> // NOLINT
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "sherpa-onnx/c-api/cxx-api.h"
|
||||
|
||||
int32_t main() {
|
||||
using namespace sherpa_onnx::cxx; // NOLINT
|
||||
|
||||
OnlineSpeechDenoiserConfig config;
|
||||
std::string enroll_model = "./sherpa-onnx-voxlock-int8/enroll.onnx";
|
||||
std::string chunk_model = "./sherpa-onnx-voxlock-int8/chunk_int8.onnx";
|
||||
std::string wav_filename =
|
||||
"./sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav";
|
||||
std::string out_wave_filename = "./voxlock-enhanced-online-16k.wav";
|
||||
config.model.voxlock.enroll_model = enroll_model;
|
||||
config.model.voxlock.chunk_model = chunk_model;
|
||||
|
||||
auto sd = OnlineSpeechDenoiser::Create(config);
|
||||
if (!sd.Get()) {
|
||||
std::cerr << "Please check your config\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
Wave wave = ReadWave(wav_filename);
|
||||
if (wave.samples.empty()) {
|
||||
std::cerr << "Failed to read: '" << wav_filename << "'\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<float> samples;
|
||||
auto frame_shift = sd.GetFrameShiftInSamples();
|
||||
|
||||
std::cout << "Started\n";
|
||||
const auto begin = std::chrono::steady_clock::now();
|
||||
|
||||
for (int32_t start = 0; start < static_cast<int32_t>(wave.samples.size());
|
||||
start += frame_shift) {
|
||||
int32_t n = std::min<int32_t>(frame_shift, wave.samples.size() - start);
|
||||
auto denoised = sd.Run(wave.samples.data() + start, n, wave.sample_rate);
|
||||
samples.insert(samples.end(), denoised.samples.begin(),
|
||||
denoised.samples.end());
|
||||
}
|
||||
|
||||
auto tail = sd.Flush();
|
||||
samples.insert(samples.end(), tail.samples.begin(), tail.samples.end());
|
||||
|
||||
const auto end = std::chrono::steady_clock::now();
|
||||
std::cout << "Done\n";
|
||||
|
||||
WriteWave(out_wave_filename, {samples, sd.GetSampleRate()});
|
||||
|
||||
const float elapsed_seconds =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(end - begin)
|
||||
.count() /
|
||||
1000.;
|
||||
float duration = wave.samples.size() / static_cast<float>(wave.sample_rate);
|
||||
float rtf = elapsed_seconds / duration;
|
||||
|
||||
std::cout << "Saved to " << out_wave_filename << "\n";
|
||||
printf("Duration: %.3fs\n", duration);
|
||||
printf("Elapsed seconds: %.3fs\n", elapsed_seconds);
|
||||
printf("(Real time factor) RTF = %.3f / %.3f = %.3f\n", elapsed_seconds,
|
||||
duration, rtf);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// cxx-api-examples/online-speech-enhancement-voxlock-with-voice-sample-cxx-api.cc
|
||||
//
|
||||
// Copyright (c) 2026 Xiaomi Corporation
|
||||
//
|
||||
// VoxLock is a target-speaker voice isolation model. It keeps the voice of
|
||||
// one speaker, e.g., the caller in a phone call, and removes the other
|
||||
// voices.
|
||||
//
|
||||
// The model is from https://github.com/arbazsiddiqui/voxlock
|
||||
//
|
||||
// This example provides a voice sample of the speaker to keep, so VoxLock
|
||||
// isolates that speaker from the first sample. The voice sample must have at
|
||||
// least 3 seconds of the speaker's voice; from a longer file, VoxLock uses
|
||||
// the loudest 3 seconds within its first 30 seconds. See
|
||||
// ./online-speech-enhancement-voxlock-cxx-api.cc if you don't have a voice
|
||||
// sample.
|
||||
//
|
||||
// We assume you have pre-downloaded the model from
|
||||
// https://github.com/k2-fsa/sherpa-onnx/releases/tag/speech-enhancement-models
|
||||
//
|
||||
// An example command to download:
|
||||
// clang-format off
|
||||
/*
|
||||
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
*/
|
||||
// clang-format on
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono> // NOLINT
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "sherpa-onnx/c-api/cxx-api.h"
|
||||
|
||||
int32_t main() {
|
||||
using namespace sherpa_onnx::cxx; // NOLINT
|
||||
|
||||
OnlineSpeechDenoiserConfig config;
|
||||
std::string enroll_model = "./sherpa-onnx-voxlock-int8/enroll.onnx";
|
||||
std::string chunk_model = "./sherpa-onnx-voxlock-int8/chunk_int8.onnx";
|
||||
std::string voice_sample =
|
||||
"./sherpa-onnx-voxlock-int8/test_wavs/en-voice-sample-f.wav";
|
||||
std::string wav_filename =
|
||||
"./sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav";
|
||||
std::string out_wave_filename =
|
||||
"./voxlock-enhanced-online-with-voice-sample-16k.wav";
|
||||
config.model.voxlock.enroll_model = enroll_model;
|
||||
config.model.voxlock.chunk_model = chunk_model;
|
||||
config.model.voxlock.voice_sample = voice_sample;
|
||||
|
||||
auto sd = OnlineSpeechDenoiser::Create(config);
|
||||
if (!sd.Get()) {
|
||||
std::cerr << "Please check your config\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
Wave wave = ReadWave(wav_filename);
|
||||
if (wave.samples.empty()) {
|
||||
std::cerr << "Failed to read: '" << wav_filename << "'\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<float> samples;
|
||||
auto frame_shift = sd.GetFrameShiftInSamples();
|
||||
|
||||
std::cout << "Started\n";
|
||||
const auto begin = std::chrono::steady_clock::now();
|
||||
|
||||
for (int32_t start = 0; start < static_cast<int32_t>(wave.samples.size());
|
||||
start += frame_shift) {
|
||||
int32_t n = std::min<int32_t>(frame_shift, wave.samples.size() - start);
|
||||
auto denoised = sd.Run(wave.samples.data() + start, n, wave.sample_rate);
|
||||
samples.insert(samples.end(), denoised.samples.begin(),
|
||||
denoised.samples.end());
|
||||
}
|
||||
|
||||
auto tail = sd.Flush();
|
||||
samples.insert(samples.end(), tail.samples.begin(), tail.samples.end());
|
||||
|
||||
const auto end = std::chrono::steady_clock::now();
|
||||
std::cout << "Done\n";
|
||||
|
||||
WriteWave(out_wave_filename, {samples, sd.GetSampleRate()});
|
||||
|
||||
const float elapsed_seconds =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(end - begin)
|
||||
.count() /
|
||||
1000.;
|
||||
float duration = wave.samples.size() / static_cast<float>(wave.sample_rate);
|
||||
float rtf = elapsed_seconds / duration;
|
||||
|
||||
std::cout << "Saved to " << out_wave_filename << "\n";
|
||||
printf("Duration: %.3fs\n", duration);
|
||||
printf("Elapsed seconds: %.3fs\n", elapsed_seconds);
|
||||
printf("(Real time factor) RTF = %.3f / %.3f = %.3f\n", elapsed_seconds,
|
||||
duration, rtf);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// cxx-api-examples/speech-enhancement-voxlock-cxx-api.cc
|
||||
//
|
||||
// Copyright (c) 2026 Xiaomi Corporation
|
||||
//
|
||||
// VoxLock is a target-speaker voice isolation model. It keeps the voice of
|
||||
// one speaker, e.g., the caller in a phone call, and removes the other
|
||||
// voices.
|
||||
//
|
||||
// The model is from https://github.com/arbazsiddiqui/voxlock
|
||||
//
|
||||
// This example does not provide a voice sample, so VoxLock takes the loudest
|
||||
// 3 seconds in the first 15 seconds of the input as the speaker to keep. See
|
||||
// ./speech-enhancement-voxlock-with-voice-sample-cxx-api.cc if you have a
|
||||
// voice sample of the speaker.
|
||||
//
|
||||
// We assume you have pre-downloaded the model from
|
||||
// https://github.com/k2-fsa/sherpa-onnx/releases/tag/speech-enhancement-models
|
||||
//
|
||||
// An example command to download:
|
||||
// clang-format off
|
||||
/*
|
||||
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
*/
|
||||
// clang-format on
|
||||
|
||||
#include <chrono> // NOLINT
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "sherpa-onnx/c-api/cxx-api.h"
|
||||
|
||||
int32_t main() {
|
||||
using namespace sherpa_onnx::cxx; // NOLINT
|
||||
|
||||
OfflineSpeechDenoiserConfig config;
|
||||
std::string enroll_model = "./sherpa-onnx-voxlock-int8/enroll.onnx";
|
||||
std::string chunk_model = "./sherpa-onnx-voxlock-int8/chunk_int8.onnx";
|
||||
std::string wav_filename =
|
||||
"./sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav";
|
||||
std::string out_wave_filename = "./voxlock-enhanced-16k.wav";
|
||||
config.model.voxlock.enroll_model = enroll_model;
|
||||
config.model.voxlock.chunk_model = chunk_model;
|
||||
|
||||
auto sd = OfflineSpeechDenoiser::Create(config);
|
||||
if (!sd.Get()) {
|
||||
std::cerr << "Please check your config\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
Wave wave = ReadWave(wav_filename);
|
||||
if (wave.samples.empty()) {
|
||||
std::cerr << "Failed to read: '" << wav_filename << "'\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "Started\n";
|
||||
const auto begin = std::chrono::steady_clock::now();
|
||||
auto denoised =
|
||||
sd.Run(wave.samples.data(), wave.samples.size(), wave.sample_rate);
|
||||
const auto end = std::chrono::steady_clock::now();
|
||||
std::cout << "Done\n";
|
||||
|
||||
WriteWave(out_wave_filename, {denoised.samples, denoised.sample_rate});
|
||||
|
||||
const float elapsed_seconds =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(end - begin)
|
||||
.count() /
|
||||
1000.;
|
||||
float duration = wave.samples.size() / static_cast<float>(wave.sample_rate);
|
||||
float rtf = elapsed_seconds / duration;
|
||||
|
||||
std::cout << "Saved to " << out_wave_filename << "\n";
|
||||
printf("Duration: %.3fs\n", duration);
|
||||
printf("Elapsed seconds: %.3fs\n", elapsed_seconds);
|
||||
printf("(Real time factor) RTF = %.3f / %.3f = %.3f\n", elapsed_seconds,
|
||||
duration, rtf);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// cxx-api-examples/speech-enhancement-voxlock-with-voice-sample-cxx-api.cc
|
||||
//
|
||||
// Copyright (c) 2026 Xiaomi Corporation
|
||||
//
|
||||
// VoxLock is a target-speaker voice isolation model. It keeps the voice of
|
||||
// one speaker, e.g., the caller in a phone call, and removes the other
|
||||
// voices.
|
||||
//
|
||||
// The model is from https://github.com/arbazsiddiqui/voxlock
|
||||
//
|
||||
// This example provides a voice sample of the speaker to keep, so VoxLock
|
||||
// isolates that speaker from the first sample. The voice sample must have at
|
||||
// least 3 seconds of the speaker's voice; from a longer file, VoxLock uses
|
||||
// the loudest 3 seconds within its first 30 seconds. See
|
||||
// ./speech-enhancement-voxlock-cxx-api.cc if you don't have a voice sample.
|
||||
//
|
||||
// We assume you have pre-downloaded the model from
|
||||
// https://github.com/k2-fsa/sherpa-onnx/releases/tag/speech-enhancement-models
|
||||
//
|
||||
// An example command to download:
|
||||
// clang-format off
|
||||
/*
|
||||
wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/sherpa-onnx-voxlock-int8.tar.bz2
|
||||
tar xvf sherpa-onnx-voxlock-int8.tar.bz2
|
||||
*/
|
||||
// clang-format on
|
||||
|
||||
#include <chrono> // NOLINT
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "sherpa-onnx/c-api/cxx-api.h"
|
||||
|
||||
int32_t main() {
|
||||
using namespace sherpa_onnx::cxx; // NOLINT
|
||||
|
||||
OfflineSpeechDenoiserConfig config;
|
||||
std::string enroll_model = "./sherpa-onnx-voxlock-int8/enroll.onnx";
|
||||
std::string chunk_model = "./sherpa-onnx-voxlock-int8/chunk_int8.onnx";
|
||||
std::string voice_sample =
|
||||
"./sherpa-onnx-voxlock-int8/test_wavs/en-voice-sample-f.wav";
|
||||
std::string wav_filename =
|
||||
"./sherpa-onnx-voxlock-int8/test_wavs/en-combined.wav";
|
||||
std::string out_wave_filename =
|
||||
"./voxlock-enhanced-with-voice-sample-16k.wav";
|
||||
config.model.voxlock.enroll_model = enroll_model;
|
||||
config.model.voxlock.chunk_model = chunk_model;
|
||||
config.model.voxlock.voice_sample = voice_sample;
|
||||
|
||||
auto sd = OfflineSpeechDenoiser::Create(config);
|
||||
if (!sd.Get()) {
|
||||
std::cerr << "Please check your config\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
Wave wave = ReadWave(wav_filename);
|
||||
if (wave.samples.empty()) {
|
||||
std::cerr << "Failed to read: '" << wav_filename << "'\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cout << "Started\n";
|
||||
const auto begin = std::chrono::steady_clock::now();
|
||||
auto denoised =
|
||||
sd.Run(wave.samples.data(), wave.samples.size(), wave.sample_rate);
|
||||
const auto end = std::chrono::steady_clock::now();
|
||||
std::cout << "Done\n";
|
||||
|
||||
WriteWave(out_wave_filename, {denoised.samples, denoised.sample_rate});
|
||||
|
||||
const float elapsed_seconds =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(end - begin)
|
||||
.count() /
|
||||
1000.;
|
||||
float duration = wave.samples.size() / static_cast<float>(wave.sample_rate);
|
||||
float rtf = elapsed_seconds / duration;
|
||||
|
||||
std::cout << "Saved to " << out_wave_filename << "\n";
|
||||
printf("Duration: %.3fs\n", duration);
|
||||
printf("Elapsed seconds: %.3fs\n", elapsed_seconds);
|
||||
printf("(Real time factor) RTF = %.3f / %.3f = %.3f\n", elapsed_seconds,
|
||||
duration, rtf);
|
||||
return 0;
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "sherpa-onnx/c-api/cxx-api.h"
|
||||
|
||||
auto main() -> int {
|
||||
int32_t main() {
|
||||
std::cout << "sherpa-onnx version : " << sherpa_onnx::cxx::GetVersionStr()
|
||||
<< "\n";
|
||||
std::cout << "sherpa-onnx Git SHA1: " << sherpa_onnx::cxx::GetGitSha1()
|
||||
|
||||
@@ -3019,6 +3019,12 @@ static sherpa_onnx::OfflineSpeechDenoiserConfig GetOfflineSpeechDenoiserConfig(
|
||||
c.model.dpdfnet.model = SHERPA_ONNX_OR(config->model.dpdfnet.model, "");
|
||||
c.model.dpdfnet.attenuation_limit_db =
|
||||
config->model.dpdfnet.attenuation_limit_db;
|
||||
c.model.voxlock.enroll_model =
|
||||
SHERPA_ONNX_OR(config->model.voxlock.enroll_model, "");
|
||||
c.model.voxlock.chunk_model =
|
||||
SHERPA_ONNX_OR(config->model.voxlock.chunk_model, "");
|
||||
c.model.voxlock.voice_sample =
|
||||
SHERPA_ONNX_OR(config->model.voxlock.voice_sample, "");
|
||||
|
||||
if (c.model.debug) {
|
||||
#if __OHOS__
|
||||
@@ -3236,6 +3242,12 @@ static sherpa_onnx::OnlineSpeechDenoiserConfig GetOnlineSpeechDenoiserConfig(
|
||||
c.model.debug = config->model.debug;
|
||||
c.model.provider = SHERPA_ONNX_OR(config->model.provider, "cpu");
|
||||
c.model.dpdfnet.model = SHERPA_ONNX_OR(config->model.dpdfnet.model, "");
|
||||
c.model.voxlock.enroll_model =
|
||||
SHERPA_ONNX_OR(config->model.voxlock.enroll_model, "");
|
||||
c.model.voxlock.chunk_model =
|
||||
SHERPA_ONNX_OR(config->model.voxlock.chunk_model, "");
|
||||
c.model.voxlock.voice_sample =
|
||||
SHERPA_ONNX_OR(config->model.voxlock.voice_sample, "");
|
||||
|
||||
if (c.model.debug) {
|
||||
#if __OHOS__
|
||||
|
||||
@@ -66,6 +66,10 @@
|
||||
* - `offline-speaker-diarization-c-api.c` for diarization
|
||||
* - `speech-enhancement-gtcrn-c-api.c` and
|
||||
* `online-speech-enhancement-gtcrn-c-api.c` for speech enhancement
|
||||
* - `speech-enhancement-voxlock-c-api.c` and
|
||||
* `online-speech-enhancement-voxlock-c-api.c` for target-speaker voice
|
||||
* isolation with VoxLock; the model is from
|
||||
* https://github.com/arbazsiddiqui/voxlock
|
||||
*/
|
||||
|
||||
#ifndef SHERPA_ONNX_C_API_C_API_H_
|
||||
@@ -4262,6 +4266,44 @@ typedef struct SherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig {
|
||||
float attenuation_limit_db;
|
||||
} SherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig;
|
||||
|
||||
/**
|
||||
* @brief VoxLock target-speaker voice isolation model configuration.
|
||||
*
|
||||
* VoxLock keeps the voice of one speaker (the caller) and removes other
|
||||
* voices. The model is from https://github.com/arbazsiddiqui/voxlock
|
||||
*/
|
||||
typedef struct SherpaOnnxOfflineSpeechDenoiserVoxLockModelConfig {
|
||||
/**
|
||||
* Path to the VoxLock enroll model, e.g., `enroll.onnx`.
|
||||
*
|
||||
* It runs once on a voice sample of the speaker to keep. Download the
|
||||
* models from
|
||||
* https://github.com/arbazsiddiqui/voxlock/releases/tag/sherpa-onnx-models
|
||||
*/
|
||||
const char *enroll_model;
|
||||
/**
|
||||
* Path to the VoxLock chunk model, e.g., `chunk.onnx` or
|
||||
* `chunk_int8.onnx`.
|
||||
*
|
||||
* It runs on each chunk of the audio.
|
||||
*/
|
||||
const char *chunk_model;
|
||||
/**
|
||||
* Optional. Path to a wave file with at least 3 seconds of the caller's
|
||||
* voice. VoxLock keeps this voice and removes the others. From a longer
|
||||
* file, it uses the loudest 3 seconds within the first 30 seconds. A file
|
||||
* that is shorter or cannot be read is ignored, as if it were empty.
|
||||
*
|
||||
* If empty or ignored, the voice sample is taken from the input audio:
|
||||
*
|
||||
* - Offline denoiser: the loudest 3 seconds in the first 15 seconds of
|
||||
* the input are used.
|
||||
* - Online denoiser: the audio is passed through unchanged until 3 seconds
|
||||
* of speech have been heard; that speech is used as the voice sample.
|
||||
*/
|
||||
const char *voice_sample;
|
||||
} SherpaOnnxOfflineSpeechDenoiserVoxLockModelConfig;
|
||||
|
||||
/**
|
||||
* @brief Speech denoiser model configuration shared by offline and online APIs.
|
||||
*
|
||||
@@ -4279,6 +4321,8 @@ typedef struct SherpaOnnxOfflineSpeechDenoiserModelConfig {
|
||||
const char *provider;
|
||||
/** DPDFNet model configuration. */
|
||||
SherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig dpdfnet;
|
||||
/** VoxLock model configuration. */
|
||||
SherpaOnnxOfflineSpeechDenoiserVoxLockModelConfig voxlock;
|
||||
} SherpaOnnxOfflineSpeechDenoiserModelConfig;
|
||||
|
||||
/** @brief Configuration for offline speech denoising. */
|
||||
|
||||
@@ -21,6 +21,9 @@ static void FillSpeechDenoiserModelConfig(
|
||||
dst->gtcrn.model = src.gtcrn.model.c_str();
|
||||
dst->dpdfnet.model = src.dpdfnet.model.c_str();
|
||||
dst->dpdfnet.attenuation_limit_db = src.dpdfnet.attenuation_limit_db;
|
||||
dst->voxlock.enroll_model = src.voxlock.enroll_model.c_str();
|
||||
dst->voxlock.chunk_model = src.voxlock.chunk_model.c_str();
|
||||
dst->voxlock.voice_sample = src.voxlock.voice_sample.c_str();
|
||||
dst->num_threads = src.num_threads;
|
||||
dst->provider = src.provider.c_str();
|
||||
dst->debug = src.debug;
|
||||
|
||||
@@ -1287,6 +1287,27 @@ struct OfflineSpeechDenoiserDpdfNetModelConfig {
|
||||
float attenuation_limit_db = 0.0f;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief VoxLock target-speaker voice isolation model configuration.
|
||||
*
|
||||
* VoxLock keeps the voice of one speaker (the caller) and removes other
|
||||
* voices. The model is from https://github.com/arbazsiddiqui/voxlock
|
||||
*/
|
||||
struct OfflineSpeechDenoiserVoxLockModelConfig {
|
||||
/** Path to the VoxLock enroll model, e.g., `enroll.onnx`. */
|
||||
std::string enroll_model;
|
||||
/** Path to the VoxLock chunk model, e.g., `chunk.onnx`. */
|
||||
std::string chunk_model;
|
||||
/**
|
||||
* Optional. Path to a wave file with at least 3 seconds of the caller's
|
||||
* voice. From a longer file, the loudest 3 seconds within the first 30
|
||||
* seconds are used. A file that is shorter or cannot be read is ignored,
|
||||
* as if it were empty. If empty or ignored, the voice sample is taken from
|
||||
* the input audio; see the C API docs for the offline/online fallbacks.
|
||||
*/
|
||||
std::string voice_sample;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Speech denoiser model configuration.
|
||||
*
|
||||
@@ -1298,6 +1319,8 @@ struct OfflineSpeechDenoiserModelConfig {
|
||||
OfflineSpeechDenoiserGtcrnModelConfig gtcrn;
|
||||
/** DPDFNet configuration. */
|
||||
OfflineSpeechDenoiserDpdfNetModelConfig dpdfnet;
|
||||
/** VoxLock configuration. */
|
||||
OfflineSpeechDenoiserVoxLockModelConfig voxlock;
|
||||
/** Number of inference threads. */
|
||||
int32_t num_threads = 1;
|
||||
/** Enable verbose debug logging. */
|
||||
|
||||
Reference in new issue
Block a user