add support for writing ogg streams

This commit is contained in:
Josh Coalson 2001-10-31 18:31:36 +00:00
parent 172ac00220
commit f7fc5c89e8
8 changed files with 700 additions and 174 deletions

View File

@ -76,6 +76,9 @@ if test x$sse_os = xtrue ; then
AC_DEFINE(FLAC__SSE_OS)
fi
AM_PATH_OGG( , AC_MSG_WARN([*** Ogg development enviroment not installed - ogg support will not be built]))
AM_CONDITIONAL(FLaC__HAS_OGG, test x$OGG_LIBS != x)
AM_PATH_XMMS(0.9.5.1, , AC_MSG_WARN([*** XMMS >= 0.9.5.1 not installed - xmms support will not be built]))
AM_CONDITIONAL(FLaC__HAS_XMMS, test x$XMMS_INPUT_PLUGIN_DIR != x)

View File

@ -29,5 +29,10 @@ flac_SOURCES = \
encode.h \
file.h
if FLaC__HAS_OGG
flac_LDFLAGS = -lm
else
flac_LDFLAGS = -lm -logg
endif
flac_LDADD = $(top_builddir)/src/libFLAC/libFLAC.la

View File

@ -20,8 +20,10 @@
#
PROGRAM_NAME = flac
INCLUDES = -I./include -I../../include
LIBS = -lFLAC -lm
#@@@OGG
INCLUDES = -I./include -I../../include -I$(HOME)/local/include
#@@@OGG conditionalize -logg
LIBS = -lFLAC -lm -L$(HOME)/local/lib -logg
OBJS = \
analyze.o \

View File

