shithub: sox

Download patch

ref: a0f8a662f93dfc9a22380c8064d56298c9f664df
parent: 2a130249d1cb39e17963d03ef0b1108f5debbafe
author: cbagwell <cbagwell>
date: Tue Sep 21 22:11:59 EDT 2004

Modify crossfade scripts to auto-detect when fading doesn't need to occur.

--- a/scripts/crossfade.sh
+++ b/scripts/crossfade.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# crossfade_cat.sh
+# crossfade.sh
 #
 # Original script from Kester Clegg.  Mods by Chris Bagwell to show
 # more examples of sox features.
@@ -14,11 +14,15 @@
 #
 # 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.
+# By default, the script attempts to guess if the audio files
+# already have a fadein/out on them or if they just have really
+# low volumes that won't cause clipping when mixxing.  If this
+# is not detected then the script will perform a fade in/out to
+# prevent clipping.
 #
+# The user may specify "yes" or "no" to force the fade in/out
+# to occur.  They can also specify "auto" which is the default.
+#
 # $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
@@ -33,7 +37,7 @@
 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"
+    echo "If a fadeout or fadein is not desired then specify \"no\" for that option.  \"yes\" will force a fade and \"auto\" will try to detect if a fade should occur."
     exit 1
 fi
 
@@ -41,23 +45,23 @@
 first_file=$2
 second_file=$3
 
-fade_first="yes"
+fade_first="auto"
 if [ "$4" != "" ]; then
     fade_first=$4
 fi
 
-fade_second="yes"
+fade_second="auto"
 if [ "$5" != "" ]; then
     fade_second=$5
 fi
 
 fade_first_opts=
-if [ "$fade_first" == "yes" ]; then
+if [ "$fade_first" != "no" ]; then
     fade_first_opts="fade t 0 0:0:$fade_length"
 fi
 
 fade_second_opts=
-if [ "$fade_second" == "yes" ]; then
+if [ "$fade_second" != "no" ]; then
     fade_second_opts="fade t 0:0:$fade_length"
 fi
 
@@ -72,13 +76,47 @@
 
 # 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
+$SOX "$first_file" -s -w fadeout1.wav trim $trim_length $fade_first_opts
+
+# When user specifies "auto" try to guess if a fadeout is needed.
+# "RMS amplitude" from the stat effect is effectively an average
+# value of samples for the whole fade length file.  If it seems
+# quite then assume a fadeout has already been done.  An RMS value
+# of 0.1 was just obtained from trail and error.
+if [ "$fade_first" == "auto" ]; then
+    RMS=`$SOX fadeout1.wav 2>&1 -e stat | grep RMS | grep amplitude | cut -d : -f 2 | cut -f 1`
+    should_fade=`echo "$RMS > 0.1" | bc`
+    if [ $should_fade == 0 ]; then
+        echo "Auto mode decided not to fadeout with RMS of $RMS"
+        fade_first_opts=""
+    else
+        echo "Auto mode will fadeout"
+    fi
+fi
+
+$SOX fadeout1.wav fadeout2.wav $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
+$SOX "$second_file" -s -w fadein1.wav trim 0 $fade_length
+
+# For auto, do similar thing as for fadeout.
+if [ "$fade_second" == "auto" ]; then
+    RMS=`$SOX fadein1.wav 2>&1 -e stat | grep RMS | grep amplitude | cut -d : -f 2 | cut -f 1`
+    should_fade=`echo "$RMS > 0.1" | bc`
+    if [ $should_fade == 0 ]; then
+        echo "Auto mode decided not to fadein with RMS of $RMS"
+        fade_second_opts=""
+    else
+        echo "Auto mode will fadein"
+    fi
+fi
+
+$SOX fadein1.wav fadein2.wav $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
+$SOXMIX -v 1.0 fadeout2.wav -v 1.0 fadein2.wav crossfade.wav
 
 echo "Spliting crossfade into $crossfade_split_length lengths"
 $SOX crossfade.wav crossfade1.wav trim 0 $crossfade_split_length
@@ -94,7 +132,7 @@
 $SOX crossfade2.wav song2.wav "cfi_${second_file}.wav"
 
 echo -e "Removing temporary files...\n" 
