Exemplo n.º 1
0
OggReader*
oggreader_open(FILE *stream) {
    OggReader *reader = malloc(sizeof(OggReader));
    reader->ogg_stream = br_open(stream, BS_LITTLE_ENDIAN);
    reader->current_segment = 1;
    reader->current_header.page_segment_count = 0;
    reader->current_header.type = 0;
    reader->current_header.checksum = 0;
    reader->checksum = 0;
    br_add_callback(reader->ogg_stream, ogg_crc, &(reader->checksum));
    return reader;
}
Exemplo n.º 2
0
flac_status
flacdec_read_frame_header(BitstreamReader *bitstream,
                          struct flac_STREAMINFO *streaminfo,
                          struct flac_frame_header *header)
{
    unsigned block_size_bits;
    unsigned sample_rate_bits;
    uint8_t crc8 = 0;

    br_add_callback(bitstream, (bs_callback_f)flac_crc8, &crc8);

    /*read and verify sync code*/
    if (bitstream->read(bitstream, 14) != 0x3FFE) {
        return ERR_INVALID_SYNC_CODE;
    }

    /*read and verify reserved bit*/
    if (bitstream->read(bitstream, 1) != 0) {
        return ERR_INVALID_RESERVED_BIT;
    }

    header->blocking_strategy = bitstream->read(bitstream, 1);

    block_size_bits = bitstream->read(bitstream, 4);
    sample_rate_bits = bitstream->read(bitstream, 4);
    header->channel_assignment = bitstream->read(bitstream, 4);
    switch (header->channel_assignment) {
    case 0x8:
    case 0x9:
    case 0xA:
        header->channel_count = 2;
        break;
    default:
        header->channel_count = header->channel_assignment + 1;
        break;
    }

    switch (bitstream->read(bitstream, 3)) {
    case 0:
        header->bits_per_sample = streaminfo->bits_per_sample; break;
    case 1:
        header->bits_per_sample = 8; break;
    case 2:
        header->bits_per_sample = 12; break;
    case 4:
        header->bits_per_sample = 16; break;
    case 5:
        header->bits_per_sample = 20; break;
    case 6:
        header->bits_per_sample = 24; break;
    default:
        return ERR_INVALID_BITS_PER_SAMPLE;
    }
    bitstream->read(bitstream, 1); /*padding*/

    header->frame_number = read_utf8(bitstream);

    switch (block_size_bits) {
    case 0x0: header->block_size = streaminfo->maximum_block_size; break;
    case 0x1: header->block_size = 192; break;
    case 0x2: header->block_size = 576; break;
    case 0x3: header->block_size = 1152; break;
    case 0x4: header->block_size = 2304; break;
    case 0x5: header->block_size = 4608; break;
    case 0x6: header->block_size = bitstream->read(bitstream, 8) + 1; break;
    case 0x7: header->block_size = bitstream->read(bitstream, 16) + 1; break;
    case 0x8: header->block_size = 256; break;
    case 0x9: header->block_size = 512; break;
    case 0xA: header->block_size = 1024; break;
    case 0xB: header->block_size = 2048; break;
    case 0xC: header->block_size = 4096; break;
    case 0xD: header->block_size = 8192; break;
    case 0xE: header->block_size = 16384; break;
    case 0xF: header->block_size = 32768; break;
    }

    switch (sample_rate_bits) {
    case 0x0: header->sample_rate = streaminfo->sample_rate; break;
    case 0x1: header->sample_rate = 88200; break;
    case 0x2: header->sample_rate = 176400; break;
    case 0x3: header->sample_rate = 192000; break;
    case 0x4: header->sample_rate = 8000; break;
    case 0x5: header->sample_rate = 16000; break;
    case 0x6: header->sample_rate = 22050; break;
    case 0x7: header->sample_rate = 24000; break;
    case 0x8: header->sample_rate = 32000; break;
    case 0x9: header->sample_rate = 44100; break;
    case 0xA: header->sample_rate = 48000; break;
    case 0xB: header->sample_rate = 96000; break;
    case 0xC: header->sample_rate = bitstream->read(bitstream, 8) * 1000; break;
    case 0xD: header->sample_rate = bitstream->read(bitstream, 16); break;
    case 0xE: header->sample_rate = bitstream->read(bitstream, 16) * 10; break;
    case 0xF:
        return ERR_INVALID_SAMPLE_RATE;
    }

