static PyObject* ALACDecoder_read(decoders_ALACDecoder* self, PyObject *args) { pcm_FrameList *framelist; status_t status; unsigned pcm_frames_read; if (self->closed) { PyErr_SetString(PyExc_ValueError, "cannot read closed stream"); return NULL; } if (self->read_pcm_frames >= self->total_pcm_frames) { return empty_FrameList(self->audiotools_pcm, self->channels, self->bits_per_sample); } /*build FrameList based on alac decoding parameters*/ framelist = new_FrameList(self->audiotools_pcm, self->channels, self->bits_per_sample, self->params.block_size); /*decode ALAC frameset to FrameList*/ if (!setjmp(*br_try(self->bitstream))) { status = decode_frameset(self, &pcm_frames_read, framelist->samples); br_etry(self->bitstream); } else { br_etry(self->bitstream); Py_DECREF((PyObject*)framelist); PyErr_SetString(PyExc_IOError, "I/O error reading stream"); return NULL; } if (status != OK) { Py_DECREF((PyObject*)framelist); PyErr_SetString(alac_exception(status), alac_strerror(status)); return NULL; } /*constrain FrameList to actual amount of PCM frames read which may be less than block size at the end of stream*/ framelist->frames = pcm_frames_read; framelist->samples_length = pcm_frames_read * self->channels; /*reorder FrameList to .wav order*/ reorder_channels(pcm_frames_read, self->channels, framelist->samples); self->read_pcm_frames += pcm_frames_read; /*return populated FrameList*/ return (PyObject*)framelist; }
static PyObject* MP3Decoder_read(decoders_MP3Decoder* self, PyObject *args) { pcm_FrameList *framelist; int *samples; static int16_t buffer[BUFFER_SIZE]; size_t buffer_size; size_t i; if (self->closed) { PyErr_SetString(PyExc_ValueError, "stream is closed"); return NULL; } /*perform mpg123_read() to output buffer*/ switch (mpg123_read(self->handle, (unsigned char*)buffer, BUFFER_SIZE, &buffer_size)) { case MPG123_DONE: /*return empty framelist*/ return empty_FrameList(self->audiotools_pcm, self->channels, 16); case MPG123_OK: framelist = new_FrameList(self->audiotools_pcm, self->channels, BITS_PER_SAMPLE, (unsigned)(buffer_size / 2 / self->channels)); samples = framelist->samples; for (i = 0; i < (buffer_size / 2); i++) { samples[i] = buffer[i]; } return (PyObject*)framelist; default: /*raise exception*/ PyErr_SetString(PyExc_ValueError, "error decoding MP3 frame"); return NULL; } }
PyObject* FlacDecoder_read(decoders_FlacDecoder* self, PyObject *args) { uint16_t crc16 = 0; int channel; struct flac_frame_header frame_header; PyObject* framelist; PyThreadState *thread_state; flac_status error; if (self->closed) { PyErr_SetString(PyExc_ValueError, "cannot read closed stream"); return NULL; } self->subframe_data->reset(self->subframe_data); /*if all samples have been read, return an empty FrameList*/ if (self->stream_finalized) { return empty_FrameList(self->audiotools_pcm, self->streaminfo.channels, self->streaminfo.bits_per_sample); } if (self->remaining_samples < 1) { self->stream_finalized = 1; if (FlacDecoder_verify_okay(self)) { return empty_FrameList(self->audiotools_pcm, self->streaminfo.channels, self->streaminfo.bits_per_sample); } else { PyErr_SetString(PyExc_ValueError, "MD5 mismatch at end of stream"); return NULL; } } thread_state = PyEval_SaveThread(); if (!setjmp(*br_try(self->bitstream))) { /*add callback for CRC16 calculation*/ br_add_callback(self->bitstream, (bs_callback_f)flac_crc16, &crc16); /*read frame header*/ if ((error = flacdec_read_frame_header(self->bitstream, &(self->streaminfo), &frame_header)) != OK) { br_pop_callback(self->bitstream, NULL); PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_ValueError, FlacDecoder_strerror(error)); br_etry(self->bitstream); return NULL; } /*read 1 subframe per channel*/ for (channel = 0; channel < frame_header.channel_count; channel++) if ((error = flacdec_read_subframe( self->bitstream, self->qlp_coeffs, self->residuals, (unsigned int)MIN(frame_header.block_size, self->remaining_samples), flacdec_subframe_bits_per_sample(&frame_header, channel), self->subframe_data->append(self->subframe_data))) != OK) { br_pop_callback(self->bitstream, NULL); PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_ValueError, FlacDecoder_strerror(error)); br_etry(self->bitstream); return NULL; } /*handle difference channels, if any*/ flacdec_decorrelate_channels(frame_header.channel_assignment, self->subframe_data, self->framelist_data); /*check CRC-16*/ self->bitstream->byte_align(self->bitstream); self->bitstream->read(self->bitstream, 16); br_pop_callback(self->bitstream, NULL); if (crc16 != 0) { PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_ValueError, "invalid checksum in frame"); br_etry(self->bitstream); return NULL; } /*decrement remaining samples*/ self->remaining_samples -= frame_header.block_size; } else { /*handle I/O error during read*/ br_pop_callback(self->bitstream, NULL); PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_IOError, "EOF reading frame"); br_etry(self->bitstream); return NULL; } br_etry(self->bitstream); PyEval_RestoreThread(thread_state); framelist = array_i_to_FrameList(self->audiotools_pcm, self->framelist_data, frame_header.channel_count, frame_header.bits_per_sample); if (framelist != NULL) { /*update MD5 sum*/ if (FlacDecoder_update_md5sum(self, framelist) == OK) /*return pcm.FrameList Python object*/ return framelist; else { Py_DECREF(framelist); return NULL; } } else { return NULL; } }
static PyObject* ALACDecoder_read(decoders_ALACDecoder* self, PyObject *args) { unsigned channel_count; BitstreamReader* mdat = self->bitstream; array_ia* frameset_channels = self->frameset_channels; PyThreadState *thread_state; /*return an empty framelist if total samples are exhausted*/ if (self->remaining_frames == 0) { return empty_FrameList(self->audiotools_pcm, self->channels, self->bits_per_sample); } thread_state = PyEval_SaveThread(); if (!setjmp(*br_try(mdat))) { frameset_channels->reset(frameset_channels); /*get initial frame's channel count*/ channel_count = mdat->read(mdat, 3) + 1; while (channel_count != 8) { /*read a frame from the frameset into "channels"*/ if (read_frame(self, mdat, frameset_channels, channel_count) != OK) { br_etry(mdat); PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_ValueError, self->error_message); return NULL; } else { /*ensure all frames have the same sample count*/ /*FIXME*/ /*read the channel count of the next frame in the frameset, if any*/ channel_count = mdat->read(mdat, 3) + 1; } } /*once all the frames in the frameset are read, byte-align the output stream*/ mdat->byte_align(mdat); br_etry(mdat); PyEval_RestoreThread(thread_state); /*decrement the remaining sample count*/ self->remaining_frames -= MIN(self->remaining_frames, frameset_channels->_[0]->len); /*convert ALAC channel assignment to standard audiotools assignment*/ alac_order_to_wave_order(frameset_channels); /*finally, build and return framelist object from the sample data*/ return array_ia_to_FrameList(self->audiotools_pcm, frameset_channels, self->bits_per_sample); } else { br_etry(mdat); PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_IOError, "EOF during frame reading"); return NULL; } }
static PyObject* OggFlacDecoder_read(decoders_OggFlacDecoder *self, PyObject *args) { ogg_status ogg_status; flac_status flac_status; struct flac_frame_header frame_header; int channel; PyObject *framelist; PyThreadState *thread_state; if (self->closed) { PyErr_SetString(PyExc_ValueError, "cannot read closed stream"); return NULL; } self->subframe_data->reset(self->subframe_data); /*if all samples have been read, return an empty FrameList*/ if (self->stream_finalized) { return empty_FrameList(self->audiotools_pcm, self->streaminfo.channels, self->streaminfo.bits_per_sample); } thread_state = PyEval_SaveThread(); ogg_status = oggreader_next_packet(self->ogg_stream, self->packet); PyEval_RestoreThread(thread_state); if (ogg_status == OGG_OK) { /*decode the next FrameList from the stream*/ thread_state = PyEval_SaveThread(); self->crc16 = 0; if (!setjmp(*br_try(self->packet))) { /*read frame header*/ if ((flac_status = flacdec_read_frame_header(self->packet, &(self->streaminfo), &frame_header)) != OK) { PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_ValueError, FlacDecoder_strerror(flac_status)); br_etry(self->packet); return NULL; } /*read 1 subframe per channel*/ for (channel = 0; channel < frame_header.channel_count; channel++) if ((flac_status = flacdec_read_subframe( self->packet, self->qlp_coeffs, self->residuals, frame_header.block_size, flacdec_subframe_bits_per_sample(&frame_header, channel), self->subframe_data->append(self->subframe_data))) != OK) { PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_ValueError, FlacDecoder_strerror(flac_status)); br_etry(self->packet); return NULL; } br_etry(self->packet); /*handle difference channels, if any*/ flacdec_decorrelate_channels(frame_header.channel_assignment, self->subframe_data, self->framelist_data); /*check CRC-16*/ self->packet->byte_align(self->packet); self->packet->read(self->packet, 16); if (self->crc16 != 0) { PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_ValueError, "invalid checksum in frame"); return NULL; } PyEval_RestoreThread(thread_state); framelist = a_int_to_FrameList(self->audiotools_pcm, self->framelist_data, frame_header.channel_count, frame_header.bits_per_sample); if (framelist != NULL) { /*update MD5 sum*/ if (OggFlacDecoder_update_md5sum(self, framelist) == 1) /*return pcm.FrameList Python object*/ return framelist; else { Py_DECREF(framelist); return NULL; } } else { return NULL; } } else { /*read error decoding FLAC frame*/ PyEval_RestoreThread(thread_state); PyErr_SetString(PyExc_IOError, "I/O error decoding FLAC frame"); br_etry(self->packet); return NULL; } } else if (ogg_status == OGG_STREAM_FINISHED) { /*Ogg stream is finished so verify stream's MD5 sum then return an empty FrameList if it matches correctly*/ if (OggFlacDecoder_verify_okay(self)) { self->stream_finalized = 1; return empty_FrameList(self->audiotools_pcm, self->streaminfo.channels, self->streaminfo.bits_per_sample); } else { PyErr_SetString(PyExc_ValueError, "MD5 mismatch at end of stream"); return NULL; } } else { /*error reading the next Ogg packet, so raise the appropriate exception*/ PyErr_SetString(ogg_exception(ogg_status), ogg_strerror(ogg_status)); return NULL; } }
static PyObject* DVDA_Title_read(decoders_DVDA_Title *self, PyObject *args) { DVDA_Packet next_packet; struct bs_buffer* packet_data = self->packet_data; mlp_status mlp_status; /*if track has been exhausted, return empty FrameList*/ if (!self->pcm_frames_remaining) { return empty_FrameList(self->audiotools_pcm, self->channel_count, self->bits_per_sample); } /*otherwise, build FrameList from PCM or MLP packet data*/ switch (self->frame_codec) { case PCM: /*if not enough bytes in buffer, read another packet*/ while (aobpcm_packet_empty(&(self->pcm_decoder), self->frames)) { if (read_audio_packet(self->packet_reader, &next_packet, packet_data)) { PyErr_SetString(PyExc_IOError, "I/O reading PCM packet"); return NULL; } /*FIXME - ensure packet has same format as PCM*/ buf_extend(packet_data, self->frames); } /*FIXME - make this thread friendly*/ read_aobpcm(&(self->pcm_decoder), self->frames, self->codec_framelist); break; case MLP: /*if not enough bytes in buffer, read another packet*/ while (mlp_packet_empty(self->mlp_decoder)) { if (read_audio_packet(self->packet_reader, &next_packet, packet_data)) { PyErr_SetString(PyExc_IOError, "I/O reading MLP packet"); return NULL; } /*FIXME - ensure packet has same format as MLP*/ buf_extend(packet_data, self->frames); } /*FIXME - make this thread friendly*/ if ((mlp_status = read_mlp_frames(self->mlp_decoder, self->codec_framelist)) != OK) { PyErr_SetString(mlp_python_exception(mlp_status), mlp_python_exception_msg(mlp_status)); return NULL; } } /*account for framelists larger than frames remaining*/ self->codec_framelist->cross_split(self->codec_framelist, MIN(self->pcm_frames_remaining, self->codec_framelist->_[0]->len), self->output_framelist, self->codec_framelist); /*deduct output FrameList's PCM frames from remaining count*/ self->pcm_frames_remaining -= self->output_framelist->_[0]->len; /*and return output FrameList*/ return aa_int_to_FrameList(self->audiotools_pcm, self->output_framelist, self->bits_per_sample); }
static PyObject* VorbisDecoder_read(decoders_VorbisDecoder *self, PyObject *args) { int current_bitstream; long samples_read; float **pcm_channels; if (self->closed) { PyErr_SetString(PyExc_ValueError, "stream is closed"); return NULL; } samples_read = ov_read_float(&(self->vorbisfile), &pcm_channels, 4096, ¤t_bitstream); if (samples_read >= 0) { /*convert floating point samples to integer-based ones*/ pcm_FrameList *framelist; int *samples; int c; if (samples_read == 0) { if (self->vorbisfile.os.e_o_s == 0) { /*EOF encountered without EOF being marked in stream*/ PyErr_SetString(PyExc_IOError, "I/O error reading from Ogg stream"); return NULL; } else { return empty_FrameList(self->audiotools_pcm, self->channel_count, BITS_PER_SAMPLE); } } framelist = new_FrameList(self->audiotools_pcm, self->channel_count, BITS_PER_SAMPLE, (unsigned)samples_read); samples = framelist->samples; for (c = 0; c < self->channel_count; c++) { int channel[samples_read]; float_to_int_converter(BITS_PER_SAMPLE)( (unsigned)samples_read, pcm_channels[c], channel); put_channel_data(samples, c, self->channel_count, (unsigned)samples_read, channel); } /*reorder channels to .wav order if necessary*/ switch (self->channel_count) { case 1: case 2: default: /*no change*/ break; case 3: /*fL fC fR -> fL fR fC*/ swap_channel_data(samples, 1, 2, self->channel_count, (unsigned)samples_read); break; case 4: /*fL fR bL bR -> fL fR bL bR*/ /*no change*/ break; case 5: /*fL fC fR bL bR -> fL fR fC bL bR*/ swap_channel_data(samples, 1, 2, self->channel_count, (unsigned)samples_read); break; case 6: /*fL fC fR bL bR LFE -> fL fR fC bL bR LFE*/ swap_channel_data(samples, 1, 2, self->channel_count, (unsigned)samples_read); /*fL fR fC bL bR LFE -> fL fR fC LFE bR bL*/ swap_channel_data(samples, 3, 5, self->channel_count, (unsigned)samples_read); /*fL fR fC LFE bR bL -> fL fR fC LFE bL bR*/ swap_channel_data(samples, 4, 5, self->channel_count, (unsigned)samples_read); break; case 7: /*fL fC fR sL sR bC LFE -> fL fR fC sL sR bC LFE*/ swap_channel_data(samples, 1, 2, self->channel_count, (unsigned)samples_read); /*fL fR fC sL sR bC LFE -> fL fR fC LFE sR bC sL*/ swap_channel_data(samples, 3, 6, self->channel_count, (unsigned)samples_read); /*fL fR fC LFE sR bC sL -> fL fR fC LFE bC sR sL*/ swap_channel_data(samples, 4, 5, self->channel_count, (unsigned)samples_read); /*fL fR fC LFE bC sR sL -> fL fR fC LFE bC sL sR*/ swap_channel_data(samples, 5, 6, self->channel_count, (unsigned)samples_read); break; case 8: /*fL fC fR sL sR bL bR LFE -> fL fR fC sL sR bL bR LFE*/ swap_channel_data(samples, 1, 2, self->channel_count, (unsigned)samples_read); /*fL fR fC sL sR bL bR LFE -> fL fR fC LFE sR bL bR sL*/ swap_channel_data(samples, 3, 6, self->channel_count, (unsigned)samples_read); /*fL fR fC LFE sR bL bR sL -> fL fR fC LFE bL sR bR sL*/ swap_channel_data(samples, 4, 5, self->channel_count, (unsigned)samples_read); /*fL fR fC LFE bL sR bR sL -> fL fR fC LFE bL bR sR sL*/ swap_channel_data(samples, 5, 6, self->channel_count, (unsigned)samples_read); /*fL fR fC LFE bL bR sR sL -> fL fR fC LFE bL bR sL sR*/ swap_channel_data(samples, 6, 7, self->channel_count, (unsigned)samples_read); break; } return (PyObject*)framelist; } else { switch (samples_read) { case OV_HOLE: PyErr_SetString(PyExc_ValueError, "data interruption detected"); return NULL; case OV_EBADLINK: PyErr_SetString(PyExc_ValueError, "invalid stream section"); return NULL; case OV_EINVAL: PyErr_SetString(PyExc_ValueError, "initial file headers corrupt"); return NULL; default: PyErr_SetString(PyExc_ValueError, "unspecified error"); return NULL; } } }