Beispiel #1
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;
}
Beispiel #2
0
int pcmreader_read(struct pcmreader_s* reader,
                   unsigned pcm_frames,
                   array_ia* channels)
{
    unsigned bytes_to_read = (pcm_frames *
                              reader->channels *
                              reader->bytes_per_sample);
    size_t bytes_read;
    unsigned frames_read;

    array_i* channel_a;
    unsigned int byte;
    unsigned int sample;
    unsigned int channel;
    unsigned int frame;

    struct pcmreader_callback *callback;
    FrameList_int_to_char_converter callback_converter;

    uint8_t* callback_buffer;

    if (reader->buffer_size < bytes_to_read) {
        reader->buffer_size = bytes_to_read;
        reader->buffer = realloc(reader->buffer, bytes_to_read);
    }

    /*read data into "buffer" as plain bytes*/
    bytes_read = fread(reader->buffer, sizeof(uint8_t), bytes_to_read,
                       reader->file);

    /*remove partial PCM frames, if any*/
    while (bytes_read % (reader->channels * reader->bytes_per_sample))
        bytes_read--;

    frames_read = (unsigned)(bytes_read /
                             (reader->channels * reader->bytes_per_sample));

    /*place "buffer" into "channels", split up by channel*/
    channels->reset(channels);
    for (channel = 0; channel < reader->channels; channel++) {
        channel_a = channels->append(channels);
        channel_a->resize(channel_a, frames_read);
        for (frame = 0; frame < frames_read; frame++) {
            sample = channel + (frame * reader->channels);
            a_append(channel_a,
                     reader->buffer_converter(reader->buffer +
                                              (sample *
                                               reader->bytes_per_sample)));
        }
    }

    /*apply all callbacks on that collection of samples*/
    for (callback = reader->callbacks;
         callback != NULL;
         callback = callback->next) {
        callback_converter =
            FrameList_get_int_to_char_converter(reader->bits_per_sample,
                                                !callback->little_endian,
                                                callback->is_signed);

        callback_buffer = malloc(bytes_read);

        for (byte = 0; byte < bytes_read; byte += reader->bytes_per_sample) {
            callback_converter(reader->buffer_converter(reader->buffer + byte),
                               callback_buffer + byte);
        }

        callback->callback(callback->user_data,
                           (unsigned char*)callback_buffer,
                           (unsigned long)bytes_read);

        free(callback_buffer);
    }

    return 0;
}
Beispiel #3
0
int main(int argc, char* argv[]) {
    decoders_DVDA_Title title;
    char* audio_ts;
    unsigned titleset;
    unsigned start_sector;
    unsigned end_sector;
    unsigned pts_ticks;

    DVDA_Packet next_packet;
    struct bs_buffer* packet_data;
    mlp_status mlp_status;

    unsigned output_data_size = 1;
    uint8_t* output_data;

    unsigned bytes_per_sample;
    FrameList_int_to_char_converter converter;

    if (argc < 6) {
        fprintf(stderr, "*** Usage: %s <AUDIO_TS> <titleset> "
                "<start sector> <end sector> <PTS ticks>\n", argv[0]);
        return 1;
    } else {
        audio_ts = argv[1];
        titleset = strtoul(argv[2], NULL, 10);
        start_sector = strtoul(argv[3], NULL, 10);
        end_sector = strtoul(argv[4], NULL, 10);
        pts_ticks = strtoul(argv[5], NULL, 10);
    }

    if (DVDA_Title_init(&title, audio_ts, titleset,
                        start_sector, end_sector)) {
        fprintf(stderr, "*** Error: unable to initialize DVDA title\n");
        return 1;
    } else {
        packet_data = title.packet_data;
        output_data = malloc(output_data_size);
    }

    if (!DVDA_Title_next_track(&title, pts_ticks)) {
        fprintf(stderr, "*** Error getting next track\n");
        goto error;
    } else {
        bytes_per_sample = title.bits_per_sample / 8;
        converter = FrameList_get_int_to_char_converter(
            title.bits_per_sample, 0, 1);
    }

    fprintf(stderr, "frames remaining: %u\n", title.pcm_frames_remaining);

    while (title.pcm_frames_remaining) {
        unsigned pcm_size;
        unsigned channel;
        unsigned frame;

        /*build FrameList from PCM or MLP packet data*/
        switch (title.frame_codec) {
        case PCM:
            /*if not enough bytes in buffer, read another packet*/
            while (aobpcm_packet_empty(&(title.pcm_decoder), title.frames)) {
                if (read_audio_packet(title.packet_reader,
                                      &next_packet, packet_data)) {
                    fprintf(stderr, "I/O Error reading PCM packet\n");
                    goto error;
                }

                /*FIXME - ensure packet has same format as PCM*/

                buf_extend(packet_data, title.frames);
            }

            /*FIXME - make this thread friendly*/
            read_aobpcm(&(title.pcm_decoder),
                        title.frames,
                        title.codec_framelist);
            break;
        case MLP:
            /*if not enough bytes in buffer, read another packet*/
            while (mlp_packet_empty(title.mlp_decoder)) {
                if (read_audio_packet(title.packet_reader,
                                      &next_packet, packet_data)) {
                    fprintf(stderr, "I/O Error reading MLP packet\n");
                    goto error;
                }

                /*FIXME - ensure packet has same format as MLP*/

                buf_extend(packet_data, title.frames);
            }

            /*FIXME - make this thread friendly*/
            if ((mlp_status = read_mlp_frames(title.mlp_decoder,
                                              title.codec_framelist)) != OK) {
                fprintf(stderr, "*** MLP Error: %s\n",
                        mlp_python_exception_msg(mlp_status));
                goto error;
            }
        }

        /*account for framelists larger than frames remaining*/
        title.codec_framelist->cross_split(
            title.codec_framelist,
            MIN(title.pcm_frames_remaining, title.codec_framelist->_[0]->len),
            title.output_framelist,
            title.codec_framelist);

        /*deduct output FrameList's PCM frames from remaining count*/
        title.pcm_frames_remaining -= title.output_framelist->_[0]->len;

        /*convert framelist data to string*/
        pcm_size = (bytes_per_sample *
                    title.output_framelist->len *
                    title.output_framelist->_[0]->len);

        if (pcm_size > output_data_size) {
            output_data_size = pcm_size;
            output_data = realloc(output_data, output_data_size);
        }
        for (channel = 0; channel < title.output_framelist->len; channel++) {
            const a_int* channel_data = title.output_framelist->_[channel];
            for (frame = 0; frame < channel_data->len; frame++) {
                converter(channel_data->_[frame],
                          output_data +
                          ((frame * title.output_framelist->len) + channel) *
                          bytes_per_sample);
            }
        }

        /*output framelist data to stdout*/
        fwrite(output_data, sizeof(unsigned char), pcm_size, stdout);
    }


    DVDA_Title_dealloc(&title);
    free(output_data);

    return 0;

error:
    DVDA_Title_dealloc(&title);
    free(output_data);

    return 0;
}