Merge branch 'eid-rnnoise' into 'master'

Add rnnoise denoiser

See merge request kart-krew-dev/ring-racers-internal!2861
This commit is contained in:
Eidolon 2025-09-16 17:11:19 -05:00
commit 6eae1715a0
31 changed files with 7219 additions and 17 deletions

View file

@ -20,6 +20,14 @@
- libvorbis + libvorbisenc
Copyright (c) 2002-2020 Xiph.org Foundation
https://github.com/xiph/vorbis
- ReNameNoise + rnnoise
Copyright (c) 2024 The Mumble Developers
Copyright (c) 2017 Mozilla
Copyright (c) 2007-2017 Jean-Marc Valin
Copyright (c) 2005-2017 Xiph.Org Foundation
Copyright (c) 2003-2004 Mark Borgerding
https://github.com/mumble-voip/ReNameNoise
--------------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without

View file

@ -279,6 +279,7 @@ target_link_libraries(SRB2SDL2 PRIVATE ZLIB::ZLIB)
target_link_libraries(SRB2SDL2 PRIVATE PNG::PNG)
target_link_libraries(SRB2SDL2 PRIVATE CURL::libcurl)
target_link_libraries(SRB2SDL2 PRIVATE Opus::opus)
target_link_libraries(SRB2SDL2 PRIVATE ReNameNoise::renamenoise)
if("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
target_link_libraries(SRB2SDL2 PRIVATE -lexecinfo)
target_link_libraries(SRB2SDL2 PRIVATE -lpthread)

View file

@ -1410,6 +1410,10 @@ consvar_t cv_voice_loopback = Player("voice_loopback", "Off")
.dont_save()
.description("When on, plays the local player's voice");
consvar_t cv_voice_denoise = Player("voice_denoise", "On")
.on_off()
.description("When on, denoises the voice microphone signal");
consvar_t cv_voice_proximity = NetVar("voice_proximity", "On")
.on_off()
.description("Whether proximity effects for voice chat are enabled on the server.");

View file

@ -17,6 +17,7 @@
#endif
#include <opus.h>
#include <renamenoise.h>
#include "i_time.h"
#include "i_net.h"
@ -203,6 +204,7 @@ static UINT64 g_player_opus_lastframe[MAXPLAYERS];
static UINT32 g_player_voice_frames_this_tic[MAXPLAYERS];
#define MAX_PLAYER_VOICE_FRAMES_PER_TIC 3
static OpusEncoder *g_local_opus_encoder;
static ReNameNoiseDenoiseState *g_local_renamenoise_state;
static UINT64 g_local_opus_frame = 0;
#define SRB2_VOICE_OPUS_FRAME_SIZE 960
static float g_local_voice_buffer[SRB2_VOICE_OPUS_FRAME_SIZE];
@ -2573,6 +2575,25 @@ static void Command_connect(void)
static void ResetNode(INT32 node);
static void RecreatePlayerOpusDecoder(INT32 playernum)
{
// Destroy and recreate the opus decoder for this playernum
OpusDecoder *opusdecoder = g_player_opus_decoders[playernum];
if (opusdecoder)
{
opus_decoder_destroy(opusdecoder);
opusdecoder = NULL;
}
int error;
opusdecoder = opus_decoder_create(48000, 1, &error);
if (error != OPUS_OK)
{
CONS_Alert(CONS_WARNING, "Failed to create Opus decoder for player %d: opus error %d\n", playernum, error);
opusdecoder = NULL;
}
g_player_opus_decoders[playernum] = opusdecoder;
}
//
// CL_ClearPlayer
//
@ -2648,23 +2669,7 @@ void CL_ClearPlayer(INT32 playernum)
// Clear voice chat data
S_ResetVoiceQueue(playernum);
{
// Destroy and recreate the opus decoder for this playernum
OpusDecoder *opusdecoder = g_player_opus_decoders[playernum];
if (opusdecoder)
{
opus_decoder_destroy(opusdecoder);
opusdecoder = NULL;
}
int error;
opusdecoder = opus_decoder_create(48000, 1, &error);
if (error != OPUS_OK)
{
CONS_Alert(CONS_WARNING, "Failed to create Opus decoder for player %d: opus error %d\n", playernum, error);
opusdecoder = NULL;
}
g_player_opus_decoders[playernum] = opusdecoder;
}
RecreatePlayerOpusDecoder(playernum);
}
//
@ -3709,6 +3714,17 @@ void D_QuitNetGame(void)
#endif
}
static void InitializeLocalVoiceDenoiser(void)
{
if (g_local_renamenoise_state != NULL)
{
renamenoise_destroy(g_local_renamenoise_state);
g_local_renamenoise_state = NULL;
}
g_local_renamenoise_state = renamenoise_create(NULL);
}
static void InitializeLocalVoiceEncoder(void)
{
// Reset voice opus encoder for local "player 1"
@ -3815,6 +3831,7 @@ static void Got_AddPlayer(const UINT8 **p, INT32 playernum)
}
DEBFILE("spawning me\n");
InitializeLocalVoiceDenoiser();
InitializeLocalVoiceEncoder();
}
@ -7592,6 +7609,28 @@ void NetVoiceUpdate(void)
g_local_voice_buffer[i] *= ampfactor;
}
if (cv_voice_denoise.value)
{
if (g_local_renamenoise_state == NULL)
{
InitializeLocalVoiceDenoiser();
}
int rnnoise_size = renamenoise_get_frame_size();
float *subframe_buffer = (float*) Z_Malloc(rnnoise_size * sizeof(float), PU_STATIC, NULL);
float *denoise_buffer = (float*) Z_Malloc(rnnoise_size * sizeof(float), PU_STATIC, NULL);
// rnnoise frames are smaller than opus, but we should not expect the opus frame to be an exact multiple of rnnoise
for (int denoise_position = 0; denoise_position < SRB2_VOICE_OPUS_FRAME_SIZE; denoise_position += rnnoise_size)
{
memset(subframe_buffer, 0, rnnoise_size * sizeof(float));
memcpy(subframe_buffer, g_local_voice_buffer + denoise_position, min(rnnoise_size * sizeof(float), (SRB2_VOICE_OPUS_FRAME_SIZE - denoise_position) * sizeof(float)));
renamenoise_process_frame(g_local_renamenoise_state, denoise_buffer, subframe_buffer);
memcpy(g_local_voice_buffer + denoise_position, denoise_buffer, min(rnnoise_size * sizeof(float), (SRB2_VOICE_OPUS_FRAME_SIZE - denoise_position) * sizeof(float)));
}
Z_Free(denoise_buffer);
Z_Free(subframe_buffer);
}
float softmem = 0.f;
opus_pcm_soft_clip(g_local_voice_buffer, SRB2_VOICE_OPUS_FRAME_SIZE, 1, &softmem);
@ -7670,6 +7709,10 @@ void NetVoiceUpdate(void)
if (cv_voice_loopback.value)
{
if (g_player_opus_decoders[consoleplayer] == NULL && !netgame)
{
RecreatePlayerOpusDecoder(consoleplayer);
}
result = opus_decode_float(g_player_opus_decoders[consoleplayer], encoded, result, g_local_voice_buffer, SRB2_VOICE_OPUS_FRAME_SIZE, 0);
S_QueueVoiceFrameFromPlayer(consoleplayer, g_local_voice_buffer, result * sizeof(float), false);
}

View file

@ -28,6 +28,9 @@ menuitem_t OPTIONS_Voice[] =
{IT_STRING | IT_CVAR, "Input Amplifier", "Amplify your voice, in decibels. Negative values are quieter.",
NULL, {.cvar = &cv_voice_inputamp}, 0, 0},
{IT_STRING | IT_CVAR, "Input Noise Suppression", "Suppress background noise from your voice.",
NULL, {.cvar = &cv_voice_denoise}, 0, 0},
{IT_STRING | IT_CVAR, "Input Sensitivity", "Voice higher than this threshold will transmit, in decibels.",
NULL, {.cvar = &cv_voice_activationthreshold}, 0, 0},

View file

@ -52,6 +52,7 @@ extern consvar_t cv_voice_selfdeafen;
extern consvar_t cv_voice_mode;
extern consvar_t cv_voice_selfmute;
extern consvar_t cv_voice_loopback;
extern consvar_t cv_voice_denoise;
extern consvar_t cv_voice_inputamp;
extern consvar_t cv_voice_activationthreshold;
extern consvar_t cv_voice_proximity;

View file

@ -19,3 +19,5 @@ add_subdirectory(fmt)
add_subdirectory(vulkan-headers)
add_subdirectory(volk)
add_subdirectory(vma)
add_subdirectory(renamenoise)

1
thirdparty/renamenoise/AUTHORS vendored Normal file
View file

@ -0,0 +1 @@
Jean-Marc Valin <jmvalin@jmvalin.ca>

