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