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, <pf->active));
277
278 CTYPES_CHECK("ltpf.pitch", to_scalar(
279 PyDict_GetItemString(obj, "pitch"), NPY_INT, <pf->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"), <pf->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, <pf->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, <pf->active));
313
314 PyDict_SetItemString(obj, "pitch",
315 new_scalar(NPY_INT, <pf->pitch));
316
317 PyDict_SetItemString(obj, "nc",
318 new_1d_copy(NPY_FLOAT, 2, <pf->nc));
319
320 PyDict_SetItemString(obj, "hp50",
321 from_ltpf_hp50_state(PyDict_New(), <pf->hp50));
322
323 PyDict_SetItemString(obj, "x_12k8",
324 new_1d_copy(NPY_INT16, n_12k8, <pf->x_12k8));
325
326 PyDict_SetItemString(obj, "x_6k4",
327 new_1d_copy(NPY_INT16, n_6k4, <pf->x_6k4));
328
329 PyDict_SetItemString(obj, "tc",
330 new_scalar(NPY_INT, <pf->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, <pf->active));
345
346 CTYPES_CHECK("ltpf.pitch", to_scalar(
347 PyDict_GetItemString(obj, "pitch"), NPY_INT, <pf->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, <pf->active));
368
369 PyDict_SetItemString(obj, "pitch",
370 new_scalar(NPY_INT, <pf->pitch));
371
372 PyDict_SetItemString(obj, "c",
373 new_1d_copy(NPY_FLOAT, 2*12, <pf->c));
374
375 PyDict_SetItemString(obj, "x",
376 new_1d_copy(NPY_FLOAT, 12, <pf->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