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", (unsigned)dt < LC3_NUM_DT);
36 CTYPES_CHECK("sr", (unsigned)bw < LC3_NUM_BANDWIDTH);
37
38 int ne = LC3_NE(dt, bw);
39
40 CTYPES_CHECK("x", to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
41
42 g_obj = new_1d_ptr(NPY_FLOAT, 2, &g);
43 a_obj = new_2d_ptr(NPY_FLOAT, 2, 9, &a);
44
45 compute_lpc_coeffs(dt, bw, x, g, a);
46
47 return Py_BuildValue("NN", g_obj, a_obj);
48 }
49
lpc_reflection_py(PyObject * m,PyObject * args)50 static PyObject *lpc_reflection_py(PyObject *m, PyObject *args)
51 {
52 PyObject *a_obj, *rc_obj;
53 float *a, *rc;
54
55 if (!PyArg_ParseTuple(args, "O", &a_obj))
56 return NULL;
57
58 CTYPES_CHECK("a", to_1d_ptr(a_obj, NPY_FLOAT, 9, &a));
59 rc_obj = new_1d_ptr(NPY_FLOAT, 8, &rc);
60
61 lpc_reflection(a, rc);
62
63 return Py_BuildValue("N", rc_obj);
64 }
65
quantize_rc_py(PyObject * m,PyObject * args)66 static PyObject *quantize_rc_py(PyObject *m, PyObject *args)
67 {
68 PyObject *rc_obj, *rc_q_obj;
69 float *rc;
70 int rc_order, *rc_q;
71
72 if (!PyArg_ParseTuple(args, "O", &rc_obj))
73 return NULL;
74
75 CTYPES_CHECK("rc", to_1d_ptr(rc_obj, NPY_FLOAT, 8, &rc));
76
77 rc_q_obj = new_1d_ptr(NPY_INT, 8, &rc_q);
78
79 quantize_rc(rc, &rc_order, rc_q);
80
81 return Py_BuildValue("iN", rc_order, rc_q_obj);
82 }
83
unquantize_rc_py(PyObject * m,PyObject * args)84 static PyObject *unquantize_rc_py(PyObject *m, PyObject *args)
85 {
86 PyObject *rc_q_obj, *rc_obj;
87 int rc_order, *rc_q;
88 float *rc;
89
90 if (!PyArg_ParseTuple(args, "OI", &rc_q_obj, &rc_order))
91 return NULL;
92
93 CTYPES_CHECK("rc_q", to_1d_ptr(rc_q_obj, NPY_INT, 8, &rc_q));
94 CTYPES_CHECK("rc_order", (unsigned)rc_order <= 8);
95
96 rc_obj = new_1d_ptr(NPY_FLOAT, 8, &rc);
97
98 unquantize_rc(rc_q, rc_order, rc);
99
100 return Py_BuildValue("N", rc_obj);
101 }
102
analyze_py(PyObject * m,PyObject * args)103 static PyObject *analyze_py(PyObject *m, PyObject *args)
104 {
105 PyObject *x_obj;
106 struct lc3_tns_data data = { 0 };
107 unsigned dt, bw;
108 int nn_flag;
109 unsigned nbytes;
110 float *x;
111
112 if (!PyArg_ParseTuple(args, "IIpIO", &dt, &bw, &nn_flag, &nbytes, &x_obj))
113 return NULL;
114
115 CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
116 CTYPES_CHECK("bw", (unsigned)bw < LC3_NUM_BANDWIDTH);
117
118 int ne = LC3_NE(dt, bw);
119
120 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
121
122 lc3_tns_analyze(dt, bw, nn_flag, nbytes, &data, x);
123
124 return Py_BuildValue("ON", x_obj, new_tns_data(&data));
125 }
126
synthesize_py(PyObject * m,PyObject * args)127 static PyObject *synthesize_py(PyObject *m, PyObject *args)
128 {
129 PyObject *data_obj, *x_obj;
130 unsigned dt, bw;
131 struct lc3_tns_data data;
132 float *x;
133
134 if (!PyArg_ParseTuple(args, "IIOO", &dt, &bw, &data_obj, &x_obj))
135 return NULL;
136
137 CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
138 CTYPES_CHECK("bw", (unsigned)bw < LC3_NUM_BANDWIDTH);
139 CTYPES_CHECK(NULL, data_obj = to_tns_data(data_obj, &data));
140
141 int ne = LC3_NE(dt, bw);
142
143 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
144
145 lc3_tns_synthesize(dt, bw, &data, x);
146
147 return Py_BuildValue("O", x_obj);
148 }
149
get_nbits_py(PyObject * m,PyObject * args)150 static PyObject *get_nbits_py(PyObject *m, PyObject *args)
151 {
152 PyObject *data_obj;
153 struct lc3_tns_data data = { 0 };
154
155 if (!PyArg_ParseTuple(args, "O", &data_obj))
156 return NULL;
157
158 CTYPES_CHECK("data", to_tns_data(data_obj, &data));
159
160 int nbits = lc3_tns_get_nbits(&data);
161
162 return Py_BuildValue("i", nbits);
163 }
164
165 static PyMethodDef methods[] = {
166 { "tns_compute_lpc_coeffs", compute_lpc_coeffs_py, METH_VARARGS },
167 { "tns_lpc_reflection" , lpc_reflection_py , METH_VARARGS },
168 { "tns_quantize_rc" , quantize_rc_py , METH_VARARGS },
169 { "tns_unquantize_rc" , unquantize_rc_py , METH_VARARGS },
170 { "tns_analyze" , analyze_py , METH_VARARGS },
171 { "tns_synthesize" , synthesize_py , METH_VARARGS },
172 { "tns_get_nbits" , get_nbits_py , METH_VARARGS },
173 { NULL },
174 };
175
lc3_tns_py_init(PyObject * m)176 PyMODINIT_FUNC lc3_tns_py_init(PyObject *m)
177 {
178 import_array();
179
180 PyModule_AddFunctions(m, methods);
181
182 return m;
183 }
184