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 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 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 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 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 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 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 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 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