An audio frequency generator produces a continual audible monotone at a set frequency and level of volume. There are controls to adjust the frequency and the volume up and down as desired. Some also have a selector to switch the waveform type between sine wave, square wave and triangular sawtooth.

Audio frequency generator is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

The task is to emulate an audio frequency generator. It is permissible to use an inbuilt computer speaker if the system does not have the facility to utilize dedicated sound hardware.

The solution should include:

  • A demonstration of how to check for availability of sound hardware on the system (on systems where this is possible)
  • A demonstration of how to produce a continual audible monotone (on sound hardware this would typicvally be a sine wave)
  • A method of adjusting the frequency and volume of the monotone. (one way would be to use left and right arrow keys to increase or decrease frequency, and up and down keys to increase or decrease the volume)
  • A method to silence or reset the sound hardware on exit.

Optionally the solution can also include:

  • A demonstration of how to fall back to internal speaker, if sound hardware is not available
  • A facility to switch between sine wave, square wave and triangular sawtooth

Languages that provide no facilities for utilizing sound hardware of any kind should be omitted.

Pure Data

audio-frequency-generator.pd

#N canvas 245 70 635 516 10;
#X obj 501 214 cnv 15 84 66 empty empty empty 80 12 0 10 -262130 -13381 0;
#X obj 319 98 cnv 15 133 15 empty empty frequency 74 8 0 10 -204786 -13381 0;
#X obj 319 55 line;
#X floatatom 319 98 8 0 0 1 - - -;
#X obj 109 436 dac~;
#X obj 322 261 hsl 128 15 0 1 0 0 empty empty volume 90 8 0 10 -203904 -1 -4160 0 0;
#X obj 85 142 osc~;
#X floatatom 554 34 5 0 0 0 MIDI_note_number - -;
#X obj 554 52 mtof;
#X obj 32 142 phasor~;
#X obj 119 371 *~;
#X obj 227 345 line~;
#X floatatom 319 285 5 0 0 0 - - -;
#X floatatom 154 444 5 0 0 1 dB - -;
#X obj 154 423 env~ 256;
#X obj 154 462 - 100;
#X obj 320 357 vu 15 120 empty empty -1 -8 0 10 -66577 -1 1 0;
#X msg 227 323 \$1 20;
#X obj 32 292 *~;
#X obj 84 293 *~;
#X obj 120 293 *~;
#X obj 319 142 tgl 15 0 empty empty sawtooth 20 7 0 10 -261234 -1 -258113 0 1;
#X obj 319 165 tgl 15 0 empty empty sine 20 7 0 10 -261234 -1 -258113 0 1;
#X obj 319 188 tgl 15 0 empty empty square 20 7 0 10 -261234 -1 -258113 0 1;
#N canvas 0 0 450 300 (subpatch) 0;
#X array graph 100 float 0;
#X coords 0 1 99 -1 200 140 1 0 0;
#X restore 386 339 graph;
#X obj 63 239 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -228856 -1;
#X obj 173 142 triang~;
#X obj 172 293 *~;
#X obj 319 211 tgl 15 0 empty empty triangle 20 7 0 10 -261234 -1 -258113 0 1;
#X obj 120 142 square~;
#X obj 226 142 pulse~;
#X obj 227 293 *~;
#X obj 319 234 tgl 15 0 empty empty pulse 20 7 0 10 -261234 -1 -258113 0 1;
#X obj 32 164 -~ 0.5;
#X obj 45 462 tabwrite~ graph;
#X obj 529 193 loadbang;
#X msg 529 215 \; pd dsp 1;
#X msg 319 34 18 \, 24000 30000;
#X msg 529 250 \; pd dsp 0;
#X text 509 223 on;
#X text 503 258 off;
#X msg 32 34 50;
#X msg 63 34 100;
#X msg 94 34 200;
#X msg 126 34 500;
#X msg 157 34 1000;
#X msg 195 34 2000;
#X msg 232 34 4000;
#X msg 268 34 8000;
#X connect 2 0 3 0;
#X connect 3 0 6 0;
#X connect 3 0 9 0;
#X connect 3 0 25 0;
#X connect 3 0 26 0;
#X connect 3 0 29 0;
#X connect 3 0 30 0;
#X connect 5 0 12 0;
#X connect 5 0 25 0;
#X connect 6 0 19 0;
#X connect 7 0 8 0;
#X connect 8 0 3 0;
#X connect 9 0 33 0;
#X connect 10 0 4 0;
#X connect 10 0 4 1;
#X connect 10 0 14 0;
#X connect 10 0 34 0;
#X connect 11 0 10 1;
#X connect 12 0 17 0;
#X connect 13 0 15 0;
#X connect 14 0 13 0;
#X connect 15 0 16 0;
#X connect 17 0 11 0;
#X connect 18 0 10 0;
#X connect 19 0 10 0;
#X connect 20 0 10 0;
#X connect 21 0 18 1;
#X connect 21 0 25 0;
#X connect 22 0 19 1;
#X connect 22 0 25 0;
#X connect 23 0 20 1;
#X connect 23 0 25 0;
#X connect 25 0 34 0;
#X connect 26 0 27 0;
#X connect 27 0 10 0;
#X connect 28 0 27 1;
#X connect 28 0 25 0;
#X connect 29 0 20 0;
#X connect 30 0 31 0;
#X connect 31 0 10 0;
#X connect 32 0 25 0;
#X connect 32 0 31 1;
#X connect 33 0 18 0;
#X connect 35 0 36 0;
#X connect 37 0 2 0;
#X connect 41 0 3 0;
#X connect 42 0 3 0;
#X connect 43 0 3 0;
#X connect 44 0 3 0;
#X connect 45 0 3 0;
#X connect 46 0 3 0;
#X connect 47 0 3 0;
#X connect 48 0 3 0;

