14930cef6SMatthias Ringwald /******************************************************************************
24930cef6SMatthias Ringwald *
34930cef6SMatthias Ringwald * Copyright 2022 Google LLC
44930cef6SMatthias Ringwald *
54930cef6SMatthias Ringwald * Licensed under the Apache License, Version 2.0 (the "License");
64930cef6SMatthias Ringwald * you may not use this file except in compliance with the License.
74930cef6SMatthias Ringwald * You may obtain a copy of the License at:
84930cef6SMatthias Ringwald *
94930cef6SMatthias Ringwald * http://www.apache.org/licenses/LICENSE-2.0
104930cef6SMatthias Ringwald *
114930cef6SMatthias Ringwald * Unless required by applicable law or agreed to in writing, software
124930cef6SMatthias Ringwald * distributed under the License is distributed on an "AS IS" BASIS,
134930cef6SMatthias Ringwald * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144930cef6SMatthias Ringwald * See the License for the specific language governing permissions and
154930cef6SMatthias Ringwald * limitations under the License.
164930cef6SMatthias Ringwald *
174930cef6SMatthias Ringwald ******************************************************************************/
184930cef6SMatthias Ringwald
194930cef6SMatthias Ringwald #include "lc3.h"
204930cef6SMatthias Ringwald #include <Python.h>
214930cef6SMatthias Ringwald #include <numpy/ndarrayobject.h>
224930cef6SMatthias Ringwald
234930cef6SMatthias Ringwald #include <tns.c>
244930cef6SMatthias Ringwald #include "ctypes.h"
254930cef6SMatthias Ringwald
compute_lpc_coeffs_py(PyObject * m,PyObject * args)264930cef6SMatthias Ringwald static PyObject *compute_lpc_coeffs_py(PyObject *m, PyObject *args)
274930cef6SMatthias Ringwald {
284930cef6SMatthias Ringwald PyObject *x_obj, *a_obj, *g_obj;
294930cef6SMatthias Ringwald unsigned dt, bw;
304930cef6SMatthias Ringwald float *x, *g, (*a)[9];
314930cef6SMatthias Ringwald
324930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "IIO", &dt, &bw, &x_obj))
334930cef6SMatthias Ringwald return NULL;
344930cef6SMatthias Ringwald
35*6897da5cSDirk Helbig CTYPES_CHECK("dt", dt < LC3_NUM_DT);
36*6897da5cSDirk Helbig CTYPES_CHECK("sr", bw < LC3_NUM_BANDWIDTH);
374930cef6SMatthias Ringwald
38*6897da5cSDirk Helbig int ne = lc3_ne(dt, bw);
39*6897da5cSDirk Helbig int maxorder = dt <= LC3_DT_5M ? 4 : 8;
404930cef6SMatthias Ringwald
414930cef6SMatthias Ringwald CTYPES_CHECK("x", to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
424930cef6SMatthias Ringwald
434930cef6SMatthias Ringwald g_obj = new_1d_ptr(NPY_FLOAT, 2, &g);
444930cef6SMatthias Ringwald a_obj = new_2d_ptr(NPY_FLOAT, 2, 9, &a);
454930cef6SMatthias Ringwald
46*6897da5cSDirk Helbig compute_lpc_coeffs(dt, bw, maxorder, x, g, a);
474930cef6SMatthias Ringwald
484930cef6SMatthias Ringwald return Py_BuildValue("NN", g_obj, a_obj);
494930cef6SMatthias Ringwald }
504930cef6SMatthias Ringwald
lpc_reflection_py(PyObject * m,PyObject * args)514930cef6SMatthias Ringwald static PyObject *lpc_reflection_py(PyObject *m, PyObject *args)
524930cef6SMatthias Ringwald {
534930cef6SMatthias Ringwald PyObject *a_obj, *rc_obj;
54*6897da5cSDirk Helbig unsigned dt;
554930cef6SMatthias Ringwald float *a, *rc;
564930cef6SMatthias Ringwald
57*6897da5cSDirk Helbig if (!PyArg_ParseTuple(args, "IO", &dt, &a_obj))
584930cef6SMatthias Ringwald return NULL;
594930cef6SMatthias Ringwald
60*6897da5cSDirk Helbig CTYPES_CHECK("dt", dt < LC3_NUM_DT);
614930cef6SMatthias Ringwald
62*6897da5cSDirk Helbig int maxorder = dt <= LC3_DT_5M ? 4 : 8;
63*6897da5cSDirk Helbig
64*6897da5cSDirk Helbig CTYPES_CHECK("a", to_1d_ptr(a_obj, NPY_FLOAT, 9, &a));
65*6897da5cSDirk Helbig rc_obj = new_1d_ptr(NPY_FLOAT, maxorder, &rc);
66*6897da5cSDirk Helbig
67*6897da5cSDirk Helbig lpc_reflection(a, maxorder, rc);
684930cef6SMatthias Ringwald
694930cef6SMatthias Ringwald return Py_BuildValue("N", rc_obj);
704930cef6SMatthias Ringwald }
714930cef6SMatthias Ringwald
quantize_rc_py(PyObject * m,PyObject * args)724930cef6SMatthias Ringwald static PyObject *quantize_rc_py(PyObject *m, PyObject *args)
734930cef6SMatthias Ringwald {
744930cef6SMatthias Ringwald PyObject *rc_obj, *rc_q_obj;
75*6897da5cSDirk Helbig unsigned dt;
764930cef6SMatthias Ringwald float *rc;
774930cef6SMatthias Ringwald int rc_order, *rc_q;
784930cef6SMatthias Ringwald
79*6897da5cSDirk Helbig if (!PyArg_ParseTuple(args, "iO", &dt, &rc_obj))
804930cef6SMatthias Ringwald return NULL;
814930cef6SMatthias Ringwald
82*6897da5cSDirk Helbig CTYPES_CHECK("dt", dt < LC3_NUM_DT);
834930cef6SMatthias Ringwald
84*6897da5cSDirk Helbig int maxorder = dt <= LC3_DT_5M ? 4 : 8;
85*6897da5cSDirk Helbig
86*6897da5cSDirk Helbig CTYPES_CHECK("rc", to_1d_ptr(rc_obj, NPY_FLOAT, 8, &rc));
874930cef6SMatthias Ringwald rc_q_obj = new_1d_ptr(NPY_INT, 8, &rc_q);
884930cef6SMatthias Ringwald
89*6897da5cSDirk Helbig quantize_rc(rc, maxorder, &rc_order, rc_q);
904930cef6SMatthias Ringwald
914930cef6SMatthias Ringwald return Py_BuildValue("iN", rc_order, rc_q_obj);
924930cef6SMatthias Ringwald }
934930cef6SMatthias Ringwald
unquantize_rc_py(PyObject * m,PyObject * args)944930cef6SMatthias Ringwald static PyObject *unquantize_rc_py(PyObject *m, PyObject *args)
954930cef6SMatthias Ringwald {
964930cef6SMatthias Ringwald PyObject *rc_q_obj, *rc_obj;
974930cef6SMatthias Ringwald int rc_order, *rc_q;
984930cef6SMatthias Ringwald float *rc;
994930cef6SMatthias Ringwald
1004930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "OI", &rc_q_obj, &rc_order))
1014930cef6SMatthias Ringwald return NULL;
1024930cef6SMatthias Ringwald
1034930cef6SMatthias Ringwald CTYPES_CHECK("rc_q", to_1d_ptr(rc_q_obj, NPY_INT, 8, &rc_q));
1044930cef6SMatthias Ringwald CTYPES_CHECK("rc_order", (unsigned)rc_order <= 8);
1054930cef6SMatthias Ringwald
1064930cef6SMatthias Ringwald rc_obj = new_1d_ptr(NPY_FLOAT, 8, &rc);
1074930cef6SMatthias Ringwald
1084930cef6SMatthias Ringwald unquantize_rc(rc_q, rc_order, rc);
1094930cef6SMatthias Ringwald
1104930cef6SMatthias Ringwald return Py_BuildValue("N", rc_obj);
1114930cef6SMatthias Ringwald }
1124930cef6SMatthias Ringwald
analyze_py(PyObject * m,PyObject * args)1134930cef6SMatthias Ringwald static PyObject *analyze_py(PyObject *m, PyObject *args)
1144930cef6SMatthias Ringwald {
1154930cef6SMatthias Ringwald PyObject *x_obj;
1164930cef6SMatthias Ringwald struct lc3_tns_data data = { 0 };
1174930cef6SMatthias Ringwald unsigned dt, bw;
118*6897da5cSDirk Helbig int nn_flag, nbytes;
1194930cef6SMatthias Ringwald float *x;
1204930cef6SMatthias Ringwald
121*6897da5cSDirk Helbig if (!PyArg_ParseTuple(args, "IIpiO",
122*6897da5cSDirk Helbig &dt, &bw, &nn_flag, &nbytes, &x_obj))
1234930cef6SMatthias Ringwald return NULL;
1244930cef6SMatthias Ringwald
125*6897da5cSDirk Helbig CTYPES_CHECK("dt", dt < LC3_NUM_DT);
126*6897da5cSDirk Helbig CTYPES_CHECK("bw", bw < LC3_NUM_BANDWIDTH);
1274930cef6SMatthias Ringwald
128*6897da5cSDirk Helbig int ne = lc3_ne(dt, bw);
1294930cef6SMatthias Ringwald
1304930cef6SMatthias Ringwald CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
1314930cef6SMatthias Ringwald
1324930cef6SMatthias Ringwald lc3_tns_analyze(dt, bw, nn_flag, nbytes, &data, x);
1334930cef6SMatthias Ringwald
1344930cef6SMatthias Ringwald return Py_BuildValue("ON", x_obj, new_tns_data(&data));
1354930cef6SMatthias Ringwald }
1364930cef6SMatthias Ringwald
synthesize_py(PyObject * m,PyObject * args)1374930cef6SMatthias Ringwald static PyObject *synthesize_py(PyObject *m, PyObject *args)
1384930cef6SMatthias Ringwald {
1394930cef6SMatthias Ringwald PyObject *data_obj, *x_obj;
1404930cef6SMatthias Ringwald unsigned dt, bw;
1414930cef6SMatthias Ringwald struct lc3_tns_data data;
1424930cef6SMatthias Ringwald float *x;
1434930cef6SMatthias Ringwald
1444930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "IIOO", &dt, &bw, &data_obj, &x_obj))
1454930cef6SMatthias Ringwald return NULL;
1464930cef6SMatthias Ringwald
147*6897da5cSDirk Helbig CTYPES_CHECK("dt", dt < LC3_NUM_DT);
148*6897da5cSDirk Helbig CTYPES_CHECK("bw", bw < LC3_NUM_BANDWIDTH);
1494930cef6SMatthias Ringwald CTYPES_CHECK(NULL, data_obj = to_tns_data(data_obj, &data));
1504930cef6SMatthias Ringwald
151*6897da5cSDirk Helbig int ne = lc3_ne(dt, bw);
1524930cef6SMatthias Ringwald
1534930cef6SMatthias Ringwald CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
1544930cef6SMatthias Ringwald
1554930cef6SMatthias Ringwald lc3_tns_synthesize(dt, bw, &data, x);
1564930cef6SMatthias Ringwald
1574930cef6SMatthias Ringwald return Py_BuildValue("O", x_obj);
1584930cef6SMatthias Ringwald }
1594930cef6SMatthias Ringwald
get_nbits_py(PyObject * m,PyObject * args)1604930cef6SMatthias Ringwald static PyObject *get_nbits_py(PyObject *m, PyObject *args)
1614930cef6SMatthias Ringwald {
1624930cef6SMatthias Ringwald PyObject *data_obj;
1634930cef6SMatthias Ringwald struct lc3_tns_data data = { 0 };
1644930cef6SMatthias Ringwald
1654930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "O", &data_obj))
1664930cef6SMatthias Ringwald return NULL;
1674930cef6SMatthias Ringwald
1684930cef6SMatthias Ringwald CTYPES_CHECK("data", to_tns_data(data_obj, &data));
1694930cef6SMatthias Ringwald
1704930cef6SMatthias Ringwald int nbits = lc3_tns_get_nbits(&data);
1714930cef6SMatthias Ringwald
1724930cef6SMatthias Ringwald return Py_BuildValue("i", nbits);
1734930cef6SMatthias Ringwald }
1744930cef6SMatthias Ringwald
1754930cef6SMatthias Ringwald static PyMethodDef methods[] = {
1764930cef6SMatthias Ringwald { "tns_compute_lpc_coeffs", compute_lpc_coeffs_py, METH_VARARGS },
1774930cef6SMatthias Ringwald { "tns_lpc_reflection" , lpc_reflection_py , METH_VARARGS },
1784930cef6SMatthias Ringwald { "tns_quantize_rc" , quantize_rc_py , METH_VARARGS },
1794930cef6SMatthias Ringwald { "tns_unquantize_rc" , unquantize_rc_py , METH_VARARGS },
1804930cef6SMatthias Ringwald { "tns_analyze" , analyze_py , METH_VARARGS },
1814930cef6SMatthias Ringwald { "tns_synthesize" , synthesize_py , METH_VARARGS },
1824930cef6SMatthias Ringwald { "tns_get_nbits" , get_nbits_py , METH_VARARGS },
1834930cef6SMatthias Ringwald { NULL },
1844930cef6SMatthias Ringwald };
1854930cef6SMatthias Ringwald
lc3_tns_py_init(PyObject * m)1864930cef6SMatthias Ringwald PyMODINIT_FUNC lc3_tns_py_init(PyObject *m)
1874930cef6SMatthias Ringwald {
1884930cef6SMatthias Ringwald import_array();
1894930cef6SMatthias Ringwald
1904930cef6SMatthias Ringwald PyModule_AddFunctions(m, methods);
1914930cef6SMatthias Ringwald
1924930cef6SMatthias Ringwald return m;
1934930cef6SMatthias Ringwald }
194