77
88#include < rnnoise/rnnoise.h>
99
10- void RnNoiseCommonPlugin::init () {
11- deinit ();
12- createDenoiseState ();
10+ RnNoiseCommonPlugin::RnNoiseCommonPlugin () :
11+ m_errorStr (NULL ),
12+ m_initialized(false ),
13+ m_resample (false )
14+ {
1315}
1416
15- void RnNoiseCommonPlugin::deinit () {
16- m_denoiseState.reset ();
17+ void RnNoiseCommonPlugin::setSampleRate (unsigned long sampleRate)
18+ {
19+ m_downRatio = (double )k_denoiseSampleRate / (double )sampleRate;
20+ m_upRatio = (double )sampleRate / (double )k_denoiseSampleRate;
21+ m_resample = sampleRate != 48000 ;
1722}
1823
19- void RnNoiseCommonPlugin::process (const float *in, float *out, int32_t sampleFrames) {
20- if (sampleFrames == 0 ) {
21- return ;
22- }
23-
24- if (!m_denoiseState) {
25- createDenoiseState ();
26- }
24+ bool RnNoiseCommonPlugin::init () {
25+ int err;
2726
28- // Good case, we can copy less data around and rnnoise lib is built for it
29- if (sampleFrames == k_denoiseFrameSize) {
30- m_inputBuffer.resize (sampleFrames);
27+ if (m_initialized)
28+ deinit ();
3129
32- for (size_t i = 0 ; i < sampleFrames; i++) {
33- m_inputBuffer[i] = in[i] * std::numeric_limits<short >::max ();
34- }
30+ m_srcIn = std::shared_ptr<SRC_STATE>(
31+ src_new (SRC_SINC_BEST_QUALITY, 1 , &err),
32+ [](SRC_STATE *st)
33+ {
34+ src_delete (st);
35+ }
36+ );
37+
38+ if (err)
39+ {
40+ m_errorStr = src_strerror (err);
41+ return false ;
42+ }
43+
44+ m_srcOut = std::shared_ptr<SRC_STATE>(
45+ src_new (SRC_SINC_BEST_QUALITY, 1 , &err),
46+ [](SRC_STATE *st)
47+ {
48+ src_delete (st);
49+ }
50+ );
51+
52+ if (err)
53+ {
54+ m_srcIn.reset ();
55+ m_errorStr = src_strerror (err);
56+ return false ;
57+ }
58+
59+ m_denoiseState = std::shared_ptr<DenoiseState>(
60+ rnnoise_create (),
61+ [](DenoiseState *st)
62+ {
63+ rnnoise_destroy (st);
64+ }
65+ );
3566
36- rnnoise_process_frame (m_denoiseState.get (), out, &m_inputBuffer[0 ]);
67+ src_set_ratio (m_srcIn.get (), m_downRatio);
68+ src_set_ratio (m_srcOut .get (), m_upRatio );
3769
38- for ( size_t i = 0 ; i < sampleFrames; i++) {
39- out[i] /= std::numeric_limits< short >:: max ( );
40- }
41- } else {
42- m_inputBuffer. resize (m_inputBuffer. size () + sampleFrames) ;
70+ m_inBuffer . resize (k_denoiseFrameSize);
71+ m_outBuffer. resize (k_denoiseFrameSize * 2 );
72+ m_outBufferR = 0 ;
73+ m_outBufferW = 0 ;
74+ m_outBufferA = 0 ;
4375
44- // From [-1.f,1.f] range to [min short, max short] range which rnnoise lib will understand
45- {
46- float *inputBufferWriteStart = (m_inputBuffer.end () - sampleFrames).base ();
47- for (size_t i = 0 ; i < sampleFrames; i++) {
48- inputBufferWriteStart[i] = in[i] * std::numeric_limits<short >::max ();
49- }
50- }
76+ m_initialized = true ;
77+ m_errorStr = NULL ;
78+ return true ;
79+ }
5180
52- const size_t samplesToProcess = m_inputBuffer.size () / k_denoiseFrameSize;
53- const size_t framesToProcess = samplesToProcess * k_denoiseFrameSize;
81+ void RnNoiseCommonPlugin::deinit () {
82+ m_denoiseState.reset ();
83+ m_srcIn .reset ();
84+ m_srcOut .reset ();
85+ m_initialized = false ;
86+ }
5487
55- m_outputBuffer.resize (m_outputBuffer.size () + framesToProcess);
88+ void RnNoiseCommonPlugin::process (const float *in, float *out, int32_t sampleFrames)
89+ {
90+ const float mul = 1 .0f / std::numeric_limits<short >::max ();
91+ if (!sampleFrames)
92+ return ;
93+
94+ if (!m_initialized)
95+ init ();
96+
97+ SRC_DATA srcIn;
98+ srcIn.data_in = in;
99+ srcIn.input_frames = sampleFrames;
100+ srcIn.end_of_input = 0 ;
101+ srcIn.src_ratio = m_downRatio;
102+ srcIn.data_out = &m_inBuffer[0 ];
103+ srcIn.output_frames = m_inBuffer.size ();
104+
105+ SRC_DATA srcOut;
106+ srcOut.data_out = out;
107+ srcOut.output_frames = sampleFrames;
108+ srcOut.end_of_input = 0 ;
109+ srcOut.src_ratio = m_upRatio;
110+
111+ long frames = 0 ;
112+ while (srcIn.input_frames )
113+ {
114+ if (m_resample)
115+ {
116+ // resample the samples and then scale them
117+ src_process (m_srcIn.get (), &srcIn);
118+ for (long i = 0 ; i < srcIn.output_frames_gen ; ++i)
119+ m_inBuffer[i] *= std::numeric_limits<short >::max ();
120+ }
121+ else
122+ {
123+ // just copy the data and scale it
124+ srcIn.input_frames_used = srcIn.input_frames ;
125+ if (srcIn.input_frames_used > srcIn.output_frames )
126+ srcIn.input_frames_used = srcIn.output_frames ;
127+ srcIn.output_frames_gen = srcIn.input_frames_used ;
128+
129+ for (long i = 0 ; i < srcIn.output_frames_gen ; ++i)
130+ m_inBuffer[i] = in[i] * std::numeric_limits<short >::max ();
131+ }
56132
57- // Process input buffer by chunks of k_denoiseFrameSize, put result into out buffer to return into range [-1.f,1.f]
133+ srcIn.data_in += srcIn.input_frames_used ;
134+ srcIn.input_frames -= srcIn.input_frames_used ;
135+
136+ float *denoise_in = &m_inBuffer[0 ];
137+ while (srcIn.output_frames_gen )
138+ {
139+ const int wrote = rnnoise_add_samples (m_denoiseState.get (), denoise_in, srcIn.output_frames_gen );
140+ denoise_in += wrote;
141+ srcIn.output_frames_gen -= wrote;
142+
143+ if (rnnoise_get_needed (m_denoiseState.get ()) == 0 )
144+ {
145+ rnnoise_process_frame (m_denoiseState.get (), &m_outBuffer[m_outBufferW]);
146+
147+ // scale the levels back to normal
148+ for (int32_t i = 0 ; i < k_denoiseFrameSize; ++i)
149+ m_outBuffer[m_outBufferW + i] *= mul;
150+
151+ m_outBufferW += k_denoiseFrameSize;
152+ m_outBufferA += k_denoiseFrameSize;
153+ if (m_outBufferW == m_outBuffer.size ())
154+ m_outBufferW = 0 ;
155+ }
156+
157+ // resample what we can to the output
158+ while (m_outBufferA && srcOut.output_frames )
159+ {
160+ srcOut.data_in = &m_outBuffer[m_outBufferR];
161+ srcOut.input_frames = m_outBufferW < m_outBufferR ? m_outBuffer.size () - m_outBufferR : m_outBufferW - m_outBufferR;
162+
163+ if (m_resample)
164+ src_process (m_srcOut.get (), &srcOut);
165+ else
58166 {
59- float *outBufferWriteStart = (m_outputBuffer.end () - framesToProcess).base ();
60-
61- for (size_t i = 0 ; i < samplesToProcess; i++) {
62- float *currentOutBuffer = &outBufferWriteStart[i * k_denoiseFrameSize];
63- float *currentInBuffer = &m_inputBuffer[i * k_denoiseFrameSize];
64- rnnoise_process_frame (m_denoiseState.get (), currentOutBuffer, currentInBuffer);
65-
66- for (size_t j = 0 ; j < k_denoiseFrameSize; j++) {
67- currentOutBuffer[j] /= std::numeric_limits<short >::max ();
68- }
69- }
167+ // simply copy the buffer if we are not resampling
168+ srcOut.input_frames_used = srcOut.input_frames ;
169+ if (srcOut.input_frames_used > srcOut.output_frames )
170+ srcOut.input_frames_used = srcOut.output_frames ;
171+ memcpy (srcOut.data_out , srcOut.data_in , srcOut.input_frames_used * sizeof (float ));
70172 }
71173
72- const size_t toCopyIntoOutput = std::min (m_outputBuffer.size (), static_cast <size_t >(sampleFrames));
174+ if (!srcOut.input_frames_used && !srcOut.output_frames_gen )
175+ break ;
73176
74- std::memcpy (out, &m_outputBuffer[0 ], toCopyIntoOutput * sizeof (float ));
177+ m_outBufferR += srcOut.input_frames_used ;
178+ m_outBufferA -= srcOut.input_frames_used ;
75179
76- m_inputBuffer.erase (m_inputBuffer.begin (), m_inputBuffer.begin () + framesToProcess);
77- m_outputBuffer.erase (m_outputBuffer.begin (), m_outputBuffer.begin () + toCopyIntoOutput);
180+ srcOut.data_out += srcOut.output_frames_gen ;
181+ srcOut.output_frames -= srcOut.output_frames_gen ;
182+ frames += srcOut.output_frames_gen ;
78183
79- if (toCopyIntoOutput < sampleFrames) {
80- std::fill (out + toCopyIntoOutput, out + sampleFrames, 0 . f ) ;
81- }
184+ if (m_outBufferR == m_outBuffer. size ())
185+ m_outBufferR = 0 ;
186+ }
82187 }
83- }
84-
85- void RnNoiseCommonPlugin::createDenoiseState () {
86- m_denoiseState = std::shared_ptr<DenoiseState>(rnnoise_create (), [](DenoiseState *st) {
87- rnnoise_destroy (st);
88- });
188+ }
189+
190+ // if we generated less frames then wanted, pad them across to the right
191+ if (frames && frames < sampleFrames)
192+ {
193+ const size_t pad = sampleFrames - frames;
194+ memmove (out + pad, out, frames);
195+ memset (out, 0 , pad);
196+ }
89197}
0 commit comments