17
thirdparty/renamenoise/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,17 @@
# Update from https://github.com/mumble-voip/ReNameNoise
# ReNameNoise unversioned
# License: BSD-3
add_library(renamenoise STATIC)
target_sources(renamenoise PRIVATE
"src/rnn_data.c"
"src/rnn.c"
"src/pitch.c"
"src/renamenoise_fft.c"
"src/denoise.c"
"src/renamenoise_lpc.c"
)
target_include_directories(renamenoise PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_compile_definitions(renamenoise PRIVATE "RENAMENOISE_BUILD")
target_compile_definitions(renamenoise PRIVATE "ENABLE_ASSERTIONS")
add_library(ReNameNoise::renamenoise ALIAS renamenoise)

32
thirdparty/renamenoise/COPYING vendored Normal file
View file

@ -0,0 +1,32 @@
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2017, Mozilla
Copyright (c) 2007-2017, Jean-Marc Valin
Copyright (c) 2005-2017, Xiph.Org Foundation
Copyright (c) 2003-2004, Mark Borgerding
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the Xiph.Org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

67
thirdparty/renamenoise/README.md vendored Normal file
View file

@ -0,0 +1,67 @@
# ReNameNoise
ReNameNoise - a fork of [RNNoise](https://gitlab.xiph.org/xiph/rnnoise) - is a noise suppression library based on a recurrent neural network.
A description of the algorithm is provided in the following paper:
```
J.-M. Valin, A Hybrid DSP/Deep Learning Approach to Real-Time Full-Band Speech
Enhancement, Proceedings of IEEE Multimedia Signal Processing (MMSP) Workshop,
arXiv:1709.08243, 2018.
https://arxiv.org/pdf/1709.08243.pdf
```
An interactive demo is available at: https://jmvalin.ca/demo/rnnoise/
## Prerequisites
To build the library with the existing, pre-trained network data you will need to install the following packages:
* build-essential
* cmake
## Build
To compile, open a terminal in the repository root directory and type:
```bash
cmake .
make
```
To compile the library only, without the demo executable:
```bash
cmake -DRENAMENOISE_DEMO_EXECUTABLE=OFF .
make
```
## Usage
While it is meant to be used as a library, a simple command-line tool is
provided as an example. It operates on RAW 16-bit (machine endian) mono
PCM files sampled at 48 kHz. It can be used as:
``./examples/renamenoise_demo <noisy speech> <output denoised>``
The output is also a 16-bit raw PCM file.d
## Training
Training is not necessary to use the library as presented in this repository.
However, if you want to train the network on your own samples you need to follow these steps:
```bash
cd src ; ./compile.sh
./denoise_training signal.raw noise.raw count > training.f32
# (note the matrix size and replace 500000 87 below)
cd training ; ./bin2hdf5.py ../src/training.f32 500000 87 training.h5
./rnn_train.py
./dump_rnn.py weights.hdf5 ../src/rnn_data.c ../src/rnn_data.h
```

View file

@ -0,0 +1,125 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2018, Gregor Richards
Copyright (c) 2017, Mozilla
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RENAMENOISE_H
#define RENAMENOISE_H
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef RENAMENOISE_EXPORT
# if defined(WIN32)
# if defined(RENAMENOISE_BUILD) && defined(DLL_EXPORT)
# define RENAMENOISE_EXPORT __declspec(dllexport)
# else
# define RENAMENOISE_EXPORT
# endif
# elif defined(__GNUC__) && defined(RENAMENOISE_BUILD)
# define RENAMENOISE_EXPORT __attribute__((visibility("default")))
# else
# define RENAMENOISE_EXPORT
# endif
#endif
typedef struct ReNameNoiseDenoiseState ReNameNoiseDenoiseState;
typedef struct ReNameNoiseModel ReNameNoiseModel;
/**
* Return the size of ReNameNoiseDenoiseState
*/
RENAMENOISE_EXPORT int renamenoise_get_size(void);
/**
* Return the number of samples processed by renamenoise_process_frame at a time
*/
RENAMENOISE_EXPORT int renamenoise_get_frame_size(void);
/**
* Initializes a pre-allocated ReNameNoiseDenoiseState
*
* If model is NULL the default model is used.
*
* See: renamenoise_create() and renamenoise_model_from_file()
*/
RENAMENOISE_EXPORT int renamenoise_init(ReNameNoiseDenoiseState *st, ReNameNoiseModel *model);
/**
* Allocate and initialize a ReNameNoiseDenoiseState
*
* If model is NULL the default model is used.
*
* The returned pointer MUST be freed with renamenoise_destroy().
*/
RENAMENOISE_EXPORT ReNameNoiseDenoiseState *renamenoise_create(ReNameNoiseModel *model);
/**
* Free a ReNameNoiseDenoiseState produced by renamenoise_create.
*
* The optional custom model must be freed by renamenoise_model_free() after.
*/
RENAMENOISE_EXPORT void renamenoise_destroy(ReNameNoiseDenoiseState *st);
/**
* Denoise a frame of samples
*
* in and out must be at least renamenoise_get_frame_size() large.
*/
RENAMENOISE_EXPORT float renamenoise_process_frame(ReNameNoiseDenoiseState *st, float *out, const float *in);
/**
* Denoise a frame of samples, but clamp the output to fit into a 16 bit signed short
*
* in and out must be at least renamenoise_get_frame_size() large.
*/
RENAMENOISE_EXPORT float renamenoise_process_frame_clamped(ReNameNoiseDenoiseState *st, short *out, const float *in);
/**
* Load a model from a file
*
* It must be deallocated with renamenoise_model_free()
*/
RENAMENOISE_EXPORT ReNameNoiseModel *renamenoise_model_from_file(FILE *f);
/**
* Free a custom model
*
* It must be called after all the ReNameNoiseDenoiseStates referring to it are freed.
*/
RENAMENOISE_EXPORT void renamenoise_model_free(ReNameNoiseModel *model);
#ifdef __cplusplus
}
#endif
#endif /* RENAMENOISE_H */

View file

@ -0,0 +1,111 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2003-2004, Mark Borgerding
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RENAMENOISE_FFT_GUTS_H
#define RENAMENOISE_FFT_GUTS_H
/**
renamenoise_fft.h
Defines renamenoise_fft_scalar as either short or a float type
and defines
typedef struct {
renamenoise_fft_scalar r;
renamenoise_fft_scalar i;
} renamenoise_fft_cpx;
**/
#include "renamenoise_fft.h"
/*
Explanation of macros dealing with complex math:
C_MUL(m,a,b) : m = a*b
C_SUB( res, a,b) : res = a - b
C_SUBFROM( res , a) : res -= a
C_ADDTO( res , a) : res += a
*/
#define RENAMENOISE_S_MUL(a, b) ((a) * (b))
#define RENAMENOISE_C_MUL(m, a, b) \
do { \
(m).r = (a).r * (b).r - (a).i * (b).i; \
(m).i = (a).r * (b).i + (a).i * (b).r; \
} while (0)
#define RENAMENOISE_C_MULC(m, a, b) \
do { \
(m).r = (a).r * (b).r + (a).i * (b).i; \
(m).i = (a).i * (b).r - (a).r * (b).i; \
} while (0)
#define RENAMENOISE_C_MUL4(m, a, b) RENAMENOISE_C_MUL(m, a, b)
#define RENAMENOISE_C_MULBYSCALAR(c, s) \
do { \
(c).r *= (s); \
(c).i *= (s); \
} while (0)
#ifndef RENAMENOISE_C_ADD
# define RENAMENOISE_C_ADD(res, a, b) \
do { \
(res).r = (a).r + (b).r; \
(res).i = (a).i + (b).i; \
} while (0)
# define RENAMENOISE_C_SUB(res, a, b) \
do { \
(res).r = (a).r - (b).r; \
(res).i = (a).i - (b).i; \
} while (0)
# define RENAMENOISE_C_ADDTO(res, a) \
do { \
(res).r += (a).r; \
(res).i += (a).i; \
} while (0)
# define RENAMENOISE_C_SUBFROM(res, a) \
do { \
(res).r -= (a).r; \
(res).i -= (a).i; \
} while (0)
#endif /* !RENAMENOISE_C_ADD defined */
#define RENAMENOISE_FFT_COS(phase) (renamenoise_fft_scalar) cos(phase)
#define RENAMENOISE_FFT_SIN(phase) (renamenoise_fft_scalar) sin(phase)
#define renamenoise_kf_cexp(x, phase) \
do { \
(x)->r = RENAMENOISE_FFT_COS(phase); \
(x)->i = RENAMENOISE_FFT_SIN(phase); \
} while (0)
#endif /* RENAMENOISE_FFT_GUTS_H */

165
thirdparty/renamenoise/src/arch.h vendored Normal file
View file

@ -0,0 +1,165 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2007-2009, Xiph.Org Foundation
Copyright (c) 2007-2008, CSIRO
Copyright (c) 2003-2008, Jean-Marc Valin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
@file arch.h
@brief Various architecture definitions for ReNameNoise
*/
#ifndef ARCH_H
#define ARCH_H
#include "common.h"
#include "renamenoise_types.h"
#if !defined(__GNUC_PREREQ)
# if defined(__GNUC__) && defined(__GNUC_MINOR__)
# define __GNUC_PREREQ(_maj, _min) ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((_maj) << 16) + (_min))
# else
# define __GNUC_PREREQ(_maj, _min) 0
# endif
#endif
#ifndef M_PI
# define M_PI (3.14159265358979323846)
#endif
#define renamenoise_fatal(str) _renamenoise_fatal(str, __FILE__, __LINE__);
#ifdef ENABLE_ASSERTIONS
# include <stdio.h>
# include <stdlib.h>
# ifdef __GNUC__
__attribute__((noreturn))
# endif
static RENAMENOISE_INLINE void
_renamenoise_fatal(const char *str, const char *file, int line) {
fprintf(stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
abort();
}
# define renamenoise_assert(cond) \
{ \
if (!(cond)) { \
renamenoise_fatal("assertion failed: " #cond); \
} \
}
# define renamenoise_assert2(cond, message) \
{ \
if (!(cond)) { \
renamenoise_fatal("assertion failed: " #cond "\n" message); \
} \
}
#else
# define renamenoise_assert(cond)
# define renamenoise_assert2(cond, message)
#endif /* !ENABLE_ASSERTIONS defined */
#define RENAMENOISE_MIN16(a, b) ((a) < (b) ? (a) : (b))
#define RENAMENOISE_MAX16(a, b) ((a) > (b) ? (a) : (b))
#define RENAMENOISE_MIN32(a, b) ((a) < (b) ? (a) : (b))
#define RENAMENOISE_MAX32(a, b) ((a) > (b) ? (a) : (b))
typedef float renamenoise_val16;
typedef float renamenoise_val32;
typedef float renamenoise_sig;
#ifdef RENAMENOISE_FLOAT_APPROX
// This code should reliably detect NaN/inf even when -ffast-math is used.
// Assumes IEEE 754 format.
static RENAMENOISE_INLINE int renamenoise_isnan(float x) {
union {
float f;
renamenoise_uint32 i;
} in;
in.f = x;
return ((in.i >> 23) & 0xFF) == 0xFF && (in.i & 0x007FFFFF) != 0;
}
#else
# ifdef __FAST_MATH__
# error Cannot build renamenoise with -ffast-math unless RENAMENOISE_FLOAT_APPROX is defined. This could result in crashes on extreme (e.g. NaN) input
# endif
# define renamenoise_isnan(x) ((x) != (x))
#endif
#define RENAMENOISE_Q15ONE 1.0f
#define RENAMENOISE_EPSILON 1e-15f
#define RENAMENOISE_VERY_SMALL 1e-30f
#define RENAMENOISE_VERY_LARGE16 1e15f
#define RENAMENOISE_HALF(x) (.5f * (x))
#define RENAMENOISE_ADD(a, b) ((a) + (b))
#define RENAMENOISE_SUB(a, b) ((a) - (b))
#define RENAMENOISE_MAC(c, a, b) ((c) + (renamenoise_val32) (a) * (renamenoise_val32) (b))
#define RENAMENOISE_MULT(a, b) ((a) * (b))
#if __STDC_VERSION__ < 199901L || (__STDC_VERSION__ > 201000L && __STDC_NO_VLA__ == 1)
# define RENAMENOISE_NO_VLA
#endif
#ifdef RENAMENOISE_NO_VLA
# include <malloc.h>
# define renamenoise_stackalloc(type, id, len) type *id = alloca((len) * sizeof(type))
#else
# define renamenoise_stackalloc(type, id, len) type id[len]
#endif
// Portable macros for denoting unreachable code.
// In such a scenario, perform an early exit ('panic')
#if _MSC_VER // MSVC
# define renamenoise_unreachable() __assume(0)
#elif __GNUC__ || __clang__ || __MINGW32__
# define renamenoise_unreachable() __builtin_unreachable()
// #elif __BORLANDC__
// #define renamenoise_unreachable() __builtin_unreachable() // unknown. needs investigation
#else
# define renamenoise_unreachable()
#endif
#endif /* ARCH_H */

54
thirdparty/renamenoise/src/common.h vendored Normal file
View file

@ -0,0 +1,54 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2017, Jean-Marc Valin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef COMMON_H
#define COMMON_H
#include "stdlib.h"
#include "string.h"
#define RENAMENOISE_INLINE inline
/** Copy n elements from src to dst. The 0* term provides compile-time type checking */
#ifndef OVERRIDE_RENAMENOISE_COPY
# define RENAMENOISE_COPY(dst, src, n) (memcpy((dst), (src), (n) * sizeof(*(dst)) + 0 * ((dst) - (src))))
#endif
/** Copy n elements from src to dst, allowing overlapping regions. The 0* term provides compile-time type checking */
#ifndef OVERRIDE_RENAMENOISE_MOVE
# define RENAMENOISE_MOVE(dst, src, n) (memmove((dst), (src), (n) * sizeof(*(dst)) + 0 * ((dst) - (src))))
#endif
/** Set n elements of dst to zero */
#ifndef OVERRIDE_RENAMENOISE_CLEAR
# define RENAMENOISE_CLEAR(dst, n) (memset((dst), 0, (n) * sizeof(*(dst))))
#endif
#endif /* COMMON_H */

3
thirdparty/renamenoise/src/compile.sh vendored Executable file
View file

@ -0,0 +1,3 @@
#!/bin/sh
gcc -DRENAMENOISE_TRAINING=1 -Wall -W -O3 -g -I../include denoise.c renamenoise_fft.c pitch.c renamenoise_lpc.c rnn.c rnn_data.c -o denoise_training -lm

692
thirdparty/renamenoise/src/denoise.c vendored Normal file
View file

@ -0,0 +1,692 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2018, Gregor Richards
Copyright (c) 2017, Mozilla
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "arch.h"
#include "common.h"
#include "pitch.h"
#include "renamenoise.h"
#include "renamenoise_fft.h"
#include "rnn.h"
#include "rnn_data.h"
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define RENAMENOISE_FRAME_SIZE_SHIFT 2
#define RENAMENOISE_FRAME_SIZE (120 << RENAMENOISE_FRAME_SIZE_SHIFT)
#define RENAMENOISE_WINDOW_SIZE (2 * RENAMENOISE_FRAME_SIZE)
#define RENAMENOISE_FREQ_SIZE (RENAMENOISE_FRAME_SIZE + 1)
#define RENAMENOISE_PITCH_MIN_PERIOD 60
#define RENAMENOISE_PITCH_MAX_PERIOD 768
#define RENAMENOISE_PITCH_FRAME_SIZE 960
#define RENAMENOISE_PITCH_BUF_SIZE (RENAMENOISE_PITCH_MAX_PERIOD + RENAMENOISE_PITCH_FRAME_SIZE)
#define RENAMENOISE_SQUARE(x) ((x) * (x))
#define RENAMENOISE_NB_BANDS 22
#define RENAMENOISE_CEPS_MEM 8
#define RENAMENOISE_NB_DELTA_CEPS 6
#define RENAMENOISE_NB_FEATURES (RENAMENOISE_NB_BANDS + 3 * RENAMENOISE_NB_DELTA_CEPS + 2)
#ifndef RENAMENOISE_TRAINING
# define RENAMENOISE_TRAINING 0
#endif
/* The built-in model, used if no file is given as input */
extern const struct ReNameNoiseModel renamenoise_model_orig;
static const renamenoise_int16 renamenoise_eband5ms[] = {
// 0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12,
// 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 20k
14, 16, 20, 24, 28, 34, 40, 48, 60, 78, 100};
typedef struct {
int init;
renamenoise_fft_state *kfft;
float half_window[RENAMENOISE_FRAME_SIZE];
float dct_table[RENAMENOISE_NB_BANDS * RENAMENOISE_NB_BANDS];
} ReNameNoiseCommonState;
struct ReNameNoiseDenoiseState {
float analysis_mem[RENAMENOISE_FRAME_SIZE];
float cepstral_mem[RENAMENOISE_CEPS_MEM][RENAMENOISE_NB_BANDS];
int memid;
float synthesis_mem[RENAMENOISE_FRAME_SIZE];
float pitch_buf[RENAMENOISE_PITCH_BUF_SIZE];
float pitch_enh_buf[RENAMENOISE_PITCH_BUF_SIZE];
float last_gain;
int last_period;
float mem_hp_x[2];
float lastg[RENAMENOISE_NB_BANDS];
ReNameNoiseRNNState rnn;
};
void renamenoise_compute_band_energy(float *bandE, const renamenoise_fft_cpx *X) {
int i;
float sum[RENAMENOISE_NB_BANDS] = {0};
for (i = 0; i < RENAMENOISE_NB_BANDS - 1; i++) {
int j;
int band_size;
band_size = (renamenoise_eband5ms[i + 1] - renamenoise_eband5ms[i]) << RENAMENOISE_FRAME_SIZE_SHIFT;
for (j = 0; j < band_size; j++) {
float tmp;
float frac = (float) j / band_size;
tmp = RENAMENOISE_SQUARE(X[(renamenoise_eband5ms[i] << RENAMENOISE_FRAME_SIZE_SHIFT) + j].r);
tmp += RENAMENOISE_SQUARE(X[(renamenoise_eband5ms[i] << RENAMENOISE_FRAME_SIZE_SHIFT) + j].i);
sum[i] = sum[i] + (1 - frac) * tmp;
sum[i + 1] = sum[i + 1] + frac * tmp;
}
}
sum[0] *= 2;
sum[RENAMENOISE_NB_BANDS - 1] *= 2;
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
bandE[i] = sum[i];
}
}
void renamenoise_compute_band_corr(float *bandE, const renamenoise_fft_cpx *X, const renamenoise_fft_cpx *P) {
int i;
float sum[RENAMENOISE_NB_BANDS] = {0};
for (i = 0; i < RENAMENOISE_NB_BANDS - 1; i++) {
int j;
int band_size;
band_size = (renamenoise_eband5ms[i + 1] - renamenoise_eband5ms[i]) << RENAMENOISE_FRAME_SIZE_SHIFT;
for (j = 0; j < band_size; j++) {
float tmp;
float frac = (float) j / band_size;
tmp = X[(renamenoise_eband5ms[i] << RENAMENOISE_FRAME_SIZE_SHIFT) + j].r
* P[(renamenoise_eband5ms[i] << RENAMENOISE_FRAME_SIZE_SHIFT) + j].r;
tmp += X[(renamenoise_eband5ms[i] << RENAMENOISE_FRAME_SIZE_SHIFT) + j].i
* P[(renamenoise_eband5ms[i] << RENAMENOISE_FRAME_SIZE_SHIFT) + j].i;
sum[i] += (1 - frac) * tmp;
sum[i + 1] += frac * tmp;
}
}
sum[0] *= 2;
sum[RENAMENOISE_NB_BANDS - 1] *= 2;
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
bandE[i] = sum[i];
}
}
void renamenoise_interp_band_gain(float *g, const float *bandE) {
int i;
memset(g, 0, RENAMENOISE_FREQ_SIZE);
for (i = 0; i < RENAMENOISE_NB_BANDS - 1; i++) {
int j;
int band_size;
band_size = (renamenoise_eband5ms[i + 1] - renamenoise_eband5ms[i]) << RENAMENOISE_FRAME_SIZE_SHIFT;
for (j = 0; j < band_size; j++) {
float frac = (float) j / band_size;
g[(renamenoise_eband5ms[i] << RENAMENOISE_FRAME_SIZE_SHIFT) + j] = (1 - frac) * bandE[i] + frac * bandE[i + 1];
}
}
}
ReNameNoiseCommonState renamenoise_common;
static void renamenoise_check_init(void) {
int i;
if (renamenoise_common.init) {
return;
}
renamenoise_common.kfft = renamenoise_fft_alloc_twiddles(2 * RENAMENOISE_FRAME_SIZE, NULL, NULL, NULL, 0);
for (i = 0; i < RENAMENOISE_FRAME_SIZE; i++) {
renamenoise_common.half_window[i] =
sin(.5 * M_PI * sin(.5 * M_PI * (i + .5) / RENAMENOISE_FRAME_SIZE) * sin(.5 * M_PI * (i + .5) / RENAMENOISE_FRAME_SIZE));
}
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
int j;
for (j = 0; j < RENAMENOISE_NB_BANDS; j++) {
renamenoise_common.dct_table[i * RENAMENOISE_NB_BANDS + j] = cos((i + .5) * j * M_PI / RENAMENOISE_NB_BANDS);
if (j == 0) {
renamenoise_common.dct_table[i * RENAMENOISE_NB_BANDS + j] *= sqrt(.5);
}
}
}
renamenoise_common.init = 1;
}
static void renamenoise_dct(float *out, const float *in) {
int i;
renamenoise_check_init();
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
int j;
float sum = 0;
for (j = 0; j < RENAMENOISE_NB_BANDS; j++) {
sum += in[j] * renamenoise_common.dct_table[j * RENAMENOISE_NB_BANDS + i];
}
out[i] = sum * sqrt(2. / 22);
}
}
static void renamenoise_forward_transform(renamenoise_fft_cpx *out, const float *in) {
int i;
renamenoise_fft_cpx x[RENAMENOISE_WINDOW_SIZE];
renamenoise_fft_cpx y[RENAMENOISE_WINDOW_SIZE];
renamenoise_check_init();
for (i = 0; i < RENAMENOISE_WINDOW_SIZE; i++) {
x[i].r = in[i];
x[i].i = 0;
}
renamenoise_fft(renamenoise_common.kfft, x, y, 0);
for (i = 0; i < RENAMENOISE_FREQ_SIZE; i++) {
out[i] = y[i];
}
}
static void renamenoise_inverse_transform(float *out, const renamenoise_fft_cpx *in) {
int i;
renamenoise_fft_cpx x[RENAMENOISE_WINDOW_SIZE];
renamenoise_fft_cpx y[RENAMENOISE_WINDOW_SIZE];
renamenoise_check_init();
for (i = 0; i < RENAMENOISE_FREQ_SIZE; i++) {
x[i] = in[i];
}
for (; i < RENAMENOISE_WINDOW_SIZE; i++) {
x[i].r = x[RENAMENOISE_WINDOW_SIZE - i].r;
x[i].i = -x[RENAMENOISE_WINDOW_SIZE - i].i;
}
renamenoise_fft(renamenoise_common.kfft, x, y, 0);
// output in reverse order for IFFT.
out[0] = RENAMENOISE_WINDOW_SIZE * y[0].r;
for (i = 1; i < RENAMENOISE_WINDOW_SIZE; i++) {
out[i] = RENAMENOISE_WINDOW_SIZE * y[RENAMENOISE_WINDOW_SIZE - i].r;
}
}
static void renamenoise_apply_window(float *x) {
int i;
renamenoise_check_init();
for (i = 0; i < RENAMENOISE_FRAME_SIZE; i++) {
x[i] *= renamenoise_common.half_window[i];
x[RENAMENOISE_WINDOW_SIZE - 1 - i] *= renamenoise_common.half_window[i];
}
}
int renamenoise_get_size(void) {
return sizeof(ReNameNoiseDenoiseState);
}
int renamenoise_get_frame_size(void) {
return RENAMENOISE_FRAME_SIZE;
}
int renamenoise_init(ReNameNoiseDenoiseState *st, ReNameNoiseModel *model) {
memset(st, 0, sizeof(*st));
if (model) {
st->rnn.model = model;
} else {
st->rnn.model = &renamenoise_model_orig;
}
st->rnn.vad_gru_state = calloc(sizeof(float), st->rnn.model->vad_gru_size);
st->rnn.noise_gru_state = calloc(sizeof(float), st->rnn.model->noise_gru_size);
st->rnn.denoise_gru_state = calloc(sizeof(float), st->rnn.model->denoise_gru_size);
return 0;
}
ReNameNoiseDenoiseState *renamenoise_create(ReNameNoiseModel *model) {
ReNameNoiseDenoiseState *st;
st = malloc(renamenoise_get_size());
renamenoise_init(st, model);
return st;
}
void renamenoise_destroy(ReNameNoiseDenoiseState *st) {
free(st->rnn.vad_gru_state);
free(st->rnn.noise_gru_state);
free(st->rnn.denoise_gru_state);
free(st);
}
#if RENAMENOISE_TRAINING
int lowpass = RENAMENOISE_FREQ_SIZE;
int band_lp = RENAMENOISE_NB_BANDS;
#endif
static void renamenoise_frame_analysis(ReNameNoiseDenoiseState *st, renamenoise_fft_cpx *X, float *Ex, const float *in) {
int i;
float x[RENAMENOISE_WINDOW_SIZE];
RENAMENOISE_COPY(x, st->analysis_mem, RENAMENOISE_FRAME_SIZE);
for (i = 0; i < RENAMENOISE_FRAME_SIZE; i++) {
x[RENAMENOISE_FRAME_SIZE + i] = in[i];
}
RENAMENOISE_COPY(st->analysis_mem, in, RENAMENOISE_FRAME_SIZE);
renamenoise_apply_window(x);
renamenoise_forward_transform(X, x);
#if RENAMENOISE_TRAINING
for (i = lowpass; i < RENAMENOISE_FREQ_SIZE; i++) {
X[i].r = X[i].i = 0;
}
#endif
renamenoise_compute_band_energy(Ex, X);
}
static int renamenoise_compute_frame_features(ReNameNoiseDenoiseState *st, renamenoise_fft_cpx *X, renamenoise_fft_cpx *P, float *Ex, float *Ep,
float *Exp, float *features, const float *in) {
int i;
float E = 0;
float *ceps_0, *ceps_1, *ceps_2;
float spec_variability = 0;
float Ly[RENAMENOISE_NB_BANDS];
float p[RENAMENOISE_WINDOW_SIZE];
float pitch_buf[RENAMENOISE_PITCH_BUF_SIZE >> 1];
int pitch_index;
float gain;
float *(pre[1]);
float tmp[RENAMENOISE_NB_BANDS];
float follow, logMax;
renamenoise_frame_analysis(st, X, Ex, in);
RENAMENOISE_MOVE(st->pitch_buf, &st->pitch_buf[RENAMENOISE_FRAME_SIZE], RENAMENOISE_PITCH_BUF_SIZE - RENAMENOISE_FRAME_SIZE);
RENAMENOISE_COPY(&st->pitch_buf[RENAMENOISE_PITCH_BUF_SIZE - RENAMENOISE_FRAME_SIZE], in, RENAMENOISE_FRAME_SIZE);
pre[0] = &st->pitch_buf[0];
renamenoise_pitch_downsample(pre, pitch_buf, RENAMENOISE_PITCH_BUF_SIZE, 1);
renamenoise_pitch_search(pitch_buf + (RENAMENOISE_PITCH_MAX_PERIOD >> 1), pitch_buf, RENAMENOISE_PITCH_FRAME_SIZE,
RENAMENOISE_PITCH_MAX_PERIOD - 3 * RENAMENOISE_PITCH_MIN_PERIOD, &pitch_index);
pitch_index = RENAMENOISE_PITCH_MAX_PERIOD - pitch_index;
gain = renamenoise_remove_doubling(pitch_buf, RENAMENOISE_PITCH_MAX_PERIOD, RENAMENOISE_PITCH_MIN_PERIOD, RENAMENOISE_PITCH_FRAME_SIZE,
&pitch_index, st->last_period, st->last_gain);
st->last_period = pitch_index;
st->last_gain = gain;
for (i = 0; i < RENAMENOISE_WINDOW_SIZE; i++) {
p[i] = st->pitch_buf[RENAMENOISE_PITCH_BUF_SIZE - RENAMENOISE_WINDOW_SIZE - pitch_index + i];
}
renamenoise_apply_window(p);
renamenoise_forward_transform(P, p);
renamenoise_compute_band_energy(Ep, P);
renamenoise_compute_band_corr(Exp, X, P);
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
Exp[i] = Exp[i] / sqrt(.001 + Ex[i] * Ep[i]);
}
renamenoise_dct(tmp, Exp);
for (i = 0; i < RENAMENOISE_NB_DELTA_CEPS; i++) {
features[RENAMENOISE_NB_BANDS + 2 * RENAMENOISE_NB_DELTA_CEPS + i] = tmp[i];
}
features[RENAMENOISE_NB_BANDS + 2 * RENAMENOISE_NB_DELTA_CEPS] -= 1.3;
features[RENAMENOISE_NB_BANDS + 2 * RENAMENOISE_NB_DELTA_CEPS + 1] -= 0.9;
features[RENAMENOISE_NB_BANDS + 3 * RENAMENOISE_NB_DELTA_CEPS] = .01 * (pitch_index - 300);
logMax = -2;
follow = -2;
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
Ly[i] = log10(1e-2 + Ex[i]);
Ly[i] = RENAMENOISE_MAX16(logMax - 7, RENAMENOISE_MAX16(follow - 1.5, Ly[i]));
logMax = RENAMENOISE_MAX16(logMax, Ly[i]);
follow = RENAMENOISE_MAX16(follow - 1.5, Ly[i]);
E += Ex[i];
}
if (!RENAMENOISE_TRAINING && E < 0.04) {
// If there's no audio, avoid messing up the state.
RENAMENOISE_CLEAR(features, RENAMENOISE_NB_FEATURES);
return 1;
}
renamenoise_dct(features, Ly);
features[0] -= 12;
features[1] -= 4;
ceps_0 = st->cepstral_mem[st->memid];
ceps_1 = (st->memid < 1) ? st->cepstral_mem[RENAMENOISE_CEPS_MEM + st->memid - 1] : st->cepstral_mem[st->memid - 1];
ceps_2 = (st->memid < 2) ? st->cepstral_mem[RENAMENOISE_CEPS_MEM + st->memid - 2] : st->cepstral_mem[st->memid - 2];
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
ceps_0[i] = features[i];
}
st->memid++;
for (i = 0; i < RENAMENOISE_NB_DELTA_CEPS; i++) {
features[i] = ceps_0[i] + ceps_1[i] + ceps_2[i];
features[RENAMENOISE_NB_BANDS + i] = ceps_0[i] - ceps_2[i];
features[RENAMENOISE_NB_BANDS + RENAMENOISE_NB_DELTA_CEPS + i] = ceps_0[i] - 2 * ceps_1[i] + ceps_2[i];
}
// Spectral variability features.
if (st->memid == RENAMENOISE_CEPS_MEM) {
st->memid = 0;
}
for (i = 0; i < RENAMENOISE_CEPS_MEM; i++) {
int j;
float mindist = 1e15f;
for (j = 0; j < RENAMENOISE_CEPS_MEM; j++) {
int k;
float dist = 0;
for (k = 0; k < RENAMENOISE_NB_BANDS; k++) {
float tmp;
tmp = st->cepstral_mem[i][k] - st->cepstral_mem[j][k];
dist += tmp * tmp;
}
if (j != i) {
mindist = RENAMENOISE_MIN32(mindist, dist);
}
}
spec_variability += mindist;
}
features[RENAMENOISE_NB_BANDS + 3 * RENAMENOISE_NB_DELTA_CEPS + 1] = spec_variability / RENAMENOISE_CEPS_MEM - 2.1;
return RENAMENOISE_TRAINING && E < 0.1;
}
static void renamenoise_frame_synthesis(ReNameNoiseDenoiseState *st, float *out, const renamenoise_fft_cpx *y) {
float x[RENAMENOISE_WINDOW_SIZE];
int i;
renamenoise_inverse_transform(x, y);
renamenoise_apply_window(x);
for (i = 0; i < RENAMENOISE_FRAME_SIZE; i++) {
out[i] = x[i] + st->synthesis_mem[i];
}
RENAMENOISE_COPY(st->synthesis_mem, &x[RENAMENOISE_FRAME_SIZE], RENAMENOISE_FRAME_SIZE);
}
static void renamenoise_biquad(float *y, float mem[2], const float *x, const float *b, const float *a, int N) {
int i;
for (i = 0; i < N; i++) {
float xi, yi;
xi = x[i];
yi = x[i] + mem[0];
mem[0] = mem[1] + (b[0] * (double) xi - a[0] * (double) yi);
mem[1] = (b[1] * (double) xi - a[1] * (double) yi);
y[i] = yi;
}
}
void renamenoise_pitch_filter(renamenoise_fft_cpx *X, const renamenoise_fft_cpx *P, const float *Ex, const float *Ep, const float *Exp,
const float *g) {
int i;
float r[RENAMENOISE_NB_BANDS];
float rf[RENAMENOISE_FREQ_SIZE] = {0};
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
if (Exp[i] > g[i]) {
r[i] = 1;
} else {
r[i] = RENAMENOISE_SQUARE(Exp[i]) * (1 - RENAMENOISE_SQUARE(g[i])) / (.001 + RENAMENOISE_SQUARE(g[i]) * (1 - RENAMENOISE_SQUARE(Exp[i])));
}
r[i] = sqrt(RENAMENOISE_MIN16(1, RENAMENOISE_MAX16(0, r[i])));
r[i] *= sqrt(Ex[i] / (1e-8 + Ep[i]));
}
renamenoise_interp_band_gain(rf, r);
for (i = 0; i < RENAMENOISE_FREQ_SIZE; i++) {
X[i].r += rf[i] * P[i].r;
X[i].i += rf[i] * P[i].i;
}
float newE[RENAMENOISE_NB_BANDS];
renamenoise_compute_band_energy(newE, X);
float norm[RENAMENOISE_NB_BANDS];
float normf[RENAMENOISE_FREQ_SIZE] = {0};
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
norm[i] = sqrt(Ex[i] / (1e-8 + newE[i]));
}
renamenoise_interp_band_gain(normf, norm);
for (i = 0; i < RENAMENOISE_FREQ_SIZE; i++) {
X[i].r *= normf[i];
X[i].i *= normf[i];
}
}
float renamenoise_process_frame(ReNameNoiseDenoiseState *st, float *out, const float *in) {
int i;
renamenoise_fft_cpx X[RENAMENOISE_FREQ_SIZE];
renamenoise_fft_cpx P[RENAMENOISE_WINDOW_SIZE];
float x[RENAMENOISE_FRAME_SIZE];
float Ex[RENAMENOISE_NB_BANDS], Ep[RENAMENOISE_NB_BANDS];
float Exp[RENAMENOISE_NB_BANDS];
float features[RENAMENOISE_NB_FEATURES];
float g[RENAMENOISE_NB_BANDS];
float gf[RENAMENOISE_FREQ_SIZE] = {1};
float vad_prob = 0;
int silence;
static const float a_hp[2] = {-1.99599, 0.99600};
static const float b_hp[2] = {-2, 1};
renamenoise_biquad(x, st->mem_hp_x, in, b_hp, a_hp, RENAMENOISE_FRAME_SIZE);
silence = renamenoise_compute_frame_features(st, X, P, Ex, Ep, Exp, features, x);
if (!silence) {
renamenoise_compute_rnn(&st->rnn, g, &vad_prob, features);
renamenoise_pitch_filter(X, P, Ex, Ep, Exp, g);
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
float alpha = .6f;
g[i] = RENAMENOISE_MAX16(g[i], alpha * st->lastg[i]);
st->lastg[i] = g[i];
}
renamenoise_interp_band_gain(gf, g);
for (i = 0; i < RENAMENOISE_FREQ_SIZE; i++) {
X[i].r *= gf[i];
X[i].i *= gf[i];
}
}
renamenoise_frame_synthesis(st, out, X);
return vad_prob;
}
float renamenoise_process_frame_clamped(ReNameNoiseDenoiseState *st, short *out, const float *in) {
float denoise_frames[RENAMENOISE_FRAME_SIZE];
float vad_prob = renamenoise_process_frame(st, denoise_frames, in);
for (unsigned int i = 0; i < RENAMENOISE_FRAME_SIZE; i++) {
out[i] = (short) RENAMENOISE_MIN16(RENAMENOISE_MAX16(denoise_frames[i], SHRT_MIN), SHRT_MAX);
}
return vad_prob;
}
#if RENAMENOISE_TRAINING
static float renamenoise_uni_rand() {
return rand() / (double) RAND_MAX - .5;
}
static void renamenoise_rand_resp(float *a, float *b) {
a[0] = .75 * renamenoise_uni_rand();
a[1] = .75 * renamenoise_uni_rand();
b[0] = .75 * renamenoise_uni_rand();
b[1] = .75 * renamenoise_uni_rand();
}
int main(int argc, char **argv) {
int i;
int count = 0;
static const float a_hp[2] = {-1.99599, 0.99600};
static const float b_hp[2] = {-2, 1};
float a_noise[2] = {0};
float b_noise[2] = {0};
float a_sig[2] = {0};
float b_sig[2] = {0};
float mem_hp_x[2] = {0};
float mem_hp_n[2] = {0};
float mem_resp_x[2] = {0};
float mem_resp_n[2] = {0};
float x[RENAMENOISE_FRAME_SIZE];
float n[RENAMENOISE_FRAME_SIZE];
float xn[RENAMENOISE_FRAME_SIZE];
int vad_cnt = 0;
int gain_change_count = 0;
float speech_gain = 1, noise_gain = 1;
FILE *f1, *f2;
int maxCount;
ReNameNoiseDenoiseState *st;
ReNameNoiseDenoiseState *noise_state;
ReNameNoiseDenoiseState *noisy;
st = renamenoise_create(NULL);
noise_state = renamenoise_create(NULL);
noisy = renamenoise_create(NULL);
if (argc != 4) {
fprintf(stderr, "usage: %s <speech> <noise> <count>\n", argv[0]);
return 1;
}
f1 = fopen(argv[1], "r");
f2 = fopen(argv[2], "r");
maxCount = atoi(argv[3]);
for (i = 0; i < 150; i++) {
short tmp[RENAMENOISE_FRAME_SIZE];
fread(tmp, sizeof(short), RENAMENOISE_FRAME_SIZE, f2);
}
while (1) {
renamenoise_fft_cpx X[RENAMENOISE_FREQ_SIZE], Y[RENAMENOISE_FREQ_SIZE], N[RENAMENOISE_FREQ_SIZE], P[RENAMENOISE_WINDOW_SIZE];
float Ex[RENAMENOISE_NB_BANDS], Ey[RENAMENOISE_NB_BANDS], En[RENAMENOISE_NB_BANDS], Ep[RENAMENOISE_NB_BANDS];
float Exp[RENAMENOISE_NB_BANDS];
float Ln[RENAMENOISE_NB_BANDS];
float features[RENAMENOISE_NB_FEATURES];
float g[RENAMENOISE_NB_BANDS];
short tmp[RENAMENOISE_FRAME_SIZE];
float vad = 0;
float E = 0;
if (count == maxCount) {
break;
}
if ((count % 1000) == 0) {
fprintf(stderr, "%d\r", count);
}
if (++gain_change_count > 2821) {
speech_gain = pow(10., (-40 + (rand() % 60)) / 20.);
noise_gain = pow(10., (-30 + (rand() % 50)) / 20.);
if (rand() % 10 == 0) {
noise_gain = 0;
}
noise_gain *= speech_gain;
if (rand() % 10 == 0) {
speech_gain = 0;
}
gain_change_count = 0;
renamenoise_rand_resp(a_noise, b_noise);
renamenoise_rand_resp(a_sig, b_sig);
lowpass = RENAMENOISE_FREQ_SIZE * 3000. / 24000. * pow(50., rand() / (double) RAND_MAX);
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
if (renamenoise_eband5ms[i] << RENAMENOISE_FRAME_SIZE_SHIFT > lowpass) {
band_lp = i;
break;
}
}
}
if (speech_gain != 0) {
fread(tmp, sizeof(short), RENAMENOISE_FRAME_SIZE, f1);
if (feof(f1)) {
rewind(f1);
fread(tmp, sizeof(short), RENAMENOISE_FRAME_SIZE, f1);
}
for (i = 0; i < RENAMENOISE_FRAME_SIZE; i++) {
x[i] = speech_gain * tmp[i];
}
for (i = 0; i < RENAMENOISE_FRAME_SIZE; i++) {
E += tmp[i] * (float) tmp[i];
}
} else {
for (i = 0; i < RENAMENOISE_FRAME_SIZE; i++) {
x[i] = 0;
}
E = 0;
}
if (noise_gain != 0) {
fread(tmp, sizeof(short), RENAMENOISE_FRAME_SIZE, f2);
if (feof(f2)) {
rewind(f2);
fread(tmp, sizeof(short), RENAMENOISE_FRAME_SIZE, f2);
}
for (i = 0; i < RENAMENOISE_FRAME_SIZE; i++) {
n[i] = noise_gain * tmp[i];
}
} else {
for (i = 0; i < RENAMENOISE_FRAME_SIZE; i++) {
n[i] = 0;
}
}
renamenoise_biquad(x, mem_hp_x, x, b_hp, a_hp, RENAMENOISE_FRAME_SIZE);
renamenoise_biquad(x, mem_resp_x, x, b_sig, a_sig, RENAMENOISE_FRAME_SIZE);
renamenoise_biquad(n, mem_hp_n, n, b_hp, a_hp, RENAMENOISE_FRAME_SIZE);
renamenoise_biquad(n, mem_resp_n, n, b_noise, a_noise, RENAMENOISE_FRAME_SIZE);
for (i = 0; i < RENAMENOISE_FRAME_SIZE; i++) {
xn[i] = x[i] + n[i];
}
if (E > 1e9f) {
vad_cnt = 0;
} else if (E > 1e8f) {
vad_cnt -= 5;
} else if (E > 1e7f) {
vad_cnt++;
} else {
vad_cnt += 2;
}
if (vad_cnt < 0) {
vad_cnt = 0;
}
if (vad_cnt > 15) {
vad_cnt = 15;
}
if (vad_cnt >= 10) {
vad = 0;
} else if (vad_cnt > 0) {
vad = 0.5f;
} else {
vad = 1.f;
}
renamenoise_frame_analysis(st, Y, Ey, x);
renamenoise_frame_analysis(noise_state, N, En, n);
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
Ln[i] = log10(1e-2 + En[i]);
}
int silence = renamenoise_compute_frame_features(noisy, X, P, Ex, Ep, Exp, features, xn);
renamenoise_pitch_filter(X, P, Ex, Ep, Exp, g);
// printf("%f %d\n", noisy->last_gain, noisy->last_period);
for (i = 0; i < RENAMENOISE_NB_BANDS; i++) {
g[i] = sqrt((Ey[i] + 1e-3) / (Ex[i] + 1e-3));
if (g[i] > 1) {
g[i] = 1;
}
if (silence || i > band_lp) {
g[i] = -1;
}
if (Ey[i] < 5e-2 && Ex[i] < 5e-2) {
g[i] = -1;
}
if (vad == 0 && noise_gain == 0) {
g[i] = -1;
}
}
count++;
fwrite(features, sizeof(float), RENAMENOISE_NB_FEATURES, stdout);
fwrite(g, sizeof(float), RENAMENOISE_NB_BANDS, stdout);
fwrite(Ln, sizeof(float), RENAMENOISE_NB_BANDS, stdout);
fwrite(&vad, sizeof(float), 1, stdout);
}
fprintf(stderr, "matrix size: %d x %d\n", count, RENAMENOISE_NB_FEATURES + 2 * RENAMENOISE_NB_BANDS + 1);
fclose(f1);
fclose(f2);
return 0;
}
#endif

