ref: a823e49837cabf1f3a21ec94c076cd4bfeda6697
parent: 4610e33750d1d51d1d88081a6391ecdc446f36d6
author: Ulrich Klauer <ulrich@chirlu.de>
date: Mon Jan 23 03:01:44 EST 2012
Fix optimize_trim() in multiple effects chain mode Try the optimize_trim() hack only at the very start of processing, but not after switching to another effects chain or restarting the first. It would otherwise seek relative to the beginning of the input file, changing the semantics of the command instead of just providing a speed improvement. To make doubly sure and developers aware of the trap, check for the condition both within optimize_trim() and in process() where it is called. To illustrate the bug fixed by this commit, consider the command line play example trim 1s 10 : trim 1s 10 which is now (correctly) almost equivalent to play example trim 0 20 but was similar to play example trim 0 10 repeat before, at least in case "example" was a seekable file. The problem was concealed in many cases (e.g., the command line sox infile.wav output.wav trim 0 30 : newfile : restart given as an example in the man page) by the fact that optimize_trim() didn't kick in when the offset was zero.
--- a/ChangeLog
+++ b/ChangeLog
@@ -87,6 +87,7 @@
divisible by the number of channels. [3420899] (Ulrich Klauer)
o Complete rewrite of the trim effect with extended syntax (backwards
compatible) and capabilities. [FR 2941349] (Ulrich Klauer)
+ o Fix trim optimization unexpectedly seeking backwards. (Ulrich Klauer)
Misc:
--- a/src/sox.c
+++ b/src/sox.c
@@ -181,6 +181,10 @@
static unsigned *nuser_effects = NULL; /* array: number of effects in each chain */
static int current_eff_chain = 0;
static int eff_chain_count = 0;
+static sox_bool very_first_effchain = sox_true;
+ /* Indicates that not only the first effects chain is in effect (hrm), but
+ also that it has never been restarted. Only then we may use the
+ optimize_trim() hack. */
static char *effects_filename = NULL;
static char * play_rate_arg = NULL;
static char *norm_level = NULL;
@@ -1125,6 +1129,8 @@
{
sox_bool reuse_output = sox_true;
+ very_first_effchain = sox_false;
+
/* If input file reached EOF then delete all effects in current
* chain and restart the current chain.
*
@@ -1387,10 +1393,13 @@
* "effect descriptor" and see what the start location is. This has to be
* done after its start() is called to have the correct location. Also, only
* do this when only working with one input file. This is because the logic
- * to do it for multiple files is complex and problably never used. This
- * hack is a huge time savings when trimming gigs of audio data into
- * managable chunks. */
- if (input_count == 1 && effects_chain->length > 1 && strcmp(effects_chain->effects[1][0].handler.name, "trim") == 0) {
+ * to do it for multiple files is complex and probably never used. The same
+ * is true for a restarted or additional effects chain (relative positioning
+ * within the file and possible samples still buffered in the input effect
+ * would have to be taken into account). This hack is a huge time savings
+ * when trimming gigs of audio data into managable chunks. */
+ if (input_count == 1 && very_first_effchain && effects_chain->length > 1 &&
+ strcmp(effects_chain->effects[1][0].handler.name, "trim") == 0) {
if (files[0]->ft->handler.seek && files[0]->ft->seekable){
uint64_t offset = sox_trim_get_start(&effects_chain->effects[1][0]);
if (offset && sox_seek(files[0]->ft, offset, SOX_SEEK_SET) == SOX_SUCCESS) {
@@ -1737,7 +1746,8 @@
&ofile->ft->encoding);
add_effects(effects_chain);
- optimize_trim();
+ if (very_first_effchain)
+ optimize_trim();
#if defined(HAVE_TERMIOS_H) || defined(HAVE_CONIO_H)
if (stdin_is_a_tty) {