uses Ext.comment /* (c) David W. Barts (davidb@scn.org) / http://www.scn.org/~davidb Oakland, CA, USA --------------0F248FB38A4CAC17417D7469 Content-Type: text/plain; charset=us-ascii; name="sine.fs" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sine.fs" */ \ Play sine waves. \ include audioout.fs uses Audio.audioout \ Values of pi and 2*pi, the former is already defined in gForth. \ 1e0 fasin 2e0 f* fconstant pi pi 2e0 f* fconstant 2pi \ For mapping sin(x) into integers 3.2767e4 fconstant scaling 1.0e0 fconstant offset \ Frequency (in Hz) and time (in ms) of the note to be played 0 value note-hz 0 value note-ms \ Sampling frequency of the DSP 44100 constant dsp-hz \ Minimum frequency allowed 30 constant min-hz \ Words to set the frequency and time of the note : hertz ( n -- ) dup min-hz < over dsp-hz 2/ > or abort" ? Illegal frequency" to note-hz ; : msec ( n -- ) to note-ms ; \ ... for alternate units as well : kilo ( n xt -- ) 1000 * ; : sec ( n -- ) kilo msec ; : seconds sec ; : khz ( n -- ) kilo hertz ; \ Convenience words for floating point conversion : s>f ( n -- | F: -- n ) s>d d>f ; : f>s ( F: n -- | -- n ) f>d d>s ; \ Determine the number of samples to play : num-samples ( -- n ) dsp-hz note-ms * 1000 / ; \ Width of a sample in radians, and a word to set it fvariable sample-width : set-width ( -- ) 2pi \ width of a whole cycle in radians dsp-hz s>f note-hz s>f f/ \ width of a cycle in samples f/ sample-width f! ; \ divide to get radians/sample \ Munge a float in the range [-1,1] into integer the DSP can grok : munge-number ( F: n1 -- | -- n2 ) offset f+ scaling f* f>s ; \ Play a tone. Assumes device is already open; intended for playing \ things back-to-back. : play ( -- ) set-width \ calculate width of sample num-samples 0 ?do \ for each sample period do i s>f sample-width f@ f* \ compute time in radians fsin \ compute sin(radians) munge-number \ convert to integer write-aud-cell \ send to the dsp loop ; \ "Play" a rest. : rest ( -- ) offset f>s num-samples 0 ?do dup write-aud-cell loop ; \ Play a single note at a time. The inefficient use of open-audio \ and close-audio is because of YASB (yet another sox bug). : play1 open-audio play close-audio ;