    /*check for valid CRC-8 value*/
    bitstream->read(bitstream, 8);
    br_pop_callback(bitstream, NULL);
    if (crc8 != 0)
        return ERR_INVALID_FRAME_CRC;

    /*Once we've read everything,
      ensure the values are compatible with STREAMINFO.*/

    if (streaminfo->sample_rate != header->sample_rate) {
        return ERR_SAMPLE_RATE_MISMATCH;
    }
    if (streaminfo->channels != header->channel_count) {
        return ERR_CHANNEL_COUNT_MISMATCH;
    }
    if (streaminfo->bits_per_sample != header->bits_per_sample) {
        return ERR_BITS_PER_SAMPLE_MISMATCH;
    }
    if (header->block_size > streaminfo->maximum_block_size) {
        return ERR_MAXIMUM_BLOCK_SIZE_EXCEEDED;
    }

    return OK;
}
Exemplo n.º 3
0
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;
    }
}
Exemplo n.º 4
0
static PyObject*
FlacDecoder_offsets(decoders_FlacDecoder* self, PyObject *args)
{
    int channel;
    struct flac_frame_header frame_header;
    flac_status error;
    PyObject* offsets = PyList_New(0);
    PyObject* offset_pair;
    unsigned long long total_offset = 0;
    unsigned samples;
    unsigned long long offset;

    br_add_callback(self->bitstream,
                    (bs_callback_f)increment_offset,
                    &total_offset);

    while (self->remaining_samples > 0) {
        self->subframe_data->reset(self->subframe_data);
        offset = total_offset;

        if (!setjmp(*br_try(self->bitstream))) {
            /*read frame header*/
            if ((error = flacdec_read_frame_header(self->bitstream,
                                                   &(self->streaminfo),
                                                   &frame_header)) != OK) {
                PyErr_SetString(PyExc_ValueError, FlacDecoder_strerror(error));
                goto error;
            }

            samples = frame_header.block_size;

            /*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) {
                    PyErr_SetString(PyExc_ValueError,
                                    FlacDecoder_strerror(error));
                    goto error;
                }

            /*read CRC-16*/
            self->bitstream->byte_align(self->bitstream);
            self->bitstream->read(self->bitstream, 16);

            /*decrement remaining samples*/
            self->remaining_samples -= frame_header.block_size;

            /*add offset pair to our list*/
            offset_pair = Py_BuildValue("(K, I)", offset, samples);
            PyList_Append(offsets, offset_pair);
            Py_DECREF(offset_pair);
        } else {
            /*handle I/O error during read*/
            PyErr_SetString(PyExc_IOError, "EOF reading frame");
            goto error;
        }

        br_etry(self->bitstream);
    }

    self->stream_finalized = 1;
    br_pop_callback(self->bitstream, NULL);

    return offsets;
error:
    Py_XDECREF(offsets);
    br_etry(self->bitstream);
    br_pop_callback(self->bitstream, NULL);

    return NULL;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
int main(int argc, char* argv[]) {
    FILE* ogg_file;
    OggReader* ogg_stream = NULL;
    BitstreamReader* packet = NULL;
    struct flac_STREAMINFO streaminfo;
    uint16_t header_packets;
    a_int* residuals = NULL;
    a_int* qlp_coeffs = NULL;
    aa_int* subframe_data = NULL;
    a_int* framelist_data = NULL;
    ogg_status result;
    uint16_t crc16 = 0;

    FrameList_int_to_char_converter converter;
    unsigned pcm_size;
    unsigned output_data_size = 1;
    uint8_t* output_data = NULL;

    audiotools__MD5Context md5;
    unsigned char stream_md5sum[16];
    const static unsigned char blank_md5sum[16] = {0, 0, 0, 0, 0, 0, 0, 0,
                                                   0, 0, 0, 0, 0, 0, 0, 0};

    if (argc < 2) {
        fprintf(stderr, "*** Usage: %s <file.oga>\n", argv[0]);
        return 1;
    }

    /*open input file for reading*/
    if ((ogg_file = fopen(argv[1], "rb")) == NULL) {
        fprintf(stderr, "*** %s: %s\n", argv[1], strerror(errno));
        return 1;
    } else {
        /*open bitstream and setup temporary arrays/buffers*/
        ogg_stream = oggreader_open(ogg_file);
        packet = br_substream_new(BS_BIG_ENDIAN);
        subframe_data = aa_int_new();
        residuals = a_int_new();
        qlp_coeffs = a_int_new();
        framelist_data = a_int_new();
        output_data = malloc(output_data_size);
    }

    /*the first packet should be the FLAC's STREAMINFO*/
    if ((result = oggreader_next_packet(ogg_stream, packet)) == OGG_OK) {
        if (!oggflac_read_streaminfo(packet, &streaminfo, &header_packets)) {
            goto error;
        } else {
            converter = FrameList_get_int_to_char_converter(
                streaminfo.bits_per_sample, 0, 1);
        }
    } else {
        fprintf(stderr, "*** Error: %s\n", ogg_strerror(result));
        goto error;
    }

    /*skip subsequent header packets*/
    for (; header_packets > 0; header_packets--) {
        if ((result = oggreader_next_packet(ogg_stream, packet)) != OGG_OK) {
            fprintf(stderr, "*** Error: %s\n", ogg_strerror(result));
            goto error;
        }
    }

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

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

    /*decode the next FrameList from the stream*/
    result = oggreader_next_packet(ogg_stream, packet);

    while (result != OGG_STREAM_FINISHED) {
        if (result == OGG_OK) {
            flac_status flac_status;
            struct flac_frame_header frame_header;
            unsigned channel;

            subframe_data->reset(subframe_data);

            if (!setjmp(*br_try(packet))) {
                /*read frame header*/
                if ((flac_status =
                     flacdec_read_frame_header(packet,
                                               &streaminfo,
                                               &frame_header)) != OK) {
                    fprintf(stderr, "*** Error: %s\n",
                            FlacDecoder_strerror(flac_status));
                    br_etry(packet);
                    goto error;
                }

                /*read 1 subframe per channel*/
                for (channel = 0;
                     channel < frame_header.channel_count;
                     channel++)
                    if ((flac_status = flacdec_read_subframe(
                        packet,
                        qlp_coeffs,
                        residuals,
                        frame_header.block_size,
                        flacdec_subframe_bits_per_sample(&frame_header,
                                                         channel),
                        subframe_data->append(subframe_data))) != OK) {
                        fprintf(stderr, "*** Error: %s\n",
                                FlacDecoder_strerror(flac_status));
                        br_etry(packet);
                        goto error;
                    }

                br_etry(packet);
            } else {
                br_etry(packet);
                fprintf(stderr, "*** I/O Error reading FLAC frame\n");
                goto error;
            }

            /*handle difference channels, if any*/
            flacdec_decorrelate_channels(frame_header.channel_assignment,
                                         subframe_data,
                                         framelist_data);

            /*check CRC-16*/
            packet->byte_align(packet);
            packet->read(packet, 16);
            if (crc16 != 0) {
                fprintf(stderr, "*** Error: invalid checksum in frame\n");
                goto error;
            }

            /*turn FrameList into string of output*/
            pcm_size = (streaminfo.bits_per_sample / 8) * framelist_data->len;
            if (pcm_size > output_data_size) {
                output_data_size = pcm_size;
                output_data = realloc(output_data, output_data_size);
            }
            FrameList_samples_to_char(output_data,
                                      framelist_data->_,
                                      converter,
                                      framelist_data->len,
                                      streaminfo.bits_per_sample);

            /*update MD5 sum*/
            audiotools__MD5Update(&md5, output_data, pcm_size);

            /*output string to stdout*/
            fwrite(output_data, sizeof(unsigned char), pcm_size, stdout);

            result = oggreader_next_packet(ogg_stream, packet);
        } else {
            /*some error reading Ogg stream*/
            fprintf(stderr, "*** Error: %s\n", ogg_strerror(result));
            goto error;
        }
    }

    /*Ogg stream is finished so verify stream's MD5 sum*/
    audiotools__MD5Final(stream_md5sum, &md5);

    if (!((memcmp(streaminfo.md5sum, blank_md5sum, 16) == 0) ||
          (memcmp(stream_md5sum, streaminfo.md5sum, 16) == 0))) {
        fprintf(stderr, "*** MD5 mismatch at end of stream\n");
        goto error;
    }

    /*close streams, temporary buffers*/
    oggreader_close(ogg_stream);
    packet->close(packet);
    subframe_data->del(subframe_data);
    residuals->del(residuals);
    qlp_coeffs->del(qlp_coeffs);
    framelist_data->del(framelist_data);
    free(output_data);

    return 0;

error:
    oggreader_close(ogg_stream);
    packet->close(packet);
    subframe_data->del(subframe_data);
    residuals->del(residuals);
    qlp_coeffs->del(qlp_coeffs);
    framelist_data->del(framelist_data);
    free(output_data);

    return 1;
}
Exemplo n.º 7
0
PyObject*
verifymodule_ogg(PyObject *dummy, PyObject *args) {
    PyObject *file_obj;
    BitstreamReader *bitstream;
    int has_previous_header = 0;
    struct ogg_header previous_header;
    struct ogg_header header;
    uint8_t *data_buffer = NULL;
    int data_buffer_size = 0;
    int i;
    uint32_t checksum;

    /*fixes a "may be used unitialized" warning*/
    previous_header.bitstream_serial_number =
        previous_header.page_sequence_number = 0;

    if (!PyArg_ParseTuple(args, "O", &file_obj))
        return NULL;

    if (!PyFile_CheckExact(file_obj)) {
        PyErr_SetString(PyExc_TypeError,
                        "first argument must be an actual file object");
        return NULL;
    } else {
        bitstream = br_open(PyFile_AsFile(file_obj), BS_LITTLE_ENDIAN);
        br_add_callback(bitstream, ogg_crc, &checksum);
    }

    if (!setjmp(*br_try(bitstream))) {
        do {
            checksum = 0;
            if (verifymodule_read_ogg_header(bitstream, &header) == OK) {
                if (data_buffer_size < header.segment_length_total) {
                    data_buffer = realloc(data_buffer,
                                          header.segment_length_total);
                    data_buffer_size = header.segment_length_total;
                }
                if (fread(data_buffer,
                          sizeof(uint8_t),
                          header.segment_length_total,
                          bitstream->input.file) !=
                    header.segment_length_total) {
                    PyErr_SetString(PyExc_IOError, "I/O error reading stream");
                    goto error;
                }

                for (i = 0; i < header.segment_length_total; i++)
                    ogg_crc(data_buffer[i], &checksum);
                if (header.checksum != checksum) {
                    PyErr_SetString(PyExc_ValueError,
                                    "checksum mismatch in stream");
                    goto error;
                }

                /* printf("calculated checksum : 0x%8.8X\n", checksum); */

                if (has_previous_header) {
                    if (header.bitstream_serial_number !=
                        previous_header.bitstream_serial_number) {
                        PyErr_SetString(PyExc_ValueError,
                                        "differing serial numbers in stream");
                        goto error;
                    }
                    if (header.page_sequence_number !=
                        (previous_header.page_sequence_number + 1)) {
                        PyErr_SetString(PyExc_ValueError,
                                        "page sequence number not incrementing");
                        goto error;
                    }
                    previous_header = header;
                } else {
                    previous_header = header;
                    has_previous_header = 1;
                }
            } else {
                goto error;
            }
        } while (!(header.type & 0x4));
    } else {
        PyErr_SetString(PyExc_IOError, "I/O error reading stream");
        goto error;
    }

    br_etry(bitstream);
    free(data_buffer);
    bitstream->input.file = NULL;
    bitstream->free(bitstream);
    Py_INCREF(Py_None);
    return Py_None;
 error:
    br_etry(bitstream);
    if (data_buffer != NULL)
        free(data_buffer);
    bitstream->input.file = NULL;
    bitstream->free(bitstream);
    return NULL;
}