User Tools

Site Tools


using_20sound_20with_20true_20frequencies

Using SOUND with true frequencies

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.

This website uses cookies for visitor traffic analysis. By using the website, you agree with storing the cookies on your computer.More information
using_20sound_20with_20true_20frequencies.txt · Last modified: 2018/04/15 12:48 by richardrussell