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
214930cef6SMatthias Ringwald #define PY_SSIZE_T_CLEAN
224930cef6SMatthias Ringwald #include <Python.h>
234930cef6SMatthias Ringwald #include <numpy/ndarrayobject.h>
244930cef6SMatthias Ringwald
254930cef6SMatthias Ringwald #include <lc3.c>
264930cef6SMatthias Ringwald
274930cef6SMatthias Ringwald #define __CTYPES_LC3_C
284930cef6SMatthias Ringwald #include "ctypes.h"
294930cef6SMatthias Ringwald
setup_encoder_py(PyObject * m,PyObject * args)304930cef6SMatthias Ringwald static PyObject *setup_encoder_py(PyObject *m, PyObject *args)
314930cef6SMatthias Ringwald {
324930cef6SMatthias Ringwald int dt_us, sr_hz;
334930cef6SMatthias Ringwald
344930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "ii", &dt_us, &sr_hz))
354930cef6SMatthias Ringwald return NULL;
364930cef6SMatthias Ringwald
374930cef6SMatthias Ringwald CTYPES_CHECK("dt_us", LC3_CHECK_DT_US(dt_us));
384930cef6SMatthias Ringwald CTYPES_CHECK("sr_hz", LC3_CHECK_SR_HZ(sr_hz));
394930cef6SMatthias Ringwald
404930cef6SMatthias Ringwald lc3_encoder_t encoder = lc3_setup_encoder(dt_us, sr_hz, 0,
414930cef6SMatthias Ringwald malloc(lc3_encoder_size(dt_us, sr_hz)));
424930cef6SMatthias Ringwald
434930cef6SMatthias Ringwald PyObject *encoder_obj = from_encoder(NULL, encoder);
444930cef6SMatthias Ringwald
454930cef6SMatthias Ringwald free(encoder);
464930cef6SMatthias Ringwald
474930cef6SMatthias Ringwald return Py_BuildValue("N", encoder_obj);
484930cef6SMatthias Ringwald }
494930cef6SMatthias Ringwald
encode_py(PyObject * m,PyObject * args)504930cef6SMatthias Ringwald static PyObject *encode_py(PyObject *m, PyObject *args)
514930cef6SMatthias Ringwald {
524930cef6SMatthias Ringwald PyObject *encoder_obj, *pcm_obj;
534930cef6SMatthias Ringwald int nbytes;
544930cef6SMatthias Ringwald int16_t *pcm;
554930cef6SMatthias Ringwald
564930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "OOi", &encoder_obj, &pcm_obj, &nbytes))
574930cef6SMatthias Ringwald return NULL;
584930cef6SMatthias Ringwald
594930cef6SMatthias Ringwald lc3_encoder_t encoder =
604930cef6SMatthias Ringwald lc3_setup_encoder(10000, 48000, 0, &(lc3_encoder_mem_48k_t){ });
614930cef6SMatthias Ringwald
624930cef6SMatthias Ringwald CTYPES_CHECK(NULL, encoder_obj = to_encoder(encoder_obj, encoder));
634930cef6SMatthias Ringwald
64*6897da5cSDirk Helbig int ns = lc3_ns(encoder->dt, encoder->sr);
654930cef6SMatthias Ringwald
664930cef6SMatthias Ringwald CTYPES_CHECK("x", pcm_obj = to_1d_ptr(pcm_obj, NPY_INT16, ns, &pcm));
674930cef6SMatthias Ringwald CTYPES_CHECK("nbytes", nbytes >= 20 && nbytes <= 400);
684930cef6SMatthias Ringwald
694930cef6SMatthias Ringwald uint8_t out[nbytes];
704930cef6SMatthias Ringwald
714930cef6SMatthias Ringwald lc3_encode(encoder, LC3_PCM_FORMAT_S16, pcm, 1, nbytes, out);
724930cef6SMatthias Ringwald
734930cef6SMatthias Ringwald from_encoder(encoder_obj, encoder);
744930cef6SMatthias Ringwald
754930cef6SMatthias Ringwald return Py_BuildValue("N",
764930cef6SMatthias Ringwald PyBytes_FromStringAndSize((const char *)out, nbytes));
774930cef6SMatthias Ringwald }
784930cef6SMatthias Ringwald
setup_decoder_py(PyObject * m,PyObject * args)794930cef6SMatthias Ringwald static PyObject *setup_decoder_py(PyObject *m, PyObject *args)
804930cef6SMatthias Ringwald {
814930cef6SMatthias Ringwald int dt_us, sr_hz;
824930cef6SMatthias Ringwald
834930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "ii", &dt_us, &sr_hz))
844930cef6SMatthias Ringwald return NULL;
854930cef6SMatthias Ringwald
864930cef6SMatthias Ringwald CTYPES_CHECK("dt_us", LC3_CHECK_DT_US(dt_us));
874930cef6SMatthias Ringwald CTYPES_CHECK("sr_hz", LC3_CHECK_SR_HZ(sr_hz));
884930cef6SMatthias Ringwald
894930cef6SMatthias Ringwald lc3_decoder_t decoder = lc3_setup_decoder(dt_us, sr_hz, 0,
904930cef6SMatthias Ringwald malloc(lc3_decoder_size(dt_us, sr_hz)));
914930cef6SMatthias Ringwald
924930cef6SMatthias Ringwald PyObject *decoder_obj = from_decoder(NULL, decoder);
934930cef6SMatthias Ringwald
944930cef6SMatthias Ringwald free(decoder);
954930cef6SMatthias Ringwald
964930cef6SMatthias Ringwald return Py_BuildValue("N", decoder_obj);
974930cef6SMatthias Ringwald }
984930cef6SMatthias Ringwald
decode_py(PyObject * m,PyObject * args)994930cef6SMatthias Ringwald static PyObject *decode_py(PyObject *m, PyObject *args)
1004930cef6SMatthias Ringwald {
1014930cef6SMatthias Ringwald PyObject *decoder_obj, *pcm_obj, *in_obj;
1024930cef6SMatthias Ringwald int16_t *pcm;
1034930cef6SMatthias Ringwald
1044930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "OO", &decoder_obj, &in_obj))
1054930cef6SMatthias Ringwald return NULL;
1064930cef6SMatthias Ringwald
1074930cef6SMatthias Ringwald CTYPES_CHECK("in", in_obj == Py_None || PyBytes_Check(in_obj));
1084930cef6SMatthias Ringwald
1094930cef6SMatthias Ringwald char *in = in_obj == Py_None ? NULL : PyBytes_AsString(in_obj);
1104930cef6SMatthias Ringwald int nbytes = in_obj == Py_None ? 0 : PyBytes_Size(in_obj);
1114930cef6SMatthias Ringwald
1124930cef6SMatthias Ringwald lc3_decoder_t decoder =
1134930cef6SMatthias Ringwald lc3_setup_decoder(10000, 48000, 0, &(lc3_decoder_mem_48k_t){ });
1144930cef6SMatthias Ringwald
1154930cef6SMatthias Ringwald CTYPES_CHECK(NULL, decoder_obj = to_decoder(decoder_obj, decoder));
1164930cef6SMatthias Ringwald
117*6897da5cSDirk Helbig int ns = lc3_ns(decoder->dt, decoder->sr);
1184930cef6SMatthias Ringwald pcm_obj = new_1d_ptr(NPY_INT16, ns, &pcm);
1194930cef6SMatthias Ringwald
1204930cef6SMatthias Ringwald lc3_decode(decoder, in, nbytes, LC3_PCM_FORMAT_S16, pcm, 1);
1214930cef6SMatthias Ringwald
1224930cef6SMatthias Ringwald from_decoder(decoder_obj, decoder);
1234930cef6SMatthias Ringwald
1244930cef6SMatthias Ringwald return Py_BuildValue("N", pcm_obj);
1254930cef6SMatthias Ringwald }
1264930cef6SMatthias Ringwald
1274930cef6SMatthias Ringwald static PyMethodDef methods[] = {
1284930cef6SMatthias Ringwald { "setup_encoder" , setup_encoder_py , METH_VARARGS },
1294930cef6SMatthias Ringwald { "encode" , encode_py , METH_VARARGS },
1304930cef6SMatthias Ringwald { "setup_decoder" , setup_decoder_py , METH_VARARGS },
1314930cef6SMatthias Ringwald { "decode" , decode_py , METH_VARARGS },
1324930cef6SMatthias Ringwald { NULL },
1334930cef6SMatthias Ringwald };
1344930cef6SMatthias Ringwald
lc3_interface_py_init(PyObject * m)1354930cef6SMatthias Ringwald PyMODINIT_FUNC lc3_interface_py_init(PyObject *m)
1364930cef6SMatthias Ringwald {
1374930cef6SMatthias Ringwald import_array();
1384930cef6SMatthias Ringwald
1394930cef6SMatthias Ringwald PyModule_AddFunctions(m, methods);
1404930cef6SMatthias Ringwald
1414930cef6SMatthias Ringwald return m;
1424930cef6SMatthias Ringwald }
143