Audio Function Generator Script.

Hi all…
Well I did not get a reply on my very first upload on binary manipulation so I assume it must be OK to include the same method in this applescript:-

http://www.macscripter.net/viewtopic.php?id=45065

Assuming the moderators will allow me too, I am going to learn applescripting the hard way by developing an Audio Function Generator, fixed frequency at the moment but hopefully from around 100Hz to 10KHz or better.
I suspect an AudioScope, like the shell script one I am still developing on the site in the URL above, is not possible.

This will have the limitations of the hardware interpolation settings as I have no idea how to change subtleties like that with a high level scripting language and the fact that this is in mono, 8 bit unsigned depth and initially 8000 SPS.

This is the next step and I found out the the “dialog box” can only have 3 buttons - sigh.
The sub-routines are set up first and the may look a little odd but hopefully the comments will help a little.

Enjoy, as much as i do with learning new languages.

From an amateur coder, developing on a MacBook Pro 13 inch, circa August 2012, default applesrcipt environment…

Bazza.

-- Experimental Audio Function Generator, Version 0.00.02.
-- Issued CC0, 2016, B.Walker, G0LCU.
-- Prepare waveforms at a fixed frequency of 1KHz, 8 bit depth, mono, 8000 SPS in .WAV format using shell commands.
-- Each real burst is about 8 seconds, afplay is used and timed limit set to 1 second.
-- Noise is not done yet.

-- This variable will eventually set the frequency.
global sample_rate
set sample_rate to "#!/bin/bash
printf '%b' '\\x40\\x1F\\x00\\x00\\x40\\x1F\\x00\\x00' >> /tmp/sinewave.wav
"

-- This will not change.
on header_start()
	do shell script "#!/bin/bash
printf '%b' '\\x52\\x49\\x46\\x46\\x24\\x00\\x01\\x00\\x57\\x41\\x56\\x45\\x66\\x6d\\x74\\x20\\x10\\x00\\x00\\x00\\x01\\x00\\x01\\x00' > /tmp/sinewave.wav
"
end header_start

-- This will always change on frequency change.
on header_rate()
	do shell script sample_rate
end header_rate

-- This will not change.
on header_end()
	do shell script "#!/bin/bash
printf '%b' '\\x01\\x00\\x08\\x00\\x64\\x61\\x74\\x61\\x00\\x00\\x01\\x00' >> /tmp/sinewave.wav
cp /tmp/sinewave.wav /tmp/squarewave.wav
cp /tmp/sinewave.wav /tmp/sawtooth+.wav
cp /tmp/sinewave.wav /tmp/sawtooth-.wav
cp /tmp/sinewave.wav /tmp/triangle.wav
cp /tmp/sinewave.wav /tmp/noise.wav
cp /tmp/sinewave.wav /tmp/pulse+.wav
cp /tmp/sinewave.wav /tmp/pulse-.wav
exit 0
"
end header_end

-- This routine is only temporary, it will change to create 512KB files instead of 64KB files.
on rawfile()
	do shell script "#!/bin/bash
for waveform in {0..8191}
do
	printf '%b' '\\x80\\x26\\x00\\x26\\x7F\\xD9\\xFF\\xD9' >> /tmp/sinewave.wav
	printf '%b' '\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00' >> /tmp/squarewave.wav
	printf '%b' '\\x00\\x24\\x49\\x6d\\x91\\xB6\\xDA\\xFF' >> /tmp/sawtooth+.wav
	printf '%b' '\\xFF\\xDA\\xB6\\x91\\x6D\\x49\\x24\\00' >> /tmp/sawtooth-.wav
	printf '%b' '\\x00\\x40\\x80\\xC0\\xFF\\xC0\\x80\\40' >> /tmp/triangle.wav
	printf '%b' '\\x80\\x26\\x00\\x26\\x7F\\xD9\\xFF\\xD9' >> /tmp/noise.wav
	printf '%b' '\\xFF\\x00\\x00\\x00\\x00\\x00\\x00\\x00' >> /tmp/pulse+.wav
	printf '%b' '\\x00\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF' >> /tmp/pulse-.wav
done
exit 0
"
end rawfile

-- Test subroutine only.
on start()
	display dialog "Audio Function Generator, Version 0.00.02." buttons {"Sine", "Square", "Continue"} default button "Continue"
	if result = {button returned:"Sine"} then
		do shell script "/usr/bin/afplay -t 1 -d /tmp/sinewave.wav"
	else if result = {button returned:"Square"} then
		do shell script "/usr/bin/afplay -t 1 -d /tmp/squarewave.wav"
	else if result = {button returned:"Continue"} then
		return
	end if
end start

-- Set up the files for 1KHz tones for about 8 seconds maximum, code below set to 1 second bursts at the moment.
set go_sub to header_start()
set go_sub to header_rate()
set go_sub to header_end()
set go_sub to rawfile()

-- Call the test subroutine.
set go_sub to start()

-- Main loop.
repeat
	set waveform to (choose from list {"Sine", "Square", "Sawtooth+", "Sawtooth-", "Triangle", "Noise", "Pulse+", "Pulse-", "More", "Quit"} with prompt "Select Waveform Required:-" default items "Sine" OK button name {"GO!"} cancel button name {"Cancel..."})
	if waveform is false then error number -128 -- User cancelled.
	if waveform is {"Sine"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/sinewave.wav"
	if waveform is {"Square"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/squarewave.wav"
	if waveform is {"Sawtooth+"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/sawtooth+.wav"
	if waveform is {"Sawtooth-"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/sawtooth-.wav"
	if waveform is {"Triangle"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/triangle.wav"
	if waveform is {"Noise"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/noise.wav"
	if waveform is {"Pulse+"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/pulse+.wav"
	if waveform is {"Pulse-"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/pulse-.wav"
	if waveform is {"Quit"} then exit repeat -- User quitted.
	-- The next part below is fro future use in another window, using the test subroutine at the moment.
	if waveform is {"More"} then set go_sub to start()
end repeat
end

Have fun guys and gals…

Model: MacBoo Pro 13 inch.
AppleScript: 2.2.1
Browser: Firefox 48.0
Operating System: Mac OS X (10.7)

Well all…

The next stage so far…

At this point Nigel Garvey, (Moderator), suggested a true applescript version of creating binary files but was much too slow. Thanks for the effort Nigel, much appreciated.

However I have reverted back to dropping into the shell to create 8 off .WAV files all 524332 bytes in size, this is near instant on this aging MBP.

This is to allow for a maximum of 48000 SPS, and give at least a burst of 10 seconds at that rate in the finished creation.

The code is limited to 1 second per burst at the moment purely for quickness in testing for bugs and other coding errors.

When you click on “More” this will open another section for opertional subtleties in the future, this is purely experimental at this point.

You can probably see how my mindset works now…

Remember I know nothing about AppleScript-ing, but I sure know how to hit the hardware by the back door.
Things are gonna get harder now so gaps between uploads my be longer and longer.
(BTW, I will be doing this in AWK as well, as I intend to learn that language also.)

Bazza.

-- Experimental Audio Function Generator.
-- Issued CC0, 2016, B.Walker, G0LCU.
-- Prepare waveforms at a fixed frequency of 1KHz, 8 bit depth, unsigned integer, mono, 8000 SPS in .WAV format using shell commands.
-- The OSX command line "afplay" is used and timed limit set to 1 second.

-- This variable will eventually set the frequency.
global sample_rate
global title

set sample_rate to "#!/bin/bash
printf '%b' '\\x40\\x1F\\x00\\x00\\x40\\x1F\\x00\\x00' >> /tmp/sinewave.wav
"
set title to "Audio Function Generator, Version 0.00.05.
Issued CC0 licence, 2016, B.Walker, G0LCU."

-- This will not change.
on header_start()
	do shell script "#!/bin/bash
printf '%b' '\\x52\\x49\\x46\\x46\\x24\\x00\\x08\\x00\\x57\\x41\\x56\\x45\\x66\\x6d\\x74\\x20\\x10\\x00\\x00\\x00\\x01\\x00\\x01\\x00' > /tmp/sinewave.wav
"
end header_start

-- This will always change on frequency change, 1KHz on initial startup.
on header_rate()
	do shell script sample_rate
end header_rate

-- This will not change.
on header_end()
	do shell script "#!/bin/bash
printf '%b' '\\x01\\x00\\x08\\x00\\x64\\x61\\x74\\x61\\x00\\x00\\x08\\x00' >> /tmp/sinewave.wav
cp /tmp/sinewave.wav /tmp/squarewave.wav
cp /tmp/sinewave.wav /tmp/sawtooth+.wav
cp /tmp/sinewave.wav /tmp/sawtooth-.wav
cp /tmp/sinewave.wav /tmp/triangle.wav
cp /tmp/sinewave.wav /tmp/noise.wav
cp /tmp/sinewave.wav /tmp/pulse+.wav
cp /tmp/sinewave.wav /tmp/pulse-.wav
exit 0
"
end header_end

-- All files are now 524332 bytes in size.
on rawfile()
	do shell script "#!/bin/bash
SINE='\\x80\\x26\\x00\\x26\\x7F\\xD9\\xFF\\xD9'
for waveform in {0..15}
do
	SINE=$SINE$SINE
done
printf '%b' $SINE >> /tmp/sinewave.wav
SQUARE='\\xFF\\xFF\\xFF\\xFF\\x00\\x00\\x00\\x00'
for waveform in {0..15}
do
	SQUARE=$SQUARE$SQUARE
done
printf '%b' $SQUARE >> /tmp/squarewave.wav
SAWTOOTHPLUS='\\x00\\x24\\x49\\x6D\\x91\\xB6\\xDA\\xFF'
for waveform in {0..15}
do
	SAWTOOTHPLUS=$SAWTOOTHPLUS$SAWTOOTHPLUS
done
printf '%b' $SAWTOOTHPLUS >> /tmp/sawtooth+.wav
SAWTOOTHMINUS='\\xFF\\xDA\\xB6\\x91\\x6D\\x49\\x24\\00'
for waveform in {0..15}
do
	SAWTOOTHMINUS=$SAWTOOTHMINUS$SAWTOOTHMINUS
done
printf '%b' $SAWTOOTHMINUS >> /tmp/sawtooth-.wav
TRIANGLE='\\x00\\x40\\x80\\xC0\\xFF\\xC0\\x80\\40'
for waveform in {0..15}
do
	TRIANGLE=$TRIANGLE$TRIANGLE
done
printf '%b' $TRIANGLE >> /tmp/triangle.wav

PULSEPLUS='\\xFF\\x00\\x00\\x00\\x00\\x00\\x00\\x00'
for waveform in {0..15}
do
	PULSEPLUS=$PULSEPLUS$PULSEPLUS
done
printf '%b' $PULSEPLUS >> /tmp/pulse+.wav
PULSEMINUS='\\x00\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF\\xFF'
for waveform in {0..15}
do
	PULSEMINUS=$PULSEMINUS$PULSEMINUS
done
printf '%b' $PULSEMINUS >> /tmp/pulse-.wav
dd if=/dev/urandom of=/tmp/noise.raw bs=65536 count=8 > /dev/null 2>&1
cat /tmp/noise.raw >> /tmp/noise.wav
rm /tmp/noise.raw
exit 0
"
end rawfile

-- Author, licence and program name.
on VER()
	display dialog title buttons {"OK"} default button "OK"
end VER

on more_commands()
	set commands to (choose from list {"VER", "Exit"} with prompt "Select Entensions:-" default items "Exit" OK button name {"OK"} cancel button name {"Return"})
	if commands is {"Return"} then return
	if commands is {"VER"} then set go_sub to VER()
	if commands is {"Exit"} then return
end more_commands

-- Set up the files for 1KHz tones, code below set to 1 second test bursts at the moment.
set go_sub to header_start()
set go_sub to header_rate()
set go_sub to header_end()
set go_sub to rawfile()

-- Call the test subroutine.
set go_sub to VER()

-- Main loop.
repeat
	set waveform to (choose from list {"Sine", "Square", "Sawtooth+", "Sawtooth-", "Triangle", "Noise", "Pulse+", "Pulse-", "More", "Quit"} with prompt "Select Waveform Required:-" default items "Sine" OK button name {"Start"} cancel button name {"Cancel..."})
	-- if waveform is false then error number -128
	if waveform is false then exit repeat
	if waveform is {"Sine"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/sinewave.wav"
	if waveform is {"Square"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/squarewave.wav"
	if waveform is {"Sawtooth+"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/sawtooth+.wav"
	if waveform is {"Sawtooth-"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/sawtooth-.wav"
	if waveform is {"Triangle"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/triangle.wav"
	if waveform is {"Noise"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/noise.wav"
	if waveform is {"Pulse+"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/pulse+.wav"
	if waveform is {"Pulse-"} then do shell script "/usr/bin/afplay -t 1 -d /tmp/pulse-.wav"
	if waveform is {"Quit"} then exit repeat -- User quitted.
	-- The next part below is fro future use in another window, using the test subroutine at the moment.
	if waveform is {"More"} then set go_sub to more_commands()
end repeat
end