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