first commit

This commit is contained in:
Uladzimir Karpenka
2026-06-01 15:58:45 +03:00
commit 89c8a0e2b5
313 changed files with 945364 additions and 0 deletions
@@ -0,0 +1,98 @@
/*
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 "denoise_mixer.h"
#include <stdlib.h>
#include <string.h>
struct DenoiseMixer {
float* residual_spectrum;
float* denoised_spectrum;
uint32_t fft_size;
uint32_t real_spectrum_size;
uint32_t sample_rate;
uint32_t hop;
};
DenoiseMixer* denoise_mixer_initialize(uint32_t fft_size, uint32_t sample_rate,
uint32_t hop) {
DenoiseMixer* self = (DenoiseMixer*)calloc(1U, sizeof(DenoiseMixer));
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 = hop;
self->residual_spectrum = (float*)calloc((self->fft_size), sizeof(float));
self->denoised_spectrum = (float*)calloc((self->fft_size), sizeof(float));
if (!self->residual_spectrum || !self->denoised_spectrum) {
denoise_mixer_free(self);
return NULL;
}
return self;
}
void denoise_mixer_free(DenoiseMixer* self) {
if (!self) {
return;
}
free(self->residual_spectrum);
free(self->denoised_spectrum);
free(self);
}
bool denoise_mixer_run(DenoiseMixer* self, float* fft_spectrum,
const float* gain_spectrum,
DenoiseMixerParameters parameters) {
if (!fft_spectrum || !gain_spectrum) {
return false;
}
// Get denoised spectrum - Apply to both real and complex parts
for (uint32_t k = 0U; k < self->fft_size; k++) {
self->denoised_spectrum[k] = fft_spectrum[k] * gain_spectrum[k];
}
// Get residual spectrum - Apply to both real and complex parts
for (uint32_t k = 0U; k < self->fft_size; k++) {
self->residual_spectrum[k] = fft_spectrum[k] - self->denoised_spectrum[k];
}
// Mix denoised and residual - Now a simple toggle
if (parameters.residual_listen) {
for (uint32_t k = 0U; k < self->fft_size; k++) {
fft_spectrum[k] = self->residual_spectrum[k];
}
} else {
for (uint32_t k = 0U; k < self->fft_size; k++) {
fft_spectrum[k] = self->denoised_spectrum[k];
}
}
return true;
}
@@ -0,0 +1,42 @@
/*
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 DENOISE_MIXER_H
#define DENOISE_MIXER_H
#include <stdbool.h>
#include <stdint.h>
typedef struct DenoiseMixerParameters {
float noise_level;
bool residual_listen;
float whitening_amount;
} DenoiseMixerParameters;
typedef struct DenoiseMixer DenoiseMixer;
DenoiseMixer* denoise_mixer_initialize(uint32_t fft_size, uint32_t sample_rate,
uint32_t hop);
void denoise_mixer_free(DenoiseMixer* self);
bool denoise_mixer_run(DenoiseMixer* self, float* fft_spectrum,
const float* gain_spectrum,
DenoiseMixerParameters parameters);
#endif
Binary file not shown.
@@ -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
*/
#include "general_utils.h"
#include <float.h>
#include <math.h>
#include <stdlib.h>
float sanitize_denormal(float value) {
if (!isnormal(value)) {
value = 0.F;
}
return value;
}
float from_db_to_coefficient(const float value_db) {
return expf(value_db / 20.F * logf(10.F));
}
float remap_percentage_log_like_unity(const float value) {
return 1.F - expf(-3.F * (value));
}
int get_next_divisible_two(int number) {
int q = number / 2;
int n1 = 2 * q;
int n2 = (number * 2) > 0 ? (2 * (q + 1)) : (2 * (q - 1));
if (abs(number - n1) < abs(number - n2)) {
return n1;
}
return n2;
}
int get_next_power_two(int number) {
return (int)roundf(powf(2.F, ceilf(log2f((float)number))));
}
@@ -0,0 +1,39 @@
/*
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 GENERAL_UTILS_H
#define GENERAL_UTILS_H
#include <stdbool.h>
#include <stdint.h>
// Compile-time validation
_Static_assert(sizeof(float) >= 4, "float must be at least 32 bits");
_Static_assert(sizeof(double) >= 8, "double must be at least 64 bits");
__attribute__((warn_unused_result)) float sanitize_denormal(float value);
__attribute__((warn_unused_result)) float from_db_to_coefficient(
float value_db);
__attribute__((warn_unused_result)) float remap_percentage_log_like_unity(
float value);
__attribute__((warn_unused_result)) int get_next_divisible_two(int number);
__attribute__((warn_unused_result)) int get_next_power_two(int number);
#endif
Binary file not shown.
@@ -0,0 +1,7 @@
shared_sources += files(
'general_utils.c',
'denoise_mixer.c',
'spectral_features.c',
'spectral_utils.c',
'spectral_trailing_buffer.c',
)
@@ -0,0 +1,189 @@
/*
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_features.h"
#include <math.h>
#include <stdlib.h>
struct SpectralFeatures {
float* power_spectrum;
float* phase_spectrum;
float* magnitude_spectrum;
uint32_t real_spectrum_size;
};
SpectralFeatures* spectral_features_initialize(
const uint32_t real_spectrum_size) {
SpectralFeatures* self =
(SpectralFeatures*)calloc(1U, sizeof(SpectralFeatures));
if (!self) {
return NULL;
}
self->real_spectrum_size = real_spectrum_size;
self->power_spectrum =
(float*)calloc(self->real_spectrum_size, sizeof(float));
self->phase_spectrum =
(float*)calloc(self->real_spectrum_size, sizeof(float));
self->magnitude_spectrum =
(float*)calloc(self->real_spectrum_size, sizeof(float));
if (!self->power_spectrum || !self->phase_spectrum ||
!self->magnitude_spectrum) {
spectral_features_free(self);
return NULL;
}
return self;
}
void spectral_features_free(SpectralFeatures* self) {
if (!self) {
return;
}
free(self->power_spectrum);
free(self->phase_spectrum);
free(self->magnitude_spectrum);
free(self);
}
float* get_power_spectrum(SpectralFeatures* self) {
return self->power_spectrum;
}
float* get_magnitude_spectrum(SpectralFeatures* self) {
return self->magnitude_spectrum;
}
float* get_phase_spectrum(SpectralFeatures* self) {
return self->phase_spectrum;
}
static bool compute_power_spectrum(SpectralFeatures* self,
const float* fft_spectrum,
const uint32_t fft_spectrum_size) {
if (!self || !fft_spectrum || !fft_spectrum_size) {
return false;
}
const uint32_t n = fft_spectrum_size;
const uint32_t n2 = n / 2U;
const bool is_even = (n % 2U == 0);
// DC bin
self->power_spectrum[0] = fft_spectrum[0] * fft_spectrum[0];
// Complex bins
for (uint32_t k = 1U; k < n2; k++) {
float real = fft_spectrum[k];
float imag = fft_spectrum[n - k];
self->power_spectrum[k] = (real * real) + (imag * imag);
}
// Nyquist bin
if (is_even) {
self->power_spectrum[n2] = fft_spectrum[n2] * fft_spectrum[n2];
}
return true;
}
static bool compute_magnitude_spectrum(SpectralFeatures* self,
const float* fft_spectrum,
const uint32_t fft_spectrum_size) {
if (!self || !fft_spectrum || !fft_spectrum_size) {
return false;
}
const uint32_t n = fft_spectrum_size;
const uint32_t n2 = n / 2U;
const bool is_even = (n % 2U == 0);
// DC bin
self->magnitude_spectrum[0] = fabsf(fft_spectrum[0]);
// Complex bins
for (uint32_t k = 1U; k < n2; k++) {
self->magnitude_spectrum[k] = hypotf(fft_spectrum[k], fft_spectrum[n - k]);
}
// Nyquist bin
if (is_even) {
self->magnitude_spectrum[n2] = fabsf(fft_spectrum[n2]);
}
return true;
}
static bool compute_phase_spectrum(SpectralFeatures* self,
const float* fft_spectrum,
const uint32_t fft_spectrum_size) {
if (!self || !fft_spectrum || !fft_spectrum_size) {
return false;
}
const uint32_t n = fft_spectrum_size;
const uint32_t n2 = n / 2U;
const bool is_even = (n % 2U == 0);
// DC bin - purely real
self->phase_spectrum[0] = atan2f(0.F, fft_spectrum[0]);
// Complex bins
for (uint32_t k = 1U; k < n2; k++) {
float real = fft_spectrum[k];
float imag = fft_spectrum[n - k];
self->phase_spectrum[k] = atan2f(imag, real);
}
// Nyquist bin - purely real
if (is_even) {
self->phase_spectrum[n2] = atan2f(0.F, fft_spectrum[n2]);
}
return true;
}
float* get_spectral_feature(SpectralFeatures* self, const float* fft_spectrum,
uint32_t fft_spectrum_size, SpectrumType type) {
if (!self || !fft_spectrum || fft_spectrum_size == 0U) {
return NULL;
}
switch (type) {
case POWER_SPECTRUM:
compute_power_spectrum(self, fft_spectrum, fft_spectrum_size);
return get_power_spectrum(self);
break;
case MAGNITUDE_SPECTRUM:
compute_magnitude_spectrum(self, fft_spectrum, fft_spectrum_size);
return get_magnitude_spectrum(self);
break;
case PHASE_SPECTRUM:
compute_phase_spectrum(self, fft_spectrum, fft_spectrum_size);
return get_phase_spectrum(self);
break;
default:
return NULL;
break;
}
}
@@ -0,0 +1,40 @@
/*
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_FEATURES_H
#define SPECTRAL_FEATURES_H
#include <stdbool.h>
#include <stdint.h>
typedef struct SpectralFeatures SpectralFeatures;
typedef enum SpectrumType {
POWER_SPECTRUM = 0,
MAGNITUDE_SPECTRUM = 1,
PHASE_SPECTRUM = 2,
} SpectrumType;
SpectralFeatures* spectral_features_initialize(uint32_t real_spectrum_size);
void spectral_features_free(SpectralFeatures* self);
float* get_spectral_feature(SpectralFeatures* self, const float* fft_spectrum,
uint32_t fft_spectrum_size, SpectrumType type);
#endif
Binary file not shown.
@@ -0,0 +1,90 @@
/*
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_trailing_buffer.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
struct SpectralTrailingBuffer {
uint32_t real_spectrum_size;
uint32_t buffer_size;
float* buffer;
};
SpectralTrailingBuffer* spectral_trailing_buffer_initialize(
const uint32_t real_spectrum_size, const uint32_t buffer_size) {
SpectralTrailingBuffer* self =
(SpectralTrailingBuffer*)calloc(1U, sizeof(SpectralTrailingBuffer));
if (!self) {
return NULL;
}
self->real_spectrum_size = real_spectrum_size;
self->buffer_size = buffer_size;
self->buffer = (float*)calloc(
((size_t)self->real_spectrum_size * (size_t)self->buffer_size),
sizeof(float));
if (!self->buffer) {
spectral_trailing_buffer_free(self);
return NULL;
}
return self;
}
void spectral_trailing_buffer_free(SpectralTrailingBuffer* self) {
if (!self) {
return;
}
free(self->buffer);
free(self);
}
bool spectral_trailing_buffer_push_back(SpectralTrailingBuffer* self,
const float* input_spectrum) {
if (!input_spectrum) {
return false;
}
memmove(self->buffer, &self->buffer[self->real_spectrum_size],
sizeof(float) * self->real_spectrum_size * (self->buffer_size - 1U));
memcpy(&self->buffer[(size_t)self->real_spectrum_size *
(size_t)(self->buffer_size - 1U)],
input_spectrum, sizeof(float) * self->real_spectrum_size);
return true;
}
float* get_trailing_spectral_buffer(SpectralTrailingBuffer* self) {
return self->buffer;
}
uint32_t get_spectrum_buffer_size(SpectralTrailingBuffer* self) {
return self->buffer_size;
}
uint32_t get_spectrum_size(SpectralTrailingBuffer* self) {
return self->real_spectrum_size;
}
@@ -0,0 +1,38 @@
/*
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_TRAILING_BUFFER_H
#define SPECTRAL_TRAILING_BUFFER_H
#include <stdbool.h>
#include <stdint.h>
typedef struct SpectralTrailingBuffer SpectralTrailingBuffer;
SpectralTrailingBuffer* spectral_trailing_buffer_initialize(
uint32_t real_spectrum_size, uint32_t buffer_size);
void spectral_trailing_buffer_free(SpectralTrailingBuffer* self);
bool spectral_trailing_buffer_push_back(SpectralTrailingBuffer* self,
const float* input_spectrum);
float* get_trailing_spectral_buffer(SpectralTrailingBuffer* self);
uint32_t get_spectrum_buffer_size(SpectralTrailingBuffer* self);
uint32_t get_spectrum_size(SpectralTrailingBuffer* self);
#endif
@@ -0,0 +1,280 @@
/*
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_utils.h"
#include "../configurations.h"
#include "general_utils.h"
#include <float.h>
#include <math.h>
#include <stdlib.h>
static float blackman(const uint32_t bin_index, const uint32_t fft_size) {
const float p = ((float)(bin_index)) / ((float)(fft_size));
return sanitize_denormal(0.42F - (0.5F * cosf(2.F * M_PIf * p)) +
(0.08F * cosf(4.F * M_PIf * p)));
}
static float hanning(const uint32_t bin_index, const uint32_t fft_size) {
const float p = ((float)(bin_index)) / ((float)(fft_size));
return sanitize_denormal(0.5F - (0.5F * cosf(2.F * M_PIf * p)));
}
static float hamming(const uint32_t bin_index, const uint32_t fft_size) {
const float p = ((float)(bin_index)) / ((float)(fft_size));
return sanitize_denormal(0.54F - (0.46F * cosf(2.F * M_PIf * p)));
}
static float vorbis(const uint32_t bin_index, const uint32_t fft_size) {
const float p = ((float)(bin_index)) / ((float)(fft_size));
return sanitize_denormal(sinf(M_PIf / 2.F * powf(sinf(M_PIf * p), 2.F)));
}
bool get_fft_window(float* window, const uint32_t fft_size,
const WindowTypes window_type) {
if (!window || !fft_size) {
return false;
}
for (uint32_t k = 0; k < fft_size; k++) {
switch (window_type) {
case HANN_WINDOW:
window[k] = hanning(k, fft_size);
break;
case HAMMING_WINDOW:
window[k] = hamming(k, fft_size);
break;
case BLACKMAN_WINDOW:
window[k] = blackman(k, fft_size);
break;
case VORBIS_WINDOW:
window[k] = vorbis(k, fft_size);
break;
default:
break;
}
}
return true;
}
bool initialize_spectrum_with_value(float* spectrum, uint32_t spectrum_size,
const float value) {
if (!spectrum || spectrum_size == 0U) {
return false;
}
for (uint32_t i = 0U; i < spectrum_size; i++) {
spectrum[i] = value;
}
return true;
}
float max_spectral_value(const float* spectrum,
const uint32_t real_spectrum_size) {
if (!spectrum || real_spectrum_size == 0U) {
return 0.F;
}
float max = spectrum[0];
for (uint32_t k = 1U; k < real_spectrum_size; k++) {
max = fmaxf(spectrum[k], max);
}
return max;
}
float min_spectral_value(const float* spectrum,
const uint32_t real_spectrum_size) {
if (!spectrum || real_spectrum_size == 0U) {
return 0.F;
}
float min = spectrum[0];
for (uint32_t k = 1U; k < real_spectrum_size; k++) {
min = fminf(spectrum[k], min);
}
return min;
}
bool min_spectrum_float(float* spectrum_one, const float* spectrum_two,
const uint32_t spectrum_size) {
if (!spectrum_one || !spectrum_two || spectrum_size == 0U) {
return false;
}
for (uint32_t k = 0; k < spectrum_size; k++) {
spectrum_one[k] = fminf(spectrum_one[k], spectrum_two[k]);
}
return true;
}
bool max_spectrum_float(float* spectrum_one, const float* spectrum_two,
const uint32_t spectrum_size) {
if (!spectrum_one || !spectrum_two || spectrum_size == 0U) {
return false;
}
for (uint32_t k = 0; k < spectrum_size; k++) {
spectrum_one[k] = fmaxf(spectrum_one[k], spectrum_two[k]);
}
return true;
}
bool min_spectrum_double(double* spectrum_one, const double* spectrum_two,
const uint32_t spectrum_size) {
if (!spectrum_one || !spectrum_two || spectrum_size == 0U) {
return false;
}
for (uint32_t k = 0; k < spectrum_size; k++) {
spectrum_one[k] = fmin(spectrum_one[k], spectrum_two[k]);
}
return true;
}
bool max_spectrum_double(double* spectrum_one, const double* spectrum_two,
const uint32_t spectrum_size) {
if (!spectrum_one || !spectrum_two || spectrum_size == 0U) {
return false;
}
for (uint32_t k = 0; k < spectrum_size; k++) {
spectrum_one[k] = fmax(spectrum_one[k], spectrum_two[k]);
}
return true;
}
bool direct_matrix_to_vector_spectral_convolution(const float* matrix_spectum,
const float* spectrum,
float* out_spectrum,
uint32_t spectrum_size) {
if (!matrix_spectum || !spectrum || !out_spectrum || spectrum_size == 0U) {
return false;
}
for (uint32_t i = 0U; i < spectrum_size; i++) {
out_spectrum[i] = 0.F;
for (uint32_t j = 0U; j < spectrum_size; j++) {
out_spectrum[i] +=
(matrix_spectum[(i * spectrum_size) + j] * spectrum[j]);
}
}
return true;
}
float fft_bin_to_freq(const uint32_t bin_index, const uint32_t sample_rate,
const uint32_t fft_size) {
return (float)bin_index * ((float)sample_rate / (float)fft_size);
}
uint32_t freq_to_fft_bin(const float freq, const uint32_t sample_rate,
const uint32_t fft_size) {
return (uint32_t)((freq / ((float)sample_rate / (float)fft_size)) + 0.5f);
}
float spectral_flux(const float* spectrum, const float* previous_spectrum,
const uint32_t spectrum_size) {
if (!spectrum || !previous_spectrum || spectrum_size == 0U) {
return 0.F;
}
float spectral_flux = 0.F;
for (uint32_t i = 0U; i < spectrum_size; i++) {
const float temp = sqrtf(spectrum[i]) - sqrtf(previous_spectrum[i]);
spectral_flux += (temp + fabsf(temp)) / 2.F;
}
return spectral_flux;
}
bool get_rolling_mean_spectrum(float* averaged_spectrum,
const float* current_spectrum,
const uint32_t number_of_blocks,
const uint32_t spectrum_size) {
if (!averaged_spectrum || !current_spectrum || spectrum_size == 0U) {
return false;
}
for (uint32_t k = 0U; k < spectrum_size; k++) {
if (number_of_blocks <= 1U) {
averaged_spectrum[k] = current_spectrum[k];
} else {
averaged_spectrum[k] += (current_spectrum[k] - averaged_spectrum[k]) /
(float)number_of_blocks;
}
}
return true;
}
static int min_max_comparator(const void* a, const void* b) {
float x = *(const float*)a;
float y = *(const float*)b;
return x >= y ? 1 : -1;
}
static float find_median(const float* array, uint32_t array_size) {
float median = 0.F;
if (array_size % 2 == 0) {
// if number of elements are even
median = (array[(array_size - 1U) / 2U] + array[array_size / 2U]) / 2.F;
} else {
// if number of elements are odd
median = array[array_size / 2U];
}
return median;
}
bool get_rolling_median_spectrum(float* median_spectrum,
const float* current_spectrum_buffer,
const uint32_t number_of_blocks,
const uint32_t spectrum_size) {
if (!median_spectrum || !current_spectrum_buffer || spectrum_size == 0U) {
return false;
}
float tmp_buffer[number_of_blocks];
for (uint32_t i = 0U; i < spectrum_size; i++) {
for (uint32_t j = 0U; j < number_of_blocks; j++) {
tmp_buffer[j] = current_spectrum_buffer[(j * spectrum_size) + i];
}
// Sorting array
qsort(tmp_buffer, number_of_blocks, sizeof(float), min_max_comparator);
float median_of_buffer = find_median(tmp_buffer, number_of_blocks);
// Taking the max of the median
if (median_of_buffer > median_spectrum[i]) {
median_spectrum[i] = median_of_buffer;
}
}
return true;
}
@@ -0,0 +1,78 @@
/*
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_UTILS_H
#define SPECTRAL_UTILS_H
#include <stdbool.h>
#include <stdint.h>
typedef enum WindowTypes {
HANN_WINDOW = 0,
HAMMING_WINDOW = 1,
BLACKMAN_WINDOW = 2,
VORBIS_WINDOW = 3
} WindowTypes;
bool get_fft_window(float* window, uint32_t fft_size, WindowTypes window_type);
bool initialize_spectrum_with_value(float* spectrum, uint32_t spectrum_size,
float value);
bool direct_matrix_to_vector_spectral_convolution(const float* matrix_spectum,
const float* spectrum,
float* out_spectrum,
uint32_t spectrum_size);
float max_spectral_value(const float* spectrum, uint32_t real_spectrum_size);
float min_spectral_value(const float* spectrum, uint32_t real_spectrum_size);
#define min_spectrum(spectrum_one, spectrum_two, spectrum_size) \
_Generic((spectrum_one), \
float*: min_spectrum_float, \
double*: min_spectrum_double, \
default: min_spectrum_float)(spectrum_one, spectrum_two, spectrum_size)
#define max_spectrum(spectrum_one, spectrum_two, spectrum_size) \
_Generic((spectrum_one), \
float*: max_spectrum_float, \
double*: max_spectrum_double, \
default: max_spectrum_float)(spectrum_one, spectrum_two, spectrum_size)
bool min_spectrum_float(float* spectrum_one, const float* spectrum_two,
uint32_t spectrum_size);
bool max_spectrum_float(float* spectrum_one, const float* spectrum_two,
uint32_t spectrum_size);
bool min_spectrum_double(double* spectrum_one, const double* spectrum_two,
uint32_t spectrum_size);
bool max_spectrum_double(double* spectrum_one, const double* spectrum_two,
uint32_t spectrum_size);
float fft_bin_to_freq(uint32_t bin_index, uint32_t sample_rate,
uint32_t fft_size);
uint32_t freq_to_fft_bin(float freq, uint32_t sample_rate, uint32_t fft_size);
float spectral_flux(const float* spectrum, const float* previous_spectrum,
uint32_t spectrum_size);
bool get_rolling_mean_spectrum(float* averaged_spectrum,
const float* current_spectrum,
uint32_t number_of_blocks,
uint32_t spectrum_size);
bool get_rolling_median_spectrum(float* median_spectrum,
const float* current_spectrum_buffer,
uint32_t number_of_blocks,
uint32_t spectrum_size);
#endif
Binary file not shown.