1 #include "pcmconv.h"
2 #include <stdlib.h>
3 
4 /********************************************************
5  Audio Tools, a module and set of tools for manipulating audio data
6  Copyright (C) 2007-2014  Brian Langenberger
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21 *******************************************************/
22 
23 #ifndef STANDALONE
24 
25 #if PY_MAJOR_VERSION >= 3
26 #ifndef PyInt_AsLong
27 #define PyInt_AsLong PyLong_AsLong
28 #endif
29 #endif
30 
31 PyObject*
open_audiotools_pcm(void)32 open_audiotools_pcm(void)
33 {
34     return PyImport_ImportModule("audiotools.pcm");
35 }
36 
37 PyObject*
a_int_to_FrameList(PyObject * audiotools_pcm,a_int * samples,unsigned int channels,unsigned int bits_per_sample)38 a_int_to_FrameList(PyObject* audiotools_pcm,
39                    a_int* samples,
40                    unsigned int channels,
41                    unsigned int bits_per_sample)
42 {
43     if ((samples->len % channels) == 0) {
44         pcm_FrameList *framelist;
45 
46         if ((framelist = (pcm_FrameList*)empty_FrameList(
47                  audiotools_pcm, channels, bits_per_sample)) != NULL) {
48             framelist->frames = samples->len / channels;
49             framelist->samples_length = framelist->frames * framelist->channels;
50             framelist->samples = PyMem_Realloc(
51                 framelist->samples,
52                 framelist->samples_length *
53                 sizeof(int));
54 
55             memcpy(framelist->samples,
56                    samples->_,
57                    framelist->samples_length * sizeof(int));
58 
59             return (PyObject*)framelist;
60         } else {
61             return NULL;
62         }
63     } else {
64         PyErr_SetString(PyExc_ValueError,
65                         "samples data not divisible by channel count");
66         return NULL;
67     }
68 }
69 
70 PyObject*
aa_int_to_FrameList(PyObject * audiotools_pcm,aa_int * channels,unsigned int bits_per_sample)71 aa_int_to_FrameList(PyObject* audiotools_pcm,
72                     aa_int* channels,
73                     unsigned int bits_per_sample)
74 {
75     const unsigned channel_count = channels->len;
76     unsigned pcm_frames;
77     pcm_FrameList *framelist;
78 
79     /*ensure all channels are the same length*/
80     if (channel_count > 0) {
81         pcm_frames = channels->_[0]->len;
82         unsigned c;
83 
84         for (c = 1; c < channel_count; c++) {
85             if (channels->_[c]->len != pcm_frames) {
86                 PyErr_SetString(PyExc_ValueError, "channel length mismatch");
87                 return NULL;
88             }
89         }
90     } else {
91         pcm_frames = 0;
92     }
93 
94     /*then populate framelist*/
95     if ((framelist = (pcm_FrameList*)empty_FrameList(
96              audiotools_pcm, channel_count, bits_per_sample)) != NULL) {
97         unsigned c;
98         unsigned i;
99 
100         framelist->frames = pcm_frames;
101         framelist->samples_length = pcm_frames * channel_count;
102         framelist->samples = PyMem_Realloc(
103             framelist->samples,
104             framelist->samples_length *
105             sizeof(int));
106         for (c = 0; c < channel_count; c++) {
107             const a_int* channel = channels->_[c];
108             for (i = 0; i < pcm_frames; i++) {
109                 framelist->samples[(i * channel_count) + c] = channel->_[i];
110             }
111         }
112 
113         return (PyObject*)framelist;
114     } else {
115         return NULL;
116     }
117 }
118 
119 PyObject*
empty_FrameList(PyObject * audiotools_pcm,unsigned int channels,unsigned int bits_per_sample)120 empty_FrameList(PyObject* audiotools_pcm,
121                 unsigned int channels,
122                 unsigned int bits_per_sample)
123 {
124     return PyObject_CallMethod(
125         audiotools_pcm,
126         "empty_framelist", "ii", channels, bits_per_sample);
127 }
128 
129 struct pcmreader_s*
open_pcmreader(PyObject * pcmreader_obj)130 open_pcmreader(PyObject* pcmreader_obj)
131 {
132     struct pcmreader_s* pcmreader = malloc(sizeof(struct pcmreader_s));
133     PyObject* attr;
134     PyObject* audiotools_pcm;
135 
136     /*setup some placeholder values*/
137     pcmreader->pcmreader_obj = NULL;
138     pcmreader->framelist_type = NULL;
139     pcmreader->sample_rate = 0;
140     pcmreader->channels = 0;
141     pcmreader->channel_mask = 0;
142     pcmreader->bits_per_sample = 0;
143     pcmreader->bytes_per_sample = 0;
144     pcmreader->callbacks = NULL;
145 
146     pcmreader->read = pcmreader_read;
147     pcmreader->close = pcmreader_close;
148     pcmreader->add_callback = pcmreader_add_callback;
149     pcmreader->del = pcmreader_del;
150 
151     /*attempt to extract proper values from the pcmreader_obj*/
152     if ((attr = PyObject_GetAttrString(pcmreader_obj,
153                                        "sample_rate")) == NULL)
154         goto error;
155     pcmreader->sample_rate = (unsigned int)PyInt_AsLong(attr);
156     Py_DECREF(attr);
157     if (PyErr_Occurred())
158         goto error;
159 
160     if ((attr = PyObject_GetAttrString(pcmreader_obj,
161                                        "bits_per_sample")) == NULL)
162         goto error;
163     pcmreader->bits_per_sample = (unsigned int)PyInt_AsLong(attr);
164     Py_DECREF(attr);
165     if (PyErr_Occurred())
166         goto error;
167 
168     if ((attr = PyObject_GetAttrString(pcmreader_obj,
169                                        "channels")) == NULL)
170         goto error;
171     pcmreader->channels = (unsigned int)PyInt_AsLong(attr);
172     Py_DECREF(attr);
173     if (PyErr_Occurred())
174         goto error;
175 
176     if ((attr = PyObject_GetAttrString(pcmreader_obj,
177                                        "channel_mask")) == NULL)
178         goto error;
179     pcmreader->channel_mask = (unsigned int)PyInt_AsLong(attr);
180     Py_DECREF(attr);
181     if (PyErr_Occurred())
182         goto error;
183 
184     pcmreader->bytes_per_sample = pcmreader->bits_per_sample / 8;
185 
186     /*attach and incref the wrapped PCMReader object*/
187     pcmreader->pcmreader_obj = pcmreader_obj;
188     Py_INCREF(pcmreader_obj);
189 
190     /*attach a pcm.FrameList type object for verification during reads*/
191     if ((audiotools_pcm = PyImport_ImportModule("audiotools.pcm")) == NULL) {
192         goto error;
193     }
194 
195     pcmreader->framelist_type = PyObject_GetAttrString(audiotools_pcm,
196                                                        "FrameList");
197 
198     Py_DECREF(audiotools_pcm);
199 
200     return pcmreader;
201 
202  error:
203     Py_XDECREF(pcmreader->pcmreader_obj);
204     Py_XDECREF(pcmreader->framelist_type);
205     free(pcmreader);
206     return NULL;
207 }
208 
209 int
pcmreader_converter(PyObject * obj,void ** pcm_reader)210 pcmreader_converter(PyObject* obj, void** pcm_reader)
211 {
212     pcmreader* pcmreader_s = open_pcmreader(obj);
213     if (pcmreader_s != NULL) {
214         *pcm_reader = pcmreader_s;
215         return 1;
216     } else {
217         return 0;
218     }
219 }
220 
pcmreader_read(struct pcmreader_s * reader,unsigned pcm_frames,aa_int * channels)221 int pcmreader_read(struct pcmreader_s* reader,
222                     unsigned pcm_frames,
223                     aa_int* channels)
224 {
225     PyObject* framelist_obj;
226     pcm_FrameList* framelist;
227     unsigned frame;
228     unsigned channel;
229     a_int* channel_a;
230 
231     struct pcmreader_callback* callback;
232     PyObject* string_obj;
233     unsigned char* string;
234     Py_ssize_t string_length;
235 
236     /*make a call to "pcmreader.read(pcm_frames)"
237       where "pcm_frames" is set to the proper PCM frame count*/
238     if (((framelist_obj =
239           PyObject_CallMethod(reader->pcmreader_obj, "read", "i",
240                               (int)pcm_frames))) == NULL) {
241         /*ensure result isn't an exception*/
242         return 1;
243     }
244 
245     /*ensure result is a pcm.FrameList object*/
246     if (Py_TYPE(framelist_obj) != (PyTypeObject*)reader->framelist_type) {
247         Py_DECREF(framelist_obj);
248         PyErr_SetString(PyExc_TypeError,
249                         "results from pcmreader.read() must be FrameLists");
250         return 1;
251     } else {
252         framelist = (pcm_FrameList*)framelist_obj;
253     }
254 
255     /*split framelist's packed ints into a set of channels*/
256     channels->reset(channels);
257     for (channel = 0; channel < framelist->channels; channel++) {
258         channel_a = channels->append(channels);
259         channel_a->resize(channel_a, framelist->frames);
260         for (frame = 0; frame < framelist->frames; frame++) {
261             a_append(channel_a,
262                      framelist->samples[(frame * framelist->channels) +
263                                         channel]);
264         }
265     }
266 
267     /*apply all callbacks to pcm.FrameList object*/
268     for (callback = reader->callbacks;
269          callback != NULL;
270          callback = callback->next) {
271         string_obj = PyObject_CallMethod(framelist_obj,
272                                          "to_bytes", "(ii)",
273                                          !callback->little_endian,
274                                          callback->is_signed);
275         if (string_obj == NULL) {
276             Py_DECREF(framelist_obj);
277             return 1;
278         }
279 
280         if (PyBytes_AsStringAndSize(string_obj,
281                                     (char**)(&string),
282                                     &string_length) == -1) {
283             Py_DECREF(framelist_obj);
284             Py_DECREF(string_obj);
285             return 1;
286         }
287 
288         callback->callback(callback->user_data,
289                            string,
290                            (unsigned long)string_length);
291 
292         Py_DECREF(string_obj);
293     }
294 
295     /*free any allocated buffers and Python objects*/
296     Py_DECREF(framelist_obj);
297 
298     return 0;
299 }
300 
pcmreader_close(struct pcmreader_s * reader)301 void pcmreader_close(struct pcmreader_s* reader)
302 {
303     PyObject* result = PyObject_CallMethod(reader->pcmreader_obj,
304                                            "close", NULL);
305     if (result != NULL) {
306         Py_DECREF(result);
307     } else {
308         PyErr_Clear();
309     }
310 }
311 
pcmreader_del(struct pcmreader_s * reader)312 void pcmreader_del(struct pcmreader_s* reader)
313 {
314     struct pcmreader_callback *callback;
315     struct pcmreader_callback *next;
316 
317     /*free callback nodes*/
318     for (callback = reader->callbacks; callback != NULL; callback = next) {
319         next = callback->next;
320         free(callback);
321     }
322 
323     /*decref wrapped PCMReader object*/
324     Py_XDECREF(reader->pcmreader_obj);
325 
326     /*decref pcm.FrameList type*/
327     Py_XDECREF(reader->framelist_type);
328 
329     /*free pcmreader struct*/
330     free(reader);
331 }
332 
333 #else
334 
open_pcmreader(FILE * file,unsigned int sample_rate,unsigned int channels,unsigned int channel_mask,unsigned int bits_per_sample,unsigned int big_endian,unsigned int is_signed)335 struct pcmreader_s* open_pcmreader(FILE* file,
336                                    unsigned int sample_rate,
337                                    unsigned int channels,
338                                    unsigned int channel_mask,
339                                    unsigned int bits_per_sample,
340                                    unsigned int big_endian,
341                                    unsigned int is_signed)
342 {
343     struct pcmreader_s* pcmreader = malloc(sizeof(struct pcmreader_s));
344 
345     pcmreader->file = file;
346     pcmreader->sample_rate = sample_rate;
347     pcmreader->channels = channels;
348     pcmreader->channel_mask = channel_mask;
349     pcmreader->bits_per_sample = bits_per_sample;
350     pcmreader->bytes_per_sample = bits_per_sample / 8;
351 
352     pcmreader->big_endian = big_endian;
353     pcmreader->is_signed = is_signed;
354 
355     pcmreader->buffer_size = 1;
356     pcmreader->buffer = malloc(pcmreader->buffer_size);
357     pcmreader->callback_buffer_size = 1;
358     pcmreader->callback_buffer = malloc(pcmreader->callback_buffer_size);
359     pcmreader->buffer_converter =
360         FrameList_get_char_to_int_converter(pcmreader->bits_per_sample,
361                                             pcmreader->big_endian,
362                                             pcmreader->is_signed);;
363 
364     pcmreader->callbacks = NULL;
365 
366     pcmreader->read = pcmreader_read;
367     pcmreader->close = pcmreader_close;
368     pcmreader->add_callback = pcmreader_add_callback;
369     pcmreader->del = pcmreader_del;
370 
371     return pcmreader;
372 }
373 
pcmreader_read(struct pcmreader_s * reader,unsigned pcm_frames,aa_int * channels)374 int pcmreader_read(struct pcmreader_s* reader,
375                    unsigned pcm_frames,
376                    aa_int* channels)
377 {
378     unsigned bytes_to_read = (pcm_frames *
379                               reader->channels *
380                               reader->bytes_per_sample);
381     size_t bytes_read;
382     unsigned frames_read;
383 
384     a_int* channel_a;
385     unsigned int byte;
386     unsigned int sample;
387     unsigned int channel;
388     unsigned int frame;
389 
390     struct pcmreader_callback *callback;
391     FrameList_int_to_char_converter callback_converter;
392 
393     if (reader->buffer_size < bytes_to_read) {
394         reader->buffer_size = bytes_to_read;
395         reader->buffer = realloc(reader->buffer, bytes_to_read);
396     }
397 
398     /*read data into "buffer" as plain bytes*/
399     bytes_read = fread(reader->buffer, sizeof(uint8_t), bytes_to_read,
400                        reader->file);
401 
402     /*remove partial PCM frames, if any*/
403     while (bytes_read % (reader->channels * reader->bytes_per_sample))
404         bytes_read--;
405 
406     frames_read = (unsigned)(bytes_read /
407                              (reader->channels * reader->bytes_per_sample));
408 
409     /*place "buffer" into "channels", split up by channel*/
410     channels->reset(channels);
411     for (channel = 0; channel < reader->channels; channel++) {
412         channel_a = channels->append(channels);
413         channel_a->resize(channel_a, frames_read);
414         for (frame = 0; frame < frames_read; frame++) {
415             sample = channel + (frame * reader->channels);
416             a_append(channel_a,
417                      reader->buffer_converter(reader->buffer +
418                                               (sample *
419                                                reader->bytes_per_sample)));
420         }
421     }
422 
423     /*apply all callbacks on that collection of samples*/
424     for (callback = reader->callbacks;
425          callback != NULL;
426          callback = callback->next) {
427         if (reader->callback_buffer_size < bytes_read) {
428             reader->callback_buffer_size = bytes_read;
429             reader->callback_buffer = realloc(reader->callback_buffer,
430                                               bytes_read);
431         }
432 
433         callback_converter =
434             FrameList_get_int_to_char_converter(reader->bits_per_sample,
435                                                 !callback->little_endian,
436                                                 callback->is_signed);
437 
438         for (byte = 0; byte < bytes_read; byte += reader->bytes_per_sample) {
439             callback_converter(reader->buffer_converter(reader->buffer + byte),
440                                reader->callback_buffer + byte);
441         }
442 
443         callback->callback(callback->user_data,
444                            (unsigned char*)reader->callback_buffer,
445                            (unsigned long)bytes_read);
446     }
447 
448     return 0;
449 }
450 
pcmreader_close(struct pcmreader_s * reader)451 void pcmreader_close(struct pcmreader_s* reader)
452 {
453     fclose(reader->file);
454 }
455 
pcmreader_del(struct pcmreader_s * reader)456 void pcmreader_del(struct pcmreader_s* reader)
457 {
458     struct pcmreader_callback *callback;
459     struct pcmreader_callback *next;
460 
461     /*free callback nodes*/
462     for (callback = reader->callbacks; callback != NULL; callback = next) {
463         next = callback->next;
464         free(callback);
465     }
466 
467     /*free temporary buffer*/
468     free(reader->buffer);
469     free(reader->callback_buffer);
470 
471     /*free pcmreader struct*/
472     free(reader);
473 }
474 
475 
476 #endif
477 
478 
pcmreader_add_callback(struct pcmreader_s * reader,void (* callback)(void *,unsigned char *,unsigned long),void * user_data,int is_signed,int little_endian)479 void pcmreader_add_callback(struct pcmreader_s* reader,
480                             void (*callback)(void*,
481                                              unsigned char*,
482                                              unsigned long),
483                             void *user_data,
484                             int is_signed,
485                             int little_endian)
486 {
487     struct pcmreader_callback *callback_node =
488         malloc(sizeof(struct pcmreader_callback));
489 
490     callback_node->callback = callback;
491     callback_node->is_signed = is_signed;
492     callback_node->little_endian = little_endian;
493     callback_node->user_data = user_data;
494     callback_node->next = reader->callbacks;
495 
496     reader->callbacks = callback_node;
497 }
498