square~.pd

#N canvas 770 214 450 300 10;
#X obj 46 17 inlet;
#X obj 112 51 * -1;
#X obj 46 74 phasor~;
#X obj 46 95 *~ 2;
#X obj 46 116 -~ 1;
#X obj 46 137 clip~ 0 1;
#X obj 112 74 phasor~;
#X obj 112 95 *~ 2;
#X obj 112 116 -~ 1;
#X obj 112 137 clip~ 0 1;
#X obj 194 18 loadbang;
#X msg 194 39 0;
#X obj 47 187 +~;
#X obj 47 208 -~ 0.5;
#X obj 47 229 *~ 2;
#X obj 47 250 outlet~;
#X obj 156 18 inlet;
#X connect 0 0 1 0;
#X connect 0 0 2 0;
#X connect 1 0 6 0;
#X connect 2 0 3 0;
#X connect 3 0 4 0;
#X connect 4 0 5 0;
#X connect 5 0 12 0;
#X connect 6 0 7 0;
#X connect 7 0 8 0;
#X connect 8 0 9 0;
#X connect 9 0 12 1;
#X connect 10 0 11 0;
#X connect 11 0 2 1;
#X connect 11 0 6 1;
#X connect 12 0 13 0;
#X connect 13 0 14 0;
#X connect 14 0 15 0;
#X connect 16 0 11 0;

triang~.pd

#N canvas 770 214 450 300 10;
#X obj 46 17 inlet;
#X obj 112 51 * -1;
#X obj 46 74 phasor~;
#X obj 46 95 *~ 2;
#X obj 46 116 -~ 1;
#X obj 46 137 clip~ 0 1;
#X obj 112 74 phasor~;
#X obj 112 95 *~ 2;
#X obj 112 116 -~ 1;
#X obj 112 137 clip~ 0 1;
#X obj 194 18 loadbang;
#X msg 194 39 0;
#X obj 47 187 +~;
#X obj 47 208 -~ 0.5;
#X obj 47 229 *~ 2;
#X obj 47 250 outlet~;
#X obj 156 18 inlet;
#X connect 0 0 1 0;
#X connect 0 0 2 0;
#X connect 1 0 6 0;
#X connect 2 0 3 0;
#X connect 3 0 4 0;
#X connect 4 0 5 0;
#X connect 5 0 12 0;
#X connect 6 0 7 0;
#X connect 7 0 8 0;
#X connect 8 0 9 0;
#X connect 9 0 12 1;
#X connect 10 0 11 0;
#X connect 11 0 2 1;
#X connect 11 0 6 1;
#X connect 12 0 13 0;
#X connect 13 0 14 0;
#X connect 14 0 15 0;
#X connect 16 0 11 0;

