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