示例#1
0
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;
    }
}
示例#2
0
int
OggFlacDecoder_init(decoders_OggFlacDecoder *self,
                    PyObject *args, PyObject *kwds) {
    char* filename;
    ogg_status result;
    uint16_t header_packets;

    self->ogg_stream = NULL;
    self->ogg_file = NULL;
    self->subframe_data = aa_int_new();
    self->residuals = a_int_new();
    self->qlp_coeffs = a_int_new();
    self->framelist_data = a_int_new();
    self->audiotools_pcm = NULL;
    self->packet = br_substream_new(BS_BIG_ENDIAN);
    self->stream_finalized = 0;

    if (!PyArg_ParseTuple(args, "si", &filename, &(self->channel_mask)))
        return -1;

    if (self->channel_mask < 0) {
        PyErr_SetString(PyExc_ValueError, "channel_mask must be >= 0");
        return -1;
    }

    self->ogg_file = fopen(filename, "rb");
    if (self->ogg_file == NULL) {
        PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
        return -1;
    } else {
        self->ogg_stream = oggreader_open(self->ogg_file);
    }

    /*the first packet should be the FLAC's STREAMINFO*/
    if ((result = oggreader_next_packet(self->ogg_stream,
                                        self->packet)) == OGG_OK) {
        if (!oggflac_read_streaminfo(self->packet,
                                     &(self->streaminfo),
                                     &header_packets))
            return -1;
    } else {
        PyErr_SetString(ogg_exception(result), ogg_strerror(result));
        return -1;
    }

    /*skip subsequent header packets*/
    for (; header_packets > 0; header_packets--) {
        if ((result = oggreader_next_packet(self->ogg_stream,
                                            self->packet)) != OGG_OK) {
            PyErr_SetString(ogg_exception(result), ogg_strerror(result));
            return -1;
        }
    }

    /*initialize the output MD5 sum*/
    audiotools__MD5Init(&(self->md5));

    /*add callback for CRC16 calculation*/
    br_add_callback(self->packet, (bs_callback_f)flac_crc16, &(self->crc16));

    /*setup a framelist generator function*/
    if ((self->audiotools_pcm = open_audiotools_pcm()) == NULL)
        return -1;

    /*mark stream as not closed and ready for reading*/
    self->closed = 0;

    return 0;
}
示例#3
0
int
VorbisDecoder_init(decoders_VorbisDecoder *self, PyObject *args, PyObject *kwds) {
    char* filename;
    ogg_status ogg_result;
    vorbis_status vorbis_result;

    self->ogg_stream = NULL;
    self->ogg_file = NULL;
    self->packet = br_substream_new(BS_LITTLE_ENDIAN);

    if (!PyArg_ParseTuple(args, "s", &filename))
        goto error;
    self->ogg_file = fopen(filename, "rb");
    if (self->ogg_file == NULL) {
        PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
        goto error;
    } else {
        self->ogg_stream = oggreader_open(self->ogg_file);
    }

    /*read identification packet*/
    if ((ogg_result = oggreader_next_packet(self->ogg_stream,
                                        self->packet)) == OGG_OK) {
        if ((vorbis_result =
             vorbis_read_identification_packet(self->packet,
                                               &(self->identification))) !=
            VORBIS_OK) {
            PyErr_SetString(vorbis_exception(vorbis_result),
                            vorbis_strerror(vorbis_result));
            goto error;
        }
    } else {
        PyErr_SetString(ogg_exception(ogg_result), ogg_strerror(ogg_result));
        goto error;
    }

    /*skip comments packet, but ensure it's positioned properly*/
    if ((ogg_result = oggreader_next_packet(self->ogg_stream,
                                        self->packet)) == OGG_OK) {
        if (vorbis_read_common_header(self->packet) != 3) {
            PyErr_SetString(PyExc_ValueError,
                            "comment not second Ogg packet");
            goto error;
        }
    } else {
        PyErr_SetString(ogg_exception(ogg_result), ogg_strerror(ogg_result));
        goto error;
    }

    /*read setup header*/
    if ((ogg_result = oggreader_next_packet(self->ogg_stream,
                                        self->packet)) == OGG_OK) {
        if ((vorbis_result = vorbis_read_setup_packet(self->packet)) !=
            VORBIS_OK) {
            PyErr_SetString(vorbis_exception(vorbis_result),
                            vorbis_strerror(vorbis_result));
            goto error;
        }
    } else {
        PyErr_SetString(ogg_exception(ogg_result), ogg_strerror(ogg_result));
        goto error;
    }

    return 0;

 error:
    return -1;
}