363
thirdparty/renamenoise/src/pitch.c vendored Normal file
View file

@ -0,0 +1,363 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2007-2009, Xiph.Org Foundation
Copyright (c) 2007-2008, CSIRO
Copyright (c) 2003-2008, Jean-Marc Valin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
@file pitch.c
@brief Pitch analysis
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "pitch.h"
#include "common.h"
#include "math.h"
#include "renamenoise_lpc.h"
static void renamenoise_find_best_pitch(renamenoise_val32 *xcorr, renamenoise_val16 *y, int len, int max_pitch, int *best_pitch) {
int i, j;
renamenoise_val32 Syy = 1;
renamenoise_val16 best_num[2];
renamenoise_val32 best_den[2];
best_num[0] = -1;
best_num[1] = -1;
best_den[0] = 0;
best_den[1] = 0;
best_pitch[0] = 0;
best_pitch[1] = 1;
for (j = 0; j < len; j++) {
Syy = RENAMENOISE_ADD(Syy, RENAMENOISE_MULT(y[j], y[j]));
}
for (i = 0; i < max_pitch; i++) {
if (xcorr[i] > 0) {
renamenoise_val16 num;
renamenoise_val32 xcorr16;
xcorr16 = xcorr[i];
// Considering the range of xcorr16, this should avoid both underflows and overflows (inf) when squaring xcorr16
xcorr16 *= 1e-12f;
num = RENAMENOISE_MULT(xcorr16, xcorr16);
if (RENAMENOISE_MULT(num, best_den[1]) > RENAMENOISE_MULT(best_num[1], Syy)) {
if (RENAMENOISE_MULT(num, best_den[0]) > RENAMENOISE_MULT(best_num[0], Syy)) {
best_num[1] = best_num[0];
best_den[1] = best_den[0];
best_pitch[1] = best_pitch[0];
best_num[0] = num;
best_den[0] = Syy;
best_pitch[0] = i;
} else {
best_num[1] = num;
best_den[1] = Syy;
best_pitch[1] = i;
}
}
}
Syy += RENAMENOISE_MULT(y[i + len], y[i + len]) - RENAMENOISE_MULT(y[i], y[i]);
Syy = RENAMENOISE_MAX32(1, Syy);
}
}
static void renamenoise_fir5(const renamenoise_val16 *x, const renamenoise_val16 *num, renamenoise_val16 *y, int N, renamenoise_val16 *mem) {
int i;
renamenoise_val16 num0, num1, num2, num3, num4;
renamenoise_val32 mem0, mem1, mem2, mem3, mem4;
num0 = num[0];
num1 = num[1];
num2 = num[2];
num3 = num[3];
num4 = num[4];
mem0 = mem[0];
mem1 = mem[1];
mem2 = mem[2];
mem3 = mem[3];
mem4 = mem[4];
for (i = 0; i < N; i++) {
renamenoise_val32 sum = x[i];
sum = RENAMENOISE_MAC(sum, num0, mem0);
sum = RENAMENOISE_MAC(sum, num1, mem1);
sum = RENAMENOISE_MAC(sum, num2, mem2);
sum = RENAMENOISE_MAC(sum, num3, mem3);
sum = RENAMENOISE_MAC(sum, num4, mem4);
mem4 = mem3;
mem3 = mem2;
mem2 = mem1;
mem1 = mem0;
mem0 = x[i];
y[i] = sum;
}
mem[0] = mem0;
mem[1] = mem1;
mem[2] = mem2;
mem[3] = mem3;
mem[4] = mem4;
}
void renamenoise_pitch_downsample(renamenoise_sig *x[], renamenoise_val16 *x_lp, int len, int C) {
int i;
renamenoise_val32 ac[5];
renamenoise_val16 tmp = RENAMENOISE_Q15ONE;
renamenoise_val16 lpc[4], mem[5] = {0, 0, 0, 0, 0};
renamenoise_val16 lpc2[5];
renamenoise_val16 c1 = .8f;
for (i = 1; i < (len >> 1); i++) {
x_lp[i] = RENAMENOISE_HALF(RENAMENOISE_HALF(x[0][(2 * i - 1)] + x[0][(2 * i + 1)]) + x[0][2 * i]);
}
x_lp[0] = RENAMENOISE_HALF(RENAMENOISE_HALF(x[0][1]) + x[0][0]);
if (C == 2) {
for (i = 1; i < (len >> 1); i++) {
x_lp[i] += RENAMENOISE_HALF(RENAMENOISE_HALF(x[1][(2 * i - 1)] + x[1][(2 * i + 1)]) + x[1][2 * i]);
}
x_lp[0] += RENAMENOISE_HALF(RENAMENOISE_HALF(x[1][1]) + x[1][0]);
}
_renamenoise_autocorr(x_lp, ac, NULL, 0, 4, len >> 1);
// Noise floor -40 dB
ac[0] *= 1.0001f;
// Lag windowing
for (i = 1; i <= 4; i++) {
// ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));
ac[i] -= ac[i] * (.008f * i) * (.008f * i);
}
_renamenoise_lpc(lpc, ac, 4);
for (i = 0; i < 4; i++) {
tmp = RENAMENOISE_MULT(.9f, tmp);
lpc[i] = RENAMENOISE_MULT(lpc[i], tmp);
}
// Add a zero
lpc2[0] = lpc[0] + .8f;
lpc2[1] = lpc[1] + RENAMENOISE_MULT(c1, lpc[0]);
lpc2[2] = lpc[2] + RENAMENOISE_MULT(c1, lpc[1]);
lpc2[3] = lpc[3] + RENAMENOISE_MULT(c1, lpc[2]);
lpc2[4] = RENAMENOISE_MULT(c1, lpc[3]);
renamenoise_fir5(x_lp, lpc2, x_lp, len >> 1, mem);
}
void renamenoise_pitch_xcorr(const renamenoise_val16 *_x, const renamenoise_val16 *_y, renamenoise_val32 *xcorr, int len, int max_pitch) {
// Unrolled version of the pitch correlation -- runs faster on x86 and ARM
int i;
// The EDSP version requires that max_pitch is at least 1,
// and that _x is 32-bit aligned.
// Since it's hard to put asserts in assembly, put them here.
renamenoise_assert(max_pitch > 0);
renamenoise_assert((((unsigned char *) _x - (unsigned char *) NULL) & 3) == 0);
for (i = 0; i < max_pitch - 3; i += 4) {
renamenoise_val32 sum[4] = {0, 0, 0, 0};
renamenoise_xcorr_kernel(_x, _y + i, sum, len);
xcorr[i] = sum[0];
xcorr[i + 1] = sum[1];
xcorr[i + 2] = sum[2];
xcorr[i + 3] = sum[3];
}
// In case max_pitch isn't a multiple of 4, do non-unrolled version.
for (; i < max_pitch; i++) {
renamenoise_val32 sum;
sum = renamenoise_inner_prod(_x, _y + i, len);
xcorr[i] = sum;
}
}
void renamenoise_pitch_search(const renamenoise_val16 *x_lp, renamenoise_val16 *y, int len, int max_pitch, int *pitch) {
int i, j;
int lag;
int best_pitch[2] = {0, 0};
int offset;
renamenoise_assert(len > 0);
renamenoise_assert(max_pitch > 0);
lag = len + max_pitch;
renamenoise_stackalloc(renamenoise_val16, x_lp4, len >> 2);
renamenoise_stackalloc(renamenoise_val16, y_lp4, lag >> 2);
renamenoise_stackalloc(renamenoise_val32, xcorr, max_pitch >> 1);
// Downsample by 2 again
for (j = 0; j < (len >> 2); j++) {
x_lp4[j] = x_lp[2 * j];
}
for (j = 0; j < (lag >> 2); j++) {
y_lp4[j] = y[2 * j];
}
// Coarse search with 4x decimation
renamenoise_pitch_xcorr(x_lp4, y_lp4, xcorr, len >> 2, max_pitch >> 2);
renamenoise_find_best_pitch(xcorr, y_lp4, len >> 2, max_pitch >> 2, best_pitch);
// Finer search with 2x decimation
for (i = 0; i < (max_pitch >> 1); i++) {
renamenoise_val32 sum;
xcorr[i] = 0;
if (abs(i - 2 * best_pitch[0]) > 2 && abs(i - 2 * best_pitch[1]) > 2) {
continue;
}
sum = renamenoise_inner_prod(x_lp, y + i, len >> 1);
xcorr[i] = RENAMENOISE_MAX32(-1, sum);
}
renamenoise_find_best_pitch(xcorr, y, len >> 1, max_pitch >> 1, best_pitch);
// Refine by pseudo-interpolation
if (best_pitch[0] > 0 && best_pitch[0] < (max_pitch >> 1) - 1) {
renamenoise_val32 a, b, c;
a = xcorr[best_pitch[0] - 1];
b = xcorr[best_pitch[0]];
c = xcorr[best_pitch[0] + 1];
if ((c - a) > RENAMENOISE_MULT(.7f, b - a)) {
offset = 1;
} else if ((a - c) > RENAMENOISE_MULT(.7f, b - c)) {
offset = -1;
} else {
offset = 0;
}
} else {
offset = 0;
}
*pitch = 2 * best_pitch[0] - offset;
}
static renamenoise_val16 renamenoise_compute_pitch_gain(renamenoise_val32 xy, renamenoise_val32 xx, renamenoise_val32 yy) {
return xy / sqrt(1 + xx * yy);
}
static const int renamenoise_second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
renamenoise_val16 renamenoise_remove_doubling(renamenoise_val16 *x, int maxperiod, int minperiod, int N, int *T0_, int prev_period,
renamenoise_val16 prev_gain) {
int k, i, T, T0;
renamenoise_val16 g, g0;
renamenoise_val16 pg;
renamenoise_val32 xy, xx, yy, xy2;
renamenoise_val32 xcorr[3];
renamenoise_val32 best_xy, best_yy;
int offset;
int minperiod0;
minperiod0 = minperiod;
maxperiod /= 2;
minperiod /= 2;
*T0_ /= 2;
prev_period /= 2;
N /= 2;
x += maxperiod;
if (*T0_ >= maxperiod) {
*T0_ = maxperiod - 1;
}
T = T0 = *T0_;
renamenoise_stackalloc(renamenoise_val32, yy_lookup, maxperiod + 1);
renamenoise_dual_inner_prod(x, x, x - T0, N, &xx, &xy);
yy_lookup[0] = xx;
yy = xx;
for (i = 1; i <= maxperiod; i++) {
yy = yy + RENAMENOISE_MULT(x[-i], x[-i]) - RENAMENOISE_MULT(x[N - i], x[N - i]);
yy_lookup[i] = RENAMENOISE_MAX32(0, yy);
}
yy = yy_lookup[T0];
best_xy = xy;
best_yy = yy;
g = g0 = renamenoise_compute_pitch_gain(xy, xx, yy);
// Look for any pitch at T/k
for (k = 2; k <= 15; k++) {
int T1, T1b;
renamenoise_val16 g1;
renamenoise_val16 cont = 0;
renamenoise_val16 thresh;
T1 = (2 * T0 + k) / (2 * k);
if (T1 < minperiod) {
break;
}
// Look for another strong correlation at T1b
if (k == 2) {
if (T1 + T0 > maxperiod) {
T1b = T0;
} else {
T1b = T0 + T1;
}
} else {
T1b = (2 * renamenoise_second_check[k] * T0 + k) / (2 * k);
}
renamenoise_dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2);
xy = RENAMENOISE_HALF(xy + xy2);
yy = RENAMENOISE_HALF(yy_lookup[T1] + yy_lookup[T1b]);
g1 = renamenoise_compute_pitch_gain(xy, xx, yy);
if (abs(T1 - prev_period) <= 1) {
cont = prev_gain;
} else if (abs(T1 - prev_period) <= 2 && 5 * k * k < T0) {
cont = RENAMENOISE_HALF(prev_gain);
} else {
cont = 0;
}
thresh = RENAMENOISE_MAX16(.3f, RENAMENOISE_MULT(.7f, g0) - cont);
// Bias against very high pitch (very short period) to avoid false-positives due to short-term correlation
if (T1 < 3 * minperiod) {
thresh = RENAMENOISE_MAX16(.4f, RENAMENOISE_MULT(.85f, g0) - cont);
} else if (T1 < 2 * minperiod) {
thresh = RENAMENOISE_MAX16(.5f, RENAMENOISE_MULT(.9f, g0) - cont);
}
if (g1 > thresh) {
best_xy = xy;
best_yy = yy;
T = T1;
g = g1;
}
}
best_xy = RENAMENOISE_MAX32(0, best_xy);
if (best_yy <= best_xy) {
pg = RENAMENOISE_Q15ONE;
} else {
pg = best_xy / (best_yy + 1);
}
for (k = 0; k < 3; k++) {
xcorr[k] = renamenoise_inner_prod(x, x - (T + k - 1), N);
}
if ((xcorr[2] - xcorr[0]) > RENAMENOISE_MULT(.7f, xcorr[1] - xcorr[0])) {
offset = 1;
} else if ((xcorr[0] - xcorr[2]) > RENAMENOISE_MULT(.7f, xcorr[1] - xcorr[2])) {
offset = -1;
} else {
offset = 0;
}
if (pg > g) {
pg = g;
}
*T0_ = 2 * T + offset;
if (*T0_ < minperiod0) {
*T0_ = minperiod0;
}
return pg;
}