-rm fadeout.wav fadein.wav crossfade.wav crossfade1.wav crossfade2.wav song1.wav song2.wav
+rm fadeout1.wav fadeout2.wav fadein1.wav fadein2.wav crossfade.wav crossfade1.wav crossfade2.wav song1.wav song2.wav
 mins=`echo "$trim_length / 60" | bc`
 secs=`echo "$trim_length % 60" | bc`
 echo "The crossfade occurs at around $mins mins $secs secs in $first_file"
--- a/scripts/crossfade_cat.sh
+++ b/scripts/crossfade_cat.sh
@@ -7,11 +7,15 @@
 # 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.
+# By default, the script attempts to guess if the audio files
+# already have a fadein/out on them or if they just have really
+# low volumes that won't cause clipping when mixxing.  If this
+# is not detected then the script will perform a fade in/out to
+# prevent clipping.
 #
+# The user may specify "yes" or "no" to force the fade in/out
+# to occur.  They can also specify "auto" which is the default.
+#
 # $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
@@ -25,7 +29,7 @@
 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"
+    echo "If a fadeout or fadein is not desired then specify \"no\" for that option.  \"yes\" will force a fade and \"auto\" will try to detect if a fade should occur."
     exit 1
 fi
 
@@ -33,23 +37,23 @@
 first_file=$2
 second_file=$3
 
-fade_first="yes"
+fade_first="auto"
 if [ "$4" != "" ]; then
     fade_first=$4
 fi
 
-fade_second="yes"
+fade_second="auto"
 if [ "$5" != "" ]; then
     fade_second=$5
 fi
 
 fade_first_opts=
-if [ "$fade_first" == "yes" ]; then
+if [ "$fade_first" != "no" ]; then
     fade_first_opts="fade t 0 0:0:$fade_length"
 fi
 
 fade_second_opts=
-if [ "$fade_second" == "yes" ]; then
+if [ "$fade_second" != "no" ]; then
     fade_second_opts="fade t 0:0:$fade_length"
 fi
 
@@ -63,13 +67,47 @@
 
 # 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
+$SOX "$first_file" -s -w fadeout1.wav trim $trim_length
+
+# When user specifies "auto" try to guess if a fadeout is needed.
+# "RMS amplitude" from the stat effect is effectively an average
+# value of samples for the whole fade length file.  If it seems
+# quite then assume a fadeout has already been done.  An RMS value
+# of 0.1 was just obtained from trail and error.
+if [ "$fade_first" == "auto" ]; then
+    RMS=`$SOX fadeout1.wav 2>&1 -e stat | grep RMS | grep amplitude | cut -d : -f 2 | cut -f 1`
+    should_fade=`echo "$RMS > 0.1" | bc`
+    if [ $should_fade == 0 ]; then
+        echo "Auto mode decided not to fadeout with RMS of $RMS"
+        fade_first_opts=""
+    else
+        echo "Auto mode will fadeout"
+    fi
+fi
+
+$SOX fadeout1.wav fadeout2.wav $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
+$SOX "$second_file" -s -w fadein1.wav trim 0 $fade_length
+
+# For auto, do similar thing as for fadeout.
+if [ "$fade_second" == "auto" ]; then
+    RMS=`$SOX fadein1.wav 2>&1 -e stat | grep RMS | grep amplitude | cut -d : -f 2 | cut -f 1`
+    should_fade=`echo "$RMS > 0.1" | bc`
+    if [ $should_fade == 0 ]; then
+        echo "Auto mode decided not to fadein with RMS of $RMS"
+        fade_second_opts=""
+    else
+        echo "Auto mode will fadein"
+    fi
+fi
+
+$SOX fadein1.wav fadein2.wav $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
+$SOXMIX -v 1.0 fadeout2.wav -v 1.0 fadein2.wav crossfade.wav
 
 echo "Trimming off crossfade sections from original files..."
 
@@ -78,7 +116,7 @@
 $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
+rm fadeout1.wav fadeout2.wav fadein1.wav fadein2.wav crossfade.wav song1.wav song2.wav
 mins=`echo "$trim_length / 60" | bc`
 secs=`echo "$trim_length % 60" | bc`
 echo "The crossfade in mix.wav occurs at around $mins mins $secs secs"