about summary refs log tree commit
diff options
context:
space:
mode:
authorjcoalson <jcoalson>2006-08-28 03:42:10 +0000
committerjcoalson <jcoalson>2006-08-28 03:42:10 +0000
commit116f102b9984ffd5bbd30e3e5fdbfd12a5d368cf (patch)
tree449060da25ab1ba7c0373b6e4d40fd64202deb48
parent68cf0fac9175dc06914fa841f2002bd1e1f60c94 (diff)
downloadflac-arm-1.1.3-116f102b9984ffd5bbd30e3e5fdbfd12a5d368cf.tar.gz
add support for encoding from FLAC to FLAC while preserving metadata
-rw-r--r--doc/html/changelog.html2
-rw-r--r--doc/html/documentation.html6
-rw-r--r--man/flac.sgml5
-rw-r--r--src/flac/encode.c534
-rw-r--r--src/flac/encode.h7
-rw-r--r--src/flac/main.c119
-rw-r--r--test/Makefile.am2
-rw-r--r--test/Makefile.lite2
-rw-r--r--test/flac-to-flac-metadata-test-files/Makefile.am44
-rw-r--r--test/flac-to-flac-metadata-test-files/case00a-expect.meta84
-rw-r--r--test/flac-to-flac-metadata-test-files/case01a-expect.meta79
-rw-r--r--test/flac-to-flac-metadata-test-files/case01b-expect.meta75
-rw-r--r--test/flac-to-flac-metadata-test-files/case01c-expect.meta79
-rw-r--r--test/flac-to-flac-metadata-test-files/case01d-expect.meta79
-rw-r--r--test/flac-to-flac-metadata-test-files/case01e-expect.meta79
-rw-r--r--test/flac-to-flac-metadata-test-files/case02a-expect.meta73
-rw-r--r--test/flac-to-flac-metadata-test-files/case02b-expect.meta74
-rw-r--r--test/flac-to-flac-metadata-test-files/case02c-expect.meta79
-rw-r--r--test/flac-to-flac-metadata-test-files/case03a-expect.meta84
-rw-r--r--test/flac-to-flac-metadata-test-files/case03b-expect.meta84
-rw-r--r--test/flac-to-flac-metadata-test-files/case03c-expect.meta40
-rw-r--r--test/flac-to-flac-metadata-test-files/case04a-expect.meta26
-rw-r--r--test/flac-to-flac-metadata-test-files/case04b-expect.meta36
-rw-r--r--test/flac-to-flac-metadata-test-files/case04c-expect.meta31
-rw-r--r--test/flac-to-flac-metadata-test-files/case04d-expect.meta60
-rw-r--r--test/flac-to-flac-metadata-test-files/case04e-expect.meta70
-rw-r--r--test/flac-to-flac-metadata-test-files/input-SCPAP.flacbin0 -> 4021 bytes
-rw-r--r--test/flac-to-flac-metadata-test-files/input-SCVA.flacbin0 -> 1015 bytes
-rw-r--r--test/flac-to-flac-metadata-test-files/input-SCVAUP.flacbin0 -> 4224 bytes
-rw-r--r--test/flac-to-flac-metadata-test-files/input-SCVPAP.flacbin0 -> 4228 bytes
-rw-r--r--test/flac-to-flac-metadata-test-files/input-SVAUP.flacbin0 -> 3680 bytes
-rw-r--r--test/flac-to-flac-metadata-test-files/input-VA.flacbin0 -> 287 bytes
-rw-r--r--test/flac-to-flac-metadata-test-files/input0.cue7
-rwxr-xr-xtest/test_flac.sh496
34 files changed, 2107 insertions, 249 deletions
diff --git a/doc/html/changelog.html b/doc/html/changelog.html
index d465a931..edfaa155 100644
--- a/doc/html/changelog.html
+++ b/doc/html/changelog.html
@@ -67,6 +67,7 @@
                                 <ul>
                                         <li>Large file (&gt;2GB) support everywhere</li>
                                         <li>Much better recovery for corrupted files</li>
+                                        <li><span class="commandname">flac</span> now supports FLAC as input to the encoder (i.e. can re-encode FLAC to FLAC) and preserve all the metadata like tags, etc.</li>
                                 </ul>
                         </li>
                         <li>
@@ -85,6 +86,7 @@
                                 flac:
                                 <ul>
                                         <li>Improved the <a href="documentation.html#flac_options_decode_through_errors"><span class="argument">-F</span></a> to allow decoding of FLAC files whose metadata is corrupted, and other kinds of corruption.</li>
+                                        <li>Encoder can now take FLAC as input.  The output FLAC file will have all the same metadata as the original unless overridden with options on the command line.</li>
                                         <li>Added a new option <a href="documentation.html#flac_options_tag_from_file"><span class="argument">--tag-from-file</span></a> for setting a tag from file (e.g. for importing a cuesheet as a tag).</li>
                                         <li>Added support for encoding from non-compressed AIFF-C (<a href="https://sourceforge.net/tracker/?func=detail&amp;atid=113478&amp;aid=1090933&amp;group_id=13478">SF #1090933</a>).</li>
                                         <li>Importing of non-CDDA-compliant cuesheets now only issues a warning, not an error (see <a href="http://www.hydrogenaudio.org/forums/index.php?showtopic=31282">here</a>).</li>
diff --git a/doc/html/documentation.html b/doc/html/documentation.html
index 48e725b5..835ce61a 100644
--- a/doc/html/documentation.html
+++ b/doc/html/documentation.html
@@ -142,9 +142,9 @@
         </div>
         <div class="box_header"></div>
         <div class="box_body">
-                <span class="commandname">flac</span> is the command-line file encoder/decoder.  The input to the encoder and the output to the decoder must either be RIFF WAVE format, AIFF, or raw interleaved sample data.  <span class="commandname">flac</span> only supports linear PCM samples (in other words, no A-LAW, uLAW, etc.).  Another restriction (hopefully short-term) is that the input must be 8, 16, or 24 bits per sample.  This is not a limitation of the FLAC format, just the reference encoder/decoder.
+                <span class="commandname">flac</span> is the command-line file encoder/decoder.  The encoder currently supports as input RIFF WAVE, AIFF, or FLAC format, or raw interleaved samples.  The decoder currently can output to RIFF WAVE or AIFF format, or raw interleaved samples.  <span class="commandname">flac</span> only supports linear PCM samples (in other words, no A-LAW, uLAW, etc.).  Another restriction (hopefully short-term) is that the input must be 8, 16, or 24 bits per sample.  This is not a limitation of the FLAC format, just the reference encoder/decoder.
                 <br /><br />
-                <span class="commandname">flac</span> assumes that files ending in ".wav" or that have the RIFF WAVE header present are WAVE files, and files ending in ".aif" or ".aiff" or have the AIFF header present are in AIFF files.  This may be overridden with a command-line option.  It also assumes that files ending in ".ogg" are Ogg FLAC files.  Other than this, <span class="commandname">flac</span> makes no assumptions about file extensions, though the convention is that FLAC files have the extension ".flac" (or ".fla" on ancient file systems like FAT-16).
+                <span class="commandname">flac</span> assumes that files ending in ".wav" or that have the RIFF WAVE header present are WAVE files, files ending in ".aif" or ".aiff" or have the AIFF header present are AIFF files, and files ending in ".flac" or have the FLAC header present are FLAC files.  This assumption may be overridden with a command-line option.  It also assumes that files ending in ".ogg" are Ogg FLAC files.  Other than this, <span class="commandname">flac</span> makes no assumptions about file extensions, though the convention is that FLAC files have the extension ".flac" (or ".fla" on ancient file systems like FAT-16).
                 <br /><br />
                 Before going into the full command-line description, a few other things help to sort it out: 1) <span class="commandname">flac</span> encodes by default, so you must use <b>-d</b> to decode; 2) the options <span class="argument">-0</span> .. <span class="argument">-8</span> (or <span class="argument">--fast</span> and <span class="argument">--best</span>) that control the compression level actually are just synonyms for different groups of specific encoding options (described later) and you can get the same effect by using the same options; 3) <span class="commandname">flac</span> behaves similarly to gzip in the way it handles input and output files.
                 <br /><br />
@@ -197,6 +197,8 @@
                 <br /><br />
                 In test mode, <span class="commandname">flac</span> acts just like in decode mode, except no output file is written.  Both decode and test modes detect errors in the stream, but they also detect when the MD5 signature of the decoded audio does not match the stored MD5 signature, even when the bitstream is valid.
                 <br /><br />
+                <span class="commandname">flac</span> can also re-encode FLAC files.  In other words, you can specify a FLAC file as an input to the encoder and it will decoder it and re-encode it according to the options you specify.  It will also preserve all the metadata unless you override it with other options (e.g. specifying new tags, seekpoints, cuesheet, padding, etc.).
+                <br /><br />
 
                 <table width="100%" border="0" cellspacing="0" cellpadding="0" bgcolor="#EEEED4"><tr><td>
                 <table width="100%" border="1" bgcolor="#EEEED4">
diff --git a/man/flac.sgml b/man/flac.sgml
index 44c587e6..b63d47b8 100644
--- a/man/flac.sgml
+++ b/man/flac.sgml
@@ -50,6 +50,7 @@
                <arg><replaceable>infile.wav</replaceable></arg>
                <arg><replaceable>infile.aiff</replaceable></arg>
                <arg><replaceable>infile.raw</replaceable></arg>
+               <arg><replaceable>infile.flac</replaceable></arg>
                <arg>-</arg>
             </group>
           </cmdsynopsis>
@@ -71,10 +72,6 @@
              encoding, decoding, testing and analyzing FLAC streams.
           </para>
 
-          <para>This manual page was originally written for the &debian;
-            distribution because the original program did not have a
-            manual page.</para>
-
         </refsect1>
         <refsect1>
           <title>OPTIONS</title>
diff --git a/src/flac/encode.c b/src/flac/encode.c
index 6528c7a4..8bafa5bd 100644
--- a/src/flac/encode.c
+++ b/src/flac/encode.c
@@ -103,6 +103,19 @@ typedef struct {
         FLAC__StreamMetadata *seek_table_template;
 } EncoderSession;
 
+/* this is data attached to the FLAC decoder when encoding from a FLAC file */
+typedef struct {
+        EncoderSession *encoder_session;
+        off_t filesize;
+        const FLAC__byte *lookahead;
+        unsigned lookahead_length;
+        size_t num_metadata_blocks;
+        FLAC__StreamMetadata *metadata_blocks[1024]; /*@@@ BAD MAGIC number */
+        FLAC__uint64 samples_left_to_process;
+        FLAC__bool fatal_error;
+} FLACDecoderData;
+
+const int FLAC_ENCODE__DEFAULT_PADDING = 4096;
 
 static FLAC__bool is_big_endian_host_;
 
@@ -140,7 +153,7 @@ static FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg
 static void EncoderSession_destroy(EncoderSession *e);
 static int EncoderSession_finish_ok(EncoderSession *e, int info_align_carry, int info_align_zero);
 static int EncoderSession_finish_error(EncoderSession *e);
-static FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate);
+static FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate, FLACDecoderData *flac_decoder_data);
 static FLAC__bool EncoderSession_process(EncoderSession *e, const FLAC__int32 * const buffer[], unsigned samples);
 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);
@@ -153,7 +166,15 @@ static void ogg_file_encoder_progress_callback(const OggFLAC__FileEncoder *encod
 static FLAC__StreamEncoderWriteStatus flac_stream_encoder_write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
 static void flac_stream_encoder_metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
 static void flac_file_encoder_progress_callback(const FLAC__FileEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, 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);
+static FLAC__SeekableStreamDecoderReadStatus flac_decoder_read_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
+static FLAC__SeekableStreamDecoderSeekStatus flac_decoder_seek_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+static FLAC__SeekableStreamDecoderTellStatus flac_decoder_tell_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+static FLAC__SeekableStreamDecoderLengthStatus flac_decoder_length_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data);
+static FLAC__bool flac_decoder_eof_callback(const FLAC__SeekableStreamDecoder *decoder, void *client_data);
+static FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
+static void flac_decoder_metadata_callback(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
+static void flac_decoder_error_callback(const FLAC__SeekableStreamDecoder *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);
 static void print_stats(const EncoderSession *encoder_session);
 static void print_error_with_state(const EncoderSession *e, const char *message);
 static void print_verify_error(EncoderSession *e);
@@ -386,7 +407,7 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con
                         /* +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*bytes_per_frame+54;
 
-                        if(!EncoderSession_init_encoder(&encoder_session, options.common, channels, bps, sample_rate))
+                        if(!EncoderSession_init_encoder(&encoder_session, options.common, channels, bps, sample_rate, /*flac_decoder_data=*/0))
                                 return EncoderSession_finish_error(&encoder_session);
 
                         /* first do any samples in the reservoir */
