Well guys, this MUST be a first.
This is DEMO code only and has NO error detection or correction, nor out of bounds checking.
I have succumbed to Python and scipy to do the FFT heavy lifting as I have absolutely no idea where to start do such a thing using AWK. This is a taster for me to include into AudioScope.sh. I am thinking of doing each vertical plot in differing colours and juggling the numbers to suit.
This IS a bash script but creates a 250Hz 1 second WAV file and the python script on the fly.
At the moment the plotting takes a few seconds, but I am not bothered about that at this point. The fact that it works has even amazed me!
The two images show the pre-generated 250Hz spectrum and a 1 second burst of me talking into the MBP's mic...
COMMENTS?!
I await the flak...
#!/bin/bash
# AF_Spec_An.sh
# Generate a 250Hz square wave, WAV file, for testing. Mono, 8KHz sample, unsigned integer, 8 bit depth.
CHAR=0
: > /tmp/250Hz.wav
: > /tmp/bash_array
: > /tmp/FFT_WAV.py
printf "\122\111\106\106\144\037\000\000\127\101\126\105\146\155\164\040\020\000\000\000\001\000\001\000\100\037\000\000\100\037\000\000\001\000\010\000\144\141\164\141\100\037\000\000" >> /tmp/250Hz.wav
while [ $CHAR -le 249 ]
do
printf "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" >> /tmp/250Hz.wav
CHAR=$(( $CHAR + 1 ))
done
# A test display only, active area x = 64, y = 21.
display()
{
printf "%b" "\033[2J\033[H"
graticule=" +----------------------------[DISPLAY]----------------------------+\n"
graticule=$graticule" 100 ++-------+-------+-------+-------+-------+-------+-------+-------++\n"
graticule=$graticule" | | | | | | | | |\n"
graticule=$graticule" 90 + | | | | | | | |\n"
graticule=$graticule" R | | | | | | | | |\n"
graticule=$graticule" E 80 + | | | | | | | |\n"
graticule=$graticule" L | | | | | | | | |\n"
graticule=$graticule" A 70 + | | | | | | | |\n"
graticule=$graticule" T | | | | | | | | |\n"
graticule=$graticule" I 60 + | | | | | | | |\n"
graticule=$graticule" V | | | | | | | | |\n"
graticule=$graticule" E 50 + | | | | | | | |\n"
graticule=$graticule" | | | | | | | | |\n"
graticule=$graticule" L 40 + | | | | | | | |\n"
graticule=$graticule" E | | | | | | | | |\n"
graticule=$graticule" V 30 + | | | | | | | |\n"
graticule=$graticule" E | | | | | | | | |\n"
graticule=$graticule" L 20 + | | | | | | | |\n"
graticule=$graticule" Log10(x) | | | | | | | | |\n"
graticule=$graticule" 10 + | | | | | | | |\n"
graticule=$graticule" | | | | | | | | |\n"
graticule=$graticule" 0++-------+-------+-------+-------+-------+-------+-------+-------++\n"
graticule=$graticule" FREQ Hz +0------500----1000----1500----2000----2500----3000----3500----4000\n"
printf "$graticule"
}
# Pythoin code to do the heavy FFT lifting.
cat << PYTHON_CODE > /tmp/FFT_WAV.py
# Python 2.7.10 (default, Feb 6 2017, 23:53:20)
# [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin
# Type "help", "copyright", "credits" or "license" for more information.
import sys
import scipy
from scipy.io import wavfile
global ARRAY_STRING
ARRAY_STRING = ""
# The inbuilt tester.
RATE, WAVEDATA = wavfile.read('/tmp/250Hz.wav')
# A 1 second speech burst.
# RATE, WAVEDATA = wavfile.read('/Users/amiga/Desktop/Sound/test.wav')
DATA = WAVEDATA.T
ELEMENTS = [(ELEMENT/2**8.0)*2-1 for ELEMENT in DATA]
COMPLEX = scipy.fft(ELEMENTS)
LIST = scipy.ndarray.tolist(abs(COMPLEX))
for SUBSCRIPT in range(7999, 3999, -1):
FFT = int(LIST[SUBSCRIPT])
if FFT < 1.0: FFT = 1
FFT = int(5*scipy.log10(FFT))
ARRAY_STRING = ARRAY_STRING + str(FFT) + " "
filename = open('/tmp/bash_array', 'w+')
filename.write(ARRAY_STRING)
filename.close()
sys.exit()
PYTHON_CODE
# Now run the Python code.
python /tmp/FFT_WAV.py
# Place the space delimited string into a bash array.
bash_array=( $( cat /tmp/bash_array ) )
# Setup the display.
display
# Finally plot the audio spectrum.
COUNT=0
HORIZ=13
VERT=${bash_array[$COUNT]}
# Display window...
# HORIZ, 13 minimum, 77 maximum.
# VERT, 2 minimum, 22 maximum.
# VERT MUST be inverted.
while [ $COUNT -le 3999 ]
do
VERT=$(( 22 - $VERT ))
if [ $HORIZ -gt 77 ]
then
break
fi
for DRAW in $( seq $VERT 1 22 )
do
# Bending the rules a little for printf, but this is only a proof of principle demo.
printf "%b" "\033["$DRAW";"$HORIZ"f\033[1;31m*\033[0m\n\n"
done
if [ $(( $COUNT % 63 )) -eq 0 ]
then
HORIZ=$(( $HORIZ + 1 ))
fi
COUNT=$(( $COUNT + 1 ))
VERT=${bash_array[$COUNT]}
done