Commit 495abdde authored by Josh Coalson's avatar Josh Coalson
Browse files

fix WAVE autodetect to be more robust and not require ungetc()

parent 3fa53d62
......@@ -107,7 +107,7 @@ static bool read_little_endian_uint32(FILE *f, uint32 *val, bool eof_ok);
static bool write_big_endian_uint16(FILE *f, uint16 val);
static bool write_big_endian_uint64(FILE *f, uint64 val);
int flac__encode_wav(FILE *infile, const char *infilename, const char *outfilename, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, 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 byte *lookahead, unsigned lookahead_length, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, 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)
{
encoder_wrapper_struct encoder_wrapper;
bool is_unsigned_samples = false;
......@@ -126,6 +126,9 @@ int flac__encode_wav(FILE *infile, const char *infilename, const char *outfilena
encoder_wrapper.outfilename = outfilename;
encoder_wrapper.seek_table.points = 0;
encoder_wrapper.first_seek_point_to_check = 0;
(void)infilesize;
(void)lookahead;
(void)lookahead_length;
if(0 == strcmp(outfilename, "-")) {
encoder_wrapper.fout = stdout;
......@@ -142,28 +145,8 @@ int flac__encode_wav(FILE *infile, const char *infilename, const char *outfilena
goto wav_abort_;
/*
* check the RIFF chunk
* lookahead[] already has "RIFFxxxxWAVE", do sub-chunks
*/
if(!read_little_endian_uint32(infile, &xx, false))
goto wav_abort_;
if(xx != 0x46464952) { /* "RIFF" */
fprintf(stderr, "ERROR: no RIFF header\n");
goto wav_abort_;
}
if(!read_little_endian_uint32(infile, &xx, false))
goto wav_abort_;
/*
* now process the WAVE chunk
*/
if(!read_little_endian_uint32(infile, &xx, true))
goto wav_end_;
if(xx != 0x45564157) { /* "WAVE" */
fprintf(stderr, "ERROR: no WAVE header\n");
goto wav_abort_;
}
/* do sub-chunks */
while(!feof(infile)) {
if(!read_little_endian_uint32(infile, &xx, true))
goto wav_abort_;
......@@ -247,14 +230,14 @@ int flac__encode_wav(FILE *infile, const char *infilename, const char *outfilena
}
}
else {
int64 left;
unsigned need;
for(left = (int64)skip; left > 0; left -= CHUNK_OF_SAMPLES) {
unsigned left, need;
for(left = skip; left > 0; ) {
need = min(left, CHUNK_OF_SAMPLES);
if(fread(ucbuffer, 1, bytes_per_wide_sample * need, infile) < need) {
fprintf(stderr, "ERROR seeking while skipping samples in input file %s\n", infilename);
goto wav_abort_;
}
left -= need;
}
}
}
......@@ -305,15 +288,27 @@ int flac__encode_wav(FILE *infile, const char *infilename, const char *outfilena
/* chunk size */
if(!read_little_endian_uint32(infile, &xx, false))
goto wav_abort_;
if(-1 == fseek(infile, xx, SEEK_CUR)) {
fprintf(stderr, "ERROR seeking ahead while skipping unsupported sub-chunk in input file %s\n", infilename);
goto wav_abort_;
if(infile != stdin) {
if(-1 == fseek(infile, xx, SEEK_CUR)) {
fprintf(stderr, "ERROR seeking ahead while skipping unsupported sub-chunk in input file %s\n", infilename);
goto wav_abort_;
}
}
else {
unsigned left, need;
const unsigned chunk = sizeof(ucbuffer);
for(left = xx; left > 0; ) {
need = min(left, chunk);
if(fread(ucbuffer, 1, need, infile) < need) {
fprintf(stderr, "ERROR seeking while skipping unsupported sub-chunk in input file %s\n", infilename);
goto wav_abort_;
}
left -= need;
}
}
}
}
wav_end_:
if(encoder_wrapper.encoder) {
if(encoder_wrapper.encoder->state == FLAC__ENCODER_OK)
FLAC__encoder_finish(encoder_wrapper.encoder);
......@@ -362,7 +357,7 @@ wav_abort_:
return 1;
}
int flac__encode_raw(FILE *infile, const char *infilename, const char *outfilename, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, 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, bool is_big_endian, 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 byte *lookahead, unsigned lookahead_length, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, 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, bool is_big_endian, bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned sample_rate)
{
encoder_wrapper_struct encoder_wrapper;
size_t bytes_read;
......@@ -393,41 +388,44 @@ int flac__encode_raw(FILE *infile, const char *infilename, const char *outfilena
goto raw_abort_;
/* get the file length */
if(0 != fseek(infile, 0, SEEK_END)) {
if(infilesize < 0) {
encoder_wrapper.total_samples_to_encode = encoder_wrapper.unencoded_size = 0;
}
else {
long filesize;
fflush(infile);
if(-1 == (filesize = ftell(infile))) {
encoder_wrapper.total_samples_to_encode = encoder_wrapper.unencoded_size = 0;
}
else {
encoder_wrapper.unencoded_size = filesize - skip * bytes_per_wide_sample;
encoder_wrapper.total_samples_to_encode = filesize / bytes_per_wide_sample - skip;
}
encoder_wrapper.unencoded_size = (unsigned)infilesize - skip * bytes_per_wide_sample;
encoder_wrapper.total_samples_to_encode = (unsigned)infilesize / bytes_per_wide_sample - skip;
}
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) {
if(infile != stdin) {
if(-1 == fseek(infile, bytes_per_wide_sample * (unsigned)skip, SEEK_SET)) {
fprintf(stderr, "ERROR seeking while skipping samples in input file %s\n", infilename);
goto raw_abort_;
}
}
else {
int64 left;
unsigned need;
for(left = (int64)skip; left > 0; left -= CHUNK_OF_SAMPLES) {
need = min(left, CHUNK_OF_SAMPLES);
if(fread(ucbuffer, 1, bytes_per_wide_sample * need, infile) < need) {
unsigned skip_bytes = bytes_per_wide_sample * (unsigned)skip;
if(skip_bytes > lookahead_length) {
skip_bytes -= lookahead_length;
lookahead_length = 0;
if(infile != stdin) {
if(-1 == fseek(infile, (long)skip_bytes, SEEK_SET)) {
fprintf(stderr, "ERROR seeking while skipping samples in input file %s\n", infilename);
goto raw_abort_;
}
}
else {
unsigned left, need;
const unsigned chunk = sizeof(ucbuffer);
for(left = skip_bytes; left > 0; ) {
need = min(left, chunk);
if(fread(ucbuffer, 1, need, infile) < need) {
fprintf(stderr, "ERROR seeking while skipping samples in input file %s\n", infilename);
goto raw_abort_;
}
left -= need;
}
}
}
else {
lookahead += skip_bytes;
lookahead_length -= skip_bytes;
}
}
else {
......@@ -440,7 +438,19 @@ int flac__encode_raw(FILE *infile, const char *infilename, const char *outfilena
encoder_wrapper.verify_fifo.into_frames = true;
while(!feof(infile)) {
bytes_read = fread(ucbuffer, sizeof(unsigned char), CHUNK_OF_SAMPLES * bytes_per_wide_sample, infile);
if(lookahead_length > 0) {
FLAC__ASSERT(lookahead_length < CHUNK_OF_SAMPLES * bytes_per_wide_sample);
memcpy(ucbuffer, lookahead, lookahead_length);
bytes_read = fread(ucbuffer+lookahead_length, sizeof(unsigned char), CHUNK_OF_SAMPLES * bytes_per_wide_sample - lookahead_length, infile) + lookahead_length;
if(ferror(infile)) {
fprintf(stderr, "ERROR reading from %s\n", infilename);
goto raw_abort_;
}
lookahead_length = 0;
}
else
bytes_read = fread(ucbuffer, sizeof(unsigned char), CHUNK_OF_SAMPLES * bytes_per_wide_sample, infile);
if(bytes_read == 0) {
if(ferror(infile)) {
fprintf(stderr, "ERROR reading from %s\n", infilename);
......
......@@ -21,7 +21,7 @@
#include "FLAC/ordinals.h"
int flac__encode_wav(FILE *infile, const char *infilename, const char *outfilename, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, 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, const char *infilename, const char *outfilename, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, 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, bool is_big_endian, bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned sample_rate);
int flac__encode_wav(FILE *infile, long infilesize, const char *infilename, const char *outfilename, const byte *lookahead, unsigned lookahead_length, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, 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 byte *lookahead, unsigned lookahead_length, bool verbose, uint64 skip, bool verify, bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, 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, bool is_big_endian, bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned sample_rate);
#endif
......@@ -512,12 +512,17 @@ int encode_file(const char *infilename, const char *forced_outfilename)
FILE *encode_infile;
char outfilename[4096]; /* @@@ bad MAGIC NUMBER */
char *p;
byte lookahead[12];
unsigned lookahead_length;
int retval;
long infilesize;
if(0 == strcmp(infilename, "-")) {
infilesize = -1;
encode_infile = stdin;
}
else {
infilesize = flac__file_get_filesize(infilename);
if(0 == (encode_infile = fopen(infilename, "rb"))) {
fprintf(stderr, "ERROR: can't open input file %s\n", infilename);
return 1;
......@@ -528,21 +533,20 @@ int encode_file(const char *infilename, const char *forced_outfilename)
fprintf(stderr, "%s:\n", infilename);
if(format_is_wave < 0) {
/* lamely attempt to guess the file type based on the first 4 bytes (which is all ungetc will guarantee us) */
char head[4];
int h, n;
/* first set format based on name */
if(strstr(infilename, ".wav") == infilename + (strlen(infilename) - strlen(".wav")))
if(0 == strcasecmp(infilename+(strlen(infilename)-4), ".wav"))
format_is_wave = true;
else
format_is_wave = false;
if((n = fread(head, 1, 4, encode_infile)) < 4) {
/* attempt to guess the file type based on the first 12 bytes */
if((lookahead_length = fread(lookahead, 1, 12, encode_infile)) < 12) {
if(format_is_wave)
fprintf(stderr, "WARNING: %s is not a WAVE file, treating as a raw file\n", infilename);
format_is_wave = false;
}
else {
if(strncmp(head, "RIFF", 4)) {
if(strncmp(lookahead, "RIFF", 4) || strncmp(lookahead+8, "WAVE", 4)) {
if(format_is_wave)
fprintf(stderr, "WARNING: %s is not a WAVE file, treating as a raw file\n", infilename);
format_is_wave = false;
......@@ -550,8 +554,6 @@ int encode_file(const char *infilename, const char *forced_outfilename)
else
format_is_wave = true;
}
for(h = n-1; h >= 0; h--)
ungetc(head[h], encode_infile);
}
if(!format_is_wave) {
......@@ -578,9 +580,9 @@ int encode_file(const char *infilename, const char *forced_outfilename)
forced_outfilename = cmdline_forced_outfilename;
if(format_is_wave)
retval = flac__encode_wav(encode_infile, infilename, forced_outfilename, verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, 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);
retval = flac__encode_wav(encode_infile, infilesize, infilename, forced_outfilename, lookahead, lookahead_length, verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, 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, infilename, forced_outfilename, verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, 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);
retval = flac__encode_raw(encode_infile, infilesize, infilename, forced_outfilename, lookahead, lookahead_length, verbose, skip, verify, lax, do_mid_side, loose_mid_side, do_exhaustive_model_search, 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);
if(retval == 0 && strcmp(infilename, "-")) {
if(strcmp(forced_outfilename, "-"))
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment