1#!/bin/sh 2 3# SoX script: testtones.sh (c) 2009 robs@users.sourceforge.net 4# Based on an original idea by Carsten Borchardt 5# 6# This program is free software; you can redistribute it and/or modify it 7# under the terms of the GNU General Public License as published by the 8# Free Software Foundation; either version 2 of the License, or (at your 9# option) any later version. 10# 11# This program is distributed in the hope that it will be useful, but 12# WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 14# Public License for more details. 15# 16# You should have received a copy of the GNU General Public License along 17# with this program; if not, write to the Free Software Foundation, Inc., 18# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 20 21 22# Usage: testtones.sh [RATE [AUDIO_LENGTH]] 23# 24# This script generate files containing audio tones of various 25# frequencies and power levels that can be used to test an audio 26# system's reproduction quality and response. By default, the 27# generated files are suitable for writing to a test CD (using a 28# programme such as k3b). 29# 30# The audio files are created in the current directory and a list of 31# the files generated is also created. A description of each 32# generated file is sent to the console as the script executes. 33# 34# RATE (default 44100) is the sample-rate at which to generate the 35# test tones. Use 48000 to test a PC/work-station or DAT system. 36# 37# AUDIO_LENGTH (default 36) sets the length in seconds of (most of) 38# the test-tones. 39# 40# Other parameters can be changed in the Configuration section below. 41 42 43 44# Configuration: 45 46sox="../src/sox" # Where is sox? E.g. sox, /usr/local/bin/sox 47type=wav # File type, e.g. flac, cdda 48rate=44100 # Default sample rate 49#chans2="-c 2" # Uncomment for all files to have 2 channels 50part_octave=6 # 5 for harmonic split, 6 for true half octave 51tone_length=36 # In seconds; not used for sweeps 52fade_time=.05 # Fade in/out time (for smooth start and end of tone) 53gain="gain -1" # Headroom for playpack chain 54#NDD=-D # Uncomment to disable TPDF default dither 55vol_dither="-f ge" # Type of dither to be used for volume tests 56plot=yes # Uncomment to enable PNG plots 57 58 59 60plot() 61{ 62 [ -n "$plot" ] && [ -n "$name" ] && $sox -D "$name" -n \ 63 spectrogram -h -w kaiser -o "`basename "$name" $type`png" 64} 65 66 67 68next_file() # Generate incrementing file name; update variables 69{ 70 plot # the previous file 71 72 file_count=$(($file_count + 1)) 73 name=`printf "%02i-%s.$type" $file_count "$1" | tr / "~"` 74 echo " $name" 75 echo "$name" >> $log 76 77 length=$tone_length; [ -n "$2" ] && length=$2 78 total_length=$(($total_length + $length)) 79 80 output="-b 16 $chans2 --comment="" $name" 81 fade="fade h $fade_time $length $fade_time" 82} 83 84 85 86# Initialisation: 87 88[ -n "$1" ] && rate="$1" 89[ -n "$2" ] && tone_length="$2" 90 91log="`basename "$0"`.log" 92: > $log # Initialise log file 93 94total_length=0 # In seconds 95file_count=0 96 97freqs="100 1k 10k" 98input="$sox $NDD -r $rate -n" 99 100echo "Creating test audio files with sample-rate = $rate" 101 102 103 104echo; echo "Silence:" 105 106next_file silence 107$input -D $output trim 0 $length 108 109 110 111echo; echo "Noise colours:" 112 113next_file white-noise 114$input $output synth $length whitenoise $fade $gain 115next_file pink-noise 116$input $output synth $length pinknoise $fade $gain 117next_file brown-noise 118$input $output synth $length brownnoise $fade $gain 119 120 121 122echo; echo "Single, fixed frequency pure tones, half octave steps:" 123 124note=-60 # 5 octaves below middle A = 13.75Hz 125while [ $note -le 67 ]; do # 5 and a bit octaves above middle A ~= 20kHz 126 if [ -x /usr/bin/bc ]; then 127 freq=`echo "scale = 9; 440 * e($note / 12 * l(2))" | bc -l` 128 next_file `printf "%.1f" $freq`Hz 129 else 130 next_file %$note 131 fi 132 $input $output synth -j 0 sine %$note $fade $gain 133 note=$(($note + $part_octave)) 134 part_octave=$((12 - $part_octave)) 135done 136 137 138 139echo; echo "Single, fixed frequency pure tones, decade/sub-decade steps:" 140 141for freq in 20 50 100 200 500 1k 2k 5k 10k 20k; do 142 next_file "${freq}hz" 143 $input $output synth sine $freq $fade $gain 144done 145 146 147 148echo; echo "Single, fixed frequency pure tones, CD frequency sub-harmonics:" 149 150for freq in 5512.5 11025 16537.5 22050; do 151 next_file "cd-${freq}hz" 152 $input $output synth $length sine $freq 0 25 $fade $gain 153done 154 155 156 157echo; echo "Sweep frequency @ 1 semitone/s, with a mark @ each octave of \`A':" 158 159phase1=75 160phase2=1 161for freq in %-60/%67 %67/%-60; do 162 next_file ${freq}_sweep 127 163 $input $output synth sine %30 \ 164 synth sine amod 8.333333333333333333 0 $phase1 \ 165 synth squa amod 0.08333333333333333333 0 $phase2 1 gain -9 \ 166 synth $length sine mix $freq gain -h 3 $gain 167 phase1=41.66666666666666667 168 phase2=42.66666666666666667 169done 170 171 172 173echo; echo "Dual, fixed frequency pure tones:" 174 175next_file 9kHz+10kHz 176$input $output synth $length sine 9k synth sine mix 10k $fade $gain 177next_file 440hz+445hz 178$input $output synth $length sine 440 synth sine mix 445 $fade $gain 179 180 181 182echo; echo "Single, fixed frequency harmonic tones:" 183 184for freq in 100 1k 5k; do 185 for shape in square saw; do 186 next_file ${freq}hz_$shape 187 $input $output synth $length $shape $freq $fade gain -3 188 done 189done 190 191 192 193echo; echo "Single, fixed frequency pure tones, 12dB attenuation steps:" 194 195for freq in $freqs; do 196 for att in 12 24 36 48 60 72 84 96 108; do 197 next_file ${freq}hz_${att}dB_att 198 $input $output synth $length sine $freq gain -h -$att $fade dither $vol_dither 199 done 200done 201 202 203 204echo; echo "Sweep volume @ 1dB/s, -108->0->-108dB, with a mark (-40dB) every 12dB:" 205 206for freq in $freqs; do 207 next_file ${freq}hz_108dB-sweep 216 208 $input $output synth $length sin $freq sin %30 \ 209 synth squ amod 0 100 sine amod 8.333333333333333333 0 75 \ 210 synth exp amod 0.00462962962962962963 0 0 50 54 \ 211 squ amod 0.08333333333333333333 0 1 1 \ 212 remix 1v.99,2v.01 dither $vol_dither 213done 214 215 216 217echo; echo "1kHz tone offset with 1Hz:" 218 219next_file offset_10%_square 220$input $output synth $length square 1 sine 1000 remix 1v0.05,2v0.95 gain -h 0 $fade $gain 221next_file offset_50%_sine 222$input $output synth $length sine 1 synth sine mix 1000 $fade $gain 223 224 225 226echo; echo "Silence on one channel, full volume on the other:" 227 228for freq in $freqs; do 229 next_file ${freq}hz_left-chan 230 $input $output synth $length sine $freq remix 1 0 gain -h 0 $fade $gain 231 next_file ${freq}hz_right-chan 232 $input $output synth $length sine $freq remix 0 1 gain -h 0 $fade $gain 233done 234 235 236 237echo; echo "Phase difference (24, 90, 180 degrees) between channels:" 238 239for freq in $freqs; do 240 for phase in 6.667 25 50; do 241 next_file ${freq}hz_phase-$phase 242 $input $output synth $length sine $freq sine $freq 0 $phase $fade $gain 243 done 244done 245 246 247 248echo; echo "Plucked scale:" 249 250options= 251overdrive="gain -3" 252for f in pluck pluck_dist; do 253 next_file $f 42 254 note=-29 255 :>tmp.s32 256 257 while [ $note -lt 17 ]; do 258 $input -t s32 - synth .4 pluck %$note $options >> tmp.s32 259 note=$(($note + 1)) 260 done 261 $input -t s32 - synth 1.2 pluck %$note $options >> tmp.s32 262 263 while [ $note -gt -29 ]; do 264 $input -t s32 - synth .4 pluck %$note $options >> tmp.s32 265 note=$(($note - 1)) 266 done 267 $input -t s32 - synth pluck %$note $options fade t 0 4 3.6 >> tmp.s32 268 269 $sox -r $rate -c 1 tmp.s32 $output $overdrive remix 1 1 reverb 30 270 271 rm -f tmp.s32 272 options="0 0 60 75 0" 273 overdrive="overdrive gain -10" 274done 275 276 277 278plot # the last file 279minutes=$(($total_length / 60)) 280seconds=$(($total_length - $minutes * 60)) 281echo; echo "Sample-rate = $rate; # files created = $file_count; total audio length = `printf "%i:%02i" $minutes $seconds`" 282