pulse~.pd

#N canvas 784 384 450 300 10;
#X obj 51 56 phasor~;
#X obj 51 77 -~ 0.99;
#X obj 51 98 clip~ 0 1;
#X obj 51 119 *~ 100;
#X obj 51 140 outlet~;
#X obj 51 34 inlet;
#X obj 90 34 inlet;
#X connect 0 0 1 0;
#X connect 1 0 2 0;
#X connect 2 0 3 0;
#X connect 3 0 4 0;
#X connect 5 0 0 0;
#X connect 6 0 0 1;

Tcl

Library: Snack

This does not work on Windows due the use of the external stty program. <lang tcl>package require sound

set baseFrequency 261.63 set baseAmplitude [expr {64000 / 100.0}] set halfSemis 0 set volSteps 10

  1. How to adjust the generator

proc adjustPitchVolume {changePitch changeVolume} {

   global filter baseFrequency baseAmplitude halfSemis volSteps
   incr halfSemis $changePitch
   incr volSteps $changeVolume
   # Clamp the volume range
   set volSteps [expr {$volSteps < 0 ? 0 : $volSteps > 10 ? 10 : $volSteps}]
   puts -nonewline " Pitch: [expr {$halfSemis / 2.0}]  Volume: $volSteps  \r"
   set freq [expr {$baseFrequency * 2**($halfSemis/24.0)}]
   set ampl [expr {$baseAmplitude * $volSteps**2}]
   # This is where we set the actual frequency of the generated sound
   $filter configure $freq $ampl

}

  1. Callback handler for pressed keys

proc keyPress {} {

   global done
   switch [string tolower [read stdin 1]] {

"q" { set done 1 } "u" { adjustPitchVolume 1 0 } "d" { adjustPitchVolume -1 0 } "s" { adjustPitchVolume 0 -1 } "l" { adjustPitchVolume 0 1 } default { if {[eof stdin]} { set done 1 } }

   }

}

  1. Instantiate the sound generation objects from the Snack library

set filter [snack::filter generator 1 32000 0.5 sine -1] set sound [snack::sound -rate 32050]

  1. Make things ready for a console application

exec stty raw -echo <@stdin >@stdout fconfigure stdout -buffering none fileevent stdin readable keyPress puts "'U' to raise pitch, 'D' to lower pitch, 'L' for louder, 'S' for softer" puts "'Q' to quit"

  1. Start the playing

$sound play -filter $filter adjustPitchVolume 0 0

  1. Wait until the user is finished

vwait done

  1. Clean up the console from its non-standard state

fileevent stdin readable {} puts "" exec stty -raw echo <@stdin >@stdout

  1. Stop the sound playing

$sound stop exit</lang>

ZX Spectrum Basic

The ZX Spectrum is not very good at making sound. Most applications in BASIC would just produce annoying beeps, and the following is no exception. To emulate the signal generator, we just produce repetative beeps using the inbuilt speaker. The left and right keys (5 and 8) change the tone. There is no volume control on the Spectrum.

<lang zxbasic>10 REM The crappest signal generator in the world 20 REM We do not check for boundary errors in this simple demo 30 LET n=1 40 LET k$=INKEY$ 50 IF k$="5" THEN LET n=n-0.5 60 IF k$="8" THEN LET n=n+0.5 70 PRINT AT 0,0;n," " 80 BEEP 0.1,n: REM beep for 0.1 second at n semitones relative to middle C 90 GO TO 40</lang>