-
Notifications
You must be signed in to change notification settings - Fork 0
/
noise_reducer.go
121 lines (104 loc) · 3.26 KB
/
noise_reducer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package caress
/*
#cgo pkg-config: rnnoise-nu
#include <stdio.h>
#include <math.h>
#include "rnnoise-nu.h"
DenoiseState *create_rnnoise(){
return rnnoise_create(NULL);
}
DenoiseState *create_rnnoise_with(const char *name){
RNNModel *model = NULL;
model = rnnoise_get_model(name);
return rnnoise_create(model);
}
void process_frame_float(DenoiseState *state, int frameSize, float *out, const float *in){
for (int i = 0; i < frameSize; i++) out[i] *= 0x7fff;
rnnoise_process_frame(state, out, in);
for (int i = 0; i < frameSize; i++) out[i] /= 0x7fff;
}
void process_frame(DenoiseState *state, int frameSize, short *out, const short *in){
float x[frameSize];
for (int i=0;i<frameSize;i++) x[i] = in[i];
rnnoise_process_frame(state, x, x);
for (int i=0;i<frameSize;i++) out[i] = x[i];
}
void setup(DenoiseState *state, double attenuation, int sampleRate){
int sample_rate = sampleRate;
float max_attenuation = pow(10, -attenuation/10);
rnnoise_set_param(state, RNNOISE_PARAM_MAX_ATTENUATION, max_attenuation);
rnnoise_set_param(state, RNNOISE_PARAM_SAMPLE_RATE, sample_rate);
}
void set_max_attenuation(DenoiseState *state, double attenuation){
float max_attenuation = pow(10, -attenuation/10);
rnnoise_set_param(state, RNNOISE_PARAM_MAX_ATTENUATION, max_attenuation);
}
*/
import "C"
import (
"unsafe"
)
type NoiseReducer struct {
rnnStates []*C.DenoiseState
numChannels int
sampleRate uint32
attenuationDB float64
}
func NewNoiseReducer(numChannels int, sampleRate uint32, attenuationDB float64, model RnnoiseModel) *NoiseReducer {
states := []*C.DenoiseState{}
var state *C.DenoiseState
for i := 0; i < numChannels; i++ {
if model == RnnoiseModelNone {
state = C.create_rnnoise()
} else {
state = C.create_rnnoise_with(C.CString(string(model)))
}
C.setup(state, C.double(attenuationDB), C.int(sampleRate))
states = append(states, state)
}
return &NoiseReducer{
rnnStates: states,
numChannels: numChannels,
sampleRate: sampleRate,
attenuationDB: attenuationDB,
}
}
func (r *NoiseReducer) ProcessFrame(frame []int16, channel int) {
if len(frame) == 0 || len(r.rnnStates) == 0 {
return
}
C.process_frame(r.rnnStates[channel], C.int(len(frame)), (*C.short)(unsafe.Pointer(&frame[0])), (*C.short)(unsafe.Pointer(&frame[0])))
}
func (r *NoiseReducer) ProcessFrameFloat(frame []float32, channel int) {
if len(frame) == 0 || len(r.rnnStates) == 0 {
return
}
C.process_frame_float(r.rnnStates[channel], C.int(len(frame)), (*C.float)(&frame[0]), (*C.float)(&frame[0]))
}
func (r *NoiseReducer) SetAttenuationDB(attenuationDB float64) {
r.attenuationDB = attenuationDB
for _, state := range r.rnnStates {
C.set_max_attenuation(state, C.double(attenuationDB))
}
}
func (r *NoiseReducer) ChangeRnnModel(model RnnoiseModel) {
states := []*C.DenoiseState{}
var state *C.DenoiseState
for i := 0; i < r.numChannels; i++ {
if model == RnnoiseModelNone {
state = C.create_rnnoise()
} else {
state = C.create_rnnoise_with(C.CString(string(model)))
}
C.setup(state, C.double(r.attenuationDB), C.int(r.sampleRate))
states = append(states, state)
}
r.Destroy()
r.rnnStates = states
}
func (r *NoiseReducer) Destroy() {
for _, state := range r.rnnStates {
C.rnnoise_destroy(state)
}
r.rnnStates = []*C.DenoiseState{}
}