mirror of https://github.com/xiph/flac
fix WAVE autodetect to be more robust and not require ungetc()
This commit is contained in:
parent
3fa53d6211
commit
495abdde6f
|
@ -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, "-"))
|
||||
|
|
Loading…
Reference in New Issue