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 <Python.h>
20 #include <numpy/ndarrayobject.h>
21
22 #include <ltpf.c>
23 #include "ctypes.h"
24
resample_py(PyObject * m,PyObject * args)25 static PyObject *resample_py(PyObject *m, PyObject *args)
26 {
27 unsigned dt, sr;
28 PyObject *hp50_obj, *x_obj, *y_obj;
29 struct lc3_ltpf_hp50_state hp50;
30 int16_t *x, *y;
31
32 if (!PyArg_ParseTuple(args, "IIOOO", &dt, &sr, &hp50_obj, &x_obj, &y_obj))
33 return NULL;
34
35 CTYPES_CHECK("dt", (unsigned)dt < LC3_NUM_DT);
36 CTYPES_CHECK("sr", (unsigned)sr < LC3_NUM_SRATE);
37 CTYPES_CHECK(NULL, hp50_obj = to_ltpf_hp50_state(hp50_obj, &hp50));
38
39 int ns = LC3_NS(dt, sr), nt = LC3_NT(dt);
40 int ny = sizeof((struct lc3_ltpf_analysis){ }.x_12k8) / sizeof(int16_t);
41 int n = dt == LC3_DT_7M5 ? 96 : 128;
42
43 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_INT16, ns+nt, &x));
44 CTYPES_CHECK("y", y_obj = to_1d_ptr(y_obj, NPY_INT16, ny, &y));
45
46 resample_12k8[sr](&hp50, x + nt, y + (ny - n), n);
47
48 from_ltpf_hp50_state(hp50_obj, &hp50);
49 return Py_BuildValue("O", y_obj);
50 }
51
analyse_py(PyObject * m,PyObject * args)52 static PyObject *analyse_py(PyObject *m, PyObject *args)
53 {
54 PyObject *ltpf_obj, *x_obj;
55 unsigned dt, sr;
56 struct lc3_ltpf_analysis ltpf;
57 struct lc3_ltpf_data data = { 0 };
58 int16_t *x;
59
60 if (!PyArg_ParseTuple(args, "IIOO", &dt, &sr, <pf_obj, &x_obj))
61 return NULL;
62
63 CTYPES_CHECK("dt", dt < LC3_NUM_DT);
64 CTYPES_CHECK("sr", sr < LC3_NUM_SRATE);
65 CTYPES_CHECK(NULL, ltpf_obj = to_ltpf_analysis(ltpf_obj, <pf));
66
67 int ns = LC3_NS(dt, sr), nt = LC3_NT(sr);
68
69 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_INT16, ns+nt, &x));
70
71 int pitch_present =
72 lc3_ltpf_analyse(dt, sr, <pf, x + nt, &data);
73
74 from_ltpf_analysis(ltpf_obj, <pf);
75 return Py_BuildValue("iN", pitch_present, new_ltpf_data(&data));
76 }
77
synthesize_py(PyObject * m,PyObject * args)78 static PyObject *synthesize_py(PyObject *m, PyObject *args)
79 {
80 PyObject *ltpf_obj, *data_obj, *x_obj;
81 struct lc3_ltpf_synthesis ltpf;
82 struct lc3_ltpf_data data;
83 bool pitch_present;
84 unsigned dt, sr;
85 int nbytes;
86 float *x;
87
88 if (!PyArg_ParseTuple(args, "IIiOOO",
89 &dt, &sr, &nbytes, <pf_obj, &data_obj, &x_obj))
90 return NULL;
91
92 CTYPES_CHECK("dt", dt < LC3_NUM_DT);
93 CTYPES_CHECK("sr", sr < LC3_NUM_SRATE);
94 CTYPES_CHECK("nbytes", nbytes >= 20 && nbytes <= 400);
95 CTYPES_CHECK(NULL, ltpf_obj = to_ltpf_synthesis(ltpf_obj, <pf));
96
97 if ((pitch_present = (data_obj != Py_None)))
98 CTYPES_CHECK(NULL, data_obj = to_ltpf_data(data_obj, &data));
99
100 int ns = LC3_NS(dt,sr), nd = 18 * LC3_SRATE_KHZ(sr);
101
102 CTYPES_CHECK("x", x_obj = to_1d_ptr(x_obj, NPY_FLOAT, nd+ns, &x));
103
104 lc3_ltpf_synthesize(dt, sr, nbytes,
105 <pf, pitch_present ? &data : NULL, x, x + nd);
106
107 from_ltpf_synthesis(ltpf_obj, <pf);
108 return Py_BuildValue("O", x_obj);
109 }
110
get_nbits_py(PyObject * m,PyObject * args)111 static PyObject *get_nbits_py(PyObject *m, PyObject *args)
112 {
113 int pitch_present;
114
115 if (!PyArg_ParseTuple(args, "i", &pitch_present))
116 return NULL;
117
118 int nbits = lc3_ltpf_get_nbits(pitch_present);
119
120 return Py_BuildValue("i", nbits);
121 }
122
123 static PyMethodDef methods[] = {
124 { "ltpf_resample" , resample_py , METH_VARARGS },
125 { "ltpf_analyse" , analyse_py , METH_VARARGS },
126 { "ltpf_synthesize", synthesize_py, METH_VARARGS },
127 { "ltpf_get_nbits" , get_nbits_py , METH_VARARGS },
128 { NULL },
129 };
130
lc3_ltpf_py_init(PyObject * m)131 PyMODINIT_FUNC lc3_ltpf_py_init(PyObject *m)
132 {
133 import_array();
134
135 PyModule_AddFunctions(m, methods);
136
137 return m;
138 }
139