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 #ifndef __CTYPES_H
20 #define __CTYPES_H
21 
22 #include <Python.h>
23 #include <numpy/ndarrayobject.h>
24 
25 #include <stdbool.h>
26 
27 
28 #define CTYPES_CHECK(exc, t) \
29     do { \
30         if (!(t)) return (exc) ? PyErr_Format(PyExc_TypeError, exc) : NULL; \
31     } while(0)
32 
33 
34 /**
35  * From C types to Numpy Array types
36  */
37 
38 #define to_scalar(obj, t, ptr) \
39     __to_scalar(obj, t, (void *)(ptr))
40 
41 #define to_1d_ptr(obj, t, n, ptr) \
42     __to_1d_ptr(obj, t, n, (void **)(ptr))
43 
44 #define to_2d_ptr(obj, t, n1, n2, ptr) \
45     __to_2d_ptr(obj, t, n1, n2, (void **)(ptr))
46 
47 #define to_1d_copy(obj, t, ptr, n) \
48     __to_1d_copy(obj, t, ptr, n)
49 
50 #define to_2d_copy(obj, t, ptr, n1, n2) \
51     __to_2d_copy(obj, t, ptr, n1, n2)
52 
53 
54 /**
55  * From Numpy Array types to C types
56  */
57 
58 #define new_scalar(obj, ptr) \
59     __new_scalar(obj, ptr)
60 
61 #define new_1d_ptr(t, n, ptr) \
62     __new_1d_ptr(t, n, (void **)(ptr))
63 
64 #define new_2d_ptr(t, n1, n2, ptr) \
65     __new_2d_ptr(t, n1, n2, (void **)(ptr))
66 
67 #define new_1d_copy(t, n, src) \
68     __new_1d_copy(t, n, src)
69 
70 #define new_2d_copy(t, n1, n2, src) \
71     __new_2d_copy(t, n1, n2, src)
72 
73 
74 /* -------------------------------------------------------------------------- */
75 
76 __attribute__((unused))
__to_scalar(PyObject * obj,int t,void * ptr)77 static PyObject *__to_scalar(PyObject *obj, int t, void *ptr)
78 {
79     obj = obj ? PyArray_FROMANY(obj, t, 0, 0, NPY_ARRAY_FORCECAST) : obj;
80     if (!obj)
81         return NULL;
82 
83     memcpy(ptr, PyArray_DATA((PyArrayObject *)obj),
84         PyArray_NBYTES((PyArrayObject *)obj));
85 
86     return obj;
87 }
88 
89 __attribute__((unused))
__to_1d_ptr(PyObject * obj,int t,int n,void ** ptr)90 static PyObject *__to_1d_ptr(PyObject *obj, int t, int n, void **ptr)
91 {
92     obj = obj ? PyArray_FROMANY(obj,
93         t, 1, 1, NPY_ARRAY_FORCECAST|NPY_ARRAY_CARRAY) : obj;
94     if (!obj || (n && PyArray_SIZE((PyArrayObject *)obj) != n))
95         return NULL;
96 
97     *ptr = PyArray_DATA((PyArrayObject *)obj);
98     return obj;
99 }
100 
101 __attribute__((unused))
__to_2d_ptr(PyObject * obj,int t,int n1,int n2,void ** ptr)102 static PyObject *__to_2d_ptr(PyObject *obj, int t, int n1, int n2, void **ptr)
103 {
104     obj = obj ? PyArray_FROMANY(obj,
105         t, 2, 2, NPY_ARRAY_FORCECAST|NPY_ARRAY_CARRAY) : obj;
106     if (!obj || (n1 && PyArray_DIMS((PyArrayObject *)obj)[0] != n1)
107              || (n2 && PyArray_DIMS((PyArrayObject *)obj)[1] != n2))
108         return NULL;
109 
110     *ptr = PyArray_DATA((PyArrayObject *)obj);
111     return obj;
112 }
113 
114 __attribute__((unused))
__to_1d_copy(PyObject * obj,int t,void * v,int n)115 static PyObject *__to_1d_copy(PyObject *obj, int t, void *v, int n)
116 {
117     void *src;
118 
119     if ((obj = to_1d_ptr(obj, t, n, &src)))
120         memcpy(v, src, PyArray_NBYTES((PyArrayObject *)obj));
121 
122     return obj;
123 }
124 
125 __attribute__((unused))
__to_2d_copy(PyObject * obj,int t,void * v,int n1,int n2)126 static PyObject *__to_2d_copy(PyObject *obj, int t, void *v, int n1, int n2)
127 {
128     void *src;
129 
130     if ((obj = to_2d_ptr(obj, t, n1, n2, &src)))
131         memcpy(v, src, PyArray_NBYTES((PyArrayObject *)obj));
132 
133     return obj;
134 }
135 
136 /* -------------------------------------------------------------------------- */
137 
138 __attribute__((unused))
__new_scalar(int t,const void * ptr)139 static PyObject *__new_scalar(int t, const void *ptr)
140 {
141     PyObject *obj = PyArray_SimpleNew(0, NULL, t);
142 
143     memcpy(PyArray_DATA((PyArrayObject *)obj), ptr,
144         PyArray_NBYTES((PyArrayObject *)obj));
145 
146     return obj;
147 }
148 
149 __attribute__((unused))
__new_1d_ptr(int t,int n,void ** ptr)150 static PyObject *__new_1d_ptr(int t, int n, void **ptr)
151 {
152     PyObject *obj = PyArray_SimpleNew(1, (const npy_intp []){ n }, t);
153 
154     *ptr = PyArray_DATA((PyArrayObject *)obj);
155     return obj;
156 }
157 
158 __attribute__((unused))
__new_2d_ptr(int t,int n1,int n2,void ** ptr)159 static PyObject *__new_2d_ptr(int t, int n1, int n2, void **ptr)
160 {
161     PyObject *obj;
162 
163     obj = PyArray_SimpleNew(2, ((const npy_intp []){ n1, n2 }), t);
164 
165     *ptr = PyArray_DATA((PyArrayObject *)obj);
166     return obj;
167 }
168 
169 __attribute__((unused))
__new_1d_copy(int t,int n,const void * src)170 static PyObject *__new_1d_copy(int t, int n, const void *src)
171 {
172     PyObject *obj;
173     void *dst;
174 
175     if ((obj = new_1d_ptr(t, n, &dst)))
176         memcpy(dst, src, PyArray_NBYTES((PyArrayObject *)obj));
177 
178     return obj;
179 }
180 
181 __attribute__((unused))
__new_2d_copy(int t,int n1,int n2,const void * src)182 static PyObject *__new_2d_copy(int t, int n1, int n2, const void *src)
183 {
184     PyObject *obj;
185     void *dst;
186 
187     if ((obj = new_2d_ptr(t, n1, n2, &dst)))
188         memcpy(dst, src, PyArray_NBYTES((PyArrayObject *)obj));
189 
190     return obj;
191 }
192 
193 /* -------------------------------------------------------------------------- */
194 
195 #include <lc3.h>
196 
197 __attribute__((unused))
to_attdet_analysis(PyObject * obj,struct lc3_attdet_analysis * attdet)198 static PyObject *to_attdet_analysis(
199     PyObject *obj, struct lc3_attdet_analysis *attdet)
200 {
201     CTYPES_CHECK("attdet", obj && PyDict_Check(obj));
202 
203     CTYPES_CHECK("attdet.en1", to_scalar(
204         PyDict_GetItemString(obj, "en1"), NPY_INT32, &attdet->en1));
205 
206     CTYPES_CHECK("attdet.an1", to_scalar(
207         PyDict_GetItemString(obj, "an1"), NPY_INT32, &attdet->an1));
208 
209     CTYPES_CHECK("attdet.p_att", to_scalar(
210         PyDict_GetItemString(obj, "p_att"), NPY_INT, &attdet->p_att));
211 
212     return obj;
213 }
214 
215 __attribute__((unused))
from_attdet_analysis(PyObject * obj,const struct lc3_attdet_analysis * attdet)216 static PyObject *from_attdet_analysis(
217     PyObject *obj, const struct lc3_attdet_analysis *attdet)
218 {
219     if (!obj) obj = PyDict_New();
220 
221     PyDict_SetItemString(obj, "en1",
222         new_scalar(NPY_INT32, &attdet->en1));
223 
224     PyDict_SetItemString(obj, "an1",
225         new_scalar(NPY_INT32, &attdet->an1));
226 
227     PyDict_SetItemString(obj, "p_att",
228         new_scalar(NPY_INT, &attdet->p_att));
229 
230     return obj;
231 }
232 
233 /* -------------------------------------------------------------------------- */
234 
235 #include <ltpf.h>
236 
237 __attribute__((unused))
to_ltpf_hp50_state(PyObject * obj,struct lc3_ltpf_hp50_state * hp50)238 static PyObject *to_ltpf_hp50_state(
239     PyObject *obj, struct lc3_ltpf_hp50_state *hp50)
240 {
241     CTYPES_CHECK("hp50", obj && PyDict_Check(obj));
242 
243     CTYPES_CHECK("hp50.s1", to_scalar(
244         PyDict_GetItemString(obj, "s1"), NPY_INT64, &hp50->s1));
245 
246     CTYPES_CHECK("hp50.s2", to_scalar(
247         PyDict_GetItemString(obj, "s2"), NPY_INT64, &hp50->s2));
248 
249     return obj;
250 }
251 
252 __attribute__((unused))
from_ltpf_hp50_state(PyObject * obj,const struct lc3_ltpf_hp50_state * hp50)253 static PyObject *from_ltpf_hp50_state(
254     PyObject *obj, const struct lc3_ltpf_hp50_state *hp50)
255 {
256     PyDict_SetItemString(obj, "s1",
257         new_scalar(NPY_INT64, &hp50->s1));
258 
259     PyDict_SetItemString(obj, "s2",
260         new_scalar(NPY_INT64, &hp50->s2));
261 
262     return obj;
263 }
264 
265 __attribute__((unused))
to_ltpf_analysis(PyObject * obj,struct lc3_ltpf_analysis * ltpf)266 static PyObject *to_ltpf_analysis(
267     PyObject *obj, struct lc3_ltpf_analysis *ltpf)
268 {
269     PyObject *nc_obj, *x_12k8_obj, *x_6k4_obj;
270     const int n_12k8 = sizeof(ltpf->x_12k8) / sizeof(*ltpf->x_12k8);
271     const int n_6k4 = sizeof(ltpf->x_6k4) / sizeof(*ltpf->x_6k4);
272 
273     CTYPES_CHECK("ltpf", obj && PyDict_Check(obj));
274 
275     CTYPES_CHECK("ltpf.active", to_scalar(
276         PyDict_GetItemString(obj, "active"), NPY_BOOL, &ltpf->active));
277 
278     CTYPES_CHECK("ltpf.pitch", to_scalar(
279         PyDict_GetItemString(obj, "pitch"), NPY_INT, &ltpf->pitch));
280 
281     CTYPES_CHECK("ltpf.nc", nc_obj = to_1d_copy(
282         PyDict_GetItemString(obj, "nc"), NPY_FLOAT, ltpf->nc, 2));
283     PyDict_SetItemString(obj, "nc", nc_obj);
284 
285     CTYPES_CHECK(NULL, to_ltpf_hp50_state(
286         PyDict_GetItemString(obj, "hp50"), &ltpf->hp50));
287 
288     CTYPES_CHECK("ltpf.x_12k8", x_12k8_obj = to_1d_copy(
289         PyDict_GetItemString(obj, "x_12k8"), NPY_INT16, ltpf->x_12k8, n_12k8));
290     PyDict_SetItemString(obj, "x_12k8", x_12k8_obj);
291 
292     CTYPES_CHECK("ltpf.x_6k4", x_6k4_obj = to_1d_copy(
293         PyDict_GetItemString(obj, "x_6k4"), NPY_INT16, ltpf->x_6k4, n_6k4));
294     PyDict_SetItemString(obj, "x_6k4", x_6k4_obj);
295 
296     CTYPES_CHECK("ltpf.tc", to_scalar(
297         PyDict_GetItemString(obj, "tc"), NPY_INT, &ltpf->tc));
298 
299     return obj;
300 }
301 
302 __attribute__((unused))
from_ltpf_analysis(PyObject * obj,const struct lc3_ltpf_analysis * ltpf)303 static PyObject *from_ltpf_analysis(
304     PyObject *obj, const struct lc3_ltpf_analysis *ltpf)
305 {
306     const int n_12k8 = sizeof(ltpf->x_12k8) / sizeof(*ltpf->x_12k8);
307     const int n_6k4 = sizeof(ltpf->x_6k4) / sizeof(*ltpf->x_6k4);
308 
309     if (!obj) obj = PyDict_New();
310 
311     PyDict_SetItemString(obj, "active",
312         new_scalar(NPY_BOOL, &ltpf->active));
313 
314     PyDict_SetItemString(obj, "pitch",
315         new_scalar(NPY_INT, &ltpf->pitch));
316 
317     PyDict_SetItemString(obj, "nc",
318         new_1d_copy(NPY_FLOAT, 2, &ltpf->nc));
319 
320     PyDict_SetItemString(obj, "hp50",
321         from_ltpf_hp50_state(PyDict_New(), &ltpf->hp50));
322 
323     PyDict_SetItemString(obj, "x_12k8",
324         new_1d_copy(NPY_INT16, n_12k8, &ltpf->x_12k8));
325 
326     PyDict_SetItemString(obj, "x_6k4",
327         new_1d_copy(NPY_INT16, n_6k4, &ltpf->x_6k4));
328 
329     PyDict_SetItemString(obj, "tc",
330         new_scalar(NPY_INT, &ltpf->tc));
331 
332     return obj;
333 }
334 
335 __attribute__((unused))
to_ltpf_synthesis(PyObject * obj,struct lc3_ltpf_synthesis * ltpf)336 static PyObject *to_ltpf_synthesis(
337     PyObject *obj, struct lc3_ltpf_synthesis *ltpf)
338 {
339     PyObject *c_obj, *x_obj;
340 
341     CTYPES_CHECK("ltpf", obj && PyDict_Check(obj));
342 
343     CTYPES_CHECK("ltpf.active", to_scalar(
344         PyDict_GetItemString(obj, "active"), NPY_BOOL, &ltpf->active));
345 
346     CTYPES_CHECK("ltpf.pitch", to_scalar(
347         PyDict_GetItemString(obj, "pitch"), NPY_INT, &ltpf->pitch));
348 
349     CTYPES_CHECK("ltpf.c", c_obj = to_1d_copy(
350         PyDict_GetItemString(obj, "c"), NPY_FLOAT, ltpf->c, 2*12));
351     PyDict_SetItemString(obj, "c", c_obj);
352 
353     CTYPES_CHECK("ltpf.x", x_obj = to_1d_copy(
354         PyDict_GetItemString(obj, "x"), NPY_FLOAT, ltpf->x, 12));
355     PyDict_SetItemString(obj, "x", x_obj);
356 
357     return obj;
358 }
359 
360 __attribute__((unused))
from_ltpf_synthesis(PyObject * obj,const struct lc3_ltpf_synthesis * ltpf)361 static PyObject *from_ltpf_synthesis(
362     PyObject *obj, const struct lc3_ltpf_synthesis *ltpf)
363 {
364     if (!obj) obj = PyDict_New();
365 
366     PyDict_SetItemString(obj, "active",
367         new_scalar(NPY_BOOL, &ltpf->active));
368 
369     PyDict_SetItemString(obj, "pitch",
370         new_scalar(NPY_INT, &ltpf->pitch));
371 
372     PyDict_SetItemString(obj, "c",
373         new_1d_copy(NPY_FLOAT, 2*12, &ltpf->c));
374 
375     PyDict_SetItemString(obj, "x",
376         new_1d_copy(NPY_FLOAT, 12, &ltpf->x));
377 
378     return obj;
379 }
380 
381 __attribute__((unused))
new_ltpf_data(const struct lc3_ltpf_data * data)382 static PyObject *new_ltpf_data(const struct lc3_ltpf_data *data)
383 {
384     PyObject *obj = PyDict_New();
385 
386     PyDict_SetItemString(obj, "active",
387         new_scalar(NPY_BOOL, &data->active));
388 
389     PyDict_SetItemString(obj, "pitch_index",
390         new_scalar(NPY_INT, &data->pitch_index));
391 
392     return obj;
393 }
394 
395 __attribute__((unused))
to_ltpf_data(PyObject * obj,const struct lc3_ltpf_data * data)396 static PyObject *to_ltpf_data(
397      PyObject *obj, const struct lc3_ltpf_data *data)
398 {
399     PyObject *item;
400 
401     CTYPES_CHECK("ltpf", obj && PyDict_Check(obj));
402 
403     if ((item = PyDict_GetItemString(obj, "active")))
404         CTYPES_CHECK("ltpf.active",
405             to_scalar(item, NPY_BOOL, &data->active));
406 
407     if ((item = PyDict_GetItemString(obj, "pitch_index")))
408         CTYPES_CHECK("ltpf.pitch_index",
409             to_scalar(item, NPY_INT, &data->pitch_index));
410 
411     return obj;
412 }
413 
414 /* -------------------------------------------------------------------------- */
415 
416 #include <sns.h>
417 
418 __attribute__((unused))
new_sns_data(const struct lc3_sns_data * data)419 static PyObject *new_sns_data(const struct lc3_sns_data *data)
420 {
421     PyObject *obj = PyDict_New();
422 
423     PyDict_SetItemString(obj, "lfcb",
424         new_scalar(NPY_INT, &data->lfcb));
425 
426     PyDict_SetItemString(obj, "hfcb",
427         new_scalar(NPY_INT, &data->hfcb));
428 
429     PyDict_SetItemString(obj, "shape",
430         new_scalar(NPY_INT, &data->shape));
431 
432     PyDict_SetItemString(obj, "gain",
433         new_scalar(NPY_INT, &data->gain));
434 
435     PyDict_SetItemString(obj, "idx_a",
436         new_scalar(NPY_INT, &data->idx_a));
437 
438     PyDict_SetItemString(obj, "ls_a",
439         new_scalar(NPY_BOOL, &data->ls_a));
440 
441     PyDict_SetItemString(obj, "idx_b",
442         new_scalar(NPY_INT, &data->idx_b));
443 
444     PyDict_SetItemString(obj, "ls_b",
445         new_scalar(NPY_BOOL, &data->ls_b));
446 
447     return obj;
448 }
449 
450 __attribute__((unused))
to_sns_data(PyObject * obj,struct lc3_sns_data * data)451 static PyObject *to_sns_data(PyObject *obj, struct lc3_sns_data *data)
452 {
453     PyObject *item;
454 
455     CTYPES_CHECK("sns", obj && PyDict_Check(obj));
456 
457     if ((item = PyDict_GetItemString(obj, "lfcb")))
458         CTYPES_CHECK("sns.lfcb", to_scalar(item, NPY_INT, &data->lfcb));
459 
460     if ((item = PyDict_GetItemString(obj, "hfcb")))
461         CTYPES_CHECK("sns.hfcb", to_scalar(item, NPY_INT, &data->hfcb));
462 
463     if ((item = PyDict_GetItemString(obj, "shape")))
464         CTYPES_CHECK("sns.shape", to_scalar(item, NPY_INT, &data->shape));
465 
466     if ((item = PyDict_GetItemString(obj, "gain")))
467         CTYPES_CHECK("sns.gain", to_scalar(item, NPY_INT, &data->gain));
468 
469     if ((item = PyDict_GetItemString(obj, "idx_a")))
470         CTYPES_CHECK("sns.idx_a", to_scalar(item, NPY_INT, &data->idx_a));
471 
472     if ((item = PyDict_GetItemString(obj, "ls_a")))
473         CTYPES_CHECK("sns.ls_a", to_scalar(item, NPY_INT, &data->ls_a));
474 
475     if ((item = PyDict_GetItemString(obj, "idx_b")))
476         CTYPES_CHECK("sns.idx_b", to_scalar(item, NPY_INT, &data->idx_b));
477 
478     if ((item = PyDict_GetItemString(obj, "ls_b")))
479         CTYPES_CHECK("sns.ls_b", to_scalar(item, NPY_INT, &data->ls_b));
480 
481     return obj;
482 }
483 
484 /* -------------------------------------------------------------------------- */
485 
486 #include <tns.h>
487 
488 __attribute__((unused))
new_tns_data(const struct lc3_tns_data * side)489 static PyObject *new_tns_data(const struct lc3_tns_data *side)
490 {
491     PyObject *obj = PyDict_New();
492 
493     PyDict_SetItemString(obj, "nfilters",
494         new_scalar(NPY_INT, &side->nfilters));
495 
496     PyDict_SetItemString(obj, "lpc_weighting",
497         new_scalar(NPY_BOOL, &side->lpc_weighting));
498 
499     PyDict_SetItemString(obj, "rc_order",
500         new_1d_copy(NPY_INT, 2, side->rc_order));
501 
502     PyDict_SetItemString(obj, "rc",
503         new_2d_copy(NPY_INT, 2, 8, side->rc));
504 
505     return obj;
506 }
507 
508 __attribute__((unused))
to_tns_data(PyObject * obj,struct lc3_tns_data * side)509 static PyObject *to_tns_data(PyObject *obj, struct lc3_tns_data *side)
510 {
511     PyObject *item;
512 
513     CTYPES_CHECK("tns", obj && PyDict_Check(obj));
514 
515     if ((item = PyDict_GetItemString(obj, "nfilters")))
516         CTYPES_CHECK("tns.nfilters",
517             to_scalar(item, NPY_INT, &side->nfilters));
518 
519     if ((item = PyDict_GetItemString(obj, "lpc_weighting"))) {
520         CTYPES_CHECK("tns.lpc_weighting",
521             to_scalar(item, NPY_BOOL, &side->lpc_weighting));
522     }
523 
524     if ((item = PyDict_GetItemString(obj, "rc_order"))) {
525         CTYPES_CHECK("tns.rc_order",
526             item = to_1d_copy(item, NPY_INT, side->rc_order, 2));
527         PyDict_SetItemString(obj, "rc_order", item);
528     }
529 
530     if ((item = PyDict_GetItemString(obj, "rc"))) {
531         CTYPES_CHECK("tns.rc",
532             item = to_2d_copy(item, NPY_INT, side->rc, 2, 8));
533         PyDict_SetItemString(obj, "rc", item);
534     }
535 
536     return obj;
537 }
538 
539 /* -------------------------------------------------------------------------- */
540 
541 #include <spec.h>
542 
543 __attribute__((unused))
from_spec_analysis(PyObject * obj,const struct lc3_spec_analysis * spec)544 static PyObject *from_spec_analysis(
545     PyObject *obj, const struct lc3_spec_analysis *spec)
546 {
547     if (!obj) obj = PyDict_New();
548 
549     PyDict_SetItemString(obj, "nbits_off",
550         new_scalar(NPY_FLOAT, &spec->nbits_off));
551 
552     PyDict_SetItemString(obj, "nbits_spare",
553         new_scalar(NPY_INT, &spec->nbits_spare));
554 
555     return obj;
556 }
557 
558 __attribute__((unused))
to_spec_analysis(PyObject * obj,struct lc3_spec_analysis * spec)559 static PyObject *to_spec_analysis(
560     PyObject *obj, struct lc3_spec_analysis *spec)
561 {
562     CTYPES_CHECK("spec", obj && PyDict_Check(obj));
563 
564     CTYPES_CHECK("spec.nbits_off",
565         to_scalar(PyDict_GetItemString(obj, "nbits_off"),
566             NPY_FLOAT, &spec->nbits_off));
567 
568     CTYPES_CHECK("spec.nbits_spare",
569         to_scalar(PyDict_GetItemString(obj, "nbits_spare"),
570             NPY_INT, &spec->nbits_spare));
571 
572     return obj;
573 }
574 
575 __attribute__((unused))
new_spec_side(const struct lc3_spec_side * side)576 static PyObject *new_spec_side(const struct lc3_spec_side *side)
577 {
578     PyObject *obj = PyDict_New();
579 
580     PyDict_SetItemString(obj, "g_idx",
581         new_scalar(NPY_INT, &side->g_idx));
582 
583     PyDict_SetItemString(obj, "nq",
584         new_scalar(NPY_INT, &side->nq));
585 
586     PyDict_SetItemString(obj, "lsb_mode",
587         new_scalar(NPY_BOOL, &side->lsb_mode));
588 
589     return obj;
590 }
591 
592 __attribute__((unused))
to_spec_data(PyObject * obj,struct lc3_spec_side * side)593 static PyObject *to_spec_data(
594     PyObject *obj, struct lc3_spec_side *side)
595 {
596     PyObject *item;
597 
598     CTYPES_CHECK("side", obj && PyDict_Check(obj));
599 
600     if ((item = PyDict_GetItemString(obj, "g_idx")))
601         CTYPES_CHECK("side.g_idx",
602             to_scalar(item, NPY_INT, &side->g_idx));
603 
604     if ((item = PyDict_GetItemString(obj, "nq")))
605         CTYPES_CHECK("side.nq",
606             to_scalar(item, NPY_INT, &side->nq));
607 
608     if ((item = PyDict_GetItemString(obj, "lsb_mode")))
609         CTYPES_CHECK("side.lsb_mode",
610             to_scalar(item, NPY_BOOL, &side->lsb_mode));
611 
612     return obj;
613 }
614 
615 /* -------------------------------------------------------------------------- */
616 
617 #ifdef __CTYPES_LC3_C
618 
619 __attribute__((unused))
new_side_data(const struct side_data * side)620 static PyObject *new_side_data(const struct side_data *side)
621 {
622     PyObject *obj = PyDict_New();
623 
624     PyDict_SetItemString(obj, "bw",
625         new_scalar(NPY_INT, &(int){ side->bw }));
626 
627     PyDict_SetItemString(obj, "ltpf",
628         new_ltpf_data(&side->ltpf));
629 
630     PyDict_SetItemString(obj, "sns",
631         new_sns_data(&side->sns));
632 
633     PyDict_SetItemString(obj, "tns",
634         new_tns_data(&side->tns));
635 
636     return obj;
637 }
638 
639 __attribute__((unused))
to_side_data(PyObject * obj,struct side_data * side)640 static PyObject *to_side_data(PyObject *obj, struct side_data *side)
641 {
642     PyObject *item;
643 
644     CTYPES_CHECK("frame", obj && PyDict_Check(obj));
645 
646     if ((item = PyDict_GetItemString(obj, "bw"))) {
647         int bw;
648         CTYPES_CHECK("frame.bw", to_scalar(item, NPY_INT, &bw));
649         side->bw = bw;
650     }
651 
652     if ((item = PyDict_GetItemString(obj, "ltpf")))
653         to_ltpf_data(item, &side->ltpf);
654 
655     if ((item = PyDict_GetItemString(obj, "sns")))
656         to_sns_data(item, &side->sns);
657 
658     if ((item = PyDict_GetItemString(obj, "tns")))
659         to_tns_data(item, &side->tns);
660 
661     return obj;
662 }
663 
664 __attribute__((unused))
new_plc_state(const struct lc3_plc_state * plc)665 static PyObject *new_plc_state(const struct lc3_plc_state *plc)
666 {
667     PyObject *obj = PyDict_New();
668 
669     PyDict_SetItemString(obj, "seed",
670         new_scalar(NPY_UINT16, &plc->seed));
671 
672     PyDict_SetItemString(obj, "count",
673         new_scalar(NPY_INT, &plc->count));
674 
675     PyDict_SetItemString(obj, "alpha",
676         new_scalar(NPY_FLOAT, &plc->alpha));
677 
678     return obj;
679 }
680 
681 __attribute__((unused))
to_plc_state(PyObject * obj,struct lc3_plc_state * plc)682 static PyObject *to_plc_state(
683     PyObject *obj, struct lc3_plc_state *plc)
684 {
685     CTYPES_CHECK("plc", obj && PyDict_Check(obj));
686 
687     CTYPES_CHECK("plc.seed", to_scalar(
688         PyDict_GetItemString(obj, "seed"), NPY_UINT16, &plc->seed));
689 
690     CTYPES_CHECK("plc.count", to_scalar(
691         PyDict_GetItemString(obj, "count"), NPY_INT, &plc->count));
692 
693     CTYPES_CHECK("plc.alpha", to_scalar(
694         PyDict_GetItemString(obj, "alpha"), NPY_FLOAT, &plc->alpha));
695 
696     return obj;
697 }
698 
699 __attribute__((unused))
from_encoder(PyObject * obj,const struct lc3_encoder * enc)700 static PyObject *from_encoder(PyObject *obj, const struct lc3_encoder *enc)
701 {
702     unsigned dt = enc->dt, sr = enc->sr;
703     unsigned sr_pcm = enc->sr_pcm;
704     int ns = LC3_NS(dt, sr);
705     int nd = LC3_ND(dt, sr);
706     int nt = LC3_NT(sr);
707 
708     if (!obj) obj = PyDict_New();
709 
710     PyDict_SetItemString(obj, "dt",
711         new_scalar(NPY_INT, &dt));
712 
713     PyDict_SetItemString(obj, "sr",
714         new_scalar(NPY_INT, &sr));
715 
716     PyDict_SetItemString(obj, "sr_pcm",
717         new_scalar(NPY_INT, &sr_pcm));
718 
719     PyDict_SetItemString(obj, "attdet",
720         from_attdet_analysis(NULL, &enc->attdet));
721 
722     PyDict_SetItemString(obj, "ltpf",
723         from_ltpf_analysis(NULL, &enc->ltpf));
724 
725     PyDict_SetItemString(obj, "quant",
726         from_spec_analysis(NULL, &enc->spec));
727 
728     PyDict_SetItemString(obj, "xt",
729         new_1d_copy(NPY_INT16, nt+ns, enc->xt-nt));
730 
731     PyDict_SetItemString(obj, "xs",
732         new_1d_copy(NPY_FLOAT, ns, enc->xs));
733 
734     PyDict_SetItemString(obj, "xd",
735         new_1d_copy(NPY_FLOAT, nd, enc->xd));
736 
737     return obj;
738 }
739 
740 __attribute__((unused))
to_encoder(PyObject * obj,struct lc3_encoder * enc)741 static PyObject *to_encoder(PyObject *obj, struct lc3_encoder *enc)
742 {
743     unsigned dt, sr, sr_pcm;
744     PyObject *xt_obj, *xs_obj, *xd_obj;
745 
746     CTYPES_CHECK("encoder", obj && PyDict_Check(obj));
747 
748     CTYPES_CHECK("encoder.dt", to_scalar(
749         PyDict_GetItemString(obj, "dt"), NPY_INT, &dt));
750     CTYPES_CHECK("encoder.dt", (unsigned)(enc->dt = dt) < LC3_NUM_DT);
751 
752     CTYPES_CHECK("encoder.sr", to_scalar(
753         PyDict_GetItemString(obj, "sr"), NPY_INT, &sr));
754     CTYPES_CHECK("encoder.sr", (unsigned)(enc->sr = sr) < LC3_NUM_SRATE);
755 
756     CTYPES_CHECK("encoder.sr_pcm", to_scalar(
757         PyDict_GetItemString(obj, "sr_pcm"), NPY_INT, &sr_pcm));
758     CTYPES_CHECK("encoder.s_pcmr",
759         (unsigned)(enc->sr_pcm = sr_pcm) < LC3_NUM_SRATE);
760 
761     int ns = LC3_NS(dt, sr);
762     int nd = LC3_ND(dt, sr);
763     int nt = LC3_NT(sr);
764 
765     CTYPES_CHECK(NULL, to_attdet_analysis(
766         PyDict_GetItemString(obj, "attdet"), &enc->attdet));
767 
768     CTYPES_CHECK(NULL, to_ltpf_analysis(
769         PyDict_GetItemString(obj, "ltpf"), &enc->ltpf));
770 
771     CTYPES_CHECK(NULL, to_spec_analysis(
772         PyDict_GetItemString(obj, "quant"), &enc->spec));
773 
774     CTYPES_CHECK("encoder.xt", xt_obj = to_1d_copy(
775         PyDict_GetItemString(obj, "xt"), NPY_INT16, enc->xt-nt, ns+nt));
776     PyDict_SetItemString(obj, "xt", xt_obj);
777 
778     CTYPES_CHECK("encoder.xs", xs_obj = to_1d_copy(
779         PyDict_GetItemString(obj, "xs"), NPY_FLOAT, enc->xs, ns));
780     PyDict_SetItemString(obj, "xs", xs_obj);
781 
782     CTYPES_CHECK("encoder.xd", xd_obj = to_1d_copy(
783         PyDict_GetItemString(obj, "xd"), NPY_FLOAT, enc->xd, nd));
784     PyDict_SetItemString(obj, "xd", xd_obj);
785 
786     return obj;
787 }
788 
789 __attribute__((unused))
from_decoder(PyObject * obj,const struct lc3_decoder * dec)790 static PyObject *from_decoder(PyObject *obj, const struct lc3_decoder *dec)
791 {
792     unsigned dt = dec->dt, sr = dec->sr;
793     unsigned sr_pcm = dec->sr_pcm;
794     unsigned xs_pos = dec->xs - dec->xh;
795     int nh = LC3_NH(dt, sr);
796     int ns = LC3_NS(dt, sr);
797     int nd = LC3_ND(dt, sr);
798 
799     if (!obj) obj = PyDict_New();
800 
801     PyDict_SetItemString(obj, "dt",
802         new_scalar(NPY_INT, &dt));
803 
804     PyDict_SetItemString(obj, "sr",
805         new_scalar(NPY_INT, &sr));
806 
807     PyDict_SetItemString(obj, "sr_pcm",
808         new_scalar(NPY_INT, &sr_pcm));
809 
810     PyDict_SetItemString(obj, "ltpf",
811         from_ltpf_synthesis(NULL, &dec->ltpf));
812 
813     PyDict_SetItemString(obj, "plc",
814         new_plc_state(&dec->plc));
815 
816     PyDict_SetItemString(obj, "xh",
817         new_1d_copy(NPY_FLOAT, nh, dec->xh));
818 
819     PyDict_SetItemString(obj, "xs_pos",
820         new_scalar(NPY_INT, &xs_pos));
821 
822     PyDict_SetItemString(obj, "xd",
823         new_1d_copy(NPY_FLOAT, nd, dec->xd));
824 
825     PyDict_SetItemString(obj, "xg",
826         new_1d_copy(NPY_FLOAT, ns, dec->xg));
827 
828     return obj;
829 }
830 
831 __attribute__((unused))
to_decoder(PyObject * obj,struct lc3_decoder * dec)832 static PyObject *to_decoder(PyObject *obj, struct lc3_decoder *dec)
833 {
834     unsigned dt, sr, sr_pcm, xs_pos;
835     PyObject *xh_obj, *xd_obj, *xg_obj;
836 
837     CTYPES_CHECK("decoder", obj && PyDict_Check(obj));
838 
839     CTYPES_CHECK("decoder.dt", to_scalar(
840         PyDict_GetItemString(obj, "dt"), NPY_INT, &dt));
841     CTYPES_CHECK("decoder.dt", (unsigned)(dec->dt = dt) < LC3_NUM_DT);
842 
843     CTYPES_CHECK("decoder.sr", to_scalar(
844         PyDict_GetItemString(obj, "sr"), NPY_INT, &sr));
845     CTYPES_CHECK("decoder.sr", (unsigned)(dec->sr = sr) < LC3_NUM_SRATE);
846 
847     CTYPES_CHECK("decoder.sr_pcm", to_scalar(
848         PyDict_GetItemString(obj, "sr_pcm"), NPY_INT, &sr_pcm));
849     CTYPES_CHECK("decoder.sr_pcm",
850         (unsigned)(dec->sr_pcm = sr_pcm) < LC3_NUM_SRATE);
851 
852     int nh = LC3_NH(dt, sr);
853     int ns = LC3_NS(dt, sr);
854     int nd = LC3_ND(dt, sr);
855 
856     CTYPES_CHECK(NULL, to_ltpf_synthesis(
857         PyDict_GetItemString(obj, "ltpf"), &dec->ltpf));
858 
859     CTYPES_CHECK(NULL, to_plc_state(
860         PyDict_GetItemString(obj, "plc"), &dec->plc));
861 
862     CTYPES_CHECK("decoder.xh", xh_obj = to_1d_copy(
863         PyDict_GetItemString(obj, "xh"), NPY_FLOAT, dec->xh, nh));
864     PyDict_SetItemString(obj, "xh", xh_obj);
865 
866     CTYPES_CHECK("decoder.xs", to_scalar(
867         PyDict_GetItemString(obj, "xs_pos"), NPY_INT, &xs_pos));
868     dec->xs = dec->xh + xs_pos;
869 
870     CTYPES_CHECK("decoder.xd", xd_obj = to_1d_copy(
871         PyDict_GetItemString(obj, "xd"), NPY_FLOAT, dec->xd, nd));
872     PyDict_SetItemString(obj, "xd", xd_obj);
873 
874     CTYPES_CHECK("decoder.xg", xg_obj = to_1d_copy(
875         PyDict_GetItemString(obj, "xg"), NPY_FLOAT, dec->xg, ns));
876     PyDict_SetItemString(obj, "xg", xg_obj);
877 
878     return obj;
879 }
880 
881 
882 /* -------------------------------------------------------------------------- */
883 
884 #endif /* __CTYPES_LC3_C */
885 
886 #endif /* __CTYPES */
887