/* flac - Command-line FLAC encoder/decoder
- * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson
+ * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Josh Coalson
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
-#if defined _WIN32 && !defined __CYGWIN__
-/* where MSVC puts unlink() */
-# include <io.h>
-#else
-# include <unistd.h>
-#endif
-#if defined _MSC_VER || defined __MINGW32__
-#include <sys/types.h> /* for off_t */
-#if _MSC_VER <= 1600 /* @@@ [2G limit] */
-#define fseeko fseek
-#define ftello ftell
-#endif
-#endif
#include <errno.h>
#include <limits.h> /* for LONG_MAX */
#include <math.h> /* for floor() */
#include <stdio.h> /* for FILE etc. */
#include <stdlib.h> /* for malloc */
#include <string.h> /* for strcmp(), strerror() */
+#include <sys/stat.h>
#include "FLAC/all.h"
#include "share/alloc.h"
#include "share/grabbag.h"
+#include "share/compat.h"
+#include "share/private.h"
+#include "share/safe_str.h"
#include "encode.h"
#ifdef min
#define max(x,y) ((x)>(y)?(x):(y))
/* this MUST be >= 588 so that sector aligning can take place with one read */
+/* this MUST be < 2^sizeof(size_t) / ( FLAC__MAX_CHANNELS * (FLAC__MAX_BITS_PER_SAMPLE/8) ) */
#define CHUNK_OF_SAMPLES 2048
typedef struct {
/* this is the client_data attached to the FLAC decoder when encoding from a FLAC file */
typedef struct {
- off_t filesize;
+ FLAC__off_t filesize;
const FLAC__byte *lookahead;
unsigned lookahead_length;
size_t num_metadata_blocks;
FileFormat format;
union {
struct {
- size_t data_bytes;
- FLAC__bool pad;
+ FLAC__uint64 data_bytes;
} iff;
struct {
FLAC__StreamDecoder *decoder;
/*
- * unpublished debug routines from the FLAC libs
- */
-extern FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
-extern FLAC__bool FLAC__stream_encoder_set_do_md5(FLAC__StreamEncoder *encoder, FLAC__bool value);
-
-/*
* local routines
*/
-static FLAC__bool EncoderSession_construct(EncoderSession *e, encode_options_t options, off_t infilesize, FILE *infile, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length);
+static FLAC__bool EncoderSession_construct(EncoderSession *e, encode_options_t options, FLAC__off_t infilesize, FILE *infile, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length);
static void EncoderSession_destroy(EncoderSession *e);
static int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_align_zero, foreign_metadata_t *foreign_metadata);
static int EncoderSession_finish_error(EncoderSession *e);
static FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options);
static FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 * const buffer[], unsigned samples);
+static FLAC__bool EncoderSession_format_is_iff(const EncoderSession *e);
static FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int num_requested_seek_points, FLAC__StreamMetadata *cuesheet, EncoderSession *e);
static FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input);
static FLAC__bool verify_metadata(const EncoderSession *e, FLAC__StreamMetadata **metadata, unsigned num_metadata);
static FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
static void flac_decoder_metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
static void flac_decoder_error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
-static FLAC__bool parse_cuesheet(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset, FLAC__bool treat_warnings_as_errors);
+static FLAC__bool parse_cuesheet(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, unsigned sample_rate, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset, FLAC__bool treat_warnings_as_errors);
static void print_stats(const EncoderSession *encoder_session);
static void print_error_with_init_status(const EncoderSession *e, const char *message, FLAC__StreamEncoderInitStatus init_status);
static void print_error_with_state(const EncoderSession *e, const char *message);
static FLAC__bool read_bytes(FILE *f, FLAC__byte *buf, size_t n, FLAC__bool eof_ok, const char *fn);
static FLAC__bool read_uint16(FILE *f, FLAC__bool big_endian, FLAC__uint16 *val, const char *fn);
static FLAC__bool read_uint32(FILE *f, FLAC__bool big_endian, FLAC__uint32 *val, const char *fn);
+static FLAC__bool read_uint64(FILE *f, FLAC__bool big_endian, FLAC__uint64 *val, const char *fn);
static FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, const char *fn);
static FLAC__bool fskip_ahead(FILE *f, FLAC__uint64 offset);
static unsigned count_channel_mask_bits(FLAC__uint32 mask);
static FLAC__bool get_sample_info_wave(EncoderSession *e, encode_options_t options)
{
- FLAC__bool got_fmt_chunk = false, got_data_chunk = false;
+ FLAC__bool got_fmt_chunk = false, got_data_chunk = false, got_ds64_chunk = false;
unsigned sample_rate = 0, channels = 0, bps = 0, shift = 0;
FLAC__uint32 channel_mask = 0;
- size_t data_bytes = 0;
+ FLAC__uint64 ds64_data_size = 0;
e->info.is_unsigned_samples = false;
e->info.is_big_endian = false;
- /*
- * lookahead[] already has "RIFFxxxxWAVE", do "fmt" chunk and beginning of "data" chunk
- */
+ if(e->format == FORMAT_WAVE64) {
+ /*
+ * lookahead[] already has "riff\x2E\x91\xCF\x11\xA5\xD6\x28\xDB", skip over remaining header
+ */
+ if(!fskip_ahead(e->fin, 16+8+16-12)) { /* riff GUID + riff size + WAVE GUID - lookahead */
+ flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping over remaining \"riff\" header\n", e->inbasefilename);
+ return false;
+ }
+ }
+ /* else lookahead[] already has "RIFFxxxxWAVE" or "RF64xxxxWAVE" */
+
while(!feof(e->fin) && !got_data_chunk) {
- char chunk_id[5] = { '\0', '\0', '\0', '\0', '\0' }; /* one extra byte for terminating NUL so we can also treat it like a C string */
- if(!read_bytes(e->fin, (FLAC__byte*)chunk_id, 4, /*eof_ok=*/true, e->inbasefilename)) {
+ /* chunk IDs are 4 bytes for WAVE/RF64, 16 for Wave64 */
+ /* for WAVE/RF64 we want the 5th char zeroed so we can treat it like a C string */
+ char chunk_id[16] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' };
+
+ if(!read_bytes(e->fin, (FLAC__byte*)chunk_id, e->format==FORMAT_WAVE64?16:4, /*eof_ok=*/true, e->inbasefilename)) {
flac__utils_printf(stderr, 1, "%s: ERROR: incomplete chunk identifier\n", e->inbasefilename);
return false;
}
if(feof(e->fin))
break;
- if(!memcmp(chunk_id, "fmt ", 4)) { /* format chunk */
+ if(e->format == FORMAT_RF64 && !memcmp(chunk_id, "ds64", 4)) { /* RF64 64-bit sizes chunk */
+ FLAC__uint32 xx, data_bytes;
+
+ if(got_ds64_chunk) {
+ flac__utils_printf(stderr, 1, "%s: ERROR: file has multiple 'ds64' chunks\n", e->inbasefilename);
+ return false;
+ }
+ if(got_fmt_chunk || got_data_chunk) {
+ flac__utils_printf(stderr, 1, "%s: ERROR: 'ds64' chunk appears after 'fmt ' or 'data' chunk\n", e->inbasefilename);
+ return false;
+ }
+
+ /* ds64 chunk size */
+ if(!read_uint32(e->fin, /*big_endian=*/false, &xx, e->inbasefilename))
+ return false;
+ data_bytes = xx;
+ if(data_bytes < 28) {
+ flac__utils_printf(stderr, 1, "%s: ERROR: non-standard 'ds64' chunk has length = %u\n", e->inbasefilename, (unsigned)data_bytes);
+ return false;
+ }
+ if(data_bytes & 1) /* should never happen, but enforce WAVE alignment rules */
+ data_bytes++;
+
+ /* RIFF 64-bit size, lo/hi */
+ if(!read_uint32(e->fin, /*big_endian=*/false, &xx, e->inbasefilename))
+ return false;
+ if(!read_uint32(e->fin, /*big_endian=*/false, &xx, e->inbasefilename))
+ return false;
+
+ /* 'data' 64-bit size */
+ if(!read_uint64(e->fin, /*big_endian=*/false, &ds64_data_size, e->inbasefilename))
+ return false;
+
+ data_bytes -= 16;
+
+ /* skip any extra data in the ds64 chunk */
+ if(!fskip_ahead(e->fin, data_bytes)) {
+ flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping over extra 'ds64' data\n", e->inbasefilename);
+ return false;
+ }
+
+ got_ds64_chunk = true;
+ }
+ else if(
+ !memcmp(chunk_id, "fmt ", 4) &&
+ (e->format!=FORMAT_WAVE64 || !memcmp(chunk_id, "fmt \xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16))
+ ) { /* format chunk */
FLAC__uint16 x;
- FLAC__uint32 xx;
+ FLAC__uint32 xx, data_bytes;
FLAC__uint16 wFormatTag; /* wFormatTag word from the 'fmt ' chunk */
- unsigned block_align;
if(got_fmt_chunk) {
flac__utils_printf(stderr, 1, "%s: ERROR: file has multiple 'fmt ' chunks\n", e->inbasefilename);
if(!read_uint32(e->fin, /*big_endian=*/false, &xx, e->inbasefilename))
return false;
data_bytes = xx;
+ if(e->format == FORMAT_WAVE64) {
+ /* other half of the size field should be 0 */
+ if(!read_uint32(e->fin, /*big_endian=*/false, &xx, e->inbasefilename))
+ return false;
+ if(xx) {
+ flac__utils_printf(stderr, 1, "%s: ERROR: freakishly large Wave64 'fmt ' chunk has length = 0x%08X%08X\n", e->inbasefilename, (unsigned)xx, (unsigned)data_bytes);
+ return false;
+ }
+ /* subtract size of header */
+ if (data_bytes < 16+8) {
+ flac__utils_printf(stderr, 1, "%s: ERROR: freakishly small Wave64 'fmt ' chunk has length = 0x%08X%08X\n", e->inbasefilename, (unsigned)xx, (unsigned)data_bytes);
+ return false;
+ }
+ data_bytes -= (16+8);
+ }
if(data_bytes < 16) {
flac__utils_printf(stderr, 1, "%s: ERROR: non-standard 'fmt ' chunk has length = %u\n", e->inbasefilename, (unsigned)data_bytes);
return false;
}
+ if(e->format != FORMAT_WAVE64) {
+ if(data_bytes & 1) /* should never happen, but enforce WAVE alignment rules */
+ data_bytes++;
+ }
+ else { /* Wave64 */
+ data_bytes = (data_bytes+7) & (~7u); /* should never happen, but enforce Wave64 alignment rules */
+ }
/* format code */
if(!read_uint16(e->fin, /*big_endian=*/false, &wFormatTag, e->inbasefilename))
/* block align */
if(!read_uint16(e->fin, /*big_endian=*/false, &x, e->inbasefilename))
return false;
- block_align = (unsigned)x;
+
/* bits per sample */
if(!read_uint16(e->fin, /*big_endian=*/false, &x, e->inbasefilename))
return false;
}
else if(
channel_mask == 0x003f || /* 6 channels: front left, front right, front center, LFE, back left, back right */
- channel_mask == 0x060f /* 6 channels: front left, front right, front center, LFE, side left, side right */
+ channel_mask == 0x060f || /* 6 channels: front left, front right, front center, LFE, side left, side right */
+ channel_mask == 0x070f || /* 7 channels: front left, front right, front center, LFE, back center, side left, side right */
+ channel_mask == 0x063f /* 8 channels: front left, front right, front center, LFE, back left, back right, side left, side right */
) {
/* to dolby order: front left, center, front right, surround left, surround right, LFE */
channel_map[1] = 2;
channel_mask == 0x0037 || /* 5 channels: front left, front right, front center, back left, back right */
channel_mask == 0x0607 || /* 5 channels: front left, front right, front center, side left, side right */
channel_mask == 0x003f || /* 6 channels: front left, front right, front center, LFE, back left, back right */
- channel_mask == 0x060f /* 6 channels: front left, front right, front center, LFE, side left, side right */
+ channel_mask == 0x060f || /* 6 channels: front left, front right, front center, LFE, side left, side right */
+ channel_mask == 0x070f || /* 7 channels: front left, front right, front center, LFE, back center, side left, side right */
+ channel_mask == 0x063f /* 8 channels: front left, front right, front center, LFE, back left, back right, side left, side right */
) {
/* keep default channel order */
}
got_fmt_chunk = true;
}
- else if(!memcmp(chunk_id, "data", 4)) { /* data chunk */
+ else if(
+ !memcmp(chunk_id, "data", 4) &&
+ (e->format!=FORMAT_WAVE64 || !memcmp(chunk_id, "data\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16))
+ ) { /* data chunk */
FLAC__uint32 xx;
+ FLAC__uint64 data_bytes;
if(!got_fmt_chunk) {
flac__utils_printf(stderr, 1, "%s: ERROR: got 'data' chunk before 'fmt' chunk\n", e->inbasefilename);
}
/* data size */
- if(!read_uint32(e->fin, /*big_endian=*/false, &xx, e->inbasefilename))
- return false;
+ if(e->format != FORMAT_WAVE64) {
+ if(!read_uint32(e->fin, /*big_endian=*/false, &xx, e->inbasefilename))
+ return false;
+ data_bytes = xx;
+ }
+ else { /* Wave64 */
+ if(!read_uint64(e->fin, /*big_endian=*/false, &data_bytes, e->inbasefilename))
+ return false;
+ /* subtract size of header */
+ if (data_bytes < 16+8) {
+ flac__utils_printf(stderr, 1, "%s: ERROR: freakishly small Wave64 'data' chunk has length = 0x00000000%08X\n", e->inbasefilename, (unsigned)data_bytes);
+ return false;
+ }
+ data_bytes -= (16+8);
+ }
+ if(e->format == FORMAT_RF64) {
+ if(!got_ds64_chunk) {
+ flac__utils_printf(stderr, 1, "%s: ERROR: RF64 file has no 'ds64' chunk before 'data' chunk\n", e->inbasefilename);
+ return false;
+ }
+ if(data_bytes == 0xffffffff)
+ data_bytes = ds64_data_size;
+ }
if(options.ignore_chunk_sizes) {
FLAC__ASSERT(!options.sector_align);
- if(xx) {
- flac__utils_printf(stderr, 1, "%s: WARNING: \"data\" chunk has non-zero size, using --ignore-chunk-sizes is probably a bad idea\n", e->inbasefilename, chunk_id);
+ if(data_bytes) {
+ flac__utils_printf(stderr, 1, "%s: WARNING: 'data' chunk has non-zero size, using --ignore-chunk-sizes is probably a bad idea\n", e->inbasefilename, chunk_id);
if(e->treat_warnings_as_errors)
return false;
}
- data_bytes = (size_t)0 - (size_t)e->info.bytes_per_wide_sample; /* max out data_bytes; we'll use EOF as signal to stop reading */
+ data_bytes = (FLAC__uint64)0 - (FLAC__uint64)e->info.bytes_per_wide_sample; /* max out data_bytes; we'll use EOF as signal to stop reading */
}
- else {
- data_bytes = xx;
- if(0 == data_bytes) {
- flac__utils_printf(stderr, 1, "%s: ERROR: 'data' chunk has size of 0\n", e->inbasefilename);
- return false;
- }
+ else if(0 == data_bytes) {
+ flac__utils_printf(stderr, 1, "%s: ERROR: 'data' chunk has size of 0\n", e->inbasefilename);
+ return false;
}
e->fmt.iff.data_bytes = data_bytes;
- e->fmt.iff.pad = (data_bytes & 1) ? true : false;
got_data_chunk = true;
break;
}
else {
FLAC__uint32 xx;
+ FLAC__uint64 skip;
if(!options.format_options.iff.foreign_metadata) {
- flac__utils_printf(stderr, 1, "%s: WARNING: skipping unknown chunk '%s' (use --keep-foreign-metadata to keep)\n", e->inbasefilename, chunk_id);
+ if(e->format != FORMAT_WAVE64)
+ flac__utils_printf(stderr, 1, "%s: WARNING: skipping unknown chunk '%s' (use --keep-foreign-metadata to keep)\n", e->inbasefilename, chunk_id);
+ else
+ flac__utils_printf(stderr, 1, "%s: WARNING: skipping unknown chunk %02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X (use --keep-foreign-metadata to keep)\n",
+ e->inbasefilename,
+ (unsigned)((const unsigned char *)chunk_id)[3],
+ (unsigned)((const unsigned char *)chunk_id)[2],
+ (unsigned)((const unsigned char *)chunk_id)[1],
+ (unsigned)((const unsigned char *)chunk_id)[0],
+ (unsigned)((const unsigned char *)chunk_id)[5],
+ (unsigned)((const unsigned char *)chunk_id)[4],
+ (unsigned)((const unsigned char *)chunk_id)[7],
+ (unsigned)((const unsigned char *)chunk_id)[6],
+ (unsigned)((const unsigned char *)chunk_id)[9],
+ (unsigned)((const unsigned char *)chunk_id)[8],
+ (unsigned)((const unsigned char *)chunk_id)[10],
+ (unsigned)((const unsigned char *)chunk_id)[11],
+ (unsigned)((const unsigned char *)chunk_id)[12],
+ (unsigned)((const unsigned char *)chunk_id)[13],
+ (unsigned)((const unsigned char *)chunk_id)[14],
+ (unsigned)((const unsigned char *)chunk_id)[15]
+ );
if(e->treat_warnings_as_errors)
return false;
}
/* chunk size */
- if(!read_uint32(e->fin, /*big_endian=*/false, &xx, e->inbasefilename))
- return false;
- else {
- unsigned long skip = xx + (xx & 1);
-
- FLAC__ASSERT(skip <= LONG_MAX);
+ if(e->format != FORMAT_WAVE64) {
+ if(!read_uint32(e->fin, /*big_endian=*/false, &xx, e->inbasefilename))
+ return false;
+ skip = xx;
+ skip += skip & 1;
+ }
+ else { /* Wave64 */
+ if(!read_uint64(e->fin, /*big_endian=*/false, &skip, e->inbasefilename))
+ return false;
+ skip = (skip+7) & (~(FLAC__uint64)7);
+ /* subtract size of header */
+ if (skip < 16+8) {
+ flac__utils_printf(stderr, 1, "%s: ERROR: freakishly small Wave64 chunk has length = 0x00000000%08X\n", e->inbasefilename, (unsigned)skip);
+ return false;
+ }
+ skip -= (16+8);
+ }
+ if(skip) {
if(!fskip_ahead(e->fin, skip)) {
flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping over chunk\n", e->inbasefilename);
return false;
static FLAC__bool get_sample_info_aiff(EncoderSession *e, encode_options_t options)
{
FLAC__bool got_comm_chunk = false, got_ssnd_chunk = false;
- unsigned sample_rate = 0, channels = 0, bps = 0, shift = 0, sample_frames = 0;
+ unsigned sample_rate = 0, channels = 0, bps = 0, shift = 0;
+ FLAC__uint64 sample_frames = 0;
FLAC__uint32 channel_mask = 0;
e->info.is_unsigned_samples = false;
FLAC__uint16 x;
FLAC__uint32 xx;
unsigned long skip;
- const FLAC__bool is_aifc = options.format == FORMAT_AIFF_C;
+ const FLAC__bool is_aifc = e->format == FORMAT_AIFF_C;
const FLAC__uint32 minimum_comm_size = (is_aifc? 22 : 18);
if(got_comm_chunk) {
return false;
channels = (unsigned)x;
if(channels > 2 && !options.channel_map_none) {
- flac__utils_printf(stderr, 1, "%s: ERROR: unsupported number channels %u for AIFF\n", e->inbasefilename, channels);
+ flac__utils_printf(stderr, 1, "%s: ERROR: unsupported number of channels %u for AIFF\n", e->inbasefilename, channels);
return false;
}
/* keep default channel order */
}
else {
- flac__utils_printf(stderr, 1, "%s: ERROR: unsupported number channels %u for AIFF\n", e->inbasefilename, channels);
+ flac__utils_printf(stderr, 1, "%s: ERROR: unsupported number of channels %u for AIFF\n", e->inbasefilename, channels);
return false;
}
}
else if(!memcmp(chunk_id, "SSND", 4) && !got_ssnd_chunk) { /* sound data chunk */
FLAC__uint32 xx;
- unsigned offset = 0, block_size = 0, data_bytes;
+ FLAC__uint64 data_bytes;
+ unsigned offset = 0;
if(!got_comm_chunk) {
flac__utils_printf(stderr, 1, "%s: ERROR: got 'SSND' chunk before 'COMM' chunk\n", e->inbasefilename);
/* SSND chunk size */
if(!read_uint32(e->fin, /*big_endian=*/true, &xx, e->inbasefilename))
return false;
+ data_bytes = xx;
if(options.ignore_chunk_sizes) {
FLAC__ASSERT(!options.sector_align);
- if(xx) {
- flac__utils_printf(stderr, 1, "%s: WARNING: \"SSND\" chunk has non-zero size, using --ignore-chunk-sizes is probably a bad idea\n", e->inbasefilename, chunk_id);
+ if(data_bytes) {
+ flac__utils_printf(stderr, 1, "%s: WARNING: 'SSND' chunk has non-zero size, using --ignore-chunk-sizes is probably a bad idea\n", e->inbasefilename, chunk_id);
if(e->treat_warnings_as_errors)
return false;
}
- data_bytes = (size_t)0 - (size_t)e->info.bytes_per_wide_sample; /* max out data_bytes; we'll use EOF as signal to stop reading */
+ data_bytes = (FLAC__uint64)0 - (FLAC__uint64)e->info.bytes_per_wide_sample; /* max out data_bytes; we'll use EOF as signal to stop reading */
+ }
+ else if(data_bytes <= 8) {
+ flac__utils_printf(stderr, 1, "%s: ERROR: 'SSND' chunk has size <= 8\n", e->inbasefilename);
+ return false;
}
else {
- data_bytes = xx;
data_bytes -= 8; /* discount the offset and block size fields */
}
- e->fmt.iff.pad = (data_bytes & 1) ? true : false;
/* offset */
if(!read_uint32(e->fin, /*big_endian=*/true, &xx, e->inbasefilename))
/* block size */
if(!read_uint32(e->fin, /*big_endian=*/true, &xx, e->inbasefilename))
return false;
- else if(xx != 0) {
- flac__utils_printf(stderr, 1, "%s: ERROR: block size is %u; must be 0\n", e->inbasefilename, (unsigned)xx);
- return false;
+ if(xx && !options.ignore_chunk_sizes)
+ data_bytes -= (xx - (data_bytes % xx));
+ if(options.ignore_chunk_sizes) {
+ if(xx) {
+ flac__utils_printf(stderr, 1, "%s: WARNING: 'SSND' chunk has non-zero blocksize, using --ignore-chunk-sizes is probably a bad idea\n", e->inbasefilename, chunk_id);
+ if(e->treat_warnings_as_errors)
+ return false;
+ }
}
- block_size = xx;
/* skip any SSND offset bytes */
if(!fskip_ahead(e->fin, offset)) {
flac__utils_printf(stderr, 1, "%s: ERROR: skipping offset in SSND chunk\n", e->inbasefilename);
return false;
}
- if(data_bytes != (sample_frames * e->info.bytes_per_wide_sample)) {
- flac__utils_printf(stderr, 1, "%s: ERROR: SSND chunk size inconsistent with sample frame count\n", e->inbasefilename);
- return false;
- }
e->fmt.iff.data_bytes = data_bytes;
return true;
}
-static FLAC__bool get_sample_info_flac(EncoderSession *e, encode_options_t options)
+static FLAC__bool get_sample_info_flac(EncoderSession *e)
{
if (!(
FLAC__stream_decoder_set_md5_checking(e->fmt.flac.decoder, false) &&
return false;
}
- if (options.format == FORMAT_OGGFLAC) {
+ if (e->format == FORMAT_OGGFLAC) {
if (FLAC__stream_decoder_init_ogg_stream(e->fmt.flac.decoder, flac_decoder_read_callback, flac_decoder_seek_callback, flac_decoder_tell_callback, flac_decoder_length_callback, flac_decoder_eof_callback, flac_decoder_write_callback, flac_decoder_metadata_callback, flac_decoder_error_callback, /*client_data=*/e) != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
flac__utils_printf(stderr, 1, "%s: ERROR: initializing decoder for Ogg FLAC input, state = %s\n", e->inbasefilename, FLAC__stream_decoder_get_resolved_state_string(e->fmt.flac.decoder));
return false;
/*
* public routines
*/
-int flac__encode_file(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, encode_options_t options)
+int flac__encode_file(FILE *infile, FLAC__off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, encode_options_t options)
{
EncoderSession encoder_session;
size_t channel_map[FLAC__MAX_CHANNELS];
}
/* read foreign metadata if requested */
- if(
- (options.format == FORMAT_WAVE || options.format == FORMAT_AIFF || options.format == FORMAT_AIFF_C) &&
- options.format_options.iff.foreign_metadata
- ) {
+ if(EncoderSession_format_is_iff(&encoder_session) && options.format_options.iff.foreign_metadata) {
const char *error;
if(!(
- options.format == FORMAT_WAVE?
+ options.format == FORMAT_WAVE || options.format == FORMAT_RF64?
flac__foreign_metadata_read_from_wave(options.format_options.iff.foreign_metadata, infilename, &error) :
+ options.format == FORMAT_WAVE64?
+ flac__foreign_metadata_read_from_wave64(options.format_options.iff.foreign_metadata, infilename, &error) :
flac__foreign_metadata_read_from_aiff(options.format_options.iff.foreign_metadata, infilename, &error)
)) {
flac__utils_printf(stderr, 1, "%s: ERROR reading foreign metadata: %s\n", encoder_session.inbasefilename, error);
return EncoderSession_finish_error(&encoder_session);
break;
case FORMAT_WAVE:
+ case FORMAT_WAVE64:
+ case FORMAT_RF64:
if(!get_sample_info_wave(&encoder_session, options))
return EncoderSession_finish_error(&encoder_session);
break;
flac__utils_printf(stderr, 1, "%s: ERROR: creating decoder for FLAC input\n", encoder_session.inbasefilename);
return EncoderSession_finish_error(&encoder_session);
}
- if(!get_sample_info_flac(&encoder_session, options))
+ if(!get_sample_info_flac(&encoder_session))
return EncoderSession_finish_error(&encoder_session);
break;
default:
total_samples_in_input = (FLAC__uint64)infilesize / encoder_session.info.bytes_per_wide_sample + *options.align_reservoir_samples;
break;
case FORMAT_WAVE:
+ case FORMAT_WAVE64:
+ case FORMAT_RF64:
case FORMAT_AIFF:
case FORMAT_AIFF_C:
+ /* truncation in the division removes any padding byte that was counted in encoder_session.fmt.iff.data_bytes */
total_samples_in_input = encoder_session.fmt.iff.data_bytes / encoder_session.info.bytes_per_wide_sample + *options.align_reservoir_samples;
break;
case FORMAT_FLAC:
/* adjust encoding parameters based on skip and until values */
switch(options.format) {
case FORMAT_RAW:
- infilesize -= (off_t)skip * encoder_session.info.bytes_per_wide_sample;
+ infilesize -= (FLAC__off_t)skip * encoder_session.info.bytes_per_wide_sample;
encoder_session.total_samples_to_encode = total_samples_in_input - skip;
break;
case FORMAT_WAVE:
+ case FORMAT_WAVE64:
+ case FORMAT_RF64:
case FORMAT_AIFF:
case FORMAT_AIFF_C:
- encoder_session.fmt.iff.data_bytes -= (unsigned)skip * encoder_session.info.bytes_per_wide_sample; /*@@@ WATCHOUT: 4GB limit */
+ encoder_session.fmt.iff.data_bytes -= skip * encoder_session.info.bytes_per_wide_sample;
if(options.ignore_chunk_sizes) {
encoder_session.total_samples_to_encode = 0;
flac__utils_printf(stderr, 2, "(No runtime statistics possible; please wait for encoding to finish...)\n");
FLAC__ASSERT(total_samples_in_input > 0);
FLAC__ASSERT(!options.sector_align);
if(options.format == FORMAT_RAW)
- infilesize -= (off_t)trim * encoder_session.info.bytes_per_wide_sample;
- else if(options.format == FORMAT_WAVE || options.format == FORMAT_AIFF || options.format == FORMAT_AIFF_C)
- encoder_session.fmt.iff.data_bytes -= (unsigned)trim * encoder_session.info.bytes_per_wide_sample;
+ infilesize -= (FLAC__off_t)trim * encoder_session.info.bytes_per_wide_sample;
+ else if(EncoderSession_format_is_iff(&encoder_session))
+ encoder_session.fmt.iff.data_bytes -= trim * encoder_session.info.bytes_per_wide_sample;
encoder_session.total_samples_to_encode -= trim;
}
if(options.sector_align && (options.format != FORMAT_RAW || infilesize >=0)) { /* for RAW, need to know the filesize */
encoder_session.unencoded_size = encoder_session.total_samples_to_encode * encoder_session.info.bytes_per_wide_sample;
break;
case FORMAT_WAVE:
- /* +44 for the size of the WAV headers; this is just an estimate for the progress indicator and doesn't need to be exact */
+ /* +44 for the size of the WAVE headers; this is just an estimate for the progress indicator and doesn't need to be exact */
encoder_session.unencoded_size = encoder_session.total_samples_to_encode * encoder_session.info.bytes_per_wide_sample + 44;
break;
+ case FORMAT_WAVE64:
+ /* +44 for the size of the WAVE headers; this is just an estimate for the progress indicator and doesn't need to be exact */
+ encoder_session.unencoded_size = encoder_session.total_samples_to_encode * encoder_session.info.bytes_per_wide_sample + 104;
+ break;
+ case FORMAT_RF64:
+ /* +72 for the size of the RF64 headers; this is just an estimate for the progress indicator and doesn't need to be exact */
+ encoder_session.unencoded_size = encoder_session.total_samples_to_encode * encoder_session.info.bytes_per_wide_sample + 80;
+ break;
case FORMAT_AIFF:
case FORMAT_AIFF_C:
- /* +54 for the size of the WAV headers; this is just an estimate for the progress indicator and doesn't need to be exact */
+ /* +54 for the size of the AIFF headers; this is just an estimate for the progress indicator and doesn't need to be exact */
encoder_session.unencoded_size = encoder_session.total_samples_to_encode * encoder_session.info.bytes_per_wide_sample + 54;
break;
case FORMAT_FLAC:
}
break;
case FORMAT_WAVE:
+ case FORMAT_WAVE64:
+ case FORMAT_RF64:
case FORMAT_AIFF:
case FORMAT_AIFF_C:
if(!fskip_ahead(encoder_session.fin, skip * encoder_session.info.bytes_per_wide_sample)) {
*options.align_reservoir_samples = align_remainder;
if(options.format == FORMAT_RAW) {
FLAC__ASSERT(infilesize >= 0);
- infilesize -= (off_t)((*options.align_reservoir_samples) * encoder_session.info.bytes_per_wide_sample);
+ infilesize -= (FLAC__off_t)((*options.align_reservoir_samples) * encoder_session.info.bytes_per_wide_sample);
FLAC__ASSERT(infilesize >= 0);
}
- else if(options.format == FORMAT_WAVE || options.format == FORMAT_AIFF || options.format == FORMAT_AIFF_C)
+ else if(EncoderSession_format_is_iff(&encoder_session))
encoder_session.fmt.iff.data_bytes -= (*options.align_reservoir_samples) * encoder_session.info.bytes_per_wide_sample;
}
}
return EncoderSession_finish_error(&encoder_session);
}
else if(feof(infile)) {
- flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written);
+ flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %" PRIu64 " samples, got %" PRIu64 " samples\n", encoder_session.inbasefilename, encoder_session.total_samples_to_encode, encoder_session.samples_written);
if(encoder_session.treat_warnings_as_errors)
return EncoderSession_finish_error(&encoder_session);
total_input_bytes_read = max_input_bytes;
}
break;
case FORMAT_WAVE:
+ case FORMAT_WAVE64:
+ case FORMAT_RF64:
case FORMAT_AIFF:
case FORMAT_AIFF_C:
while(encoder_session.fmt.iff.data_bytes > 0) {
- size_t bytes_read = fread(ucbuffer_, sizeof(unsigned char), min(encoder_session.fmt.iff.data_bytes, CHUNK_OF_SAMPLES * encoder_session.info.bytes_per_wide_sample), infile);
+ const size_t bytes_to_read = (size_t)min(
+ encoder_session.fmt.iff.data_bytes,
+ (FLAC__uint64)CHUNK_OF_SAMPLES * (FLAC__uint64)encoder_session.info.bytes_per_wide_sample
+ );
+ size_t bytes_read = fread(ucbuffer_, sizeof(unsigned char), bytes_to_read, infile);
if(bytes_read == 0) {
if(ferror(infile)) {
flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename);
}
else if(feof(infile)) {
if(options.ignore_chunk_sizes) {
- flac__utils_printf(stderr, 1, "%s: INFO: hit EOF with --ignore-chunk-sizes, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.samples_written);
+ flac__utils_printf(stderr, 1, "%s: INFO: hit EOF with --ignore-chunk-sizes, got %" PRIu64 " samples\n", encoder_session.inbasefilename, encoder_session.samples_written);
}
else {
- flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written);
+ flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %" PRIu64 " samples, got %" PRIu64 " samples\n", encoder_session.inbasefilename, encoder_session.total_samples_to_encode, encoder_session.samples_written);
if(encoder_session.treat_warnings_as_errors)
return EncoderSession_finish_error(&encoder_session);
}
return EncoderSession_finish_error(&encoder_session);
}
else if(bytes_read != (*options.align_reservoir_samples) * encoder_session.info.bytes_per_wide_sample) {
- flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)bytes_read, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written);
+ flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; read %" PRIu64 " bytes; expected %" PRIu64 " samples, got %" PRIu64 " samples\n", encoder_session.inbasefilename, bytes_read, encoder_session.total_samples_to_encode, encoder_session.samples_written);
if(encoder_session.treat_warnings_as_errors)
return EncoderSession_finish_error(&encoder_session);
}
&encoder_session,
info_align_carry,
info_align_zero,
- (options.format == FORMAT_WAVE || options.format == FORMAT_AIFF || options.format == FORMAT_AIFF_C)? options.format_options.iff.foreign_metadata : 0
+ EncoderSession_format_is_iff(&encoder_session)? options.format_options.iff.foreign_metadata : 0
);
}
-FLAC__bool EncoderSession_construct(EncoderSession *e, encode_options_t options, off_t infilesize, FILE *infile, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length)
+FLAC__bool EncoderSession_construct(EncoderSession *e, encode_options_t options, FLAC__off_t infilesize, FILE *infile, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length)
{
unsigned i;
FLAC__uint32 test = 1;
case FORMAT_RAW:
break;
case FORMAT_WAVE:
+ case FORMAT_WAVE64:
+ case FORMAT_RF64:
case FORMAT_AIFF:
case FORMAT_AIFF_C:
e->fmt.iff.data_bytes = 0;
- e->fmt.iff.pad = 0;
break;
case FORMAT_FLAC:
case FORMAT_OGGFLAC:
const unsigned channels = e->info.channels;
const unsigned bps = e->info.bits_per_sample - e->info.shift;
const unsigned sample_rate = e->info.sample_rate;
- FLACDecoderData *flac_decoder_data = (options.format == FORMAT_FLAC || options.format == FORMAT_OGGFLAC)? &e->fmt.flac.client_data : 0;
+ FLACDecoderData *flac_decoder_data = (e->format == FORMAT_FLAC || e->format == FORMAT_OGGFLAC)? &e->fmt.flac.client_data : 0;
FLAC__StreamMetadata padding;
FLAC__StreamMetadata **metadata = 0;
static_metadata_t static_metadata;
- unsigned num_metadata = 0, i;
+ unsigned num_metadata = 0, ic;
FLAC__StreamEncoderInitStatus init_status;
const FLAC__bool is_cdda = (channels == 1 || channels == 2) && (bps == 16) && (sample_rate == 44100);
char apodizations[2000];
}
}
- if(!parse_cuesheet(&static_metadata.cuesheet, options.cuesheet_filename, e->inbasefilename, is_cdda, e->total_samples_to_encode, e->treat_warnings_as_errors))
+ if(!parse_cuesheet(&static_metadata.cuesheet, options.cuesheet_filename, e->inbasefilename, sample_rate, is_cdda, e->total_samples_to_encode, e->treat_warnings_as_errors))
return false;
if(!convert_to_seek_table_template(options.requested_seek_points, options.num_requested_seek_points, options.cued_seekpoints? static_metadata.cuesheet : 0, e)) {
* metadata as the basis for the encoded file
*/
{
+ unsigned i;
/*
* first handle pictures: simple append any --pictures
* specified.
* we're not encoding from FLAC so we will build the metadata
* from scratch
*/
- const foreign_metadata_t *foreign_metadata = (options.format == FORMAT_WAVE || options.format == FORMAT_AIFF || options.format == FORMAT_AIFF_C)? options.format_options.iff.foreign_metadata : 0;
+ const foreign_metadata_t *foreign_metadata = EncoderSession_format_is_iff(e)? options.format_options.iff.foreign_metadata : 0;
+ unsigned i;
if(e->seek_table_template->data.seek_table.num_points > 0) {
e->seek_table_template->is_last = false; /* the encoder will set this for us */
}
static_metadata_append(&static_metadata, p, /*needs_delete=*/true);
static_metadata.metadata[static_metadata.num_metadata-1]->length = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8 + foreign_metadata->blocks[i].size;
-/*fprintf(stderr,"@@@@@@ add PADDING=%u\n",static_metadata.metadata[static_metadata.num_metadata-1]->length);*/
}
}
if(options.padding != 0) {
FLAC__stream_encoder_set_channels(e->encoder, channels);
FLAC__stream_encoder_set_bits_per_sample(e->encoder, bps);
FLAC__stream_encoder_set_sample_rate(e->encoder, sample_rate);
- for(i = 0; i < options.num_compression_settings; i++) {
- switch(options.compression_settings[i].type) {
+ for(ic = 0; ic < options.num_compression_settings; ic++) {
+ switch(options.compression_settings[ic].type) {
case CST_BLOCKSIZE:
- FLAC__stream_encoder_set_blocksize(e->encoder, options.compression_settings[i].value.t_unsigned);
+ FLAC__stream_encoder_set_blocksize(e->encoder, options.compression_settings[ic].value.t_unsigned);
break;
case CST_COMPRESSION_LEVEL:
- FLAC__stream_encoder_set_compression_level(e->encoder, options.compression_settings[i].value.t_unsigned);
+ FLAC__stream_encoder_set_compression_level(e->encoder, options.compression_settings[ic].value.t_unsigned);
apodizations[0] = '\0';
break;
case CST_DO_MID_SIDE:
- FLAC__stream_encoder_set_do_mid_side_stereo(e->encoder, options.compression_settings[i].value.t_bool);
+ FLAC__stream_encoder_set_do_mid_side_stereo(e->encoder, options.compression_settings[ic].value.t_bool);
break;
case CST_LOOSE_MID_SIDE:
- FLAC__stream_encoder_set_loose_mid_side_stereo(e->encoder, options.compression_settings[i].value.t_bool);
+ FLAC__stream_encoder_set_loose_mid_side_stereo(e->encoder, options.compression_settings[ic].value.t_bool);
break;
case CST_APODIZATION:
- if(strlen(apodizations)+strlen(options.compression_settings[i].value.t_string)+2 >= sizeof(apodizations)) {
+ if(strlen(apodizations)+strlen(options.compression_settings[ic].value.t_string)+2 >= sizeof(apodizations)) {
flac__utils_printf(stderr, 1, "%s: ERROR: too many apodization functions requested\n", e->inbasefilename);
static_metadata_clear(&static_metadata);
return false;
}
else {
- strcat(apodizations, options.compression_settings[i].value.t_string);
- strcat(apodizations, ";");
+ safe_strncat(apodizations, options.compression_settings[ic].value.t_string, sizeof(apodizations));
+ safe_strncat(apodizations, ";", sizeof(apodizations));
}
break;
case CST_MAX_LPC_ORDER:
- FLAC__stream_encoder_set_max_lpc_order(e->encoder, options.compression_settings[i].value.t_unsigned);
+ FLAC__stream_encoder_set_max_lpc_order(e->encoder, options.compression_settings[ic].value.t_unsigned);
break;
case CST_QLP_COEFF_PRECISION:
- FLAC__stream_encoder_set_qlp_coeff_precision(e->encoder, options.compression_settings[i].value.t_unsigned);
+ FLAC__stream_encoder_set_qlp_coeff_precision(e->encoder, options.compression_settings[ic].value.t_unsigned);
break;
case CST_DO_QLP_COEFF_PREC_SEARCH:
- FLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder, options.compression_settings[i].value.t_bool);
+ FLAC__stream_encoder_set_do_qlp_coeff_prec_search(e->encoder, options.compression_settings[ic].value.t_bool);
break;
case CST_DO_ESCAPE_CODING:
- FLAC__stream_encoder_set_do_escape_coding(e->encoder, options.compression_settings[i].value.t_bool);
+ FLAC__stream_encoder_set_do_escape_coding(e->encoder, options.compression_settings[ic].value.t_bool);
break;
case CST_DO_EXHAUSTIVE_MODEL_SEARCH:
- FLAC__stream_encoder_set_do_exhaustive_model_search(e->encoder, options.compression_settings[i].value.t_bool);
+ FLAC__stream_encoder_set_do_exhaustive_model_search(e->encoder, options.compression_settings[ic].value.t_bool);
break;
case CST_MIN_RESIDUAL_PARTITION_ORDER:
- FLAC__stream_encoder_set_min_residual_partition_order(e->encoder, options.compression_settings[i].value.t_unsigned);
+ FLAC__stream_encoder_set_min_residual_partition_order(e->encoder, options.compression_settings[ic].value.t_unsigned);
break;
case CST_MAX_RESIDUAL_PARTITION_ORDER:
- FLAC__stream_encoder_set_max_residual_partition_order(e->encoder, options.compression_settings[i].value.t_unsigned);
+ FLAC__stream_encoder_set_max_residual_partition_order(e->encoder, options.compression_settings[ic].value.t_unsigned);
break;
case CST_RICE_PARAMETER_SEARCH_DIST:
- FLAC__stream_encoder_set_rice_parameter_search_dist(e->encoder, options.compression_settings[i].value.t_unsigned);
+ FLAC__stream_encoder_set_rice_parameter_search_dist(e->encoder, options.compression_settings[ic].value.t_unsigned);
break;
}
}
return FLAC__stream_encoder_process(e->encoder, buffer, samples);
}
+FLAC__bool EncoderSession_format_is_iff(const EncoderSession *e)
+{
+ return
+ e->format == FORMAT_WAVE ||
+ e->format == FORMAT_WAVE64 ||
+ e->format == FORMAT_RF64 ||
+ e->format == FORMAT_AIFF ||
+ e->format == FORMAT_AIFF_C;
+}
+
FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int num_requested_seek_points, FLAC__StreamMetadata *cuesheet, EncoderSession *e)
{
const FLAC__bool only_placeholders = e->is_stdout;
EncoderSession *e = (EncoderSession*)client_data;
(void)decoder;
- if(fseeko(e->fin, (off_t)absolute_byte_offset, SEEK_SET) < 0)
+ if(fseeko(e->fin, (FLAC__off_t)absolute_byte_offset, SEEK_SET) < 0)
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
else
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
FLAC__StreamDecoderTellStatus flac_decoder_tell_callback(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
{
EncoderSession *e = (EncoderSession*)client_data;
- off_t pos;
+ FLAC__off_t pos;
(void)decoder;
if((pos = ftello(e->fin)) < 0)
data->fatal_error = true;
}
-FLAC__bool parse_cuesheet(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset, FLAC__bool treat_warnings_as_errors)
+FLAC__bool parse_cuesheet(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, unsigned sample_rate, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset, FLAC__bool treat_warnings_as_errors)
{
FILE *f;
unsigned last_line_read;
return false;
}
- *cuesheet = grabbag__cuesheet_parse(f, &error_message, &last_line_read, is_cdda, lead_out_offset);
+ *cuesheet = grabbag__cuesheet_parse(f, &error_message, &last_line_read, sample_rate, is_cdda, lead_out_offset);
fclose(f);
FLAC__ASSERT(encoder_session->total_samples_to_encode > 0);
if(samples_written == encoder_session->total_samples_to_encode) {
- flac__utils_printf(stderr, 2, "\r%s:%s wrote %u bytes, ratio=",
+ flac__utils_printf(stderr, 2, "\r%s:%s wrote %" PRIu64 " bytes, ratio=",
encoder_session->inbasefilename,
encoder_session->verify? " Verify OK," : "",
- (unsigned)encoder_session->bytes_written
+ encoder_session->bytes_written
);
}
else {
FLAC__stream_encoder_get_verify_decoder_error_stats(e->encoder, &absolute_sample, &frame_number, &channel, &sample, &expected, &got);
flac__utils_printf(stderr, 1, "%s: ERROR: mismatch in decoded data, verify FAILED!\n", e->inbasefilename);
- flac__utils_printf(stderr, 1, " Absolute sample=%u, frame=%u, channel=%u, sample=%u, expected %d, got %d\n", (unsigned)absolute_sample, frame_number, channel, sample, expected, got);
+ flac__utils_printf(stderr, 1, " Absolute sample=%" PRIu64 ", frame=%u, channel=%u, sample=%u, expected %d, got %d\n", absolute_sample, frame_number, channel, sample, expected, got);
flac__utils_printf(stderr, 1, " In all known cases, verify errors are caused by hardware problems,\n");
flac__utils_printf(stderr, 1, " usually overclocking or bad RAM. Delete %s\n", e->outfilename);
flac__utils_printf(stderr, 1, " and repeat the flac command exactly as before. If it does not give a\n");
return true;
}
+FLAC__bool read_uint64(FILE *f, FLAC__bool big_endian, FLAC__uint64 *val, const char *fn)
+{
+ if(!read_bytes(f, (FLAC__byte*)val, 8, /*eof_ok=*/false, fn))
+ return false;
+ if(is_big_endian_host_ != big_endian) {
+ FLAC__byte tmp, *b = (FLAC__byte*)val;
+ tmp = b[7]; b[7] = b[0]; b[0] = tmp;
+ tmp = b[6]; b[6] = b[1]; b[1] = tmp;
+ tmp = b[5]; b[5] = b[2]; b[2] = tmp;
+ tmp = b[4]; b[4] = b[3]; b[3] = tmp;
+ }
+ return true;
+}
+
FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, const char *fn)
/* Read an IEEE 754 80-bit (aka SANE) extended floating point value from 'f',
* convert it into an integral value and store in 'val'. Return false if only
FLAC__bool fskip_ahead(FILE *f, FLAC__uint64 offset)
{
static unsigned char dump[8192];
+ struct stat stb;
-#ifdef _MSC_VER
- if(f == stdin) {
- /* MS' stdio impl can't even seek forward on stdin, have to use pure non-fseek() version: */
- while(offset > 0) {
- const long need = (long)min(offset, sizeof(dump));
- if((long)fread(dump, 1, need, f) < need)
- return false;
- offset -= need;
- }
- }
- else
-#endif
+ if(fstat(fileno(f), &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFREG)
{
- while(offset > 0) {
- long need = (long)min(offset, LONG_MAX);
- if(fseeko(f, need, SEEK_CUR) < 0) {
- need = (long)min(offset, sizeof(dump));
- if((long)fread(dump, 1, need, f) < need)
- return false;
- }
- offset -= need;
- }
+ if(fseeko(f, offset, SEEK_CUR) == 0)
+ return true;
+ }
+ while(offset > 0) {
+ const long need = (long)min(offset, sizeof(dump));
+ if((long)fread(dump, 1, need, f) < need)
+ return false;
+ offset -= need;
}
return true;
}