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 <sns.c> 24 #include "ctypes.h" 25 26 static PyObject *compute_scale_factors_py(PyObject *m, PyObject *args) 27 { 28 unsigned dt, sr; 29 int nbytes, att; 30 PyObject *eb_obj, *scf_obj; 31 float *eb, *scf; 32 33 if (!PyArg_ParseTuple(args, "IIiOp", &dt, &sr, &nbytes, &eb_obj, &att)) 34 return NULL; 35 36 CTYPES_CHECK("dt", dt < LC3_NUM_DT); 37 CTYPES_CHECK("sr", sr < LC3_NUM_SRATE); 38 39 int nb = lc3_num_bands[dt][sr]; 40 41 CTYPES_CHECK("eb", to_1d_ptr(eb_obj, NPY_FLOAT, nb, &eb)); 42 scf_obj = new_1d_ptr(NPY_FLOAT, 16, &scf); 43 44 compute_scale_factors(dt, sr, nbytes, eb, att, scf); 45 46 return Py_BuildValue("N", scf_obj); 47 } 48 49 static PyObject *resolve_codebooks_py(PyObject *m, PyObject *args) 50 { 51 PyObject *scf_obj; 52 float *scf; 53 int lfcb_idx, hfcb_idx; 54 55 if (!PyArg_ParseTuple(args, "O", &scf_obj)) 56 return NULL; 57 58 CTYPES_CHECK("eb", to_1d_ptr(scf_obj, NPY_FLOAT, 16, &scf)); 59 60 resolve_codebooks(scf, &lfcb_idx, &hfcb_idx); 61 62 return Py_BuildValue("ii", lfcb_idx, hfcb_idx); 63 } 64 65 static PyObject *quantize_py(PyObject *m, PyObject *args) 66 { 67 PyObject *scf_obj, *y_obj, *yn_obj; 68 float *scf; 69 70 int lfcb_idx, hfcb_idx; 71 int shape_idx, gain_idx; 72 float (*yn)[16]; 73 int (*y)[16]; 74 75 if (!PyArg_ParseTuple(args, "Oii", &scf_obj, &lfcb_idx, &hfcb_idx)) 76 return NULL; 77 78 CTYPES_CHECK("scf", to_1d_ptr(scf_obj, NPY_FLOAT, 16, &scf)); 79 CTYPES_CHECK("lfcb_idx", (unsigned)lfcb_idx < 32); 80 CTYPES_CHECK("hfcb_idx", (unsigned)hfcb_idx < 32); 81 82 y_obj = new_2d_ptr(NPY_INT, 4, 16, &y); 83 yn_obj = new_2d_ptr(NPY_FLOAT, 4, 16, &yn); 84 85 quantize(scf, lfcb_idx, hfcb_idx, 86 y, yn, &shape_idx, &gain_idx); 87 88 return Py_BuildValue("NNii", y_obj, yn_obj, shape_idx, gain_idx); 89 } 90 91 static PyObject *unquantize_py(PyObject *m, PyObject *args) 92 { 93 PyObject *y_obj, *scf_obj; 94 int lfcb_idx, hfcb_idx; 95 int shape, gain; 96 float *y, *scf; 97 98 if (!PyArg_ParseTuple(args, "iiOii", 99 &lfcb_idx, &hfcb_idx, &y_obj, &shape, &gain)) 100 return NULL; 101 102 CTYPES_CHECK("lfcb_idx", (unsigned)lfcb_idx < 32); 103 CTYPES_CHECK("hfcb_idx", (unsigned)hfcb_idx < 32); 104 CTYPES_CHECK("y", to_1d_ptr(y_obj, NPY_FLOAT, 16, &y)); 105 CTYPES_CHECK("shape", (unsigned)shape < 4); 106 CTYPES_CHECK("gain", 107 (unsigned)gain < (unsigned)lc3_sns_vq_gains[shape].count); 108 109 scf_obj = new_1d_ptr(NPY_FLOAT, 16, &scf); 110 111 unquantize(lfcb_idx, hfcb_idx, y, shape, gain, scf); 112 113 return Py_BuildValue("N", scf_obj); 114 } 115 116 static PyObject *spectral_shaping_py(PyObject *m, PyObject *args) 117 { 118 PyObject *scf_q_obj, *x_obj; 119 unsigned dt, sr; 120 float *scf_q, *x; 121 int inv; 122 123 if (!PyArg_ParseTuple(args, "IIOpO", &dt, &sr, &scf_q_obj, &inv, &x_obj)) 124 return NULL; 125 126 CTYPES_CHECK("dt", dt < LC3_NUM_DT); 127 CTYPES_CHECK("sr", sr < LC3_NUM_SRATE); 128 129 int ne = lc3_ne(dt, sr); 130 131 CTYPES_CHECK("scf_q", to_1d_ptr(scf_q_obj, NPY_FLOAT, 16, &scf_q)); 132 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x)); 133 134 spectral_shaping(dt, sr, scf_q, inv, x, x); 135 136 return Py_BuildValue("O", x_obj); 137 } 138 139 static PyObject *analyze_py(PyObject *m, PyObject *args) 140 { 141 PyObject *eb_obj, *x_obj; 142 struct lc3_sns_data data = { 0 }; 143 unsigned dt, sr; 144 int nbytes, att; 145 float *eb, *x; 146 147 if (!PyArg_ParseTuple(args, "IIiOpO", 148 &dt, &sr, &nbytes, &eb_obj, &att, &x_obj)) 149 return NULL; 150 151 CTYPES_CHECK("dt", dt < LC3_NUM_DT); 152 CTYPES_CHECK("sr", sr < LC3_NUM_SRATE); 153 154 int ne = lc3_ne(dt, sr); 155 int nb = lc3_num_bands[dt][sr]; 156 157 CTYPES_CHECK("eb", to_1d_ptr(eb_obj, NPY_FLOAT, nb, &eb)); 158 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x)); 159 160 lc3_sns_analyze(dt, sr, nbytes, eb, att, &data, x, x); 161 162 return Py_BuildValue("ON", x_obj, new_sns_data(&data)); 163 } 164 165 static PyObject *synthesize_py(PyObject *m, PyObject *args) 166 { 167 PyObject *data_obj, *x_obj; 168 struct lc3_sns_data data; 169 unsigned dt, sr; 170 float *x; 171 172 if (!PyArg_ParseTuple(args, "IIOO", &dt, &sr, &data_obj, &x_obj)) 173 return NULL; 174 175 CTYPES_CHECK("dt", dt < LC3_NUM_DT); 176 CTYPES_CHECK("sr", sr < LC3_NUM_SRATE); 177 CTYPES_CHECK(NULL, data_obj = to_sns_data(data_obj, &data)); 178 179 int ne = lc3_ne(dt, sr); 180 181 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x)); 182 183 lc3_sns_synthesize(dt, sr, &data, x, x); 184 185 return Py_BuildValue("O", x_obj); 186 } 187 188 static PyObject *get_nbits_py(PyObject *m, PyObject *args) 189 { 190 if (!PyArg_ParseTuple(args, "")) 191 return NULL; 192 193 int nbits = lc3_sns_get_nbits(); 194 195 return Py_BuildValue("i", nbits); 196 } 197 198 static PyMethodDef methods[] = { 199 { "sns_compute_scale_factors", compute_scale_factors_py, METH_VARARGS }, 200 { "sns_resolve_codebooks" , resolve_codebooks_py , METH_VARARGS }, 201 { "sns_quantize" , quantize_py , METH_VARARGS }, 202 { "sns_unquantize" , unquantize_py , METH_VARARGS }, 203 { "sns_spectral_shaping" , spectral_shaping_py , METH_VARARGS }, 204 { "sns_analyze" , analyze_py , METH_VARARGS }, 205 { "sns_synthesize" , synthesize_py , METH_VARARGS }, 206 { "sns_get_nbits" , get_nbits_py , METH_VARARGS }, 207 { NULL }, 208 }; 209 210 PyMODINIT_FUNC lc3_sns_py_init(PyObject *m) 211 { 212 import_array(); 213 214 PyModule_AddFunctions(m, methods); 215 216 return m; 217 } 218