137
thirdparty/renamenoise/src/pitch.h vendored Normal file
View file

@ -0,0 +1,137 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2007-2009, Xiph.Org Foundation
Copyright (c) 2007-2008, CSIRO
Copyright (c) 2003-2008, Jean-Marc Valin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
@file pitch.h
@brief Pitch analysis
*/
#ifndef PITCH_H
#define PITCH_H
#include "arch.h"
void renamenoise_pitch_downsample(renamenoise_sig *x[], renamenoise_val16 *x_lp, int len, int C);
void renamenoise_pitch_search(const renamenoise_val16 *x_lp, renamenoise_val16 *y, int len, int max_pitch, int *pitch);
renamenoise_val16 renamenoise_remove_doubling(renamenoise_val16 *x, int maxperiod, int minperiod, int N, int *T0, int prev_period,
renamenoise_val16 prev_gain);
// OPT: This is the kernel you really want to optimize. It gets used a lot by the prefilter and by the PLC.
static RENAMENOISE_INLINE void renamenoise_xcorr_kernel(const renamenoise_val16 *x, const renamenoise_val16 *y, renamenoise_val32 sum[4], int len) {
int j;
renamenoise_val16 y_0, y_1, y_2, y_3;
renamenoise_assert(len >= 3);
y_3 = 0; /* gcc doesn't realize that y_3 can't be used uninitialized */
y_0 = *y++;
y_1 = *y++;
y_2 = *y++;
for (j = 0; j < len - 3; j += 4) {
renamenoise_val16 tmp;
tmp = *x++;
y_3 = *y++;
sum[0] = RENAMENOISE_MAC(sum[0], tmp, y_0);
sum[1] = RENAMENOISE_MAC(sum[1], tmp, y_1);
sum[2] = RENAMENOISE_MAC(sum[2], tmp, y_2);
sum[3] = RENAMENOISE_MAC(sum[3], tmp, y_3);
tmp = *x++;
y_0 = *y++;
sum[0] = RENAMENOISE_MAC(sum[0], tmp, y_1);
sum[1] = RENAMENOISE_MAC(sum[1], tmp, y_2);
sum[2] = RENAMENOISE_MAC(sum[2], tmp, y_3);
sum[3] = RENAMENOISE_MAC(sum[3], tmp, y_0);
tmp = *x++;
y_1 = *y++;
sum[0] = RENAMENOISE_MAC(sum[0], tmp, y_2);
sum[1] = RENAMENOISE_MAC(sum[1], tmp, y_3);
sum[2] = RENAMENOISE_MAC(sum[2], tmp, y_0);
sum[3] = RENAMENOISE_MAC(sum[3], tmp, y_1);
tmp = *x++;
y_2 = *y++;
sum[0] = RENAMENOISE_MAC(sum[0], tmp, y_3);
sum[1] = RENAMENOISE_MAC(sum[1], tmp, y_0);
sum[2] = RENAMENOISE_MAC(sum[2], tmp, y_1);
sum[3] = RENAMENOISE_MAC(sum[3], tmp, y_2);
}
if (j++ < len) {
renamenoise_val16 tmp = *x++;
y_3 = *y++;
sum[0] = RENAMENOISE_MAC(sum[0], tmp, y_0);
sum[1] = RENAMENOISE_MAC(sum[1], tmp, y_1);
sum[2] = RENAMENOISE_MAC(sum[2], tmp, y_2);
sum[3] = RENAMENOISE_MAC(sum[3], tmp, y_3);
}
if (j++ < len) {
renamenoise_val16 tmp = *x++;
y_0 = *y++;
sum[0] = RENAMENOISE_MAC(sum[0], tmp, y_1);
sum[1] = RENAMENOISE_MAC(sum[1], tmp, y_2);
sum[2] = RENAMENOISE_MAC(sum[2], tmp, y_3);
sum[3] = RENAMENOISE_MAC(sum[3], tmp, y_0);
}
if (j < len) {
renamenoise_val16 tmp = *x++;
y_1 = *y++;
sum[0] = RENAMENOISE_MAC(sum[0], tmp, y_2);
sum[1] = RENAMENOISE_MAC(sum[1], tmp, y_3);
sum[2] = RENAMENOISE_MAC(sum[2], tmp, y_0);
sum[3] = RENAMENOISE_MAC(sum[3], tmp, y_1);
}
}
static RENAMENOISE_INLINE void renamenoise_dual_inner_prod(const renamenoise_val16 *x, const renamenoise_val16 *y01, const renamenoise_val16 *y02,
int N, renamenoise_val32 *xy1, renamenoise_val32 *xy2) {
int i;
renamenoise_val32 xy01 = 0;
renamenoise_val32 xy02 = 0;
for (i = 0; i < N; i++) {
xy01 = RENAMENOISE_MAC(xy01, x[i], y01[i]);
xy02 = RENAMENOISE_MAC(xy02, x[i], y02[i]);
}
*xy1 = xy01;
*xy2 = xy02;
}
// We make sure a C version is always available for cases where the overhead of vectorization and passing around an arch flag aren't worth it.
static RENAMENOISE_INLINE renamenoise_val32 renamenoise_inner_prod(const renamenoise_val16 *x, const renamenoise_val16 *y, int N) {
int i;
renamenoise_val32 xy = 0;
for (i = 0; i < N; i++) {
xy = RENAMENOISE_MAC(xy, x[i], y[i]);
}
return xy;
}
void renamenoise_pitch_xcorr(const renamenoise_val16 *_x, const renamenoise_val16 *_y, renamenoise_val32 *xcorr, int len, int max_pitch);
#endif /* PITCH_H */