@@ -714,7 +735,7 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con
                         /* +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_session.unencoded_size = encoder_session.total_samples_to_encode * bytes_per_wide_sample + 44;
 
-                        if(!EncoderSession_init_encoder(&encoder_session, options.common, channels, bps, sample_rate))
+                        if(!EncoderSession_init_encoder(&encoder_session, options.common, channels, bps, sample_rate, /*flac_decoder_data=*/0))
                                 return EncoderSession_finish_error(&encoder_session);
 
                         /*
@@ -963,7 +984,7 @@ int flac__encode_raw(FILE *infile, off_t infilesize, const char *infilename, con
                 }
         }
 
-        if(!EncoderSession_init_encoder(&encoder_session, options.common, options.channels, options.bps, options.sample_rate))
+        if(!EncoderSession_init_encoder(&encoder_session, options.common, options.channels, options.bps, options.sample_rate, /*flac_decoder_data=*/0))
                 return EncoderSession_finish_error(&encoder_session);
 
         /*
@@ -1036,7 +1057,7 @@ int flac__encode_raw(FILE *infile, off_t infilesize, const char *infilename, con
                 while(total_input_bytes_read < max_input_bytes) {
                         {
                                 size_t wanted = (CHUNK_OF_SAMPLES * bytes_per_wide_sample);
-                                wanted = (size_t) min((off_t)wanted, max_input_bytes - total_input_bytes_read);
+                                wanted = (size_t) min((FLAC__uint64)wanted, max_input_bytes - total_input_bytes_read);
 
                                 if(lookahead_length > 0) {
                                         FLAC__ASSERT(lookahead_length <= wanted);
@@ -1126,6 +1147,163 @@ int flac__encode_raw(FILE *infile, off_t infilesize, const char *infilename, con
         return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero);
 }
 
+int flac__encode_flac(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, flac_encode_options_t options)
+{
+        EncoderSession encoder_session;
+        FLAC__SeekableStreamDecoder *decoder = 0;
+        FLACDecoderData decoder_data;
+        size_t i;
+        int retval;
+
+        if(!
+                EncoderSession_construct(
+                        &encoder_session,
+#ifdef FLAC__HAS_OGG
+                        options.common.use_ogg,
+#else
+                        /*use_ogg=*/false,
+#endif
+                        options.common.verify,
+                        infile,
+                        infilename,
+                        outfilename
+                )
+        )
+                return 1;
+
+        decoder_data.encoder_session = &encoder_session;
+        decoder_data.filesize = (infilesize == (off_t)(-1)? 0 : infilesize);
+        decoder_data.lookahead = lookahead;
+        decoder_data.lookahead_length = lookahead_length;
+        decoder_data.num_metadata_blocks = 0;
+        decoder_data.samples_left_to_process = 0;
+        decoder_data.fatal_error = false;
+
+        /*
+         * set up FLAC decoder for the input
+         */
+        if (0 == (decoder = FLAC__seekable_stream_decoder_new())) {
+                flac__utils_printf(stderr, 1, "%s: ERROR: creating decoder for FLAC input\n", encoder_session.inbasefilename);
+                return EncoderSession_finish_error(&encoder_session);
+        }
+        if (!(
+                FLAC__seekable_stream_decoder_set_md5_checking(decoder, false) &&
+                FLAC__seekable_stream_decoder_set_read_callback(decoder, flac_decoder_read_callback) &&
+                FLAC__seekable_stream_decoder_set_seek_callback(decoder, flac_decoder_seek_callback) &&
+                FLAC__seekable_stream_decoder_set_tell_callback(decoder, flac_decoder_tell_callback) &&
+                FLAC__seekable_stream_decoder_set_length_callback(decoder, flac_decoder_length_callback) &&
+                FLAC__seekable_stream_decoder_set_eof_callback(decoder, flac_decoder_eof_callback) &&
+                FLAC__seekable_stream_decoder_set_write_callback(decoder, flac_decoder_write_callback) &&
+                FLAC__seekable_stream_decoder_set_metadata_callback(decoder, flac_decoder_metadata_callback) &&
+                FLAC__seekable_stream_decoder_set_error_callback(decoder, flac_decoder_error_callback) &&
+                FLAC__seekable_stream_decoder_set_client_data(decoder, &decoder_data) &&
+                FLAC__seekable_stream_decoder_set_metadata_respond_all(decoder)
+        )) {
+                flac__utils_printf(stderr, 1, "%s: ERROR: setting up decoder for FLAC input\n", encoder_session.inbasefilename);
+                goto fubar1; /*@@@ yuck */
+        }
+
+        if (FLAC__seekable_stream_decoder_init(decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK) {
+                flac__utils_printf(stderr, 1, "%s: ERROR: initializing decoder for FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__seekable_stream_decoder_get_resolved_state_string(decoder));
+                goto fubar1; /*@@@ yuck */
+        }
+
+        if (!FLAC__seekable_stream_decoder_process_until_end_of_metadata(decoder) || decoder_data.fatal_error) {
+                if (decoder_data.fatal_error)
+                        flac__utils_printf(stderr, 1, "%s: ERROR: out of memory or too many metadata blocks while reading metadata in FLAC input\n", encoder_session.inbasefilename);
+                else
+                        flac__utils_printf(stderr, 1, "%s: ERROR: reading metadata in FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__seekable_stream_decoder_get_resolved_state_string(decoder));
+                goto fubar1; /*@@@ yuck */
+        }
+
+        if (decoder_data.num_metadata_blocks == 0) {
+                flac__utils_printf(stderr, 1, "%s: ERROR: reading metadata in FLAC input, got no metadata blocks\n", encoder_session.inbasefilename);
+                goto fubar2; /*@@@ yuck */
+        }
+        else if (decoder_data.metadata_blocks[0]->type != FLAC__METADATA_TYPE_STREAMINFO) {
+                flac__utils_printf(stderr, 1, "%s: ERROR: reading metadata in FLAC input, first metadata block is not STREAMINFO\n", encoder_session.inbasefilename);
+                goto fubar2; /*@@@ yuck */
+        }
+        else if (decoder_data.metadata_blocks[0]->data.stream_info.total_samples == 0) {
+                flac__utils_printf(stderr, 1, "%s: ERROR: FLAC input has STREAMINFO with unknown total samples which is not supported\n", encoder_session.inbasefilename);
+                goto fubar2; /*@@@ yuck */
+        }
+
+        /*
+         * now that we have the STREAMINFO and know the sample rate,
+         * canonicalize the --skip string to a number of samples:
+         */
+        flac__utils_canonicalize_skip_until_specification(&options.common.skip_specification, decoder_data.metadata_blocks[0]->data.stream_info.sample_rate);
+        FLAC__ASSERT(options.common.skip_specification.value.samples >= 0);
+        encoder_session.skip = (FLAC__uint64)options.common.skip_specification.value.samples;
+        FLAC__ASSERT(!options.common.sector_align); /* --sector-align with FLAC input is not supported */
+
+        {
+                FLAC__uint64 total_samples_in_input, trim = 0;
+
+                total_samples_in_input = decoder_data.metadata_blocks[0]->data.stream_info.total_samples;
+
+                /*
+                 * now that we know the input size, canonicalize the
+                 * --until string to an absolute sample number:
+                 */
+                if(!canonicalize_until_specification(&options.common.until_specification, encoder_session.inbasefilename, decoder_data.metadata_blocks[0]->data.stream_info.sample_rate, encoder_session.skip, total_samples_in_input))
+                        goto fubar2; /*@@@ yuck */
+                encoder_session.until = (FLAC__uint64)options.common.until_specification.value.samples;
+
+                encoder_session.total_samples_to_encode = total_samples_in_input - encoder_session.skip;
+                if(encoder_session.until > 0) {
+                        trim = total_samples_in_input - encoder_session.until;
+                        FLAC__ASSERT(total_samples_in_input > 0);
+                        encoder_session.total_samples_to_encode -= trim;
+                }
+
+                encoder_session.unencoded_size = decoder_data.filesize;
+
+                if(!EncoderSession_init_encoder(&encoder_session, options.common, decoder_data.metadata_blocks[0]->data.stream_info.channels, decoder_data.metadata_blocks[0]->data.stream_info.bits_per_sample, decoder_data.metadata_blocks[0]->data.stream_info.sample_rate, &decoder_data))
+                        return EncoderSession_finish_error(&encoder_session);
+
+                /*
+                 * have to wait until the FLAC encoder is set up for writing
+                 * before any seeking in the input FLAC file, because the seek
+                 * itself will usually call the decoder's write callback, and
+                 * our decoder's write callback passes samples to our FLAC
+                 * encoder
+                 */
+                decoder_data.samples_left_to_process = encoder_session.total_samples_to_encode;
+                if(encoder_session.skip > 0) {
+                        if(!FLAC__seekable_stream_decoder_seek_absolute(decoder, encoder_session.skip)) {
+                                flac__utils_printf(stderr, 1, "%s: ERROR while skipping samples, FLAC decoder state = %s\n", encoder_session.inbasefilename, FLAC__seekable_stream_decoder_get_resolved_state_string(decoder));
+                                goto fubar2; /*@@@ yuck */
+                        }
+                }
+
+                /*
+                 * now do samples from the file
+                 */
+                while(!decoder_data.fatal_error && decoder_data.samples_left_to_process > 0) {
+                        if(!FLAC__seekable_stream_decoder_process_single(decoder)) {
+                                flac__utils_printf(stderr, 1, "%s: ERROR: while decoding FLAC input, state = %s\n", encoder_session.inbasefilename, FLAC__seekable_stream_decoder_get_resolved_state_string(decoder));
+                                goto fubar2; /*@@@ yuck */
+                        }
+                }
+        }
+
+        FLAC__seekable_stream_decoder_delete(decoder);
+        retval = EncoderSession_finish_ok(&encoder_session, -1, -1);
+        /* have to wail until encoder is completely finished before deleting because of the final step of writing the seekpoint offsets */
+        for(i = 0; i < decoder_data.num_metadata_blocks; i++)
+                free(decoder_data.metadata_blocks[i]);
+        return retval;
+
+fubar2:
+        for(i = 0; i < decoder_data.num_metadata_blocks; i++)
+                free(decoder_data.metadata_blocks[i]);
+fubar1:
+        FLAC__seekable_stream_decoder_delete(decoder);
+        return EncoderSession_finish_error(&encoder_session);
+}
+
 FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC__bool verify, FILE *infile, const char *infilename, const char *outfilename)
 {
         unsigned i;
@@ -1355,6 +1533,7 @@ int EncoderSession_finish_error(EncoderSession *e)
         if(fse_state == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA)
                 print_verify_error(e);
         else
+                /*@@@@@@@@@ BUG: if error was caused because the output file already exists but the file encoder could not write on top of it (i.e. it's not writable), this will delete the pre-existing file, which is not what we want */
                 unlink(e->outfilename);
 
         EncoderSession_destroy(e);
@@ -1362,11 +1541,12 @@ int EncoderSession_finish_error(EncoderSession *e)
         return 1;
 }
 
-FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate)
+FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t options, unsigned channels, unsigned bps, unsigned sample_rate, FLACDecoderData *flac_decoder_data)
 {
         unsigned num_metadata;
         FLAC__StreamMetadata padding, *cuesheet = 0;
-        FLAC__StreamMetadata *metadata[4];
+        FLAC__StreamMetadata *static_metadata[4];
+        FLAC__StreamMetadata **metadata = static_metadata;
         const FLAC__bool is_cdda = (channels == 1 || channels == 2) && (bps == 16) && (sample_rate == 44100);
 
         e->replay_gain = options.replay_gain;
@@ -1394,7 +1574,7 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio
         if(channels != 2)
                 options.do_mid_side = options.loose_mid_side = false;
 
-        if(!parse_cuesheet_(&cuesheet, options.cuesheet_filename, e->inbasefilename, is_cdda, e->total_samples_to_encode))
+        if(!parse_cuesheet(&cuesheet, options.cuesheet_filename, e->inbasefilename, is_cdda, e->total_samples_to_encode))
                 return false;
 
         if(!convert_to_seek_table_template(options.requested_seek_points, options.num_requested_seek_points, options.cued_seekpoints? cuesheet : 0, e)) {
@@ -1404,19 +1584,206 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio
                 return false;
         }
 
-        num_metadata = 0;
-        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 */
-                metadata[num_metadata++] = e->seek_table_template;
+        if(flac_decoder_data) {
+                /*
+                 * we're encoding from FLAC so we will use the FLAC file's
+                 * metadata as the basic for the encoded file
+                 */
+                {
+                        /*
+                         * first handle padding: if --no-padding was specified,
+                         * then delete all padding; else if -P was specified,
+                         * use that instead of existing padding (if any); else
+                         * if existing file has padding, move all existing
+                         * padding blocks to one padding block at the end; else
+                         * use default padding.
+                         */
+                        int p = -1;
+                        size_t i, j;
+                        for(i = 0, j = 0; i < flac_decoder_data->num_metadata_blocks; i++) {
+                                if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_PADDING) {
+                                        if(p < 0)
+                                                p = 0;
+                                        p += flac_decoder_data->metadata_blocks[i]->length;
+                                        FLAC__metadata_object_delete(flac_decoder_data->metadata_blocks[i]);
+                                        flac_decoder_data->metadata_blocks[i] = 0;
+                                }
+                                else
+                                        flac_decoder_data->metadata_blocks[j++] = flac_decoder_data->metadata_blocks[i];
+                        }
+                        flac_decoder_data->num_metadata_blocks = j;
+                        if(options.padding > 0)
+                                p = options.padding;
+                        if(p < 0)
+                                p = FLAC_ENCODE__DEFAULT_PADDING;
+                        if(options.padding != 0) {
+                                if(p > 0 && flac_decoder_data->num_metadata_blocks < sizeof(flac_decoder_data->metadata_blocks)/sizeof(flac_decoder_data->metadata_blocks[0])) {
+                                        flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING);
+                                        if(0 == flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks]) {
+                                                flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for PADDING block\n", e->inbasefilename);
+                                                if(0 != cuesheet)
+                                                        FLAC__metadata_object_delete(cuesheet);
+                                                return false;
+                                        }
+                                        flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks]->is_last = false; /* the encoder will set this for us */
+                                        flac_decoder_data->metadata_blocks[flac_decoder_data->num_metadata_blocks]->length = p;
+                                        flac_decoder_data->num_metadata_blocks++;
+                                }
+                        }
+                }
+                {
+                        /*
+                         * next handle vorbis comment: if any tags were specified
+                         * or there is no existing vorbis comment, we create a
+                         * new vorbis comment (discarding any existing one); else
+                         * we keep the existing one
+                         */
+                        size_t i, j;
+                        FLAC__bool vc_found = false;
+                        for(i = 0, j = 0; i < flac_decoder_data->num_metadata_blocks; i++) {
+                                if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
+                                        vc_found = true;
+                                if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT && options.vorbis_comment->data.vorbis_comment.num_comments > 0) {
+                                        if(options.vorbis_comment->data.vorbis_comment.num_comments > 0)
+                                                flac__utils_printf(stderr, 1, "%s: WARNING, replacing tags from input FLAC file with those given on the command-line\n", e->inbasefilename);
+                                        FLAC__metadata_object_delete(flac_decoder_data->metadata_blocks[i]);
+                                        flac_decoder_data->metadata_blocks[i] = 0;
+                                }
+                                else
+                                        flac_decoder_data->metadata_blocks[j++] = flac_decoder_data->metadata_blocks[i];
+                        }
+                        flac_decoder_data->num_metadata_blocks = j;
+                        if((!vc_found || options.vorbis_comment->data.vorbis_comment.num_comments > 0) && flac_decoder_data->num_metadata_blocks < sizeof(flac_decoder_data->metadata_blocks)/sizeof(flac_decoder_data->metadata_blocks[0])) {
+                                /* prepend ours */
+                                FLAC__StreamMetadata *vc = FLAC__metadata_object_clone(options.vorbis_comment);
+                                if(0 == vc) {
+                                        flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for VORBIS_COMMENT block\n", e->inbasefilename);
+                                        if(0 != cuesheet)
+                                                FLAC__metadata_object_delete(cuesheet);
+                                        return false;
+                                }
+                                for(i = flac_decoder_data->num_metadata_blocks; i > 1; i--)
+                                        flac_decoder_data->metadata_blocks[i] = flac_decoder_data->metadata_blocks[i-1];
+                                flac_decoder_data->metadata_blocks[1] = vc;
+                                flac_decoder_data->num_metadata_blocks++;
+                        }
+                }
+                {
+                        /*
+                         * next handle cuesheet: if --cuesheet was specified, use
+                         * it; else if file has existing CUESHEET and cuesheet's
+                         * lead-out offset is correct, keep it; else no CUESHEET
+                         */
+                        size_t i, j;
+                        for(i = 0, j = 0; i < flac_decoder_data->num_metadata_blocks; i++) {
+                                FLAC__bool existing_cuesheet_is_bad = false;
+                                /* check if existing cuesheet matches the input audio */
+                                if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_CUESHEET && 0 == cuesheet) {
+                                        const FLAC__StreamMetadata_CueSheet *cs = &flac_decoder_data->metadata_blocks[i]->data.cue_sheet;
+                                        if(e->total_samples_to_encode == 0) {
+                                                flac__utils_printf(stderr, 1, "%s: WARNING, cuesheet in input FLAC file cannot be kept if input size is not known, dropping it...\n", e->inbasefilename);
+                                                existing_cuesheet_is_bad = true;
+                                        }
+                                        else if(e->total_samples_to_encode != cs->tracks[cs->num_tracks-1].offset) {
+                                                flac__utils_printf(stderr, 1, "%s: WARNING, lead-out offset of cuesheet in input FLAC file does not match input length, dropping existing cuesheet...\n", e->inbasefilename);
+                                                existing_cuesheet_is_bad = true;
+                                        }
+                                }
+                                if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_CUESHEET && (existing_cuesheet_is_bad || 0 != cuesheet)) {
+                                        if(0 != cuesheet)
+                                                flac__utils_printf(stderr, 1, "%s: WARNING, replacing cuesheet in input FLAC file with the one given on the command-line\n", e->inbasefilename);
+                                        FLAC__metadata_object_delete(flac_decoder_data->metadata_blocks[i]);
+                                        flac_decoder_data->metadata_blocks[i] = 0;
+                                }
+                                else
+                                        flac_decoder_data->metadata_blocks[j++] = flac_decoder_data->metadata_blocks[i];
+                        }
+                        flac_decoder_data->num_metadata_blocks = j;
+                        if(0 != cuesheet && flac_decoder_data->num_metadata_blocks < sizeof(flac_decoder_data->metadata_blocks)/sizeof(flac_decoder_data->metadata_blocks[0])) {
+                                /* prepend ours */
+                                FLAC__StreamMetadata *cs = FLAC__metadata_object_clone(cuesheet);
+                                if(0 == cs) {
+                                        flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for CUESHEET block\n", e->inbasefilename);
+                                        if(0 != cuesheet)
+                                                FLAC__metadata_object_delete(cuesheet);
+                                        return false;
+                                }
+                                for(i = flac_decoder_data->num_metadata_blocks; i > 1; i--)
+                                        flac_decoder_data->metadata_blocks[i] = flac_decoder_data->metadata_blocks[i-1];
+                                flac_decoder_data->metadata_blocks[1] = cs;
+                                flac_decoder_data->num_metadata_blocks++;
+                        }
+                }
+                {
+                        /*
+                         * finally handle seektable: if -S- was specified, no
+                         * SEEKTABLE; else if -S was specified, use it/them;
+                         * else if file has existing SEEKTABLE and input size is
+                         * preserved (no --skip/--until/etc specified), keep it;
+                         * else use default seektable options
+                         *
+                         * note: meanings of num_requested_seek_points:
+                         *  -1 : no -S option given, default to some value
+                         *   0 : -S- given (no seektable)
+                         *  >0 : one or more -S options given
+                         */
+                        size_t i, j;
+                        FLAC__bool existing_seektable = false;
+                        for(i = 0, j = 0; i < flac_decoder_data->num_metadata_blocks; i++) {
+                                if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_SEEKTABLE)
+                                        existing_seektable = true;
+                                if(flac_decoder_data->metadata_blocks[i]->type == FLAC__METADATA_TYPE_SEEKTABLE && (e->total_samples_to_encode != flac_decoder_data->metadata_blocks[0]->data.stream_info.total_samples || options.num_requested_seek_points >= 0)) {
+                                        if(options.num_requested_seek_points > 0)
+                                                flac__utils_printf(stderr, 1, "%s: WARNING, replacing seektable in input FLAC file with the one given on the command-line\n", e->inbasefilename);
+                                        else if(options.num_requested_seek_points == 0)
+                                                ; /* no warning, silently delete existing SEEKTABLE since user specified --no-seektable (-S-) */
+                                        else
+                                                flac__utils_printf(stderr, 1, "%s: WARNING, can't use existing seektable in input FLAC since the input size is changing or unknown, dropping existing SEEKTABLE block...\n", e->inbasefilename);
+                                        FLAC__metadata_object_delete(flac_decoder_data->metadata_blocks[i]);
+                                        flac_decoder_data->metadata_blocks[i] = 0;
+                                        existing_seektable = false;
+                                }
+                                else
+                                        flac_decoder_data->metadata_blocks[j++] = flac_decoder_data->metadata_blocks[i];
+                        }
+                        flac_decoder_data->num_metadata_blocks = j;
+                        if((options.num_requested_seek_points > 0 || (options.num_requested_seek_points < 0 && !existing_seektable)) && flac_decoder_data->num_metadata_blocks < sizeof(flac_decoder_data->metadata_blocks)/sizeof(flac_decoder_data->metadata_blocks[0])) {
+                                /* prepend ours */
+                                FLAC__StreamMetadata *st = FLAC__metadata_object_clone(e->seek_table_template);
+                                if(0 == st) {
+                                        flac__utils_printf(stderr, 1, "%s: ERROR allocating memory for SEEKTABLE block\n", e->inbasefilename);
+                                        if(0 != cuesheet)
+                                                FLAC__metadata_object_delete(cuesheet);
+                                        return false;
+                                }
+                                for(i = flac_decoder_data->num_metadata_blocks; i > 1; i--)
+                                        flac_decoder_data->metadata_blocks[i] = flac_decoder_data->metadata_blocks[i-1];
+                                flac_decoder_data->metadata_blocks[1] = st;
+                                flac_decoder_data->num_metadata_blocks++;
+                        }
+                }
+                metadata = &flac_decoder_data->metadata_blocks[1]; /* don't include STREAMINFO */
+                num_metadata = flac_decoder_data->num_metadata_blocks - 1;
         }
