unsafe_libopus/celt/
celt.rs

1use crate::celt::modes::OpusCustomMode;
2
3pub mod arch_h {
4    pub type opus_val16 = f32;
5    pub type opus_val32 = f32;
6}
7
8pub use self::arch_h::{opus_val16, opus_val32};
9use crate::externs::memmove;
10
11pub static trim_icdf: [u8; 11] = [126, 124, 119, 109, 87, 41, 19, 9, 4, 2, 0];
12pub static spread_icdf: [u8; 4] = [25, 23, 2, 0];
13pub static tapset_icdf: [u8; 3] = [2, 1, 0];
14pub static tf_select_table: [[i8; 8]; 4] = [
15    [0, -1, 0, -1, 0, -1, 0, -1],
16    [0, -1, 0, -2, 1, 0, 1, -1],
17    [0, -2, 0, -3, 2, 0, 1, -1],
18    [0, -2, 0, -3, 3, 0, 1, -1],
19];
20
21pub const OPUS_SET_ENERGY_MASK_REQUEST: i32 = 10026;
22pub const CELT_GET_MODE_REQUEST: i32 = 10015;
23pub const CELT_SET_SILK_INFO_REQUEST: i32 = 10028;
24pub const CELT_SET_ANALYSIS_REQUEST: i32 = 10022;
25pub const CELT_SET_SIGNALLING_REQUEST: i32 = 10016;
26pub const OPUS_SET_LFE_REQUEST: i32 = 10024;
27pub const CELT_SET_START_BAND_REQUEST: i32 = 10010;
28pub const CELT_SET_CHANNELS_REQUEST: i32 = 10008;
29pub const CELT_SET_END_BAND_REQUEST: i32 = 10012;
30pub const CELT_SET_PREDICTION_REQUEST: i32 = 10002;
31pub const CELT_GET_AND_CLEAR_ERROR_REQUEST: i32 = 10007;
32
33pub const COMBFILTER_MAXPERIOD: i32 = 1024;
34pub const COMBFILTER_MINPERIOD: i32 = 15;
35
36pub fn resampling_factor(rate: i32) -> i32 {
37    match rate {
38        48000 => 1,
39        24000 => 2,
40        16000 => 3,
41        12000 => 4,
42        8000 => 6,
43        _ => panic!("Unsupported sampling rate: {}", rate),
44    }
45}
46unsafe fn comb_filter_const_c(
47    y: *mut opus_val32,
48    x: *mut opus_val32,
49    T: i32,
50    N: i32,
51    g10: opus_val16,
52    g11: opus_val16,
53    g12: opus_val16,
54) {
55    let mut x0: opus_val32 = 0.;
56    let mut x1: opus_val32 = 0.;
57    let mut x2: opus_val32 = 0.;
58    let mut x3: opus_val32 = 0.;
59    let mut x4: opus_val32 = 0.;
60    let mut i: i32 = 0;
61    x4 = *x.offset((-T - 2) as isize);
62    x3 = *x.offset((-T - 1) as isize);
63    x2 = *x.offset(-T as isize);
64    x1 = *x.offset((-T + 1) as isize);
65    i = 0;
66    while i < N {
67        x0 = *x.offset((i - T + 2) as isize);
68        *y.offset(i as isize) =
69            *x.offset(i as isize) + g10 * x2 + g11 * (x1 + x3) + g12 * (x0 + x4);
70        *y.offset(i as isize) = *y.offset(i as isize);
71        x4 = x3;
72        x3 = x2;
73        x2 = x1;
74        x1 = x0;
75        i += 1;
76    }
77}
78pub unsafe fn comb_filter(
79    y: *mut opus_val32,
80    x: *mut opus_val32,
81    mut T0: i32,
82    mut T1: i32,
83    N: i32,
84    g0: opus_val16,
85    g1: opus_val16,
86    tapset0: i32,
87    tapset1: i32,
88    window: *const opus_val16,
89    mut overlap: i32,
90    _arch: i32,
91) {
92    let mut i: i32 = 0;
93    let mut g00: opus_val16 = 0.;
94    let mut g01: opus_val16 = 0.;
95    let mut g02: opus_val16 = 0.;
96    let mut g10: opus_val16 = 0.;
97    let mut g11: opus_val16 = 0.;
98    let mut g12: opus_val16 = 0.;
99    let mut x0: opus_val32 = 0.;
100    let mut x1: opus_val32 = 0.;
101    let mut x2: opus_val32 = 0.;
102    let mut x3: opus_val32 = 0.;
103    let mut x4: opus_val32 = 0.;
104    static mut gains: [[opus_val16; 3]; 3] = [
105        [0.3066406250f32, 0.2170410156f32, 0.1296386719f32],
106        [0.4638671875f32, 0.2680664062f32, 0.0f32],
107        [0.7998046875f32, 0.1000976562f32, 0.0f32],
108    ];
109    if g0 == 0 as f32 && g1 == 0 as f32 {
110        if x != y {
111            memmove(
112                y as *mut core::ffi::c_void,
113                x as *const core::ffi::c_void,
114                (N as u64)
115                    .wrapping_mul(::core::mem::size_of::<opus_val32>() as u64)
116                    .wrapping_add((0 * y.offset_from(x) as i64) as u64),
117            );
118        }
119        return;
120    }
121    T0 = if T0 > 15 { T0 } else { 15 };
122    T1 = if T1 > 15 { T1 } else { 15 };
123    g00 = g0 * gains[tapset0 as usize][0 as usize];
124    g01 = g0 * gains[tapset0 as usize][1 as usize];
125    g02 = g0 * gains[tapset0 as usize][2 as usize];
126    g10 = g1 * gains[tapset1 as usize][0 as usize];
127    g11 = g1 * gains[tapset1 as usize][1 as usize];
128    g12 = g1 * gains[tapset1 as usize][2 as usize];
129    x1 = *x.offset((-T1 + 1) as isize);
130    x2 = *x.offset(-T1 as isize);
131    x3 = *x.offset((-T1 - 1) as isize);
132    x4 = *x.offset((-T1 - 2) as isize);
133    if g0 == g1 && T0 == T1 && tapset0 == tapset1 {
134        overlap = 0;
135    }
136    i = 0;
137    while i < overlap {
138        let mut f: opus_val16 = 0.;
139        x0 = *x.offset((i - T1 + 2) as isize);
140        f = *window.offset(i as isize) * *window.offset(i as isize);
141        *y.offset(i as isize) = *x.offset(i as isize)
142            + (1.0f32 - f) * g00 * *x.offset((i - T0) as isize)
143            + (1.0f32 - f)
144                * g01
145                * (*x.offset((i - T0 + 1) as isize) + *x.offset((i - T0 - 1) as isize))
146            + (1.0f32 - f)
147                * g02
148                * (*x.offset((i - T0 + 2) as isize) + *x.offset((i - T0 - 2) as isize))
149            + f * g10 * x2
150            + f * g11 * (x1 + x3)
151            + f * g12 * (x0 + x4);
152        *y.offset(i as isize) = *y.offset(i as isize);
153        x4 = x3;
154        x3 = x2;
155        x2 = x1;
156        x1 = x0;
157        i += 1;
158    }
159    if g1 == 0 as f32 {
160        if x != y {
161            memmove(
162                y.offset(overlap as isize) as *mut core::ffi::c_void,
163                x.offset(overlap as isize) as *const core::ffi::c_void,
164                ((N - overlap) as u64)
165                    .wrapping_mul(::core::mem::size_of::<opus_val32>() as u64)
166                    .wrapping_add(
167                        (0 * y
168                            .offset(overlap as isize)
169                            .offset_from(x.offset(overlap as isize))
170                            as i64) as u64,
171                    ),
172            );
173        }
174        return;
175    }
176    comb_filter_const_c(
177        y.offset(i as isize),
178        x.offset(i as isize),
179        T1,
180        N - i,
181        g10,
182        g11,
183        g12,
184    );
185}
186pub unsafe fn init_caps(m: *const OpusCustomMode, cap: *mut i32, LM: i32, C: i32) {
187    let mut i: i32 = 0;
188    i = 0;
189    while i < (*m).nbEBands {
190        let mut N: i32 = 0;
191        N = (*((*m).eBands).offset((i + 1) as isize) as i32
192            - *((*m).eBands).offset(i as isize) as i32)
193            << LM;
194        *cap.offset(i as isize) =
195            (*((*m).cache.caps).offset(((*m).nbEBands * (2 * LM + C - 1) + i) as isize) as i32
196                + 64)
197                * C
198                * N
199                >> 2;
200        i += 1;
201    }
202}
203
204pub fn opus_strerror(error: i32) -> &'static str {
205    static error_strings: [&str; 8] = [
206        "success (0)",
207        "invalid argument (-1)",
208        "buffer too small (-2)",
209        "internal error (-3)",
210        "corrupted stream (-4)",
211        "request not implemented (-5)",
212        "invalid state (-6)",
213        "memory allocation failed (-7)",
214    ];
215    if error > 0 || error < -7 {
216        "unknown error"
217    } else {
218        error_strings[-error as usize]
219    }
220}
221
222pub fn opus_get_version_string() -> &'static str {
223    "unsafe-libopus (rust port) 1.3.1"
224}