1#!/bin/bash
2#
3# crossfade_cat.sh
4#
5# Concatenates two files together with a crossfade of $1 seconds.
6# Filenames are specified as $2 and $3.
7#
8# $4 is optional and specifies if a fadeout should be performed on
9# first file.
10# $5 is optional and specifies if a fadein should be performed on
11# second file.
12#
13# Example: crossfade_cat.sh 10 infile1.wav infile2.wav auto auto
14#
15# By default, the script attempts to guess if the audio files
16# already have a fadein/out on them or if they just have really
17# low volumes that won't cause clipping when mixxing.  If this
18# is not detected then the script will perform a fade in/out to
19# prevent clipping.
20#
21# The user may specify "yes" or "no" to force the fade in/out
22# to occur.  They can also specify "auto" which is the default.
23#
24# Crossfaded file is created as "mix.wav".
25#
26# Original script from Kester Clegg.  Mods by Chris Bagwell to show
27# more examples of sox features.
28#
29
30SOX=../src/sox
31SOXI=../src/soxi
32
33if [ "$3" == "" ]; then
34    echo "Usage: $0 crossfade_seconds first_file second_file [ fadeout ] [ fadein ]"
35    echo
36    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."
37    echo
38    echo "Example: $0 10 infile1.wav infile2.wav auto auto"
39    exit 1
40fi
41
42fade_length=$1
43first_file=$2
44second_file=$3
45
46fade_first="auto"
47if [ "$4" != "" ]; then
48    fade_first=$4
49fi
50
51fade_second="auto"
52if [ "$5" != "" ]; then
53    fade_second=$5
54fi
55
56fade_first_opts=
57if [ "$fade_first" != "no" ]; then
58    fade_first_opts="fade t 0 0:0:$fade_length 0:0:$fade_length"
59fi
60
61fade_second_opts=
62if [ "$fade_second" != "no" ]; then
63    fade_second_opts="fade t 0:0:$fade_length"
64fi
65
66echo "crossfade and concatenate files"
67echo
68echo  "Finding length of $first_file..."
69first_length=`$SOX --info -D "$first_file"`
70echo "Length is $first_length seconds"
71
72trim_length=`echo "$first_length - $fade_length" | bc`
73
74# Get crossfade section from first file and optionally do the fade out
75echo "Obtaining $fade_length seconds of fade out portion from $first_file..."
76$SOX "$first_file" -e signed-integer -b 16 fadeout1.wav trim $trim_length
77
78# When user specifies "auto" try to guess if a fadeout is needed.
79# "RMS amplitude" from the stat effect is effectively an average
80# value of samples for the whole fade length file.  If it seems
81# quiet then assume a fadeout has already been done.  An RMS value
82# of 0.1 was just obtained from trial and error.
83if [ "$fade_first" == "auto" ]; then
84    RMS=`$SOX fadeout1.wav 2>&1 -n stat | grep RMS | grep amplitude | cut -d : -f 2 | cut -f 1`
85    should_fade=`echo "$RMS > 0.1" | bc`
86    if [ $should_fade == 0 ]; then
87        echo "Auto mode decided not to fadeout with RMS of $RMS"
88        fade_first_opts=""
89    else
90        echo "Auto mode will fadeout"
91    fi
92fi
93
94$SOX fadeout1.wav fadeout2.wav $fade_first_opts
95
96# Get the crossfade section from the second file and optionally do the fade in
97echo "Obtaining $fade_length seconds of fade in portion from $second_file..."
98$SOX "$second_file" -e signed-integer -b 16 fadein1.wav trim 0 $fade_length
99
100# For auto, do similar thing as for fadeout.
101if [ "$fade_second" == "auto" ]; then
102    RMS=`$SOX fadein1.wav 2>&1 -n stat | grep RMS | grep amplitude | cut -d : -f 2 | cut -f 1`
103    should_fade=`echo "$RMS > 0.1" | bc`
104    if [ $should_fade == 0 ]; then
105        echo "Auto mode decided not to fadein with RMS of $RMS"
106        fade_second_opts=""
107    else
108        echo "Auto mode will fadein"
109    fi
110fi
111
112$SOX fadein1.wav fadein2.wav $fade_second_opts
113
114# Mix the crossfade files together at full volume
115echo "Crossfading..."
116$SOX -m -v 1.0 fadeout2.wav -v 1.0 fadein2.wav crossfade.wav
117
118echo "Trimming off crossfade sections from original files..."
119
120$SOX "$first_file" -e signed-integer -b 16 song1.wav trim 0 $trim_length
121$SOX "$second_file" -e signed-integer -b 16 song2.wav trim $fade_length
122$SOX song1.wav crossfade.wav song2.wav mix.wav
123
124echo -e "Removing temporary files...\n"
125rm fadeout1.wav fadeout2.wav fadein1.wav fadein2.wav crossfade.wav song1.wav song2.wav
126mins=`echo "$trim_length / 60" | bc`
127secs=`echo "$trim_length % 60" | bc`
128echo "The crossfade in mix.wav occurs at around $mins mins $secs secs"
129
130