View file

@ -0,0 +1,471 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2008, Xiph.Org Foundation, CSIRO
Copyright (c) 2005-2007, Xiph.Org Foundation
Lots of modifications by Jean-Marc Valin
Copyright (c) 2003-2004, Mark Borgerding
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Lots of modifications by Jean-Marc Valin. This code is originally from Mark
// Borgerding's KISS-FFT but has been heavily modified to better suit Opus and
// was subsequently refactored for ReNameNoise
#ifndef SKIP_CONFIG_H
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
#endif
#include "_renamenoise_fft_guts.h"
// The guts header contains all the multiplication and addition macros that are
// defined for complex numbers. It also declares the kf_ internal functions.
static void renamenoise_kf_bfly2(renamenoise_fft_cpx *Fout, int m, int N) {
renamenoise_fft_cpx *Fout2;
int i;
(void) m;
if (m == 1) {
renamenoise_assert(m == 1);
for (i = 0; i < N; i++) {
renamenoise_fft_cpx t;
Fout2 = Fout + 1;
t = *Fout2;
RENAMENOISE_C_SUB(*Fout2, *Fout, t);
RENAMENOISE_C_ADDTO(*Fout, t);
Fout += 2;
}
} else {
renamenoise_val16 tw;
tw = 0.7071067812f;
// We know that m==4 here because the radix-2 is just after a radix-4
renamenoise_assert(m == 4);
for (i = 0; i < N; i++) {
renamenoise_fft_cpx t;
Fout2 = Fout + 4;
t = Fout2[0];
RENAMENOISE_C_SUB(Fout2[0], Fout[0], t);
RENAMENOISE_C_ADDTO(Fout[0], t);
t.r = RENAMENOISE_S_MUL(RENAMENOISE_ADD(Fout2[1].r, Fout2[1].i), tw);
t.i = RENAMENOISE_S_MUL(RENAMENOISE_SUB(Fout2[1].i, Fout2[1].r), tw);
RENAMENOISE_C_SUB(Fout2[1], Fout[1], t);
RENAMENOISE_C_ADDTO(Fout[1], t);
t.r = Fout2[2].i;
t.i = -Fout2[2].r;
RENAMENOISE_C_SUB(Fout2[2], Fout[2], t);
RENAMENOISE_C_ADDTO(Fout[2], t);
t.r = RENAMENOISE_S_MUL(RENAMENOISE_SUB(Fout2[3].i, Fout2[3].r), tw);
t.i = RENAMENOISE_S_MUL(-RENAMENOISE_ADD(Fout2[3].i, Fout2[3].r), tw);
RENAMENOISE_C_SUB(Fout2[3], Fout[3], t);
RENAMENOISE_C_ADDTO(Fout[3], t);
Fout += 8;
}
}
}
static void renamenoise_kf_bfly4(renamenoise_fft_cpx *Fout, const size_t fstride, const renamenoise_fft_state *st, int m, int N, int mm) {
int i;
if (m == 1) {
// Degenerate case where all the twiddles are 1.
for (i = 0; i < N; i++) {
renamenoise_fft_cpx scratch0, scratch1;
RENAMENOISE_C_SUB(scratch0, *Fout, Fout[2]);
RENAMENOISE_C_ADDTO(*Fout, Fout[2]);
RENAMENOISE_C_ADD(scratch1, Fout[1], Fout[3]);
RENAMENOISE_C_SUB(Fout[2], *Fout, scratch1);
RENAMENOISE_C_ADDTO(*Fout, scratch1);
RENAMENOISE_C_SUB(scratch1, Fout[1], Fout[3]);
Fout[1].r = RENAMENOISE_ADD(scratch0.r, scratch1.i);
Fout[1].i = RENAMENOISE_SUB(scratch0.i, scratch1.r);
Fout[3].r = RENAMENOISE_SUB(scratch0.r, scratch1.i);
Fout[3].i = RENAMENOISE_ADD(scratch0.i, scratch1.r);
Fout += 4;
}
} else {
int j;
renamenoise_fft_cpx scratch[6];
const renamenoise_twiddle_cpx *tw1, *tw2, *tw3;
const int m2 = 2 * m;
const int m3 = 3 * m;
renamenoise_fft_cpx *Fout_beg = Fout;
for (i = 0; i < N; i++) {
Fout = Fout_beg + i * mm;
tw3 = tw2 = tw1 = st->twiddles;
// m is guaranteed to be a multiple of 4.
for (j = 0; j < m; j++) {
RENAMENOISE_C_MUL(scratch[0], Fout[m], *tw1);
RENAMENOISE_C_MUL(scratch[1], Fout[m2], *tw2);
RENAMENOISE_C_MUL(scratch[2], Fout[m3], *tw3);
RENAMENOISE_C_SUB(scratch[5], *Fout, scratch[1]);
RENAMENOISE_C_ADDTO(*Fout, scratch[1]);
RENAMENOISE_C_ADD(scratch[3], scratch[0], scratch[2]);
RENAMENOISE_C_SUB(scratch[4], scratch[0], scratch[2]);
RENAMENOISE_C_SUB(Fout[m2], *Fout, scratch[3]);
tw1 += fstride;
tw2 += fstride * 2;
tw3 += fstride * 3;
RENAMENOISE_C_ADDTO(*Fout, scratch[3]);
Fout[m].r = RENAMENOISE_ADD(scratch[5].r, scratch[4].i);
Fout[m].i = RENAMENOISE_SUB(scratch[5].i, scratch[4].r);
Fout[m3].r = RENAMENOISE_SUB(scratch[5].r, scratch[4].i);
Fout[m3].i = RENAMENOISE_ADD(scratch[5].i, scratch[4].r);
++Fout;
}
}
}
}
static void renamenoise_kf_bfly3(renamenoise_fft_cpx *Fout, const size_t fstride, const renamenoise_fft_state *st, int m, int N, int mm) {
int i;
size_t k;
const size_t m2 = 2 * m;
const renamenoise_twiddle_cpx *tw1, *tw2;
renamenoise_fft_cpx scratch[5];
renamenoise_twiddle_cpx epi3;
renamenoise_fft_cpx *Fout_beg = Fout;
epi3 = st->twiddles[fstride * m];
for (i = 0; i < N; i++) {
Fout = Fout_beg + i * mm;
tw1 = tw2 = st->twiddles;
// For non-custom modes, m is guaranteed to be a multiple of 4.
k = m;
do {
RENAMENOISE_C_MUL(scratch[1], Fout[m], *tw1);
RENAMENOISE_C_MUL(scratch[2], Fout[m2], *tw2);
RENAMENOISE_C_ADD(scratch[3], scratch[1], scratch[2]);
RENAMENOISE_C_SUB(scratch[0], scratch[1], scratch[2]);
tw1 += fstride;
tw2 += fstride * 2;
Fout[m].r = RENAMENOISE_SUB(Fout->r, RENAMENOISE_HALF(scratch[3].r));
Fout[m].i = RENAMENOISE_SUB(Fout->i, RENAMENOISE_HALF(scratch[3].i));
RENAMENOISE_C_MULBYSCALAR(scratch[0], epi3.i);
RENAMENOISE_C_ADDTO(*Fout, scratch[3]);
Fout[m2].r = RENAMENOISE_ADD(Fout[m].r, scratch[0].i);
Fout[m2].i = RENAMENOISE_SUB(Fout[m].i, scratch[0].r);
Fout[m].r = RENAMENOISE_SUB(Fout[m].r, scratch[0].i);
Fout[m].i = RENAMENOISE_ADD(Fout[m].i, scratch[0].r);
++Fout;
} while (--k);
}
}
static void renamenoise_kf_bfly5(renamenoise_fft_cpx *Fout, const size_t fstride, const renamenoise_fft_state *st, int m, int N, int mm) {
renamenoise_fft_cpx *Fout0, *Fout1, *Fout2, *Fout3, *Fout4;
int i, u;
renamenoise_fft_cpx scratch[13];
const renamenoise_twiddle_cpx *tw;
renamenoise_twiddle_cpx ya, yb;
renamenoise_fft_cpx *Fout_beg = Fout;
ya = st->twiddles[fstride * m];
yb = st->twiddles[fstride * 2 * m];
tw = st->twiddles;
for (i = 0; i < N; i++) {
Fout = Fout_beg + i * mm;
Fout0 = Fout;
Fout1 = Fout0 + m;
Fout2 = Fout0 + 2 * m;
Fout3 = Fout0 + 3 * m;
Fout4 = Fout0 + 4 * m;
// For non-custom modes, m is guaranteed to be a multiple of 4.
for (u = 0; u < m; ++u) {
scratch[0] = *Fout0;
RENAMENOISE_C_MUL(scratch[1], *Fout1, tw[u * fstride]);
RENAMENOISE_C_MUL(scratch[2], *Fout2, tw[2 * u * fstride]);
RENAMENOISE_C_MUL(scratch[3], *Fout3, tw[3 * u * fstride]);
RENAMENOISE_C_MUL(scratch[4], *Fout4, tw[4 * u * fstride]);
RENAMENOISE_C_ADD(scratch[7], scratch[1], scratch[4]);
RENAMENOISE_C_SUB(scratch[10], scratch[1], scratch[4]);
RENAMENOISE_C_ADD(scratch[8], scratch[2], scratch[3]);
RENAMENOISE_C_SUB(scratch[9], scratch[2], scratch[3]);
Fout0->r = RENAMENOISE_ADD(Fout0->r, RENAMENOISE_ADD(scratch[7].r, scratch[8].r));
Fout0->i = RENAMENOISE_ADD(Fout0->i, RENAMENOISE_ADD(scratch[7].i, scratch[8].i));
scratch[5].r =
RENAMENOISE_ADD(scratch[0].r, RENAMENOISE_ADD(RENAMENOISE_S_MUL(scratch[7].r, ya.r), RENAMENOISE_S_MUL(scratch[8].r, yb.r)));
scratch[5].i =
RENAMENOISE_ADD(scratch[0].i, RENAMENOISE_ADD(RENAMENOISE_S_MUL(scratch[7].i, ya.r), RENAMENOISE_S_MUL(scratch[8].i, yb.r)));
scratch[6].r = RENAMENOISE_ADD(RENAMENOISE_S_MUL(scratch[10].i, ya.i), RENAMENOISE_S_MUL(scratch[9].i, yb.i));
scratch[6].i = -RENAMENOISE_ADD(RENAMENOISE_S_MUL(scratch[10].r, ya.i), RENAMENOISE_S_MUL(scratch[9].r, yb.i));
RENAMENOISE_C_SUB(*Fout1, scratch[5], scratch[6]);
RENAMENOISE_C_ADD(*Fout4, scratch[5], scratch[6]);
scratch[11].r =
RENAMENOISE_ADD(scratch[0].r, RENAMENOISE_ADD(RENAMENOISE_S_MUL(scratch[7].r, yb.r), RENAMENOISE_S_MUL(scratch[8].r, ya.r)));
scratch[11].i =
RENAMENOISE_ADD(scratch[0].i, RENAMENOISE_ADD(RENAMENOISE_S_MUL(scratch[7].i, yb.r), RENAMENOISE_S_MUL(scratch[8].i, ya.r)));
scratch[12].r = RENAMENOISE_SUB(RENAMENOISE_S_MUL(scratch[9].i, ya.i), RENAMENOISE_S_MUL(scratch[10].i, yb.i));
scratch[12].i = RENAMENOISE_SUB(RENAMENOISE_S_MUL(scratch[10].r, yb.i), RENAMENOISE_S_MUL(scratch[9].r, ya.i));
RENAMENOISE_C_ADD(*Fout2, scratch[11], scratch[12]);
RENAMENOISE_C_SUB(*Fout3, scratch[11], scratch[12]);
++Fout0;
++Fout1;
++Fout2;
++Fout3;
++Fout4;
}
}
}
static void renamenoise_compute_bitrev_table(int Fout, renamenoise_int16 *f, const size_t fstride, int in_stride, renamenoise_int16 *factors,
const renamenoise_fft_state *st) {
const int p = *factors++; // the radix
const int m = *factors++; // stage's fft length/p
if (m == 1) {
int j;
for (j = 0; j < p; j++) {
*f = Fout + j;
f += fstride * in_stride;
}
} else {
int j;
for (j = 0; j < p; j++) {
renamenoise_compute_bitrev_table(Fout, f, fstride * p, in_stride, factors, st);
f += fstride * in_stride;
Fout += m;
}
}
}
// facbuf is populated by p1,m1,p2,m2, ...
// where
// p[i] * m[i] = m[i-1]
// m0 = n
static int renamenoise_kf_factor(int n, renamenoise_int16 *facbuf) {
int p = 4;
int i;
int stages = 0;
int nbak = n;
// factor out powers of 4, powers of 2, then any remaining primes
do {
while (n % p) {
switch (p) {
case 4: p = 2; break;
case 2: p = 3; break;
default: p += 2; break;
}
if (p > 32000 || (renamenoise_int32) p * (renamenoise_int32) p > n) {
p = n; // no more factors, skip to end
}
}
n /= p;
if (p > 5) {
return 0;
}
facbuf[2 * stages] = p;
if (p == 2 && stages > 1) {
facbuf[2 * stages] = 4;
facbuf[2] = 2;
}
stages++;
} while (n > 1);
n = nbak;
// Reverse the order to get the radix 4 at the end, so we can use the
// fast degenerate case. It turns out that reversing the order also
// improves the noise behaviour.
for (i = 0; i < stages / 2; i++) {
int tmp;
tmp = facbuf[2 * i];
facbuf[2 * i] = facbuf[2 * (stages - i - 1)];
facbuf[2 * (stages - i - 1)] = tmp;
}
for (i = 0; i < stages; i++) {
n /= facbuf[2 * i];
facbuf[2 * i + 1] = n;
}
return 1;
}
static void renamenoise_compute_twiddles(renamenoise_twiddle_cpx *twiddles, int nfft) {
int i;
for (i = 0; i < nfft; ++i) {
double phase = (-2 * M_PI / nfft) * i;
renamenoise_kf_cexp(twiddles + i, phase);
}
}
int renamenoise_fft_alloc_arch_c(renamenoise_fft_state *st) {
(void) st;
return 0;
}
/**
* Allocates all necessary storage space for the fft and ifft.
* The return value is a contiguous block of memory. As such,
* It can be freed with free().
*/
renamenoise_fft_state *renamenoise_fft_alloc_twiddles(int nfft, void *mem, size_t *lenmem, const renamenoise_fft_state *base, int arch) {
renamenoise_fft_state *st = NULL;
size_t memneeded = sizeof(struct renamenoise_fft_state); // twiddle factors
if (lenmem == NULL) {
st = (renamenoise_fft_state *) RENAMENOISE_FFT_MALLOC(memneeded);
} else {
if (mem != NULL && *lenmem >= memneeded) {
st = (renamenoise_fft_state *) mem;
}
*lenmem = memneeded;
}
if (st) {
renamenoise_int16 *bitrev;
renamenoise_twiddle_cpx *twiddles;
st->nfft = nfft;
st->scale = 1.f / nfft;
if (base != NULL) {
st->twiddles = base->twiddles;
st->shift = 0;
while (st->shift < 32 && nfft << st->shift != base->nfft) {
st->shift++;
}
if (st->shift >= 32) {
goto fail;
}
} else {
st->twiddles = twiddles = (renamenoise_twiddle_cpx *) RENAMENOISE_FFT_MALLOC(sizeof(renamenoise_twiddle_cpx) * nfft);
renamenoise_compute_twiddles(twiddles, nfft);
st->shift = -1;
}
if (!renamenoise_kf_factor(nfft, st->factors)) {
goto fail;
}
// bitrev
st->bitrev = bitrev = (renamenoise_int16 *) RENAMENOISE_FFT_MALLOC(sizeof(renamenoise_int16) * nfft);
if (st->bitrev == NULL) {
goto fail;
}
renamenoise_compute_bitrev_table(0, bitrev, 1, 1, st->factors, st);
// Initialize architecture specific fft parameters
if (renamenoise_fft_alloc_arch(st, arch)) {
goto fail;
}
}
return st;
fail:
renamenoise_fft_free(st, arch);
return NULL;
}
renamenoise_fft_state *renamenoise_fft_alloc(int nfft, void *mem, size_t *lenmem, int arch) {
return renamenoise_fft_alloc_twiddles(nfft, mem, lenmem, NULL, arch);
}
void renamenoise_fft_free_arch_c(renamenoise_fft_state *st) {
(void) st;
}
void renamenoise_fft_free(const renamenoise_fft_state *cfg, int arch) {
if (cfg) {
renamenoise_fft_free_arch((renamenoise_fft_state *) cfg, arch);
renamenoise_free2((renamenoise_int16 *) cfg->bitrev);
if (cfg->shift < 0) {
renamenoise_free2((renamenoise_twiddle_cpx *) cfg->twiddles);
}
renamenoise_free2((renamenoise_fft_state *) cfg);
}
}
void renamenoise_fft_impl(const renamenoise_fft_state *st, renamenoise_fft_cpx *fout) {
int m2, m;
int p;
int L;
int fstride[RENAMENOISE_MAXFACTORS];
int i;
int shift;
// st->shift can be -1
shift = st->shift > 0 ? st->shift : 0;
fstride[0] = 1;
L = 0;
do {
p = st->factors[2 * L];
m = st->factors[2 * L + 1];
fstride[L + 1] = fstride[L] * p;
L++;
} while (m != 1);
m = st->factors[2 * L - 1];
for (i = L - 1; i >= 0; i--) {
if (i != 0) {
m2 = st->factors[2 * i - 1];
} else {
m2 = 1;
}
switch (st->factors[2 * i]) {
case 2: renamenoise_kf_bfly2(fout, m, fstride[i]); break;
case 4: renamenoise_kf_bfly4(fout, fstride[i] << shift, st, m, fstride[i], m2); break;
case 3: renamenoise_kf_bfly3(fout, fstride[i] << shift, st, m, fstride[i], m2); break;
case 5: renamenoise_kf_bfly5(fout, fstride[i] << shift, st, m, fstride[i], m2); break;
}
m = m2;
}
}
void renamenoise_fft_c(const renamenoise_fft_state *st, const renamenoise_fft_cpx *fin, renamenoise_fft_cpx *fout) {
int i;
renamenoise_val16 scale;
scale = st->scale;
renamenoise_assert2(fin != fout, "In-place FFT not supported");
// Bit-reverse the input
for (i = 0; i < st->nfft; i++) {
renamenoise_fft_cpx x = fin[i];
fout[st->bitrev[i]].r = RENAMENOISE_MULT(scale, x.r);
fout[st->bitrev[i]].i = RENAMENOISE_MULT(scale, x.i);
}
renamenoise_fft_impl(st, fout);
}

