int OpusDecoder_init(decoders_OpusDecoder *self, PyObject *args, PyObject *kwds) { char *filename; int error; self->opus_file = NULL; self->audiotools_pcm = NULL; self->channels = NULL; self->closed = 0; if (!PyArg_ParseTuple(args, "s", &filename)) return -1; if ((self->opus_file = op_open_file(filename, &error)) == NULL) { PyErr_SetString(PyExc_ValueError, "error opening Opus file"); return -1; } self->channel_count = op_channel_count(self->opus_file, -1); if ((self->audiotools_pcm = open_audiotools_pcm()) == NULL) return -1; self->channels = aa_int_new(); return 0; }
int FlacDecoder_init(decoders_FlacDecoder *self, PyObject *args, PyObject *kwds) { self->file = NULL; self->bitstream = NULL; self->seektable = a_obj_new((ARRAY_COPY_FUNC)seekpoint_copy, free, 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->remaining_samples = 0; if (!PyArg_ParseTuple(args, "O", &self->file)) { return -1; } else { Py_INCREF(self->file); } /*open BitstreamReader from FLAC file stream based on whether it's a low-level file object*/ if (PyFile_Check(self->file)) { /*open bitstream through file object*/ self->bitstream = br_open(PyFile_AsFile(self->file), BS_BIG_ENDIAN); } else { /*treat file as Python-implemented file-like object*/ self->bitstream = br_open_external( self->file, BS_BIG_ENDIAN, 4096, (ext_read_f)br_read_python, (ext_close_f)bs_close_python, (ext_free_f)bs_free_python_nodecref); } /*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->channel_mask))) { self->streaminfo.channels = 0; return -1; } if (PyFile_Check(self->file)) { /*place mark at beginning of stream but after metadata in case seeking is needed*/ self->bitstream->mark(self->bitstream); } 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; /*mark stream as not closed and ready for reading*/ self->closed = 0; return 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; }
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; }
int DVDA_Title_init(decoders_DVDA_Title *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"audio_ts", "titleset", "start_sector", "end_sector", "cdrom", NULL}; char* audio_ts; unsigned titleset; unsigned start_sector; unsigned end_sector; #else int DVDA_Title_init(decoders_DVDA_Title *self, char* audio_ts, unsigned titleset, unsigned start_sector, unsigned end_sector) { #endif char* cdrom = NULL; self->sector_reader = NULL; self->packet_reader = NULL; self->packet_data = buf_new(); self->frames = buf_new(); self->pcm_frames_remaining = 0; self->bits_per_sample = 0; self->sample_rate = 0; self->channel_count = 0; self->channel_mask = 0; self->mlp_decoder = open_mlp_decoder(self->frames); self->codec_framelist = aa_int_new(); self->output_framelist = aa_int_new(); #ifndef STANDALONE if ((self->audiotools_pcm = open_audiotools_pcm()) == NULL) return -1; if (!PyArg_ParseTupleAndKeywords(args, kwds, "sIII|s", kwlist, &audio_ts, &titleset, &start_sector, &end_sector, &cdrom)) return -1; #endif /*setup a sector reader according to AUDIO_TS and cdrom device*/ if ((self->sector_reader = open_sector_reader(audio_ts, titleset, cdrom)) == NULL) { #ifndef STANDALONE PyErr_SetFromErrnoWithFilename(PyExc_IOError, audio_ts); #endif return -1; } /*setup a packet reader according to start and end sector this packet reader will be shared by all returned DVDA_Tracks*/ self->packet_reader = open_packet_reader(self->sector_reader, start_sector, end_sector); return 0; }
static result_t encode_opus_file(char *filename, pcmreader *pcmreader, int quality, unsigned original_sample_rate) { const int multichannel = (pcmreader->channels > 2); const unsigned channel_mapping = (pcmreader->channels > 8 ? 255 : pcmreader->channels > 2); int stream_count; int coupled_stream_count; unsigned char stream_map[255]; result_t result = ENCODE_OK; FILE *output_file = NULL; ogg_stream_state ogg_stream; ogg_page ogg_page; OpusEncoder *opus_encoder = NULL; OpusMSEncoder *opus_ms_encoder = NULL; int error; aa_int *samples = NULL; opus_int16 *opus_samples = NULL; unsigned char opus_frame[OPUS_FRAME_LEN]; ogg_int64_t granulepos = 0; ogg_int64_t packetno = 0; opus_int32 preskip; /*open output file for writing*/ if ((output_file = fopen(filename, "w+b")) == NULL) { return ERR_IOERROR; } if (!multichannel) { if ((opus_encoder = opus_encoder_create(48000, pcmreader->channels, OPUS_APPLICATION_AUDIO, &error)) == NULL) { fclose(output_file); return ERR_ENCODER_INIT; } opus_encoder_ctl(opus_encoder, OPUS_SET_COMPLEXITY(quality)); opus_encoder_ctl(opus_encoder, OPUS_GET_LOOKAHEAD(&preskip)); } else { if ((opus_ms_encoder = opus_multistream_surround_encoder_create( 48000, pcmreader->channels, channel_mapping, &stream_count, &coupled_stream_count, stream_map, OPUS_APPLICATION_AUDIO, &error)) == NULL) { fclose(output_file); return ERR_ENCODER_INIT; } opus_multistream_encoder_ctl(opus_ms_encoder, OPUS_SET_COMPLEXITY(quality)); opus_multistream_encoder_ctl(opus_ms_encoder, OPUS_GET_LOOKAHEAD(&preskip)); } srand((unsigned)time(NULL)); ogg_stream_init(&ogg_stream, rand()); /*write header and comment packets to Ogg stream*/ { BitstreamWriter *header = bw_open_recorder(BS_LITTLE_ENDIAN); BitstreamWriter *comment = bw_open_recorder(BS_LITTLE_ENDIAN); int i; /*write header packet to Ogg stream*/ const char opushead[] = "OpusHead"; const char opuscomment[] = "OpusTags"; const char *vendor_string = opus_get_version_string(); const size_t vendor_string_len = strlen(vendor_string); ogg_packet packet_head; ogg_packet packet_tags; header->write_bytes(header, (uint8_t*)opushead, (unsigned)strlen(opushead)); header->write(header, 8, 1); /*version*/ header->write(header, 8, pcmreader->channels); header->write(header, 16, preskip); header->write(header, 32, original_sample_rate); header->write(header, 16, 0); /*output gain*/ header->write(header, 8, channel_mapping); if (channel_mapping != 0) { header->write(header, 8, stream_count); header->write(header, 8, coupled_stream_count); for (i = 0; i < pcmreader->channels; i++) { header->write(header, 8, stream_map[i]); } } packet_head.packet = BUF_WINDOW_START(header->output.buffer); packet_head.bytes = BUF_WINDOW_SIZE(header->output.buffer); packet_head.b_o_s = 1; packet_head.e_o_s = 0; packet_head.granulepos = 0; packet_head.packetno = packetno++; ogg_stream_packetin(&ogg_stream, &packet_head); for (i = ogg_stream_flush(&ogg_stream, &ogg_page); i != 0; i = ogg_stream_flush(&ogg_stream, &ogg_page)) { fwrite(ogg_page.header, 1, ogg_page.header_len, output_file); fwrite(ogg_page.body, 1, ogg_page.body_len, output_file); } /*write comment packet to Ogg stream*/ comment->write_bytes(comment, (uint8_t*)opuscomment, (unsigned)strlen(opuscomment)); comment->write(comment, 32, (unsigned)vendor_string_len); comment->write_bytes(comment, (uint8_t*)vendor_string, (unsigned)vendor_string_len); comment->write(comment, 32, 0); packet_tags.packet = BUF_WINDOW_START(comment->output.buffer); packet_tags.bytes = BUF_WINDOW_SIZE(comment->output.buffer); packet_tags.b_o_s = 0; packet_tags.e_o_s = 0; packet_tags.granulepos = 0; packet_tags.packetno = packetno++; ogg_stream_packetin(&ogg_stream, &packet_tags); for (i = ogg_stream_flush(&ogg_stream, &ogg_page); i != 0; i = ogg_stream_flush(&ogg_stream, &ogg_page)) { fwrite(ogg_page.header, 1, ogg_page.header_len, output_file); fwrite(ogg_page.body, 1, ogg_page.body_len, output_file); } header->close(header); comment->close(comment); } samples = aa_int_new(); opus_samples = malloc(sizeof(opus_int16) * pcmreader->channels * BLOCK_SIZE); /*for each non-empty FrameList from PCMReader, encode Opus frame*/ if (pcmreader->read(pcmreader, BLOCK_SIZE, samples)) { result = ERR_PCMREADER; goto cleanup; } else if (samples->_[0]->len > BLOCK_SIZE) { result = ERR_BLOCK_SIZE; goto cleanup; } while (samples->_[0]->len > 0) { const int short_framelist = (samples->_[0]->len < BLOCK_SIZE); unsigned c; opus_int32 encoded_size; ogg_packet packet; granulepos += samples->_[0]->len; /*pad FrameList with additional null samples if necessary*/ for (c = 0; c < samples->len; c++) { a_int *channel = samples->_[c]; channel->mappend(channel, BLOCK_SIZE - samples->_[0]->len, 0); } /*rearrange channels to Vorbis order if necessary*/ reorder_channels(pcmreader->channel_mask, samples); /*place samples in interleaved buffer*/ for (c = 0; c < samples->len; c++) { unsigned i; a_int *channel = samples->_[c]; for (i = 0; i < channel->len; i++) { opus_samples[c + (i * samples->len)] = (opus_int16)channel->_[i]; } } /*call opus_encode on interleaved buffer to get next packet*/ if (!multichannel) { encoded_size = opus_encode(opus_encoder, opus_samples, samples->_[0]->len, opus_frame, OPUS_FRAME_LEN); } else { encoded_size = opus_multistream_encode(opus_ms_encoder, opus_samples, samples->_[0]->len, opus_frame, OPUS_FRAME_LEN); } /*get next FrameList to encode*/ if (pcmreader->read(pcmreader, BLOCK_SIZE, samples)) { result = ERR_PCMREADER; goto cleanup; } else if (samples->_[0]->len > BLOCK_SIZE) { result = ERR_BLOCK_SIZE; goto cleanup; } /*dump Opus packet to Ogg stream*/ /*do this *after* reading the next FrameList in order to detect the end of stream properly based on whether the FrameList has no frames*/ packet.packet = (unsigned char *)opus_frame; packet.bytes = encoded_size; packet.b_o_s = 0; packet.e_o_s = (short_framelist || (samples->_[0]->len == 0)); packet.granulepos = granulepos; packet.packetno = packetno; ogg_stream_packetin(&ogg_stream, &packet); while (ogg_stream_pageout(&ogg_stream, &ogg_page)) { fwrite(ogg_page.header, 1, ogg_page.header_len, output_file); fwrite(ogg_page.body, 1, ogg_page.body_len, output_file); } } /*flush any remaining Ogg pages to disk*/ while (ogg_stream_flush(&ogg_stream, &ogg_page)) { fwrite(ogg_page.header, 1, ogg_page.header_len, output_file); fwrite(ogg_page.body, 1, ogg_page.body_len, output_file); } cleanup: fclose(output_file); ogg_stream_clear(&ogg_stream); if (!multichannel) { opus_encoder_destroy(opus_encoder); } else { opus_multistream_encoder_destroy(opus_ms_encoder); } samples->del(samples); free(opus_samples); return result; }