1 /******************************************************************************
2 *
3 * Copyright 2022 Google LLC
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #include "lc3.h"
20 #include <Python.h>
21 #include <numpy/ndarrayobject.h>
22
23 #include <tns.c>
24 #include "ctypes.h"
25
compute_lpc_coeffs_py(PyObject * m,PyObject * args)26 static PyObject *compute_lpc_coeffs_py(PyObject *m, PyObject *args)
27 {
28 PyObject *x_obj, *a_obj, *g_obj;
29 unsigned dt, bw;
30 float *x, *g, (*a)[9];
31
32 if (!PyArg_ParseTuple(args, "IIO", &dt, &bw, &x_obj))
33 return NULL;
34
35 CTYPES_CHECK("dt", dt < LC3_NUM_DT);
36 CTYPES_CHECK("sr", bw < LC3_NUM_BANDWIDTH);
37
38 int ne = lc3_ne(dt, bw);
39 int maxorder = dt <= LC3_DT_5M ? 4 : 8;
40
41 CTYPES_CHECK("x", to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
42
43 g_obj = new_1d_ptr(NPY_FLOAT, 2, &g);
44 a_obj = new_2d_ptr(NPY_FLOAT, 2, 9, &a);
45
46 compute_lpc_coeffs(dt, bw, maxorder, x, g, a);
47
48 return Py_BuildValue("NN", g_obj, a_obj);
49 }
50
lpc_reflection_py(PyObject * m,PyObject * args)51 static PyObject *lpc_reflection_py(PyObject *m, PyObject *args)
52 {
53 PyObject *a_obj, *rc_obj;
54 unsigned dt;
55 float *a, *rc;
56
57 if (!PyArg_ParseTuple(args, "IO", &dt, &a_obj))
58 return NULL;
59
60 CTYPES_CHECK("dt", dt < LC3_NUM_DT);
61
62 int maxorder = dt <= LC3_DT_5M ? 4 : 8;
63
64 CTYPES_CHECK("a", to_1d_ptr(a_obj, NPY_FLOAT, 9, &a));
65 rc_obj = new_1d_ptr(NPY_FLOAT, maxorder, &rc);
66
67 lpc_reflection(a, maxorder, rc);
68
69 return Py_BuildValue("N", rc_obj);
70 }
71
quantize_rc_py(PyObject * m,PyObject * args)72 static PyObject *quantize_rc_py(PyObject *m, PyObject *args)
73 {
74 PyObject *rc_obj, *rc_q_obj;
75 unsigned dt;
76 float *rc;
77 int rc_order, *rc_q;
78
79 if (!PyArg_ParseTuple(args, "iO", &dt, &rc_obj))
80 return NULL;
81
82 CTYPES_CHECK("dt", dt < LC3_NUM_DT);
83
84 int maxorder = dt <= LC3_DT_5M ? 4 : 8;
85
86 CTYPES_CHECK("rc", to_1d_ptr(rc_obj, NPY_FLOAT, 8, &rc));
87 rc_q_obj = new_1d_ptr(NPY_INT, 8, &rc_q);
88
89 quantize_rc(rc, maxorder, &rc_order, rc_q);
90
91 return Py_BuildValue("iN", rc_order, rc_q_obj);
92 }
93
unquantize_rc_py(PyObject * m,PyObject * args)94 static PyObject *unquantize_rc_py(PyObject *m, PyObject *args)
95 {
96 PyObject *rc_q_obj, *rc_obj;
97 int rc_order, *rc_q;
98 float *rc;
99
100 if (!PyArg_ParseTuple(args, "OI", &rc_q_obj, &rc_order))
101 return NULL;
102
103 CTYPES_CHECK("rc_q", to_1d_ptr(rc_q_obj, NPY_INT, 8, &rc_q));
104 CTYPES_CHECK("rc_order", (unsigned)rc_order <= 8);
105
106 rc_obj = new_1d_ptr(NPY_FLOAT, 8, &rc);
107
108 unquantize_rc(rc_q, rc_order, rc);
109
110 return Py_BuildValue("N", rc_obj);
111 }
112
analyze_py(PyObject * m,PyObject * args)113 static PyObject *analyze_py(PyObject *m, PyObject *args)
114 {
115 PyObject *x_obj;
116 struct lc3_tns_data data = { 0 };
117 unsigned dt, bw;
118 int nn_flag, nbytes;
119 float *x;
120
121 if (!PyArg_ParseTuple(args, "IIpiO",
122 &dt, &bw, &nn_flag, &nbytes, &x_obj))
123 return NULL;
124
125 CTYPES_CHECK("dt", dt < LC3_NUM_DT);
126 CTYPES_CHECK("bw", bw < LC3_NUM_BANDWIDTH);
127
128 int ne = lc3_ne(dt, bw);
129
130 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
131
132 lc3_tns_analyze(dt, bw, nn_flag, nbytes, &data, x);
133
134 return Py_BuildValue("ON", x_obj, new_tns_data(&data));
135 }
136
synthesize_py(PyObject * m,PyObject * args)137 static PyObject *synthesize_py(PyObject *m, PyObject *args)
138 {
139 PyObject *data_obj, *x_obj;
140 unsigned dt, bw;
141 struct lc3_tns_data data;
142 float *x;
143
144 if (!PyArg_ParseTuple(args, "IIOO", &dt, &bw, &data_obj, &x_obj))
145 return NULL;
146
147 CTYPES_CHECK("dt", dt < LC3_NUM_DT);
148 CTYPES_CHECK("bw", bw < LC3_NUM_BANDWIDTH);
149 CTYPES_CHECK(NULL, data_obj = to_tns_data(data_obj, &data));
150
151 int ne = lc3_ne(dt, bw);
152
153 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
154
155 lc3_tns_synthesize(dt, bw, &data, x);
156
157 return Py_BuildValue("O", x_obj);
158 }
159
get_nbits_py(PyObject * m,PyObject * args)160 static PyObject *get_nbits_py(PyObject *m, PyObject *args)
161 {
162 PyObject *data_obj;
163 struct lc3_tns_data data = { 0 };
164
165 if (!PyArg_ParseTuple(args, "O", &data_obj))
166 return NULL;
167
168 CTYPES_CHECK("data", to_tns_data(data_obj, &data));
169
170 int nbits = lc3_tns_get_nbits(&data);
171
172 return Py_BuildValue("i", nbits);
173 }
174
175 static PyMethodDef methods[] = {
176 { "tns_compute_lpc_coeffs", compute_lpc_coeffs_py, METH_VARARGS },
177 { "tns_lpc_reflection" , lpc_reflection_py , METH_VARARGS },
178 { "tns_quantize_rc" , quantize_rc_py , METH_VARARGS },
179 { "tns_unquantize_rc" , unquantize_rc_py , METH_VARARGS },
180 { "tns_analyze" , analyze_py , METH_VARARGS },
181 { "tns_synthesize" , synthesize_py , METH_VARARGS },
182 { "tns_get_nbits" , get_nbits_py , METH_VARARGS },
183 { NULL },
184 };
185
lc3_tns_py_init(PyObject * m)186 PyMODINIT_FUNC lc3_tns_py_init(PyObject *m)
187 {
188 import_array();
189
190 PyModule_AddFunctions(m, methods);
191
192 return m;
193 }
194