View file

@ -0,0 +1,150 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2008, Xiph.Org Foundation, CSIRO
Copyright (c) 2005-2007, Xiph.Org Foundation
Lots of modifications by Jean-Marc Valin
Copyright (c) 2003-2004, Mark Borgerding
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RENAMENOISE_FFT_H
#define RENAMENOISE_FFT_H
#include "arch.h"
#include <math.h>
#include <stdlib.h>
#define renamenoise_alloc2(x) malloc(x)
#define renamenoise_free2(x) free(x)
#ifdef __cplusplus
extern "C" {
#endif
#define RENAMENOISE_FFT_MALLOC renamenoise_alloc2
#ifndef renamenoise_fft_scalar
// default is float
# define renamenoise_fft_scalar float
# define renamenoise_twiddle_scalar float
#endif
typedef struct {
renamenoise_fft_scalar r;
renamenoise_fft_scalar i;
} renamenoise_fft_cpx;
typedef struct {
renamenoise_twiddle_scalar r;
renamenoise_twiddle_scalar i;
} renamenoise_twiddle_cpx;
#define RENAMENOISE_MAXFACTORS 8
// e.g. an fft of length 128 has 4 factors
// as far as renamenoisefft is concerned
// 4*4*4*2
typedef struct renamenoise_arch_fft_state {
int is_supported;
void *priv;
} renamenoise_arch_fft_state;
typedef struct renamenoise_fft_state {
int nfft;
renamenoise_val16 scale;
int shift;
renamenoise_int16 factors[2 * RENAMENOISE_MAXFACTORS];
const renamenoise_int16 *bitrev;
const renamenoise_twiddle_cpx *twiddles;
renamenoise_arch_fft_state *arch_fft;
} renamenoise_fft_state;
// typedef struct renamenoise_fft_state* renamenoise_fft_cfg;
/**
* renamenoise_fft_alloc
*
* Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
*
* typical usage: renamenoise_fft_cfg
* mycfg=renamenoise_fft_alloc(1024,0,NULL,NULL);
*
* The return value from fft_alloc is a cfg buffer used internally
* by the fft routine or NULL.
*
* If lenmem is NULL, then renamenoise_fft_alloc will allocate a cfg buffer
* using malloc. The returned value should be free()d when done to avoid memory
* leaks.
*
* The state can be placed in a user supplied buffer 'mem':
* If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
* then the function places the cfg in mem and the size used in *lenmem
* and returns mem.
*
* If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
* then the function returns NULL and places the minimum cfg
* buffer size in *lenmem.
*/
renamenoise_fft_state *renamenoise_fft_alloc_twiddles(int nfft, void *mem, size_t *lenmem, const renamenoise_fft_state *base, int arch);
renamenoise_fft_state *renamenoise_fft_alloc(int nfft, void *mem, size_t *lenmem, int arch);
/**
* renamenoise_fft(cfg,in_out_buf)
*
* Perform an FFT on a complex input buffer.
* for a forward FFT,
* fin should be f[0] , f[1] , ... ,f[nfft-1]
* fout will be F[0] , F[1] , ... ,F[nfft-1]
* Note that each element is complex and can be accessed like
* f[k].r and f[k].i
*/
void renamenoise_fft_c(const renamenoise_fft_state *cfg, const renamenoise_fft_cpx *fin, renamenoise_fft_cpx *fout);
void renamenoise_fft_impl(const renamenoise_fft_state *st, renamenoise_fft_cpx *fout);
void renamenoise_fft_free(const renamenoise_fft_state *cfg, int arch);
void renamenoise_fft_free_arch_c(renamenoise_fft_state *st);
int renamenoise_fft_alloc_arch_c(renamenoise_fft_state *st);
#if !defined(OVERRIDE_RENAMENOISE_FFT)
# define renamenoise_fft_alloc_arch(_st, arch) ((void) (arch), renamenoise_fft_alloc_arch_c(_st))
# define renamenoise_fft_free_arch(_st, arch) ((void) (arch), renamenoise_fft_free_arch_c(_st))
# define renamenoise_fft(_cfg, _fin, _fout, arch) ((void) (arch), renamenoise_fft_c(_cfg, _fin, _fout))
#endif /* end if !defined(OVERRIDE_RENAMENOISE_FFT) */
#ifdef __cplusplus
}
#endif
#endif /* RENAMENOISE_FFT_H */

