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
setup_encoder_py(PyObject * m,PyObject * args)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
encode_py(PyObject * m,PyObject * args)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
setup_decoder_py(PyObject * m,PyObject * args)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
decode_py(PyObject * m,PyObject * args)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
lc3_interface_py_init(PyObject * m)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