Skip to main content

rusty_opus/silk/
enc_api.rs

1use crate::range_coder::RangeCoder;
2use crate::silk::control_fixed::*;
3use crate::silk::control_snr::silk_control_snr;
4use crate::silk::define::*;
5use crate::silk::encode_indices::*;
6use crate::silk::encode_pulses::*;
7use crate::silk::gain_quant::{silk_gains_id, silk_gains_quant};
8use crate::silk::hp_variable_cutoff::silk_hp_variable_cutoff;
9use crate::silk::lp_variable_cutoff::*;
10use crate::silk::macros::*;
11use crate::silk::noise_shape_analysis::*;
12use crate::silk::nsq::*;
13use crate::silk::nsq_del_dec::*;
14use crate::silk::pitch_analysis::*;
15use crate::silk::structs::*;
16use crate::silk::vad::silk_vad_get_sa_q8;
17
18pub fn silk_encode_do_vad(ps_enc: &mut SilkEncoderState, input: &[i16], activity: i32) {
19    let activity_threshold = SPEECH_ACTIVITY_DTX_THRES_Q8;
20
21    let frame_length = ps_enc.s_cmn.frame_length as usize;
22    silk_vad_get_sa_q8(ps_enc, input, frame_length);
23
24    if activity == 0 && ps_enc.s_cmn.speech_activity_q8 >= activity_threshold {
25        ps_enc.s_cmn.speech_activity_q8 = activity_threshold - 1;
26    }
27
28    if ps_enc.s_cmn.speech_activity_q8 < activity_threshold {
29        ps_enc.s_cmn.indices.signal_type = TYPE_NO_VOICE_ACTIVITY as i8;
30        ps_enc.s_cmn.no_speech_counter += 1;
31        if ps_enc.s_cmn.no_speech_counter <= NB_SPEECH_FRAMES_BEFORE_DTX {
32            ps_enc.s_cmn.in_dtx = 0;
33        } else if ps_enc.s_cmn.no_speech_counter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX
34        {
35            ps_enc.s_cmn.no_speech_counter = NB_SPEECH_FRAMES_BEFORE_DTX;
36            ps_enc.s_cmn.in_dtx = 0;
37        }
38        ps_enc.s_cmn.vad_flags[ps_enc.s_cmn.n_frames_encoded as usize] = 0;
39    } else {
40        ps_enc.s_cmn.no_speech_counter = 0;
41        ps_enc.s_cmn.in_dtx = 0;
42        ps_enc.s_cmn.indices.signal_type = TYPE_UNVOICED as i8;
43        ps_enc.s_cmn.vad_flags[ps_enc.s_cmn.n_frames_encoded as usize] = 1;
44    }
45}
46
47pub fn silk_encode_prefill(ps_enc: &mut SilkEncoderState, samples: &[i16], _activity: i32) {
48    let fs_khz = ps_enc.s_cmn.fs_khz as usize;
49
50    if fs_khz != 8 && fs_khz != 12 && fs_khz != 16 {
51        return;
52    }
53
54    let prefill_frame_length = fs_khz * 10;
55
56    if samples.len() < prefill_frame_length {
57        return;
58    }
59
60    let real_frame_length = ps_enc.s_cmn.frame_length as usize;
61    let real_nb_subfr = ps_enc.s_cmn.nb_subfr;
62    let real_subfr_length = ps_enc.s_cmn.subfr_length;
63
64    ps_enc.s_cmn.frame_length = prefill_frame_length as i32;
65    ps_enc.s_cmn.nb_subfr = 2;
66    ps_enc.s_cmn.subfr_length = (prefill_frame_length / 2) as i32;
67
68    let ltp_mem_length = ps_enc.s_cmn.ltp_mem_length as usize;
69    let la_shape_ms_samples = 5 * fs_khz;
70
71    let n = prefill_frame_length.min(samples.len());
72
73    let mut input_buf = [0i16; super::define::MAX_FRAME_LENGTH + 2];
74    input_buf[0] = ps_enc.stereo.s_mid[0];
75    input_buf[1] = ps_enc.stereo.s_mid[1];
76    input_buf[2..2 + n].copy_from_slice(&samples[..n]);
77    ps_enc.stereo.s_mid[0] = input_buf[prefill_frame_length];
78    ps_enc.stereo.s_mid[1] = input_buf[prefill_frame_length + 1];
79
80    silk_lp_variable_cutoff(
81        &mut ps_enc.s_cmn.s_lp,
82        &mut input_buf[1..],
83        prefill_frame_length,
84    );
85
86    let x_frame_idx = ltp_mem_length;
87    let dst = x_frame_idx + la_shape_ms_samples;
88
89    if dst + prefill_frame_length <= ps_enc.s_cmn.x_buf.len() {
90        ps_enc.s_cmn.x_buf[dst..dst + prefill_frame_length]
91            .copy_from_slice(&input_buf[1..1 + prefill_frame_length]);
92    }
93
94    let move_len = ltp_mem_length + la_shape_ms_samples;
95    if prefill_frame_length + move_len <= ps_enc.s_cmn.x_buf.len() {
96        ps_enc
97            .s_cmn
98            .x_buf
99            .copy_within(prefill_frame_length..prefill_frame_length + move_len, 0);
100    }
101
102    ps_enc.s_cmn.frame_length = real_frame_length as i32;
103    ps_enc.s_cmn.nb_subfr = real_nb_subfr;
104    ps_enc.s_cmn.subfr_length = real_subfr_length;
105}
106
107pub fn silk_encode_frame(
108    ps_enc: &mut SilkEncoderState,
109    input: &[i16],
110    rc: &mut RangeCoder,
111    pn_bytes_out: &mut i32,
112    cond_coding: i32,
113    max_bits: i32,
114    use_cbr: i32,
115) -> i32 {
116    let mut s_enc_ctrl = SilkEncoderControl::default();
117
118    ps_enc.s_cmn.indices.seed = (ps_enc.s_cmn.frame_counter & 3) as i8;
119    ps_enc.s_cmn.frame_counter += 1;
120
121    let frame_length = ps_enc.s_cmn.frame_length as usize;
122    let ltp_mem_length = ps_enc.s_cmn.ltp_mem_length as usize;
123    let la_shape = ps_enc.s_cmn.la_shape as usize;
124
125    let x_frame_idx = ltp_mem_length;
126
127    let la_shape_max = 5 * ps_enc.s_cmn.fs_khz as usize;
128    let new_samples_idx = x_frame_idx + la_shape_max;
129    ps_enc.s_cmn.x_buf[new_samples_idx..new_samples_idx + frame_length]
130        .copy_from_slice(&input[..frame_length]);
131
132    let x_buf_copy = ps_enc.s_cmn.x_buf;
133
134    let mut res_pitch = [0i16; LA_PITCH_MAX + MAX_FRAME_LENGTH + LTP_MEM_LENGTH_MS * MAX_FS_KHZ];
135    let res_pitch_frame_idx = ltp_mem_length;
136
137    // Env read cached once (was per-frame — census 2026-08-07 hygiene batch).
138    static FLP_ENV: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
139    if ps_enc.use_flp || *FLP_ENV.get_or_init(|| std::env::var_os("SILK_FLP").is_some()) {
140        crate::silk::flp::silk_encode_frame_flp_analysis(ps_enc, &mut s_enc_ctrl, cond_coding);
141        let _ = (&res_pitch, res_pitch_frame_idx, la_shape, &x_buf_copy);
142    } else {
143        silk_find_pitch_lags_fix(ps_enc, &mut s_enc_ctrl, &mut res_pitch, &x_buf_copy, 0);
144
145        let x_tmp = &x_buf_copy[x_frame_idx - la_shape..];
146        silk_noise_shape_analysis_fix(
147            ps_enc,
148            &mut s_enc_ctrl,
149            &res_pitch[res_pitch_frame_idx..],
150            x_tmp,
151        );
152
153        let predict_lpc_order = ps_enc.s_cmn.predict_lpc_order as usize;
154        let x_tmp_frame = &x_buf_copy[x_frame_idx - predict_lpc_order..];
155        silk_find_pred_coefs_fix(
156            ps_enc,
157            &mut s_enc_ctrl,
158            &res_pitch,
159            res_pitch_frame_idx,
160            x_tmp_frame,
161            &x_buf_copy,
162            cond_coding,
163        );
164
165        silk_process_gains_fix(ps_enc, &mut s_enc_ctrl, cond_coding);
166    }
167
168    let max_iter = 6;
169    let mut gain_mult_q8: i32 = 256;
170    let mut found_lower = false;
171    let mut found_upper = false;
172    #[allow(unused_assignments)]
173    let mut n_bits: i32 = 0;
174    let mut n_bits_lower: i32 = 0;
175    let mut n_bits_upper: i32 = 0;
176    let mut gain_mult_lower: i32 = 0;
177    let mut gain_mult_upper: i32 = 0;
178    let mut gains_id: i32 =
179        silk_gains_id(&ps_enc.s_cmn.indices.gains_indices, ps_enc.s_cmn.nb_subfr);
180    let mut gains_id_lower: i32 = -1;
181    let mut gains_id_upper: i32 = -1;
182
183    let bits_margin = if use_cbr != 0 { 5 } else { max_bits / 4 };
184
185    let rc_copy = rc.clone();
186    let nsq_copy = ps_enc.s_nsq;
187    let seed_copy = ps_enc.s_cmn.indices.seed;
188    let ec_prev_lag_index_copy = ps_enc.s_cmn.ec_prev_lag_index;
189    let ec_prev_signal_type_copy = ps_enc.s_cmn.ec_prev_signal_type;
190    let mut rc_copy2: Option<RangeCoder> = None;
191    let mut nsq_copy2: Option<SilkNSQState> = None;
192    let mut ec_buf_copy = [0u8; 1275];
193    let mut last_gain_index_copy2: i8 = 0;
194
195    let mut gain_lock = [false; MAX_NB_SUBFR];
196    let mut best_gain_mult = [256i32; MAX_NB_SUBFR];
197    let mut best_sum = [i32::MAX; MAX_NB_SUBFR];
198
199    for iter in 0..=max_iter {
200        if gains_id == gains_id_lower {
201            n_bits = n_bits_lower;
202        } else if gains_id == gains_id_upper {
203            n_bits = n_bits_upper;
204        } else {
205            if iter > 0 {
206                *rc = rc_copy.clone();
207                ps_enc.s_nsq = nsq_copy;
208                ps_enc.s_cmn.indices.seed = seed_copy;
209                ps_enc.s_cmn.ec_prev_lag_index = ec_prev_lag_index_copy;
210                ps_enc.s_cmn.ec_prev_signal_type = ec_prev_signal_type_copy;
211            }
212
213            let mut pred_coef_q12_flat = [0i16; 2 * MAX_LPC_ORDER];
214            pred_coef_q12_flat[..MAX_LPC_ORDER].copy_from_slice(&s_enc_ctrl.pred_coef_q12[0]);
215            pred_coef_q12_flat[MAX_LPC_ORDER..].copy_from_slice(&s_enc_ctrl.pred_coef_q12[1]);
216
217            if ps_enc.s_cmn.n_states_delayed_decision > 1 {
218                let winner_seed = silk_nsq_del_dec(
219                    &ps_enc.s_cmn,
220                    &mut ps_enc.s_nsq,
221                    &ps_enc.s_cmn.indices,
222                    &ps_enc.s_cmn.x_buf[x_frame_idx..],
223                    &mut ps_enc.pulses,
224                    &pred_coef_q12_flat,
225                    &s_enc_ctrl.ltp_coef_q14,
226                    &s_enc_ctrl.ar_q13,
227                    &s_enc_ctrl.harm_shape_gain_q14,
228                    &s_enc_ctrl.tilt_q14,
229                    &s_enc_ctrl.lf_shp_q14,
230                    &s_enc_ctrl.gains_q16,
231                    &s_enc_ctrl.pitch_l,
232                    s_enc_ctrl.lambda_q10,
233                    s_enc_ctrl.ltp_scale_q14,
234                );
235
236                ps_enc.s_cmn.indices.seed = winner_seed as i8;
237            } else {
238                silk_nsq(
239                    &ps_enc.s_cmn,
240                    &mut ps_enc.s_nsq,
241                    &ps_enc.s_cmn.indices,
242                    &ps_enc.s_cmn.x_buf[x_frame_idx..],
243                    &mut ps_enc.pulses,
244                    &pred_coef_q12_flat,
245                    &s_enc_ctrl.ltp_coef_q14,
246                    &s_enc_ctrl.ar_q13,
247                    &s_enc_ctrl.harm_shape_gain_q14,
248                    &s_enc_ctrl.tilt_q14,
249                    &s_enc_ctrl.lf_shp_q14,
250                    &s_enc_ctrl.gains_q16,
251                    &s_enc_ctrl.pitch_l,
252                    s_enc_ctrl.lambda_q10,
253                    s_enc_ctrl.ltp_scale_q14,
254                );
255            }
256
257            if iter == max_iter && !found_lower {
258                rc_copy2 = Some(rc.clone());
259            }
260
261            silk_encode_indices(
262                ps_enc,
263                rc,
264                ps_enc.s_cmn.n_frames_encoded as usize,
265                false,
266                cond_coding,
267            );
268
269            silk_encode_pulses(
270                rc,
271                ps_enc.s_cmn.indices.signal_type as i32,
272                ps_enc.s_cmn.indices.quant_offset_type as i32,
273                &ps_enc.pulses,
274                ps_enc.s_cmn.frame_length as usize,
275            );
276
277            n_bits = rc.tell();
278
279            if iter == max_iter && !found_lower && n_bits > max_bits {
280                if let Some(rc_c2) = &rc_copy2 {
281                    *rc = rc_c2.clone();
282                }
283
284                ps_enc.s_shape.last_gain_index = s_enc_ctrl.last_gain_index_prev;
285                for i in 0..ps_enc.s_cmn.nb_subfr as usize {
286                    ps_enc.s_cmn.indices.gains_indices[i] = 4;
287                }
288                if cond_coding != CODE_CONDITIONALLY {
289                    ps_enc.s_cmn.indices.gains_indices[0] = s_enc_ctrl.last_gain_index_prev;
290                }
291                ps_enc.s_cmn.ec_prev_lag_index = ec_prev_lag_index_copy;
292                ps_enc.s_cmn.ec_prev_signal_type = ec_prev_signal_type_copy;
293
294                ps_enc.pulses.fill(0);
295
296                silk_encode_indices(
297                    ps_enc,
298                    rc,
299                    ps_enc.s_cmn.n_frames_encoded as usize,
300                    false,
301                    cond_coding,
302                );
303                silk_encode_pulses(
304                    rc,
305                    ps_enc.s_cmn.indices.signal_type as i32,
306                    ps_enc.s_cmn.indices.quant_offset_type as i32,
307                    &ps_enc.pulses,
308                    ps_enc.s_cmn.frame_length as usize,
309                );
310
311                n_bits = rc.tell();
312            }
313
314            if use_cbr == 0 && iter == 0 && n_bits <= max_bits {
315                break;
316            }
317        }
318
319        if iter == max_iter {
320            if found_lower && (gains_id == gains_id_lower || n_bits > max_bits) {
321                if let Some(rc_c2) = &rc_copy2 {
322                    *rc = rc_c2.clone();
323                    let offs = rc.offs as usize;
324                    rc.buf[..offs].copy_from_slice(&ec_buf_copy[..offs]);
325                }
326                if let Some(nsq_c2) = &nsq_copy2 {
327                    ps_enc.s_nsq = *nsq_c2;
328                }
329                ps_enc.s_shape.last_gain_index = last_gain_index_copy2;
330            }
331            break;
332        }
333
334        if n_bits > max_bits {
335            if !found_lower && iter >= 2 {
336                s_enc_ctrl.lambda_q10 =
337                    silk_add_rshift32(s_enc_ctrl.lambda_q10, s_enc_ctrl.lambda_q10, 1);
338                found_upper = false;
339                gains_id_upper = -1;
340            } else {
341                found_upper = true;
342                n_bits_upper = n_bits;
343                gain_mult_upper = gain_mult_q8;
344                gains_id_upper = gains_id;
345            }
346        } else if n_bits < max_bits - bits_margin {
347            found_lower = true;
348            n_bits_lower = n_bits;
349            gain_mult_lower = gain_mult_q8;
350            if gains_id != gains_id_lower {
351                gains_id_lower = gains_id;
352
353                rc_copy2 = Some(rc.clone());
354                let offs = rc.offs as usize;
355                ec_buf_copy[..offs].copy_from_slice(&rc.buf[..offs]);
356                nsq_copy2 = Some(ps_enc.s_nsq);
357                last_gain_index_copy2 = ps_enc.s_shape.last_gain_index;
358            }
359        } else {
360            break;
361        }
362
363        if !found_lower && n_bits > max_bits {
364            let subfr_length = ps_enc.s_cmn.subfr_length as usize;
365            for i in 0..ps_enc.s_cmn.nb_subfr as usize {
366                let mut sum: i32 = 0;
367                for j in (i * subfr_length)..((i + 1) * subfr_length) {
368                    sum += ps_enc.pulses[j].abs() as i32;
369                }
370                if iter == 0 || (sum < best_sum[i] && !gain_lock[i]) {
371                    best_sum[i] = sum;
372                    best_gain_mult[i] = gain_mult_q8;
373                } else {
374                    gain_lock[i] = true;
375                }
376            }
377        }
378
379        if !(found_lower && found_upper) {
380            if n_bits > max_bits {
381                gain_mult_q8 = silk_min_32(1024, (gain_mult_q8 * 3) / 2);
382            } else {
383                gain_mult_q8 = silk_max_32(64, (gain_mult_q8 * 4) / 5);
384            }
385        } else {
386            let delta = gain_mult_upper - gain_mult_lower;
387            gain_mult_q8 = gain_mult_lower
388                + silk_div32_16(
389                    (gain_mult_upper - gain_mult_lower) * (max_bits - n_bits_lower),
390                    n_bits_upper - n_bits_lower,
391                );
392
393            let lower_limit = silk_add_rshift32(gain_mult_lower, delta, 2);
394            let upper_limit = silk_sub_rshift32(gain_mult_upper, delta, 2);
395            if gain_mult_q8 > lower_limit {
396                gain_mult_q8 = lower_limit;
397            } else if gain_mult_q8 < upper_limit {
398                gain_mult_q8 = upper_limit;
399            }
400        }
401
402        for i in 0..ps_enc.s_cmn.nb_subfr as usize {
403            let tmp = if gain_lock[i] {
404                best_gain_mult[i]
405            } else {
406                gain_mult_q8
407            };
408            s_enc_ctrl.gains_q16[i] =
409                silk_lshift_sat32(silk_smulwb(s_enc_ctrl.gains_unq_q16[i], tmp), 8);
410        }
411
412        ps_enc.s_shape.last_gain_index = s_enc_ctrl.last_gain_index_prev;
413        silk_gains_quant(
414            &mut ps_enc.s_cmn.indices.gains_indices,
415            &mut s_enc_ctrl.gains_q16,
416            &mut ps_enc.s_shape.last_gain_index,
417            if cond_coding == CODE_CONDITIONALLY {
418                1
419            } else {
420                0
421            },
422            ps_enc.s_cmn.nb_subfr as usize,
423        );
424
425        gains_id = silk_gains_id(&ps_enc.s_cmn.indices.gains_indices, ps_enc.s_cmn.nb_subfr);
426    }
427
428    let move_len = ltp_mem_length + 5 * ps_enc.s_cmn.fs_khz as usize;
429    ps_enc
430        .s_cmn
431        .x_buf
432        .copy_within(frame_length..frame_length + move_len, 0);
433
434    ps_enc.s_cmn.prev_lag = s_enc_ctrl.pitch_l[ps_enc.s_cmn.nb_subfr as usize - 1];
435    static SILKD_ENV: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
436    if *SILKD_ENV.get_or_init(|| std::env::var_os("SILKD").is_some()) {
437        let ix = &ps_enc.s_cmn.indices;
438        let n = ix.nlsf_indices;
439        eprintln!(
440            "SILKD - st={} qo={} lag={} cont={} per={} ltps={} interp={} seed={} g={},{},{},{} ltp={},{},{},{} nlsf={},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{} lastgain={}",
441            ix.signal_type, ix.quant_offset_type, ix.lag_index, ix.contour_index,
442            ix.per_index, ix.ltp_scale_index, ix.nlsf_interp_coef_q2, ix.seed,
443            ix.gains_indices[0], ix.gains_indices[1], ix.gains_indices[2], ix.gains_indices[3],
444            ix.ltp_index[0], ix.ltp_index[1], ix.ltp_index[2], ix.ltp_index[3],
445            n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10], n[11], n[12], n[13], n[14], n[15], n[16],
446            ps_enc.s_shape.last_gain_index
447        );
448    }
449    ps_enc.s_cmn.prev_signal_type = ps_enc.s_cmn.indices.signal_type as i32;
450    ps_enc.s_cmn.first_frame_after_reset = 0;
451
452    *pn_bytes_out = (rc.tell() + 7) >> 3;
453
454    0
455}
456
457pub fn silk_encode(
458    ps_enc: &mut SilkEncoderState,
459    samples_in: &[i16],
460    n_samples_in: usize,
461    rc: &mut RangeCoder,
462    n_bytes_out: &mut i32,
463    target_rate_bps: i32,
464    max_bits: i32,
465    use_cbr: i32,
466    activity: i32,
467) -> i32 {
468    let n_frames_per_packet = ps_enc.s_cmn.n_frames_per_packet;
469    let frame_length = ps_enc.s_cmn.frame_length as usize;
470    let packet_size_ms = ps_enc.s_cmn.packet_size_ms;
471
472    ps_enc.s_cmn.n_frames_encoded = 0;
473
474    let n_blocks_of_10ms = (100 * n_samples_in as i32) / (ps_enc.s_cmn.fs_khz * 1000);
475    let _tot_blocks = if n_blocks_of_10ms > 1 {
476        n_blocks_of_10ms >> 1
477    } else {
478        1
479    };
480
481    let n_bits_total = target_rate_bps * packet_size_ms / 1000;
482    let n_bits_per_frame = n_bits_total / n_frames_per_packet;
483    let frame_rate_bps = if packet_size_ms == 10 {
484        n_bits_per_frame * 100
485    } else {
486        n_bits_per_frame * 50
487    };
488
489    let lbrr_possible = ps_enc.s_cmn.use_in_band_fec != 0
490        && ps_enc.s_cmn.packet_loss_perc > 0
491        && ps_enc.s_cmn.lbrr_enabled != 0;
492
493    let mut lbrr_symbol: i32 = 0;
494    if lbrr_possible {
495        for i in 0..n_frames_per_packet as usize {
496            if ps_enc.s_cmn.indices_lbrr[i].signal_type >= TYPE_UNVOICED as i8 {
497                lbrr_symbol |= 1 << i;
498            }
499        }
500    }
501    let use_lbrr = lbrr_symbol > 0;
502
503    ps_enc.s_cmn.lbrr_flag = if lbrr_symbol > 0 { 1 } else { 0 };
504
505    for i in 0..n_frames_per_packet as usize {
506        ps_enc.s_cmn.lbrr_flags[i] = (lbrr_symbol >> i) & 1;
507    }
508
509    let mut sample_offset = 0usize;
510
511    for frame_idx in 0..n_frames_per_packet {
512        if frame_idx == 0 {
513            silk_hp_variable_cutoff(&mut ps_enc.s_cmn);
514        }
515
516        let frame_end = (sample_offset + frame_length).min(n_samples_in);
517        let raw_frame = &samples_in[sample_offset..frame_end];
518
519        let fs_in_khz = ps_enc.s_cmn.fs_khz as usize;
520
521        if raw_frame.len() < fs_in_khz {
522            sample_offset += frame_length;
523            continue;
524        }
525
526        let input_delay: usize = match fs_in_khz {
527            8 => 6,
528            12 => 7,
529            16 => 10,
530            24 => 6,
531            48 => 12,
532            _ => 0,
533        };
534        let n_samp: usize = fs_in_khz - input_delay;
535
536        let n = raw_frame.len();
537
538        if n > MAX_FRAME_LENGTH {
539            sample_offset += frame_length;
540            continue;
541        }
542
543        let mut resampler_out = [0i16; MAX_FRAME_LENGTH];
544
545        let mut delay_buf = ps_enc.resampler_delay_buf;
546        delay_buf[input_delay..fs_in_khz].copy_from_slice(&raw_frame[..n_samp]);
547
548        resampler_out[..fs_in_khz].copy_from_slice(&delay_buf[..fs_in_khz]);
549
550        let rest_len = n - fs_in_khz;
551        let rest_end = n_samp + rest_len;
552
553        if rest_end <= raw_frame.len() && n <= MAX_FRAME_LENGTH {
554            resampler_out[fs_in_khz..n].copy_from_slice(&raw_frame[n_samp..rest_end]);
555        }
556
557        if n >= input_delay {
558            delay_buf[..input_delay].copy_from_slice(&raw_frame[n - input_delay..]);
559        }
560        ps_enc.resampler_delay_buf = delay_buf;
561
562        let mut input_buf = [0i16; MAX_FRAME_LENGTH + 2];
563        input_buf[0] = ps_enc.stereo.s_mid[0];
564        input_buf[1] = ps_enc.stereo.s_mid[1];
565        input_buf[2..2 + n].copy_from_slice(&resampler_out[..n]);
566
567        ps_enc.stereo.s_mid[0] = input_buf[frame_length];
568        ps_enc.stereo.s_mid[1] = input_buf[frame_length + 1];
569
570        if frame_idx == 0 {
571            let n_channels = ps_enc.s_cmn.n_channels;
572            let n_flag_bits = ((n_frames_per_packet + 1) * n_channels) as u32;
573            let icdf_val = (256i32 - (256i32 >> n_flag_bits)) as u8;
574            let icdf = [icdf_val, 0u8];
575            rc.encode_icdf(0, &icdf, 8);
576
577            if lbrr_symbol > 0 {
578                let lbrr_icdf = match n_frames_per_packet {
579                    2 => &crate::silk::tables::SILK_LBRR_FLAGS_2_ICDF[..],
580                    3 => &crate::silk::tables::SILK_LBRR_FLAGS_3_ICDF[..],
581                    _ => &crate::silk::tables::SILK_LBRR_FLAGS_2_ICDF[..],
582                };
583                if n_frames_per_packet > 1 {
584                    rc.encode_icdf(lbrr_symbol - 1, lbrr_icdf, 8);
585                }
586
587                for i in 0..n_frames_per_packet as usize {
588                    if ps_enc.s_cmn.lbrr_flags[i] != 0 {
589                        let lbrr_cond = if i > 0 && ps_enc.s_cmn.lbrr_flags[i - 1] != 0 {
590                            CODE_CONDITIONALLY
591                        } else {
592                            CODE_INDEPENDENTLY_NO_LTP_SCALING
593                        };
594                        silk_encode_indices(ps_enc, rc, i, true, lbrr_cond);
595                        silk_encode_pulses(
596                            rc,
597                            ps_enc.s_cmn.indices_lbrr[i].signal_type as i32,
598                            ps_enc.s_cmn.indices_lbrr[i].quant_offset_type as i32,
599                            &ps_enc.s_cmn.pulses_lbrr[i],
600                            ps_enc.s_cmn.frame_length as usize,
601                        );
602                    }
603                }
604            }
605
606            if ps_enc.s_cmn.n_channels == 2 {
607                silk_encode_stereo(rc, 0, 0, 1);
608            }
609        }
610
611        silk_control_snr(&mut ps_enc.s_cmn, frame_rate_bps);
612
613        let vad_frame = &input_buf[1..1 + frame_length];
614        silk_encode_do_vad(ps_enc, vad_frame, activity);
615
616        silk_lp_variable_cutoff(&mut ps_enc.s_cmn.s_lp, &mut input_buf[1..], frame_length);
617
618        let frame_samples = &input_buf[1..1 + frame_length];
619
620        let cond_coding = if ps_enc.s_cmn.n_frames_encoded == 0 {
621            CODE_INDEPENDENTLY
622        } else {
623            CODE_CONDITIONALLY
624        };
625
626        let frame_max_bits = if _tot_blocks == 2 && frame_idx == 0 {
627            max_bits * 3 / 5
628        } else {
629            max_bits
630        };
631
632        let mut frame_bytes = 0i32;
633        let ret = silk_encode_frame(
634            ps_enc,
635            frame_samples,
636            rc,
637            &mut frame_bytes,
638            cond_coding,
639            frame_max_bits,
640            if use_cbr != 0 && frame_idx == n_frames_per_packet - 1 {
641                1
642            } else {
643                0
644            },
645        );
646        if ret != 0 {
647            return ret;
648        }
649
650        if use_lbrr || ps_enc.s_cmn.use_in_band_fec != 0 {
651            let fi = frame_idx as usize;
652            if fi < MAX_FRAMES_PER_PACKET {
653                ps_enc.s_cmn.indices_lbrr[fi] = ps_enc.s_cmn.indices;
654
655                let gain_inc = ps_enc.s_cmn.lbrr_gain_increases.clamp(0, 16) as i8;
656                for g in 0..ps_enc.s_cmn.nb_subfr as usize {
657                    let new_gain = (ps_enc.s_cmn.indices_lbrr[fi].gains_indices[g] as i32
658                        + gain_inc as i32)
659                        .min(63) as i8;
660                    ps_enc.s_cmn.indices_lbrr[fi].gains_indices[g] = new_gain;
661                }
662
663                ps_enc.s_cmn.pulses_lbrr[fi] = ps_enc.pulses;
664            }
665        }
666
667        ps_enc.s_cmn.n_frames_encoded += 1;
668        sample_offset += frame_length;
669    }
670
671    let n_channels = ps_enc.s_cmn.n_channels;
672    let n_flag_bits = ((n_frames_per_packet + 1) * n_channels) as u32;
673    let mut flags = 0u32;
674    for i in 0..n_frames_per_packet as usize {
675        flags <<= 1;
676        flags |= ps_enc.s_cmn.vad_flags[i] as u32;
677    }
678    flags <<= 1;
679    flags |= ps_enc.s_cmn.lbrr_flag as u32;
680    if n_channels == 2 {
681        flags <<= (n_frames_per_packet + 1) as u32;
682    }
683
684    rc.patch_initial_bits(flags, n_flag_bits);
685
686    *n_bytes_out = (rc.tell() + 7) >> 3;
687
688    0
689}