-        if(0 != cuesheet)
-                metadata[num_metadata++] = cuesheet;
-        metadata[num_metadata++] = options.vorbis_comment;
-        if(options.padding > 0) {
-                padding.is_last = false; /* the encoder will set this for us */
-                padding.type = FLAC__METADATA_TYPE_PADDING;
-                padding.length = (unsigned)options.padding;
-                metadata[num_metadata++] = &padding;
+        else {
+                /*
+                 * we're not encoding from FLAC so we will build the metadata
+                 * from scratch
+                 */
+                num_metadata = 0;
+                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 */
+                        metadata[num_metadata++] = e->seek_table_template;
+                }
+                if(0 != cuesheet)
+                        metadata[num_metadata++] = cuesheet;
+                metadata[num_metadata++] = options.vorbis_comment;
+                if(options.padding != 0) {
+                        padding.is_last = false; /* the encoder will set this for us */
+                        padding.type = FLAC__METADATA_TYPE_PADDING;
+                        padding.length = (unsigned)(options.padding>0? options.padding : FLAC_ENCODE__DEFAULT_PADDING);
+                        metadata[num_metadata++] = &padding;
+                }
         }
 
         e->blocksize = options.blocksize;
@@ -1850,7 +2217,122 @@ void flac_file_encoder_progress_callback(const FLAC__FileEncoder *encoder, FLAC_
                 print_stats(encoder_session);
 }
 
