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