diff --git a/c-api-examples/speech-enhancement-dpdfnet-c-api.c b/c-api-examples/speech-enhancement-dpdfnet-c-api.c index 0017d350fe..4bfa0c3b6a 100644 --- a/c-api-examples/speech-enhancement-dpdfnet-c-api.c +++ b/c-api-examples/speech-enhancement-dpdfnet-c-api.c @@ -17,13 +17,17 @@ wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement- wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/dpdfnet4.onnx wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/dpdfnet8.onnx wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/dpdfnet2_48khz_hr.onnx +wget https://huggingface.co/Ceva-IP/DPDFNet/resolve/main/onnx/dpdfnet2_8khz.onnx +wget https://huggingface.co/Ceva-IP/DPDFNet/resolve/main/onnx/dpdfnet8_8khz.onnx +wget https://huggingface.co/Ceva-IP/DPDFNet/resolve/main/onnx/dpdfnet8_48khz_hr.onnx wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/inp_16k.wav */ // clang-format on // // Use dpdfnet_baseline.onnx, dpdfnet2.onnx, dpdfnet4.onnx, or dpdfnet8.onnx // for 16 kHz downstream ASR or speech recognition. -// Use dpdfnet2_48khz_hr.onnx for 48 kHz enhancement output. +// Use dpdfnet2_8khz.onnx or dpdfnet8_8khz.onnx for 8 kHz enhancement, and +// dpdfnet2_48khz_hr.onnx or dpdfnet8_48khz_hr.onnx for 48 kHz enhancement. #include #include @@ -37,6 +41,7 @@ int32_t main() { memset(&config, 0, sizeof(config)); config.model.dpdfnet.model = model_filename; + config.model.dpdfnet.attenuation_limit_db = 12.0f; const SherpaOnnxOfflineSpeechDenoiser *sd = SherpaOnnxCreateOfflineSpeechDenoiser(&config); diff --git a/cxx-api-examples/speech-enhancement-dpdfnet-cxx-api.cc b/cxx-api-examples/speech-enhancement-dpdfnet-cxx-api.cc index 76e01f6e13..fe6dfd9630 100644 --- a/cxx-api-examples/speech-enhancement-dpdfnet-cxx-api.cc +++ b/cxx-api-examples/speech-enhancement-dpdfnet-cxx-api.cc @@ -34,6 +34,7 @@ int32_t main() { std::string wav_filename = "./inp_16k.wav"; std::string out_wave_filename = "./enhanced-dpdfnet.wav"; config.model.dpdfnet.model = model_filename; + config.model.dpdfnet.attenuation_limit_db = 12.0f; auto sd = OfflineSpeechDenoiser::Create(config); if (!sd.Get()) { diff --git a/dart-api-examples/speech-enhancement-dpdfnet/bin/speech_enhancement_dpdfnet.dart b/dart-api-examples/speech-enhancement-dpdfnet/bin/speech_enhancement_dpdfnet.dart index c04424d265..ad0e201a05 100644 --- a/dart-api-examples/speech-enhancement-dpdfnet/bin/speech_enhancement_dpdfnet.dart +++ b/dart-api-examples/speech-enhancement-dpdfnet/bin/speech_enhancement_dpdfnet.dart @@ -26,13 +26,17 @@ void main(List arguments) async { final outputWav = res['output-wav'] as String; final config = sherpa_onnx.OfflineSpeechDenoiserConfig( - model: sherpa_onnx.OfflineSpeechDenoiserModelConfig( - gtcrn: const sherpa_onnx.OfflineSpeechDenoiserGtcrnModelConfig(), - dpdfnet: sherpa_onnx.OfflineSpeechDenoiserDpdfNetModelConfig(model: model), - numThreads: 1, - debug: true, - provider: 'cpu', - )); + model: sherpa_onnx.OfflineSpeechDenoiserModelConfig( + gtcrn: const sherpa_onnx.OfflineSpeechDenoiserGtcrnModelConfig(), + dpdfnet: sherpa_onnx.OfflineSpeechDenoiserDpdfNetModelConfig( + model: model, + attenuationLimitDb: 12.0, + ), + numThreads: 1, + debug: true, + provider: 'cpu', + ), + ); final sd = sherpa_onnx.OfflineSpeechDenoiser(config); diff --git a/dotnet-examples/speech-enhancement-dpdfnet/Program.cs b/dotnet-examples/speech-enhancement-dpdfnet/Program.cs index e4292a81a5..c96c8a621e 100644 --- a/dotnet-examples/speech-enhancement-dpdfnet/Program.cs +++ b/dotnet-examples/speech-enhancement-dpdfnet/Program.cs @@ -31,6 +31,7 @@ static void Main(string[] args) var model = "./dpdfnet_baseline.onnx"; var config = new OfflineSpeechDenoiserConfig(); config.Model.Dpdfnet.Model = model; + config.Model.Dpdfnet.AttenuationLimitDb = 12.0f; config.Model.Debug = 1; config.Model.NumThreads = 1; var sd = new OfflineSpeechDenoiser(config); diff --git a/flutter/sherpa_onnx/lib/src/offline_speech_denoiser.dart b/flutter/sherpa_onnx/lib/src/offline_speech_denoiser.dart index 11a1244b7d..de6147bfde 100644 --- a/flutter/sherpa_onnx/lib/src/offline_speech_denoiser.dart +++ b/flutter/sherpa_onnx/lib/src/offline_speech_denoiser.dart @@ -23,6 +23,8 @@ class OfflineSpeechDenoiser { final c = calloc(); c.ref.model.gtcrn.model = config.model.gtcrn.model.toNativeUtf8(); c.ref.model.dpdfnet.model = config.model.dpdfnet.model.toNativeUtf8(); + c.ref.model.dpdfnet.attenuationLimitDb = + config.model.dpdfnet.attenuationLimitDb; c.ref.model.numThreads = config.model.numThreads; c.ref.model.debug = config.model.debug ? 1 : 0; diff --git a/flutter/sherpa_onnx/lib/src/offline_speech_denoiser_config.dart b/flutter/sherpa_onnx/lib/src/offline_speech_denoiser_config.dart index d767661bc4..7de13e7413 100644 --- a/flutter/sherpa_onnx/lib/src/offline_speech_denoiser_config.dart +++ b/flutter/sherpa_onnx/lib/src/offline_speech_denoiser_config.dart @@ -35,25 +35,31 @@ class OfflineSpeechDenoiserGtcrnModelConfig { class OfflineSpeechDenoiserDpdfNetModelConfig { const OfflineSpeechDenoiserDpdfNetModelConfig({ this.model = '', + this.attenuationLimitDb = 0.0, }); factory OfflineSpeechDenoiserDpdfNetModelConfig.fromJson( Map json) { return OfflineSpeechDenoiserDpdfNetModelConfig( model: json['model'] as String? ?? '', + attenuationLimitDb: + (json['attenuation_limit_db'] as num?)?.toDouble() ?? 0.0, ); } @override String toString() { - return 'OfflineSpeechDenoiserDpdfNetModelConfig(model: $model)'; + return 'OfflineSpeechDenoiserDpdfNetModelConfig(model: $model, ' + 'attenuationLimitDb: $attenuationLimitDb)'; } Map toJson() => { 'model': model, + 'attenuation_limit_db': attenuationLimitDb, }; final String model; + final double attenuationLimitDb; } /// Aggregate model configuration for [OfflineSpeechDenoiser]. diff --git a/flutter/sherpa_onnx/lib/src/sherpa_onnx_bindings.dart b/flutter/sherpa_onnx/lib/src/sherpa_onnx_bindings.dart index 446e18393f..95a0ee4b4d 100644 --- a/flutter/sherpa_onnx/lib/src/sherpa_onnx_bindings.dart +++ b/flutter/sherpa_onnx/lib/src/sherpa_onnx_bindings.dart @@ -8,6 +8,9 @@ final class SherpaOnnxOfflineSpeechDenoiserGtcrnModelConfig extends Struct { final class SherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig extends Struct { external Pointer model; + + @Float() + external double attenuationLimitDb; } final class SherpaOnnxOfflineSpeechDenoiserModelConfig extends Struct { diff --git a/go-api-examples/speech-enhancement-dpdfnet/main.go b/go-api-examples/speech-enhancement-dpdfnet/main.go index f0e0677cf3..e108c4f517 100644 --- a/go-api-examples/speech-enhancement-dpdfnet/main.go +++ b/go-api-examples/speech-enhancement-dpdfnet/main.go @@ -10,6 +10,7 @@ func main() { config := sherpa.OfflineSpeechDenoiserConfig{} config.Model.DpdfNet.Model = "./dpdfnet_baseline.onnx" + config.Model.DpdfNet.AttenuationLimitDb = 12 config.Model.NumThreads = 1 config.Model.Debug = 1 diff --git a/harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/speech-denoiser.h b/harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/speech-denoiser.h index 975d23ea84..b7ce736595 100644 --- a/harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/speech-denoiser.h +++ b/harmony-os/SherpaOnnxHar/sherpa_onnx/src/main/cpp/speech-denoiser.h @@ -36,6 +36,7 @@ GetSpeechDenoiserDpdfNetModelConfig(Napi::Object obj) { Napi::Object o = obj.Get("dpdfnet").As(); SHERPA_ONNX_ASSIGN_ATTR_STR(model, model); + SHERPA_ONNX_ASSIGN_ATTR_FLOAT(attenuation_limit_db, attenuationLimitDb); return c; } diff --git a/java-api-examples/NonStreamingSpeechEnhancementDpdfNet.java b/java-api-examples/NonStreamingSpeechEnhancementDpdfNet.java index 5ff7f1ca0e..a69b43d8a2 100644 --- a/java-api-examples/NonStreamingSpeechEnhancementDpdfNet.java +++ b/java-api-examples/NonStreamingSpeechEnhancementDpdfNet.java @@ -21,11 +21,16 @@ public static void main(String[] args) { .setDebug(true) .setProvider("cpu") .setDpdfnet( - OfflineSpeechDenoiserDpdfNetModelConfig.builder().setModel(model).build()); + OfflineSpeechDenoiserDpdfNetModelConfig.builder() + .setModel(model) + .setAttenuationLimitDb(12.0f) + .build()); OfflineSpeechDenoiserModelConfig modelConfig = builder.build(); OfflineSpeechDenoiserConfig config = - OfflineSpeechDenoiserConfig.builder().setModel(modelConfig).build(); + OfflineSpeechDenoiserConfig.builder() + .setModel(modelConfig) + .build(); OfflineSpeechDenoiser speech_denoiser = new OfflineSpeechDenoiser(config); diff --git a/kotlin-api-examples/test_offline_speech_denoiser_dpdfnet.kt b/kotlin-api-examples/test_offline_speech_denoiser_dpdfnet.kt index 0afdbaa628..dc3fc0de49 100644 --- a/kotlin-api-examples/test_offline_speech_denoiser_dpdfnet.kt +++ b/kotlin-api-examples/test_offline_speech_denoiser_dpdfnet.kt @@ -14,7 +14,8 @@ fun createOfflineSpeechDenoiserDpdfNet(): OfflineSpeechDenoiser { val config = OfflineSpeechDenoiserConfig( model = OfflineSpeechDenoiserModelConfig( dpdfnet = OfflineSpeechDenoiserDpdfNetModelConfig( - model = "./dpdfnet_baseline.onnx" + model = "./dpdfnet_baseline.onnx", + attenuationLimitDb = 12.0f, ), provider = "cpu", numThreads = 1, diff --git a/nodejs-addon-examples/test_offline_speech_enhancement_dpdfnet.js b/nodejs-addon-examples/test_offline_speech_enhancement_dpdfnet.js index 3e0e69a33e..aef66c4775 100644 --- a/nodejs-addon-examples/test_offline_speech_enhancement_dpdfnet.js +++ b/nodejs-addon-examples/test_offline_speech_enhancement_dpdfnet.js @@ -7,7 +7,10 @@ function createOfflineSpeechDenoiser() { // https://github.com/k2-fsa/sherpa-onnx/releases/tag/speech-enhancement-models const config = { model: { - dpdfnet: {model: './dpdfnet_baseline.onnx'}, + dpdfnet: { + model: './dpdfnet_baseline.onnx', + attenuationLimitDb: 12, + }, debug: true, numThreads: 1, }, diff --git a/nodejs-examples/test-offline-speech-enhancement-dpdfnet.js b/nodejs-examples/test-offline-speech-enhancement-dpdfnet.js index caae82ffd5..312209a32e 100644 --- a/nodejs-examples/test-offline-speech-enhancement-dpdfnet.js +++ b/nodejs-examples/test-offline-speech-enhancement-dpdfnet.js @@ -15,7 +15,7 @@ function createOfflineSpeechDenoiser() { const model = './dpdfnet2.onnx'; let config = { model: { - dpdfnet: {model}, + dpdfnet: {model, attenuationLimitDb: 12}, debug: 1, }, }; diff --git a/pascal-api-examples/speech-enhancement-dpdfnet/dpdfnet.pas b/pascal-api-examples/speech-enhancement-dpdfnet/dpdfnet.pas index 0d3adfa135..008a6a6336 100644 --- a/pascal-api-examples/speech-enhancement-dpdfnet/dpdfnet.pas +++ b/pascal-api-examples/speech-enhancement-dpdfnet/dpdfnet.pas @@ -30,6 +30,7 @@ Initialize(Config); Config.Model.DpdfNet.Model := './dpdfnet_baseline.onnx'; + Config.Model.DpdfNet.AttenuationLimitDb := 12.0; Config.Model.NumThreads:= 1; Config.Model.Debug:= True; Config.Model.Provider:= 'cpu'; diff --git a/python-api-examples/README.md b/python-api-examples/README.md index 1d871db103..c85b94a602 100644 --- a/python-api-examples/README.md +++ b/python-api-examples/README.md @@ -21,9 +21,10 @@ - [online-speech-enhancement-dpdfnet.py](./online-speech-enhancement-dpdfnet.py) It shows how to use the online speech denoiser API with DPDFNet. - models. Use 16 kHz DPDFNet models such as `dpdfnet_baseline.onnx`, + Use 16 kHz DPDFNet models such as `dpdfnet_baseline.onnx`, `dpdfnet2.onnx`, `dpdfnet4.onnx`, or `dpdfnet8.onnx` for downstream ASR and - `dpdfnet2_48khz_hr.onnx` for 48 kHz enhancement output. + `dpdfnet2_8khz.onnx` or `dpdfnet8_8khz.onnx` for 8 kHz enhancement. + Use `dpdfnet2_48khz_hr.onnx` or `dpdfnet8_48khz_hr.onnx` for 48 kHz output. - [pocket-tts.py](./pocket-tts.py) It shows how to use PocketTTS with the `GenerationConfig` API. diff --git a/python-api-examples/offline-speech-enhancement-dpdfnet.py b/python-api-examples/offline-speech-enhancement-dpdfnet.py index d25e837535..b65f5fc960 100755 --- a/python-api-examples/offline-speech-enhancement-dpdfnet.py +++ b/python-api-examples/offline-speech-enhancement-dpdfnet.py @@ -15,11 +15,15 @@ wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/dpdfnet4.onnx wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/dpdfnet8.onnx wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/dpdfnet2_48khz_hr.onnx + wget https://huggingface.co/Ceva-IP/DPDFNet/resolve/main/onnx/dpdfnet2_8khz.onnx + wget https://huggingface.co/Ceva-IP/DPDFNet/resolve/main/onnx/dpdfnet8_8khz.onnx + wget https://huggingface.co/Ceva-IP/DPDFNet/resolve/main/onnx/dpdfnet8_48khz_hr.onnx wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement-models/speech_with_noise.wav Use 16 kHz DPDFNet models such as `dpdfnet_baseline.onnx`, `dpdfnet2.onnx`, `dpdfnet4.onnx`, or `dpdfnet8.onnx` for downstream ASR or speech recognition. -Use `dpdfnet2_48khz_hr.onnx` for 48 kHz enhancement output. +Use `dpdfnet2_8khz.onnx` or `dpdfnet8_8khz.onnx` for 8 kHz enhancement, and +`dpdfnet2_48khz_hr.onnx` or `dpdfnet8_48khz_hr.onnx` for 48 kHz output. """ import time @@ -45,12 +49,13 @@ def create_speech_denoiser(): config = sherpa_onnx.OfflineSpeechDenoiserConfig( model=sherpa_onnx.OfflineSpeechDenoiserModelConfig( dpdfnet=sherpa_onnx.OfflineSpeechDenoiserDpdfNetModelConfig( - model=model_filename + model=model_filename, + attenuation_limit_db=12.0, ), debug=False, num_threads=1, provider="cpu", - ) + ), ) if not config.validate(): print(config) diff --git a/rust-api-examples/examples/offline_speech_enhancement_dpdfnet.rs b/rust-api-examples/examples/offline_speech_enhancement_dpdfnet.rs index 95a53f1b9b..882dd4a159 100644 --- a/rust-api-examples/examples/offline_speech_enhancement_dpdfnet.rs +++ b/rust-api-examples/examples/offline_speech_enhancement_dpdfnet.rs @@ -24,6 +24,7 @@ fn main() -> anyhow::Result<()> { model: sherpa_onnx::OfflineSpeechDenoiserModelConfig { dpdfnet: OfflineSpeechDenoiserDpdfNetModelConfig { model: Some(args.model), + attenuation_limit_db: 12.0, }, ..Default::default() }, diff --git a/rust-api-examples/examples/streaming_speech_enhancement_dpdfnet.rs b/rust-api-examples/examples/streaming_speech_enhancement_dpdfnet.rs index e31f130a35..87ba8da378 100644 --- a/rust-api-examples/examples/streaming_speech_enhancement_dpdfnet.rs +++ b/rust-api-examples/examples/streaming_speech_enhancement_dpdfnet.rs @@ -1,7 +1,7 @@ use clap::Parser; use sherpa_onnx::{ - write, OfflineSpeechDenoiserDpdfNetModelConfig, OnlineSpeechDenoiser, OnlineSpeechDenoiserConfig, - Wave, + write, OfflineSpeechDenoiserDpdfNetModelConfig, OnlineSpeechDenoiser, + OnlineSpeechDenoiserConfig, Wave, }; #[derive(Parser, Debug)] @@ -24,6 +24,7 @@ fn main() -> anyhow::Result<()> { model: sherpa_onnx::OfflineSpeechDenoiserModelConfig { dpdfnet: OfflineSpeechDenoiserDpdfNetModelConfig { model: Some(args.model), + ..Default::default() }, ..Default::default() }, diff --git a/scripts/dotnet/OfflineSpeechDenoiserDpdfNetModelConfig.cs b/scripts/dotnet/OfflineSpeechDenoiserDpdfNetModelConfig.cs index d9234c1502..9f2ec232f0 100644 --- a/scripts/dotnet/OfflineSpeechDenoiserDpdfNetModelConfig.cs +++ b/scripts/dotnet/OfflineSpeechDenoiserDpdfNetModelConfig.cs @@ -10,9 +10,11 @@ public struct OfflineSpeechDenoiserDpdfNetModelConfig public OfflineSpeechDenoiserDpdfNetModelConfig() { Model = ""; + AttenuationLimitDb = 0.0f; } [MarshalAs(UnmanagedType.LPStr)] public string Model; + public float AttenuationLimitDb; } } diff --git a/scripts/go/sherpa_onnx.go b/scripts/go/sherpa_onnx.go index a6938ad2d5..f1ac2d6bfa 100644 --- a/scripts/go/sherpa_onnx.go +++ b/scripts/go/sherpa_onnx.go @@ -2570,7 +2570,8 @@ type OfflineSpeechDenoiserGtcrnModelConfig struct { } type OfflineSpeechDenoiserDpdfNetModelConfig struct { - Model string + Model string + AttenuationLimitDb float32 } type OfflineSpeechDenoiserModelConfig struct { @@ -2650,6 +2651,7 @@ func NewOfflineSpeechDenoiser(config *OfflineSpeechDenoiserConfig) *OfflineSpeec defer C.free(unsafe.Pointer(c.model.gtcrn.model)) c.model.dpdfnet.model = C.CString(config.Model.DpdfNet.Model) defer C.free(unsafe.Pointer(c.model.dpdfnet.model)) + c.model.dpdfnet.attenuation_limit_db = C.float(config.Model.DpdfNet.AttenuationLimitDb) c.model.num_threads = C.int(config.Model.NumThreads) c.model.debug = C.int(config.Model.Debug) diff --git a/scripts/node-addon-api/lib/types.js b/scripts/node-addon-api/lib/types.js index 3f882d7b09..98f6b78eb6 100644 --- a/scripts/node-addon-api/lib/types.js +++ b/scripts/node-addon-api/lib/types.js @@ -616,9 +616,10 @@ */ /** - * Offline Speech Denoiser model config - * @typedef {Object} OfflineSpeechDenoiserDpdfNetModelConfig - * @property {string} [model] + * Offline Speech Denoiser model config + * @typedef {Object} OfflineSpeechDenoiserDpdfNetModelConfig + * @property {string} [model] + * @property {number} [attenuationLimitDb] Offline attenuation limit in dB. */ /** @@ -632,10 +633,10 @@ */ /** - * Offline Speech Denoiser configuration (partial). - * @typedef {Object} OfflineSpeechDenoiserConfig - * @property {OfflineSpeechDenoiserModelConfig} [model] - */ + * Offline Speech Denoiser configuration (partial). + * @typedef {Object} OfflineSpeechDenoiserConfig + * @property {OfflineSpeechDenoiserModelConfig} [model] + */ /** * Online Speech Denoiser configuration (partial). diff --git a/sherpa-onnx/c-api/c-api.cc b/sherpa-onnx/c-api/c-api.cc index 6278cb210d..4db9fb8f0c 100644 --- a/sherpa-onnx/c-api/c-api.cc +++ b/sherpa-onnx/c-api/c-api.cc @@ -2828,6 +2828,8 @@ static sherpa_onnx::OfflineSpeechDenoiserConfig GetOfflineSpeechDenoiserConfig( 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.dpdfnet.attenuation_limit_db = + config->model.dpdfnet.attenuation_limit_db; if (c.model.debug) { #if __OHOS__ diff --git a/sherpa-onnx/c-api/c-api.h b/sherpa-onnx/c-api/c-api.h index f961035d9b..3a1c53a81f 100644 --- a/sherpa-onnx/c-api/c-api.h +++ b/sherpa-onnx/c-api/c-api.h @@ -4098,6 +4098,15 @@ typedef struct SherpaOnnxOfflineSpeechDenoiserGtcrnModelConfig { typedef struct SherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig { /** Model filename. */ const char *model; + /** + * Offline attenuation limit in dB. + * + * Values greater than 0 limit suppression by blending aligned noisy spectra + * into the enhanced spectra with a noisy-signal weight of + * `10^(-limit_db / 20)`. The maximum finite value is 100. Set to 0 or + * infinity to disable the limit. + */ + float attenuation_limit_db; } SherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig; /** diff --git a/sherpa-onnx/c-api/cxx-api.cc b/sherpa-onnx/c-api/cxx-api.cc index e31fe2679c..8e9d7a9772 100644 --- a/sherpa-onnx/c-api/cxx-api.cc +++ b/sherpa-onnx/c-api/cxx-api.cc @@ -20,6 +20,7 @@ static void FillSpeechDenoiserModelConfig( memset(dst, 0, sizeof(*dst)); 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->num_threads = src.num_threads; dst->provider = src.provider.c_str(); dst->debug = src.debug; diff --git a/sherpa-onnx/c-api/cxx-api.h b/sherpa-onnx/c-api/cxx-api.h index 30b255fed3..feb8d68bfc 100644 --- a/sherpa-onnx/c-api/cxx-api.h +++ b/sherpa-onnx/c-api/cxx-api.h @@ -1219,6 +1219,8 @@ struct OfflineSpeechDenoiserGtcrnModelConfig { struct OfflineSpeechDenoiserDpdfNetModelConfig { /** Model ONNX file. */ std::string model; + /** Offline attenuation limit in dB. 0 disables it. */ + float attenuation_limit_db = 0.0f; }; /** diff --git a/sherpa-onnx/c-api/docs/speech-enhancement.dox b/sherpa-onnx/c-api/docs/speech-enhancement.dox index cacdefedc8..34ff145838 100644 --- a/sherpa-onnx/c-api/docs/speech-enhancement.dox +++ b/sherpa-onnx/c-api/docs/speech-enhancement.dox @@ -39,6 +39,7 @@ Example source: [speech-enhancement-gtcrn-c-api.c](https://github.com/k2-fsa/she SherpaOnnxOfflineSpeechDenoiserConfig config; memset(&config, 0, sizeof(config)); config.model.dpdfnet.model = "./dpdfnet_baseline.onnx"; +config.model.dpdfnet.attenuation_limit_db = 12.0f; config.model.num_threads = 1; config.model.provider = "cpu"; @@ -49,7 +50,8 @@ SherpaOnnxDestroyOfflineSpeechDenoiser(sd); @endcode Model file: `dpdfnet_baseline.onnx` (also: `dpdfnet2.onnx`, `dpdfnet4.onnx`, -`dpdfnet8.onnx` for 16 kHz; `dpdfnet2_48khz_hr.onnx` for 48 kHz) +`dpdfnet8.onnx` for 16 kHz; `dpdfnet2_8khz.onnx`, `dpdfnet8_8khz.onnx` for +8 kHz; and `dpdfnet2_48khz_hr.onnx`, `dpdfnet8_48khz_hr.onnx` for 48 kHz) Example source: [speech-enhancement-dpdfnet-c-api.c](https://github.com/k2-fsa/sherpa-onnx/blob/master/c-api-examples/speech-enhancement-dpdfnet-c-api.c) @@ -92,7 +94,9 @@ const SherpaOnnxOnlineSpeechDenoiser *sd = SherpaOnnxDestroyOnlineSpeechDenoiser(sd); @endcode -Model file: `dpdfnet_baseline.onnx` +Model files: `dpdfnet_baseline.onnx`, `dpdfnet2.onnx`, `dpdfnet4.onnx`, +`dpdfnet8.onnx` for 16 kHz; `dpdfnet2_8khz.onnx`, `dpdfnet8_8khz.onnx` for +8 kHz; and `dpdfnet2_48khz_hr.onnx`, `dpdfnet8_48khz_hr.onnx` for 48 kHz. Example source: [online-speech-enhancement-dpdfnet-c-api.c](https://github.com/k2-fsa/sherpa-onnx/blob/master/c-api-examples/online-speech-enhancement-dpdfnet-c-api.c) */ diff --git a/sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-impl.h b/sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-impl.h index c849c9639e..c5b75f6fce 100644 --- a/sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-impl.h +++ b/sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-impl.h @@ -14,6 +14,7 @@ #include "kaldi-native-fbank/csrc/istft.h" #include "kaldi-native-fbank/csrc/stft.h" +#include "sherpa-onnx/csrc/macros.h" #include "sherpa-onnx/csrc/math.h" #include "sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-model.h" #include "sherpa-onnx/csrc/offline-speech-denoiser-impl.h" @@ -26,12 +27,14 @@ class OfflineSpeechDenoiserDpdfNetImpl : public OfflineSpeechDenoiserImpl { public: explicit OfflineSpeechDenoiserDpdfNetImpl( const OfflineSpeechDenoiserConfig &config) - : model_(config.model) {} + : model_(config.model), + attenuation_limit_db_(config.model.dpdfnet.attenuation_limit_db) {} template OfflineSpeechDenoiserDpdfNetImpl(Manager *mgr, const OfflineSpeechDenoiserConfig &config) - : model_(mgr, config.model) {} + : model_(mgr, config.model), + attenuation_limit_db_(config.model.dpdfnet.attenuation_limit_db) {} DenoisedAudio Run(const float *samples, int32_t n, int32_t sample_rate) const override { @@ -78,6 +81,11 @@ class OfflineSpeechDenoiserDpdfNetImpl : public OfflineSpeechDenoiserImpl { frame.second.end()); } + if (!ApplyAttenuationLimit(stft_result, attenuation_limit_db_, + &enhanced_stft_result)) { + return {}; + } + knf::IStft istft(stft_config); DenoisedAudio denoised_audio; @@ -92,6 +100,57 @@ class OfflineSpeechDenoiserDpdfNetImpl : public OfflineSpeechDenoiserImpl { } private: + static bool ApplyAttenuationLimit(const knf::StftResult &noisy, + float attenuation_limit_db, + knf::StftResult *enhanced) { + if (attenuation_limit_db <= 0.0f || std::isinf(attenuation_limit_db)) { + return true; + } + + if (noisy.num_frames != enhanced->num_frames || + noisy.real.size() != enhanced->real.size() || + noisy.imag.size() != enhanced->imag.size()) { + SHERPA_ONNX_LOGE( + "Cannot apply the DPDFNet attenuation limit because noisy and " + "enhanced STFT shapes differ"); + return false; + } + + constexpr int32_t kNoisyFrameOffset = 4; + const int32_t num_frames = noisy.num_frames; + if (num_frames <= 0) { + return true; + } + + const int32_t num_bins = + static_cast(noisy.real.size()) / num_frames; + const float alpha = std::pow(10.0f, -attenuation_limit_db / 20.0f); + const float enhanced_scale = 1.0f - alpha; + + for (int32_t frame = 0; frame < num_frames; ++frame) { + const int32_t enhanced_offset = frame * num_bins; + const int32_t noisy_frame = frame - kNoisyFrameOffset; + + for (int32_t bin = 0; bin < num_bins; ++bin) { + float noisy_real = 0.0f; + float noisy_imag = 0.0f; + if (noisy_frame >= 0) { + const int32_t noisy_offset = noisy_frame * num_bins + bin; + noisy_real = noisy.real[noisy_offset]; + noisy_imag = noisy.imag[noisy_offset]; + } + + const int32_t i = enhanced_offset + bin; + enhanced->real[i] = + alpha * noisy_real + enhanced_scale * enhanced->real[i]; + enhanced->imag[i] = + alpha * noisy_imag + enhanced_scale * enhanced->imag[i]; + } + } + + return true; + } + static std::vector ShiftWaveform(std::vector samples, int32_t shift) { if (samples.size() > static_cast(shift)) { @@ -163,6 +222,7 @@ class OfflineSpeechDenoiserDpdfNetImpl : public OfflineSpeechDenoiserImpl { private: OfflineSpeechDenoiserDpdfNetModel model_; + float attenuation_limit_db_ = 0.0f; }; } // namespace sherpa_onnx diff --git a/sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-model-config.cc b/sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-model-config.cc index 676ff114c7..a526b25f55 100644 --- a/sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-model-config.cc +++ b/sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-model-config.cc @@ -4,6 +4,7 @@ #include "sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-model-config.h" +#include #include #include @@ -15,12 +16,21 @@ namespace sherpa_onnx { void OfflineSpeechDenoiserDpdfNetModelConfig::Register(ParseOptions *po) { po->Register("speech-denoiser-dpdfnet-model", &model, "Path to a DPDFNet ONNX model for speech denoising, e.g. " - "baseline/dpdfnet2/dpdfnet4/dpdfnet8 (16 kHz) or " - "dpdfnet2_48khz_hr (48 kHz). Download DPDFNet models from the " + "baseline/dpdfnet2/dpdfnet4/dpdfnet8 (16 kHz), " + "dpdfnet2_8khz/dpdfnet8_8khz (8 kHz), or " + "dpdfnet2_48khz_hr/dpdfnet8_48khz_hr (48 kHz). " + "Download DPDFNet models from the " "sherpa-onnx GitHub release or the official Hugging Face hub: " "https://github.com/k2-fsa/sherpa-onnx/releases/tag/" "speech-enhancement-models or " "https://huggingface.co/Ceva-IP/DPDFNet"); + + po->Register( + "speech-denoiser-dpdfnet-attenuation-limit-db", &attenuation_limit_db, + "Offline-only DPDFNet attenuation limit in dB. Values greater than 0 " + "limit suppression by blending aligned noisy spectra into the enhanced " + "spectra. The maximum finite value is 100. 0 or infinity disables the " + "limit."); } bool OfflineSpeechDenoiserDpdfNetModelConfig::Validate() const { @@ -34,6 +44,14 @@ bool OfflineSpeechDenoiserDpdfNetModelConfig::Validate() const { return false; } + if (std::isnan(attenuation_limit_db) || attenuation_limit_db < 0.0f || + (attenuation_limit_db > 100.0f && !std::isinf(attenuation_limit_db))) { + SHERPA_ONNX_LOGE( + "attenuation_limit_db must be in [0, 100] or infinity. Given: %f", + attenuation_limit_db); + return false; + } + return true; } @@ -41,7 +59,8 @@ std::string OfflineSpeechDenoiserDpdfNetModelConfig::ToString() const { std::ostringstream os; os << "OfflineSpeechDenoiserDpdfNetModelConfig("; - os << "model=\"" << model << "\")"; + os << "model=\"" << model << "\", "; + os << "attenuation_limit_db=" << attenuation_limit_db << ")"; return os.str(); } diff --git a/sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-model-config.h b/sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-model-config.h index 6f3b4adac5..a052cd9361 100644 --- a/sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-model-config.h +++ b/sherpa-onnx/csrc/offline-speech-denoiser-dpdfnet-model-config.h @@ -12,6 +12,9 @@ namespace sherpa_onnx { struct OfflineSpeechDenoiserDpdfNetModelConfig { std::string model; + // Offline attenuation limit in dB. A value of 0 disables it. + float attenuation_limit_db = 0.0f; + OfflineSpeechDenoiserDpdfNetModelConfig() = default; void Register(ParseOptions *po); diff --git a/sherpa-onnx/csrc/online-speech-denoiser-dpdfnet-impl.h b/sherpa-onnx/csrc/online-speech-denoiser-dpdfnet-impl.h index b1d4d02e3b..40b3b3311e 100644 --- a/sherpa-onnx/csrc/online-speech-denoiser-dpdfnet-impl.h +++ b/sherpa-onnx/csrc/online-speech-denoiser-dpdfnet-impl.h @@ -67,10 +67,13 @@ class OnlineSpeechDenoiserDpdfNetImpl : public OnlineSpeechDenoiserImpl { void Init() { const auto &meta = model_.GetMetaData(); if (meta.profile != "dpdfnet_16khz" && - meta.profile != "dpdfnet2_48khz_hr") { + meta.profile != "dpdfnet2_8khz" && + meta.profile != "dpdfnet8_8khz" && + meta.profile != "dpdfnet2_48khz_hr" && + meta.profile != "dpdfnet8_48khz_hr") { SHERPA_ONNX_LOGE( - "Online speech denoiser currently supports only DPDFNet streaming " - "exports. Given profile: %s", + "Online speech denoiser supports the official 8, 16, and 48 kHz " + "DPDFNet streaming exports. Given profile: %s", meta.profile.c_str()); SHERPA_ONNX_EXIT(-1); } diff --git a/sherpa-onnx/csrc/sherpa-onnx-offline-denoiser.cc b/sherpa-onnx/csrc/sherpa-onnx-offline-denoiser.cc index a614473f2d..d8b65ea5c2 100644 --- a/sherpa-onnx/csrc/sherpa-onnx-offline-denoiser.cc +++ b/sherpa-onnx/csrc/sherpa-onnx-offline-denoiser.cc @@ -7,8 +7,8 @@ #include #include -#include "sherpa-onnx/csrc/offline-speech-denoiser.h" #include "sherpa-onnx/csrc/macros.h" +#include "sherpa-onnx/csrc/offline-speech-denoiser.h" #include "sherpa-onnx/csrc/wave-reader.h" #include "sherpa-onnx/csrc/wave-writer.h" @@ -30,7 +30,7 @@ wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement- --input-wav=input.wav \ --output-wav=output_16k.wav -(2) Use DPDFNet models at 16 kHz or 48 kHz +(2) Use DPDFNet models at 8, 16, or 48 kHz # Download DPDFNet models from either: # https://github.com/k2-fsa/sherpa-onnx/releases/tag/speech-enhancement-models @@ -38,6 +38,7 @@ wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement- ./bin/sherpa-onnx-offline-denoiser \ --speech-denoiser-dpdfnet-model=dpdfnet4.onnx \ + --speech-denoiser-dpdfnet-attenuation-limit-db=12 \ --input-wav=input.wav \ --output-wav=output_16k.wav @@ -45,11 +46,16 @@ wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement- # dpdfnet_baseline.onnx # dpdfnet2.onnx # dpdfnet8.onnx +# Or the 8 kHz DPDFNet models: +# dpdfnet2_8khz.onnx +# dpdfnet8_8khz.onnx ./bin/sherpa-onnx-offline-denoiser \ --speech-denoiser-dpdfnet-model=dpdfnet2_48khz_hr.onnx \ --input-wav=input.wav \ --output-wav=output_48k.wav + +# For the highest-quality 48 kHz model, use dpdfnet8_48khz_hr.onnx. )usage"; sherpa_onnx::ParseOptions po(kUsageMessage); @@ -69,6 +75,11 @@ wget https://github.com/k2-fsa/sherpa-onnx/releases/download/speech-enhancement- } fprintf(stderr, "%s\n", config.ToString().c_str()); + if (!config.Validate()) { + fprintf(stderr, "Errors in config!\n"); + return -1; + } + if (input_wave.empty()) { fprintf(stderr, "Please provide --input-wav\n"); po.PrintUsage(); diff --git a/sherpa-onnx/csrc/sherpa-onnx-online-denoiser.cc b/sherpa-onnx/csrc/sherpa-onnx-online-denoiser.cc index 0769521e51..48976f060c 100644 --- a/sherpa-onnx/csrc/sherpa-onnx-online-denoiser.cc +++ b/sherpa-onnx/csrc/sherpa-onnx-online-denoiser.cc @@ -34,7 +34,10 @@ Currently this binary supports: dpdfnet2.onnx dpdfnet4.onnx dpdfnet8.onnx + dpdfnet2_8khz.onnx + dpdfnet8_8khz.onnx dpdfnet2_48khz_hr.onnx + dpdfnet8_48khz_hr.onnx Usage: @@ -55,6 +58,9 @@ Currently this binary supports: --chunk-duration-ms=10 \ --input-wav=input.wav \ --output-wav=output_48k.wav + +# Use dpdfnet2_8khz.onnx or dpdfnet8_8khz.onnx for 8 kHz audio, and +# dpdfnet8_48khz_hr.onnx for the highest-quality 48 kHz audio. )usage"; sherpa_onnx::ParseOptions po(kUsageMessage); diff --git a/sherpa-onnx/java-api/src/main/java/com/k2fsa/sherpa/onnx/OfflineSpeechDenoiserDpdfNetModelConfig.java b/sherpa-onnx/java-api/src/main/java/com/k2fsa/sherpa/onnx/OfflineSpeechDenoiserDpdfNetModelConfig.java index 6e6eb02fc5..8acec031c4 100644 --- a/sherpa-onnx/java-api/src/main/java/com/k2fsa/sherpa/onnx/OfflineSpeechDenoiserDpdfNetModelConfig.java +++ b/sherpa-onnx/java-api/src/main/java/com/k2fsa/sherpa/onnx/OfflineSpeechDenoiserDpdfNetModelConfig.java @@ -3,9 +3,11 @@ public class OfflineSpeechDenoiserDpdfNetModelConfig { private final String model; + private final float attenuationLimitDb; private OfflineSpeechDenoiserDpdfNetModelConfig(Builder builder) { this.model = builder.model; + this.attenuationLimitDb = builder.attenuationLimitDb; } public static Builder builder() { @@ -16,8 +18,13 @@ public String getModel() { return model; } + public float getAttenuationLimitDb() { + return attenuationLimitDb; + } + public static class Builder { private String model = ""; + private float attenuationLimitDb = 0.0f; public OfflineSpeechDenoiserDpdfNetModelConfig build() { return new OfflineSpeechDenoiserDpdfNetModelConfig(this); @@ -27,5 +34,10 @@ public Builder setModel(String model) { this.model = model; return this; } + + public Builder setAttenuationLimitDb(float value) { + this.attenuationLimitDb = value; + return this; + } } } diff --git a/sherpa-onnx/jni/speech-denoiser.cc b/sherpa-onnx/jni/speech-denoiser.cc index 341bb586cd..e48fd39e09 100644 --- a/sherpa-onnx/jni/speech-denoiser.cc +++ b/sherpa-onnx/jni/speech-denoiser.cc @@ -30,6 +30,8 @@ OfflineSpeechDenoiserModelConfig GetOfflineSpeechDenoiserModelConfig( jclass dpdfnet_cls = env->GetObjectClass(dpdfnet); SHERPA_ONNX_JNI_READ_STRING(ans.dpdfnet.model, model, dpdfnet_cls, dpdfnet); + SHERPA_ONNX_JNI_READ_FLOAT(ans.dpdfnet.attenuation_limit_db, + attenuationLimitDb, dpdfnet_cls, dpdfnet); SHERPA_ONNX_JNI_READ_INT(ans.num_threads, numThreads, model_config_cls, model); diff --git a/sherpa-onnx/kotlin-api/OfflineSpeechDenoiser.kt b/sherpa-onnx/kotlin-api/OfflineSpeechDenoiser.kt index fd940ec758..450dbe9eec 100644 --- a/sherpa-onnx/kotlin-api/OfflineSpeechDenoiser.kt +++ b/sherpa-onnx/kotlin-api/OfflineSpeechDenoiser.kt @@ -8,6 +8,7 @@ data class OfflineSpeechDenoiserGtcrnModelConfig( data class OfflineSpeechDenoiserDpdfNetModelConfig( var model: String = "", + var attenuationLimitDb: Float = 0.0f, ) data class OfflineSpeechDenoiserModelConfig( diff --git a/sherpa-onnx/pascal-api/sherpa_onnx.pas b/sherpa-onnx/pascal-api/sherpa_onnx.pas index 3008ba402d..cc8e86aae6 100644 --- a/sherpa-onnx/pascal-api/sherpa_onnx.pas +++ b/sherpa-onnx/pascal-api/sherpa_onnx.pas @@ -732,6 +732,7 @@ TSherpaOnnxOfflineSpeechDenoiserGtcrnModelConfig = record TSherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig = record Model: AnsiString; + AttenuationLimitDb: Single; function ToString: AnsiString; end; @@ -1305,6 +1306,7 @@ SherpaOnnxOfflineSpeechDenoiserGtcrnModelConfig = record SherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig = record Model: PAnsiChar; + AttenuationLimitDb: cfloat; end; SherpaOnnxOfflineSpeechDenoiserModelConfig = record @@ -3422,7 +3424,8 @@ function TSherpaOnnxOfflineSpeechDenoiserGtcrnModelConfig.ToString: AnsiString; function TSherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig.ToString: AnsiString; begin Result := Format('TSherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig(' + - 'Model := %s)', [Self.Model]); + 'Model := %s, AttenuationLimitDb := %f)', + [Self.Model, Self.AttenuationLimitDb]); end; function TSherpaOnnxOfflineSpeechDenoiserModelConfig.ToString: AnsiString; @@ -3478,6 +3481,8 @@ constructor TSherpaOnnxOfflineSpeechDenoiser.Create(Config: TSherpaOnnxOfflineSp C := Default(SherpaOnnxOfflineSpeechDenoiserConfig); C.Model.Gtcrn.Model := PAnsiChar(Config.Model.Gtcrn.Model); C.Model.DpdfNet.Model := PAnsiChar(Config.Model.DpdfNet.Model); + C.Model.DpdfNet.AttenuationLimitDb := + Config.Model.DpdfNet.AttenuationLimitDb; C.Model.NumThreads := Config.Model.NumThreads; C.Model.Debug := Ord(Config.Model.Debug); C.Model.Provider := PAnsiChar(Config.Model.Provider); diff --git a/sherpa-onnx/python/csrc/offline-speech-denoiser-dpdfnet-model-config.cc b/sherpa-onnx/python/csrc/offline-speech-denoiser-dpdfnet-model-config.cc index f241526c30..7225bc45d3 100644 --- a/sherpa-onnx/python/csrc/offline-speech-denoiser-dpdfnet-model-config.cc +++ b/sherpa-onnx/python/csrc/offline-speech-denoiser-dpdfnet-model-config.cc @@ -14,8 +14,15 @@ void PybindOfflineSpeechDenoiserDpdfNetModelConfig(py::module *m) { using PyClass = OfflineSpeechDenoiserDpdfNetModelConfig; py::class_(*m, "OfflineSpeechDenoiserDpdfNetModelConfig") .def(py::init<>()) - .def(py::init(), py::arg("model") = "") + .def(py::init([](const std::string &model, float attenuation_limit_db) { + PyClass ans; + ans.model = model; + ans.attenuation_limit_db = attenuation_limit_db; + return ans; + }), + py::arg("model") = "", py::arg("attenuation_limit_db") = 0.0f) .def_readwrite("model", &PyClass::model) + .def_readwrite("attenuation_limit_db", &PyClass::attenuation_limit_db) .def("validate", &PyClass::Validate) .def("__str__", &PyClass::ToString); } diff --git a/sherpa-onnx/python/csrc/offline-speech-denoiser.cc b/sherpa-onnx/python/csrc/offline-speech-denoiser.cc index 0eedf1317e..d7c230750f 100644 --- a/sherpa-onnx/python/csrc/offline-speech-denoiser.cc +++ b/sherpa-onnx/python/csrc/offline-speech-denoiser.cc @@ -49,7 +49,11 @@ void PybindOfflineSpeechDenoiserConfig(py::module *m) { py::class_(*m, "OfflineSpeechDenoiserConfig") .def(py::init<>()) - .def(py::init(), + .def(py::init([](const OfflineSpeechDenoiserModelConfig &model) { + PyClass ans; + ans.model = model; + return ans; + }), py::arg("model") = OfflineSpeechDenoiserModelConfig{}) .def_readwrite("model", &PyClass::model) .def("validate", &PyClass::Validate) diff --git a/sherpa-onnx/rust/sherpa-onnx-sys/src/speech_denoiser.rs b/sherpa-onnx/rust/sherpa-onnx-sys/src/speech_denoiser.rs index dcf7f1e0e4..2a0ca776c5 100644 --- a/sherpa-onnx/rust/sherpa-onnx-sys/src/speech_denoiser.rs +++ b/sherpa-onnx/rust/sherpa-onnx-sys/src/speech_denoiser.rs @@ -10,6 +10,7 @@ pub struct OfflineSpeechDenoiserGtcrnModelConfig { #[derive(Debug, Copy, Clone)] pub struct OfflineSpeechDenoiserDpdfNetModelConfig { pub model: *const c_char, + pub attenuation_limit_db: f32, } #[repr(C)] diff --git a/sherpa-onnx/rust/sherpa-onnx/src/offline_speech_denoiser.rs b/sherpa-onnx/rust/sherpa-onnx/src/offline_speech_denoiser.rs index b43c6b40bf..8bca823bef 100644 --- a/sherpa-onnx/rust/sherpa-onnx/src/offline_speech_denoiser.rs +++ b/sherpa-onnx/rust/sherpa-onnx/src/offline_speech_denoiser.rs @@ -33,6 +33,8 @@ impl OfflineSpeechDenoiserGtcrnModelConfig { /// DPDFNet model path for offline denoising. pub struct OfflineSpeechDenoiserDpdfNetModelConfig { pub model: Option, + /// Offline attenuation limit in dB. 0 disables it. + pub attenuation_limit_db: f32, } impl OfflineSpeechDenoiserDpdfNetModelConfig { @@ -42,6 +44,7 @@ impl OfflineSpeechDenoiserDpdfNetModelConfig { ) -> sys::OfflineSpeechDenoiserDpdfNetModelConfig { sys::OfflineSpeechDenoiserDpdfNetModelConfig { model: to_c_ptr(&self.model, cstrings), + attenuation_limit_db: self.attenuation_limit_db, } } } diff --git a/swift-api-examples/SherpaOnnx.swift b/swift-api-examples/SherpaOnnx.swift index 22e14f54e5..3aa22e91b0 100644 --- a/swift-api-examples/SherpaOnnx.swift +++ b/swift-api-examples/SherpaOnnx.swift @@ -1951,10 +1951,13 @@ public func sherpaOnnxOfflineSpeechDenoiserGtcrnModelConfig(model: String = "") return SherpaOnnxOfflineSpeechDenoiserGtcrnModelConfig(model: toCPointer(model)) } -public func sherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig(model: String = "") - -> SherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig -{ - return SherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig(model: toCPointer(model)) +public func sherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig( + model: String = "", + attenuationLimitDb: Float = 0 +) -> SherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig { + return SherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig( + model: toCPointer(model), + attenuation_limit_db: attenuationLimitDb) } public func sherpaOnnxOfflineSpeechDenoiserModelConfig( diff --git a/swift-api-examples/speech-enhancement-dpdfnet.swift b/swift-api-examples/speech-enhancement-dpdfnet.swift index 6e23651004..676bc68306 100644 --- a/swift-api-examples/speech-enhancement-dpdfnet.swift +++ b/swift-api-examples/speech-enhancement-dpdfnet.swift @@ -22,7 +22,9 @@ func run() { // Use dpdfnet2_48khz_hr.onnx for 48 kHz enhancement output. var config = sherpaOnnxOfflineSpeechDenoiserConfig( model: sherpaOnnxOfflineSpeechDenoiserModelConfig( - dpdfnet: sherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig(model: model)) + dpdfnet: sherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig( + model: model, + attenuationLimitDb: 12.0)) ) let sd = SherpaOnnxOfflineSpeechDenoiserWrapper(config: &config) diff --git a/wasm/speech-enhancement/sherpa-onnx-speech-enhancement.js b/wasm/speech-enhancement/sherpa-onnx-speech-enhancement.js index 71dbac0694..094b57c261 100644 --- a/wasm/speech-enhancement/sherpa-onnx-speech-enhancement.js +++ b/wasm/speech-enhancement/sherpa-onnx-speech-enhancement.js @@ -55,11 +55,12 @@ function initSherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig(config, Module) { const modelLen = Module.lengthBytesUTF8(config.model) + 1; const n = modelLen; const buffer = Module._malloc(n); - const len = 1 * 4; + const len = 2 * 4; const ptr = Module._malloc(len); Module.stringToUTF8(config.model, buffer, modelLen); Module.setValue(ptr, buffer, 'i8*'); + Module.setValue(ptr + 4, config.attenuationLimitDb || 0, 'float'); return { buffer: buffer, @@ -141,6 +142,30 @@ function initSherpaOnnxOfflineSpeechDenoiserConfig(config, Module) { }; } +function initSherpaOnnxOnlineSpeechDenoiserConfig(config, Module) { + if (!('model' in config)) { + config.model = { + gtcrn: {model: ''}, + dpdfnet: {model: ''}, + provider: 'cpu', + debug: 1, + numThreads: 1, + }; + } + + const modelConfig = + initSherpaOnnxOfflineSpeechDenoiserModelConfig(config.model, Module); + const len = modelConfig.len; + const ptr = Module._malloc(len); + Module._CopyHeap(modelConfig.ptr, modelConfig.len, ptr); + + return { + ptr: ptr, + len: len, + config: modelConfig, + }; +} + function copyDenoisedAudio(handle, Module) { const numSamples = Module.HEAP32[handle / 4 + 1]; const denoisedSampleRate = Module.HEAP32[handle / 4 + 2]; @@ -209,7 +234,7 @@ class OfflineSpeechDenoiser extends SpeechDenoiserBase { class OnlineSpeechDenoiser extends SpeechDenoiserBase { constructor(configObj, Module) { super(Module); - const config = initSherpaOnnxOfflineSpeechDenoiserConfig(configObj, Module); + const config = initSherpaOnnxOnlineSpeechDenoiserConfig(configObj, Module); const handle = Module._SherpaOnnxCreateOnlineSpeechDenoiser(config.ptr); freeConfig(config, Module); diff --git a/wasm/speech-enhancement/sherpa-onnx-wasm-main-speech-enhancement.cc b/wasm/speech-enhancement/sherpa-onnx-wasm-main-speech-enhancement.cc index 0b1a4353ad..2151a7952c 100644 --- a/wasm/speech-enhancement/sherpa-onnx-wasm-main-speech-enhancement.cc +++ b/wasm/speech-enhancement/sherpa-onnx-wasm-main-speech-enhancement.cc @@ -16,7 +16,7 @@ extern "C" { static_assert(sizeof(SherpaOnnxOfflineSpeechDenoiserGtcrnModelConfig) == 1 * 4, ""); static_assert(sizeof(SherpaOnnxOfflineSpeechDenoiserDpdfNetModelConfig) == - 1 * 4, + 2 * 4, ""); static_assert( sizeof(SherpaOnnxOfflineSpeechDenoiserModelConfig) == @@ -37,6 +37,8 @@ void MyPrint(SherpaOnnxOfflineSpeechDenoiserConfig *config) { fprintf(stdout, "num threads: %d\n", model->num_threads); fprintf(stdout, "debug: %d\n", model->debug); fprintf(stdout, "provider: %s\n", model->provider); + fprintf(stdout, "dpdfnet attenuation limit (dB): %.2f\n", + model->dpdfnet.attenuation_limit_db); } void CopyHeap(const char *src, int32_t num_bytes, char *dst) {