View file

@ -0,0 +1,111 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2009-2010, Xiph.Org Foundation, Written by Jean-Marc Valin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "renamenoise_lpc.h"
#include "arch.h"
#include "common.h"
#include "pitch.h"
void _renamenoise_lpc(renamenoise_val16 *_lpc, // out: [0...p-1] LPC coefficients
const renamenoise_val32 *ac, // in: [0...p] autocorrelation values
int p) {
int i, j;
renamenoise_val32 r;
renamenoise_val32 error = ac[0];
float *lpc = _lpc;
RENAMENOISE_CLEAR(lpc, p);
if (ac[0] != 0) {
for (i = 0; i < p; i++) {
// Sum up this iteration's reflection coefficient
renamenoise_val32 rr = 0;
for (j = 0; j < i; j++) {
rr += RENAMENOISE_MULT(lpc[j], ac[i - j]);
}
rr += ac[i + 1];
r = -rr / error;
// Update LPC coefficients and total error
lpc[i] = r;
for (j = 0; j < ((i + 1) >> 1); j++) {
renamenoise_val32 tmp1, tmp2;
tmp1 = lpc[j];
tmp2 = lpc[i - 1 - j];
lpc[j] = tmp1 + RENAMENOISE_MULT(r, tmp2);
lpc[i - 1 - j] = tmp2 + RENAMENOISE_MULT(r, tmp1);
}
error = error - RENAMENOISE_MULT(RENAMENOISE_MULT(r, r), error);
// Bail out once we get 30 dB gain
if (error < .001f * ac[0]) {
break;
}
}
}
}
int _renamenoise_autocorr(const renamenoise_val16 *x, // in: [0...n-1] samples x
renamenoise_val32 *ac, // out: [0...lag-1] ac values
const renamenoise_val16 *window, int overlap, int lag, int n) {
renamenoise_val32 d;
int i, k;
int fastN = n - lag;
int shift;
const renamenoise_val16 *xptr;
renamenoise_stackalloc(renamenoise_val16, xx, n);
renamenoise_assert(n > 0);
renamenoise_assert(overlap >= 0);
if (overlap == 0) {
xptr = x;
} else {
for (i = 0; i < n; i++) {
xx[i] = x[i];
}
for (i = 0; i < overlap; i++) {
xx[i] = RENAMENOISE_MULT(x[i], window[i]);
xx[n - i - 1] = RENAMENOISE_MULT(x[n - i - 1], window[i]);
}
xptr = xx;
}
shift = 0;
renamenoise_pitch_xcorr(xptr, xptr, ac, fastN, lag + 1);
for (k = 0; k <= lag; k++) {
for (i = k + fastN, d = 0; i < n; i++) {
d = RENAMENOISE_MAC(d, xptr[i], xptr[i - k]);
}
ac[k] += d;
}
return shift;
}

View file

@ -0,0 +1,41 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2009-2010, Xiph.Org Foundation, Written by Jean-Marc Valin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RENAMENOISE_LPC_H
#define RENAMENOISE_LPC_H
#include "arch.h"
#include "common.h"
void _renamenoise_lpc(renamenoise_val16 *_lpc, const renamenoise_val32 *ac, int p);
int _renamenoise_autocorr(const renamenoise_val16 *x, renamenoise_val32 *ac, const renamenoise_val16 *window, int overlap, int lag, int n);
#endif /* RENAMENOISE_LPC_H */

View file

@ -0,0 +1,164 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 1994-2002, Xiph.Org Foundation, Modified by Jean-Marc Valin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// renamenoise_types.h based on opus_types.h based on ogg_types.h from libogg
/**
@file renamenoise_types.h
@brief Reference implementation types
*/
#ifndef RENAMENOISE_TYPES_H
#define RENAMENOISE_TYPES_H
// Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h)
#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) \
|| (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined(HAVE_STDINT_H))
# include <stdint.h>
typedef int16_t renamenoise_int16;
typedef uint16_t renamenoise_uint16;
typedef int32_t renamenoise_int32;
typedef uint32_t renamenoise_uint32;
#elif defined(_WIN32)
# if defined(__CYGWIN__)
# include <_G_config.h>
typedef _G_int32_t renamenoise_int32;
typedef _G_uint32_t renamenoise_uint32;
typedef _G_int16 renamenoise_int16;
typedef _G_uint16 renamenoise_uint16;
# elif defined(__MINGW32__)
typedef short renamenoise_int16;
typedef unsigned short renamenoise_uint16;
typedef int renamenoise_int32;
typedef unsigned int renamenoise_uint32;
# elif defined(__MWERKS__)
typedef int renamenoise_int32;
typedef unsigned int renamenoise_uint32;
typedef short renamenoise_int16;
typedef unsigned short renamenoise_uint16;
# else
// MSVC/Borland
typedef __int32 renamenoise_int32;
typedef unsigned __int32 renamenoise_uint32;
typedef __int16 renamenoise_int16;
typedef unsigned __int16 renamenoise_uint16;
# endif
#elif defined(__MACOS__)
# include <sys/types.h>
typedef SInt16 renamenoise_int16;
typedef UInt16 renamenoise_uint16;
typedef SInt32 renamenoise_int32;
typedef UInt32 renamenoise_uint32;
#elif (defined(__APPLE__) && defined(__MACH__)) // MacOS X Framework build
# include <sys/types.h>
typedef int16_t renamenoise_int16;
typedef u_int16_t renamenoise_uint16;
typedef int32_t renamenoise_int32;
typedef u_int32_t renamenoise_uint32;
#elif defined(__BEOS__)
// Be
# include <inttypes.h>
typedef int16 renamenoise_int16;
typedef u_int16 renamenoise_uint16;
typedef int32_t renamenoise_int32;
typedef u_int32_t renamenoise_uint32;
#elif defined(__EMX__)
// OS/2 GCC
typedef short renamenoise_int16;
typedef unsigned short renamenoise_uint16;
typedef int renamenoise_int32;
typedef unsigned int renamenoise_uint32;
#elif defined(DJGPP)
// DJGPP
typedef short renamenoise_int16;
typedef unsigned short renamenoise_uint16;
typedef int renamenoise_int32;
typedef unsigned int renamenoise_uint32;
#elif defined(R5900)
// PS2 EE
typedef int renamenoise_int32;
typedef unsigned renamenoise_uint32;
typedef short renamenoise_int16;
typedef unsigned short renamenoise_uint16;
#elif defined(__SYMBIAN32__)
// Symbian GCC
typedef signed short renamenoise_int16;
typedef unsigned short renamenoise_uint16;
typedef signed int renamenoise_int32;
typedef unsigned int renamenoise_uint32;
#elif defined(CONFIG_TI_C54X) || defined(CONFIG_TI_C55X)
typedef short renamenoise_int16;
typedef unsigned short renamenoise_uint16;
typedef long renamenoise_int32;
typedef unsigned long renamenoise_uint32;
#elif defined(CONFIG_TI_C6X)
typedef short renamenoise_int16;
typedef unsigned short renamenoise_uint16;
typedef int renamenoise_int32;
typedef unsigned int renamenoise_uint32;
#else
// Give up, take a reasonable guess
typedef short renamenoise_int16;
typedef unsigned short renamenoise_uint16;
typedef int renamenoise_int32;
typedef unsigned int renamenoise_uint32;
#endif
#define renamenoise_int int // used for counters etc; at least 16 bits
#define renamenoise_int64 long long
#define renamenoise_int8 signed char
#define renamenoise_uint unsigned int // used for counters etc; at least 16 bits
#define renamenoise_uint64 unsigned long long
#define renamenoise_uint8 unsigned char
#endif /* RENAMENOISE_TYPES_H */

238
thirdparty/renamenoise/src/rnn.c vendored Normal file
View file

@ -0,0 +1,238 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2012-2017, Jean-Marc Valin
Copyright (c) 2008-2011, Octasic Inc
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "rnn.h"
#include "arch.h"
#include "common.h"
#include "renamenoise_types.h"
#include "rnn_data.h"
#include "tansig_table.h"
#include <math.h>
#include <stdio.h>
static RENAMENOISE_INLINE float renamenoise_tansig_approx(float x) {
int i;
float y, dy;
float sign = 1;
// Tests are reversed to catch NaNs
if (!(x < 8)) {
return 1;
}
if (!(x > -8)) {
return -1;
}
// Another check in case of -ffast-math
if (renamenoise_isnan(x)) {
return 0;
}
if (x < 0) {
x = -x;
sign = -1;
}
i = (int) floor(.5f + 25 * x);
x -= .04f * i;
y = renamenoise_tansig_table[i];
dy = 1 - y * y;
y = y + x * dy * (1 - y * x);
return sign * y;
}
static RENAMENOISE_INLINE float renamenoise_sigmoid_approx(float x) {
return .5 + .5 * renamenoise_tansig_approx(.5 * x);
}
static RENAMENOISE_INLINE float renamenoise_relu(float x) {
return x < 0 ? 0 : x;
}
static void renamenoise_faxpy(float *restrict a, const renamenoise_rnn_weight *restrict b, const int k, const float u) {
if (u == 0.0) {
return;
}
for (int idx = 0; idx < k; idx++) {
a[idx] += b[idx] * u;
}
}
static void renamenoise_faxpy2(float *restrict a, const renamenoise_rnn_weight *restrict b, const int k, const float u, const float u2) {
if (u == 0.0 || u2 == 0.0) {
return;
}
for (int idx = 0; idx < k; idx++) {
a[idx] += (b[idx] * u) * u2;
}
}
void renamenoise_compute_dense(const ReNameNoiseDenseLayer *layer, float *output, const float *input) {
int i, j;
int N, M;
M = layer->nb_inputs;
N = layer->nb_neurons;
const renamenoise_rnn_weight *ip = layer->input_weights;
// Compute update gate.
for (i = 0; i < N; i++) {
output[i] = layer->bias[i];
}
for (j = 0; j < M; j++, ip += N) {
renamenoise_faxpy(output, ip, N, input[j]);
}
if (layer->activation == RENAMENOISE_ACTIVATION_SIGMOID) {
for (i = 0; i < N; i++) {
output[i] = renamenoise_sigmoid_approx(RENAMENOISE_WEIGHTS_SCALE * output[i]);
}
} else if (layer->activation == RENAMENOISE_ACTIVATION_TANH) {
for (i = 0; i < N; i++) {
output[i] = renamenoise_tansig_approx(RENAMENOISE_WEIGHTS_SCALE * output[i]);
}
} else if (layer->activation == RENAMENOISE_ACTIVATION_RELU) {
for (i = 0; i < N; i++) {
output[i] = renamenoise_relu(RENAMENOISE_WEIGHTS_SCALE * output[i]);
}
} else {
renamenoise_unreachable();
}
}
void renamenoise_compute_gru(const ReNameNoiseGRULayer *gru, float *state, const float *input) {
int i, j;
int N, M;
int stride;
float z[RENAMENOISE_MAX_NEURONS];
float r[RENAMENOISE_MAX_NEURONS];
float h[RENAMENOISE_MAX_NEURONS];
M = gru->nb_inputs;
N = gru->nb_neurons;
stride = 3 * N;
const renamenoise_rnn_weight *ip = gru->input_weights;
const renamenoise_rnn_weight *rp = gru->recurrent_weights;
// Compute update gate.
for (i = 0; i < N; i++) {
z[i] = gru->bias[i];
}
for (j = 0; j < M; j++, ip += stride) {
renamenoise_faxpy(z, ip, N, input[j]);
}
for (j = 0; j < N; j++, rp += stride) {
renamenoise_faxpy(z, rp, N, state[j]);
}
for (i = 0; i < N; i++) {
z[i] = renamenoise_sigmoid_approx(RENAMENOISE_WEIGHTS_SCALE * z[i]);
}
// Compute reset gate.
for (i = 0; i < N; i++) {
r[i] = gru->bias[N + i];
}
ip = gru->input_weights + N;
rp = gru->recurrent_weights + N;
for (j = 0; j < M; j++, ip += stride) {
renamenoise_faxpy(r, ip, N, input[j]);
}
for (j = 0; j < N; j++, rp += stride) {
renamenoise_faxpy(r, rp, N, state[j]);
}
for (i = 0; i < N; i++) {
r[i] = renamenoise_sigmoid_approx(RENAMENOISE_WEIGHTS_SCALE * r[i]);
}
// Compute output.
for (i = 0; i < N; i++) {
h[i] = gru->bias[2 * N + i];
}
ip = gru->input_weights + 2 * N;
rp = gru->recurrent_weights + 2 * N;
for (j = 0; j < M; j++, ip += stride) {
renamenoise_faxpy(h, ip, N, input[j]);
}
for (j = 0; j < N; j++, rp += stride) {
renamenoise_faxpy2(h, rp, N, state[j], r[j]);
}
for (i = 0; i < N; i++) {
if (gru->activation == RENAMENOISE_ACTIVATION_SIGMOID) {
h[i] = renamenoise_sigmoid_approx(RENAMENOISE_WEIGHTS_SCALE * h[i]);
} else if (gru->activation == RENAMENOISE_ACTIVATION_TANH) {
h[i] = renamenoise_tansig_approx(RENAMENOISE_WEIGHTS_SCALE * h[i]);
} else if (gru->activation == RENAMENOISE_ACTIVATION_RELU) {
h[i] = renamenoise_relu(RENAMENOISE_WEIGHTS_SCALE * h[i]);
} else {
renamenoise_unreachable();
}
h[i] = z[i] * state[i] + (1 - z[i]) * h[i];
}
memcpy((void *) state, (void *) h, N * sizeof(float));
}
#define RENAMENOISE_INPUT_SIZE 42
void renamenoise_compute_rnn(ReNameNoiseRNNState *rnn, float *gains, float *vad, const float *input) {
int i;
float dense_out[RENAMENOISE_MAX_NEURONS];
float noise_input[RENAMENOISE_MAX_NEURONS * 3];
float denoise_input[RENAMENOISE_MAX_NEURONS * 3];
renamenoise_compute_dense(rnn->model->input_dense, dense_out, input);
renamenoise_compute_gru(rnn->model->vad_gru, rnn->vad_gru_state, dense_out);
renamenoise_compute_dense(rnn->model->vad_output, vad, rnn->vad_gru_state);
for (i = 0; i < rnn->model->input_dense_size; i++) {
noise_input[i] = dense_out[i];
}
for (i = 0; i < rnn->model->vad_gru_size; i++) {
noise_input[i + rnn->model->input_dense_size] = rnn->vad_gru_state[i];
}
for (i = 0; i < RENAMENOISE_INPUT_SIZE; i++) {
noise_input[i + rnn->model->input_dense_size + rnn->model->vad_gru_size] = input[i];
}
renamenoise_compute_gru(rnn->model->noise_gru, rnn->noise_gru_state, noise_input);
for (i = 0; i < rnn->model->vad_gru_size; i++) {
denoise_input[i] = rnn->vad_gru_state[i];
}
for (i = 0; i < rnn->model->noise_gru_size; i++) {
denoise_input[i + rnn->model->vad_gru_size] = rnn->noise_gru_state[i];
}
for (i = 0; i < RENAMENOISE_INPUT_SIZE; i++) {
denoise_input[i + rnn->model->vad_gru_size + rnn->model->noise_gru_size] = input[i];
}
renamenoise_compute_gru(rnn->model->denoise_gru, rnn->denoise_gru_state, denoise_input);
renamenoise_compute_dense(rnn->model->denoise_output, gains, rnn->denoise_gru_state);
}

