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 <spec.c> 24 #include "ctypes.h" 25 26 static PyObject *estimate_gain_py(PyObject *m, PyObject *args) 27 { 28 unsigned dt, sr; 29 int nbytes, nbits_budget, g_off; 30 float nbits_off; 31 PyObject *x_obj; 32 float *x; 33 34 if (!PyArg_ParseTuple(args, "IIOiifi", &dt, &sr, 35 &x_obj, &nbytes, &nbits_budget, &nbits_off, &g_off)) 36 return NULL; 37 38 CTYPES_CHECK("dt", dt < LC3_NUM_DT); 39 CTYPES_CHECK("sr", sr < LC3_NUM_SRATE); 40 41 int ne = lc3_ne(dt, sr); 42 43 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x)); 44 45 int g_min; 46 bool reset_off; 47 48 int g_int = estimate_gain(dt, sr, 49 x, nbytes, nbits_budget, nbits_off, g_off, &reset_off, &g_min); 50 51 return Py_BuildValue("iii", g_int, reset_off, g_min); 52 } 53 54 static PyObject *adjust_gain_py(PyObject *m, PyObject *args) 55 { 56 unsigned dt, sr; 57 int g_idx, nbits, nbits_budget, g_idx_min; 58 59 if (!PyArg_ParseTuple(args, "IIiiii", &dt, &sr, 60 &g_idx, &nbits, &nbits_budget, &g_idx_min)) 61 return NULL; 62 63 CTYPES_CHECK("dt", dt < LC3_NUM_DT); 64 CTYPES_CHECK("sr", sr < LC3_NUM_SRATE); 65 CTYPES_CHECK("g_idx", g_idx >= 0 && g_idx <= 255); 66 67 g_idx = adjust_gain(dt, sr, g_idx, nbits, nbits_budget, g_idx_min); 68 69 return Py_BuildValue("i", g_idx); 70 } 71 72 static PyObject *quantize_py(PyObject *m, PyObject *args) 73 { 74 unsigned dt, sr; 75 int g_int; 76 PyObject *x_obj; 77 float *x; 78 int nq; 79 80 if (!PyArg_ParseTuple(args, "IIiO", &dt, &sr, &g_int, &x_obj)) 81 return NULL; 82 83 CTYPES_CHECK("dt", dt < LC3_NUM_DT); 84 CTYPES_CHECK("sr", sr < LC3_NUM_SRATE); 85 CTYPES_CHECK("g_int", g_int >= -255 && g_int <= 255); 86 87 int ne = lc3_ne(dt, sr); 88 89 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x)); 90 91 quantize(dt, sr, g_int, x, &nq); 92 93 return Py_BuildValue("Oi", x_obj, nq); 94 } 95 96 static PyObject *compute_nbits_py(PyObject *m, PyObject *args) 97 { 98 unsigned dt, sr; 99 int nbytes, nq, nbits_budget; 100 PyObject *x_obj; 101 float *x; 102 103 if (!PyArg_ParseTuple(args, "IIiOii", &dt, &sr, 104 &nbytes, &x_obj, &nq, &nbits_budget)) 105 return NULL; 106 107 CTYPES_CHECK("dt", dt < LC3_NUM_DT); 108 CTYPES_CHECK("sr", sr < LC3_NUM_SRATE); 109 110 int ne = lc3_ne(dt, sr); 111 112 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x)); 113 114 bool lsb_mode; 115 116 int nbits = compute_nbits( 117 dt, sr, nbytes, x, &nq, nbits_budget, &lsb_mode); 118 119 return Py_BuildValue("iii", nbits, nq, lsb_mode); 120 } 121 122 static PyObject *analyze_py(PyObject *m, PyObject *args) 123 { 124 unsigned dt, sr; 125 int nbytes, pitch; 126 127 PyObject *tns_obj, *spec_obj, *x_obj; 128 struct lc3_tns_data tns = { 0 }; 129 struct lc3_spec_analysis spec = { 0 }; 130 struct lc3_spec_side side = { 0 }; 131 float *x; 132 133 if (!PyArg_ParseTuple(args, "IIipOOO", &dt, &sr, 134 &nbytes, &pitch, &tns_obj, &spec_obj, &x_obj)) 135 return NULL; 136 137 CTYPES_CHECK("dt", dt < LC3_NUM_DT); 138 CTYPES_CHECK("sr", sr < LC3_NUM_SRATE); 139 140 int ne = lc3_ne(dt, sr); 141 142 CTYPES_CHECK(NULL, tns_obj = to_tns_data(tns_obj, &tns)); 143 CTYPES_CHECK(NULL, spec_obj = to_spec_analysis(spec_obj, &spec)); 144 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x)); 145 146 lc3_spec_analyze(dt, sr, nbytes, pitch, &tns, &spec, x, &side); 147 148 from_spec_analysis(spec_obj, &spec); 149 return Py_BuildValue("ON", x_obj, new_spec_side(&side)); 150 } 151 152 static PyObject *estimate_noise_py(PyObject *m, PyObject *args) 153 { 154 unsigned dt, bw; 155 PyObject *x_obj; 156 float *x; 157 int hrmode, n; 158 159 if (!PyArg_ParseTuple(args, "IIpOI", 160 &dt, &bw, &hrmode, &x_obj, &n)) 161 return NULL; 162 163 CTYPES_CHECK("dt", dt < LC3_NUM_DT); 164 CTYPES_CHECK("bw", bw < LC3_NUM_BANDWIDTH); 165 166 int ne = lc3_ne(dt, bw); 167 168 CTYPES_CHECK("x" , x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x )); 169 170 int noise_factor = estimate_noise(dt, bw, hrmode, x, n); 171 172 return Py_BuildValue("i", noise_factor); 173 } 174 175 static PyMethodDef methods[] = { 176 { "spec_estimate_gain" , estimate_gain_py , METH_VARARGS }, 177 { "spec_adjust_gain" , adjust_gain_py , METH_VARARGS }, 178 { "spec_quantize" , quantize_py , METH_VARARGS }, 179 { "spec_compute_nbits" , compute_nbits_py , METH_VARARGS }, 180 { "spec_analyze" , analyze_py , METH_VARARGS }, 181 { "spec_estimate_noise", estimate_noise_py, METH_VARARGS }, 182 { NULL }, 183 }; 184 185 PyMODINIT_FUNC lc3_spec_py_init(PyObject *m) 186 { 187 import_array(); 188 189 PyModule_AddFunctions(m, methods); 190 191 return m; 192 } 193