Merge pull request #6372 from pkviet/rtxaudio

obs-filter: Add new RTX audio fx (dereverb & combined denoiser+ dereverb)
This commit is contained in:
Ryan Foster 2022-07-24 10:31:36 -04:00 committed by GitHub
commit 933255a680
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 430 additions and 108 deletions

View File

@ -75,7 +75,9 @@ NoiseSuppress.Intensity="Suppression Intensity"
NoiseSuppress.Method="Method"
NoiseSuppress.Method.Speex="Speex (low CPU usage, low quality)"
NoiseSuppress.Method.RNNoise="RNNoise (good quality, more CPU usage)"
NoiseSuppress.Method.nvafx="NVIDIA Noise Removal (good quality, no CPU usage)"
NoiseSuppress.Method.Nvafx.Denoiser="NVIDIA Noise Removal"
NoiseSuppress.Method.Nvafx.Dereverb="NVIDIA Room Echo Removal"
NoiseSuppress.Method.Nvafx.DenoiserPlusDereverb="NVIDIA Noise Removal + Room Echo Removal"
Saturation="Saturation"
HueShift="Hue Shift"
Amount="Amount"

View File

@ -2,6 +2,7 @@
#include <inttypes.h>
#include <util/circlebuf.h>
#include <util/threading.h>
#include <obs-module.h>
#ifdef LIBSPEEXDSP_ENABLED
@ -44,7 +45,9 @@ bool nvafx_loaded = false;
#define S_METHOD "method"
#define S_METHOD_SPEEX "speex"
#define S_METHOD_RNN "rnnoise"
#define S_METHOD_NVAFX "nvafx"
#define S_METHOD_NVAFX_DENOISER "denoiser"
#define S_METHOD_NVAFX_DEREVERB "dereverb"
#define S_METHOD_NVAFX_DEREVERB_DENOISER "dereverb_denoiser"
#define MT_ obs_module_text
#define TEXT_SUPPRESS_LEVEL MT_("NoiseSuppress.SuppressLevel")
@ -52,7 +55,10 @@ bool nvafx_loaded = false;
#define TEXT_METHOD MT_("NoiseSuppress.Method")
#define TEXT_METHOD_SPEEX MT_("NoiseSuppress.Method.Speex")
#define TEXT_METHOD_RNN MT_("NoiseSuppress.Method.RNNoise")
#define TEXT_METHOD_NVAFX MT_("NoiseSuppress.Method.nvafx")
#define TEXT_METHOD_NVAFX_DENOISER MT_("NoiseSuppress.Method.Nvafx.Denoiser")
#define TEXT_METHOD_NVAFX_DEREVERB MT_("NoiseSuppress.Method.Nvafx.Dereverb")
#define TEXT_METHOD_NVAFX_DEREVERB_DENOISER \
MT_("NoiseSuppress.Method.Nvafx.DenoiserPlusDereverb")
#define MAX_PREPROC_CHANNELS 8
@ -87,7 +93,8 @@ struct noise_suppress_data {
bool use_rnnoise;
bool use_nvafx;
bool nvafx_enabled;
bool has_mono_src;
volatile bool reinit_done;
#ifdef LIBSPEEXDSP_ENABLED
/* Speex preprocessor state */
SpeexPreprocessState *spx_states[MAX_PREPROC_CHANNELS];
@ -111,6 +118,7 @@ struct noise_suppress_data {
unsigned int num_samples_per_frame, num_channels;
char *model;
bool nvafx_initialized;
const char *fx;
/* Resampler */
audio_resampler_t *nvafx_resampler;
@ -209,7 +217,7 @@ static void noise_suppress_destroy(void *data)
audio_resampler_destroy(ng->nvafx_resampler_back);
}
bfree(ng->model);
bfree((void *)ng->fx);
if (ng->nvafx_enabled) {
if (ng->use_nvafx)
pthread_join(ng->nvafx_thread, NULL);
@ -224,31 +232,44 @@ static void noise_suppress_destroy(void *data)
bfree(ng);
}
static void *nvafx_initialize(void *data)
static bool nvafx_initialize_internal(void *data)
{
#ifdef LIBNVAFX_ENABLED
struct noise_suppress_data *ng = data;
int err;
NvAFX_Status err;
if (!ng->use_nvafx || !nvafx_loaded)
return NULL;
pthread_mutex_lock(&ng->nvafx_mutex);
pthread_mutex_lock(&nvafx_initializer_mutex);
if (!ng->handle[0]) {
ng->sample_rate = NVAFX_SAMPLE_RATE;
for (size_t i = 0; i < ng->channels; i++) {
err = NvAFX_CreateEffect(NVAFX_EFFECT_DENOISER,
&ng->handle[i]);
if (err != NVAFX_STATUS_SUCCESS) {
do_log(LOG_ERROR,
"NvAFX_CreateEffect() failed, error %i",
err);
// Create FX
CUcontext old = {0};
CUcontext curr = {0};
if (cuCtxGetCurrent(&old) != CUDA_SUCCESS) {
goto failure;
}
// if initialization was with rnnoise or speex
if (strcmp(ng->fx, S_METHOD_NVAFX_DENOISER) != 0 &&
strcmp(ng->fx, S_METHOD_NVAFX_DEREVERB) != 0 &&
strcmp(ng->fx, S_METHOD_NVAFX_DEREVERB_DENOISER) !=
0) {
ng->fx = bstrdup(S_METHOD_NVAFX_DENOISER);
}
err = NvAFX_CreateEffect(ng->fx, &ng->handle[i]);
if (err != NVAFX_STATUS_SUCCESS) {
do_log(LOG_ERROR,
"%s FX creation failed, error %i",
ng->fx, err);
goto failure;
}
if (cuCtxGetCurrent(&curr) != CUDA_SUCCESS) {
goto failure;
}
if (curr != old) {
cuCtxPopCurrent(NULL);
}
// Set sample rate of FX
err = NvAFX_SetU32(ng->handle[i],
NVAFX_PARAM_DENOISER_SAMPLE_RATE,
NVAFX_PARAM_INPUT_SAMPLE_RATE,
ng->sample_rate);
if (err != NVAFX_STATUS_SUCCESS) {
do_log(LOG_ERROR,
@ -256,19 +277,21 @@ static void *nvafx_initialize(void *data)
ng->sample_rate, err);
goto failure;
}
// initial setting of intensity to 1.0f
err = NvAFX_SetFloat(
ng->handle[i],
NVAFX_PARAM_DENOISER_INTENSITY_RATIO,
ng->intensity_ratio);
// Set intensity of FX
err = NvAFX_SetFloat(ng->handle[i],
NVAFX_PARAM_INTENSITY_RATIO,
ng->intensity_ratio);
if (err != NVAFX_STATUS_SUCCESS) {
do_log(LOG_ERROR,
"NvAFX_SetFloat(Intensity Ratio: %f) failed, error %i",
1.0f, err);
ng->intensity_ratio, err);
goto failure;
}
// Set AI models path
err = NvAFX_SetString(ng->handle[i],
NVAFX_PARAM_DENOISER_MODEL_PATH,
NVAFX_PARAM_MODEL_PATH,
ng->model);
if (err != NVAFX_STATUS_SUCCESS) {
do_log(LOG_ERROR,
@ -276,6 +299,8 @@ static void *nvafx_initialize(void *data)
err);
goto failure;
}
// Load FX
err = NvAFX_Load(ng->handle[i]);
if (err != NVAFX_STATUS_SUCCESS) {
do_log(LOG_ERROR,
@ -283,40 +308,67 @@ static void *nvafx_initialize(void *data)
err);
goto failure;
}
os_atomic_set_bool(&ng->reinit_done, true);
}
if (ng->use_nvafx) {
err = NvAFX_GetU32(ng->handle[0],
NVAFX_PARAM_DENOISER_NUM_CHANNELS,
&ng->num_channels);
if (err != NVAFX_STATUS_SUCCESS) {
do_log(LOG_ERROR,
"NvAFX_GetU32() failed to get the number of channels, error %i",
err);
goto failure;
}
if (ng->num_channels != 1) {
do_log(LOG_ERROR,
"The number of channels is not 1 in the sdk any more ==> update code");
goto failure;
}
NvAFX_Status err = NvAFX_GetU32(
ng->handle[0],
NVAFX_PARAM_DENOISER_NUM_SAMPLES_PER_FRAME,
&ng->num_samples_per_frame);
if (err != NVAFX_STATUS_SUCCESS) {
do_log(LOG_ERROR,
"NvAFX_GetU32() failed to get the number of samples per frame, error %i",
err);
goto failure;
}
if (ng->num_samples_per_frame != NVAFX_FRAME_SIZE) {
do_log(LOG_ERROR,
"The number of samples per frame has changed from 480 (= 10 ms) ==> update code");
goto failure;
}
}
return true;
failure:
ng->use_nvafx = false;
return false;
#else
UNUSED_PARAMETER(data);
return false;
#endif
}
static void *nvafx_initialize(void *data)
{
#ifdef LIBNVAFX_ENABLED
struct noise_suppress_data *ng = data;
NvAFX_Status err;
if (!ng->use_nvafx || !nvafx_loaded) {
return NULL;
}
pthread_mutex_lock(&ng->nvafx_mutex);
pthread_mutex_lock(&nvafx_initializer_mutex);
if (!nvafx_initialize_internal(data)) {
goto failure;
}
if (ng->use_nvafx) {
err = NvAFX_GetU32(ng->handle[0],
NVAFX_PARAM_NUM_INPUT_CHANNELS,
&ng->num_channels);
if (err != NVAFX_STATUS_SUCCESS) {
do_log(LOG_ERROR,
"NvAFX_GetU32() failed to get the number of channels, error %i",
err);
goto failure;
}
if (ng->num_channels != 1) {
do_log(LOG_ERROR,
"The number of channels is not 1 in the sdk any more ==> update code");
goto failure;
}
NvAFX_Status err = NvAFX_GetU32(
ng->handle[0], NVAFX_PARAM_NUM_INPUT_SAMPLES_PER_FRAME,
&ng->num_samples_per_frame);
if (err != NVAFX_STATUS_SUCCESS) {
do_log(LOG_ERROR,
"NvAFX_GetU32() failed to get the number of samples per frame, error %i",
err);
goto failure;
}
if (ng->num_samples_per_frame != NVAFX_FRAME_SIZE) {
do_log(LOG_ERROR,
"The number of samples per frame has changed from 480 (= 10 ms) ==> update code");
goto failure;
}
}
ng->nvafx_initialized = true;
ng->nvafx_loading = false;
pthread_mutex_unlock(&nvafx_initializer_mutex);
pthread_mutex_unlock(&ng->nvafx_mutex);
return NULL;
@ -387,25 +439,22 @@ static void noise_suppress_update(void *data, obs_data_t *s)
ng->latency = 1000000000LL / (1000 / BUFFER_SIZE_MSEC);
ng->use_rnnoise = strcmp(method, S_METHOD_RNN) == 0;
ng->use_nvafx = ng->nvafx_enabled &&
strcmp(method, S_METHOD_NVAFX) == 0;
/* Process 10 millisecond segments to keep latency low */
/* Also RNNoise only supports buffers of this exact size. */
/* At 48kHz, NVAFX processes 480 samples which corresponds to 10 ms.*/
ng->frames = frames;
ng->channels = channels;
bool nvafx_requested =
strcmp(method, S_METHOD_NVAFX_DENOISER) == 0 ||
strcmp(method, S_METHOD_NVAFX_DEREVERB) == 0 ||
strcmp(method, S_METHOD_NVAFX_DEREVERB_DENOISER) == 0;
#ifdef LIBNVAFX_ENABLED
ng->intensity_ratio = (float)obs_data_get_double(s, S_NVAFX_INTENSITY);
if (ng->use_nvafx) {
pthread_mutex_lock(&ng->nvafx_mutex);
if (ng->nvafx_initialized) {
int err;
float intensity = (float)obs_data_get_double(s, S_NVAFX_INTENSITY);
if (ng->use_nvafx && ng->nvafx_initialized) {
if (intensity != ng->intensity_ratio &&
(strcmp(ng->fx, method) == 0)) {
NvAFX_Status err;
ng->intensity_ratio = intensity;
pthread_mutex_lock(&ng->nvafx_mutex);
for (size_t i = 0; i < ng->channels; i++) {
err = NvAFX_SetFloat(
ng->handle[i],
NVAFX_PARAM_DENOISER_INTENSITY_RATIO,
NVAFX_PARAM_INTENSITY_RATIO,
ng->intensity_ratio);
if (err != NVAFX_STATUS_SUCCESS) {
do_log(LOG_ERROR,
@ -414,9 +463,44 @@ static void noise_suppress_update(void *data, obs_data_t *s)
ng->use_nvafx = false;
}
}
pthread_mutex_unlock(&ng->nvafx_mutex);
}
pthread_mutex_unlock(&ng->nvafx_mutex);
if ((strcmp(ng->fx, method) != 0)) {
bfree((void *)ng->fx);
ng->fx = bstrdup(method);
ng->intensity_ratio = intensity;
os_atomic_set_bool(&ng->reinit_done, false);
pthread_mutex_lock(&ng->nvafx_mutex);
for (int i = 0; i < (int)ng->channels; i++) {
/* Destroy previous FX */
if (NvAFX_DestroyEffect(ng->handle[i]) !=
NVAFX_STATUS_SUCCESS) {
do_log(LOG_ERROR,
"FX failed to be destroyed.");
ng->use_nvafx = false;
} else
ng->handle[i] = NULL;
}
if (ng->use_nvafx) {
nvafx_initialize_internal(data);
}
pthread_mutex_unlock(&ng->nvafx_mutex);
}
} else {
ng->fx = bstrdup(method);
}
#endif
ng->use_nvafx = ng->nvafx_enabled && nvafx_requested;
/* Process 10 millisecond segments to keep latency low. */
/* Also RNNoise only supports buffers of this exact size. */
/* At 48kHz, NVAFX processes 480 samples which corresponds to 10 ms.*/
ng->frames = frames;
ng->channels = channels;
#ifdef LIBNVAFX_ENABLED
#endif
/* Ignore if already allocated */
#if defined(LIBSPEEXDSP_ENABLED)
@ -463,6 +547,7 @@ static void noise_suppress_update(void *data, obs_data_t *s)
#ifdef LIBNVAFX_ENABLED
if (!ng->nvafx_initialized && ng->use_nvafx && !ng->nvafx_loading) {
ng->intensity_ratio = intensity;
ng->nvafx_loading = true;
pthread_create(&ng->nvafx_thread, NULL, nvafx_initialize, ng);
}
@ -536,28 +621,65 @@ bool load_nvafx(void)
#define LOAD_SYM(sym) LOAD_SYM_FROM_LIB(sym, nv_audiofx, "NVAudioEffects.dll")
LOAD_SYM(NvAFX_GetEffectList);
LOAD_SYM(NvAFX_CreateEffect);
LOAD_SYM(NvAFX_CreateChainedEffect);
LOAD_SYM(NvAFX_DestroyEffect);
LOAD_SYM(NvAFX_SetU32);
LOAD_SYM(NvAFX_SetU32List);
LOAD_SYM(NvAFX_SetString);
LOAD_SYM(NvAFX_SetStringList);
LOAD_SYM(NvAFX_SetFloat);
LOAD_SYM(NvAFX_SetFloatList);
LOAD_SYM(NvAFX_GetU32);
LOAD_SYM(NvAFX_GetString);
LOAD_SYM(NvAFX_GetStringList);
LOAD_SYM(NvAFX_GetFloat);
LOAD_SYM(NvAFX_GetFloatList);
LOAD_SYM(NvAFX_Load);
LOAD_SYM(NvAFX_GetSupportedDevices);
LOAD_SYM(NvAFX_Run);
LOAD_SYM(NvAFX_Reset);
#undef LOAD_SYM
#define LOAD_SYM(sym) LOAD_SYM_FROM_LIB(sym, nv_cuda, "nvcuda.dll")
LOAD_SYM(cuCtxGetCurrent);
LOAD_SYM(cuCtxPopCurrent);
LOAD_SYM(cuInit);
#undef LOAD_SYM
int err;
NvAFX_Status err;
CUresult cudaerr;
NvAFX_Handle h = NULL;
cudaerr = cuInit(0);
if (cudaerr != CUDA_SUCCESS) {
goto cuda_errors;
}
CUcontext old = {0};
CUcontext curr = {0};
cudaerr = cuCtxGetCurrent(&old);
if (cudaerr != CUDA_SUCCESS) {
goto cuda_errors;
}
err = NvAFX_CreateEffect(NVAFX_EFFECT_DENOISER, &h);
cudaerr = cuCtxGetCurrent(&curr);
if (cudaerr != CUDA_SUCCESS) {
goto cuda_errors;
}
if (curr != old) {
cudaerr = cuCtxPopCurrent(NULL);
if (cudaerr != CUDA_SUCCESS)
goto cuda_errors;
}
if (err != NVAFX_STATUS_SUCCESS) {
if (err == NVAFX_STATUS_GPU_UNSUPPORTED) {
blog(LOG_INFO,
"[noise suppress]: NVIDIA RTX denoiser disabled: unsupported GPU");
"[noise suppress]: NVIDIA RTX AUDIO FX disabled: unsupported GPU");
} else {
blog(LOG_ERROR,
"[noise suppress]: NVIDIA RTX denoiser disabled: error %i",
"[noise suppress]: NVIDIA RTX AUDIO FX disabled, error %i",
err);
}
goto unload_everything;
@ -565,14 +687,20 @@ bool load_nvafx(void)
err = NvAFX_DestroyEffect(h);
if (err != NVAFX_STATUS_SUCCESS) {
blog(LOG_ERROR, "NvAFX_DestroyEffect() failed, error %i", err);
blog(LOG_ERROR,
"[noise suppress]: NVIDIA RTX AUDIO FX disabled, error %i",
err);
goto unload_everything;
}
nvafx_loaded = true;
blog(LOG_INFO, "[noise suppress]: NVIDIA RTX denoiser enabled");
blog(LOG_INFO, "[noise suppress]: NVIDIA RTX AUDIO FX enabled");
return true;
cuda_errors:
blog(LOG_ERROR,
"[noise suppress]: NVIDIA RTX AUDIO FX disabled, CUDA error %i",
cudaerr);
unload_everything:
release_lib();
#endif
@ -582,17 +710,17 @@ unload_everything:
#pragma warning(pop)
#endif
#ifdef LIBNVAFX_ENABLED
void unload_nvafx(void)
{
#ifdef LIBNVAFX_ENABLED
release_lib();
if (nvafx_initializer_mutex_initialized) {
pthread_mutex_destroy(&nvafx_initializer_mutex);
nvafx_initializer_mutex_initialized = false;
}
#endif
}
#endif
static void *noise_suppress_create(obs_data_t *settings, obs_source_t *filter)
{
@ -618,6 +746,7 @@ static void *noise_suppress_create(obs_data_t *settings, obs_source_t *filter)
ng->nvafx_enabled = true;
ng->nvafx_initialized = false;
ng->nvafx_loading = false;
ng->fx = NULL;
pthread_mutex_init(&ng->nvafx_mutex, NULL);
@ -780,16 +909,36 @@ static inline void process_nvafx(struct noise_suppress_data *ng)
}
/* Execute */
for (size_t i = 0; i < ng->channels; i++) {
NvAFX_Status err = NvAFX_Run(
ng->handle[i], &ng->nvafx_segment_buffers[i],
&ng->nvafx_segment_buffers[i],
ng->num_samples_per_frame, ng->num_channels);
if (err != NVAFX_STATUS_SUCCESS)
do_log(LOG_ERROR,
"NvAFX_Run() failed, error %i", err);
size_t runs = ng->has_mono_src ? 1 : ng->channels;
if (ng->reinit_done) {
for (size_t i = 0; i < runs; i++) {
NvAFX_Status err =
NvAFX_Run(ng->handle[i],
&ng->nvafx_segment_buffers[i],
&ng->nvafx_segment_buffers[i],
ng->num_samples_per_frame,
ng->num_channels);
if (err != NVAFX_STATUS_SUCCESS) {
if (err == NVAFX_STATUS_FAILED) {
do_log(LOG_DEBUG,
"NvAFX_Run() failed, error NVAFX_STATUS_FAILED.\n"
"This can occur when changing the FX and is not consequential.");
os_atomic_set_bool(
&ng->reinit_done,
false); // stop all processing; this will be reset at new init
} else {
do_log(LOG_ERROR,
"NvAFX_Run() failed, error %i.\n",
err);
}
}
}
}
if (ng->has_mono_src) {
memcpy(ng->nvafx_segment_buffers[1],
ng->nvafx_segment_buffers[0],
NVAFX_FRAME_SIZE * sizeof(float));
}
/* Revert signal level adjustment, resample back if necessary */
if (ng->nvafx_resampler) {
float *output[MAX_PREPROC_CHANNELS];
@ -877,6 +1026,11 @@ noise_suppress_filter_audio(void *data, struct obs_audio_data *audio)
struct ng_audio_info info;
size_t segment_size = ng->frames * sizeof(float);
size_t out_size;
obs_source_t *parent = obs_filter_get_parent(ng->context);
const char *name = obs_source_get_name(parent);
const char *id = obs_source_get_id(parent);
enum speaker_layout layout = obs_source_get_speaker_layout(parent);
ng->has_mono_src = layout == SPEAKERS_MONO && ng->channels == 2;
#ifdef LIBSPEEXDSP_ENABLED
if (!ng->spx_states[0])
@ -955,10 +1109,13 @@ static bool noise_suppress_method_modified(obs_properties_t *props,
obs_properties_get(props, S_SUPPRESS_LEVEL);
obs_property_t *p_navfx_intensity =
obs_properties_get(props, S_NVAFX_INTENSITY);
const char *method = obs_data_get_string(settings, S_METHOD);
bool enable_level = strcmp(method, S_METHOD_SPEEX) == 0;
bool enable_intensity = strcmp(method, S_METHOD_NVAFX) == 0;
bool enable_intensity =
strcmp(method, S_METHOD_NVAFX_DENOISER) == 0 ||
strcmp(method, S_METHOD_NVAFX_DEREVERB) == 0 ||
strcmp(method, S_METHOD_NVAFX_DEREVERB_DENOISER) == 0;
obs_property_set_visible(p_suppress_level, enable_level);
obs_property_set_visible(p_navfx_intensity, enable_intensity);
@ -1008,9 +1165,16 @@ static obs_properties_t *noise_suppress_properties(void *data)
obs_property_list_add_string(method, TEXT_METHOD_SPEEX, S_METHOD_SPEEX);
obs_property_list_add_string(method, TEXT_METHOD_RNN, S_METHOD_RNN);
#ifdef LIBNVAFX_ENABLED
if (ng->nvafx_enabled)
obs_property_list_add_string(method, TEXT_METHOD_NVAFX,
S_METHOD_NVAFX);
if (ng->nvafx_enabled) {
obs_property_list_add_string(method, TEXT_METHOD_NVAFX_DENOISER,
S_METHOD_NVAFX_DENOISER);
obs_property_list_add_string(method, TEXT_METHOD_NVAFX_DEREVERB,
S_METHOD_NVAFX_DEREVERB);
obs_property_list_add_string(
method, TEXT_METHOD_NVAFX_DEREVERB_DENOISER,
S_METHOD_NVAFX_DEREVERB_DENOISER);
}
#endif
obs_property_set_modified_callback(method,
noise_suppress_method_modified);
@ -1031,6 +1195,8 @@ static obs_properties_t *noise_suppress_properties(void *data)
#if defined(LIBRNNOISE_ENABLED) && defined(LIBSPEEXDSP_ENABLED)
if (!nvafx_loaded) {
obs_property_list_item_disable(method, 2, true);
obs_property_list_item_disable(method, 3, true);
obs_property_list_item_disable(method, 4, true);
}
#endif

View File

@ -9,23 +9,65 @@
#ifdef LIBNVAFX_ENABLED
static HMODULE nv_audiofx = NULL;
static HMODULE nv_cuda = NULL;
/** Denoiser Effect */
/** Effects @ref NvAFX_EffectSelector */
#define NVAFX_EFFECT_DENOISER "denoiser"
#define NVAFX_EFFECT_DEREVERB "dereverb"
#define NVAFX_EFFECT_DEREVERB_DENOISER "dereverb_denoiser"
#define NVAFX_EFFECT_AEC "aec"
#define NVAFX_EFFECT_SUPERRES "superres"
#define NVAFX_CHAINED_EFFECT_DENOISER_16k_SUPERRES_16k_TO_48k \
"denoiser16k_superres16kto48k"
#define NVAFX_CHAINED_EFFECT_DEREVERB_16k_SUPERRES_16k_TO_48k \
"dereverb16k_superres16kto48k"
#define NVAFX_CHAINED_EFFECT_DEREVERB_DENOISER_16k_SUPERRES_16k_TO_48k \
"dereverb_denoiser16k_superres16kto48k"
#define NVAFX_CHAINED_EFFECT_SUPERRES_8k_TO_16k_DENOISER_16k \
"superres8kto16k_denoiser16k"
#define NVAFX_CHAINED_EFFECT_SUPERRES_8k_TO_16k_DEREVERB_16k \
"superres8kto16k_dereverb16k"
#define NVAFX_CHAINED_EFFECT_SUPERRES_8k_TO_16k_DEREVERB_DENOISER_16k \
"superres8kto16k_dereverb_denoiser16k"
/** Parameter selectors */
/** Denoiser parameters. @ref NvAFX_ParameterSelector */
/** Denoiser filter model path (char*) */
#define NVAFX_PARAM_DENOISER_MODEL_PATH "denoiser_model_path"
/** Denoiser sample rate (unsigned int). Currently supported sample rate(s): 48000 */
#define NVAFX_PARAM_DENOISER_SAMPLE_RATE "sample_rate"
/** Denoiser number of samples per frame (unsigned int). This is immutable parameter */
#define NVAFX_PARAM_DENOISER_NUM_SAMPLES_PER_FRAME "num_samples_per_frame"
/** Denoiser number of channels in I/O (unsigned int). This is immutable parameter */
#define NVAFX_PARAM_DENOISER_NUM_CHANNELS "num_channels"
/** Denoiser noise suppression factor (float) */
#define NVAFX_PARAM_DENOISER_INTENSITY_RATIO "intensity_ratio"
#define NVAFX_PARAM_NUM_STREAMS "num_streams"
#define NVAFX_PARAM_USE_DEFAULT_GPU "use_default_gpu"
#define NVAFX_PARAM_USER_CUDA_CONTEXT "user_cuda_context"
#define NVAFX_PARAM_DISABLE_CUDA_GRAPH "disable_cuda_graph"
#define NVAFX_PARAM_ENABLE_VAD "enable_vad"
/** Effect parameters. @ref NvAFX_ParameterSelector */
#define NVAFX_PARAM_MODEL_PATH "model_path"
#define NVAFX_PARAM_INPUT_SAMPLE_RATE "input_sample_rate"
#define NVAFX_PARAM_OUTPUT_SAMPLE_RATE "output_sample_rate"
#define NVAFX_PARAM_NUM_INPUT_SAMPLES_PER_FRAME "num_input_samples_per_frame"
#define NVAFX_PARAM_NUM_OUTPUT_SAMPLES_PER_FRAME "num_output_samples_per_frame"
#define NVAFX_PARAM_NUM_INPUT_CHANNELS "num_input_channels"
#define NVAFX_PARAM_NUM_OUTPUT_CHANNELS "num_output_channels"
#define NVAFX_PARAM_INTENSITY_RATIO "intensity_ratio"
#pragma deprecated(NVAFX_PARAM_DENOISER_MODEL_PATH)
#define NVAFX_PARAM_DENOISER_MODEL_PATH NVAFX_PARAM_MODEL_PATH
#pragma deprecated(NVAFX_PARAM_DENOISER_SAMPLE_RATE)
#define NVAFX_PARAM_DENOISER_SAMPLE_RATE NVAFX_PARAM_SAMPLE_RATE
#pragma deprecated(NVAFX_PARAM_DENOISER_NUM_SAMPLES_PER_FRAME)
#define NVAFX_PARAM_DENOISER_NUM_SAMPLES_PER_FRAME \
NVAFX_PARAM_NUM_SAMPLES_PER_FRAME
#pragma deprecated(NVAFX_PARAM_DENOISER_NUM_CHANNELS)
#define NVAFX_PARAM_DENOISER_NUM_CHANNELS NVAFX_PARAM_NUM_CHANNELS
#pragma deprecated(NVAFX_PARAM_DENOISER_INTENSITY_RATIO)
#define NVAFX_PARAM_DENOISER_INTENSITY_RATIO NVAFX_PARAM_INTENSITY_RATIO
/** Number of audio channels **/
#pragma deprecated(NVAFX_PARAM_NUM_CHANNELS)
#define NVAFX_PARAM_NUM_CHANNELS "num_channels"
/** Sample rate (unsigned int). Currently supported sample rate(s): 48000, 16000 */
#pragma deprecated(NVAFX_PARAM_SAMPLE_RATE)
#define NVAFX_PARAM_SAMPLE_RATE "sample_rate"
/** Number of samples per frame (unsigned int). This is immutable parameter */
#pragma deprecated(NVAFX_PARAM_NUM_SAMPLES_PER_FRAME)
#define NVAFX_PARAM_NUM_SAMPLES_PER_FRAME "num_samples_per_frame"
typedef enum {
/** Success */
@ -55,6 +97,10 @@ typedef enum {
NVAFX_STATUS_GPU_UNSUPPORTED = 11,
} NvAFX_Status;
#define NVAFX_TRUE 1
#define NVAFX_FALSE 0
typedef char NvAFX_Bool;
typedef const char *NvAFX_EffectSelector;
typedef const char *NvAFX_ParameterSelector;
typedef void *NvAFX_Handle;
@ -65,17 +111,32 @@ typedef NvAFX_Status
typedef NvAFX_Status
NVAFX_API (*NvAFX_CreateEffect_t)(NvAFX_EffectSelector code,
NvAFX_Handle *effect);
typedef NvAFX_Status
NVAFX_API (*NvAFX_CreateChainedEffect_t)(NvAFX_EffectSelector code,
NvAFX_Handle *effect);
typedef NvAFX_Status NVAFX_API (*NvAFX_DestroyEffect_t)(NvAFX_Handle effect);
typedef NvAFX_Status
NVAFX_API (*NvAFX_SetU32_t)(NvAFX_Handle effect,
NvAFX_ParameterSelector param_name,
unsigned int val);
typedef NvAFX_Status
NVAFX_API (*NvAFX_SetU32List_t)(NvAFX_Handle effect,
NvAFX_ParameterSelector param_name,
unsigned int *val, unsigned int size);
typedef NvAFX_Status
NVAFX_API (*NvAFX_SetString_t)(NvAFX_Handle effect,
NvAFX_ParameterSelector param_name,
const char *val);
typedef NvAFX_Status
NVAFX_API (*NvAFX_SetStringList_t)(NvAFX_Handle effect,
NvAFX_ParameterSelector param_name,
const char **val, unsigned int size);
typedef NvAFX_Status NVAFX_API (*NvAFX_SetFloat_t)(
NvAFX_Handle effect, NvAFX_ParameterSelector param_name, float val);
typedef NvAFX_Status
NVAFX_API (*NvAFX_SetFloatList_t)(NvAFX_Handle effect,
NvAFX_ParameterSelector param_name,
float *val, unsigned int size);
typedef NvAFX_Status
NVAFX_API (*NvAFX_GetU32_t)(NvAFX_Handle effect,
NvAFX_ParameterSelector param_name,
@ -84,44 +145,137 @@ typedef NvAFX_Status
NVAFX_API (*NvAFX_GetString_t)(NvAFX_Handle effect,
NvAFX_ParameterSelector param_name,
char *val, int max_length);
typedef NvAFX_Status NVAFX_API (*NvAFX_GetStringList_t)(
NvAFX_Handle effect, NvAFX_ParameterSelector param_name, char **val,
int *max_length, unsigned int size);
typedef NvAFX_Status NVAFX_API (*NvAFX_GetFloat_t)(
NvAFX_Handle effect, NvAFX_ParameterSelector param_name, float *val);
typedef NvAFX_Status
NVAFX_API (*NvAFX_GetFloatList_t)(NvAFX_Handle effect,
NvAFX_ParameterSelector param_name,
float *val, unsigned int size);
typedef NvAFX_Status NVAFX_API (*NvAFX_Load_t)(NvAFX_Handle effect);
typedef NvAFX_Status
NVAFX_API (*NvAFX_GetSupportedDevices_t)(NvAFX_Handle effect, int *num,
int *devices);
typedef NvAFX_Status NVAFX_API (*NvAFX_Run_t)(NvAFX_Handle effect,
const float **input,
float **output,
unsigned num_samples,
unsigned num_channels);
typedef NvAFX_Status NVAFX_API (*NvAFX_Reset_t)(NvAFX_Handle effect);
/* cuda */
typedef enum cudaError_enum {
CUDA_SUCCESS = 0,
CUDA_ERROR_INVALID_VALUE = 1,
CUDA_ERROR_OUT_OF_MEMORY = 2,
CUDA_ERROR_NOT_INITIALIZED = 3,
CUDA_ERROR_DEINITIALIZED = 4,
CUDA_ERROR_PROFILER_DISABLED = 5,
CUDA_ERROR_PROFILER_NOT_INITIALIZED = 6,
CUDA_ERROR_PROFILER_ALREADY_STARTED = 7,
CUDA_ERROR_PROFILER_ALREADY_STOPPED = 8,
CUDA_ERROR_NO_DEVICE = 100,
CUDA_ERROR_INVALID_DEVICE = 101,
CUDA_ERROR_INVALID_IMAGE = 200,
CUDA_ERROR_INVALID_CONTEXT = 201,
CUDA_ERROR_CONTEXT_ALREADY_CURRENT = 202,
CUDA_ERROR_MAP_FAILED = 205,
CUDA_ERROR_UNMAP_FAILED = 206,
CUDA_ERROR_ARRAY_IS_MAPPED = 207,
CUDA_ERROR_ALREADY_MAPPED = 208,
CUDA_ERROR_NO_BINARY_FOR_GPU = 209,
CUDA_ERROR_ALREADY_ACQUIRED = 210,
CUDA_ERROR_NOT_MAPPED = 211,
CUDA_ERROR_NOT_MAPPED_AS_ARRAY = 212,
CUDA_ERROR_NOT_MAPPED_AS_POINTER = 213,
CUDA_ERROR_ECC_UNCORRECTABLE = 214,
CUDA_ERROR_UNSUPPORTED_LIMIT = 215,
CUDA_ERROR_CONTEXT_ALREADY_IN_USE = 216,
CUDA_ERROR_INVALID_SOURCE = 300,
CUDA_ERROR_FILE_NOT_FOUND = 301,
CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND = 302,
CUDA_ERROR_SHARED_OBJECT_INIT_FAILED = 303,
CUDA_ERROR_OPERATING_SYSTEM = 304,
CUDA_ERROR_INVALID_HANDLE = 400,
CUDA_ERROR_NOT_FOUND = 500,
CUDA_ERROR_NOT_READY = 600,
CUDA_ERROR_LAUNCH_FAILED = 700,
CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES = 701,
CUDA_ERROR_LAUNCH_TIMEOUT = 702,
CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING = 703,
CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED = 704,
CUDA_ERROR_PEER_ACCESS_NOT_ENABLED = 705,
CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE = 708,
CUDA_ERROR_CONTEXT_IS_DESTROYED = 709,
CUDA_ERROR_ASSERT = 710,
CUDA_ERROR_TOO_MANY_PEERS = 711,
CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED = 712,
CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED = 713,
CUDA_ERROR_UNKNOWN = 999
} CUresult;
typedef struct CUctx_st *CUcontext;
typedef CUresult(__stdcall *cuCtxGetCurrent_t)(CUcontext *pctx);
typedef CUresult(__stdcall *cuCtxPopCurrent_t)(CUcontext *pctx);
typedef CUresult(__stdcall *cuInit_t)(unsigned int Flags);
static NvAFX_GetEffectList_t NvAFX_GetEffectList = NULL;
static NvAFX_CreateEffect_t NvAFX_CreateEffect = NULL;
static NvAFX_CreateChainedEffect_t NvAFX_CreateChainedEffect = NULL;
static NvAFX_DestroyEffect_t NvAFX_DestroyEffect = NULL;
static NvAFX_SetU32_t NvAFX_SetU32 = NULL;
static NvAFX_SetU32List_t NvAFX_SetU32List = NULL;
static NvAFX_SetString_t NvAFX_SetString = NULL;
static NvAFX_SetStringList_t NvAFX_SetStringList = NULL;
static NvAFX_SetFloat_t NvAFX_SetFloat = NULL;
static NvAFX_SetFloatList_t NvAFX_SetFloatList = NULL;
static NvAFX_GetU32_t NvAFX_GetU32 = NULL;
static NvAFX_GetString_t NvAFX_GetString = NULL;
static NvAFX_GetStringList_t NvAFX_GetStringList = NULL;
static NvAFX_GetFloat_t NvAFX_GetFloat = NULL;
static NvAFX_GetFloatList_t NvAFX_GetFloatList = NULL;
static NvAFX_Load_t NvAFX_Load = NULL;
static NvAFX_GetSupportedDevices_t NvAFX_GetSupportedDevices = NULL;
static NvAFX_Run_t NvAFX_Run = NULL;
static NvAFX_Reset_t NvAFX_Reset;
/* cuda */
static cuCtxGetCurrent_t cuCtxGetCurrent = NULL;
static cuCtxPopCurrent_t cuCtxPopCurrent = NULL;
static cuInit_t cuInit = NULL;
void release_lib(void)
{
NvAFX_GetEffectList = NULL;
NvAFX_CreateEffect = NULL;
NvAFX_CreateChainedEffect = NULL;
NvAFX_DestroyEffect = NULL;
NvAFX_SetU32 = NULL;
NvAFX_SetU32List = NULL;
NvAFX_SetString = NULL;
NvAFX_SetStringList = NULL;
NvAFX_SetFloat = NULL;
NvAFX_SetFloatList = NULL;
NvAFX_GetU32 = NULL;
NvAFX_GetString = NULL;
NvAFX_GetStringList = NULL;
NvAFX_GetFloat = NULL;
NvAFX_GetFloatList = NULL;
NvAFX_Load = NULL;
NvAFX_GetSupportedDevices = NULL;
NvAFX_Run = NULL;
NvAFX_Reset = NULL;
if (nv_audiofx) {
FreeLibrary(nv_audiofx);
nv_audiofx = NULL;
}
cuCtxGetCurrent = NULL;
cuCtxPopCurrent = NULL;
cuInit = NULL;
if (nv_cuda) {
FreeLibrary(nv_cuda);
nv_cuda = NULL;
}
}
static bool nvafx_get_sdk_path(char *buffer, const size_t len)
@ -144,7 +298,7 @@ static bool load_lib(void)
SetDllDirectoryA(path);
nv_audiofx = LoadLibrary(L"NVAudioEffects.dll");
SetDllDirectoryA(NULL);
return !!nv_audiofx;
nv_cuda = LoadLibrary(L"nvcuda.dll");
return !!nv_audiofx && !!nv_cuda;
}
#endif