72
thirdparty/renamenoise/src/rnn.h vendored Normal file
View file

@ -0,0 +1,72 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2017, Jean-Marc Valin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RNN_H_
#define RNN_H_
#include "renamenoise.h"
#include "renamenoise_types.h"
#define RENAMENOISE_WEIGHTS_SCALE (1.f / 256)
#define RENAMENOISE_MAX_NEURONS 128
#define RENAMENOISE_ACTIVATION_TANH 0
#define RENAMENOISE_ACTIVATION_SIGMOID 1
#define RENAMENOISE_ACTIVATION_RELU 2
typedef signed char renamenoise_rnn_weight;
typedef struct {
const renamenoise_rnn_weight *bias;
const renamenoise_rnn_weight *input_weights;
int nb_inputs;
int nb_neurons;
int activation;
} ReNameNoiseDenseLayer;
typedef struct {
const renamenoise_rnn_weight *bias;
const renamenoise_rnn_weight *input_weights;
const renamenoise_rnn_weight *recurrent_weights;
int nb_inputs;
int nb_neurons;
int activation;
} ReNameNoiseGRULayer;
typedef struct ReNameNoiseRNNState ReNameNoiseRNNState;
void renamenoise_compute_dense(const ReNameNoiseDenseLayer *layer, float *output, const float *input);
void renamenoise_compute_gru(const ReNameNoiseGRULayer *gru, float *state, const float *input);
void renamenoise_compute_rnn(ReNameNoiseRNNState *rnn, float *gains, float *vad, const float *input);
#endif /* RNN_H_ */

3735
thirdparty/renamenoise/src/rnn_data.c vendored Normal file

File diff suppressed because it is too large Load diff

63
thirdparty/renamenoise/src/rnn_data.h vendored Normal file
View file

@ -0,0 +1,63 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2017, Xiph.Org Foundation, Jean-Marc Valin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef RNN_DATA_H
#define RNN_DATA_H
#include "rnn.h"
struct ReNameNoiseModel {
int input_dense_size;
const ReNameNoiseDenseLayer *input_dense;
int vad_gru_size;
const ReNameNoiseGRULayer *vad_gru;
int noise_gru_size;
const ReNameNoiseGRULayer *noise_gru;
int denoise_gru_size;
const ReNameNoiseGRULayer *denoise_gru;
int denoise_output_size;
const ReNameNoiseDenseLayer *denoise_output;
int vad_output_size;
const ReNameNoiseDenseLayer *vad_output;
};
struct ReNameNoiseRNNState {
const ReNameNoiseModel *model;
float *vad_gru_state;
float *noise_gru_state;
float *denoise_gru_state;
};
#endif /* RNN_DATA_H */

179
thirdparty/renamenoise/src/rnn_reader.c vendored Normal file
View file

@ -0,0 +1,179 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2018, Gregor Richards
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "renamenoise.h"
#include "rnn.h"
#include "rnn_data.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
// Although these values are the same as in rnn.h, we make them separate to
// avoid accidentally burning internal values into a file format
#define F_RENAMENOISE_ACTIVATION_TANH 0
#define F_RENAMENOISE_ACTIVATION_SIGMOID 1
#define F_RENAMENOISE_ACTIVATION_RELU 2
ReNameNoiseModel *renamenoise_model_from_file(FILE *f) {
int i, in;
if (fscanf(f, "renamenoise-nu model file version %d\n", &in) != 1 || in != 1) {
return NULL;
}
ReNameNoiseModel *ret = calloc(1, sizeof(ReNameNoiseModel));
if (!ret) {
return NULL;
}
#define RENAMENOISE_ALLOC_LAYER(type, name) \
type *name; \
name = calloc(1, sizeof(type)); \
if (!name) { \
renamenoise_model_free(ret); \
return NULL; \
} \
ret->name = name
RENAMENOISE_ALLOC_LAYER(ReNameNoiseDenseLayer, input_dense);
RENAMENOISE_ALLOC_LAYER(ReNameNoiseGRULayer, vad_gru);
RENAMENOISE_ALLOC_LAYER(ReNameNoiseGRULayer, noise_gru);
RENAMENOISE_ALLOC_LAYER(ReNameNoiseGRULayer, denoise_gru);
RENAMENOISE_ALLOC_LAYER(ReNameNoiseDenseLayer, denoise_output);
RENAMENOISE_ALLOC_LAYER(ReNameNoiseDenseLayer, vad_output);
#define RENAMENOISE_INPUT_VAL(name) \
do { \
if (fscanf(f, "%d", &in) != 1 || in < 0 || in > 128) { \
renamenoise_model_free(ret); \
return NULL; \
} \
name = in; \
} while (0)
#define RENAMENOISE_INPUT_ACTIVATION(name) \
do { \
int activation; \
RENAMENOISE_INPUT_VAL(activation); \
switch (activation) { \
case F_RENAMENOISE_ACTIVATION_SIGMOID: name = RENAMENOISE_ACTIVATION_SIGMOID; break; \
case F_RENAMENOISE_ACTIVATION_RELU: name = RENAMENOISE_ACTIVATION_RELU; break; \
default: name = RENAMENOISE_ACTIVATION_TANH; \
} \
} while (0)
#define RENAMENOISE_INPUT_ARRAY(name, len) \
do { \
renamenoise_rnn_weight *values = malloc((len) * sizeof(renamenoise_rnn_weight)); \
if (!values) { \
renamenoise_model_free(ret); \
return NULL; \
} \
name = values; \
for (i = 0; i < (len); i++) { \
if (fscanf(f, "%d", &in) != 1) { \
renamenoise_model_free(ret); \
return NULL; \
} \
values[i] = in; \
} \
} while (0)
#define RENAMENOISE_INPUT_DENSE(name) \
do { \
RENAMENOISE_INPUT_VAL(name->nb_inputs); \
RENAMENOISE_INPUT_VAL(name->nb_neurons); \
ret->name##_size = name->nb_neurons; \
RENAMENOISE_INPUT_ACTIVATION(name->activation); \
RENAMENOISE_INPUT_ARRAY(name->input_weights, name->nb_inputs * name->nb_neurons); \
RENAMENOISE_INPUT_ARRAY(name->bias, name->nb_neurons); \
} while (0)
#define RENAMENOISE_INPUT_GRU(name) \
do { \
RENAMENOISE_INPUT_VAL(name->nb_inputs); \
RENAMENOISE_INPUT_VAL(name->nb_neurons); \
ret->name##_size = name->nb_neurons; \
RENAMENOISE_INPUT_ACTIVATION(name->activation); \
RENAMENOISE_INPUT_ARRAY(name->input_weights, name->nb_inputs * name->nb_neurons * 3); \
RENAMENOISE_INPUT_ARRAY(name->recurrent_weights, name->nb_neurons * name->nb_neurons * 3); \
RENAMENOISE_INPUT_ARRAY(name->bias, name->nb_neurons * 3); \
} while (0)
RENAMENOISE_INPUT_DENSE(input_dense);
RENAMENOISE_INPUT_GRU(vad_gru);
RENAMENOISE_INPUT_GRU(noise_gru);
RENAMENOISE_INPUT_GRU(denoise_gru);
RENAMENOISE_INPUT_DENSE(denoise_output);
RENAMENOISE_INPUT_DENSE(vad_output);
return ret;
}
void renamenoise_model_free(ReNameNoiseModel *model) {
#define RENAMENOISE_FREE_MAYBE(ptr) \
do { \
if (ptr) \
free(ptr); \
} while (0)
#define RENAMENOISE_FREE_DENSE(name) \
do { \
if (model->name) { \
free((void *) model->name->input_weights); \
free((void *) model->name->bias); \
free((void *) model->name); \
} \
} while (0)
#define RENAMENOISE_FREE_GRU(name) \
do { \
if (model->name) { \
free((void *) model->name->input_weights); \
free((void *) model->name->recurrent_weights); \
free((void *) model->name->bias); \
free((void *) model->name); \
} \
} while (0)
if (!model) {
return;
}
RENAMENOISE_FREE_DENSE(input_dense);
RENAMENOISE_FREE_GRU(vad_gru);
RENAMENOISE_FREE_GRU(noise_gru);
RENAMENOISE_FREE_GRU(denoise_gru);
RENAMENOISE_FREE_DENSE(denoise_output);
RENAMENOISE_FREE_DENSE(vad_output);
free(model);
}

94
thirdparty/renamenoise/src/rnn_train.py vendored Executable file
View file

@ -0,0 +1,94 @@
#!/usr/bin/python
#
# Copyright (c) 2017, Jean-Marc Valin
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
from __future__ import print_function
from keras.models import Sequential
from keras.models import Model
from keras.layers import Input
from keras.layers import Dense
from keras.layers import LSTM
from keras.layers import GRU
from keras.layers import SimpleRNN
from keras.layers import Dropout
from keras import losses
import h5py
from keras import backend as K
import numpy as np
print('Build model...')
main_input = Input(shape=(None, 22), name='main_input')
#x = Dense(44, activation='relu')(main_input)
#x = GRU(44, dropout=0.0, recurrent_dropout=0.0, activation='tanh', recurrent_activation='sigmoid', return_sequences=True)(x)
x=main_input
x = GRU(128, activation='tanh', recurrent_activation='sigmoid', return_sequences=True)(x)
#x = GRU(128, return_sequences=True)(x)
#x = GRU(22, activation='relu', return_sequences=True)(x)
x = Dense(22, activation='sigmoid')(x)
#x = Dense(22, activation='softplus')(x)
model = Model(inputs=main_input, outputs=x)
batch_size = 32
print('Loading data...')
with h5py.File('denoise_data.h5', 'r') as hf:
all_data = hf['denoise_data'][:]
print('done.')
window_size = 500
nb_sequences = len(all_data)//window_size
print(nb_sequences, ' sequences')
x_train = all_data[:nb_sequences*window_size, :-22]
x_train = np.reshape(x_train, (nb_sequences, window_size, 22))
y_train = np.copy(all_data[:nb_sequences*window_size, -22:])
y_train = np.reshape(y_train, (nb_sequences, window_size, 22))
#y_train = -20*np.log10(np.add(y_train, .03));
all_data = 0;
x_train = x_train.astype('float32')
y_train = y_train.astype('float32')
print(len(x_train), 'train sequences. x shape =', x_train.shape, 'y shape = ', y_train.shape)
# try using different optimizers and different optimizer configs
model.compile(loss='mean_squared_error',
optimizer='adam',
metrics=['binary_accuracy'])
print('Train...')
model.fit(x_train, y_train,
batch_size=batch_size,
epochs=200,
validation_data=(x_train, y_train))
model.save("newweights.hdf5")

View file

@ -0,0 +1,55 @@
/*
Copyright (c) 2024, The Mumble Developers
Copyright (c) 2017, Jean-Marc Valin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* This file is auto-generated by gen_tables */
#ifndef TANSIG_TABLE_H
#define TANSIG_TABLE_H
static const float renamenoise_tansig_table[201] = {
0.000000f, 0.039979f, 0.079830f, 0.119427f, 0.158649f, 0.197375f, 0.235496f, 0.272905f, 0.309507f, 0.345214f, 0.379949f, 0.413644f, 0.446244f,
0.477700f, 0.507977f, 0.537050f, 0.564900f, 0.591519f, 0.616909f, 0.641077f, 0.664037f, 0.685809f, 0.706419f, 0.725897f, 0.744277f, 0.761594f,
0.777888f, 0.793199f, 0.807569f, 0.821040f, 0.833655f, 0.845456f, 0.856485f, 0.866784f, 0.876393f, 0.885352f, 0.893698f, 0.901468f, 0.908698f,
0.915420f, 0.921669f, 0.927473f, 0.932862f, 0.937863f, 0.942503f, 0.946806f, 0.950795f, 0.954492f, 0.957917f, 0.961090f, 0.964028f, 0.966747f,
0.969265f, 0.971594f, 0.973749f, 0.975743f, 0.977587f, 0.979293f, 0.980869f, 0.982327f, 0.983675f, 0.984921f, 0.986072f, 0.987136f, 0.988119f,
0.989027f, 0.989867f, 0.990642f, 0.991359f, 0.992020f, 0.992631f, 0.993196f, 0.993718f, 0.994199f, 0.994644f, 0.995055f, 0.995434f, 0.995784f,
0.996108f, 0.996407f, 0.996682f, 0.996937f, 0.997172f, 0.997389f, 0.997590f, 0.997775f, 0.997946f, 0.998104f, 0.998249f, 0.998384f, 0.998508f,
0.998623f, 0.998728f, 0.998826f, 0.998916f, 0.999000f, 0.999076f, 0.999147f, 0.999213f, 0.999273f, 0.999329f, 0.999381f, 0.999428f, 0.999472f,
0.999513f, 0.999550f, 0.999585f, 0.999617f, 0.999646f, 0.999673f, 0.999699f, 0.999722f, 0.999743f, 0.999763f, 0.999781f, 0.999798f, 0.999813f,
0.999828f, 0.999841f, 0.999853f, 0.999865f, 0.999875f, 0.999885f, 0.999893f, 0.999902f, 0.999909f, 0.999916f, 0.999923f, 0.999929f, 0.999934f,
0.999939f, 0.999944f, 0.999948f, 0.999952f, 0.999956f, 0.999959f, 0.999962f, 0.999965f, 0.999968f, 0.999970f, 0.999973f, 0.999975f, 0.999977f,
0.999978f, 0.999980f, 0.999982f, 0.999983f, 0.999984f, 0.999986f, 0.999987f, 0.999988f, 0.999989f, 0.999990f, 0.999990f, 0.999991f, 0.999992f,
0.999992f, 0.999993f, 0.999994f, 0.999994f, 0.999994f, 0.999995f, 0.999995f, 0.999996f, 0.999996f, 0.999996f, 0.999997f, 0.999997f, 0.999997f,
0.999997f, 0.999997f, 0.999998f, 0.999998f, 0.999998f, 0.999998f, 0.999998f, 0.999998f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f,
0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
};
#endif /* TANSIG_TABLE_H */