ref: af257fcf44a4bb60b8ecb593fae7fcb16290c525
parent: c58705f3fb68ede18ec726e3852c3a0cc2057337
author: cbagwell <cbagwell>
date: Thu Sep 9 22:54:18 EDT 2004
Fadeout bugfix and new crossfade script
--- a/Changelog
+++ b/Changelog
@@ -32,6 +32,10 @@
the input file, it changes volume before effects engine
and when specified with output file, its done after effects
engine.
+ o Added crossfade_cat.sh script that will concatenate to
+ audio files and do a crossfade between them.
+ o Fixed bug in fade effect were it was impossible to do a
+ fadeout starting from the beginning of the audio file.
sox-12.17.5
-----------
--- /dev/null
+++ b/scripts/crossfade_cat.sh
@@ -1,0 +1,85 @@
+#!/bin/bash
+#
+# crossfade_cat.sh
+#
+# Original script from Kester Clegg. Mods by Chris Bagwell to show
+# more examples of sox features.
+# Concatenates two files together with a crossfade of $1 seconds.
+# Filenames are specified as $2 and $3.
+#
+# By default, script fades out first file and fades in second file.
+# This makes sure that we can mix the two files together with
+# no clipping of audio. If that option is overridden then the
+# user must make sure no clipping can occur themselves.
+#
+# $4 is optional and specifies if a fadeout should be performed on
+# first file.
+# $5 is optional and specifies if a fadein should be performed on
+# second file.
+#
+# Crossfaded file is created as "mix.wav".
+
+SOX=/home/cbagwell/sox/src/sox
+SOXMIX=/home/cbagwell/sox/src/soxmix
+
+if [ "$3" == "" ]; then
+ echo "Usage: $0 crossfade_seconds first_file second_file [ fadeout ] [ fadein ]"
+ echo
+ echo "If a fadeout or fadein is not desire then specify \"no\" for that option"
+ exit 1
+fi
+
+fade_length=$1
+first_file=$2
+second_file=$3
+
+fade_first="yes"
+if [ "$4" != "" ]; then
+ fade_first=$4
+fi
+
+fade_second="yes"
+if [ "$5" != "" ]; then
+ fade_second=$5
+fi
+
+fade_first_opts=
+if [ "$fade_first" == "yes" ]; then
+ fade_first_opts="fade h 0 0:0:$fade_length"
+fi
+
+fade_second_opts=
+if [ "$fade_second" == "yes" ]; then
+ fade_second_opts="fade h 0:0:$fade_length"
+fi
+
+echo "crossfade and concatenate files"
+echo
+echo "Finding length of $first_file..."
+first_length=`$SOX "$first_file" 2>&1 -e stat | grep Length | cut -d : -f 2 | cut -d . -f 1 | cut -f 1`
+echo "Length is $first_length"
+
+trim_length=`expr $first_length - $fade_length`
+
+# Get crossfade section from first file and optionally do the fade out
+echo "Obtaining $fade_length seconds of fade out portion from $first_file..."
+$SOX "$first_file" -s -w fadeout.wav trim $trim_length $fade_first_opts
+# Get the crossfade section from the second file and optionally do the fade in
+echo "Obtaining $fade_length seconds of fade in portion from $second_file..."
+$SOX "$second_file" -s -w fadein.wav trim 0 $fade_length $fade_second_opts
+# Mix the crossfade files together at full volume
+echo "Crossfading..."
+$SOXMIX -v 1.0 fadeout.wav -v 1.0 fadein.wav crossfade.wav
+
+echo "Trimming off crossfade sections from original files..."
+
+$SOX "$first_file" -s -w song1.wav trim 0 $trim_length
+$SOX "$second_file" -s -w song2.wav trim $fade_length
+$SOX song1.wav crossfade.wav song2.wav mix.wav
+
+echo -e "Removing temporary files...\n"
+rm fadeout.wav fadein.wav crossfade.wav song1.wav song2.wav
+mins=`expr $trim_length / 60`
+secs=`expr $trim_length % 60`
+echo "The crossfade in mix.wav occurs at around $mins mins $secs secs"
+
--- a/sox.1
+++ b/sox.1
@@ -840,8 +840,9 @@
For fade-outs, the audio data will be truncated at the stop-time and
the volume will be ramped from full volume down to 0 starting at
-\fIfade-out-length\fR seconds before the \fIstop-time\fR. No fade-out
-is performed if these options are not specified.
+\fIfade-out-length\fR seconds before the \fIstop-time\fR. If fade-out-length
+is not specified, it defaults to the same value as fade-in-length.
+No fade-out is performed if the stop-time is not specified.
.br
All times can be specified in either periods of time or sample counts.
To specify time periods use the format hh:mm:ss.frac format. To specify
--- a/sox.txt
+++ b/sox.txt
@@ -668,8 +668,10 @@
For fade-outs, the audio data will be truncated at the stop-
time and the volume will be ramped from full volume down to 0
- starting at fade-out-length seconds before the stop-time. No
- fade-out is performed if these options are not specified.
+ starting at fade-out-length seconds before the stop-time. If
+ fade-out-length is not specified, it defaults to the same
+ value as fade-in-length. No fade-out is performed if the
+ stop-time is not specified.
All times can be specified in either periods of time or sam-
ple counts. To specify time periods use the format
hh:mm:ss.frac format. To specify using sample counts, spec-
--- a/src/fade.c
+++ b/src/fade.c
@@ -30,10 +30,11 @@
st_size_t in_start, in_stop, out_start, out_stop, samplesdone;
char *in_stop_str, *out_start_str, *out_stop_str;
char in_fadetype, out_fadetype;
+ char do_out;
int endpadwarned;
} *fade_t;
-#define FADE_USAGE "Usage: fade [ type ] fade-in-length [ stop-time [ fade-out-length ] ]\nTimes in seconds.\nFade type one of q, h, t, l or p.\n"
+#define FADE_USAGE "Usage: fade [ type ] fade-in-length [ stop-time [ fade-out-length ] ]\nTimes is hh:mm:ss.fac format.\nFade type one of q, h, t, l or p.\n"
/* prototypes */
static double fade_gain(st_size_t index, st_size_t range, char fadetype);
@@ -86,10 +87,10 @@
strcpy(fade->in_stop_str,argv[0]);
/* Do a dummy parse to see if it will fail */
if (st_parsesamples(0, fade->in_stop_str, &fade->in_stop, 't') !=
- ST_SUCCESS)
+ ST_SUCCESS)
{
- st_fail(FADE_USAGE);
- return(ST_EOF);
+ st_fail(FADE_USAGE);
+ return(ST_EOF);
}
fade->out_start_str = fade->out_stop_str = 0;
@@ -107,13 +108,13 @@
}
strcpy(fade->out_stop_str,argv[t_argno]);
- /* Do a dummy parse to see if it will fail */
- if (st_parsesamples(0, fade->out_stop_str,
- &fade->out_stop, 't') != ST_SUCCESS)
- {
- st_fail(FADE_USAGE);
- return(ST_EOF);
- }
+ /* Do a dummy parse to see if it will fail */
+ if (st_parsesamples(0, fade->out_stop_str,
+ &fade->out_stop, 't') != ST_SUCCESS)
+ {
+ st_fail(FADE_USAGE);
+ return(ST_EOF);
+ }
}
else
{
@@ -125,13 +126,13 @@
}
strcpy(fade->out_start_str,argv[t_argno]);
- /* Do a dummy parse to see if it will fail */
- if (st_parsesamples(0, fade->out_start_str,
- &fade->out_start, 't') != ST_SUCCESS)
- {
- st_fail(FADE_USAGE);
- return(ST_EOF);
- }
+ /* Do a dummy parse to see if it will fail */
+ if (st_parsesamples(0, fade->out_start_str,
+ &fade->out_start, 't') != ST_SUCCESS)
+ {
+ st_fail(FADE_USAGE);
+ return(ST_EOF);
+ }
}
} /* End for(t_argno) */
@@ -155,9 +156,11 @@
return(ST_EOF);
}
+ fade->do_out = 0;
/* See if user specified a stop time */
if (fade->out_stop_str)
{
+ fade->do_out = 1;
if (st_parsesamples(effp->ininfo.rate, fade->out_stop_str,
&fade->out_stop, 't') != ST_SUCCESS)
{
@@ -164,31 +167,30 @@
st_fail(FADE_USAGE);
return(ST_EOF);
}
- fade->out_stop += fade->out_start;
- /* See if user wants to fade out. */
- if (fade->out_start_str)
- {
- if (st_parsesamples(effp->ininfo.rate, fade->out_start_str,
- &fade->out_start, 't') != ST_SUCCESS)
- {
- st_fail(FADE_USAGE);
- return(ST_EOF);
- }
- /* Fade time is relative to stop time. */
- fade->out_start = fade->out_stop - fade->out_start;
+ /* See if user wants to fade out. */
+ if (fade->out_start_str)
+ {
+ if (st_parsesamples(effp->ininfo.rate, fade->out_start_str,
+ &fade->out_start, 't') != ST_SUCCESS)
+ {
+ st_fail(FADE_USAGE);
+ return(ST_EOF);
+ }
+ /* Fade time is relative to stop time. */
+ fade->out_start = fade->out_stop - fade->out_start;
- }
- else
- /* If user doesn't want to fade out then set to stop
- * time.
- */
- fade->out_start = fade->out_stop;
+ }
+ else
+ /* If no start time specified, assume everything
+ * after fadein.
+ */
+ fade->out_start = fade->in_stop;
}
else
- /* If not specified then user doesn't wants to process all
- * of file. Use a value of zero to indicate this.
- */
+ /* If not specified then user doesn't wants to process all
+ * of file. Use a value of zero to indicate this.
+ */
fade->out_stop = 0;
/* Sanity check for fade times vs total time */
@@ -211,7 +213,7 @@
* Return number of samples processed.
*/
int st_fade_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf,
- st_size_t *isamp, st_size_t *osamp)
+ st_size_t *isamp, st_size_t *osamp)
{
fade_t fade = (fade_t) effp->priv;
/* len is total samples, chcnt counts channels */
@@ -239,12 +241,12 @@
} /* endif fade-in */
if (fade->samplesdone >= fade->in_stop &&
- (fade->out_start == 0 || fade->samplesdone < fade->out_start))
+ (!fade->do_out || fade->samplesdone < fade->out_start))
{ /* steady gain phase */
*obuf = t_ibuf;
} /* endif steady phase */
- if (fade->out_start != 0 && fade->samplesdone >= fade->out_start)
+ if (fade->do_out && fade->samplesdone >= fade->out_start)
{ /* fade-out phase, decrease gain */
*obuf = t_ibuf *
fade_gain(fade->out_stop - fade->samplesdone,