by Richard Russell, May 2014
The SOUND statement's third parameter normally specifies the required pitch in units of quarter-semitones. For example the value 100 corresponds to middle C and the value 136 corresponds to the A above middle C (440 Hz, the standard musical pitch).
Steps of ΒΌ semitone will normally be sufficiently fine, even for glissando or vibrato effects, but occasionally it may be useful to specify the pitch more precisely, in terms of a frequency in Hertz. For example if one prefers to use just intonation rather than an equally-tempered scale it would be preferable to approximate the frequencies as accurately as possible (in practice BB4W provides a resolution of approximately one-third Hz).
The function FNfreqout listed below makes this possible. It takes as a parameter the required frequency in Hz (the maximum being around 10 kHz, but at frequencies that high aliasing effects can be excessive) and returns a value which should be specified as the third parameter of the SOUND statement.
Here is an example program illustrating its use:
FOR freq = 500 TO 1000 SOUND 1, -15, FNfreqout(freq), 1 NEXT END DEF FNfreqout(f) LOCAL I% : PRIVATE ftab%, indx& IF ftab% = 0 THEN LOCAL base% SYS "GetModuleHandle", 0 TO base% FOR I% = base% TO base% + 65534 STEP 2 IF !I% = &03550354 IF I%!4 = &06060606 EXIT FOR NEXT IF I% > base% + 65534 ERROR 100, "Cannot locate frequency table" ftab% = I% + 8 SYS "VirtualProtect", ftab% AND -&1000, &2000, &40, ^I% TO I% IF I% = 0 ERROR 100, "Cannot make memory image writable" ENDIF indx& += 1 : IF indx& = 0 indx& = 1 I% = 2 * indx& ftab%!I% = ftab%!I% AND &FFFF0000 OR INT(f * &10000 / 22050 + 0.5) = indx&
A limitation of this technique is that a maximum of 255 different frequencies can be 'active' at once. If FNfreqout is called more than that number of times the oldest frequencies will be overwritten. If an ENVELOPE statement is used it should not contain a pitch component (at least, not unless special measures are taken); amplitude envelopes work as expected.
Note that FNfreqout works by dynamically rewriting BBC BASIC's frequency table, so if used in a program run from the BB4W IDE subsequent programs which use the SOUND statement may be affected. If in doubt quit BBC BASIC for Windows and restart it. This issue does not affect its use in a 'compiled' program.