Example #1
0
int
ALACDecoder_init(decoders_ALACDecoder *self,
                 PyObject *args, PyObject *kwds)
{
    char *filename;
    static char *kwlist[] = {"filename", NULL};
    unsigned i;

    self->filename = NULL;
    self->file = NULL;
    self->bitstream = NULL;
    self->audiotools_pcm = NULL;

    self->frameset_channels = array_ia_new();
    self->frame_channels = array_ia_new();
    self->uncompressed_LSBs = array_i_new();
    self->residuals = array_i_new();

    for (i = 0; i < MAX_CHANNELS; i++) {
        self->subframe_headers[i].qlp_coeff = array_i_new();
    }

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &filename))
        return -1;

    /*open the alac file as a BitstreamReader*/
    if ((self->file = fopen(filename, "rb")) == NULL) {
        PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
        return -1;
    } else {
        self->bitstream = br_open(self->file, BS_BIG_ENDIAN);
    }
    self->filename = strdup(filename);

    self->bitstream->mark(self->bitstream);

    if (parse_decoding_parameters(self)) {
        self->bitstream->unmark(self->bitstream);
        return -1;
    } else {
        self->bitstream->rewind(self->bitstream);
    }

    /*seek to the 'mdat' atom, which contains the ALAC stream*/
    if (seek_mdat(self->bitstream) == ERROR) {
        self->bitstream->unmark(self->bitstream);
        PyErr_SetString(PyExc_ValueError,
                        "Unable to locate 'mdat' atom in stream");
        return -1;
    } else {
        self->bitstream->unmark(self->bitstream);
    }

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

    return 0;
}
Example #2
0
int
ReplayGainReader_init(replaygain_ReplayGainReader *self,
                      PyObject *args, PyObject *kwds) {
    self->pcmreader = NULL;
    self->channels = array_ia_new();
    self->white_noise = NULL;
    self->audiotools_pcm = NULL;

    double replaygain;
    double peak;

    if (!PyArg_ParseTuple(args, "O&dd",
                          pcmreader_converter, &(self->pcmreader),
                          &(replaygain),
                          &(peak)))
        return -1;

    if ((self->white_noise = open_dither()) == NULL)
        return -1;

    if ((self->audiotools_pcm = open_audiotools_pcm()) == NULL)
        return -1;

    self->multiplier = powl(10.0l, replaygain / 20.0l);
    if (self->multiplier > 1.0l)
        self->multiplier = 1.0l / peak;

    return 0;
}
Example #3
0
void
ReplayGainReader_dealloc(replaygain_ReplayGainReader* self) {
    if (self->pcmreader != NULL)
        self->pcmreader->del(self->pcmreader);
    self->channels = array_ia_new();
    if (self->white_noise != NULL)
        self->white_noise->close(self->white_noise);
    Py_XDECREF(self->audiotools_pcm);

    self->ob_type->tp_free((PyObject*)self);
}
Example #4
0
int
FlacDecoder_init(decoders_FlacDecoder *self,
                 PyObject *args, PyObject *kwds)
{
    char* filename;
    int stream_offset = 0;

    self->filename = NULL;
    self->file = NULL;
    self->bitstream = NULL;

    self->seektable = array_o_new((ARRAY_COPY_FUNC)seekpoint_copy,
                                  free,
                                  NULL);

    self->subframe_data = array_ia_new();
    self->residuals = array_i_new();
    self->qlp_coeffs = array_i_new();
    self->framelist_data = array_i_new();
    self->audiotools_pcm = NULL;
    self->remaining_samples = 0;

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

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

    /*open the flac file*/
    self->file = fopen(filename, "rb");
    if (self->file == NULL) {
        PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
        return -1;
    } else {
        self->bitstream = br_open(self->file, BS_BIG_ENDIAN);
    }

    /*skip the given number of bytes, if any*/
    if (stream_offset != 0)
        fseek(self->file, stream_offset, SEEK_SET);

    self->filename = strdup(filename);

    /*read the STREAMINFO block, SEEKTABLE block
      and setup the total number of samples to read*/
    if (flacdec_read_metadata(self->bitstream,
                              &(self->streaminfo),
                              self->seektable)) {
        self->streaminfo.channels = 0;
        return -1;
    }

    self->remaining_samples = self->streaminfo.total_samples;

    /*initialize the output MD5 sum*/
    audiotools__MD5Init(&(self->md5));
    self->perform_validation = 1;
    self->stream_finalized = 0;

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

    /*place mark at beginning of stream in case seeking is needed*/
    self->bitstream->mark(self->bitstream);

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

    return 0;
}
Example #5
0
static void
alac_order_to_wave_order(array_ia* alac_ordered)
{
    array_ia* wave_ordered = array_ia_new();
    array_i* wave_ch;
    unsigned i;
    wave_ordered->resize(wave_ordered, alac_ordered->len);

    switch (alac_ordered->len) {
    case 2:
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[0]); /*left*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[1]); /*right*/
        break;
    case 1:
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[0]); /*center*/
        break;
    case 3:
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[1]); /*left*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[2]); /*right*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[0]); /*center*/
        break;
    case 4:
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[1]); /*left*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[2]); /*right*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[0]); /*center*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[3]); /*back center*/
        break;
    case 5:
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[1]); /*left*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[2]); /*right*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[0]); /*center*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[3]); /*back left*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[4]); /*back right*/
        break;
    case 6:
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[1]); /*left*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[2]); /*right*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[0]); /*center*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[5]); /*LFE*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[3]); /*back left*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[4]); /*back right*/
        break;
    case 7:
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[1]); /*left*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[2]); /*right*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[0]); /*center*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[6]); /*LFE*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[3]); /*back left*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[4]); /*back right*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[5]); /*back center*/
        break;
    case 8:
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[3]); /*left*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[4]); /*right*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[0]); /*center*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[7]); /*LFE*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[5]); /*back left*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[6]); /*back right*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[1]); /*left of center*/
        wave_ch = wave_ordered->append(wave_ordered);
        wave_ch->swap(wave_ch, alac_ordered->_[2]); /*right of center*/
        break;
    default:
        for (i = 0; i < alac_ordered->len; i++) {
            wave_ch = wave_ordered->append(wave_ordered);
            wave_ch->swap(wave_ch, alac_ordered->_[i]);
        }
        break;
    }

    wave_ordered->swap(wave_ordered, alac_ordered);
    wave_ordered->del(wave_ordered);
}
Example #6
0
PyObject*
ReplayGain_title_gain(replaygain_ReplayGain *self, PyObject *args)
{
    double title_gain;
    double title_peak = 0.0;
    pcmreader* pcmreader = NULL;

    /*read PCMReader-compatible object from args*/
    if (!PyArg_ParseTuple(args, "O&", pcmreader_converter, &pcmreader)) {
        return NULL;
    } else {
        array_ia* channels = array_ia_new();
        array_fa* channels_f = array_fa_new();
        const int32_t peak_shift = 1 << (pcmreader->bits_per_sample - 1);

        if (pcmreader->sample_rate != self->sample_rate) {
            PyErr_SetString(PyExc_ValueError,
                            "pcmreader's sample rate doesn't match");
            pcmreader->del(pcmreader);
            channels->del(channels);
            channels_f->del(channels_f);
            return NULL;
        }

        /*read a FrameList object from PCMReader*/
        if (pcmreader->read(pcmreader, 4096, channels)) {
            pcmreader->del(pcmreader);
            channels->del(channels);
            channels_f->del(channels_f);
            return NULL;
        }

        /*while FrameList contains more samples*/
        while (channels->_[0]->len) {
            unsigned c;

            /*ensure FrameList only contains 1 or 2 channels*/
            if ((channels->len != 1) && (channels->len != 2)) {
                PyErr_SetString(PyExc_ValueError,
                                "FrameList must contain only 1 or 2 channels");
                pcmreader->del(pcmreader);
                channels->del(channels);
                channels_f->del(channels_f);
                return NULL;
            }

            /*if only one channel, duplicate it to the other channel*/
            channels->_[0]->copy(channels->_[0], channels->append(channels));
            channels_f->reset(channels_f);

            /*convert left and right channels to doubles,
              (but *not* doubles between -1.0 and 1.0)
              and store peak values*/
            for (c = 0; c < 2; c++) {
                array_i* channel_i = channels->_[c];
                array_f* channel_f = channels_f->append(channels_f);
                int i;
                double peak;

                channel_f->resize(channel_f, channel_i->len);

                switch (pcmreader->bits_per_sample) {
                case 8:
                    for (i = 0; i < channel_i->len; i++) {
                        a_append(channel_f, (double)(channel_i->_[i] << 8));

                        peak = ((double)(abs(channel_i->_[i])) / peak_shift);
                        title_peak = MAX(title_peak, peak);
                        self->album_peak = MAX(self->album_peak, peak);
                    }
                    break;
                case 16:
                    for (i = 0; i < channel_i->len; i++) {
                        a_append(channel_f, (double)(channel_i->_[i]));

                        peak = ((double)(abs(channel_i->_[i])) / peak_shift);
                        title_peak = MAX(title_peak, peak);
                        self->album_peak = MAX(self->album_peak, peak);
                    }
                    break;
                case 24:
                    for (i = 0; i < channel_i->len; i++) {
                        a_append(channel_f, (double)(channel_i->_[i] >> 8));

                        peak = ((double)(abs(channel_i->_[i])) / peak_shift);
                        title_peak = MAX(title_peak, peak);
                        self->album_peak = MAX(self->album_peak, peak);
                    }
                    break;
                default:
                    PyErr_SetString(PyExc_ValueError,
                                    "unsupported bits per sample");
                    pcmreader->del(pcmreader);
                    channels->del(channels);
                    channels_f->del(channels_f);
                    return NULL;
                }
            }

            /*perform actual gain analysis on channels*/
            if (ReplayGain_analyze_samples(self,
                                           channels_f->_[0]->_,
                                           channels_f->_[1]->_,
                                           channels_f->_[0]->len,
                                           2) == GAIN_ANALYSIS_ERROR) {
                PyErr_SetString(PyExc_ValueError,
                                "ReplayGain calculation error");
                pcmreader->del(pcmreader);
                channels->del(channels);
                channels_f->del(channels_f);
                return NULL;
            }

            /*read next FrameList object from PCMReader*/
            if (pcmreader->read(pcmreader, 4096, channels)) {
                pcmreader->del(pcmreader);
                channels->del(channels);
                channels_f->del(channels_f);
                return NULL;
            }
        }

        /*deallocate temporary variables*/
        pcmreader->del(pcmreader);
        channels->del(channels);
        channels_f->del(channels_f);

        /*return calculated title gain and title peak*/
        /*if enough samples have been read*/
        if ((title_gain = ReplayGain_get_title_gain(self)) !=
            GAIN_NOT_ENOUGH_SAMPLES) {
            return Py_BuildValue("(d,d)", title_gain, title_peak);
        } else {
            PyErr_SetString(PyExc_ValueError,
                            "Not enough samples to perform calculation");
            return NULL;
        }
    }
}
PyObject*
encoders_encode_alac(PyObject *dummy, PyObject *args, PyObject *keywds)
{

    static char *kwlist[] = {"file",
                             "pcmreader",
                             "block_size",
                             "initial_history",
                             "history_multiplier",
                             "maximum_k",
                             "minimum_interlacing_leftweight",
                             "maximum_interlacing_leftweight",
                             NULL};

    PyObject *file_obj;
    FILE *output_file;
    BitstreamWriter *output = NULL;
    PyObject *pcmreader_obj;
    pcmreader* pcmreader;
    struct alac_context encoder;
    array_ia* channels = array_ia_new();
    unsigned frame_file_offset;

    PyObject *log_output;

    alacenc_init_encoder(&encoder);

    encoder.options.minimum_interlacing_leftweight = 0;
    encoder.options.maximum_interlacing_leftweight = 4;

    /*extract a file object, PCMReader-compatible object and encoding options*/
    if (!PyArg_ParseTupleAndKeywords(
                    args, keywds, "OOiiii|ii",
                    kwlist,
                    &file_obj,
                    &pcmreader_obj,
                    &(encoder.options.block_size),
                    &(encoder.options.initial_history),
                    &(encoder.options.history_multiplier),
                    &(encoder.options.maximum_k),
                    &(encoder.options.minimum_interlacing_leftweight),
                    &(encoder.options.maximum_interlacing_leftweight)))
        return NULL;

    /*transform the Python PCMReader-compatible object to a pcm_reader struct*/
    if ((pcmreader = open_pcmreader(pcmreader_obj)) == NULL) {
        return NULL;
    }

    encoder.bits_per_sample = pcmreader->bits_per_sample;

    /*determine if the PCMReader is compatible with ALAC*/
    if ((pcmreader->bits_per_sample != 16) &&
        (pcmreader->bits_per_sample != 24)) {
        PyErr_SetString(PyExc_ValueError, "bits per sample must be 16 or 24");
        goto error;
    }

    /*convert file object to bitstream writer*/
    if ((output_file = PyFile_AsFile(file_obj)) == NULL) {
        PyErr_SetString(PyExc_TypeError,
                        "file must by a concrete file object");
        goto error;
    } else {
        output = bw_open(output_file, BS_BIG_ENDIAN);
        bw_add_callback(output,
                        alac_byte_counter,
                        &(encoder.mdat_byte_size));
    }

#else

int
ALACEncoder_encode_alac(char *filename,
                        FILE *input,
                        int block_size,
                        int initial_history,
                        int history_multiplier,
                        int maximum_k)
{
    FILE *output_file;
    BitstreamWriter *output = NULL;
    pcmreader *pcmreader;
    struct alac_context encoder;
    array_ia* channels = array_ia_new();
    unsigned frame_file_offset;

    alacenc_init_encoder(&encoder);

    encoder.options.block_size = block_size;
    encoder.options.initial_history = initial_history;
    encoder.options.history_multiplier = history_multiplier;
    encoder.options.maximum_k = maximum_k;
    encoder.options.minimum_interlacing_leftweight = 0;
    encoder.options.maximum_interlacing_leftweight = 4;

    output_file = fopen(filename, "wb");
    /*assume CD quality for now*/
    pcmreader = open_pcmreader(input, 44100, 2, 0x3, 16, 0, 1);

    encoder.bits_per_sample = pcmreader->bits_per_sample;

    /*convert file object to bitstream writer*/
    output = bw_open(output_file, BS_BIG_ENDIAN);
    bw_add_callback(output,
                    alac_byte_counter,
                    &(encoder.mdat_byte_size));
#endif

    /*write placeholder mdat header*/
    output->write(output, 32, 0);
    output->write_bytes(output, (uint8_t*)"mdat", 4);

    /*write frames from pcm_reader until empty*/
    if (pcmreader->read(pcmreader, encoder.options.block_size, channels))
        goto error;
    while (channels->_[0]->size > 0) {
#ifndef STANDALONE
        Py_BEGIN_ALLOW_THREADS
#endif
        /*log the number of PCM frames in each ALAC frameset*/
        encoder.frame_log->_[LOG_SAMPLE_SIZE]->append(
            encoder.frame_log->_[LOG_SAMPLE_SIZE],
            channels->_[0]->size);

        frame_file_offset = encoder.mdat_byte_size;

        /*log each frameset's starting offset in the mdat atom*/
        encoder.frame_log->_[LOG_FILE_OFFSET]->append(
            encoder.frame_log->_[LOG_FILE_OFFSET],
            frame_file_offset);

        alac_write_frameset(output, &encoder, channels);

        /*log each frame's total size in bytes*/
        encoder.frame_log->_[LOG_BYTE_SIZE]->append(
            encoder.frame_log->_[LOG_BYTE_SIZE],
            encoder.mdat_byte_size - frame_file_offset);

#ifndef STANDALONE
        Py_END_ALLOW_THREADS
#endif

        if (pcmreader->read(pcmreader, encoder.options.block_size, channels))
            goto error;
    }

    /*return to header and rewrite it with the actual value*/
    bw_pop_callback(output, NULL);
    fseek(output_file, 0, 0);
    output->write(output, 32, encoder.mdat_byte_size);

    /*close and free allocated files/buffers,
      which varies depending on whether we're running standlone or not*/

#ifndef STANDALONE

    log_output = alac_log_output(&encoder);

    pcmreader->del(pcmreader);
    output->free(output);
    alacenc_free_encoder(&encoder);
    channels->del(channels);

    return log_output;

 error:

    pcmreader->del(pcmreader);
    output->free(output);
    alacenc_free_encoder(&encoder);
    channels->del(channels);

    return NULL;
}
Example #8
0
static int
encode_audio(BitstreamWriter* bs,
             pcmreader* pcmreader,
             int signed_samples,
             unsigned block_size)
{
    unsigned left_shift = 0;
    int sign_adjustment;

    /*allocate some temporary buffers*/
    array_ia* frame = array_ia_new();
    array_ia* wrapped_samples = array_ia_new();
    array_i* shifted = array_i_new();
    array_ia* deltas = array_ia_new();
    array_i* residuals = array_i_new();
    unsigned c;
    unsigned i;

    for (i = 0; i < pcmreader->channels; i++)
        wrapped_samples->append(wrapped_samples);

    if (!signed_samples) {
        sign_adjustment = 1 << (pcmreader->bits_per_sample - 1);
    } else {
        sign_adjustment = 0;
    }

    if (pcmreader->read(pcmreader, block_size, frame))
        goto error;

    while (frame->_[0]->len > 0) {
#ifndef STANDALONE
        Py_BEGIN_ALLOW_THREADS
#endif

        if (frame->_[0]->len != block_size) {
            /*PCM frame count has changed, so issue BLOCKSIZE command*/
            block_size = frame->_[0]->len;
            write_unsigned(bs, COMMAND_SIZE, FN_BLOCKSIZE);
            write_long(bs, block_size);
        }

        for (c = 0; c < frame->len; c++) {
            array_i* channel = frame->_[c];
            array_i* wrapped = wrapped_samples->_[c];

            /*convert signed samples to unsigned, if necessary*/
            if (sign_adjustment != 0)
                for (i = 0; i < channel->len; i++)
                    channel->_[i] += sign_adjustment;

            if (all_zero(channel)) {
                /*write ZERO command and wrap channel for next set*/
                write_unsigned(bs, COMMAND_SIZE, FN_ZERO);
                wrapped->extend(wrapped, channel);
                wrapped->tail(wrapped, SAMPLES_TO_WRAP, wrapped);
            } else {
                unsigned diff = 1;
                unsigned energy = 0;

                unsigned wasted_BPS = wasted_bits(channel);
                if (wasted_BPS != left_shift) {
                    /*issue BITSHIFT comand*/
                    left_shift = wasted_BPS;
                    write_unsigned(bs, COMMAND_SIZE, FN_BITSHIFT);
                    write_unsigned(bs, BITSHIFT_SIZE, left_shift);
                }

                /*apply left shift to channel data*/
                if (left_shift > 0) {
                    shifted->reset_for(shifted, channel->len);
                    for (i = 0; i < channel->len; i++)
                        a_append(shifted, channel->_[i] >> left_shift);
                } else {
                    channel->copy(channel, shifted);
                }

                /*calculate best DIFF, energy and residuals for shifted data*/
                calculate_best_diff(shifted, wrapped, deltas,
                                    &diff, &energy, residuals);

                /*issue DIFF command*/
                write_unsigned(bs, COMMAND_SIZE, diff);
                write_unsigned(bs, ENERGY_SIZE, energy);
                for (i = 0; i < residuals->len; i++)
                    write_signed(bs, energy, residuals->_[i]);

                /*wrap shifted channel data for next set*/
                wrapped->extend(wrapped, shifted);
                wrapped->tail(wrapped, SAMPLES_TO_WRAP, wrapped);
            }
        }
Example #9
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 = array_ia_new();
    self->residuals = array_i_new();
    self->qlp_coeffs = array_i_new();
    self->framelist_data = array_i_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_func)flac_crc16, &(self->crc16));

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

    return 0;
}