xref: /btstack/3rd-party/lc3-google/test/sns_py.c (revision 4930cef6e21e6da2d7571b9259c7f0fb8bed3d01)
1*4930cef6SMatthias Ringwald /******************************************************************************
2*4930cef6SMatthias Ringwald  *
3*4930cef6SMatthias Ringwald  *  Copyright 2022 Google LLC
4*4930cef6SMatthias Ringwald  *
5*4930cef6SMatthias Ringwald  *  Licensed under the Apache License, Version 2.0 (the "License");
6*4930cef6SMatthias Ringwald  *  you may not use this file except in compliance with the License.
7*4930cef6SMatthias Ringwald  *  You may obtain a copy of the License at:
8*4930cef6SMatthias Ringwald  *
9*4930cef6SMatthias Ringwald  *  http://www.apache.org/licenses/LICENSE-2.0
10*4930cef6SMatthias Ringwald  *
11*4930cef6SMatthias Ringwald  *  Unless required by applicable law or agreed to in writing, software
12*4930cef6SMatthias Ringwald  *  distributed under the License is distributed on an "AS IS" BASIS,
13*4930cef6SMatthias Ringwald  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*4930cef6SMatthias Ringwald  *  See the License for the specific language governing permissions and
15*4930cef6SMatthias Ringwald  *  limitations under the License.
16*4930cef6SMatthias Ringwald  *
17*4930cef6SMatthias Ringwald  ******************************************************************************/
18*4930cef6SMatthias Ringwald 
19*4930cef6SMatthias Ringwald #include "lc3.h"
20*4930cef6SMatthias Ringwald #include <Python.h>
21*4930cef6SMatthias Ringwald #include <numpy/ndarrayobject.h>
22*4930cef6SMatthias Ringwald 
23*4930cef6SMatthias Ringwald #include <sns.c>
24*4930cef6SMatthias Ringwald #include "ctypes.h"
25*4930cef6SMatthias Ringwald 
26*4930cef6SMatthias Ringwald static PyObject *compute_scale_factors_py(PyObject *m, PyObject *args)
27*4930cef6SMatthias Ringwald {
28*4930cef6SMatthias Ringwald     unsigned dt, sr;
29*4930cef6SMatthias Ringwald     PyObject *eb_obj, *scf_obj;
30*4930cef6SMatthias Ringwald     float *eb, *scf;
31*4930cef6SMatthias Ringwald     int att;
32*4930cef6SMatthias Ringwald 
33*4930cef6SMatthias Ringwald     if (!PyArg_ParseTuple(args, "IIOp", &dt, &sr, &eb_obj, &att))
34*4930cef6SMatthias Ringwald         return NULL;
35*4930cef6SMatthias Ringwald 
36*4930cef6SMatthias Ringwald     CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
37*4930cef6SMatthias Ringwald     CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
38*4930cef6SMatthias Ringwald 
39*4930cef6SMatthias Ringwald     int nb = LC3_MIN(lc3_band_lim[dt][sr][LC3_NUM_BANDS], LC3_NUM_BANDS);
40*4930cef6SMatthias Ringwald 
41*4930cef6SMatthias Ringwald     CTYPES_CHECK("eb", to_1d_ptr(eb_obj, NPY_FLOAT, nb, &eb));
42*4930cef6SMatthias Ringwald     scf_obj = new_1d_ptr(NPY_FLOAT, 16, &scf);
43*4930cef6SMatthias Ringwald 
44*4930cef6SMatthias Ringwald     compute_scale_factors(dt, sr, eb, att, scf);
45*4930cef6SMatthias Ringwald 
46*4930cef6SMatthias Ringwald     return Py_BuildValue("N", scf_obj);
47*4930cef6SMatthias Ringwald }
48*4930cef6SMatthias Ringwald 
49*4930cef6SMatthias Ringwald static PyObject *resolve_codebooks_py(PyObject *m, PyObject *args)
50*4930cef6SMatthias Ringwald {
51*4930cef6SMatthias Ringwald     PyObject *scf_obj;
52*4930cef6SMatthias Ringwald     float *scf;
53*4930cef6SMatthias Ringwald     int lfcb_idx, hfcb_idx;
54*4930cef6SMatthias Ringwald 
55*4930cef6SMatthias Ringwald     if (!PyArg_ParseTuple(args, "O", &scf_obj))
56*4930cef6SMatthias Ringwald         return NULL;
57*4930cef6SMatthias Ringwald 
58*4930cef6SMatthias Ringwald     CTYPES_CHECK("eb", to_1d_ptr(scf_obj, NPY_FLOAT, 16, &scf));
59*4930cef6SMatthias Ringwald 
60*4930cef6SMatthias Ringwald     resolve_codebooks(scf, &lfcb_idx, &hfcb_idx);
61*4930cef6SMatthias Ringwald 
62*4930cef6SMatthias Ringwald     return Py_BuildValue("ii", lfcb_idx, hfcb_idx);
63*4930cef6SMatthias Ringwald }
64*4930cef6SMatthias Ringwald 
65*4930cef6SMatthias Ringwald static PyObject *quantize_py(PyObject *m, PyObject *args)
66*4930cef6SMatthias Ringwald {
67*4930cef6SMatthias Ringwald     PyObject *scf_obj, *y_obj, *yn_obj;
68*4930cef6SMatthias Ringwald     float *scf;
69*4930cef6SMatthias Ringwald     int lfcb_idx, hfcb_idx;
70*4930cef6SMatthias Ringwald     int shape_idx, gain_idx;
71*4930cef6SMatthias Ringwald     float (*yn)[16];
72*4930cef6SMatthias Ringwald     int (*y)[16];
73*4930cef6SMatthias Ringwald 
74*4930cef6SMatthias Ringwald     if (!PyArg_ParseTuple(args, "Oii", &scf_obj, &lfcb_idx, &hfcb_idx))
75*4930cef6SMatthias Ringwald         return NULL;
76*4930cef6SMatthias Ringwald 
77*4930cef6SMatthias Ringwald     CTYPES_CHECK("scf", to_1d_ptr(scf_obj, NPY_FLOAT, 16, &scf));
78*4930cef6SMatthias Ringwald     CTYPES_CHECK("lfcb_idx", (unsigned)lfcb_idx < 32);
79*4930cef6SMatthias Ringwald     CTYPES_CHECK("hfcb_idx", (unsigned)hfcb_idx < 32);
80*4930cef6SMatthias Ringwald 
81*4930cef6SMatthias Ringwald     y_obj = new_2d_ptr(NPY_INT, 4, 16, &y);
82*4930cef6SMatthias Ringwald     yn_obj = new_2d_ptr(NPY_FLOAT, 4, 16, &yn);
83*4930cef6SMatthias Ringwald 
84*4930cef6SMatthias Ringwald     quantize(scf, lfcb_idx, hfcb_idx,
85*4930cef6SMatthias Ringwald         y, yn, &shape_idx, &gain_idx);
86*4930cef6SMatthias Ringwald 
87*4930cef6SMatthias Ringwald     return Py_BuildValue("NNii", y_obj, yn_obj, shape_idx, gain_idx);
88*4930cef6SMatthias Ringwald }
89*4930cef6SMatthias Ringwald 
90*4930cef6SMatthias Ringwald static PyObject *unquantize_py(PyObject *m, PyObject *args)
91*4930cef6SMatthias Ringwald {
92*4930cef6SMatthias Ringwald     PyObject *y_obj, *scf_obj;
93*4930cef6SMatthias Ringwald     int lfcb_idx, hfcb_idx;
94*4930cef6SMatthias Ringwald     int shape, gain;
95*4930cef6SMatthias Ringwald     float *y, *scf;
96*4930cef6SMatthias Ringwald 
97*4930cef6SMatthias Ringwald     if (!PyArg_ParseTuple(args, "iiOii",
98*4930cef6SMatthias Ringwald                 &lfcb_idx, &hfcb_idx, &y_obj, &shape, &gain))
99*4930cef6SMatthias Ringwald         return NULL;
100*4930cef6SMatthias Ringwald 
101*4930cef6SMatthias Ringwald     CTYPES_CHECK("lfcb_idx", (unsigned)lfcb_idx < 32);
102*4930cef6SMatthias Ringwald     CTYPES_CHECK("hfcb_idx", (unsigned)hfcb_idx < 32);
103*4930cef6SMatthias Ringwald     CTYPES_CHECK("y", to_1d_ptr(y_obj, NPY_FLOAT, 16, &y));
104*4930cef6SMatthias Ringwald     CTYPES_CHECK("shape", (unsigned)shape < 4);
105*4930cef6SMatthias Ringwald     CTYPES_CHECK("gain",
106*4930cef6SMatthias Ringwald         (unsigned)gain < (unsigned)lc3_sns_vq_gains[shape].count);
107*4930cef6SMatthias Ringwald 
108*4930cef6SMatthias Ringwald     scf_obj = new_1d_ptr(NPY_FLOAT, 16, &scf);
109*4930cef6SMatthias Ringwald 
110*4930cef6SMatthias Ringwald     unquantize(lfcb_idx, hfcb_idx, y, shape, gain, scf);
111*4930cef6SMatthias Ringwald 
112*4930cef6SMatthias Ringwald     return Py_BuildValue("N", scf_obj);
113*4930cef6SMatthias Ringwald }
114*4930cef6SMatthias Ringwald 
115*4930cef6SMatthias Ringwald static PyObject *spectral_shaping_py(PyObject *m, PyObject *args)
116*4930cef6SMatthias Ringwald {
117*4930cef6SMatthias Ringwald     PyObject *scf_q_obj, *x_obj;
118*4930cef6SMatthias Ringwald     unsigned dt, sr;
119*4930cef6SMatthias Ringwald     float *scf_q, *x;
120*4930cef6SMatthias Ringwald     int inv;
121*4930cef6SMatthias Ringwald 
122*4930cef6SMatthias Ringwald     if (!PyArg_ParseTuple(args, "IIOpO", &dt, &sr, &scf_q_obj, &inv, &x_obj))
123*4930cef6SMatthias Ringwald         return NULL;
124*4930cef6SMatthias Ringwald 
125*4930cef6SMatthias Ringwald     CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
126*4930cef6SMatthias Ringwald     CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
127*4930cef6SMatthias Ringwald 
128*4930cef6SMatthias Ringwald     int ne = LC3_NE(dt, sr);
129*4930cef6SMatthias Ringwald 
130*4930cef6SMatthias Ringwald     CTYPES_CHECK("scf_q", to_1d_ptr(scf_q_obj, NPY_FLOAT, 16, &scf_q));
131*4930cef6SMatthias Ringwald     CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
132*4930cef6SMatthias Ringwald 
133*4930cef6SMatthias Ringwald     spectral_shaping(dt, sr, scf_q, inv, x, x);
134*4930cef6SMatthias Ringwald 
135*4930cef6SMatthias Ringwald     return Py_BuildValue("O", x_obj);
136*4930cef6SMatthias Ringwald }
137*4930cef6SMatthias Ringwald 
138*4930cef6SMatthias Ringwald static PyObject *analyze_py(PyObject *m, PyObject *args)
139*4930cef6SMatthias Ringwald {
140*4930cef6SMatthias Ringwald     PyObject *eb_obj, *x_obj;
141*4930cef6SMatthias Ringwald     struct lc3_sns_data data = { 0 };
142*4930cef6SMatthias Ringwald     unsigned dt, sr;
143*4930cef6SMatthias Ringwald     float *eb, *x;
144*4930cef6SMatthias Ringwald     int att;
145*4930cef6SMatthias Ringwald 
146*4930cef6SMatthias Ringwald     if (!PyArg_ParseTuple(args, "IIOpO", &dt, &sr, &eb_obj, &att, &x_obj))
147*4930cef6SMatthias Ringwald         return NULL;
148*4930cef6SMatthias Ringwald 
149*4930cef6SMatthias Ringwald     CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
150*4930cef6SMatthias Ringwald     CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
151*4930cef6SMatthias Ringwald 
152*4930cef6SMatthias Ringwald     int ne = LC3_NE(dt, sr);
153*4930cef6SMatthias Ringwald     int nb = LC3_MIN(ne, LC3_NUM_BANDS);
154*4930cef6SMatthias Ringwald 
155*4930cef6SMatthias Ringwald     CTYPES_CHECK("eb", to_1d_ptr(eb_obj, NPY_FLOAT, nb, &eb));
156*4930cef6SMatthias Ringwald     CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
157*4930cef6SMatthias Ringwald 
158*4930cef6SMatthias Ringwald     lc3_sns_analyze(dt, sr, eb, att, &data, x, x);
159*4930cef6SMatthias Ringwald 
160*4930cef6SMatthias Ringwald     return Py_BuildValue("ON", x_obj, new_sns_data(&data));
161*4930cef6SMatthias Ringwald }
162*4930cef6SMatthias Ringwald 
163*4930cef6SMatthias Ringwald static PyObject *synthesize_py(PyObject *m, PyObject *args)
164*4930cef6SMatthias Ringwald {
165*4930cef6SMatthias Ringwald     PyObject *data_obj, *x_obj;
166*4930cef6SMatthias Ringwald     struct lc3_sns_data data;
167*4930cef6SMatthias Ringwald     unsigned dt, sr;
168*4930cef6SMatthias Ringwald     float *x;
169*4930cef6SMatthias Ringwald 
170*4930cef6SMatthias Ringwald     if (!PyArg_ParseTuple(args, "IIOO", &dt, &sr, &data_obj, &x_obj))
171*4930cef6SMatthias Ringwald         return NULL;
172*4930cef6SMatthias Ringwald 
173*4930cef6SMatthias Ringwald     CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
174*4930cef6SMatthias Ringwald     CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
175*4930cef6SMatthias Ringwald     CTYPES_CHECK(NULL, data_obj = to_sns_data(data_obj, &data));
176*4930cef6SMatthias Ringwald 
177*4930cef6SMatthias Ringwald     int ne = LC3_NE(dt, sr);
178*4930cef6SMatthias Ringwald 
179*4930cef6SMatthias Ringwald     CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
180*4930cef6SMatthias Ringwald 
181*4930cef6SMatthias Ringwald     lc3_sns_synthesize(dt, sr, &data, x, x);
182*4930cef6SMatthias Ringwald 
183*4930cef6SMatthias Ringwald     return Py_BuildValue("O", x_obj);
184*4930cef6SMatthias Ringwald }
185*4930cef6SMatthias Ringwald 
186*4930cef6SMatthias Ringwald static PyObject *get_nbits_py(PyObject *m, PyObject *args)
187*4930cef6SMatthias Ringwald {
188*4930cef6SMatthias Ringwald     if (!PyArg_ParseTuple(args, ""))
189*4930cef6SMatthias Ringwald         return NULL;
190*4930cef6SMatthias Ringwald 
191*4930cef6SMatthias Ringwald     int nbits = lc3_sns_get_nbits();
192*4930cef6SMatthias Ringwald 
193*4930cef6SMatthias Ringwald     return Py_BuildValue("i", nbits);
194*4930cef6SMatthias Ringwald }
195*4930cef6SMatthias Ringwald 
196*4930cef6SMatthias Ringwald static PyMethodDef methods[] = {
197*4930cef6SMatthias Ringwald     { "sns_compute_scale_factors", compute_scale_factors_py, METH_VARARGS },
198*4930cef6SMatthias Ringwald     { "sns_resolve_codebooks"    , resolve_codebooks_py    , METH_VARARGS },
199*4930cef6SMatthias Ringwald     { "sns_quantize"             , quantize_py             , METH_VARARGS },
200*4930cef6SMatthias Ringwald     { "sns_unquantize"           , unquantize_py           , METH_VARARGS },
201*4930cef6SMatthias Ringwald     { "sns_spectral_shaping"     , spectral_shaping_py     , METH_VARARGS },
202*4930cef6SMatthias Ringwald     { "sns_analyze"              , analyze_py              , METH_VARARGS },
203*4930cef6SMatthias Ringwald     { "sns_synthesize"           , synthesize_py           , METH_VARARGS },
204*4930cef6SMatthias Ringwald     { "sns_get_nbits"            , get_nbits_py            , METH_VARARGS },
205*4930cef6SMatthias Ringwald     { NULL },
206*4930cef6SMatthias Ringwald };
207*4930cef6SMatthias Ringwald 
208*4930cef6SMatthias Ringwald PyMODINIT_FUNC lc3_sns_py_init(PyObject *m)
209*4930cef6SMatthias Ringwald {
210*4930cef6SMatthias Ringwald     import_array();
211*4930cef6SMatthias Ringwald 
212*4930cef6SMatthias Ringwald     PyModule_AddFunctions(m, methods);
213*4930cef6SMatthias Ringwald 
214*4930cef6SMatthias Ringwald     return m;
215*4930cef6SMatthias Ringwald }
216