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 <sns.c>
244930cef6SMatthias Ringwald #include "ctypes.h"
254930cef6SMatthias Ringwald
compute_scale_factors_py(PyObject * m,PyObject * args)264930cef6SMatthias Ringwald static PyObject *compute_scale_factors_py(PyObject *m, PyObject *args)
274930cef6SMatthias Ringwald {
284930cef6SMatthias Ringwald unsigned dt, sr;
29*6897da5cSDirk Helbig int nbytes, att;
304930cef6SMatthias Ringwald PyObject *eb_obj, *scf_obj;
314930cef6SMatthias Ringwald float *eb, *scf;
324930cef6SMatthias Ringwald
33*6897da5cSDirk Helbig if (!PyArg_ParseTuple(args, "IIiOp", &dt, &sr, &nbytes, &eb_obj, &att))
344930cef6SMatthias Ringwald return NULL;
354930cef6SMatthias Ringwald
36*6897da5cSDirk Helbig CTYPES_CHECK("dt", dt < LC3_NUM_DT);
37*6897da5cSDirk Helbig CTYPES_CHECK("sr", sr < LC3_NUM_SRATE);
384930cef6SMatthias Ringwald
39*6897da5cSDirk Helbig int nb = lc3_num_bands[dt][sr];
404930cef6SMatthias Ringwald
414930cef6SMatthias Ringwald CTYPES_CHECK("eb", to_1d_ptr(eb_obj, NPY_FLOAT, nb, &eb));
424930cef6SMatthias Ringwald scf_obj = new_1d_ptr(NPY_FLOAT, 16, &scf);
434930cef6SMatthias Ringwald
44*6897da5cSDirk Helbig compute_scale_factors(dt, sr, nbytes, eb, att, scf);
454930cef6SMatthias Ringwald
464930cef6SMatthias Ringwald return Py_BuildValue("N", scf_obj);
474930cef6SMatthias Ringwald }
484930cef6SMatthias Ringwald
resolve_codebooks_py(PyObject * m,PyObject * args)494930cef6SMatthias Ringwald static PyObject *resolve_codebooks_py(PyObject *m, PyObject *args)
504930cef6SMatthias Ringwald {
514930cef6SMatthias Ringwald PyObject *scf_obj;
524930cef6SMatthias Ringwald float *scf;
534930cef6SMatthias Ringwald int lfcb_idx, hfcb_idx;
544930cef6SMatthias Ringwald
554930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "O", &scf_obj))
564930cef6SMatthias Ringwald return NULL;
574930cef6SMatthias Ringwald
584930cef6SMatthias Ringwald CTYPES_CHECK("eb", to_1d_ptr(scf_obj, NPY_FLOAT, 16, &scf));
594930cef6SMatthias Ringwald
604930cef6SMatthias Ringwald resolve_codebooks(scf, &lfcb_idx, &hfcb_idx);
614930cef6SMatthias Ringwald
624930cef6SMatthias Ringwald return Py_BuildValue("ii", lfcb_idx, hfcb_idx);
634930cef6SMatthias Ringwald }
644930cef6SMatthias Ringwald
quantize_py(PyObject * m,PyObject * args)654930cef6SMatthias Ringwald static PyObject *quantize_py(PyObject *m, PyObject *args)
664930cef6SMatthias Ringwald {
674930cef6SMatthias Ringwald PyObject *scf_obj, *y_obj, *yn_obj;
684930cef6SMatthias Ringwald float *scf;
69*6897da5cSDirk Helbig
704930cef6SMatthias Ringwald int lfcb_idx, hfcb_idx;
714930cef6SMatthias Ringwald int shape_idx, gain_idx;
724930cef6SMatthias Ringwald float (*yn)[16];
734930cef6SMatthias Ringwald int (*y)[16];
744930cef6SMatthias Ringwald
754930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "Oii", &scf_obj, &lfcb_idx, &hfcb_idx))
764930cef6SMatthias Ringwald return NULL;
774930cef6SMatthias Ringwald
784930cef6SMatthias Ringwald CTYPES_CHECK("scf", to_1d_ptr(scf_obj, NPY_FLOAT, 16, &scf));
794930cef6SMatthias Ringwald CTYPES_CHECK("lfcb_idx", (unsigned)lfcb_idx < 32);
804930cef6SMatthias Ringwald CTYPES_CHECK("hfcb_idx", (unsigned)hfcb_idx < 32);
814930cef6SMatthias Ringwald
824930cef6SMatthias Ringwald y_obj = new_2d_ptr(NPY_INT, 4, 16, &y);
834930cef6SMatthias Ringwald yn_obj = new_2d_ptr(NPY_FLOAT, 4, 16, &yn);
844930cef6SMatthias Ringwald
854930cef6SMatthias Ringwald quantize(scf, lfcb_idx, hfcb_idx,
864930cef6SMatthias Ringwald y, yn, &shape_idx, &gain_idx);
874930cef6SMatthias Ringwald
884930cef6SMatthias Ringwald return Py_BuildValue("NNii", y_obj, yn_obj, shape_idx, gain_idx);
894930cef6SMatthias Ringwald }
904930cef6SMatthias Ringwald
unquantize_py(PyObject * m,PyObject * args)914930cef6SMatthias Ringwald static PyObject *unquantize_py(PyObject *m, PyObject *args)
924930cef6SMatthias Ringwald {
934930cef6SMatthias Ringwald PyObject *y_obj, *scf_obj;
944930cef6SMatthias Ringwald int lfcb_idx, hfcb_idx;
954930cef6SMatthias Ringwald int shape, gain;
964930cef6SMatthias Ringwald float *y, *scf;
974930cef6SMatthias Ringwald
984930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "iiOii",
994930cef6SMatthias Ringwald &lfcb_idx, &hfcb_idx, &y_obj, &shape, &gain))
1004930cef6SMatthias Ringwald return NULL;
1014930cef6SMatthias Ringwald
1024930cef6SMatthias Ringwald CTYPES_CHECK("lfcb_idx", (unsigned)lfcb_idx < 32);
1034930cef6SMatthias Ringwald CTYPES_CHECK("hfcb_idx", (unsigned)hfcb_idx < 32);
1044930cef6SMatthias Ringwald CTYPES_CHECK("y", to_1d_ptr(y_obj, NPY_FLOAT, 16, &y));
1054930cef6SMatthias Ringwald CTYPES_CHECK("shape", (unsigned)shape < 4);
1064930cef6SMatthias Ringwald CTYPES_CHECK("gain",
1074930cef6SMatthias Ringwald (unsigned)gain < (unsigned)lc3_sns_vq_gains[shape].count);
1084930cef6SMatthias Ringwald
1094930cef6SMatthias Ringwald scf_obj = new_1d_ptr(NPY_FLOAT, 16, &scf);
1104930cef6SMatthias Ringwald
1114930cef6SMatthias Ringwald unquantize(lfcb_idx, hfcb_idx, y, shape, gain, scf);
1124930cef6SMatthias Ringwald
1134930cef6SMatthias Ringwald return Py_BuildValue("N", scf_obj);
1144930cef6SMatthias Ringwald }
1154930cef6SMatthias Ringwald
spectral_shaping_py(PyObject * m,PyObject * args)1164930cef6SMatthias Ringwald static PyObject *spectral_shaping_py(PyObject *m, PyObject *args)
1174930cef6SMatthias Ringwald {
1184930cef6SMatthias Ringwald PyObject *scf_q_obj, *x_obj;
1194930cef6SMatthias Ringwald unsigned dt, sr;
1204930cef6SMatthias Ringwald float *scf_q, *x;
1214930cef6SMatthias Ringwald int inv;
1224930cef6SMatthias Ringwald
1234930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "IIOpO", &dt, &sr, &scf_q_obj, &inv, &x_obj))
1244930cef6SMatthias Ringwald return NULL;
1254930cef6SMatthias Ringwald
126*6897da5cSDirk Helbig CTYPES_CHECK("dt", dt < LC3_NUM_DT);
127*6897da5cSDirk Helbig CTYPES_CHECK("sr", sr < LC3_NUM_SRATE);
1284930cef6SMatthias Ringwald
129*6897da5cSDirk Helbig int ne = lc3_ne(dt, sr);
1304930cef6SMatthias Ringwald
1314930cef6SMatthias Ringwald CTYPES_CHECK("scf_q", to_1d_ptr(scf_q_obj, NPY_FLOAT, 16, &scf_q));
1324930cef6SMatthias Ringwald CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
1334930cef6SMatthias Ringwald
1344930cef6SMatthias Ringwald spectral_shaping(dt, sr, scf_q, inv, x, x);
1354930cef6SMatthias Ringwald
1364930cef6SMatthias Ringwald return Py_BuildValue("O", x_obj);
1374930cef6SMatthias Ringwald }
1384930cef6SMatthias Ringwald
analyze_py(PyObject * m,PyObject * args)1394930cef6SMatthias Ringwald static PyObject *analyze_py(PyObject *m, PyObject *args)
1404930cef6SMatthias Ringwald {
1414930cef6SMatthias Ringwald PyObject *eb_obj, *x_obj;
1424930cef6SMatthias Ringwald struct lc3_sns_data data = { 0 };
1434930cef6SMatthias Ringwald unsigned dt, sr;
144*6897da5cSDirk Helbig int nbytes, att;
1454930cef6SMatthias Ringwald float *eb, *x;
1464930cef6SMatthias Ringwald
147*6897da5cSDirk Helbig if (!PyArg_ParseTuple(args, "IIiOpO",
148*6897da5cSDirk Helbig &dt, &sr, &nbytes, &eb_obj, &att, &x_obj))
1494930cef6SMatthias Ringwald return NULL;
1504930cef6SMatthias Ringwald
151*6897da5cSDirk Helbig CTYPES_CHECK("dt", dt < LC3_NUM_DT);
152*6897da5cSDirk Helbig CTYPES_CHECK("sr", sr < LC3_NUM_SRATE);
1534930cef6SMatthias Ringwald
154*6897da5cSDirk Helbig int ne = lc3_ne(dt, sr);
155*6897da5cSDirk Helbig int nb = lc3_num_bands[dt][sr];
1564930cef6SMatthias Ringwald
1574930cef6SMatthias Ringwald CTYPES_CHECK("eb", to_1d_ptr(eb_obj, NPY_FLOAT, nb, &eb));
1584930cef6SMatthias Ringwald CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
1594930cef6SMatthias Ringwald
160*6897da5cSDirk Helbig lc3_sns_analyze(dt, sr, nbytes, eb, att, &data, x, x);
1614930cef6SMatthias Ringwald
1624930cef6SMatthias Ringwald return Py_BuildValue("ON", x_obj, new_sns_data(&data));
1634930cef6SMatthias Ringwald }
1644930cef6SMatthias Ringwald
synthesize_py(PyObject * m,PyObject * args)1654930cef6SMatthias Ringwald static PyObject *synthesize_py(PyObject *m, PyObject *args)
1664930cef6SMatthias Ringwald {
1674930cef6SMatthias Ringwald PyObject *data_obj, *x_obj;
1684930cef6SMatthias Ringwald struct lc3_sns_data data;
1694930cef6SMatthias Ringwald unsigned dt, sr;
1704930cef6SMatthias Ringwald float *x;
1714930cef6SMatthias Ringwald
1724930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "IIOO", &dt, &sr, &data_obj, &x_obj))
1734930cef6SMatthias Ringwald return NULL;
1744930cef6SMatthias Ringwald
175*6897da5cSDirk Helbig CTYPES_CHECK("dt", dt < LC3_NUM_DT);
176*6897da5cSDirk Helbig CTYPES_CHECK("sr", sr < LC3_NUM_SRATE);
1774930cef6SMatthias Ringwald CTYPES_CHECK(NULL, data_obj = to_sns_data(data_obj, &data));
1784930cef6SMatthias Ringwald
179*6897da5cSDirk Helbig int ne = lc3_ne(dt, sr);
1804930cef6SMatthias Ringwald
1814930cef6SMatthias Ringwald CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, ne, &x));
1824930cef6SMatthias Ringwald
1834930cef6SMatthias Ringwald lc3_sns_synthesize(dt, sr, &data, x, x);
1844930cef6SMatthias Ringwald
1854930cef6SMatthias Ringwald return Py_BuildValue("O", x_obj);
1864930cef6SMatthias Ringwald }
1874930cef6SMatthias Ringwald
get_nbits_py(PyObject * m,PyObject * args)1884930cef6SMatthias Ringwald static PyObject *get_nbits_py(PyObject *m, PyObject *args)
1894930cef6SMatthias Ringwald {
1904930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, ""))
1914930cef6SMatthias Ringwald return NULL;
1924930cef6SMatthias Ringwald
1934930cef6SMatthias Ringwald int nbits = lc3_sns_get_nbits();
1944930cef6SMatthias Ringwald
1954930cef6SMatthias Ringwald return Py_BuildValue("i", nbits);
1964930cef6SMatthias Ringwald }
1974930cef6SMatthias Ringwald
1984930cef6SMatthias Ringwald static PyMethodDef methods[] = {
1994930cef6SMatthias Ringwald { "sns_compute_scale_factors", compute_scale_factors_py, METH_VARARGS },
2004930cef6SMatthias Ringwald { "sns_resolve_codebooks" , resolve_codebooks_py , METH_VARARGS },
2014930cef6SMatthias Ringwald { "sns_quantize" , quantize_py , METH_VARARGS },
2024930cef6SMatthias Ringwald { "sns_unquantize" , unquantize_py , METH_VARARGS },
2034930cef6SMatthias Ringwald { "sns_spectral_shaping" , spectral_shaping_py , METH_VARARGS },
2044930cef6SMatthias Ringwald { "sns_analyze" , analyze_py , METH_VARARGS },
2054930cef6SMatthias Ringwald { "sns_synthesize" , synthesize_py , METH_VARARGS },
2064930cef6SMatthias Ringwald { "sns_get_nbits" , get_nbits_py , METH_VARARGS },
2074930cef6SMatthias Ringwald { NULL },
2084930cef6SMatthias Ringwald };
2094930cef6SMatthias Ringwald
lc3_sns_py_init(PyObject * m)2104930cef6SMatthias Ringwald PyMODINIT_FUNC lc3_sns_py_init(PyObject *m)
2114930cef6SMatthias Ringwald {
2124930cef6SMatthias Ringwald import_array();
2134930cef6SMatthias Ringwald
2144930cef6SMatthias Ringwald PyModule_AddFunctions(m, methods);
2154930cef6SMatthias Ringwald
2164930cef6SMatthias Ringwald return m;
2174930cef6SMatthias Ringwald }
218