@ -28,9 +28,22 @@
#include "FLAC/all.h"
#include "decode.h"
#include "file.h"
#ifdef FLaC__HAS_OGG
#include "ogg/ogg.h"
#endif
#ifdef FLaC__HAS_OGG
typedef struct {
ogg_sync_state oy;
ogg_stream_state os;
} ogg_info_struct;
#endif
typedef struct {
const char *inbasefilename;
#ifdef FLaC__HAS_OGG
FILE *fin;
#endif
FILE *fout;
FLAC__bool abort_flag;
FLAC__bool analysis_mode;
@ -48,36 +61,57 @@ typedef struct {
FLAC__bool skip_count_too_high;
FLAC__uint64 samples_processed;
unsigned frame_counter;
#ifdef FLaC__HAS_OGG
FLAC__bool is_ogg;
#endif
union {
FLAC__FileDecoder *file;
FLAC__StreamDecoder *stream;
} decoder;
#ifdef FLaC__HAS_OGG
ogg_info_struct ogg;
#endif
} stream_info_struct;
static FLAC__FileDecoder *decoder;
static FLAC__bool is_big_endian_host;
/* local routines */
static FLAC__bool init(const char *infilename, stream_info_struct *stream_info);
static FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val);
static FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val);
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data);
static void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
static void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
#ifdef FLaC__HAS_OGG
static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
#endif
/*
* We use 'void *' so that we can use the same callbacks for the
* FLAC__StreamDecoder and FLAC__FileDecoder. The 'decoder' argument is
* actually never used in the callbacks.
*/
static FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data);
static void metadata_callback(const void *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
static void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
static void print_stats(const stream_info_struct *stream_info);
int flac__decode_wav(const char *infile, const char *outfile, FLAC__bool analysis_mode, analysis_options aopts, FLAC__bool verbose, FLAC__uint64 skip)
int flac__decode_wav(const char *infile, const char *outfile, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options)
{
FLAC__bool md5_failure = false;
stream_info_struct stream_info;
decoder = 0;
stream_info.abort_flag = false;
stream_info.analysis_mode = analysis_mode;
stream_info.aopts = aopts;
stream_info.test_only = (outfile == 0);
stream_info.is_wave_out = true;
stream_info.verbose = verbose;
stream_info.skip = skip;
stream_info.verbose = options.common.verbose;
stream_info.skip = options.common.skip;
stream_info.skip_count_too_high = false;
stream_info.samples_processed = 0;
stream_info.frame_counter = 0;
#ifdef FLaC__HAS_OGG
stream_info.is_ogg = options.common.is_ogg;
#endif
stream_info.decoder.file = 0; /* this zeroes stream_info.decoder.stream also */
stream_info.inbasefilename = flac__file_get_basename(infile);
stream_info.fout = 0; /* initialized with an open file later if necessary */
@ -95,100 +129,179 @@ int flac__decode_wav(const char *infile, const char *outfile, FLAC__bool analysi
}
}
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) {
if (0 == strcmp(infile, "-")) {
stream_info.fin = stdin;
} else {
if (0 == (stream_info.fin = fopen(infile, "rb"))) {
fprintf(stderr, "%s: ERROR: can't open input file %s\n", stream_info.inbasefilename, infile);
if(stream_info.fout != stdout)
fclose(stream_info.fout);
return 1;
}
}
}
#endif
if(analysis_mode)
flac__analyze_init(aopts);
if(!init(infile, &stream_info))
goto wav_abort_;
if(skip > 0) {
if(!FLAC__file_decoder_process_metadata(decoder)) {
fprintf(stderr, "%s: ERROR while decoding metadata, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
if(stream_info.skip > 0) {
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) { //@@@ (move this check into main.c)
fprintf(stderr, "%s: ERROR, can't skip when decoding Ogg-FLAC yet; convert to native-FLAC first\n", stream_info.inbasefilename);
goto wav_abort_;
}
#endif
if(!FLAC__file_decoder_process_metadata(stream_info.decoder.file)) {
fprintf(stderr, "%s: ERROR while decoding metadata, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
goto wav_abort_;
}
if(stream_info.skip_count_too_high) {
fprintf(stderr, "%s: ERROR trying to skip more samples than in stream\n", stream_info.inbasefilename);
goto wav_abort_;
}
if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
fprintf(stderr, "%s: ERROR seeking while skipping bytes, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
if(!FLAC__file_decoder_seek_absolute(stream_info.decoder.file, stream_info.skip)) {
fprintf(stderr, "%s: ERROR seeking while skipping bytes, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
goto wav_abort_;
}
if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
if(verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR while decoding frames, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
if(!FLAC__file_decoder_process_remaining_frames(stream_info.decoder.file)) {
if(stream_info.verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR while decoding frames, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
goto wav_abort_;
}
if(FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_END_OF_FILE) {
if(verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
if(stream_info.verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
goto wav_abort_;
}
}
else {
if(!FLAC__file_decoder_process_whole_file(decoder)) {
if(verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
goto wav_abort_;
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) {
if(!FLAC__stream_decoder_process_whole_stream(stream_info.decoder.stream)) {
if(stream_info.verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__stream_decoder_get_state(stream_info.decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info.decoder.stream)]);
goto wav_abort_;
}
if(FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_END_OF_STREAM) {
if(stream_info.verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__stream_decoder_get_state(stream_info.decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info.decoder.stream)]);
goto wav_abort_;
}
}
if(FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_END_OF_FILE) {
if(verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
goto wav_abort_;
else
#endif
{
if(!FLAC__file_decoder_process_whole_file(stream_info.decoder.file)) {
if(stream_info.verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
goto wav_abort_;
}
if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
if(stream_info.verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
goto wav_abort_;
}
}
}
if(decoder) {
if(FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_UNINITIALIZED)
md5_failure = !FLAC__file_decoder_finish(decoder);
print_stats(&stream_info);
FLAC__file_decoder_delete(decoder);
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) {
if(stream_info.decoder.stream) {
if(FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_UNINITIALIZED)
FLAC__stream_decoder_finish(stream_info.decoder.stream);
md5_failure = false;
print_stats(&stream_info);
FLAC__stream_decoder_delete(stream_info.decoder.stream);
}
}
else
#endif
{
if(stream_info.decoder.file) {
if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_UNINITIALIZED)
md5_failure = !FLAC__file_decoder_finish(stream_info.decoder.file);
print_stats(&stream_info);
FLAC__file_decoder_delete(stream_info.decoder.file);
}
}
if(0 != stream_info.fout && stream_info.fout != stdout)
fclose(stream_info.fout);
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) {
if(0 != stream_info.fin && stream_info.fin != stdin)
fclose(stream_info.fin);
}
#endif
if(analysis_mode)
flac__analyze_finish(aopts);
if(md5_failure) {
fprintf(stderr, "\r%s: WARNING, MD5 signature mismatch\n", stream_info.inbasefilename);
}
else {
if(verbose)
if(stream_info.verbose)
fprintf(stderr, "\r%s: %s \n", stream_info.inbasefilename, stream_info.test_only? "ok ":analysis_mode?"done ":"done");
}
return 0;
wav_abort_:
if(decoder) {
if(FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_UNINITIALIZED)
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) {
if(stream_info.decoder.stream) {
if(FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_UNINITIALIZED)
FLAC__stream_decoder_finish(stream_info.decoder.stream);
FLAC__stream_decoder_delete(stream_info.decoder.stream);
}
}
else
#endif
{
if(stream_info.decoder.file) {
if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_UNINITIALIZED)
FLAC__file_decoder_finish(stream_info.decoder.file);
FLAC__file_decoder_delete(stream_info.decoder.file);
}
}
if(0 != stream_info.fout && stream_info.fout != stdout) {
fclose(stream_info.fout);
unlink(outfile);
}
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) {
if(0 != stream_info.fin && stream_info.fin != stdin)
fclose(stream_info.fin);
}
#endif
if(analysis_mode)
flac__analyze_finish(aopts);
return 1;
}
int flac__decode_raw(const char *infile, const char *outfile, FLAC__bool analysis_mode, analysis_options aopts, FLAC__bool verbose, FLAC__uint64 skip, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples)
int flac__decode_raw(const char *infile, const char *outfile, FLAC__bool analysis_mode, analysis_options aopts, raw_decode_options_t options)
{
FLAC__bool md5_failure = false;
stream_info_struct stream_info;
decoder = 0;
stream_info.abort_flag = false;
stream_info.analysis_mode = analysis_mode;
stream_info.aopts = aopts;
stream_info.test_only = (outfile == 0);
stream_info.is_wave_out = false;
stream_info.is_big_endian = is_big_endian;
stream_info.is_unsigned_samples = is_unsigned_samples;
stream_info.verbose = verbose;
stream_info.skip = skip;
stream_info.is_big_endian = options.is_big_endian;
stream_info.is_unsigned_samples = options.is_unsigned_samples;
stream_info.verbose = options.common.verbose;
stream_info.skip = options.common.skip;
stream_info.skip_count_too_high = false;
stream_info.samples_processed = 0;
stream_info.frame_counter = 0;
#ifdef FLaC__HAS_OGG
stream_info.is_ogg = is_ogg;
#endif
stream_info.decoder.file = 0; /* this zeroes stream_info.decoder.stream also */
stream_info.inbasefilename = flac__file_get_basename(infile);
stream_info.fout = 0; /* initialized with an open file later if necessary */
@ -206,77 +319,153 @@ int flac__decode_raw(const char *infile, const char *outfile, FLAC__bool analysi
}
}
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) {
if (0 == strcmp(infile, "-")) {
stream_info.fin = stdin;
} else {
if (0 == (stream_info.fin = fopen(infile, "rb"))) {
fprintf(stderr, "%s: ERROR: can't open input file %s\n", stream_info.inbasefilename, infile);
if(stream_info.fout != stdout)
fclose(stream_info.fout);
return 1;
}
}
}
#endif
if(analysis_mode)
flac__analyze_init(aopts);
if(!init(infile, &stream_info))
goto raw_abort_;
if(skip > 0) {
if(!FLAC__file_decoder_process_metadata(decoder)) {
fprintf(stderr, "%s: ERROR while decoding metadata, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
if(stream_info.skip > 0) {
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) { //@@@ (move this check into main.c)
fprintf(stderr, "%s: ERROR, can't skip when decoding Ogg-FLAC yet; convert to native-FLAC first\n", stream_info.inbasefilename);
goto raw_abort_;
}
#endif
if(!FLAC__file_decoder_process_metadata(stream_info.decoder.file)) {
fprintf(stderr, "%s: ERROR while decoding metadata, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
goto raw_abort_;
}
if(stream_info.skip_count_too_high) {
fprintf(stderr, "%s: ERROR trying to skip more samples than in stream\n", stream_info.inbasefilename);
goto raw_abort_;
}
if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
fprintf(stderr, "%s: ERROR seeking while skipping bytes, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
if(!FLAC__file_decoder_seek_absolute(stream_info.decoder.file, stream_info.skip)) {
fprintf(stderr, "%s: ERROR seeking while skipping bytes, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
goto raw_abort_;
}
if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
if(verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR while decoding frames, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
if(!FLAC__file_decoder_process_remaining_frames(stream_info.decoder.file)) {
if(stream_info.verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR while decoding frames, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
goto raw_abort_;
}
if(FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_END_OF_FILE) {
if(verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
if(stream_info.verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
goto raw_abort_;
}
}
else {
if(!FLAC__file_decoder_process_whole_file(decoder)) {
if(verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
goto raw_abort_;
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) {
if(!FLAC__stream_decoder_process_whole_stream(stream_info.decoder.stream)) {
if(stream_info.verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__stream_decoder_get_state(stream_info.decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info.decoder.stream)]);
goto raw_abort_;
}
if(FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_END_OF_STREAM) {
if(stream_info.verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__stream_decoder_get_state(stream_info.decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info.decoder.stream)]);
goto raw_abort_;
}
}
if(FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_END_OF_FILE) {
if(verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
goto raw_abort_;
else
#endif
{
if(!FLAC__file_decoder_process_whole_file(stream_info.decoder.file)) {
if(stream_info.verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
goto raw_abort_;
}
if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
if(stream_info.verbose) fprintf(stderr, "\n");
fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
goto raw_abort_;
}
}
}
if(decoder) {
if(FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_UNINITIALIZED)
md5_failure = !FLAC__file_decoder_finish(decoder);
print_stats(&stream_info);
FLAC__file_decoder_delete(decoder);
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) {
if(stream_info.decoder.stream) {
if(FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_UNINITIALIZED)
FLAC__stream_decoder_finish(stream_info.decoder.stream);
md5_failure = false;
print_stats(&stream_info);
FLAC__stream_decoder_delete(stream_info.decoder.stream);
}
}
else
#endif
{
if(stream_info.decoder.file) {
if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_UNINITIALIZED)
md5_failure = !FLAC__file_decoder_finish(stream_info.decoder.file);
print_stats(&stream_info);
FLAC__file_decoder_delete(stream_info.decoder.file);
}
}
if(0 != stream_info.fout && stream_info.fout != stdout)
fclose(stream_info.fout);
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) {
if(0 != stream_info.fin && stream_info.fin != stdin)
fclose(stream_info.fin);
}
#endif
if(analysis_mode)
flac__analyze_finish(aopts);
if(md5_failure) {
fprintf(stderr, "\r%s: WARNING, MD5 signature mismatch\n", stream_info.inbasefilename);
}
else {
if(verbose)
if(stream_info.verbose)
fprintf(stderr, "\r%s: %s \n", stream_info.inbasefilename, stream_info.test_only? "ok ":analysis_mode?"done ":"done");
}
return 0;
raw_abort_:
if(decoder) {
if(FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_UNINITIALIZED)
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_delete(decoder);
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) {
if(stream_info.decoder.stream) {
if(FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_UNINITIALIZED)
FLAC__stream_decoder_finish(stream_info.decoder.stream);
FLAC__stream_decoder_delete(stream_info.decoder.stream);
}
}
else
#endif
{
if(stream_info.decoder.file) {
if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_UNINITIALIZED)
FLAC__file_decoder_finish(stream_info.decoder.file);
FLAC__file_decoder_delete(stream_info.decoder.file);
}
}
if(0 != stream_info.fout && stream_info.fout != stdout) {
fclose(stream_info.fout);
unlink(outfile);
}
#ifdef FLaC__HAS_OGG
if(stream_info.is_ogg) {
if(0 != stream_info.fin && stream_info.fin != stdin)
fclose(stream_info.fin);
}
#endif
if(analysis_mode)
flac__analyze_finish(aopts);
return 1;
@ -288,22 +477,61 @@ FLAC__bool init(const char *infilename, stream_info_struct *stream_info)
is_big_endian_host = (*((FLAC__byte*)(&test)))? false : true;
decoder = FLAC__file_decoder_new();
if(0 == decoder) {
fprintf(stderr, "%s: ERROR creating the decoder instance\n", stream_info->inbasefilename);
return false;
#ifdef FLaC__HAS_OGG
if(stream_info->is_ogg) {
stream_info->decoder.stream = FLAC__stream_decoder_new();
if(0 == stream_info->decoder.stream) {
fprintf(stderr, "%s: ERROR creating the decoder instance\n", stream_info->inbasefilename);
return false;
}
FLAC__stream_decoder_set_read_callback(stream_info->decoder.stream, read_callback);
................................................................................
/*
* The three ugly casts here are to 'downcast' the 'void *' argument of
* the callback down to 'FLAC__StreamDecoder *'. In C++ this would be
* unnecessary but here the cast makes the C compiler happy.
*/
FLAC__stream_decoder_set_write_callback(stream_info->decoder.stream, (FLAC__StreamDecoderWriteStatus (*)(const FLAC__StreamDecoder *, const FLAC__Frame *, const FLAC__int32 *[], void *))write_callback);
FLAC__stream_decoder_set_metadata_callback(stream_info->decoder.stream, (void (*)(const FLAC__StreamDecoder *, const FLAC__StreamMetaData *, void *))metadata_callback);
FLAC__stream_decoder_set_error_callback(stream_info->decoder.stream, (void (*)(const FLAC__StreamDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
FLAC__stream_decoder_set_client_data(stream_info->decoder.stream, stream_info);
if(FLAC__stream_decoder_init(stream_info->decoder.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA) {
fprintf(stderr, "%s: ERROR initializing decoder, state=%d:%s\n", stream_info->inbasefilename, FLAC__stream_decoder_get_state(stream_info->decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info->decoder.stream)]);
return false;
}
ogg_stream_init(&stream_info->ogg.os, 0);
ogg_sync_init(&stream_info->ogg.oy);
}
else
#endif
{
stream_info->decoder.file = FLAC__file_decoder_new();
FLAC__file_decoder_set_md5_checking(decoder, true);
FLAC__file_decoder_set_filename(decoder, infilename);
FLAC__file_decoder_set_write_callback(decoder, write_callback);
FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
FLAC__file_decoder_set_error_callback(decoder, error_callback);
FLAC__file_decoder_set_client_data(decoder, stream_info);
if(0 == stream_info->decoder.file) {
fprintf(stderr, "%s: ERROR creating the decoder instance\n", stream_info->inbasefilename);
return false;
}
if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK) {
fprintf(stderr, "%s: ERROR initializing decoder, state=%d:%s\n", stream_info->inbasefilename, FLAC__file_decoder_get_state(decoder), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
return false;
FLAC__file_decoder_set_md5_checking(stream_info->decoder.file, true);
FLAC__file_decoder_set_filename(stream_info->decoder.file, infilename);
/*
* The three ugly casts here are to 'downcast' the 'void *' argument of
* the callback down to 'FLAC__FileDecoder *'. In C++ this would be
* unnecessary but here the cast makes the C compiler happy.
*/
FLAC__file_decoder_set_write_callback(stream_info->decoder.file, (FLAC__StreamDecoderWriteStatus (*)(const FLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 *[], void *))write_callback);
FLAC__file_decoder_set_metadata_callback(stream_info->decoder.file, (void (*)(const FLAC__FileDecoder *, const FLAC__StreamMetaData *, void *))metadata_callback);
FLAC__file_decoder_set_error_callback(stream_info->decoder.file, (void (*)(const FLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
FLAC__file_decoder_set_client_data(stream_info->decoder.file, stream_info);
if(FLAC__file_decoder_init(stream_info->decoder.file) != FLAC__FILE_DECODER_OK) {
fprintf(stderr, "%s: ERROR initializing decoder, state=%d:%s\n", stream_info->inbasefilename, FLAC__file_decoder_get_state(stream_info->decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info->decoder.file)]);
return false;
}
}
return true;
@ -330,7 +558,56 @@ FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val)
return fwrite(b, 1, 4, f) == 4;
}
FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data)
#ifdef FLaC__HAS_OGG
#define OGG_READ_BUFFER_SIZE 4096
FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
{
stream_info_struct *stream_info = (stream_info_struct *)client_data;
FILE *fin = stream_info->fin;
size_t bytes_read;
ogg_page og;
char *oggbuf;
unsigned int offset = 0;
*bytes = 0;
if (stream_info->abort_flag)
return FLAC__STREAM_DECODER_READ_ABORT;
oggbuf = ogg_sync_buffer(&stream_info->ogg.oy, OGG_READ_BUFFER_SIZE);
(void)decoder; /* avoid compiler warning */
if (feof(fin))
return FLAC__STREAM_DECODER_READ_END_OF_STREAM;
bytes_read = fread(oggbuf, 1, OGG_READ_BUFFER_SIZE, fin);
if (ferror(fin))
return FLAC__STREAM_DECODER_READ_ABORT;
if (ogg_sync_wrote(&stream_info->ogg.oy, bytes_read) < 0)
return FLAC__STREAM_DECODER_READ_ABORT;
while (ogg_sync_pageout(&stream_info->ogg.oy, &og) == 1) {
if (ogg_stream_pagein(&stream_info->ogg.os, &og) == 0) {
ogg_packet op;
while (ogg_stream_packetout(&stream_info->ogg.os, &op) == 1) {
memcpy(buffer + offset, op.packet, op.bytes);
*bytes += op.bytes;
offset += op.bytes;
}
} else {
return FLAC__STREAM_DECODER_READ_ABORT;
}
}
return FLAC__STREAM_DECODER_READ_CONTINUE;
}
#endif
FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data)
{
stream_info_struct *stream_info = (stream_info_struct *)client_data;
FILE *fout = stream_info->fout;
@ -451,7 +728,7 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder,
return FLAC__STREAM_DECODER_WRITE_CONTINUE;
}
void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
void metadata_callback(const void *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
{
stream_info_struct *stream_info = (stream_info_struct *)client_data;
(void)decoder;
@ -497,7 +774,7 @@ void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaD
}
}
void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
{
stream_info_struct *stream_info = (stream_info_struct *)client_data;
(void)decoder;

View File

@ -21,8 +21,27 @@
#include "analyze.h"
typedef struct {
FLAC__bool verbose;
#ifdef FLaC__HAS_OGG
FLAC__bool is_ogg;
#endif
FLAC__uint64 skip;
} decode_options_t;
typedef struct {
decode_options_t common;
} wav_decode_options_t;
typedef struct {
decode_options_t common;
FLAC__bool is_big_endian;
FLAC__bool is_unsigned_samples;
} raw_decode_options_t;
/* outfile == 0 => test only */
int flac__decode_wav(const char *infile, const char *outfile, FLAC__bool analysis_mode, analysis_options aopts, FLAC__bool verbose, FLAC__uint64 skip);
int flac__decode_raw(const char *infile, const char *outfile, FLAC__bool analysis_mode, analysis_options aopts, FLAC__bool verbose, FLAC__uint64 skip, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples);
int flac__decode_wav(const char *infile, const char *outfile, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options);
int flac__decode_raw(const char *infile, const char *outfile, FLAC__bool analysis_mode, analysis_options aopts, raw_decode_options_t options);
#endif

View File

@ -29,6 +29,9 @@
#include "FLAC/all.h"
#include "encode.h"
#include "file.h"
#ifdef FLaC__HAS_OGG
#include "ogg/ogg.h"
#endif
#ifdef min
#undef min
@ -62,6 +65,13 @@ typedef struct {
FLAC__StreamDecoder *decoder;
} verify_fifo_struct;
#ifdef FLaC__HAS_OGG
typedef struct {
ogg_stream_state os;
ogg_page og;
} ogg_info_struct;
#endif
typedef struct {
const char *inbasefilename;
FILE *fout;
@ -78,6 +88,10 @@ typedef struct {
verify_fifo_struct verify_fifo;
FLAC__StreamMetaData_SeekTable seek_table;
unsigned first_seek_point_to_check;
FLAC__bool use_ogg;
#ifdef FLaC__HAS_OGG
ogg_info_struct ogg;
#endif
} encoder_wrapper_struct;
static FLAC__bool is_big_endian_host;
@ -92,7 +106,7 @@ static FLAC__int32 *input[FLAC__MAX_CHANNELS];
/* local routines */
static FLAC__bool init(encoder_wrapper_struct *encoder_wrapper);
static FLAC__bool init_encoder(FLAC__bool lax, FLAC__bool do_mid_side, FLAC__bool loose_mid_side, FLAC__bool do_exhaustive_model_search, FLAC__bool do_escape_coding, FLAC__bool do_qlp_coeff_prec_search, unsigned min_residual_partition_order, unsigned max_residual_partition_order, unsigned rice_parameter_search_dist, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned channels, unsigned bps, unsigned sample_rate, unsigned padding, char *requested_seek_points, int num_requested_seek_points, encoder_wrapper_struct *encoder_wrapper);
static FLAC__bool init_encoder(encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate, encoder_wrapper_struct *encoder_wrapper);
static FLAC__bool convert_to_seek_table(char *requested_seek_points, int num_requested_seek_points, FLAC__uint64 stream_samples, unsigned blocksize, FLAC__StreamMetaData_SeekTable *seek_table);
static void append_point_to_seek_table(FLAC__StreamMetaData_SeekTable *seek_table, FLAC__uint64 sample, FLAC__uint64 stream_samples, FLAC__uint64 blocksize);
static int seekpoint_compare(const FLAC__StreamMetaData_SeekPoint *l, const FLAC__StreamMetaData_SeekPoint *r);
@ -110,7 +124,7 @@ static FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bo
static FLAC__bool write_big_endian_uint16(FILE *f, FLAC__uint16 val);
static FLAC__bool write_big_endian_uint64(FILE *f, FLAC__uint64 val);
int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, FLAC__int32 *align_reservoir[], unsigned *align_reservoir_samples, FLAC__bool sector_align, FLAC__bool is_last_file, FLAC__bool verbose, FLAC__uint64 skip, FLAC__bool verify, FLAC__bool lax, FLAC__bool do_mid_side, FLAC__bool loose_mid_side, FLAC__bool do_exhaustive_model_search, FLAC__bool do_escape_coding, FLAC__bool do_qlp_coeff_prec_search, unsigned min_residual_partition_order, unsigned max_residual_partition_order, unsigned rice_parameter_search_dist, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned padding, char *requested_seek_points, int num_requested_seek_points)
int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options)
{
encoder_wrapper_struct encoder_wrapper;
FLAC__bool is_unsigned_samples = false;
@ -122,11 +136,11 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
unsigned align_remainder = 0;
int info_align_carry = -1, info_align_zero = -1;
FLAC__ASSERT(!sector_align || skip == 0);
FLAC__ASSERT(!options.sector_align || options.common.skip == 0);
encoder_wrapper.encoder = 0;
encoder_wrapper.verify = verify;
encoder_wrapper.verbose = verbose;
encoder_wrapper.verify = options.common.verify;
encoder_wrapper.verbose = options.common.verbose;
encoder_wrapper.bytes_written = 0;
encoder_wrapper.samples_written = 0;
encoder_wrapper.stream_offset = 0;
@ -134,6 +148,9 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
encoder_wrapper.outfilename = outfilename;
encoder_wrapper.seek_table.points = 0;
encoder_wrapper.first_seek_point_to_check = 0;
#ifdef FLaC__HAS_OGG
encoder_wrapper.use_ogg = options.common.use_ogg;
#endif
(void)infilesize;
(void)lookahead;
(void)lookahead_length;
@ -190,7 +207,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
fprintf(stderr, "%s: ERROR: unsupported number channels %u\n", encoder_wrapper.inbasefilename, (unsigned)x);
goto wav_abort_;
}
else if(sector_align && x != 2) {
else if(options.sector_align && x != 2) {
fprintf(stderr, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_wrapper.inbasefilename, (unsigned)x);
goto wav_abort_;
}
@ -202,7 +219,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
fprintf(stderr, "%s: ERROR: unsupported sample rate %u\n", encoder_wrapper.inbasefilename, (unsigned)xx);
goto wav_abort_;
}
else if(sector_align && xx != 44100) {
else if(options.sector_align && xx != 44100) {
fprintf(stderr, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_wrapper.inbasefilename, (unsigned)xx);
goto wav_abort_;
}
@ -256,16 +273,16 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
bytes_per_wide_sample = channels * (bps >> 3);
if(skip > 0) {
if(options.common.skip > 0) {
if(infile != stdin) {
if(-1 == fseek(infile, bytes_per_wide_sample * (unsigned)skip, SEEK_CUR)) {
if(-1 == fseek(infile, bytes_per_wide_sample * (unsigned)options.common.skip, SEEK_CUR)) {
fprintf(stderr, "%s: ERROR during seek while skipping samples\n", encoder_wrapper.inbasefilename);
goto wav_abort_;
}
}
else {
unsigned left, need;
for(left = (unsigned)skip; left > 0; ) { /*@@@ WATCHOUT: 4GB limit */
for(left = (unsigned)options.common.skip; left > 0; ) { /*@@@ WATCHOUT: 4GB limit */
need = min(left, CHUNK_OF_SAMPLES);
if(fread(ucbuffer, bytes_per_wide_sample, need, infile) < need) {
fprintf(stderr, "%s: ERROR during read while skipping samples\n", encoder_wrapper.inbasefilename);
@ -276,11 +293,11 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
}
}
data_bytes -= (unsigned)skip * bytes_per_wide_sample; /*@@@ WATCHOUT: 4GB limit */
encoder_wrapper.total_samples_to_encode = data_bytes / bytes_per_wide_sample + *align_reservoir_samples;
if(sector_align) {
data_bytes -= (unsigned)options.common.skip * bytes_per_wide_sample; /*@@@ WATCHOUT: 4GB limit */
encoder_wrapper.total_samples_to_encode = data_bytes / bytes_per_wide_sample + *options.align_reservoir_samples;
if(options.sector_align) {
align_remainder = (unsigned)(encoder_wrapper.total_samples_to_encode % 588);
if(is_last_file)
if(options.is_last_file)
encoder_wrapper.total_samples_to_encode += (588-align_remainder); /* will pad with zeroes */
else
encoder_wrapper.total_samples_to_encode -= align_remainder; /* will stop short and carry over to next file */
@ -289,7 +306,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
/* +44 for the size of the WAV headers; this is just an estimate for the progress indicator and doesn't need to be exact */
encoder_wrapper.unencoded_size = encoder_wrapper.total_samples_to_encode * bytes_per_wide_sample + 44;
if(!init_encoder(lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_escape_coding, do_qlp_coeff_prec_search, min_residual_partition_order, max_residual_partition_order, rice_parameter_search_dist, max_lpc_order, blocksize, qlp_coeff_precision, channels, bps, sample_rate, padding, requested_seek_points, num_requested_seek_points, &encoder_wrapper))
if(!init_encoder(options.common, channels, bps, sample_rate, &encoder_wrapper))
goto wav_abort_;
encoder_wrapper.verify_fifo.into_frames = true;
@ -297,12 +314,12 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
/*
* first do any samples in the reservoir
*/
if(sector_align && *align_reservoir_samples > 0) {
if(options.sector_align && *options.align_reservoir_samples > 0) {
/* NOTE: some versions of GCC can't figure out const-ness right and will give you an 'incompatible pointer type' warning on arg 2 here: */
append_to_verify_fifo(&encoder_wrapper, align_reservoir, channels, *align_reservoir_samples);
append_to_verify_fifo(&encoder_wrapper, options.align_reservoir, channels, *options.align_reservoir_samples);
/* NOTE: some versions of GCC can't figure out const-ness right and will give you an 'incompatible pointer type' warning on arg 2 here: */
if(!FLAC__stream_encoder_process(encoder_wrapper.encoder, align_reservoir, *align_reservoir_samples)) {
if(!FLAC__stream_encoder_process(encoder_wrapper.encoder, options.align_reservoir, *options.align_reservoir_samples)) {
fprintf(stderr, "%s: ERROR during encoding, state = %d:%s\n", encoder_wrapper.inbasefilename, FLAC__stream_encoder_get_state(encoder_wrapper.encoder), FLAC__StreamEncoderStateString[FLAC__stream_encoder_get_state(encoder_wrapper.encoder)]);
goto wav_abort_;
}
@ -311,13 +328,13 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
/*
* decrement the data_bytes counter if we need to align the file
*/
if(sector_align) {
if(is_last_file) {
*align_reservoir_samples = 0;
if(options.sector_align) {
if(options.is_last_file) {
*options.align_reservoir_samples = 0;
}
else {
*align_reservoir_samples = align_remainder;
data_bytes -= (*align_reservoir_samples) * bytes_per_wide_sample;
*options.align_reservoir_samples = align_remainder;
data_bytes -= (*options.align_reservoir_samples) * bytes_per_wide_sample;
}
}
@ -358,8 +375,8 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
/*
* now read unaligned samples into reservoir or pad with zeroes if necessary
*/
if(sector_align) {
if(is_last_file) {
if(options.sector_align) {
if(options.is_last_file) {
unsigned wide_samples = 588 - align_remainder;
if(wide_samples < 588) {
unsigned channel;
@ -379,20 +396,20 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
}
}
else {
if(*align_reservoir_samples > 0) {
if(*options.align_reservoir_samples > 0) {
FLAC__ASSERT(CHUNK_OF_SAMPLES >= 588);
bytes_read = fread(ucbuffer, sizeof(unsigned char), (*align_reservoir_samples) * bytes_per_wide_sample, infile);
bytes_read = fread(ucbuffer, sizeof(unsigned char), (*options.align_reservoir_samples) * bytes_per_wide_sample, infile);
if(bytes_read == 0 && ferror(infile)) {
fprintf(stderr, "%s: ERROR during read\n", encoder_wrapper.inbasefilename);
goto wav_abort_;
}
else if(bytes_read != (*align_reservoir_samples) * bytes_per_wide_sample) {
else if(bytes_read != (*options.align_reservoir_samples) * bytes_per_wide_sample) {
fprintf(stderr, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_wrapper.inbasefilename, (unsigned)encoder_wrapper.total_samples_to_encode, (unsigned)encoder_wrapper.samples_written);
data_bytes = 0;
}
else {
info_align_carry = *align_reservoir_samples;
format_input(align_reservoir, *align_reservoir_samples, false, is_unsigned_samples, channels, bps, &encoder_wrapper);
info_align_carry = *options.align_reservoir_samples;
format_input(options.align_reservoir, *options.align_reservoir_samples, false, is_unsigned_samples, channels, bps, &encoder_wrapper);
}
}
}
@ -431,6 +448,10 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
if(FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_OK)
FLAC__stream_encoder_finish(encoder_wrapper.encoder);
FLAC__stream_encoder_delete(encoder_wrapper.encoder);
#ifdef FLaC__HAS_OGG
if(use_ogg)
ogg_stream_clear(&encoder_wrapper.ogg.os);
#endif
}
if(encoder_wrapper.verbose && encoder_wrapper.total_samples_to_encode > 0) {
print_stats(&encoder_wrapper);
@ -438,7 +459,7 @@ int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, cons
}
if(0 != encoder_wrapper.seek_table.points)
free(encoder_wrapper.seek_table.points);
if(verify) {
if(options.common.verify) {
FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder);
FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder);
if(encoder_wrapper.verify_fifo.result != FLAC__VERIFY_OK) {
@ -460,10 +481,14 @@ wav_abort_:
if(FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_OK)
FLAC__stream_encoder_finish(encoder_wrapper.encoder);
FLAC__stream_encoder_delete(encoder_wrapper.encoder);
#ifdef FLaC__HAS_OGG
if(use_ogg)
ogg_stream_clear(&encoder_wrapper.ogg.os);
#endif
}
if(0 != encoder_wrapper.seek_table.points)
free(encoder_wrapper.seek_table.points);
if(verify) {
if(options.common.verify) {
FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder);
FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder);
if(encoder_wrapper.verify_fifo.result != FLAC__VERIFY_OK) {
@ -477,17 +502,15 @@ wav_abort_:
return 1;
}
int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, FLAC__bool is_last_file, FLAC__bool verbose, FLAC__uint64 skip, FLAC__bool verify, FLAC__bool lax, FLAC__bool do_mid_side, FLAC__bool loose_mid_side, FLAC__bool do_exhaustive_model_search, FLAC__bool do_escape_coding, FLAC__bool do_qlp_coeff_prec_search, unsigned min_residual_partition_order, unsigned max_residual_partition_order, unsigned rice_parameter_search_dist, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned padding, char *requested_seek_points, int num_requested_seek_points, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned sample_rate)
int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, raw_encode_options_t options)
{
encoder_wrapper_struct encoder_wrapper;
size_t bytes_read;
const size_t bytes_per_wide_sample = channels * (bps >> 3);
(void)is_last_file;
const size_t bytes_per_wide_sample = options.channels * (options.bps >> 3);
encoder_wrapper.encoder = 0;
encoder_wrapper.verify = verify;
encoder_wrapper.verbose = verbose;
encoder_wrapper.verify = options.common.verify;
encoder_wrapper.verbose = options.common.verbose;
encoder_wrapper.bytes_written = 0;
encoder_wrapper.samples_written = 0;
encoder_wrapper.stream_offset = 0;
@ -495,6 +518,9 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
encoder_wrapper.outfilename = outfilename;
encoder_wrapper.seek_table.points = 0;
encoder_wrapper.first_seek_point_to_check = 0;
#ifdef FLaC__HAS_OGG
encoder_wrapper.use_ogg = use_ogg;
#endif
if(0 == strcmp(outfilename, "-")) {
encoder_wrapper.fout = stdout;
@ -515,15 +541,15 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
encoder_wrapper.total_samples_to_encode = encoder_wrapper.unencoded_size = 0;
}
else {
encoder_wrapper.total_samples_to_encode = (unsigned)infilesize / bytes_per_wide_sample - skip;
encoder_wrapper.total_samples_to_encode = (unsigned)infilesize / bytes_per_wide_sample - options.common.skip;
encoder_wrapper.unencoded_size = encoder_wrapper.total_samples_to_encode * bytes_per_wide_sample;
}
if(encoder_wrapper.verbose && encoder_wrapper.total_samples_to_encode <= 0)
fprintf(stderr, "(No runtime statistics possible; please wait for encoding to finish...)\n");
if(skip > 0) {
unsigned skip_bytes = bytes_per_wide_sample * (unsigned)skip;
if(options.common.skip > 0) {
unsigned skip_bytes = bytes_per_wide_sample * (unsigned)options.common.skip;
if(skip_bytes > lookahead_length) {
skip_bytes -= lookahead_length;
lookahead_length = 0;
@ -552,7 +578,7 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
}
}
if(!init_encoder(lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_escape_coding, do_qlp_coeff_prec_search, min_residual_partition_order, max_residual_partition_order, rice_parameter_search_dist, max_lpc_order, blocksize, qlp_coeff_precision, channels, bps, sample_rate, padding, requested_seek_points, num_requested_seek_points, &encoder_wrapper))
if(!init_encoder(options.common, options.channels, options.bps, options.sample_rate, &encoder_wrapper))
goto raw_abort_;
encoder_wrapper.verify_fifo.into_frames = true;
@ -583,7 +609,7 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
}
else {
unsigned wide_samples = bytes_read / bytes_per_wide_sample;
format_input(input, wide_samples, is_big_endian, is_unsigned_samples, channels, bps, &encoder_wrapper);
format_input(input, wide_samples, options.is_big_endian, options.is_unsigned_samples, options.channels, options.bps, &encoder_wrapper);
/* NOTE: some versions of GCC can't figure out const-ness right and will give you an 'incompatible pointer type' warning on arg 2 here: */
if(!FLAC__stream_encoder_process(encoder_wrapper.encoder, input, wide_samples)) {
@ -597,6 +623,10 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
if(FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_OK)
FLAC__stream_encoder_finish(encoder_wrapper.encoder);
FLAC__stream_encoder_delete(encoder_wrapper.encoder);
#ifdef FLaC__HAS_OGG
if(use_ogg)
ogg_stream_clear(&encoder_wrapper.ogg.os);
#endif
}
if(encoder_wrapper.verbose && encoder_wrapper.total_samples_to_encode > 0) {
print_stats(&encoder_wrapper);
@ -604,7 +634,7 @@ int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, cons
}
if(0 != encoder_wrapper.seek_table.points)
free(encoder_wrapper.seek_table.points);
if(verify) {
if(options.common.verify) {
FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder);
FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder);
if(encoder_wrapper.verify_fifo.result != FLAC__VERIFY_OK) {
@ -622,10 +652,14 @@ raw_abort_:
if(FLAC__stream_encoder_get_state(encoder_wrapper.encoder) == FLAC__STREAM_ENCODER_OK)
FLAC__stream_encoder_finish(encoder_wrapper.encoder);
FLAC__stream_encoder_delete(encoder_wrapper.encoder);
#ifdef FLaC__HAS_OGG
if(use_ogg)
ogg_stream_clear(&encoder_wrapper.ogg.os);
#endif
}
if(0 != encoder_wrapper.seek_table.points)
free(encoder_wrapper.seek_table.points);
if(verify) {
if(options.common.verify) {
FLAC__stream_decoder_finish(encoder_wrapper.verify_fifo.decoder);
FLAC__stream_decoder_delete(encoder_wrapper.verify_fifo.decoder);
if(encoder_wrapper.verify_fifo.result != FLAC__VERIFY_OK) {
@ -655,19 +689,29 @@ FLAC__bool init(encoder_wrapper_struct *encoder_wrapper)
return false;
}
#ifdef FLaC__HAS_OGG
if(encoder_wrapper->use_ogg) {
if(ogg_stream_init(&encoder_wrapper->ogg.os, 0) != 0) {
fprintf(stderr, "%s: ERROR initializing the Ogg stream\n", encoder_wrapper->inbasefilename);
FLAC__stream_encoder_delete(encoder_wrapper->encoder);
return false;
}
}
#endif
return true;
}
FLAC__bool init_encoder(FLAC__bool lax, FLAC__bool do_mid_side, FLAC__bool loose_mid_side, FLAC__bool do_exhaustive_model_search, FLAC__bool do_escape_coding, FLAC__bool do_qlp_coeff_prec_search, unsigned min_residual_partition_order, unsigned max_residual_partition_order, unsigned rice_parameter_search_dist, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned channels, unsigned bps, unsigned sample_rate, unsigned padding, char *requested_seek_points, int num_requested_seek_points, encoder_wrapper_struct *encoder_wrapper)
FLAC__bool init_encoder(encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate, encoder_wrapper_struct *encoder_wrapper)
{
unsigned i;
if(channels != 2)
do_mid_side = loose_mid_side = false;
options.do_mid_side = options.loose_mid_side = false;
if(encoder_wrapper->verify) {
/* set up the fifo which will hold the original signal to compare against */
encoder_wrapper->verify_fifo.size = blocksize + CHUNK_OF_SAMPLES;
encoder_wrapper->verify_fifo.size = options.blocksize + CHUNK_OF_SAMPLES;
for(i = 0; i < channels; i++) {
if(0 == (encoder_wrapper->verify_fifo.original[i] = (FLAC__int32*)malloc(sizeof(FLAC__int32) * encoder_wrapper->verify_fifo.size))) {
fprintf(stderr, "%s: ERROR allocating verify buffers\n", encoder_wrapper->inbasefilename);
@ -695,29 +739,29 @@ FLAC__bool init_encoder(FLAC__bool lax, FLAC__bool do_mid_side, FLAC__bool loose
}
}
if(!convert_to_seek_table(requested_seek_points, num_requested_seek_points, encoder_wrapper->total_samples_to_encode, blocksize, &encoder_wrapper->seek_table)) {
if(!convert_to_seek_table(options.requested_seek_points, options.num_requested_seek_points, encoder_wrapper->total_samples_to_encode, options.blocksize, &encoder_wrapper->seek_table)) {
fprintf(stderr, "%s: ERROR allocating seek table\n", encoder_wrapper->inbasefilename);
return false;
}
FLAC__stream_encoder_set_streamable_subset(encoder_wrapper->encoder, !lax);
FLAC__stream_encoder_set_do_mid_side_stereo(encoder_wrapper->encoder, do_mid_side);
FLAC__stream_encoder_set_loose_mid_side_stereo(encoder_wrapper->encoder, loose_mid_side);
FLAC__stream_encoder_set_streamable_subset(encoder_wrapper->encoder, !options.lax);
FLAC__stream_encoder_set_do_mid_side_stereo(encoder_wrapper->encoder, options.do_mid_side);
FLAC__stream_encoder_set_loose_mid_side_stereo(encoder_wrapper->encoder, options.loose_mid_side);
FLAC__stream_encoder_set_channels(encoder_wrapper->encoder, channels);
FLAC__stream_encoder_set_bits_per_sample(encoder_wrapper->encoder, bps);
FLAC__stream_encoder_set_sample_rate(encoder_wrapper->encoder, sample_rate);
FLAC__stream_encoder_set_blocksize(encoder_wrapper->encoder, blocksize);
FLAC__stream_encoder_set_max_lpc_order(encoder_wrapper->encoder, max_lpc_order);
FLAC__stream_encoder_set_qlp_coeff_precision(encoder_wrapper->encoder, qlp_coeff_precision);
FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder_wrapper->encoder, do_qlp_coeff_prec_search);
FLAC__stream_encoder_set_do_escape_coding(encoder_wrapper->encoder, do_escape_coding);
FLAC__stream_encoder_set_do_exhaustive_model_search(encoder_wrapper->encoder, do_exhaustive_model_search);
FLAC__stream_encoder_set_min_residual_partition_order(encoder_wrapper->encoder, min_residual_partition_order);
FLAC__stream_encoder_set_max_residual_partition_order(encoder_wrapper->encoder, max_residual_partition_order);
FLAC__stream_encoder_set_rice_parameter_search_dist(encoder_wrapper->encoder, rice_parameter_search_dist);
FLAC__stream_encoder_set_blocksize(encoder_wrapper->encoder, options.blocksize);
FLAC__stream_encoder_set_max_lpc_order(encoder_wrapper->encoder, options.max_lpc_order);
FLAC__stream_encoder_set_qlp_coeff_precision(encoder_wrapper->encoder, options.qlp_coeff_precision);
FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder_wrapper->encoder, options.do_qlp_coeff_prec_search);
FLAC__stream_encoder_set_do_escape_coding(encoder_wrapper->encoder, options.do_escape_coding);
FLAC__stream_encoder_set_do_exhaustive_model_search(encoder_wrapper->encoder, options.do_exhaustive_model_search);
FLAC__stream_encoder_set_min_residual_partition_order(encoder_wrapper->encoder, options.min_residual_partition_order);
FLAC__stream_encoder_set_max_residual_partition_order(encoder_wrapper->encoder, options.max_residual_partition_order);
FLAC__stream_encoder_set_rice_parameter_search_dist(encoder_wrapper->encoder, options.rice_parameter_search_dist);
FLAC__stream_encoder_set_total_samples_estimate(encoder_wrapper->encoder, encoder_wrapper->total_samples_to_encode);
FLAC__stream_encoder_set_seek_table(encoder_wrapper->encoder, (encoder_wrapper->seek_table.num_points > 0)? &encoder_wrapper->seek_table : 0);
FLAC__stream_encoder_set_padding(encoder_wrapper->encoder, padding);
FLAC__stream_encoder_set_padding(encoder_wrapper->encoder, options.padding);
FLAC__stream_encoder_set_last_metadata_is_last(encoder_wrapper->encoder, true);
FLAC__stream_encoder_set_write_callback(encoder_wrapper->encoder, write_callback);
FLAC__stream_encoder_set_metadata_callback(encoder_wrapper->encoder, metadata_callback);
@ -983,10 +1027,44 @@ FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder
}
}
if(fwrite(buffer, sizeof(FLAC__byte), bytes, encoder_wrapper->fout) == bytes)
#ifdef FLaC__HAS_OGG
if(encoder_wrapper->use_ogg) {
ogg_packet op;
memset(&op, 0, sizeof(op));
op.packet = (unsigned char *)buffer;
op.packetno = encoder_wrapper->current_frame;
op.bytes = bytes;
if (encoder_wrapper->bytes_written == bytes)
op.b_o_s = 1;
if (encoder_wrapper->total_samples_to_encode == encoder_wrapper->samples_written)
op.e_o_s = 1;
ogg_stream_packetin(&encoder_wrapper->ogg.os, &op);
while(ogg_stream_pageout(&encoder_wrapper->ogg.os, &encoder_wrapper->ogg.og) != 0) {
int written;
written = fwrite(encoder_wrapper->ogg.og.header, 1, encoder_wrapper->ogg.og.header_len, encoder_wrapper->fout);
if (written != encoder_wrapper->ogg.og.header_len)
return FLAC__STREAM_ENCODER_WRITE_FATAL_ERROR;
written = fwrite(encoder_wrapper->ogg.og.body, 1, encoder_wrapper->ogg.og.body_len, encoder_wrapper->fout);
if (written != encoder_wrapper->ogg.og.body_len)
return FLAC__STREAM_ENCODER_WRITE_FATAL_ERROR;
}
return FLAC__STREAM_ENCODER_WRITE_OK;
}
else
return FLAC__STREAM_ENCODER_WRITE_FATAL_ERROR;
#endif
{
if(fwrite(buffer, sizeof(FLAC__byte), bytes, encoder_wrapper->fout) == bytes)
return FLAC__STREAM_ENCODER_WRITE_OK;
else
return FLAC__STREAM_ENCODER_WRITE_FATAL_ERROR;
}
}
void metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data)
@ -1000,6 +1078,15 @@ void metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMet
FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO);
/*
* If we are writing to an ogg stream, there is no need to go back
* and update the STREAMINFO or SEEKTABLE blocks; the values we would
* update are not necessary with Ogg as the transport. We can't do
* it reliably anyway without knowing the Ogg structure.
*/
if(encoder_wrapper->use_ogg)
return;
/*
* we get called by the encoder when the encoding process has
* finished so that we can update the STREAMINFO and SEEKTABLE

View File

@ -21,7 +21,50 @@
#include "FLAC/ordinals.h"
int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, FLAC__int32 *align_reservoir[], unsigned *align_reservoir_samples, FLAC__bool sector_align, FLAC__bool is_last_file, FLAC__bool verbose, FLAC__uint64 skip, FLAC__bool verify, FLAC__bool lax, FLAC__bool do_mid_side, FLAC__bool loose_mid_side, FLAC__bool do_exhaustive_model_search, FLAC__bool do_escape_coding, FLAC__bool do_qlp_coeff_prec_search, unsigned min_residual_partition_order, unsigned max_residual_partition_order, unsigned rice_parameter_search_dist, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned padding, char *requested_seek_points, int num_requested_seek_points);
int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, FLAC__bool is_last_file, FLAC__bool verbose, FLAC__uint64 skip, FLAC__bool verify, FLAC__bool lax, FLAC__bool do_mid_side, FLAC__bool loose_mid_side, FLAC__bool do_exhaustive_model_search, FLAC__bool do_escape_coding, FLAC__bool do_qlp_coeff_prec_search, unsigned min_residual_partition_order, unsigned max_residual_partition_order, unsigned rice_parameter_search_dist, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned padding, char *requested_seek_points, int num_requested_seek_points, FLAC__bool is_big_endian, FLAC__bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned sample_rate);
typedef struct {
FLAC__bool verbose;
FLAC__uint64 skip;
FLAC__bool verify;
#ifdef FLaC__HAS_OGG
FLAC__bool use_ogg;
#endif
FLAC__bool lax;
FLAC__bool do_mid_side;
FLAC__bool loose_mid_side;
FLAC__bool do_exhaustive_model_search;
FLAC__bool do_escape_coding;
FLAC__bool do_qlp_coeff_prec_search;
unsigned min_residual_partition_order;
unsigned max_residual_partition_order;
unsigned rice_parameter_search_dist;
unsigned max_lpc_order;
unsigned blocksize;
unsigned qlp_coeff_precision;
unsigned padding;
char *requested_seek_points;
int num_requested_seek_points;
} encode_options_t;
typedef struct {
encode_options_t common;
FLAC__bool is_last_file;
FLAC__int32 **align_reservoir;
unsigned *align_reservoir_samples;
FLAC__bool sector_align;
} wav_encode_options_t;
typedef struct {
encode_options_t common;
FLAC__bool is_big_endian;
FLAC__bool is_unsigned_samples;
unsigned channels;
unsigned bps;
unsigned sample_rate;
} raw_encode_options_t;
int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options);
int flac__encode_raw(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, raw_encode_options_t options);
#endif

View File

@ -37,7 +37,7 @@ static int usage(const char *message, ...);
static int encode_file(const char *infilename, const char *forced_outfilename, FLAC__bool is_last_file);
static int decode_file(const char *infilename, const char *forced_outfilename);
FLAC__bool verify = false, verbose = true, lax = false, test_only = false, analyze = false;
FLAC__bool verify = false, verbose = true, lax = false, test_only = false, analyze = false, use_ogg = false;
FLAC__bool do_mid_side = true, loose_mid_side = false, do_exhaustive_model_search = false, do_escape_coding = false, do_qlp_coeff_prec_search = false;
FLAC__bool force_to_stdout = false, delete_input = false, sector_align = false;
const char *cmdline_forced_outfilename = 0, *output_prefix = 0;
@ -55,6 +55,8 @@ FLAC__int32 align_reservoir_0[588], align_reservoir_1[588]; /* for carrying over
FLAC__int32 *align_reservoir[2] = { align_reservoir_0, align_reservoir_1 };
unsigned align_reservoir_samples = 0; /* 0 .. 587 */
static const char *flac_suffix = ".flac", *ogg_suffix = ".ogg";
int main(int argc, char *argv[])
{
int i, retval = 0;
@ -110,6 +112,12 @@ int main(int argc, char *argv[])
lax = true;
else if(0 == strcmp(argv[i], "--lax-"))
lax = false;
#ifdef FLaC__HAS_OGG
else if(0 == strcmp(argv[i], "--ogg"))
use_ogg = true;
else if(0 == strcmp(argv[i], "--ogg-"))
use_ogg = false;
#endif
else if(0 == strcmp(argv[i], "-b"))
blocksize = atoi(argv[++i]);
else if(0 == strcmp(argv[i], "-e"))
@ -371,8 +379,17 @@ int main(int argc, char *argv[])
fprintf(stderr, "welcome to redistribute it under certain conditions. Type `flac' for details.\n\n");
if(!mode_decode) {
fprintf(stderr, "options:%s%s%s -P %u -b %u%s -l %u%s%s%s -q %u -r %u,%u -R %u%s\n",
delete_input?" --delete-input-file":"", sector_align?" --sector-align":"", lax?" --lax":"",
fprintf(stderr,
"options:%s%s"
#ifdef FLaC__HAS_OGG
"%s"
#endif
"%s -P %u -b %u%s -l %u%s%s%s -q %u -r %u,%u -R %u%s\n",
delete_input?" --delete-input-file":"", sector_align?" --sector-align":"",
#ifdef FLaC__HAS_OGG
ogg?" --ogg":"",
#endif
lax?" --lax":"",
padding, (unsigned)blocksize, loose_mid_side?" -M":do_mid_side?" -m":"", max_lpc_order,
do_exhaustive_model_search?" -e":"", do_escape_coding?" -E":"", do_qlp_coeff_prec_search?" -p":"",
qlp_coeff_precision,
@ -492,6 +509,9 @@ int usage(const char *message, ...)
fprintf(stderr, " --a-rtext : include residual signal in text output\n");
fprintf(stderr, " --a-rgp : generate gnuplot files of residual distribution of each subframe\n");
fprintf(stderr, "encoding options:\n");
#ifdef FLaC__HAS_OGG
fprintf(stderr, " --ogg : output Ogg-FLAC stream instead of native FLAC\n");
#endif
fprintf(stderr, " --lax : allow encoder to generate non-Subset files\n");
fprintf(stderr, " --sector-align : align encoding of multiple files on sector boundaries\n");
fprintf(stderr, " -S { # | X | #x } : include a point or points in a SEEKTABLE\n");
@ -538,7 +558,13 @@ int usage(const char *message, ...)
fprintf(stderr, " -R # : Rice parameter search distance (# is 0..32; above 2 doesn't help much)\n");
fprintf(stderr, " -V : verify a correct encoding by decoding the output in parallel and\n");
fprintf(stderr, " comparing to the original\n");
fprintf(stderr, " -S-, -m-, -M-, -e-, -E-, -p-, -V-, --delete-input-file-, --lax-, --sector-align-\n");
fprintf(stderr, " -S-, -m-, -M-, -e-, -E-, -p-, -V-, --delete-input-file-,%s --lax-, --sector-align-\n",
#ifdef FLaC__HAS_OGG
" --ogg-,"
#else
""
#endif
);
fprintf(stderr, " can all be used to turn off a particular option\n");
fprintf(stderr, "format options:\n");
fprintf(stderr, " -fb | -fl : big-endian | little-endian byte order\n");
@ -561,6 +587,7 @@ int encode_file(const char *infilename, const char *forced_outfilename, FLAC__bo
unsigned lookahead_length = 0;
int retval;
long infilesize;
encode_options_t common_options;
if(0 == strcmp(infilename, "-")) {
infilesize = -1;
@ -611,15 +638,18 @@ int encode_file(const char *infilename, const char *forced_outfilename, FLAC__bo
if(encode_infile == stdin || force_to_stdout)
strcpy(outfilename, "-");
else {
const char *suffix = (use_ogg? ogg_suffix : flac_suffix);
strcpy(outfilename, output_prefix? output_prefix : "");
strcat(outfilename, infilename);
if(0 == (p = strrchr(outfilename, '.')))
strcat(outfilename, ".flac");
strcat(outfilename, suffix);
else {
if(0 == strcmp(p, ".flac"))
strcpy(p, "_new.flac");
if(0 == strcmp(p, suffix)) {
strcpy(p, "_new");
strcat(p, suffix);
}
else
strcpy(p, ".flac");
strcpy(p, suffix);
}
}
if(0 == forced_outfilename)
@ -627,10 +657,51 @@ int encode_file(const char *infilename, const char *forced_outfilename, FLAC__bo
if(0 != cmdline_forced_outfilename)
forced_outfilename = cmdline_forced_outfilename;
if(format_is_wave)
retval = flac__encode_wav(encode_infile, infilesize, infilename, forced_outfilename, lookahead, lookahead_length, align_reservoir, &align_reservoir_samples, sector_align, is_last_file, verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_escape_coding, do_qlp_coeff_prec_search, min_residual_partition_order, max_residual_partition_order, rice_parameter_search_dist, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision, padding, requested_seek_points, num_requested_seek_points);
else
retval = flac__encode_raw(encode_infile, infilesize, infilename, forced_outfilename, lookahead, lookahead_length, is_last_file, verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, do_escape_coding, do_qlp_coeff_prec_search, min_residual_partition_order, max_residual_partition_order, rice_parameter_search_dist, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision, padding, requested_seek_points, num_requested_seek_points, format_is_big_endian, format_is_unsigned_samples, format_channels, format_bps, format_sample_rate);
common_options.verbose = verbose;
common_options.skip = skip;
common_options.verify = verify;
#ifdef FLaC__HAS_OGG
common_options.use_ogg = use_ogg;
#endif
common_options.lax = lax;
common_options.do_mid_side = do_mid_side;
common_options.loose_mid_side = loose_mid_side;
common_options.do_exhaustive_model_search = do_exhaustive_model_search;
common_options.do_escape_coding = do_escape_coding;
common_options.do_qlp_coeff_prec_search = do_qlp_coeff_prec_search;
common_options.min_residual_partition_order = min_residual_partition_order;
common_options.max_residual_partition_order = max_residual_partition_order;
common_options.rice_parameter_search_dist = rice_parameter_search_dist;
common_options.max_lpc_order = max_lpc_order;
common_options.blocksize = (unsigned)blocksize;
common_options.qlp_coeff_precision = qlp_coeff_precision;
common_options.padding = padding;
common_options.requested_seek_points = requested_seek_points;
common_options.num_requested_seek_points = num_requested_seek_points;
if(format_is_wave) {
wav_encode_options_t options;
options.common = common_options;
options.is_last_file = is_last_file;
options.align_reservoir = align_reservoir;
options.align_reservoir_samples = &align_reservoir_samples;
options.sector_align = sector_align;
retval = flac__encode_wav(encode_infile, infilesize, infilename, forced_outfilename, lookahead, lookahead_length, options);
}
else {
raw_encode_options_t options;
options.common = common_options;
options.is_big_endian = format_is_big_endian;
options.is_unsigned_samples = format_is_unsigned_samples;
options.channels = format_channels;
options.bps = format_bps;
options.sample_rate = format_sample_rate;
retval = flac__encode_raw(encode_infile, infilesize, infilename, forced_outfilename, lookahead, lookahead_length, options);
}
if(retval == 0 && strcmp(infilename, "-")) {
if(strcmp(forced_outfilename, "-"))
@ -648,6 +719,7 @@ int decode_file(const char *infilename, const char *forced_outfilename)
char outfilename[4096]; /* @@@ bad MAGIC NUMBER */
char *p;
int retval;
decode_options_t common_options;
if(!test_only && !analyze) {
if(format_is_wave < 0) {
@ -681,10 +753,28 @@ int decode_file(const char *infilename, const char *forced_outfilename)
if(0 != cmdline_forced_outfilename)
forced_outfilename = cmdline_forced_outfilename;
if(format_is_wave)
retval = flac__decode_wav(infilename, test_only? 0 : forced_outfilename, analyze, aopts, verbose, skip);
else
retval = flac__decode_raw(infilename, test_only? 0 : forced_outfilename, analyze, aopts, verbose, skip, format_is_big_endian, format_is_unsigned_samples);
common_options.verbose = verbose;
#ifdef FLaC__HAS_OGG
common_options.is_ogg = is_ogg;
#endif
common_options.skip = skip;
if(format_is_wave) {
wav_decode_options_t options;
options.common = common_options;
retval = flac__decode_wav(infilename, test_only? 0 : forced_outfilename, analyze, aopts, options);
}
else {
raw_decode_options_t options;
options.common = common_options;
options.is_big_endian = format_is_big_endian;
options.is_unsigned_samples = format_is_unsigned_samples;
retval = flac__decode_raw(infilename, test_only? 0 : forced_outfilename, analyze, aopts, options);
}
if(retval == 0 && strcmp(infilename, "-")) {
if(strcmp(forced_outfilename, "-"))