Shell audio oscilloscope journey
am 20.04.2008 00:06:22 von BruXy ------------------------------------------------------------ ----
Written by BruXy http://bruxy.regnet.cz/texty/audioscope.txt
------------------------------------------------------------ ----
There was an idea at the beginning. It should not be
a problem to made a simple audio oscilloscope in BASH!
For recording can be used sound card also know as /dev/dsp in
the system. You can simply record a 5 second of sound using:
dd if=/dev/dsp of=audio.raw bs=8k count=5
And play it with:
cat audio.raw > /dev/dsp
My next work continued on visualisation using hexdump and
printf. After few minutes the first version was born:
dd if=/dev/dsp bs=1 | hexdump -v -e'1/1 "%u\n"'|(
while read s;do s=$((s/3));printf "%*c\n" $s x;done)
So take you microphone, copy-paste these two lines to your
console or terminal emulator and watch the waves! You may notice
a small delay, because I/O operation with stdout is not very
fast. I wanted to introduce this invention into the World and I
posted it on IRCNet channel #linux.cz. After an extensive
testing we have made second version:
hexdump -v -e '1/2 "%u\n"'
s; do s=$((s>>10)); printf "%*c\n" $s x;done)
Indeed there is still same problem, the x-beam is moving from
top to bottom of terminal. We was talking about the way to
display audio waves horizontally and after few minutes a man
with nickname sd` released his improvement:
clear; hexdump -v -e '1/1 "%u\n"'
s; do c=$(((c+1)%COLUMNS));s=$((s*LINES/255));echo -ne \
"\e[${u[c]};${c}H \e[${s};${c}Hx" ; u[c]=$s ; done )
Turnover of line scan is done using terminal escape sequences.
The meaning of important escape sequences is:
\e[2J is a clear screen command
\e[${s}d move to row ${s}
Look into man console_codes for further details.
I cannot leave this challenge unheard! And there is a fully
graphical version:
while true; do echo -e "P5\n256 512\n255" > o.pgm;i=0; dd \
if=/dev/dsp bs=1024 count=1 | hexdump -v -e '1/2 "%u\n"' |\
(while read s;do s=$((s>>8));if [ $i -ge 512 ];then exit;fi;
printf "%*c" $s z;s=$((256-s));printf "%*c" $s A;i=$((i+1));
done)>>o.pgm;(display -rotate 90 o.pgm &);sleep 1; killall \
display; done #(c) 2008 BruXy #
And how did you spend your Saturday evening? :-)