1*4930cef6SMatthias Ringwald /****************************************************************************** 2*4930cef6SMatthias Ringwald * 3*4930cef6SMatthias Ringwald * Copyright 2022 Google LLC 4*4930cef6SMatthias Ringwald * 5*4930cef6SMatthias Ringwald * Licensed under the Apache License, Version 2.0 (the "License"); 6*4930cef6SMatthias Ringwald * you may not use this file except in compliance with the License. 7*4930cef6SMatthias Ringwald * You may obtain a copy of the License at: 8*4930cef6SMatthias Ringwald * 9*4930cef6SMatthias Ringwald * http://www.apache.org/licenses/LICENSE-2.0 10*4930cef6SMatthias Ringwald * 11*4930cef6SMatthias Ringwald * Unless required by applicable law or agreed to in writing, software 12*4930cef6SMatthias Ringwald * distributed under the License is distributed on an "AS IS" BASIS, 13*4930cef6SMatthias Ringwald * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*4930cef6SMatthias Ringwald * See the License for the specific language governing permissions and 15*4930cef6SMatthias Ringwald * limitations under the License. 16*4930cef6SMatthias Ringwald * 17*4930cef6SMatthias Ringwald ******************************************************************************/ 18*4930cef6SMatthias Ringwald 19*4930cef6SMatthias Ringwald #include "lc3.h" 20*4930cef6SMatthias Ringwald 21*4930cef6SMatthias Ringwald #define PY_SSIZE_T_CLEAN 22*4930cef6SMatthias Ringwald #include <Python.h> 23*4930cef6SMatthias Ringwald #include <numpy/ndarrayobject.h> 24*4930cef6SMatthias Ringwald 25*4930cef6SMatthias Ringwald #include <lc3.c> 26*4930cef6SMatthias Ringwald 27*4930cef6SMatthias Ringwald #define __CTYPES_LC3_C 28*4930cef6SMatthias Ringwald #include "ctypes.h" 29*4930cef6SMatthias Ringwald 30*4930cef6SMatthias Ringwald static PyObject *setup_encoder_py(PyObject *m, PyObject *args) 31*4930cef6SMatthias Ringwald { 32*4930cef6SMatthias Ringwald int dt_us, sr_hz; 33*4930cef6SMatthias Ringwald 34*4930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "ii", &dt_us, &sr_hz)) 35*4930cef6SMatthias Ringwald return NULL; 36*4930cef6SMatthias Ringwald 37*4930cef6SMatthias Ringwald CTYPES_CHECK("dt_us", LC3_CHECK_DT_US(dt_us)); 38*4930cef6SMatthias Ringwald CTYPES_CHECK("sr_hz", LC3_CHECK_SR_HZ(sr_hz)); 39*4930cef6SMatthias Ringwald 40*4930cef6SMatthias Ringwald lc3_encoder_t encoder = lc3_setup_encoder(dt_us, sr_hz, 0, 41*4930cef6SMatthias Ringwald malloc(lc3_encoder_size(dt_us, sr_hz))); 42*4930cef6SMatthias Ringwald 43*4930cef6SMatthias Ringwald PyObject *encoder_obj = from_encoder(NULL, encoder); 44*4930cef6SMatthias Ringwald 45*4930cef6SMatthias Ringwald free(encoder); 46*4930cef6SMatthias Ringwald 47*4930cef6SMatthias Ringwald return Py_BuildValue("N", encoder_obj); 48*4930cef6SMatthias Ringwald } 49*4930cef6SMatthias Ringwald 50*4930cef6SMatthias Ringwald static PyObject *encode_py(PyObject *m, PyObject *args) 51*4930cef6SMatthias Ringwald { 52*4930cef6SMatthias Ringwald PyObject *encoder_obj, *pcm_obj; 53*4930cef6SMatthias Ringwald int nbytes; 54*4930cef6SMatthias Ringwald int16_t *pcm; 55*4930cef6SMatthias Ringwald 56*4930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "OOi", &encoder_obj, &pcm_obj, &nbytes)) 57*4930cef6SMatthias Ringwald return NULL; 58*4930cef6SMatthias Ringwald 59*4930cef6SMatthias Ringwald lc3_encoder_t encoder = 60*4930cef6SMatthias Ringwald lc3_setup_encoder(10000, 48000, 0, &(lc3_encoder_mem_48k_t){ }); 61*4930cef6SMatthias Ringwald 62*4930cef6SMatthias Ringwald CTYPES_CHECK(NULL, encoder_obj = to_encoder(encoder_obj, encoder)); 63*4930cef6SMatthias Ringwald 64*4930cef6SMatthias Ringwald int ns = LC3_NS(encoder->dt, encoder->sr); 65*4930cef6SMatthias Ringwald 66*4930cef6SMatthias Ringwald CTYPES_CHECK("x", pcm_obj = to_1d_ptr(pcm_obj, NPY_INT16, ns, &pcm)); 67*4930cef6SMatthias Ringwald CTYPES_CHECK("nbytes", nbytes >= 20 && nbytes <= 400); 68*4930cef6SMatthias Ringwald 69*4930cef6SMatthias Ringwald uint8_t out[nbytes]; 70*4930cef6SMatthias Ringwald 71*4930cef6SMatthias Ringwald lc3_encode(encoder, LC3_PCM_FORMAT_S16, pcm, 1, nbytes, out); 72*4930cef6SMatthias Ringwald 73*4930cef6SMatthias Ringwald from_encoder(encoder_obj, encoder); 74*4930cef6SMatthias Ringwald 75*4930cef6SMatthias Ringwald return Py_BuildValue("N", 76*4930cef6SMatthias Ringwald PyBytes_FromStringAndSize((const char *)out, nbytes)); 77*4930cef6SMatthias Ringwald } 78*4930cef6SMatthias Ringwald 79*4930cef6SMatthias Ringwald static PyObject *setup_decoder_py(PyObject *m, PyObject *args) 80*4930cef6SMatthias Ringwald { 81*4930cef6SMatthias Ringwald int dt_us, sr_hz; 82*4930cef6SMatthias Ringwald 83*4930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "ii", &dt_us, &sr_hz)) 84*4930cef6SMatthias Ringwald return NULL; 85*4930cef6SMatthias Ringwald 86*4930cef6SMatthias Ringwald CTYPES_CHECK("dt_us", LC3_CHECK_DT_US(dt_us)); 87*4930cef6SMatthias Ringwald CTYPES_CHECK("sr_hz", LC3_CHECK_SR_HZ(sr_hz)); 88*4930cef6SMatthias Ringwald 89*4930cef6SMatthias Ringwald lc3_decoder_t decoder = lc3_setup_decoder(dt_us, sr_hz, 0, 90*4930cef6SMatthias Ringwald malloc(lc3_decoder_size(dt_us, sr_hz))); 91*4930cef6SMatthias Ringwald 92*4930cef6SMatthias Ringwald PyObject *decoder_obj = from_decoder(NULL, decoder); 93*4930cef6SMatthias Ringwald 94*4930cef6SMatthias Ringwald free(decoder); 95*4930cef6SMatthias Ringwald 96*4930cef6SMatthias Ringwald return Py_BuildValue("N", decoder_obj); 97*4930cef6SMatthias Ringwald } 98*4930cef6SMatthias Ringwald 99*4930cef6SMatthias Ringwald static PyObject *decode_py(PyObject *m, PyObject *args) 100*4930cef6SMatthias Ringwald { 101*4930cef6SMatthias Ringwald PyObject *decoder_obj, *pcm_obj, *in_obj; 102*4930cef6SMatthias Ringwald int16_t *pcm; 103*4930cef6SMatthias Ringwald 104*4930cef6SMatthias Ringwald if (!PyArg_ParseTuple(args, "OO", &decoder_obj, &in_obj)) 105*4930cef6SMatthias Ringwald return NULL; 106*4930cef6SMatthias Ringwald 107*4930cef6SMatthias Ringwald CTYPES_CHECK("in", in_obj == Py_None || PyBytes_Check(in_obj)); 108*4930cef6SMatthias Ringwald 109*4930cef6SMatthias Ringwald char *in = in_obj == Py_None ? NULL : PyBytes_AsString(in_obj); 110*4930cef6SMatthias Ringwald int nbytes = in_obj == Py_None ? 0 : PyBytes_Size(in_obj); 111*4930cef6SMatthias Ringwald 112*4930cef6SMatthias Ringwald lc3_decoder_t decoder = 113*4930cef6SMatthias Ringwald lc3_setup_decoder(10000, 48000, 0, &(lc3_decoder_mem_48k_t){ }); 114*4930cef6SMatthias Ringwald 115*4930cef6SMatthias Ringwald CTYPES_CHECK(NULL, decoder_obj = to_decoder(decoder_obj, decoder)); 116*4930cef6SMatthias Ringwald 117*4930cef6SMatthias Ringwald int ns = LC3_NS(decoder->dt, decoder->sr); 118*4930cef6SMatthias Ringwald pcm_obj = new_1d_ptr(NPY_INT16, ns, &pcm); 119*4930cef6SMatthias Ringwald 120*4930cef6SMatthias Ringwald lc3_decode(decoder, in, nbytes, LC3_PCM_FORMAT_S16, pcm, 1); 121*4930cef6SMatthias Ringwald 122*4930cef6SMatthias Ringwald from_decoder(decoder_obj, decoder); 123*4930cef6SMatthias Ringwald 124*4930cef6SMatthias Ringwald return Py_BuildValue("N", pcm_obj); 125*4930cef6SMatthias Ringwald } 126*4930cef6SMatthias Ringwald 127*4930cef6SMatthias Ringwald static PyMethodDef methods[] = { 128*4930cef6SMatthias Ringwald { "setup_encoder" , setup_encoder_py , METH_VARARGS }, 129*4930cef6SMatthias Ringwald { "encode" , encode_py , METH_VARARGS }, 130*4930cef6SMatthias Ringwald { "setup_decoder" , setup_decoder_py , METH_VARARGS }, 131*4930cef6SMatthias Ringwald { "decode" , decode_py , METH_VARARGS }, 132*4930cef6SMatthias Ringwald { NULL }, 133*4930cef6SMatthias Ringwald }; 134*4930cef6SMatthias Ringwald 135*4930cef6SMatthias Ringwald PyMODINIT_FUNC lc3_interface_py_init(PyObject *m) 136*4930cef6SMatthias Ringwald { 137*4930cef6SMatthias Ringwald import_array(); 138*4930cef6SMatthias Ringwald 139*4930cef6SMatthias Ringwald PyModule_AddFunctions(m, methods); 140*4930cef6SMatthias Ringwald 141*4930cef6SMatthias Ringwald return m; 142*4930cef6SMatthias Ringwald } 143