@@ -124,6 +124,18 @@ static int rnnoise_get_audio(mlt_frame frame,
124124 const int rnn_frame = rnnoise_get_frame_size (); // always 480
125125 mlt_position frame_pos = mlt_frame_get_position (frame );
126126
127+ if (ch > MAX_CHANNELS ) {
128+ mlt_log_warning (MLT_FILTER_SERVICE (filter ),
129+ "RNNoise filter supports up to %d channels, got %d; bypassing\n" ,
130+ MAX_CHANNELS ,
131+ ch );
132+ pdata -> expected_frame = frame_pos + 1 ;
133+ pdata -> n_channels = ch ;
134+ pdata -> frequency = * frequency ;
135+ mlt_service_unlock (MLT_FILTER_SERVICE (filter ));
136+ return 0 ;
137+ }
138+
127139 // Detect format change or seek discontinuity -> full reset
128140 if (pdata -> n_channels != ch || pdata -> frequency != * frequency
129141 || pdata -> expected_frame != frame_pos ) {
@@ -146,10 +158,7 @@ static int rnnoise_get_audio(mlt_frame frame,
146158 }
147159
148160 double mix = mlt_properties_get_double (filter_props , "mix" );
149- if (mix < 0.0 )
150- mix = 0.0 ;
151- if (mix > 1.0 )
152- mix = 1.0 ;
161+ mix = CLAMP (mix , 0.0 , 1.0 );
153162
154163 // ------------------------------------------------------------------
155164 // Algorithm: input-carry + output-carry
@@ -264,6 +273,7 @@ static int rnnoise_get_audio(mlt_frame frame,
264273 // [0 .. in_carry_count) → pdata->in_carry[c]
265274 // [in_carry_count .. total) → in_ch
266275 int in_virtual = - pad ; // starts in the silence region on first frame
276+ int missing_state_logged = 0 ;
267277
268278 for (int k = 0 ; k < n_chunks ; k ++ ) {
269279 // Build one rnn_frame-sample input
@@ -280,7 +290,17 @@ static int rnnoise_get_audio(mlt_frame frame,
280290 }
281291 frame_in [s ] = val ;
282292 }
283- rnnoise_process_frame (pdata -> states [c ], frame_out , frame_in );
293+ if (pdata -> states [c ]) {
294+ rnnoise_process_frame (pdata -> states [c ], frame_out , frame_in );
295+ } else {
296+ if (!missing_state_logged ) {
297+ mlt_log_error (MLT_FILTER_SERVICE (filter ),
298+ "Missing RNNoise state for channel %d; bypassing denoise\n" ,
299+ c );
300+ missing_state_logged = 1 ;
301+ }
302+ memcpy (frame_out , frame_in , sizeof (frame_out ));
303+ }
284304
285305 // Distribute output to out_ch or out_carry
286306 for (int s = 0 ; s < rnn_frame ; s ++ ) {
@@ -326,11 +346,15 @@ static int rnnoise_get_audio(mlt_frame frame,
326346 for (int s = 0 ; s < new_in_carry ; s ++ )
327347 pdata -> in_carry [c ][s ] = in_ch [in_carry_src + s ];
328348
349+ if (out_pos < n_samples ) {
350+ memset (out_ch + out_pos , 0 , (size_t ) (n_samples - out_pos ) * sizeof (float ));
351+ }
352+
329353 if (c == 0 ) {
330354 if (out_pos != n_samples )
331355 mlt_log_warning (MLT_FILTER_SERVICE (filter ),
332356 "frame=%d ch=%d output not fully filled: "
333- "out_pos=%d n_samples=%d (gap=%d)\n" ,
357+ "out_pos=%d n_samples=%d (gap=%d), zero-filled \n" ,
334358 (int ) frame_pos ,
335359 c ,
336360 out_pos ,
@@ -339,6 +363,9 @@ static int rnnoise_get_audio(mlt_frame frame,
339363 new_in_carry_count = new_in_carry ;
340364 new_out_carry_count = carry_pos ;
341365 }
366+
367+ // Keep ring position bounded to prevent long-run integer overflow.
368+ pdata -> dry_ring_pos %= ring_size ;
342369 }
343370
344371 pdata -> in_carry_count = new_in_carry_count ;
0 commit comments