mirror of
https://git.vladimir.cc/vladimir/wdsp.git
synced 2026-08-26 01:37:34 +00:00
first commit
This commit is contained in:
+354
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
libspecbleach - A spectral processing library
|
||||
|
||||
Copyright 2022 Luciano Dato <lucianodato@gmail.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "adaptive_denoiser.h"
|
||||
#include "shared/configurations.h"
|
||||
#include "shared/gain_estimation/gain_estimators.h"
|
||||
#include "shared/noise_estimation/adaptive_noise_estimator.h"
|
||||
#include "shared/post_estimation/noise_floor_manager.h"
|
||||
#include "shared/post_estimation/postfilter.h"
|
||||
#include "shared/pre_estimation/critical_bands.h"
|
||||
#include "shared/pre_estimation/noise_scaling_criterias.h"
|
||||
#include "shared/pre_estimation/spectral_smoother.h"
|
||||
#include "shared/utils/denoise_mixer.h"
|
||||
#include "shared/utils/spectral_features.h"
|
||||
#include "shared/utils/spectral_utils.h"
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct SpectralAdaptiveDenoiser {
|
||||
uint32_t fft_size;
|
||||
uint32_t real_spectrum_size;
|
||||
uint32_t sample_rate;
|
||||
uint32_t hop;
|
||||
float default_oversubtraction;
|
||||
float default_undersubtraction;
|
||||
|
||||
AdaptiveDenoiserParameters parameters;
|
||||
|
||||
float* alpha;
|
||||
float* beta;
|
||||
float* gain_spectrum;
|
||||
float* residual_spectrum;
|
||||
float* denoised_spectrum;
|
||||
float* noise_profile;
|
||||
|
||||
SpectrumType spectrum_type;
|
||||
CriticalBandType band_type;
|
||||
GainEstimationType gain_estimation_type;
|
||||
TimeSmoothingType time_smoothing_type;
|
||||
|
||||
DenoiseMixer* mixer;
|
||||
NoiseScalingCriterias* noise_scaling_criteria;
|
||||
SpectralSmoother* spectrum_smoothing;
|
||||
PostFilter* postfiltering;
|
||||
AdaptiveNoiseEstimator* adaptive_estimator;
|
||||
SpectralFeatures* spectral_features;
|
||||
NoiseFloorManager* noise_floor_manager;
|
||||
bool postfiltering_enabled;
|
||||
bool whitening_enabled;
|
||||
} SpectralAdaptiveDenoiser;
|
||||
|
||||
SpectralProcessorHandle spectral_adaptive_denoiser_initialize(
|
||||
const uint32_t sample_rate, const uint32_t fft_size,
|
||||
const uint32_t overlap_factor) {
|
||||
|
||||
if (sample_rate == 0 || fft_size == 0 || overlap_factor == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SpectralAdaptiveDenoiser* self =
|
||||
(SpectralAdaptiveDenoiser*)calloc(1U, sizeof(SpectralAdaptiveDenoiser));
|
||||
if (!self) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->fft_size = fft_size;
|
||||
self->real_spectrum_size = (self->fft_size / 2U) + 1U;
|
||||
self->sample_rate = sample_rate;
|
||||
self->hop = self->fft_size / overlap_factor;
|
||||
self->default_oversubtraction = DEFAULT_OVERSUBTRACTION;
|
||||
self->default_undersubtraction = DEFAULT_UNDERSUBTRACTION;
|
||||
self->spectrum_type = SPECTRAL_TYPE_SPEECH;
|
||||
self->band_type = CRITICAL_BANDS_TYPE_SPEECH;
|
||||
self->gain_estimation_type = GAIN_ESTIMATION_TYPE_SPEECH;
|
||||
self->time_smoothing_type = TIME_SMOOTHING_TYPE_SPEECH;
|
||||
self->postfiltering_enabled = POSTFILTER_ENABLED_SPEECH;
|
||||
self->whitening_enabled = WHITENING_ENABLED_SPEECH;
|
||||
|
||||
self->gain_spectrum = (float*)calloc(self->fft_size, sizeof(float));
|
||||
if (!self->gain_spectrum) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
(void)initialize_spectrum_with_value(self->gain_spectrum, self->fft_size,
|
||||
1.F);
|
||||
|
||||
self->alpha = (float*)calloc(self->real_spectrum_size, sizeof(float));
|
||||
if (!self->alpha) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
(void)initialize_spectrum_with_value(self->alpha, self->real_spectrum_size,
|
||||
1.F);
|
||||
|
||||
self->beta = (float*)calloc(self->real_spectrum_size, sizeof(float));
|
||||
if (!self->beta) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->noise_profile = (float*)calloc(self->real_spectrum_size, sizeof(float));
|
||||
if (!self->noise_profile) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->adaptive_estimator = louizou_estimator_initialize(
|
||||
self->real_spectrum_size, sample_rate, fft_size);
|
||||
if (!self->adaptive_estimator) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->residual_spectrum = (float*)calloc((self->fft_size), sizeof(float));
|
||||
if (!self->residual_spectrum) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->denoised_spectrum = (float*)calloc((self->fft_size), sizeof(float));
|
||||
if (!self->denoised_spectrum) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (self->postfiltering_enabled) {
|
||||
self->postfiltering = postfilter_initialize(self->fft_size);
|
||||
if (!self->postfiltering) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
self->spectrum_smoothing =
|
||||
spectral_smoothing_initialize(self->fft_size, self->time_smoothing_type);
|
||||
if (!self->spectrum_smoothing) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->noise_scaling_criteria = noise_scaling_criterias_initialize(
|
||||
self->fft_size, self->band_type, self->sample_rate, self->spectrum_type);
|
||||
if (!self->noise_scaling_criteria) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->spectral_features =
|
||||
spectral_features_initialize(self->real_spectrum_size);
|
||||
if (!self->spectral_features) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->mixer =
|
||||
denoise_mixer_initialize(self->fft_size, self->sample_rate, self->hop);
|
||||
if (!self->mixer) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->noise_floor_manager = noise_floor_manager_initialize(
|
||||
self->fft_size, self->sample_rate, self->hop);
|
||||
if (!self->noise_floor_manager) {
|
||||
spectral_adaptive_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void spectral_adaptive_denoiser_free(SpectralProcessorHandle instance) {
|
||||
SpectralAdaptiveDenoiser* self = (SpectralAdaptiveDenoiser*)instance;
|
||||
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->adaptive_estimator) {
|
||||
if (self->parameters.noise_estimation_method == SPP_MMSE_METHOD) {
|
||||
spp_mmse_estimator_free(self->adaptive_estimator);
|
||||
} else {
|
||||
louizou_estimator_free(self->adaptive_estimator);
|
||||
}
|
||||
}
|
||||
if (self->spectral_features) {
|
||||
spectral_features_free(self->spectral_features);
|
||||
}
|
||||
if (self->noise_scaling_criteria) {
|
||||
noise_scaling_criterias_free(self->noise_scaling_criteria);
|
||||
}
|
||||
if (self->spectrum_smoothing) {
|
||||
spectral_smoothing_free(self->spectrum_smoothing);
|
||||
}
|
||||
if (self->postfiltering) {
|
||||
postfilter_free(self->postfiltering);
|
||||
}
|
||||
if (self->mixer) {
|
||||
denoise_mixer_free(self->mixer);
|
||||
}
|
||||
if (self->residual_spectrum) {
|
||||
free(self->residual_spectrum);
|
||||
}
|
||||
|
||||
if (self->noise_floor_manager) {
|
||||
noise_floor_manager_free(self->noise_floor_manager);
|
||||
}
|
||||
if (self->denoised_spectrum) {
|
||||
free(self->denoised_spectrum);
|
||||
}
|
||||
if (self->noise_profile) {
|
||||
free(self->noise_profile);
|
||||
}
|
||||
if (self->gain_spectrum) {
|
||||
free(self->gain_spectrum);
|
||||
}
|
||||
if (self->alpha) {
|
||||
free(self->alpha);
|
||||
}
|
||||
if (self->beta) {
|
||||
free(self->beta);
|
||||
}
|
||||
|
||||
free(self);
|
||||
}
|
||||
|
||||
bool load_adaptive_reduction_parameters(SpectralProcessorHandle instance,
|
||||
AdaptiveDenoiserParameters parameters) {
|
||||
if (!instance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SpectralAdaptiveDenoiser* self = (SpectralAdaptiveDenoiser*)instance;
|
||||
|
||||
// Check if noise estimation method has changed
|
||||
bool method_changed = (self->parameters.noise_estimation_method !=
|
||||
parameters.noise_estimation_method);
|
||||
|
||||
self->parameters = parameters;
|
||||
|
||||
// If method changed, reinitialize the adaptive estimator
|
||||
if (method_changed && self->adaptive_estimator) {
|
||||
louizou_estimator_free(self->adaptive_estimator);
|
||||
self->adaptive_estimator = NULL;
|
||||
|
||||
// Initialize the appropriate estimator based on the method
|
||||
if (self->parameters.noise_estimation_method == SPP_MMSE_METHOD) {
|
||||
self->adaptive_estimator = spp_mmse_estimator_initialize(
|
||||
self->real_spectrum_size, self->sample_rate, self->fft_size);
|
||||
} else {
|
||||
// Default to Louizou method
|
||||
self->adaptive_estimator = louizou_estimator_initialize(
|
||||
self->real_spectrum_size, self->sample_rate, self->fft_size);
|
||||
}
|
||||
|
||||
if (!self->adaptive_estimator) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spectral_adaptive_denoiser_run(SpectralProcessorHandle instance,
|
||||
float* fft_spectrum) {
|
||||
if (!fft_spectrum || !instance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SpectralAdaptiveDenoiser* self = (SpectralAdaptiveDenoiser*)instance;
|
||||
|
||||
float* reference_spectrum =
|
||||
get_spectral_feature(self->spectral_features, fft_spectrum,
|
||||
self->fft_size, self->spectrum_type);
|
||||
|
||||
// Estimate noise using the selected method
|
||||
if (self->parameters.noise_estimation_method == SPP_MMSE_METHOD) {
|
||||
spp_mmse_estimator_run(self->adaptive_estimator, reference_spectrum,
|
||||
self->noise_profile);
|
||||
} else {
|
||||
// Default to Louizou method
|
||||
louizou_estimator_run(self->adaptive_estimator, reference_spectrum,
|
||||
self->noise_profile);
|
||||
}
|
||||
|
||||
float whitening_factor =
|
||||
self->whitening_enabled ? self->parameters.whitening_factor : 0.0f;
|
||||
|
||||
// Scale estimated noise profile for oversubtraction
|
||||
NoiseScalingParameters oversubtraction_parameters = (NoiseScalingParameters){
|
||||
.oversubtraction =
|
||||
self->default_oversubtraction + self->parameters.noise_rescale,
|
||||
.undersubtraction = self->parameters.reduction_amount,
|
||||
.scaling_type = self->parameters.noise_scaling_type,
|
||||
};
|
||||
apply_noise_scaling_criteria(self->noise_scaling_criteria, reference_spectrum,
|
||||
self->noise_profile, self->alpha, self->beta,
|
||||
oversubtraction_parameters);
|
||||
|
||||
TimeSmoothingParameters spectral_smoothing_parameters =
|
||||
(TimeSmoothingParameters){
|
||||
.smoothing = self->parameters.smoothing_factor,
|
||||
};
|
||||
spectral_smoothing_run(self->spectrum_smoothing,
|
||||
spectral_smoothing_parameters, reference_spectrum);
|
||||
|
||||
estimate_gains(self->real_spectrum_size, self->fft_size, reference_spectrum,
|
||||
self->noise_profile, self->gain_spectrum, self->alpha,
|
||||
self->beta, self->gain_estimation_type);
|
||||
|
||||
noise_floor_manager_apply(
|
||||
self->noise_floor_manager, self->real_spectrum_size, self->fft_size,
|
||||
self->gain_spectrum, self->noise_profile,
|
||||
self->parameters.reduction_amount, whitening_factor);
|
||||
|
||||
if (self->postfiltering_enabled) {
|
||||
PostFiltersParameters post_filter_parameters = (PostFiltersParameters){
|
||||
.snr_threshold = self->parameters.post_filter_threshold,
|
||||
.gain_floor = self->parameters.reduction_amount,
|
||||
};
|
||||
postfilter_apply(self->postfiltering, fft_spectrum, self->gain_spectrum,
|
||||
post_filter_parameters);
|
||||
}
|
||||
|
||||
DenoiseMixerParameters mixer_parameters = (DenoiseMixerParameters){
|
||||
.noise_level = self->parameters.reduction_amount,
|
||||
.residual_listen = self->parameters.residual_listen,
|
||||
.whitening_amount = whitening_factor,
|
||||
};
|
||||
|
||||
denoise_mixer_run(self->mixer, fft_spectrum, self->gain_spectrum,
|
||||
mixer_parameters);
|
||||
|
||||
return true;
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
libspecbleach - A spectral processing library
|
||||
|
||||
Copyright 2022 Luciano Dato <lucianodato@gmail.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SPECTRAL_ADAPTIVE_DENOISER_H
|
||||
#define SPECTRAL_ADAPTIVE_DENOISER_H
|
||||
|
||||
#include "shared/spectral_processor.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "shared/noise_estimation/adaptive_noise_estimator.h"
|
||||
|
||||
typedef struct AdaptiveDenoiserParameters {
|
||||
float reduction_amount;
|
||||
int noise_scaling_type;
|
||||
float noise_rescale;
|
||||
float smoothing_factor;
|
||||
float whitening_factor;
|
||||
float post_filter_threshold;
|
||||
bool residual_listen;
|
||||
|
||||
/* Method used for adaptive noise estimation.
|
||||
* LOUIZOU_METHOD uses minimum statistics (default), SPP_MMSE_METHOD uses
|
||||
* Speech Presence Probability with MMSE estimation for lower complexity
|
||||
* and unbiased noise tracking. */
|
||||
AdaptiveNoiseEstimationMethod noise_estimation_method;
|
||||
} AdaptiveDenoiserParameters;
|
||||
|
||||
SpectralProcessorHandle spectral_adaptive_denoiser_initialize(
|
||||
uint32_t sample_rate, uint32_t fft_size, uint32_t overlap_factor);
|
||||
void spectral_adaptive_denoiser_free(SpectralProcessorHandle instance);
|
||||
bool load_adaptive_reduction_parameters(SpectralProcessorHandle instance,
|
||||
AdaptiveDenoiserParameters parameters);
|
||||
bool spectral_adaptive_denoiser_run(SpectralProcessorHandle instance,
|
||||
float* fft_spectrum);
|
||||
|
||||
#endif
|
||||
BIN
Binary file not shown.
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
libspecbleach - A spectral processing library
|
||||
|
||||
Copyright 2022 Luciano Dato <lucianodato@gmail.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "spectral_denoiser.h"
|
||||
#include "shared/configurations.h"
|
||||
#include "shared/gain_estimation/gain_estimators.h"
|
||||
#include "shared/noise_estimation/noise_estimator.h"
|
||||
#include "shared/post_estimation/noise_floor_manager.h"
|
||||
#include "shared/post_estimation/postfilter.h"
|
||||
#include "shared/pre_estimation/critical_bands.h"
|
||||
#include "shared/pre_estimation/noise_scaling_criterias.h"
|
||||
#include "shared/pre_estimation/spectral_smoother.h"
|
||||
#include "shared/utils/denoise_mixer.h"
|
||||
#include "shared/utils/spectral_features.h"
|
||||
#include "shared/utils/spectral_utils.h"
|
||||
#include <float.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct SbSpectralDenoiser {
|
||||
uint32_t fft_size;
|
||||
uint32_t real_spectrum_size;
|
||||
uint32_t sample_rate;
|
||||
uint32_t hop;
|
||||
float default_oversubtraction;
|
||||
float default_undersubtraction;
|
||||
|
||||
float* gain_spectrum;
|
||||
float* alpha;
|
||||
float* beta;
|
||||
float* noise_spectrum;
|
||||
|
||||
SpectrumType spectrum_type;
|
||||
CriticalBandType band_type;
|
||||
DenoiserParameters denoise_parameters;
|
||||
GainEstimationType gain_estimation_type;
|
||||
TimeSmoothingType time_smoothing_type;
|
||||
NoiseEstimatorType noise_estimator_type;
|
||||
|
||||
NoiseEstimator* noise_estimator;
|
||||
PostFilter* postfiltering;
|
||||
NoiseProfile* noise_profile;
|
||||
SpectralFeatures* spectral_features;
|
||||
DenoiseMixer* mixer;
|
||||
NoiseScalingCriterias* noise_scaling_criteria;
|
||||
SpectralSmoother* spectrum_smoothing;
|
||||
NoiseFloorManager* noise_floor_manager;
|
||||
bool postfiltering_enabled;
|
||||
bool whitening_enabled;
|
||||
} SbSpectralDenoiser;
|
||||
|
||||
SpectralProcessorHandle spectral_denoiser_initialize(
|
||||
const uint32_t sample_rate, const uint32_t fft_size,
|
||||
const uint32_t overlap_factor, NoiseProfile* noise_profile) {
|
||||
|
||||
if (!noise_profile || sample_rate == 0 || fft_size == 0 ||
|
||||
overlap_factor == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SbSpectralDenoiser* self =
|
||||
(SbSpectralDenoiser*)calloc(1U, sizeof(SbSpectralDenoiser));
|
||||
if (!self) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->fft_size = fft_size;
|
||||
self->real_spectrum_size = (self->fft_size / 2U) + 1U;
|
||||
self->hop = self->fft_size / overlap_factor;
|
||||
self->sample_rate = sample_rate;
|
||||
self->spectrum_type = SPECTRAL_TYPE_GENERAL;
|
||||
self->band_type = CRITICAL_BANDS_TYPE;
|
||||
self->default_oversubtraction = DEFAULT_OVERSUBTRACTION;
|
||||
self->default_undersubtraction = DEFAULT_UNDERSUBTRACTION;
|
||||
self->gain_estimation_type = GAIN_ESTIMATION_TYPE;
|
||||
self->time_smoothing_type = TIME_SMOOTHING_TYPE;
|
||||
self->postfiltering_enabled = POSTFILTER_ENABLED_GENERAL;
|
||||
self->whitening_enabled = WHITENING_ENABLED_GENERAL;
|
||||
|
||||
self->gain_spectrum = (float*)calloc(self->fft_size, sizeof(float));
|
||||
if (!self->gain_spectrum) {
|
||||
spectral_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
(void)initialize_spectrum_with_value(self->gain_spectrum, self->fft_size,
|
||||
1.F);
|
||||
|
||||
self->alpha = (float*)calloc(self->real_spectrum_size, sizeof(float));
|
||||
if (!self->alpha) {
|
||||
spectral_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
(void)initialize_spectrum_with_value(self->alpha, self->real_spectrum_size,
|
||||
1.F);
|
||||
|
||||
self->beta = (float*)calloc(self->real_spectrum_size, sizeof(float));
|
||||
if (!self->beta) {
|
||||
spectral_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->noise_profile = noise_profile;
|
||||
self->noise_spectrum =
|
||||
(float*)calloc(self->real_spectrum_size, sizeof(float));
|
||||
if (!self->noise_spectrum) {
|
||||
spectral_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->noise_estimator =
|
||||
noise_estimation_initialize(self->fft_size, noise_profile);
|
||||
if (!self->noise_estimator) {
|
||||
spectral_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->spectral_features =
|
||||
spectral_features_initialize(self->real_spectrum_size);
|
||||
if (!self->spectral_features) {
|
||||
spectral_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (self->postfiltering_enabled) {
|
||||
self->postfiltering = postfilter_initialize(self->fft_size);
|
||||
if (!self->postfiltering) {
|
||||
spectral_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
self->spectrum_smoothing =
|
||||
spectral_smoothing_initialize(self->fft_size, self->time_smoothing_type);
|
||||
if (!self->spectrum_smoothing) {
|
||||
spectral_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->noise_scaling_criteria = noise_scaling_criterias_initialize(
|
||||
self->fft_size, self->band_type, self->sample_rate, self->spectrum_type);
|
||||
if (!self->noise_scaling_criteria) {
|
||||
spectral_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->mixer =
|
||||
denoise_mixer_initialize(self->fft_size, self->sample_rate, self->hop);
|
||||
if (!self->mixer) {
|
||||
spectral_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->noise_floor_manager = noise_floor_manager_initialize(
|
||||
self->fft_size, self->sample_rate, self->hop);
|
||||
if (!self->noise_floor_manager) {
|
||||
spectral_denoiser_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void spectral_denoiser_free(SpectralProcessorHandle instance) {
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't free noise profile used as reference here
|
||||
|
||||
if (self->noise_estimator) {
|
||||
noise_estimation_free(self->noise_estimator);
|
||||
}
|
||||
if (self->spectral_features) {
|
||||
spectral_features_free(self->spectral_features);
|
||||
}
|
||||
if (self->spectrum_smoothing) {
|
||||
spectral_smoothing_free(self->spectrum_smoothing);
|
||||
}
|
||||
if (self->noise_scaling_criteria) {
|
||||
noise_scaling_criterias_free(self->noise_scaling_criteria);
|
||||
}
|
||||
if (self->postfiltering) {
|
||||
postfilter_free(self->postfiltering);
|
||||
}
|
||||
if (self->mixer) {
|
||||
denoise_mixer_free(self->mixer);
|
||||
}
|
||||
if (self->gain_spectrum) {
|
||||
free(self->gain_spectrum);
|
||||
}
|
||||
|
||||
if (self->noise_floor_manager) {
|
||||
noise_floor_manager_free(self->noise_floor_manager);
|
||||
}
|
||||
if (self->alpha) {
|
||||
free(self->alpha);
|
||||
}
|
||||
if (self->beta) {
|
||||
free(self->beta);
|
||||
}
|
||||
if (self->noise_spectrum) {
|
||||
free(self->noise_spectrum);
|
||||
}
|
||||
|
||||
free(self);
|
||||
}
|
||||
|
||||
bool load_reduction_parameters(SpectralProcessorHandle instance,
|
||||
DenoiserParameters parameters) {
|
||||
if (!instance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
self->denoise_parameters = parameters;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spectral_denoiser_run(SpectralProcessorHandle instance,
|
||||
float* fft_spectrum) {
|
||||
if (!fft_spectrum || !instance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
float* reference_spectrum =
|
||||
get_spectral_feature(self->spectral_features, fft_spectrum,
|
||||
self->fft_size, self->spectrum_type);
|
||||
|
||||
if (self->denoise_parameters.learn_noise > 0) {
|
||||
// Learn all modes simultaneously
|
||||
for (int mode = ROLLING_MEAN; mode <= MAX; mode++) {
|
||||
noise_estimation_run(self->noise_estimator, (NoiseEstimatorType)mode,
|
||||
reference_spectrum);
|
||||
}
|
||||
} else if (is_noise_estimation_available(
|
||||
self->noise_profile,
|
||||
self->denoise_parameters.noise_reduction_mode)) {
|
||||
memcpy(self->noise_spectrum,
|
||||
get_noise_profile(self->noise_profile,
|
||||
self->denoise_parameters.noise_reduction_mode),
|
||||
self->real_spectrum_size * sizeof(float));
|
||||
|
||||
NoiseScalingParameters oversubtraction_parameters =
|
||||
(NoiseScalingParameters){
|
||||
.oversubtraction = (self->default_oversubtraction +
|
||||
self->denoise_parameters.noise_rescale),
|
||||
.undersubtraction = self->denoise_parameters.reduction_amount,
|
||||
.scaling_type = self->denoise_parameters.noise_scaling_type,
|
||||
};
|
||||
|
||||
float whitening_factor = self->whitening_enabled
|
||||
? self->denoise_parameters.whitening_factor
|
||||
: 0.0f;
|
||||
|
||||
apply_noise_scaling_criteria(
|
||||
self->noise_scaling_criteria, reference_spectrum, self->noise_spectrum,
|
||||
self->alpha, self->beta, oversubtraction_parameters);
|
||||
|
||||
TimeSmoothingParameters spectral_smoothing_parameters =
|
||||
(TimeSmoothingParameters){
|
||||
.smoothing = self->denoise_parameters.smoothing_factor,
|
||||
};
|
||||
spectral_smoothing_run(self->spectrum_smoothing,
|
||||
spectral_smoothing_parameters, reference_spectrum);
|
||||
|
||||
estimate_gains(self->real_spectrum_size, self->fft_size, reference_spectrum,
|
||||
self->noise_spectrum, self->gain_spectrum, self->alpha,
|
||||
self->beta, self->gain_estimation_type);
|
||||
|
||||
noise_floor_manager_apply(
|
||||
self->noise_floor_manager, self->real_spectrum_size, self->fft_size,
|
||||
self->gain_spectrum, self->noise_spectrum,
|
||||
self->denoise_parameters.reduction_amount, whitening_factor);
|
||||
|
||||
if (self->postfiltering_enabled) {
|
||||
PostFiltersParameters post_filter_parameters = (PostFiltersParameters){
|
||||
.snr_threshold = self->denoise_parameters.post_filter_threshold,
|
||||
.gain_floor = self->denoise_parameters.reduction_amount,
|
||||
};
|
||||
postfilter_apply(self->postfiltering, fft_spectrum, self->gain_spectrum,
|
||||
post_filter_parameters);
|
||||
}
|
||||
|
||||
DenoiseMixerParameters mixer_parameters = (DenoiseMixerParameters){
|
||||
.noise_level = self->denoise_parameters.reduction_amount,
|
||||
.residual_listen = self->denoise_parameters.residual_listen,
|
||||
.whitening_amount = whitening_factor,
|
||||
};
|
||||
|
||||
denoise_mixer_run(self->mixer, fft_spectrum, self->gain_spectrum,
|
||||
mixer_parameters);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
libspecbleach - A spectral processing library
|
||||
|
||||
Copyright 2022 Luciano Dato <lucianodato@gmail.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SPECTRAL_DENOISER_H
|
||||
#define SPECTRAL_DENOISER_H
|
||||
|
||||
#include "shared/noise_estimation/noise_profile.h"
|
||||
#include "shared/spectral_processor.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct DenoiserParameters {
|
||||
float reduction_amount;
|
||||
int noise_scaling_type;
|
||||
float noise_rescale;
|
||||
bool residual_listen;
|
||||
int learn_noise;
|
||||
int noise_reduction_mode;
|
||||
float smoothing_factor;
|
||||
float whitening_factor;
|
||||
float post_filter_threshold;
|
||||
} DenoiserParameters;
|
||||
|
||||
SpectralProcessorHandle spectral_denoiser_initialize(
|
||||
uint32_t sample_rate, uint32_t fft_size, uint32_t overlap_factor,
|
||||
NoiseProfile* noise_profile);
|
||||
void spectral_denoiser_free(SpectralProcessorHandle instance);
|
||||
bool load_reduction_parameters(SpectralProcessorHandle instance,
|
||||
DenoiserParameters parameters);
|
||||
bool spectral_denoiser_run(SpectralProcessorHandle instance,
|
||||
float* fft_spectrum);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
processors_sources = files(
|
||||
'denoiser/spectral_denoiser.c',
|
||||
'adaptivedenoiser/adaptive_denoiser.c',
|
||||
'specbleach_adenoiser.c',
|
||||
'specbleach_denoiser.c',
|
||||
)
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
libspecbleach - A spectral processing library
|
||||
|
||||
Copyright 2022 Luciano Dato <lucianodato@gmail.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "specbleach_adenoiser.h"
|
||||
#include "adaptivedenoiser/adaptive_denoiser.h"
|
||||
#include "shared/configurations.h"
|
||||
#include "shared/stft/stft_processor.h"
|
||||
#include "shared/utils/general_utils.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct SbAdaptiveDenoiser {
|
||||
uint32_t sample_rate;
|
||||
AdaptiveDenoiserParameters denoise_parameters;
|
||||
|
||||
SpectralProcessorHandle adaptive_spectral_denoiser;
|
||||
StftProcessor* stft_processor;
|
||||
} SbAdaptiveDenoiser;
|
||||
|
||||
SpectralBleachHandle specbleach_adaptive_initialize(const uint32_t sample_rate,
|
||||
float frame_size) {
|
||||
SbAdaptiveDenoiser* self =
|
||||
(SbAdaptiveDenoiser*)calloc(1U, sizeof(SbAdaptiveDenoiser));
|
||||
if (!self) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->sample_rate = sample_rate;
|
||||
|
||||
self->stft_processor = stft_processor_initialize(
|
||||
sample_rate, frame_size, OVERLAP_FACTOR_SPEECH,
|
||||
PADDING_CONFIGURATION_SPEECH, ZEROPADDING_AMOUNT_SPEECH,
|
||||
INPUT_WINDOW_TYPE_SPEECH, OUTPUT_WINDOW_TYPE_SPEECH);
|
||||
|
||||
if (!self->stft_processor) {
|
||||
specbleach_adaptive_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const uint32_t fft_size = get_stft_fft_size(self->stft_processor);
|
||||
|
||||
self->adaptive_spectral_denoiser = spectral_adaptive_denoiser_initialize(
|
||||
self->sample_rate, fft_size, OVERLAP_FACTOR_SPEECH);
|
||||
|
||||
if (!self->adaptive_spectral_denoiser) {
|
||||
specbleach_adaptive_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void specbleach_adaptive_free(SpectralBleachHandle instance) {
|
||||
SbAdaptiveDenoiser* self = (SbAdaptiveDenoiser*)instance;
|
||||
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->adaptive_spectral_denoiser) {
|
||||
spectral_adaptive_denoiser_free(self->adaptive_spectral_denoiser);
|
||||
}
|
||||
if (self->stft_processor) {
|
||||
stft_processor_free(self->stft_processor);
|
||||
}
|
||||
|
||||
free(self);
|
||||
}
|
||||
|
||||
uint32_t specbleach_adaptive_get_latency(SpectralBleachHandle instance) {
|
||||
SbAdaptiveDenoiser* self = (SbAdaptiveDenoiser*)instance;
|
||||
|
||||
return get_stft_latency(self->stft_processor);
|
||||
}
|
||||
|
||||
bool specbleach_adaptive_process(SpectralBleachHandle instance,
|
||||
const uint32_t number_of_samples,
|
||||
const float* input, float* output) {
|
||||
if (!instance || number_of_samples == 0 || !input || !output) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SbAdaptiveDenoiser* self = (SbAdaptiveDenoiser*)instance;
|
||||
|
||||
stft_processor_run(self->stft_processor, number_of_samples, input, output,
|
||||
&spectral_adaptive_denoiser_run,
|
||||
self->adaptive_spectral_denoiser);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool specbleach_adaptive_load_parameters(
|
||||
SpectralBleachHandle instance,
|
||||
SpectralBleachAdaptiveParameters parameters) {
|
||||
if (!instance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SbAdaptiveDenoiser* self = (SbAdaptiveDenoiser*)instance;
|
||||
|
||||
// clang-format off
|
||||
self->denoise_parameters = (AdaptiveDenoiserParameters){
|
||||
.residual_listen = parameters.residual_listen,
|
||||
.reduction_amount =
|
||||
from_db_to_coefficient(parameters.reduction_amount * -1.F),
|
||||
.noise_rescale = from_db_to_coefficient(parameters.noise_rescale),
|
||||
.noise_scaling_type = parameters.noise_scaling_type,
|
||||
.smoothing_factor = remap_percentage_log_like_unity(parameters.smoothing_factor / 100.F),
|
||||
.whitening_factor = parameters.whitening_factor / 100.F,
|
||||
.post_filter_threshold = from_db_to_coefficient(parameters.post_filter_threshold),
|
||||
.noise_estimation_method = parameters.noise_estimation_method,
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
load_adaptive_reduction_parameters(self->adaptive_spectral_denoiser,
|
||||
self->denoise_parameters);
|
||||
|
||||
return true;
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
libspecbleach - A spectral processing library
|
||||
|
||||
Copyright 2022 Luciano Dato <lucianodato@gmail.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "specbleach_denoiser.h"
|
||||
#include "denoiser/spectral_denoiser.h"
|
||||
#include "shared/configurations.h"
|
||||
#include "shared/noise_estimation/noise_profile.h"
|
||||
#include "shared/stft/stft_processor.h"
|
||||
#include "shared/utils/general_utils.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct SbSpectralDenoiser {
|
||||
uint32_t sample_rate;
|
||||
DenoiserParameters denoise_parameters;
|
||||
|
||||
NoiseProfile* noise_profile;
|
||||
SpectralProcessorHandle spectral_denoiser;
|
||||
StftProcessor* stft_processor;
|
||||
} SbSpectralDenoiser;
|
||||
|
||||
SpectralBleachHandle specbleach_initialize(const uint32_t sample_rate,
|
||||
float frame_size) {
|
||||
if (sample_rate < 4000 || sample_rate > 192000 || frame_size <= 0.0f) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SbSpectralDenoiser* self =
|
||||
(SbSpectralDenoiser*)calloc(1U, sizeof(SbSpectralDenoiser));
|
||||
if (!self) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->sample_rate = sample_rate;
|
||||
|
||||
self->stft_processor = stft_processor_initialize(
|
||||
sample_rate, frame_size, OVERLAP_FACTOR_GENERAL,
|
||||
PADDING_CONFIGURATION_GENERAL, ZEROPADDING_AMOUNT_GENERAL,
|
||||
INPUT_WINDOW_TYPE_GENERAL, OUTPUT_WINDOW_TYPE_GENERAL);
|
||||
|
||||
if (!self->stft_processor) {
|
||||
specbleach_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const uint32_t fft_size = get_stft_fft_size(self->stft_processor);
|
||||
const uint32_t real_spectrum_size =
|
||||
get_stft_real_spectrum_size(self->stft_processor);
|
||||
|
||||
self->noise_profile = noise_profile_initialize(real_spectrum_size);
|
||||
|
||||
if (!self->noise_profile) {
|
||||
specbleach_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->spectral_denoiser = spectral_denoiser_initialize(
|
||||
self->sample_rate, fft_size, OVERLAP_FACTOR_GENERAL, self->noise_profile);
|
||||
|
||||
if (!self->spectral_denoiser) {
|
||||
specbleach_free(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void specbleach_free(SpectralBleachHandle instance) {
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
if (!self) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->noise_profile) {
|
||||
noise_profile_free(self->noise_profile);
|
||||
}
|
||||
if (self->spectral_denoiser) {
|
||||
spectral_denoiser_free(self->spectral_denoiser);
|
||||
}
|
||||
if (self->stft_processor) {
|
||||
stft_processor_free(self->stft_processor);
|
||||
}
|
||||
|
||||
free(self);
|
||||
}
|
||||
|
||||
uint32_t specbleach_get_latency(SpectralBleachHandle instance) {
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
if (!self || !self->stft_processor) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return get_stft_latency(self->stft_processor);
|
||||
}
|
||||
|
||||
bool specbleach_process(SpectralBleachHandle instance,
|
||||
const uint32_t number_of_samples, const float* input,
|
||||
float* output) {
|
||||
if (!instance || number_of_samples == 0 || !input || !output) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
stft_processor_run(self->stft_processor, number_of_samples, input, output,
|
||||
&spectral_denoiser_run, self->spectral_denoiser);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t specbleach_get_noise_profile_size(SpectralBleachHandle instance) {
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
if (!self || !self->noise_profile) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return get_noise_profile_size(self->noise_profile);
|
||||
}
|
||||
|
||||
uint32_t specbleach_get_noise_profile_blocks_averaged(
|
||||
SpectralBleachHandle instance) {
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
if (!self || !self->noise_profile) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return get_noise_profile_blocks_averaged(
|
||||
self->noise_profile, self->denoise_parameters.noise_reduction_mode);
|
||||
}
|
||||
|
||||
float* specbleach_get_noise_profile(SpectralBleachHandle instance) {
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
if (!self || !self->noise_profile) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return get_noise_profile(self->noise_profile,
|
||||
self->denoise_parameters.noise_reduction_mode);
|
||||
}
|
||||
|
||||
bool specbleach_load_noise_profile(SpectralBleachHandle instance,
|
||||
const float* restored_profile,
|
||||
const uint32_t profile_size,
|
||||
const uint32_t averaged_blocks) {
|
||||
if (!instance || !restored_profile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
if (profile_size != get_noise_profile_size(self->noise_profile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_noise_profile(self->noise_profile,
|
||||
self->denoise_parameters.noise_reduction_mode,
|
||||
restored_profile, profile_size, averaged_blocks);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool specbleach_load_noise_profile_for_mode(SpectralBleachHandle instance,
|
||||
const float* restored_profile,
|
||||
const uint32_t profile_size,
|
||||
const uint32_t averaged_blocks,
|
||||
const int mode) {
|
||||
if (!instance || !restored_profile || mode < 1 || mode > 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
if (profile_size != get_noise_profile_size(self->noise_profile)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_noise_profile(self->noise_profile, mode, restored_profile, profile_size,
|
||||
averaged_blocks);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool specbleach_reset_noise_profile(SpectralBleachHandle instance) {
|
||||
if (!instance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
reset_noise_profile(self->noise_profile);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool specbleach_noise_profile_available(SpectralBleachHandle instance) {
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
return is_noise_estimation_available(
|
||||
self->noise_profile, self->denoise_parameters.noise_reduction_mode);
|
||||
}
|
||||
|
||||
uint32_t specbleach_get_noise_profile_blocks_averaged_for_mode(
|
||||
SpectralBleachHandle instance, int mode) {
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
if (!self || mode < 1 || mode > 3) {
|
||||
return 0;
|
||||
}
|
||||
return get_noise_profile_blocks_averaged(self->noise_profile, mode);
|
||||
}
|
||||
|
||||
float* specbleach_get_noise_profile_for_mode(SpectralBleachHandle instance,
|
||||
int mode) {
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
if (!self || mode < 1 || mode > 3) {
|
||||
return NULL;
|
||||
}
|
||||
return get_noise_profile(self->noise_profile, mode);
|
||||
}
|
||||
|
||||
bool specbleach_noise_profile_available_for_mode(SpectralBleachHandle instance,
|
||||
int mode) {
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
if (!self || mode < 1 || mode > 3) {
|
||||
return false;
|
||||
}
|
||||
return is_noise_estimation_available(self->noise_profile, mode);
|
||||
}
|
||||
|
||||
bool specbleach_load_parameters(SpectralBleachHandle instance,
|
||||
SpectralBleachDenoiserParameters parameters) {
|
||||
if (!instance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SbSpectralDenoiser* self = (SbSpectralDenoiser*)instance;
|
||||
|
||||
// clang-format off
|
||||
self->denoise_parameters = (DenoiserParameters){
|
||||
.learn_noise = parameters.learn_noise,
|
||||
.noise_reduction_mode = parameters.noise_reduction_mode,
|
||||
.residual_listen = parameters.residual_listen,
|
||||
.noise_scaling_type = parameters.noise_scaling_type,
|
||||
.reduction_amount =
|
||||
from_db_to_coefficient(parameters.reduction_amount * -1.F),
|
||||
.noise_rescale = from_db_to_coefficient(parameters.noise_rescale),
|
||||
.smoothing_factor = remap_percentage_log_like_unity(parameters.smoothing_factor / 100.F),
|
||||
.whitening_factor = parameters.whitening_factor / 100.F,
|
||||
.post_filter_threshold = from_db_to_coefficient(parameters.post_filter_threshold),
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
load_reduction_parameters(self->spectral_denoiser, self->denoise_parameters);
|
||||
|
||||
return true;
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user