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 21 #define PY_SSIZE_T_CLEAN 22 #include <Python.h> 23 #include <numpy/ndarrayobject.h> 24 25 #include <lc3.c> 26 27 #define __CTYPES_LC3_C 28 #include "ctypes.h" 29 30 static PyObject *setup_encoder_py(PyObject *m, PyObject *args) 31 { 32 int dt_us, sr_hz; 33 34 if (!PyArg_ParseTuple(args, "ii", &dt_us, &sr_hz)) 35 return NULL; 36 37 CTYPES_CHECK("dt_us", LC3_CHECK_DT_US(dt_us)); 38 CTYPES_CHECK("sr_hz", LC3_CHECK_SR_HZ(sr_hz)); 39 40 lc3_encoder_t encoder = lc3_setup_encoder(dt_us, sr_hz, 0, 41 malloc(lc3_encoder_size(dt_us, sr_hz))); 42 43 PyObject *encoder_obj = from_encoder(NULL, encoder); 44 45 free(encoder); 46 47 return Py_BuildValue("N", encoder_obj); 48 } 49 50 static PyObject *encode_py(PyObject *m, PyObject *args) 51 { 52 PyObject *encoder_obj, *pcm_obj; 53 int nbytes; 54 int16_t *pcm; 55 56 if (!PyArg_ParseTuple(args, "OOi", &encoder_obj, &pcm_obj, &nbytes)) 57 return NULL; 58 59 lc3_encoder_t encoder = 60 lc3_setup_encoder(10000, 48000, 0, &(lc3_encoder_mem_48k_t){ }); 61 62 CTYPES_CHECK(NULL, encoder_obj = to_encoder(encoder_obj, encoder)); 63 64 int ns = lc3_ns(encoder->dt, encoder->sr); 65 66 CTYPES_CHECK("x", pcm_obj = to_1d_ptr(pcm_obj, NPY_INT16, ns, &pcm)); 67 CTYPES_CHECK("nbytes", nbytes >= 20 && nbytes <= 400); 68 69 uint8_t out[nbytes]; 70 71 lc3_encode(encoder, LC3_PCM_FORMAT_S16, pcm, 1, nbytes, out); 72 73 from_encoder(encoder_obj, encoder); 74 75 return Py_BuildValue("N", 76 PyBytes_FromStringAndSize((const char *)out, nbytes)); 77 } 78 79 static PyObject *setup_decoder_py(PyObject *m, PyObject *args) 80 { 81 int dt_us, sr_hz; 82 83 if (!PyArg_ParseTuple(args, "ii", &dt_us, &sr_hz)) 84 return NULL; 85 86 CTYPES_CHECK("dt_us", LC3_CHECK_DT_US(dt_us)); 87 CTYPES_CHECK("sr_hz", LC3_CHECK_SR_HZ(sr_hz)); 88 89 lc3_decoder_t decoder = lc3_setup_decoder(dt_us, sr_hz, 0, 90 malloc(lc3_decoder_size(dt_us, sr_hz))); 91 92 PyObject *decoder_obj = from_decoder(NULL, decoder); 93 94 free(decoder); 95 96 return Py_BuildValue("N", decoder_obj); 97 } 98 99 static PyObject *decode_py(PyObject *m, PyObject *args) 100 { 101 PyObject *decoder_obj, *pcm_obj, *in_obj; 102 int16_t *pcm; 103 104 if (!PyArg_ParseTuple(args, "OO", &decoder_obj, &in_obj)) 105 return NULL; 106 107 CTYPES_CHECK("in", in_obj == Py_None || PyBytes_Check(in_obj)); 108 109 char *in = in_obj == Py_None ? NULL : PyBytes_AsString(in_obj); 110 int nbytes = in_obj == Py_None ? 0 : PyBytes_Size(in_obj); 111 112 lc3_decoder_t decoder = 113 lc3_setup_decoder(10000, 48000, 0, &(lc3_decoder_mem_48k_t){ }); 114 115 CTYPES_CHECK(NULL, decoder_obj = to_decoder(decoder_obj, decoder)); 116 117 int ns = lc3_ns(decoder->dt, decoder->sr); 118 pcm_obj = new_1d_ptr(NPY_INT16, ns, &pcm); 119 120 lc3_decode(decoder, in, nbytes, LC3_PCM_FORMAT_S16, pcm, 1); 121 122 from_decoder(decoder_obj, decoder); 123 124 return Py_BuildValue("N", pcm_obj); 125 } 126 127 static PyMethodDef methods[] = { 128 { "setup_encoder" , setup_encoder_py , METH_VARARGS }, 129 { "encode" , encode_py , METH_VARARGS }, 130 { "setup_decoder" , setup_decoder_py , METH_VARARGS }, 131 { "decode" , decode_py , METH_VARARGS }, 132 { NULL }, 133 }; 134 135 PyMODINIT_FUNC lc3_interface_py_init(PyObject *m) 136 { 137 import_array(); 138 139 PyModule_AddFunctions(m, methods); 140 141 return m; 142 } 143