-FLAC__bool parse_cuesheet_(FLAC__StreamMetadata **cuesheet, const char *cuesheet_filename, const char *inbasefilename, FLAC__bool is_cdda, FLAC__uint64 lead_out_offset)
+FLAC__SeekableStreamDecoderReadStatus flac_decoder_read_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
+{
+        size_t n = 0;
+        FLACDecoderData *data = (FLACDecoderData*)client_data;
+        (void)decoder;
+
+        if (data->fatal_error)
+                return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
+
+        /* use up lookahead first */
+        if (data->lookahead_length) {
+                n = min(data->lookahead_length, *bytes);
+                memcpy(buffer, data->lookahead, n);
+                buffer += n;
+                data->lookahead += n;
+                data->lookahead_length -= n;
+        }
+
+        /* get the rest from file */
+        if (*bytes > n) {
+                *bytes = n + fread(buffer, 1, *bytes-n, data->encoder_session->fin);
+                return ferror(data->encoder_session->fin)? FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR : FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
+        }
+        else
+                return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
+}
+
+FLAC__SeekableStreamDecoderSeekStatus flac_decoder_seek_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+        FLACDecoderData *data = (FLACDecoderData*)client_data;
+        (void)decoder;
+
+        if(fseeko(data->encoder_session->fin, (off_t)absolute_byte_offset, SEEK_SET) < 0)
+                return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
+        else
+                return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
+}
+
+FLAC__SeekableStreamDecoderTellStatus flac_decoder_tell_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+        FLACDecoderData *data = (FLACDecoderData*)client_data;
+        off_t pos;
+        (void)decoder;
+
+        if((pos = ftello(data->encoder_session->fin)) < 0)
+                return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR;
+        else {
+                *absolute_byte_offset = (FLAC__uint64)pos;
+                return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
+        }
+}
+
+FLAC__SeekableStreamDecoderLengthStatus flac_decoder_length_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
+{
+        FLACDecoderData *data = (FLACDecoderData*)client_data;
+        (void)decoder;
+
+        if(0 == data->filesize)
+                return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
+        else {
+                *stream_length = (FLAC__uint64)data->filesize;
+                return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
+        }
+}
+
+FLAC__bool flac_decoder_eof_callback(const FLAC__SeekableStreamDecoder *decoder, void *client_data)
+{
+        FLACDecoderData *data = (FLACDecoderData*)client_data;
+        (void)decoder;
+
+        return feof(data->encoder_session->fin)? true : false;
+}
+
+FLAC__StreamDecoderWriteStatus flac_decoder_write_callback(const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+{
+        FLACDecoderData *data = (FLACDecoderData*)client_data;
+        FLAC__uint64 n = min(data->samples_left_to_process, frame->header.blocksize);
+        (void)decoder;
+
+        if(!EncoderSession_process(data->encoder_session, buffer, n)) {
+                print_error_with_state(data->encoder_session, "ERROR during encoding");
+                data->fatal_error = true;
+                return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
+        }
+
+        data->samples_left_to_process -= n;
+        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+void flac_decoder_metadata_callback(const FLAC__SeekableStreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
+{
+        FLACDecoderData *data = (FLACDecoderData*)client_data;
+        (void)decoder;
+
+        if (data->fatal_error)
+                return;
+
+        if (
+                data->num_metadata_blocks == sizeof(data->metadata_blocks)/sizeof(data->metadata_blocks[0]) ||
+                0 == (data->metadata_blocks[data->num_metadata_blocks] = FLAC__metadata_object_clone(metadata))
+        )
+                data->fatal_error = true;
+        else
+                data->num_metadata_blocks++;
+}
+
+void flac_decoder_error_callback(const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
+{
+        FLACDecoderData *data = (FLACDecoderData*)client_data;
+        (void)decoder;
+
+        flac__utils_printf(stderr, 1, "%s: ERROR got %s while decoding FLAC input\n", data->encoder_session->inbasefilename, FLAC__StreamDecoderErrorStatusString[status]);
+        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)
 {
         FILE *f;
         unsigned last_line_read;
@@ -1951,7 +2433,7 @@ void print_error_with_state(const EncoderSession *e, const char *message)
                         "\n"
                         "The encoding parameters specified do not conform to the FLAC Subset and may not\n"
                         "be streamable or playable in hardware devices.  Add --lax to the command-line\n"
-                        "options to encode with these parameters.\n"
+                        "options to encode with these parameters anyway.\n"
                 );
         }
         else if(
@@ -2010,13 +2492,13 @@ void print_verify_error(EncoderSession *e)
         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, "       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->inbasefilename);
+        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");
         flac__utils_printf(stderr, 1, "       verify error in the exact same place each time you try it, then there is\n");
         flac__utils_printf(stderr, 1, "       a problem with your hardware; please see the FAQ:\n");
         flac__utils_printf(stderr, 1, "           http://flac.sourceforge.net/faq.html#tools__hardware_prob\n");
-        flac__utils_printf(stderr, 1, "       If it does fail in the exact same place every time, keep the bad FLAC\n");
-        flac__utils_printf(stderr, 1, "       file and submit a bug report to:\n");
+        flac__utils_printf(stderr, 1, "       If it does fail in the exact same place every time, keep\n");
+        flac__utils_printf(stderr, 1, "       %s and submit a bug report to:\n", e->outfilename);
         flac__utils_printf(stderr, 1, "           https://sourceforge.net/bugs/?func=addbug&group_id=13478\n");
         flac__utils_printf(stderr, 1, "       Make sure to upload the FLAC file and use the \"Monitor\" feature to\n");
         flac__utils_printf(stderr, 1, "       monitor the bug status.\n");
diff --git a/src/flac/encode.h b/src/flac/encode.h
index cfda5434..7a274d7f 100644
--- a/src/flac/encode.h
+++ b/src/flac/encode.h
@@ -31,6 +31,8 @@
 #include <config.h>
 #endif
 
+extern const int FLAC_ENCODE__DEFAULT_PADDING;
+
 typedef struct {
         utils__SkipUntilSpecification skip_specification;
         utils__SkipUntilSpecification until_specification;
@@ -89,8 +91,13 @@ typedef struct {
         unsigned sample_rate;
 } raw_encode_options_t;
 
+typedef struct {
+        encode_options_t common;
+} flac_encode_options_t;
+
 int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options, FLAC__bool is_aifc);
 int flac__encode_wav(FILE *infile, off_t 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, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, raw_encode_options_t options);
+int flac__encode_flac(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, flac_encode_options_t options);
 
 #endif
diff --git a/src/flac/main.c b/src/flac/main.c
index 14db8daf..07e98647 100644
--- a/src/flac/main.c
+++ b/src/flac/main.c
@@ -56,7 +56,7 @@
 #  include "share/getopt.h"
 #endif
 
-typedef enum { RAW, WAV, AIF } FileFormat;
+typedef enum { RAW, WAV, AIF, FLAC } FileFormat;
 
 static int do_it();
 
@@ -234,7 +234,7 @@ static struct {
         const char *cmdline_forced_outfilename;
         const char *output_prefix;
         analysis_options aopts;
-        int padding;
+        int padding; /* -1 => no -P options were given, 0 => -P- was given, else -P value */
         char apodizations[1000]; /* bad MAGIC NUMBER but buffer overflow is checked */
         unsigned max_lpc_order;
         unsigned qlp_coeff_precision;
@@ -287,6 +287,7 @@ int main(int argc, char *argv[])
         _wildcard(&argc, &argv);
 #endif
 
+        srand(time(0));
         setlocale(LC_ALL, "");
         if(!init_options()) {
                 flac__utils_printf(stderr, 1, "ERROR: allocating memory\n");
@@ -435,7 +436,7 @@ int do_it()
                          * tags that we will set later, to avoid rewriting the
                          * whole file.
                          */
-                        if(option_values.padding < 0) {
+                        if(option_values.padding <= 0) {
                                 flac__utils_printf(stderr, 1, "NOTE: --replay-gain may leave a small PADDING block even with --no-padding\n");
                                 option_values.padding = GRABBAG__REPLAYGAIN_MAX_TAG_SPACE_REQUIRED;
                         }
@@ -461,10 +462,10 @@ int do_it()
 
         if(!option_values.mode_decode) {
                 char padopt[16];
-                if(option_values.padding < 0)
+                if(option_values.padding == 0)
                         strcpy(padopt, "-");
                 else
-                        sprintf(padopt, " %d", option_values.padding);
+                        sprintf(padopt, " %d", option_values.padding > 0? option_values.padding : FLAC_ENCODE__DEFAULT_PADDING);
                 flac__utils_printf(stderr, 2,
                         "options:%s%s%s%s -P%s -b %u%s -l %u%s%s%s -q %u -r %u,%u%s\n",
                         option_values.delete_input?" --delete-input-file":"",
@@ -580,7 +581,7 @@ FLAC__bool init_options()
         option_values.output_prefix = 0;
         option_values.aopts.do_residual_text = false;
         option_values.aopts.do_residual_gnuplot = false;
-        option_values.padding = 4096;
+        option_values.padding = -1;
         option_values.apodizations[0] = '\0';
         option_values.max_lpc_order = 8;
         option_values.qlp_coeff_precision = 0;
@@ -860,7 +861,7 @@ int parse_option(int short_option, const char *long_option, const char *option_a
                         option_values.do_qlp_coeff_prec_search = false;
                 }
                 else if(0 == strcmp(long_option, "no-padding")) {
-                        option_values.padding = -1;
+                        option_values.padding = 0;
                 }
                 else if(0 == strcmp(long_option, "no-verify")) {
                         option_values.verify = false;
@@ -1040,7 +1041,7 @@ int parse_option(int short_option, const char *long_option, const char *option_a
                                 FLAC__ASSERT(0 != option_argument);
                                 option_values.padding = atoi(option_argument);
                                 if(option_values.padding < 0)
-                                        return usage_error("ERROR: argument to -P must be >= 0\n");
+                                        return usage_error("ERROR: argument to -P must be >= 0; for no padding use -P-\n");
                                 break;
                         case 'b':
                                 FLAC__ASSERT(0 != option_argument);
@@ -1552,22 +1553,15 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
         int retval;
         off_t infilesize;
         encode_options_t common_options;
-        const char *outfilename = get_encoded_outfilename(infilename);
+        const char *outfilename = get_encoded_outfilename(infilename); /* the final name of the encoded file */
+        /* internal_outfilename is the file we will actually write to; it will be a temporary name if infilename==outfilename */
+        char *internal_outfilename = 0; /* NULL implies 'use outfilename' */
 
         if(0 == outfilename) {
                 flac__utils_printf(stderr, 1, "ERROR: filename too long: %s", infilename);
                 return 1;
         }
 
-        /*
-         * Error if output file already exists (and -f not used).
-         * Use grabbag__file_get_filesize() as a cheap way to check.
-         */
-        if(!option_values.test_only && !option_values.force_file_overwrite && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) {
-                flac__utils_printf(stderr, 1, "ERROR: output file %s already exists, use -f to override\n", outfilename);
-                return 1;
-        }
-
         if(0 == strcmp(infilename, "-")) {
                 infilesize = (off_t)(-1);
                 encode_infile = grabbag__file_get_binary_stdin();
@@ -1588,6 +1582,8 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
                         fmt= AIF;
                 else if(strlen(infilename) >= 5 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-5), ".aiff"))
                         fmt= AIF;
+                else if(strlen(infilename) >= 5 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-5), ".flac"))
+                        fmt= FLAC;
 
                 /* attempt to guess the file type based on the first 12 bytes */
                 if((lookahead_length = fread(lookahead, 1, 12, encode_infile)) < 12) {
@@ -1604,6 +1600,8 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
                                 fmt= AIF;
                                 is_aifc = true;
                         }
+                        else if(!strncmp((const char *)lookahead, FLAC__STREAM_SYNC_STRING, sizeof(FLAC__STREAM_SYNC_STRING)))
+                                fmt= FLAC;
                         else {
                                 if(fmt != RAW)
                                         format_mistake(infilename, fmt == AIF ? "AIFF" : "WAVE", "raw");
@@ -1612,6 +1610,27 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
                 }
         }
 
+        /*
+         * Error if output file already exists (and -f not used).
+         * Use grabbag__file_get_filesize() as a cheap way to check.
+         */
+        if(!option_values.test_only && !option_values.force_file_overwrite && strcmp(outfilename, "-") && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) {
+                if(fmt == FLAC) {
+                        /* need more detailed error message when re-flac'ing to avoid confusing the user */
+                        flac__utils_printf(stderr, 1,
+                                "ERROR: output file %s already exists.\n\n"
+                                "By default flac encodes files to FLAC format; if you meant to decode this file\n"
+                                "from FLAC to something else, use -d.  If you meant to re-encode this file from\n"
+                                "FLAC to FLAC again, use -f to force writing to the same file, or -o to specify\n"
+                                "a different output filename.\n",
+                                outfilename
+                        );
+                }
+                else
+                        flac__utils_printf(stderr, 1, "ERROR: output file %s already exists, use -f to override\n", outfilename);
+                return 1;
+        }
+
         if(option_values.format_input_size >= 0) {
                    if (fmt != RAW || infilesize >= 0) {
                         flac__utils_printf(stderr, 1, "ERROR: can only use --input-size when encoding raw samples from stdin\n");
@@ -1622,8 +1641,12 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
                 }
         }
 
+        if(option_values.sector_align && fmt == FLAC) {
+                flac__utils_printf(stderr, 1, "ERROR: can't use --sector-align when the input file is FLAC\n");
+                return 1;
+        }
         if(option_values.sector_align && fmt == RAW && infilesize < 0) {
-                flac__utils_printf(stderr, 1, "ERROR: can't --sector-align when the input size is unknown\n");
+                flac__utils_printf(stderr, 1, "ERROR: can't use --sector-align when the input size is unknown\n");
                 return 1;
         }
 
@@ -1651,7 +1674,6 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
         common_options.use_ogg = option_values.use_ogg;
         /* set a random serial number if one has not yet been specified */
         if(!option_values.has_serial_number) {
-                srand(time(0));
                 option_values.serial_number = rand();
                 option_values.has_serial_number = true;
         }
@@ -1686,6 +1708,17 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
         common_options.debug.disable_fixed_subframes = option_values.debug.disable_fixed_subframes;
         common_options.debug.disable_verbatim_subframes = option_values.debug.disable_verbatim_subframes;
 
+        /* if infilename==outfilename, we need to write to a temporary file */
+        if(encode_infile != stdin && 0 == strcmp(infilename, outfilename)) { /*@@@@@@ BUG strcmp is not adequate to check if infilename and outfilename are the same file */
+                static const char *tmp_suffix = ".tmp";
+                if(0 == (internal_outfilename = malloc(strlen(outfilename)+strlen(tmp_suffix)+1))) {
+                        flac__utils_printf(stderr, 1, "ERROR allocating memory for tempfile name\n");
+                        return 1;
+                }
+                strcpy(internal_outfilename, outfilename);
+                strcat(internal_outfilename, tmp_suffix);
+        }
+
         if(fmt == RAW) {
                 raw_encode_options_t options;
 
@@ -1696,7 +1729,14 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
                 options.bps = option_values.format_bps;
                 options.sample_rate = option_values.format_sample_rate;
 
-                retval = flac__encode_raw(encode_infile, infilesize, infilename, outfilename, lookahead, lookahead_length, options);
+                retval = flac__encode_raw(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options);
+        }
+        else if(fmt == FLAC) {
+                flac_encode_options_t options;
+
+                options.common = common_options;
+
+                retval = flac__encode_flac(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options);
         }
         else {
                 wav_encode_options_t options;
@@ -1704,27 +1744,41 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
                 options.common = common_options;
 
                 if(fmt == AIF)
-                        retval = flac__encode_aif(encode_infile, infilesize, infilename, outfilename, lookahead, lookahead_length, options, is_aifc);
+                        retval = flac__encode_aif(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options, is_aifc);
                 else
-                        retval = flac__encode_wav(encode_infile, infilesize, infilename, outfilename, lookahead, lookahead_length, options);
+                        retval = flac__encode_wav(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options);
         }
 
-        if(retval == 0 && strcmp(infilename, "-")) {
+        if(retval == 0) {
                 if(strcmp(outfilename, "-")) {
                         if(option_values.replay_gain) {
                                 float title_gain, title_peak;
                                 const char *error;
                                 grabbag__replaygain_get_title(&title_gain, &title_peak);
-                                if(0 != (error = grabbag__replaygain_store_to_file_title(outfilename, title_gain, title_peak, /*preserve_modtime=*/true))) {
+                                if(0 != (error = grabbag__replaygain_store_to_file_title(internal_outfilename, title_gain, title_peak, /*preserve_modtime=*/true))) {
                                         flac__utils_printf(stderr, 1, "%s: ERROR writing ReplayGain title tags\n", outfilename);
                                 }
                         }
-                        grabbag__file_copy_metadata(infilename, outfilename);
+                        if(strcmp(infilename, "-"))
+                                grabbag__file_copy_metadata(infilename, internal_outfilename);
                 }
-                if(option_values.delete_input)
-                        unlink(infilename);
         }
 
+        /* rename temporary file if necessary */
+        if(retval == 0 && internal_outfilename != 0) {
+                if(rename(internal_outfilename, outfilename) < 0) {
+                        flac__utils_printf(stderr, 1, "ERROR: moving new FLAC file %s back on top of original FLAC file %s, keeping both\n", internal_outfilename, outfilename);
+                        retval = 1;
+                }
+        }
+
+        /* handle --delete-input-file, but don't want to delete if piping from stdin, or if input filename and output filename are the same */
+        if(retval == 0 && option_values.delete_input && strcmp(infilename, "-") && internal_outfilename == 0)
+                unlink(infilename);
+
+        if(internal_outfilename != 0)
+                free(internal_outfilename);
+
         return retval;
 }
 
@@ -1870,14 +1924,7 @@ const char *get_outfilename(const char *infilename, const char *suffix)
                                         return 0;
                         }
                         else {
-                                if(0 == strcmp(p, suffix)) {
-                                        *p = '\0';
-                                        if (flac__strlcat(buffer, "_new", sizeof buffer) >= sizeof buffer)
-                                                return 0;
-                                }
-                                else {
-                                        *p = '\0';
-                                }
+                                *p = '\0';
                                 if (flac__strlcat(buffer, suffix, sizeof buffer) >= sizeof buffer)
                                         return 0;
                         }
diff --git a/test/Makefile.am b/test/Makefile.am
index 26eb28a2..c2cddbdd 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -17,7 +17,7 @@
 
 TESTS_ENVIRONMENT = FLAC__TEST_LEVEL=@FLAC__TEST_LEVEL@ FLAC__TEST_WITH_VALRGIND=@FLAC__TEST_WITH_VALGRIND@
 
-SUBDIRS = cuesheets
+SUBDIRS = cuesheets flac-to-flac-metadata-test-files metaflac-test-files
 
 if FLaC__HAS_OGG
 OGG_TESTS = \
diff --git a/test/Makefile.lite b/test/Makefile.lite
index baf0f16c..17eb7ef2 100644
--- a/test/Makefile.lite
+++ b/test/Makefile.lite
@@ -54,4 +54,4 @@ valgrind: all
 release : all
 
 clean:
-        rm -f *.raw *.flac *.ogg *.cmp *.aiff *.wav *.diff *.log *.cue core
+        rm -f *.raw *.flac *.ogg *.cmp *.aiff *.wav *.diff *.log *.cue core flac-to-flac-metadata-test-files/out.* metaflac-test-files/out.*
diff --git a/test/flac-to-flac-metadata-test-files/Makefile.am b/test/flac-to-flac-metadata-test-files/Makefile.am
new file mode 100644
index 00000000..c16ef5cd
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/Makefile.am
@@ -0,0 +1,44 @@
+#  FLAC - Free Lossless Audio Codec
+#  Copyright (C) 2006  Josh Coalson
+#
+#  This file is part the FLAC project.  FLAC is comprised of several
+#  components distributed under difference licenses.  The codec libraries
+#  are distributed under Xiph.Org's BSD-like license (see the file
+#  COPYING.Xiph in this distribution).  All other programs, libraries, and
+#  plugins are distributed under the GPL (see COPYING.GPL).  The documentation
+#  is distributed under the Gnu FDL (see COPYING.FDL).  Each file in the
+#  FLAC distribution contains at the top the terms under which it may be
+#  distributed.
+#
+#  Since this particular file is relevant to all components of FLAC,
+#  it may be distributed under the Xiph.Org license, which is the least
+#  restrictive of those mentioned above.  See the file COPYING.Xiph in this
+#  distribution.
+
+EXTRA_DIST = \
+        case00a-expect.meta \
+        case01a-expect.meta \
+        case01b-expect.meta \
+        case02a-expect.meta \
+        case02b-expect.meta \
+        case03a-expect.meta \
+        case03b-expect.meta \
+        case03c-expect.meta \
+        case04a-expect.meta \
+        case04b-expect.meta \
+        case04c-expect.meta \
+        case05a-expect.meta \
+        case05b-expect.meta \
+        case05c-expect.meta \
+        case05d-expect.meta \
+        case05e-expect.meta \
+        input-SCPAP.flac \
+        input-SCVA.flac \
+        input-SCVAUP.flac \
+        input-SCVPAP.flac \
+        input-SVAUP.flac \
+        input-VA.flac \
+        input0.cue
+
+CLEANFILES = \
+        $(wildcard out.*)
diff --git a/test/flac-to-flac-metadata-test-files/case00a-expect.meta b/test/flac-to-flac-metadata-test-files/case00a-expect.meta
new file mode 100644
index 00000000..840eb58e
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case00a-expect.meta
@@ -0,0 +1,84 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 180
+  seek points: 10
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+    point 5: PLACEHOLDER
+    point 6: PLACEHOLDER
+    point 7: PLACEHOLDER
+    point 8: PLACEHOLDER
+    point 9: PLACEHOLDER
+METADATA block #2
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 1234567890123
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 588
+          number: 2
+    track[1]
+      offset: 2940
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #3
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #4
+  type: 2 (APPLICATION)
+  is last: false
+  length: 4
+  application ID: 66616b65
+  data contents:
+METADATA block #5
+  type: 126 (UNKNOWN)
+  is last: false
+  length: 0
+  data contents:
+METADATA block #6
+  type: 1 (PADDING)
+  is last: true
+  length: 3201
diff --git a/test/flac-to-flac-metadata-test-files/case01a-expect.meta b/test/flac-to-flac-metadata-test-files/case01a-expect.meta
new file mode 100644
index 00000000..500d29a6
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case01a-expect.meta
@@ -0,0 +1,79 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 180
+  seek points: 10
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+    point 5: PLACEHOLDER
+    point 6: PLACEHOLDER
+    point 7: PLACEHOLDER
+    point 8: PLACEHOLDER
+    point 9: PLACEHOLDER
+METADATA block #2
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 1234567890123
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 588
+          number: 2
+    track[1]
+      offset: 2940
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #3
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #4
+  type: 2 (APPLICATION)
+  is last: false
+  length: 4
+  application ID: 66616b65
+  data contents:
+METADATA block #5
+  type: 1 (PADDING)
+  is last: true
+  length: 3205
diff --git a/test/flac-to-flac-metadata-test-files/case01b-expect.meta b/test/flac-to-flac-metadata-test-files/case01b-expect.meta
new file mode 100644
index 00000000..3822533f
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case01b-expect.meta
@@ -0,0 +1,75 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 180
+  seek points: 10
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+    point 5: PLACEHOLDER
+    point 6: PLACEHOLDER
+    point 7: PLACEHOLDER
+    point 8: PLACEHOLDER
+    point 9: PLACEHOLDER
+METADATA block #2
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 1234567890123
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 588
+          number: 2
+    track[1]
+      offset: 2940
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #3
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #4
+  type: 2 (APPLICATION)
+  is last: true
+  length: 4
+  application ID: 66616b65
+  data contents:
diff --git a/test/flac-to-flac-metadata-test-files/case01c-expect.meta b/test/flac-to-flac-metadata-test-files/case01c-expect.meta
new file mode 100644
index 00000000..357396fa
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case01c-expect.meta
@@ -0,0 +1,79 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 180
+  seek points: 10
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+    point 5: PLACEHOLDER
+    point 6: PLACEHOLDER
+    point 7: PLACEHOLDER
+    point 8: PLACEHOLDER
+    point 9: PLACEHOLDER
+METADATA block #2
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 1234567890123
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 588
+          number: 2
+    track[1]
+      offset: 2940
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #3
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #4
+  type: 2 (APPLICATION)
+  is last: false
+  length: 4
+  application ID: 66616b65
+  data contents:
+METADATA block #5
+  type: 1 (PADDING)
+  is last: true
+  length: 1234
diff --git a/test/flac-to-flac-metadata-test-files/case01d-expect.meta b/test/flac-to-flac-metadata-test-files/case01d-expect.meta
new file mode 100644
index 00000000..357396fa
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case01d-expect.meta
@@ -0,0 +1,79 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 180
+  seek points: 10
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+    point 5: PLACEHOLDER
+    point 6: PLACEHOLDER
+    point 7: PLACEHOLDER
+    point 8: PLACEHOLDER
+    point 9: PLACEHOLDER
+METADATA block #2
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 1234567890123
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 588
+          number: 2
+    track[1]
+      offset: 2940
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #3
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #4
+  type: 2 (APPLICATION)
+  is last: false
+  length: 4
+  application ID: 66616b65
+  data contents:
+METADATA block #5
+  type: 1 (PADDING)
+  is last: true
+  length: 1234
diff --git a/test/flac-to-flac-metadata-test-files/case01e-expect.meta b/test/flac-to-flac-metadata-test-files/case01e-expect.meta
new file mode 100644
index 00000000..d9a398ed
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case01e-expect.meta
@@ -0,0 +1,79 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 180
+  seek points: 10
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+    point 5: PLACEHOLDER
+    point 6: PLACEHOLDER
+    point 7: PLACEHOLDER
+    point 8: PLACEHOLDER
+    point 9: PLACEHOLDER
+METADATA block #2
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 1234567890123
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 588
+          number: 2
+    track[1]
+      offset: 2940
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #3
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #4
+  type: 2 (APPLICATION)
+  is last: false
+  length: 4
+  application ID: 66616b65
+  data contents:
+METADATA block #5
+  type: 1 (PADDING)
+  is last: true
+  length: 4096
diff --git a/test/flac-to-flac-metadata-test-files/case02a-expect.meta b/test/flac-to-flac-metadata-test-files/case02a-expect.meta
new file mode 100644
index 00000000..f8be007c
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case02a-expect.meta
@@ -0,0 +1,73 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 40
+  comments: 0
+METADATA block #2
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 180
+  seek points: 10
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+    point 5: PLACEHOLDER
+    point 6: PLACEHOLDER
+    point 7: PLACEHOLDER
+    point 8: PLACEHOLDER
+    point 9: PLACEHOLDER
+METADATA block #3
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 1234567890123
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 588
+          number: 2
+    track[1]
+      offset: 2940
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #4
+  type: 2 (APPLICATION)
+  is last: false
+  length: 4
+  application ID: 66616b65
+  data contents:
+METADATA block #5
+  type: 1 (PADDING)
+  is last: true
+  length: 3205
diff --git a/test/flac-to-flac-metadata-test-files/case02b-expect.meta b/test/flac-to-flac-metadata-test-files/case02b-expect.meta
new file mode 100644
index 00000000..1dc659e8
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case02b-expect.meta
@@ -0,0 +1,74 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 52
+  comments: 1
+    comment[0]: artist=0
+METADATA block #2
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 180
+  seek points: 10
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+    point 5: PLACEHOLDER
+    point 6: PLACEHOLDER
+    point 7: PLACEHOLDER
+    point 8: PLACEHOLDER
+    point 9: PLACEHOLDER
+METADATA block #3
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 1234567890123
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 588
+          number: 2
+    track[1]
+      offset: 2940
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #4
+  type: 2 (APPLICATION)
+  is last: false
+  length: 4
+  application ID: 66616b65
+  data contents:
+METADATA block #5
+  type: 1 (PADDING)
+  is last: true
+  length: 3205
diff --git a/test/flac-to-flac-metadata-test-files/case02c-expect.meta b/test/flac-to-flac-metadata-test-files/case02c-expect.meta
new file mode 100644
index 00000000..26383471
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case02c-expect.meta
@@ -0,0 +1,79 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 52
+  comments: 1
+    comment[0]: artist=0
+METADATA block #2
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 180
+  seek points: 10
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+    point 5: PLACEHOLDER
+    point 6: PLACEHOLDER
+    point 7: PLACEHOLDER
+    point 8: PLACEHOLDER
+    point 9: PLACEHOLDER
+METADATA block #3
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 1234567890123
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 588
+          number: 2
+    track[1]
+      offset: 2940
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #4
+  type: 2 (APPLICATION)
+  is last: false
+  length: 4
+  application ID: 66616b65
+  data contents:
+METADATA block #5
+  type: 126 (UNKNOWN)
+  is last: false
+  length: 0
+  data contents:
+METADATA block #6
+  type: 1 (PADDING)
+  is last: true
+  length: 3201
diff --git a/test/flac-to-flac-metadata-test-files/case03a-expect.meta b/test/flac-to-flac-metadata-test-files/case03a-expect.meta
new file mode 100644
index 00000000..dfcbaeb1
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case03a-expect.meta
@@ -0,0 +1,84 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 9294969890929
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[1]
+      offset: 588
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 2352
+          number: 2
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #2
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 180
+  seek points: 10
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+    point 5: PLACEHOLDER
+    point 6: PLACEHOLDER
+    point 7: PLACEHOLDER
+    point 8: PLACEHOLDER
+    point 9: PLACEHOLDER
+METADATA block #3
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #4
+  type: 2 (APPLICATION)
+  is last: false
+  length: 4
+  application ID: 66616b65
+  data contents:
+METADATA block #5
+  type: 126 (UNKNOWN)
+  is last: false
+  length: 0
+  data contents:
+METADATA block #6
+  type: 1 (PADDING)
+  is last: true
+  length: 3201
diff --git a/test/flac-to-flac-metadata-test-files/case03b-expect.meta b/test/flac-to-flac-metadata-test-files/case03b-expect.meta
new file mode 100644
index 00000000..dfcbaeb1
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case03b-expect.meta
@@ -0,0 +1,84 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 9294969890929
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[1]
+      offset: 588
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 2352
+          number: 2
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #2
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 180
+  seek points: 10
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+    point 5: PLACEHOLDER
+    point 6: PLACEHOLDER
+    point 7: PLACEHOLDER
+    point 8: PLACEHOLDER
+    point 9: PLACEHOLDER
+METADATA block #3
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #4
+  type: 2 (APPLICATION)
+  is last: false
+  length: 4
+  application ID: 66616b65
+  data contents:
+METADATA block #5
+  type: 126 (UNKNOWN)
+  is last: false
+  length: 0
+  data contents:
+METADATA block #6
+  type: 1 (PADDING)
+  is last: true
+  length: 3201
diff --git a/test/flac-to-flac-metadata-test-files/case03c-expect.meta b/test/flac-to-flac-metadata-test-files/case03c-expect.meta
new file mode 100644
index 00000000..7cd23b62
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case03c-expect.meta
@@ -0,0 +1,40 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5879
+  MD5 signature: 2ea0e6a767b66bf0668523fd77672ce1
+METADATA block #1
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 0
+  seek points: 0
+METADATA block #2
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #3
+  type: 2 (APPLICATION)
+  is last: false
+  length: 4
+  application ID: 66616b65
+  data contents:
+METADATA block #4
+  type: 126 (UNKNOWN)
+  is last: false
+  length: 0
+  data contents:
+METADATA block #5
+  type: 1 (PADDING)
+  is last: true
+  length: 3201
diff --git a/test/flac-to-flac-metadata-test-files/case04a-expect.meta b/test/flac-to-flac-metadata-test-files/case04a-expect.meta
new file mode 100644
index 00000000..ee9583da
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case04a-expect.meta
@@ -0,0 +1,26 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #2
+  type: 2 (APPLICATION)
+  is last: true
+  length: 4
+  application ID: 66616b65
+  data contents:
diff --git a/test/flac-to-flac-metadata-test-files/case04b-expect.meta b/test/flac-to-flac-metadata-test-files/case04b-expect.meta
new file mode 100644
index 00000000..85388b33
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case04b-expect.meta
@@ -0,0 +1,36 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 90
+  seek points: 5
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+METADATA block #2
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #3
+  type: 2 (APPLICATION)
+  is last: true
+  length: 4
+  application ID: 66616b65
+  data contents:
diff --git a/test/flac-to-flac-metadata-test-files/case04c-expect.meta b/test/flac-to-flac-metadata-test-files/case04c-expect.meta
new file mode 100644
index 00000000..29fcdb15
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case04c-expect.meta
@@ -0,0 +1,31 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 0
+  seek points: 0
+METADATA block #2
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #3
+  type: 2 (APPLICATION)
+  is last: true
+  length: 4
+  application ID: 66616b65
+  data contents:
diff --git a/test/flac-to-flac-metadata-test-files/case04d-expect.meta b/test/flac-to-flac-metadata-test-files/case04d-expect.meta
new file mode 100644
index 00000000..4a7a964f
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case04d-expect.meta
@@ -0,0 +1,60 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 1234567890123
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 588
+          number: 2
+    track[1]
+      offset: 2940
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #2
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #3
+  type: 2 (APPLICATION)
+  is last: true
+  length: 4
+  application ID: 66616b65
+  data contents:
diff --git a/test/flac-to-flac-metadata-test-files/case04e-expect.meta b/test/flac-to-flac-metadata-test-files/case04e-expect.meta
new file mode 100644
index 00000000..c8a9d0d7
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/case04e-expect.meta
@@ -0,0 +1,70 @@
+METADATA block #0
+  type: 0 (STREAMINFO)
+  is last: false
+  length: 34
+  sample_rate: 44100 Hz
+  channels: 2
+  bits-per-sample: 16
+  total samples: 5880
+  MD5 signature: 74ffd4737eb5488d512be4af58943362
+METADATA block #1
+  type: 3 (SEEKTABLE)
+  is last: false
+  length: 90
+  seek points: 5
+    point 0: sample_number=0
+    point 1: sample_number=4608
+    point 2: PLACEHOLDER
+    point 3: PLACEHOLDER
+    point 4: PLACEHOLDER
+METADATA block #2
+  type: 5 (CUESHEET)
+  is last: false
+  length: 540
+  media catalog number: 1234567890123
+  lead-in: 88200
+  is CD: true
+  number of tracks: 3
+    track[0]
+      offset: 0
+      number: 1
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 2
+        index[0]
+          offset: 0
+          number: 1
+        index[1]
+          offset: 588
+          number: 2
+    track[1]
+      offset: 2940
+      number: 2
+      ISRC:
+      type: AUDIO
+      pre-emphasis: false
+      number of index points: 1
+        index[0]
+          offset: 0
+          number: 1
+    track[2]
+      offset: 5880
+      number: 170 (LEAD-OUT)
+METADATA block #3
+  type: 4 (VORBIS_COMMENT)
+  is last: false
+  length: 203
+  comments: 6
+    comment[0]: REPLAYGAIN_TRACK_PEAK=0.99996948
+    comment[1]: REPLAYGAIN_TRACK_GAIN=-7.89 dB
+    comment[2]: REPLAYGAIN_ALBUM_PEAK=0.99996948
+    comment[3]: REPLAYGAIN_ALBUM_GAIN=-7.89 dB
+    comment[4]: artist=1
+    comment[5]: title=2
+METADATA block #4
+  type: 2 (APPLICATION)
+  is last: true
+  length: 4
+  application ID: 66616b65
+  data contents:
diff --git a/test/flac-to-flac-metadata-test-files/input-SCPAP.flac b/test/flac-to-flac-metadata-test-files/input-SCPAP.flac
new file mode 100644
index 00000000..6fde318d
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/input-SCPAP.flac
Binary files differ
diff --git a/test/flac-to-flac-metadata-test-files/input-SCVA.flac b/test/flac-to-flac-metadata-test-files/input-SCVA.flac
new file mode 100644
index 00000000..4bb69262
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/input-SCVA.flac
Binary files differ
diff --git a/test/flac-to-flac-metadata-test-files/input-SCVAUP.flac b/test/flac-to-flac-metadata-test-files/input-SCVAUP.flac
new file mode 100644
index 00000000..e4ecc952
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/input-SCVAUP.flac
Binary files differ
diff --git a/test/flac-to-flac-metadata-test-files/input-SCVPAP.flac b/test/flac-to-flac-metadata-test-files/input-SCVPAP.flac
new file mode 100644
index 00000000..74749288
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/input-SCVPAP.flac
Binary files differ
diff --git a/test/flac-to-flac-metadata-test-files/input-SVAUP.flac b/test/flac-to-flac-metadata-test-files/input-SVAUP.flac
new file mode 100644
index 00000000..e3fa5c18
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/input-SVAUP.flac
Binary files differ
diff --git a/test/flac-to-flac-metadata-test-files/input-VA.flac b/test/flac-to-flac-metadata-test-files/input-VA.flac
new file mode 100644
index 00000000..4fac8781
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/input-VA.flac
Binary files differ
diff --git a/test/flac-to-flac-metadata-test-files/input0.cue b/test/flac-to-flac-metadata-test-files/input0.cue
new file mode 100644
index 00000000..2894bd06
--- /dev/null
+++ b/test/flac-to-flac-metadata-test-files/input0.cue
@@ -0,0 +1,7 @@
+CATALOG 9294969890929
+FILE "blah" FLAC
+  TRACK 01 AUDIO
+    INDEX 01 00:00:00
+  TRACK 02 AUDIO
+    INDEX 01 00:00:01
+    INDEX 02 00:00:05
diff --git a/test/test_flac.sh b/test/test_flac.sh
index dee8c616..7dfc134c 100755
--- a/test/test_flac.sh
+++ b/test/test_flac.sh
@@ -23,25 +23,34 @@ die ()
         exit 1
 }
 
-if [ x = x"$1" ] ; then
+if [ x = x"$1" ] ; then
         BUILD=debug
 else
         BUILD="$1"
 fi
 
-LD_LIBRARY_PATH=../src/libFLAC/.libs:$LD_LIBRARY_PATH
-LD_LIBRARY_PATH=../src/libOggFLAC/.libs:$LD_LIBRARY_PATH
-LD_LIBRARY_PATH=../src/share/grabbag/.libs:$LD_LIBRARY_PATH
-LD_LIBRARY_PATH=../src/share/getopt/.libs:$LD_LIBRARY_PATH
-LD_LIBRARY_PATH=../src/share/replaygain_analysis/.libs:$LD_LIBRARY_PATH
-LD_LIBRARY_PATH=../src/share/replaygain_synthesis/.libs:$LD_LIBRARY_PATH
-LD_LIBRARY_PATH=../src/share/utf8/.libs:$LD_LIBRARY_PATH
-LD_LIBRARY_PATH=../obj/$BUILD/lib:$LD_LIBRARY_PATH
+# change to 'false' to show flac output (useful for debugging)
+if true ; then
+        SILENT='--silent'
+        TOTALLY_SILENT='--totally-silent'
+else
+        SILENT=''
+        TOTALLY_SILENT=''
+fi
+
+LD_LIBRARY_PATH=`pwd`/../src/libFLAC/.libs:$LD_LIBRARY_PATH
+LD_LIBRARY_PATH=`pwd`/../src/libOggFLAC/.libs:$LD_LIBRARY_PATH
+LD_LIBRARY_PATH=`pwd`/../src/share/grabbag/.libs:$LD_LIBRARY_PATH
+LD_LIBRARY_PATH=`pwd`/../src/share/getopt/.libs:$LD_LIBRARY_PATH
+LD_LIBRARY_PATH=`pwd`/../src/share/replaygain_analysis/.libs:$LD_LIBRARY_PATH
+LD_LIBRARY_PATH=`pwd`/../src/share/replaygain_synthesis/.libs:$LD_LIBRARY_PATH
+LD_LIBRARY_PATH=`pwd`/../src/share/utf8/.libs:$LD_LIBRARY_PATH
+LD_LIBRARY_PATH=`pwd`/../obj/$BUILD/lib:$LD_LIBRARY_PATH
 export LD_LIBRARY_PATH
-PATH=../src/flac:$PATH
-PATH=../src/metaflac:$PATH
-PATH=../src/test_streams:$PATH
-PATH=../obj/$BUILD/bin:$PATH
+PATH=`pwd`/../src/flac:$PATH
+PATH=`pwd`/../src/metaflac:$PATH
+PATH=`pwd`/../src/test_streams:$PATH
+PATH=`pwd`/../obj/$BUILD/bin:$PATH
 
 flac --help 1>/dev/null 2>/dev/null || die "ERROR can't find flac executable"
 
@@ -63,6 +72,13 @@ run_metaflac ()
         fi
 }
 
+md5cmp ()
+{
+        #n=`( [ -f "$1" ] && [ -f "$2" ] && metaflac --show-md5sum --no-filename "$1" "$2" 2>/dev/null || die "ERROR: comparing FLAC files $1 and $2 by MD5 sum" ) | uniq | wc -l`
+        n=`( [ -f "$1" ] && [ -f "$2" ] && metaflac --show-md5sum --no-filename "$1" "$2" 2>/dev/null || exit 1 ) | uniq | wc -l`
+        [ "$n" != "" ] && [ $n = 1 ]
+}
+
 if [ `env | grep -ic '^comspec='` != 0 ] ; then
         is_win=yes
 else
@@ -70,7 +86,7 @@ else
 fi
 
 echo "Checking for --ogg support in flac..."
-if flac --ogg --silent --force-raw-format --endian=little --sign=signed --channels=1 --bps=8 --sample-rate=44100 -c $0 1>/dev/null 2>&1 ; then
+if flac --ogg $SILENT --force-raw-format --endian=little --sign=signed --channels=1 --bps=8 --sample-rate=44100 -c $0 1>/dev/null 2>&1 ; then
         has_ogg=yes;
         echo "flac --ogg works"
 else
@@ -78,7 +94,6 @@ else
         echo "flac --ogg doesn't work"
 fi
 
-
 echo "Generating streams..."
 if [ ! -f wacky1.wav ] ; then
         test_streams || die "ERROR during test_streams"
@@ -91,28 +106,28 @@ fi
 echo "Try encoding to a file that exists; should fail"
 cp wacky1.wav exist.wav
 touch exist.flac
-if run_flac --totally-silent -0 exist.wav ; then
+if run_flac $TOTALLY_SILENT -0 exist.wav ; then
         die "ERROR: it should have failed but didn't"
 else
         echo "OK, it failed as it should"
 fi
 
 echo "Try encoding with -f to a file that exists; should succeed"
-if run_flac --totally-silent -0 --force exist.wav ; then
+if run_flac $TOTALLY_SILENT -0 --force exist.wav ; then
         echo "OK, it succeeded as it should"
 else
         die "ERROR: it should have succeeded but didn't"
 fi
 
 echo "Try decoding to a file that exists; should fail"
-if run_flac --totally-silent -d exist.flac ; then
+if run_flac $TOTALLY_SILENT -d exist.flac ; then
         die "ERROR: it should have failed but didn't"
 else
         echo "OK, it failed as it should"
 fi
 
 echo "Try decoding with -f to a file that exists; should succeed"
-if run_flac --totally-silent -d -f exist.flac ; then
+if run_flac $TOTALLY_SILENT -d -f exist.flac ; then
         echo "OK, it succeeded as it should"
 else
         die "ERROR: it should have succeeded but didn't"
@@ -131,9 +146,9 @@ rt_test_raw ()
         bytes_per_sample=`echo $f | awk -F- '{print $3}'`
         bps=`expr $bytes_per_sample '*' 8`
         echo -n "round-trip test ($f) encode... "
-        run_flac --silent --force --verify --force-raw-format --endian=little --sign=signed --sample-rate=44100 --bps=$bps --channels=$channels $f -o rt.flac || die "ERROR"
+        run_flac $SILENT --force --verify --force-raw-format --endian=little --sign=signed --sample-rate=44100 --bps=$bps --channels=$channels $f -o rt.flac || die "ERROR"
         echo -n "decode... "
-        run_flac --silent --force --decode --force-raw-format --endian=little --sign=signed -o rt.raw rt.flac || die "ERROR"
+        run_flac $SILENT --force --decode --force-raw-format --endian=little --sign=signed -o rt.raw rt.flac || die "ERROR"
         echo -n "compare... "
         cmp $f rt.raw || die "ERROR: file mismatch"
         echo "OK"
@@ -144,9 +159,9 @@ rt_test_wav ()
 {
         f="$1"
         echo -n "round-trip test ($f) encode... "
-        run_flac --silent --force --verify $f -o rt.flac || die "ERROR"
+        run_flac $SILENT --force --verify $f -o rt.flac || die "ERROR"
         echo -n "decode... "
-        run_flac --silent --force --decode -o rt.wav rt.flac || die "ERROR"
+        run_flac $SILENT --force --decode -o rt.wav rt.flac || die "ERROR"
         echo -n "compare... "
         cmp $f rt.wav || die "ERROR: file mismatch"
         echo "OK"
@@ -157,15 +172,31 @@ rt_test_aiff ()
 {
         f="$1"
         echo -n "round-trip test ($f) encode... "
-        run_flac --silent --force --verify $f -o rt.flac || die "ERROR"
+        run_flac $SILENT --force --verify $f -o rt.flac || die "ERROR"
         echo -n "decode... "
-        run_flac --silent --force --decode -o rt.aiff rt.flac || die "ERROR"
+        run_flac $SILENT --force --decode -o rt.aiff rt.flac || die "ERROR"
         echo -n "compare... "
         cmp $f rt.aiff || die "ERROR: file mismatch"
         echo "OK"
         rm -f rt.flac rt.aiff
 }
 
+# assumes input file is WAVE; does not check the metadata-preserving features of flac-to-flac; that is checked later
+rt_test_flac ()
+{
+        f="$1"
+        echo -n "round-trip test ($f->flac->flac->wav) encode... "
+        run_flac $SILENT --force --verify $f -o rt.flac || die "ERROR"
+        echo -n "re-encode... "
+        run_flac $SILENT --force --verify -o rt2.flac rt.flac || die "ERROR"
+        echo -n "decode... "
+        run_flac $SILENT --force --decode -o rt.wav rt2.flac || die "ERROR"
+        echo -n "compare... "
+        cmp $f rt.wav || die "ERROR: file mismatch"
+        echo "OK"
+        rm -f rt.wav rt.flac rt2.flac
+}
+
 for f in rt-*.raw ; do
         rt_test_raw $f
 done
@@ -175,6 +206,9 @@ done
 for f in rt-*.aiff ; do
         rt_test_aiff $f
 done
+for f in rt-*.wav ; do
+        rt_test_flac $f
+done
 
 ############################################################################
 # test --skip and --until
@@ -202,8 +236,8 @@ dd if=master.raw ibs=1 skip=10 count=30 of=50c.skip10.until40.raw 2>/dev/null ||
 dd if=master.raw ibs=1 skip=20 count=10 of=50c.skip20.until30.raw 2>/dev/null || $dddie
 dd if=master.raw ibs=1 skip=20 count=20 of=50c.skip20.until40.raw 2>/dev/null || $dddie
 
-wav_eopt="--silent --force --verify --lax"
-wav_dopt="--silent --force --decode"
+wav_eopt="$SILENT --force --verify --lax"
+wav_dopt="$SILENT --force --decode"
 
 raw_eopt="$wav_eopt --force-raw-format --endian=big --sign=signed --sample-rate=10 --bps=8 --channels=1"
 raw_dopt="$wav_dopt --force-raw-format --endian=big --sign=signed"
@@ -260,7 +294,7 @@ test_skip_until ()
         in_fmt=$1
         out_fmt=$2
 
-        [ "$in_fmt" = wav ] || [ "$in_fmt" = aiff ] || [ "$in_fmt" = raw ] || die "ERROR: internal error, bad 'in' format '$in_fmt'"
+        [ "$in_fmt" = wav ] || [ "$in_fmt" = aiff ] || [ "$in_fmt" = raw ] || [ "$in_fmt" = flac ] || die "ERROR: internal error, bad 'in' format '$in_fmt'"
 
         [ "$out_fmt" = flac ] || [ "$out_fmt" = ogg ] || die "ERROR: internal error, bad 'out' format '$out_fmt'"
 
@@ -272,6 +306,12 @@ test_skip_until ()
                 dopt="$wav_dopt"
         fi
 
+        if [ $in_fmt = flac ] && [ $out_fmt = flac ] ; then
+                CMP=md5cmp
+        else
+                CMP=cmp
+        fi
+
         if [ $out_fmt = ogg ] ; then
                 eopt="--ogg $eopt"
         fi
@@ -284,22 +324,22 @@ test_skip_until ()
 
         echo -n "testing --skip=# (encode) $desc... "
         run_flac $eopt --skip=10 -o z50c.skip10.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.skip10.$in_fmt z50c.skip10.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.$in_fmt z50c.skip10.$in_fmt || die "ERROR: file mismatch for --skip=10 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.skip10.$in_fmt z50c.skip10.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.$in_fmt z50c.skip10.$in_fmt || die "ERROR: file mismatch for --skip=10 (encode) $desc"
         rm -f z50c.skip10.$out_fmt z50c.skip10.$in_fmt
         echo OK
 
         echo -n "testing --skip=mm:ss (encode) $desc... "
         run_flac $eopt --skip=0:01 -o z50c.skip0:01.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.skip0:01.$in_fmt z50c.skip0:01.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.$in_fmt z50c.skip0:01.$in_fmt || die "ERROR: file mismatch for --skip=0:01 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.skip0:01.$in_fmt z50c.skip0:01.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.$in_fmt z50c.skip0:01.$in_fmt || die "ERROR: file mismatch for --skip=0:01 (encode) $desc"
         rm -f z50c.skip0:01.$out_fmt z50c.skip0:01.$in_fmt
         echo OK
 
         echo -n "testing --skip=mm:ss.sss (encode) $desc... "
         run_flac $eopt --skip=0:01.1001 -o z50c.skip0:01.1001.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.skip0:01.1001.$in_fmt z50c.skip0:01.1001.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip11.$in_fmt z50c.skip0:01.1001.$in_fmt || die "ERROR: file mismatch for --skip=0:01.1001 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.skip0:01.1001.$in_fmt z50c.skip0:01.1001.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip11.$in_fmt z50c.skip0:01.1001.$in_fmt || die "ERROR: file mismatch for --skip=0:01.1001 (encode) $desc"
         rm -f z50c.skip0:01.1001.$out_fmt z50c.skip0:01.1001.$in_fmt
         echo OK
 
@@ -307,22 +347,23 @@ test_skip_until ()
         # test --skip when decoding
         #
 
+        if [ $in_fmt != $out_fmt ] ; then run_flac $eopt -o z50c.$out_fmt 50c.$in_fmt ; else cp -f 50c.$in_fmt z50c.$out_fmt ; fi || die "ERROR generating FLAC file $desc"
+
         echo -n "testing --skip=# (decode) $desc... "
-        run_flac $eopt -o z50c.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
         run_flac $dopt --skip=10 -o z50c.skip10.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.$in_fmt z50c.skip10.$in_fmt || die "ERROR: file mismatch for --skip=10 (decode) $desc"
+        $CMP 50c.skip10.$in_fmt z50c.skip10.$in_fmt || die "ERROR: file mismatch for --skip=10 (decode) $desc"
         rm -f z50c.skip10.$in_fmt
         echo OK
 
         echo -n "testing --skip=mm:ss (decode) $desc... "
         run_flac $dopt --skip=0:01 -o z50c.skip0:01.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.$in_fmt z50c.skip0:01.$in_fmt || die "ERROR: file mismatch for --skip=0:01 (decode) $desc"
+        $CMP 50c.skip10.$in_fmt z50c.skip0:01.$in_fmt || die "ERROR: file mismatch for --skip=0:01 (decode) $desc"
         rm -f z50c.skip0:01.$in_fmt
         echo OK
 
         echo -n "testing --skip=mm:ss.sss (decode) $desc... "
         run_flac $dopt --skip=0:01.1001 -o z50c.skip0:01.1001.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip11.$in_fmt z50c.skip0:01.1001.$in_fmt || die "ERROR: file mismatch for --skip=0:01.1001 (decode) $desc"
+        $CMP 50c.skip11.$in_fmt z50c.skip0:01.1001.$in_fmt || die "ERROR: file mismatch for --skip=0:01.1001 (decode) $desc"
         rm -f z50c.skip0:01.1001.$in_fmt
         echo OK
 
@@ -334,43 +375,43 @@ test_skip_until ()
 
         echo -n "testing --until=# (encode) $desc... "
         run_flac $eopt --until=40 -o z50c.until40.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.until40.$in_fmt z50c.until40.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until40.$in_fmt z50c.until40.$in_fmt || die "ERROR: file mismatch for --until=40 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.until40.$in_fmt z50c.until40.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.until40.$in_fmt z50c.until40.$in_fmt || die "ERROR: file mismatch for --until=40 (encode) $desc"
         rm -f z50c.until40.$out_fmt z50c.until40.$in_fmt
         echo OK
 
         echo -n "testing --until=mm:ss (encode) $desc... "
         run_flac $eopt --until=0:04 -o z50c.until0:04.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.until0:04.$in_fmt z50c.until0:04.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until40.$in_fmt z50c.until0:04.$in_fmt || die "ERROR: file mismatch for --until=0:04 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.until0:04.$in_fmt z50c.until0:04.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.until40.$in_fmt z50c.until0:04.$in_fmt || die "ERROR: file mismatch for --until=0:04 (encode) $desc"
         rm -f z50c.until0:04.$out_fmt z50c.until0:04.$in_fmt
         echo OK
 
         echo -n "testing --until=mm:ss.sss (encode) $desc... "
         run_flac $eopt --until=0:03.9001 -o z50c.until0:03.9001.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.until0:03.9001.$in_fmt z50c.until0:03.9001.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until39.$in_fmt z50c.until0:03.9001.$in_fmt || die "ERROR: file mismatch for --until=0:03.9001 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.until0:03.9001.$in_fmt z50c.until0:03.9001.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.until39.$in_fmt z50c.until0:03.9001.$in_fmt || die "ERROR: file mismatch for --until=0:03.9001 (encode) $desc"
         rm -f z50c.until0:03.9001.$out_fmt z50c.until0:03.9001.$in_fmt
         echo OK
 
         echo -n "testing --until=-# (encode) $desc... "
         run_flac $eopt --until=-10 -o z50c.until-10.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.until-10.$in_fmt z50c.until-10.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until40.$in_fmt z50c.until-10.$in_fmt || die "ERROR: file mismatch for --until=-10 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.until-10.$in_fmt z50c.until-10.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.until40.$in_fmt z50c.until-10.$in_fmt || die "ERROR: file mismatch for --until=-10 (encode) $desc"
         rm -f z50c.until-10.$out_fmt z50c.until-10.$in_fmt
         echo OK
 
         echo -n "testing --until=-mm:ss (encode) $desc... "
         run_flac $eopt --until=-0:01 -o z50c.until-0:01.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.until-0:01.$in_fmt z50c.until-0:01.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until40.$in_fmt z50c.until-0:01.$in_fmt || die "ERROR: file mismatch for --until=-0:01 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.until-0:01.$in_fmt z50c.until-0:01.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.until40.$in_fmt z50c.until-0:01.$in_fmt || die "ERROR: file mismatch for --until=-0:01 (encode) $desc"
         rm -f z50c.until-0:01.$out_fmt z50c.until-0:01.$in_fmt
         echo OK
 
         echo -n "testing --until=-mm:ss.sss (encode) $desc... "
         run_flac $eopt --until=-0:01.1001 -o z50c.until-0:01.1001.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.until-0:01.1001.$in_fmt z50c.until-0:01.1001.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until39.$in_fmt z50c.until-0:01.1001.$in_fmt || die "ERROR: file mismatch for --until=-0:01.1001 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.until-0:01.1001.$in_fmt z50c.until-0:01.1001.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.until39.$in_fmt z50c.until-0:01.1001.$in_fmt || die "ERROR: file mismatch for --until=-0:01.1001 (encode) $desc"
         rm -f z50c.until-0:01.1001.$out_fmt z50c.until-0:01.1001.$in_fmt
         echo OK
 
@@ -378,41 +419,41 @@ test_skip_until ()
         # test --until when decoding
         #
 
-        run_flac $eopt -o z50c.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
+        if [ $in_fmt != $out_fmt ] ; then run_flac $eopt -o z50c.$out_fmt 50c.$in_fmt ; else cp -f 50c.$in_fmt z50c.$out_fmt ; fi || die "ERROR generating FLAC file $desc"
 
         echo -n "testing --until=# (decode) $desc... "
         run_flac $dopt --until=40 -o z50c.until40.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until40.$in_fmt z50c.until40.$in_fmt || die "ERROR: file mismatch for --until=40 (decode) $desc"
+        $CMP 50c.until40.$in_fmt z50c.until40.$in_fmt || die "ERROR: file mismatch for --until=40 (decode) $desc"
         rm -f z50c.until40.$in_fmt
         echo OK
 
         echo -n "testing --until=mm:ss (decode) $desc... "
         run_flac $dopt --until=0:04 -o z50c.until0:04.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until40.$in_fmt z50c.until0:04.$in_fmt || die "ERROR: file mismatch for --until=0:04 (decode) $desc"
+        $CMP 50c.until40.$in_fmt z50c.until0:04.$in_fmt || die "ERROR: file mismatch for --until=0:04 (decode) $desc"
         rm -f z50c.until0:04.$in_fmt
         echo OK
 
         echo -n "testing --until=mm:ss.sss (decode) $desc... "
         run_flac $dopt --until=0:03.9001 -o z50c.until0:03.9001.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until39.$in_fmt z50c.until0:03.9001.$in_fmt || die "ERROR: file mismatch for --until=0:03.9001 (decode) $desc"
+        $CMP 50c.until39.$in_fmt z50c.until0:03.9001.$in_fmt || die "ERROR: file mismatch for --until=0:03.9001 (decode) $desc"
         rm -f z50c.until0:03.9001.$in_fmt
         echo OK
 
         echo -n "testing --until=-# (decode) $desc... "
         run_flac $dopt --until=-10 -o z50c.until-10.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until40.$in_fmt z50c.until-10.$in_fmt || die "ERROR: file mismatch for --until=-10 (decode) $desc"
+        $CMP 50c.until40.$in_fmt z50c.until-10.$in_fmt || die "ERROR: file mismatch for --until=-10 (decode) $desc"
         rm -f z50c.until-10.$in_fmt
         echo OK
 
         echo -n "testing --until=-mm:ss (decode) $desc... "
         run_flac $dopt --until=-0:01 -o z50c.until-0:01.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until40.$in_fmt z50c.until-0:01.$in_fmt || die "ERROR: file mismatch for --until=-0:01 (decode) $desc"
+        $CMP 50c.until40.$in_fmt z50c.until-0:01.$in_fmt || die "ERROR: file mismatch for --until=-0:01 (decode) $desc"
         rm -f z50c.until-0:01.$in_fmt
         echo OK
 
         echo -n "testing --until=-mm:ss.sss (decode) $desc... "
         run_flac $dopt --until=-0:01.1001 -o z50c.until-0:01.1001.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until39.$in_fmt z50c.until-0:01.1001.$in_fmt || die "ERROR: file mismatch for --until=-0:01.1001 (decode) $desc"
+        $CMP 50c.until39.$in_fmt z50c.until-0:01.1001.$in_fmt || die "ERROR: file mismatch for --until=-0:01.1001 (decode) $desc"
         rm -f z50c.until-0:01.1001.$in_fmt
         echo OK
 
@@ -424,64 +465,64 @@ test_skip_until ()
 
         echo -n "testing --skip=10 --until=# (encode) $desc... "
         run_flac $eopt --skip=10 --until=40 -o z50c.skip10.until40.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.skip10.until40.$in_fmt z50c.skip10.until40.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until40.$in_fmt z50c.skip10.until40.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=40 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.skip10.until40.$in_fmt z50c.skip10.until40.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.until40.$in_fmt z50c.skip10.until40.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=40 (encode) $desc"
         rm -f z50c.skip10.until40.$out_fmt z50c.skip10.until40.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=mm:ss (encode) $desc... "
         run_flac $eopt --skip=10 --until=0:04 -o z50c.skip10.until0:04.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.skip10.until0:04.$in_fmt z50c.skip10.until0:04.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until40.$in_fmt z50c.skip10.until0:04.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=0:04 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.skip10.until0:04.$in_fmt z50c.skip10.until0:04.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.until40.$in_fmt z50c.skip10.until0:04.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=0:04 (encode) $desc"
         rm -f z50c.skip10.until0:04.$out_fmt z50c.skip10.until0:04.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=mm:ss.sss (encode) $desc... "
         run_flac $eopt --skip=10 --until=0:03.9001 -o z50c.skip10.until0:03.9001.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.skip10.until0:03.9001.$in_fmt z50c.skip10.until0:03.9001.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until39.$in_fmt z50c.skip10.until0:03.9001.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=0:03.9001 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.skip10.until0:03.9001.$in_fmt z50c.skip10.until0:03.9001.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.until39.$in_fmt z50c.skip10.until0:03.9001.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=0:03.9001 (encode) $desc"
         rm -f z50c.skip10.until0:03.9001.$out_fmt z50c.skip10.until0:03.9001.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=+# (encode) $desc... "
         run_flac $eopt --skip=10 --until=+30 -o z50c.skip10.until+30.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.skip10.until+30.$in_fmt z50c.skip10.until+30.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until40.$in_fmt z50c.skip10.until+30.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=+30 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.skip10.until+30.$in_fmt z50c.skip10.until+30.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.until40.$in_fmt z50c.skip10.until+30.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=+30 (encode) $desc"
         rm -f z50c.skip10.until+30.$out_fmt z50c.skip10.until+30.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=+mm:ss (encode) $desc... "
         run_flac $eopt --skip=10 --until=+0:03 -o z50c.skip10.until+0:03.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.skip10.until+0:03.$in_fmt z50c.skip10.until+0:03.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until40.$in_fmt z50c.skip10.until+0:03.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=+0:03 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.skip10.until+0:03.$in_fmt z50c.skip10.until+0:03.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.until40.$in_fmt z50c.skip10.until+0:03.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=+0:03 (encode) $desc"
         rm -f z50c.skip10.until+0:03.$out_fmt z50c.skip10.until+0:03.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=+mm:ss.sss (encode) $desc... "
         run_flac $eopt --skip=10 --until=+0:02.9001 -o z50c.skip10.until+0:02.9001.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.skip10.until+0:02.9001.$in_fmt z50c.skip10.until+0:02.9001.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until39.$in_fmt z50c.skip10.until+0:02.9001.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=+0:02.9001 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.skip10.until+0:02.9001.$in_fmt z50c.skip10.until+0:02.9001.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.until39.$in_fmt z50c.skip10.until+0:02.9001.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=+0:02.9001 (encode) $desc"
         rm -f z50c.skip10.until+0:02.9001.$out_fmt z50c.skip10.until+0:02.9001.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=-# (encode) $desc... "
         run_flac $eopt --skip=10 --until=-10 -o z50c.skip10.until-10.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.skip10.until-10.$in_fmt z50c.skip10.until-10.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until40.$in_fmt z50c.skip10.until-10.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=-10 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.skip10.until-10.$in_fmt z50c.skip10.until-10.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.until40.$in_fmt z50c.skip10.until-10.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=-10 (encode) $desc"
         rm -f z50c.skip10.until-10.$out_fmt z50c.skip10.until-10.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=-mm:ss (encode) $desc... "
         run_flac $eopt --skip=10 --until=-0:01 -o z50c.skip10.until-0:01.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.skip10.until-0:01.$in_fmt z50c.skip10.until-0:01.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until40.$in_fmt z50c.skip10.until-0:01.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=-0:01 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.skip10.until-0:01.$in_fmt z50c.skip10.until-0:01.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.until40.$in_fmt z50c.skip10.until-0:01.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=-0:01 (encode) $desc"
         rm -f z50c.skip10.until-0:01.$out_fmt z50c.skip10.until-0:01.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=-mm:ss.sss (encode) $desc... "
         run_flac $eopt --skip=10 --until=-0:01.1001 -o z50c.skip10.until-0:01.1001.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
-        run_flac $dopt -o z50c.skip10.until-0:01.1001.$in_fmt z50c.skip10.until-0:01.1001.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until39.$in_fmt z50c.skip10.until-0:01.1001.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=-0:01.1001 (encode) $desc"
+        [ $in_fmt = $out_fmt ] || run_flac $dopt -o z50c.skip10.until-0:01.1001.$in_fmt z50c.skip10.until-0:01.1001.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.until39.$in_fmt z50c.skip10.until-0:01.1001.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=-0:01.1001 (encode) $desc"
         rm -f z50c.skip10.until-0:01.1001.$out_fmt z50c.skip10.until-0:01.1001.$in_fmt
         echo OK
 
@@ -489,41 +530,42 @@ test_skip_until ()
         # test --skip and --until when decoding
         #
 
-        run_flac $eopt -o z50c.$out_fmt 50c.$in_fmt || die "ERROR generating FLAC file $desc"
+        if [ $in_fmt != $out_fmt ] ; then run_flac $eopt -o z50c.$out_fmt 50c.$in_fmt ; else cp -f 50c.$in_fmt z50c.$out_fmt ; fi || die "ERROR generating FLAC file $desc"
+
 
         echo -n "testing --skip=10 --until=# (decode) $desc... "
         run_flac $dopt --skip=10 --until=40 -o z50c.skip10.until40.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until40.$in_fmt z50c.skip10.until40.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=40 (decode) $desc"
+        $CMP 50c.skip10.until40.$in_fmt z50c.skip10.until40.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=40 (decode) $desc"
         rm -f z50c.skip10.until40.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=mm:ss (decode) $desc... "
         run_flac $dopt --skip=10 --until=0:04 -o z50c.skip10.until0:04.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until40.$in_fmt z50c.skip10.until0:04.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=0:04 (decode) $desc"
+        $CMP 50c.skip10.until40.$in_fmt z50c.skip10.until0:04.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=0:04 (decode) $desc"
         rm -f z50c.skip10.until0:04.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=mm:ss.sss (decode) $desc... "
         run_flac $dopt --skip=10 --until=0:03.9001 -o z50c.skip10.until0:03.9001.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until39.$in_fmt z50c.skip10.until0:03.9001.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=0:03.9001 (decode) $desc"
+        $CMP 50c.skip10.until39.$in_fmt z50c.skip10.until0:03.9001.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=0:03.9001 (decode) $desc"
         rm -f z50c.skip10.until0:03.9001.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=-# (decode) $desc... "
         run_flac $dopt --skip=10 --until=-10 -o z50c.skip10.until-10.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until40.$in_fmt z50c.skip10.until-10.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=-10 (decode) $desc"
+        $CMP 50c.skip10.until40.$in_fmt z50c.skip10.until-10.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=-10 (decode) $desc"
         rm -f z50c.skip10.until-10.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=-mm:ss (decode) $desc... "
         run_flac $dopt --skip=10 --until=-0:01 -o z50c.skip10.until-0:01.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until40.$in_fmt z50c.skip10.until-0:01.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=-0:01 (decode) $desc"
+        $CMP 50c.skip10.until40.$in_fmt z50c.skip10.until-0:01.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=-0:01 (decode) $desc"
         rm -f z50c.skip10.until-0:01.$in_fmt
         echo OK
 
         echo -n "testing --skip=10 --until=-mm:ss.sss (decode) $desc... "
         run_flac $dopt --skip=10 --until=-0:01.1001 -o z50c.skip10.until-0:01.1001.$in_fmt z50c.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until39.$in_fmt z50c.skip10.until-0:01.1001.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=-0:01.1001 (decode) $desc"
+        $CMP 50c.skip10.until39.$in_fmt z50c.skip10.until-0:01.1001.$in_fmt || die "ERROR: file mismatch for --skip=10 --until=-0:01.1001 (decode) $desc"
         rm -f z50c.skip10.until-0:01.1001.$in_fmt
         echo OK
 
@@ -533,16 +575,19 @@ test_skip_until ()
 test_skip_until raw flac
 test_skip_until wav flac
 test_skip_until aiff flac
+test_skip_until flac flac
 
 if [ $has_ogg = "yes" ] ; then
         test_skip_until raw ogg
         test_skip_until wav ogg
         test_skip_until aiff ogg
+        #@@@ doesn't work yet, no comparison step written since metaflac doesn't work on ogg flac yet
+        #@@@test_skip_until flac ogg
 fi
 
 echo "testing seek extremes:"
 
-run_flac --verify --force --silent --force-raw-format --endian=big --sign=signed --sample-rate=44100 --bps=16 --channels=2 --blocksize=576 noise.raw || die "ERROR generating FLAC file"
+run_flac --verify --force $SILENT --force-raw-format --endian=big --sign=signed --sample-rate=44100 --bps=16 --channels=2 --blocksize=576 noise.raw || die "ERROR generating FLAC file"
 
 if [ $is_win = no ] ; then
         total_noise_cdda_samples=`run_metaflac --show-total-samples noise.flac`
@@ -584,10 +629,6 @@ fi
 
 
 ############################################################################
-# test --skip and --until
-############################################################################
-
-############################################################################
 # test --cue
 ############################################################################
 
@@ -613,7 +654,7 @@ test_cue ()
         in_fmt=$1
         out_fmt=$2
 
-        [ "$in_fmt" = wav ] || [ "$in_fmt" = aiff ] || [ "$in_fmt" = raw ] || die "ERROR: internal error, bad 'in' format '$in_fmt'"
+        [ "$in_fmt" = wav ] || [ "$in_fmt" = aiff ] || [ "$in_fmt" = raw ] || [ "$in_fmt" = flac ] || die "ERROR: internal error, bad 'in' format '$in_fmt'"
 
         [ "$out_fmt" = flac ] || [ "$out_fmt" = ogg ] || die "ERROR: internal error, bad 'out' format '$out_fmt'"
 
@@ -625,6 +666,12 @@ test_cue ()
                 dopt="$wav_dopt"
         fi
 
+        if [ $in_fmt = flac ] && [ $out_fmt = flac ] ; then
+                CMP=md5cmp
+        else
+                CMP=cmp
+        fi
+
         if [ $out_fmt = ogg ] ; then
                 eopt="--ogg $eopt"
         fi
@@ -646,105 +693,105 @@ test_cue ()
         # TRACK 04, INDEX 01 : 0:04.00 -> sample 40
         #
         echo -n "testing --cue=- $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=- z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=- $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=- z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=- $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=1.0 $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=1.0 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=1.0 $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=1.0 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=1.0 $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=1.0- $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=1.0- z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=1.0- $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=1.0- z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=1.0- $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=1.1 $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=1.1 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=1.1 $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=1.1 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=1.1 $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=1.1- $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=1.1- z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=1.1- $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=1.1- z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=1.1- $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=1.2 $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=1.2 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=1.2 $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=1.2 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=1.2 $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=1.2- $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=1.2- z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=1.2- $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=1.2- z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=1.2- $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=1.4 $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=1.4 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip20.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=1.4 $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=1.4 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip20.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=1.4 $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=1.4- $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=1.4- z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip20.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=1.4- $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=1.4- z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip20.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=1.4- $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=-5.0 $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=-5.0 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=-5.0 $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=-5.0 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=-5.0 $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=-4.1 $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=-4.1 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until40.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=-4.1 $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=-4.1 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.until40.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=-4.1 $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=-3.1 $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=-3.1 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until40.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=-3.1 $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=-3.1 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.until40.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=-3.1 $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=-1.4 $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=-1.4 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.until30.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=-1.4 $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=-1.4 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.until30.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=-1.4 $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=1.0-5.0 $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=1.0-5.0 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=1.0-5.0 $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=1.0-5.0 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=1.0-5.0 $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=1.1-5.0 $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=1.1-5.0 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=1.1-5.0 $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=1.1-5.0 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=1.1-5.0 $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=1.2-4.1 $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=1.2-4.1 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip10.until40.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=1.2-4.1 $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=1.2-4.1 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip10.until40.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=1.2-4.1 $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         echo -n "testing --cue=1.4-2.0 $desc... "
-        run_flac $dopt -o z50c.cue.$in_fmt --cue=1.4-2.0 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
-        cmp 50c.skip20.until30.$in_fmt z50c.cue.$in_fmt || die "ERROR: file mismatch for --cue=1.4-2.0 $desc"
-        rm -f z50c.cue.$in_fmt
+        run_flac $dopt -o z50c.cued.$in_fmt --cue=1.4-2.0 z50c.cue.$out_fmt || die "ERROR decoding FLAC file $desc"
+        $CMP 50c.skip20.until30.$in_fmt z50c.cued.$in_fmt || die "ERROR: file mismatch for --cue=1.4-2.0 $desc"
+        rm -f z50c.cued.$in_fmt
         echo OK
 
         rm -f z50c.cue.$out_fmt
@@ -753,11 +800,14 @@ test_cue ()
 test_cue raw flac
 test_cue wav flac
 test_cue aiff flac
+test_cue flac flac
 
 if [ $has_ogg = "yes" ] ; then
         test_cue raw ogg
         test_cue wav ogg
         test_cue aiff ogg
+        #@@@ doesn't work yet, no comparison step written since metaflac doesn't work on ogg flac yet
+        #@@@test_cue flac ogg
 fi
 
 ############################################################################
@@ -824,29 +874,35 @@ rm -f noise.aiff fixup.aiff fixup.flac
 echo "Generating multiple input files from noise..."
 multifile_format_decode="--endian=big --sign=signed"
 multifile_format_encode="$multifile_format_decode --sample-rate=44100 --bps=16 --channels=2"
-run_flac --verify --force --silent --force-raw-format $multifile_format_encode noise.raw || die "ERROR generating FLAC file"
-run_flac --decode --force --silent noise.flac || die "ERROR generating WAVE file"
-run_flac --decode --force --silent noise.flac -o noise.aiff || die "ERROR generating AIFF file"
-rm -f noise.flac
-cp noise.wav file0.wav
-cp noise.wav file1.wav
-cp noise.wav file2.wav
-rm -f noise.wav
-cp noise.aiff file0.aiff
-cp noise.aiff file1.aiff
-cp noise.aiff file2.aiff
-rm -f noise.aiff
-cp noise.raw file0.raw
-cp noise.raw file1.raw
-cp noise.raw file2.raw
+short_noise_cdda_samples=`expr $total_noise_cdda_samples / 8`
+run_flac --verify --force $SILENT --force-raw-format $multifile_format_encode --until=$short_noise_cdda_samples -o shortnoise.flac noise.raw || die "ERROR generating FLAC file"
+run_flac --decode --force $SILENT shortnoise.flac -o shortnoise.raw --force-raw-format $multifile_format_decode || die "ERROR generating RAW file"
+run_flac --decode --force $SILENT shortnoise.flac || die "ERROR generating WAVE file"
+run_flac --decode --force $SILENT shortnoise.flac -o shortnoise.aiff || die "ERROR generating AIFF file"
+cp shortnoise.flac file0.flac
+cp shortnoise.flac file1.flac
+cp shortnoise.flac file2.flac
+rm -f shortnoise.flac
+cp shortnoise.wav file0.wav
+cp shortnoise.wav file1.wav
+cp shortnoise.wav file2.wav
+rm -f shortnoise.wav
+cp shortnoise.aiff file0.aiff
+cp shortnoise.aiff file1.aiff
+cp shortnoise.aiff file2.aiff
+rm -f shortnoise.aiff
+cp shortnoise.raw file0.raw
+cp shortnoise.raw file1.raw
+cp shortnoise.raw file2.raw
+rm -f shortnoise.raw
 # create authoritative sector-aligned files for comparison
-file0_samples=`expr \( $total_noise_cdda_samples / 588 \) \* 588`
-file0_remainder=`expr $total_noise_cdda_samples - $file0_samples`
-file1_samples=`expr \( \( $file0_remainder + $total_noise_cdda_samples \) / 588 \) \* 588`
-file1_remainder=`expr $file0_remainder + $total_noise_cdda_samples - $file1_samples`
+file0_samples=`expr \( $short_noise_cdda_samples / 588 \) \* 588`
+file0_remainder=`expr $short_noise_cdda_samples - $file0_samples`
+file1_samples=`expr \( \( $file0_remainder + $short_noise_cdda_samples \) / 588 \) \* 588`
+file1_remainder=`expr $file0_remainder + $short_noise_cdda_samples - $file1_samples`
 file1_samples=`expr $file1_samples - $file0_remainder`
-file2_samples=`expr \( \( $file1_remainder + $total_noise_cdda_samples \) / 588 \) \* 588`
-file2_remainder=`expr $file1_remainder + $total_noise_cdda_samples - $file2_samples`
+file2_samples=`expr \( \( $file1_remainder + $short_noise_cdda_samples \) / 588 \) \* 588`
+file2_remainder=`expr $file1_remainder + $short_noise_cdda_samples - $file2_samples`
 file2_samples=`expr $file2_samples - $file1_remainder`
 if [ $file2_remainder != '0' ] ; then
         file2_samples=`expr $file2_samples + $file2_remainder`
@@ -864,13 +920,13 @@ dd if=/dev/zero ibs=4 count=$file2_remainder of=z.raw 2>/dev/null || $dddie
 cat z.raw >> file2s.raw || die "ERROR: cat-ing sector-aligned files"
 rm -f z.raw
 
-convert_to_wav file0s "$multifile_format_encode --force" "--silent --force --decode" || die "ERROR creating authoritative sector-aligned WAVE"
-convert_to_wav file1s "$multifile_format_encode --force" "--silent --force --decode" || die "ERROR creating authoritative sector-aligned WAVE"
-convert_to_wav file2s "$multifile_format_encode --force" "--silent --force --decode" || die "ERROR creating authoritative sector-aligned WAVE"
+convert_to_wav file0s "$multifile_format_encode --force" "$SILENT --force --decode" || die "ERROR creating authoritative sector-aligned WAVE"
+convert_to_wav file1s "$multifile_format_encode --force" "$SILENT --force --decode" || die "ERROR creating authoritative sector-aligned WAVE"
+convert_to_wav file2s "$multifile_format_encode --force" "$SILENT --force --decode" || die "ERROR creating authoritative sector-aligned WAVE"
 
-convert_to_aiff file0s "$multifile_format_encode --force" "--silent --force --decode" || die "ERROR creating authoritative sector-aligned AIFF"
-convert_to_aiff file1s "$multifile_format_encode --force" "--silent --force --decode" || die "ERROR creating authoritative sector-aligned AIFF"
-convert_to_aiff file2s "$multifile_format_encode --force" "--silent --force --decode" || die "ERROR creating authoritative sector-aligned AIFF"
+convert_to_aiff file0s "$multifile_format_encode --force" "$SILENT --force --decode" || die "ERROR creating authoritative sector-aligned AIFF"
+convert_to_aiff file1s "$multifile_format_encode --force" "$SILENT --force --decode" || die "ERROR creating authoritative sector-aligned AIFF"
+convert_to_aiff file2s "$multifile_format_encode --force" "$SILENT --force --decode" || die "ERROR creating authoritative sector-aligned AIFF"
 
 test_multifile ()
 {
@@ -901,18 +957,24 @@ test_multifile ()
                 encode_options="$encode_options --sector-align"
         fi
 
-        run_flac --force $encode_options $extra_encode_options file0.$input_type file1.$input_type file2.$input_type || die "ERROR"
+        if [ $input_type = flac ] ; then
+                CMP=md5cmp
+        else
+                CMP=cmp
+        fi
+
         for n in 0 1 2 ; do
-                mv file$n.$suffix file${n}x.$suffix
+                cp file$n.$input_type file${n}x.$input_type
         done
+        run_flac --force $encode_options $extra_encode_options file0x.$input_type file1x.$input_type file2x.$input_type || die "ERROR"
         run_flac --force --decode $extra_decode_options file0x.$suffix file1x.$suffix file2x.$suffix || die "ERROR"
         if [ $sector_align != sector_align ] ; then
                 for n in 0 1 2 ; do
-                        cmp file$n.$input_type file${n}x.$input_type || die "ERROR: file mismatch on file #$n"
+                        $CMP file$n.$input_type file${n}x.$input_type || die "ERROR: file mismatch on file #$n"
                 done
         else
                 for n in 0 1 2 ; do
-                        cmp file${n}s.$input_type file${n}x.$input_type || die "ERROR: file mismatch on file #$n"
+                        $CMP file${n}s.$input_type file${n}x.$input_type || die "ERROR: file mismatch on file #$n"
                 done
         fi
         for n in 0 1 2 ; do
@@ -920,18 +982,20 @@ test_multifile ()
         done
 }
 
-for input_type in raw wav aiff ; do
+for input_type in raw wav aiff flac ; do
         echo "Testing multiple $input_type files without verify..."
         test_multifile $input_type flac no_sector_align ""
 
         echo "Testing multiple $input_type files with verify..."
         test_multifile $input_type flac no_sector_align "--verify"
 
-        echo "Testing multiple $input_type files with --sector-align, without verify..."
-        test_multifile $input_type flac sector_align ""
+        if [ $input_type != flac ] ; then # --sector-align not supported for FLAC input
+                echo "Testing multiple $input_type files with --sector-align, without verify..."
+                test_multifile $input_type flac sector_align ""
 
-        echo "Testing multiple $input_type files with --sector-align, with verify..."
-        test_multifile $input_type flac sector_align "--verify"
+                echo "Testing multiple $input_type files with --sector-align, with verify..."
+                test_multifile $input_type flac sector_align "--verify"
+        fi
 
         if [ $has_ogg = "yes" ] ; then
                 echo "Testing multiple $input_type files with --ogg, without verify..."
@@ -940,13 +1004,87 @@ for input_type in raw wav aiff ; do
                 echo "Testing multiple $input_type files with --ogg, with verify..."
                 test_multifile $input_type ogg no_sector_align "--verify"
 
-                echo "Testing multiple $input_type files with --ogg and --sector-align, without verify..."
-                test_multifile $input_type ogg sector_align ""
+                if [ $input_type != flac ] ; then # --sector-align not supported for FLAC input
+                        echo "Testing multiple $input_type files with --ogg and --sector-align, without verify..."
+                        test_multifile $input_type ogg sector_align ""
 
-                echo "Testing multiple $input_type files with --ogg and --sector-align, with verify..."
-                test_multifile $input_type ogg sector_align "--verify"
+                        echo "Testing multiple $input_type files with --ogg and --sector-align, with verify..."
+                        test_multifile $input_type ogg sector_align "--verify"
+                fi
 
                 echo "Testing multiple $input_type files with --ogg and --serial-number, with verify..."
                 test_multifile $input_type ogg no_sector_align "--serial-number=321 --verify"
         fi
 done
+
+
+############################################################################
+# test the metadata-handling properties of flac-to-flac encoding
+############################################################################
+
+echo "Testing the metadata-handling properties of flac-to-flac encoding..."
+
+testdir="flac-to-flac-metadata-test-files"
+filter ()
+{
+        # minor danger, changing vendor strings will change the length of the
+        # VORBIS_COMMENT block, but if we add "^  length: " to the patterns,
+        # we lose info about PADDING size that we need
+        grep -Ev '^  vendor string: |^  m..imum .....size: ' | sed -e 's/, stream_offset.*//'
+}
+flac2flac ()
+{
+        file="$1"
+        case="$2"
+        args="$3"
+        expect="$case-expect.meta"
+        echo -n "$case... "
+        run_flac $SILENT -f -o out.flac $args $file || die "ERROR encoding FLAC file"
+        run_metaflac --list out.flac | filter > out.meta || die "ERROR listing metadata of output FLAC file"
+        diff -q -w $expect out.meta 2>/dev/null || die "ERROR: metadata does not match expected $expect"
+        echo OK
+}
+
+#filter=', stream_offset.*|^  vendor string: |^  length: |^  m..imum .....size: '
+cd $testdir || die "ERROR changing to directory $testdir"
+
+# case 00a: no alterations on a file with all metadata types, keep all metadata, in same order
+flac2flac input-SCVAUP.flac case00a ""
+# case 01a: on file with multiple PADDING blocks, they should be aggregated into one at the end
+flac2flac input-SCVPAP.flac case01a ""
+# case 01b: on file with multiple PADDING blocks and --no-padding specified, they should all be deleted
+flac2flac input-SCVPAP.flac case01b "--no-padding"
+# case 01c: on file with multiple PADDING blocks and -P specified, they should all be overwritten with -P value
+flac2flac input-SCVPAP.flac case01c "-P 1234"
+# case 01d: on file with no PADDING blocks, use -P setting
+flac2flac input-SCVA.flac case01d "-P 1234"
+# case 01e: on file with no PADDING blocks and no -P given, use default padding
+flac2flac input-SCVA.flac case01e ""
+# case 02a: on file with no VORBIS_COMMENT block, add new VORBIS_COMMENT
+flac2flac input-SCPAP.flac case02a ""
+# case 02b: on file with no VORBIS_COMMENT block and --tag, add new VORBIS_COMMENT with tags
+flac2flac input-SCPAP.flac case02b "--tag=artist=0"
+# case 02c: on file with VORBIS_COMMENT block and --tag, replace existing VORBIS_COMMENT with new tags
+flac2flac input-SCVAUP.flac case02c "$TOTALLY_SILENT --tag=artist=0"
+# case 03a: on file with no CUESHEET block and --cuesheet specified, add it
+flac2flac input-SVAUP.flac case03a "--cuesheet=input0.cue"
+# case 03b: on file with CUESHEET block and --cuesheet specified, overwrite existing CUESHEET
+flac2flac input-SCVAUP.flac case03b "$TOTALLY_SILENT --cuesheet=input0.cue"
+# case 03c: on file with CUESHEET block and size-changing option specified, drop existing CUESHEET
+flac2flac input-SCVAUP.flac case03c "$TOTALLY_SILENT --skip=1"
+# case 04a: on file with no SEEKTABLE block and --no-seektable specified, no SEEKTABLE
+flac2flac input-VA.flac case04a "--no-padding --no-seektable"
+# case 04b: on file with no SEEKTABLE block and -S specified, new SEEKTABLE
+flac2flac input-VA.flac case04b "--no-padding -S 5x"
+# case 04c: on file with no SEEKTABLE block and no seektable options specified, new SEEKTABLE with default points
+flac2flac input-VA.flac case04c "--no-padding"
+# case 04d: on file with SEEKTABLE block and --no-seektable specified, drop existing SEEKTABLE
+flac2flac input-SCVA.flac case04d "--no-padding --no-seektable"
+# case 04e: on file with SEEKTABLE block and -S specified, overwrite existing SEEKTABLE
+flac2flac input-SCVA.flac case04e "$TOTALLY_SILENT --no-padding -S 5x"
+# case 04f: on file with SEEKTABLE block and size-changing option specified, drop existing SEEKTABLE, new SEEKTABLE with default points
+#(already covered by case03c)
+
+rm -f out.flac out.meta
+
+cd ..