ATARI portfolio v sobě obsahuje malý sqeaker, který byl původně zamýšlen na vytáčení tónové volby. Nám se bude ovšm hodit i k jiným věcem. Jediné, co vlastně umí, je zahrání daného tónu po danou dobu. (Už jsem viděl i programy, které se pokoušely přehrávat i samplovaný hlas a kupodivu to jde, ale zatím nevím jak. Patrně nějakým low-levelovějším přístupem k hardware). Samotné zahrání tónu je věc jednoduchá a zařídí nám ji rozšířenáslužba BIOSu INT61h. Má to však jednu podstatnou nevýhodu: během hraní se počítač zastaví, takže nelze provádět nic jiného. Další už je snad jasné z výpisu zdrojáků.
Napřed musíme inicializovat služby INT61h, např. takto:
Zde je tónový repertoár generátoru:void initint61(void) /* inicializuje sluzby int 61h */ { union REGS regs; regs.h.ah = 0; /* MOV AH,0 - služba 0 */ int86(0x61, ®s, ®s); /* INT 61h */ }
A zde je odpovídající převodní tabulka (lze to napsat i úsporněji):
kód tón frekvence [Hz] 30h D#5 622,3 31h E-5 659,3 32h F-5 698,5 33h F#5 740,0 34h G-5 784,0 35h G#5 830,6 36h A-5 880,6 37h A#5 932,3 38h B-5 987,8 39h C-6 1046,5 3Ah C#6 1108,7 29h D-6 1174,7 3Bh D#6 1244,5 3Ch E-6 1318,5 3Dh F-6 1396,9 0Eh F#6 1480,0 3Eh G-6 1568,9 2Ch G#6 1661,2 3Fh A-6 1760,0 04h A#6 1864,7 05h B-6 1975,5 25h C-7 2093,0 2Fh C#7 2217,5 06h D-7 2349,3 07h D#7 2489,0
A nakonec ona funkce:Byte tone[25]={ 0x30, // 0 D#5 622.3 Hz 0x31, // 1 E-5 659.3 Hz 0x32, // 2 F-5 698.5 Hz 0x33, // 3 F#5 740.0 Hz 0x34, // 4 G-5 784.0 Hz 0x35, // 5 G#5 830.6 Hz 0x36, // 6 A-5 880.6 Hz 0x37, // 7 A#5 932.3 Hz 0x38, // 8 B-5 987.8 Hz 0x39, // 9 C-6 1046.5 Hz 0x3A, // 10 C#6 1108.7 Hz 0x29, // 11 D-6 1174.7 Hz 0x3B, // 12 D#6 1244.5 Hz 0x3C, // 13 E-6 1318.5 Hz 0x3D, // 14 F-6 1396.9 Hz 0x0E, // 15 F#6 1480.0 Hz 0x3E, // 16 G-6 1568.9 Hz 0x2C, // 17 G#6 1661.2 Hz 0x3F, // 18 A-6 1760.0 Hz 0x04, // 19 A#6 1864.7 Hz 0x05, // 20 B-6 1975.5 Hz 0x25, // 21 C-7 2093.0 Hz 0x2F, // 22 C#7 2217.5 Hz 0x06, // 23 D-7 2349.3 Hz 0x07 // 24 D#7 2489.0 Hz };
Toť vše.void playtone(Byte ton, Byte len) /* zahraje ton z tabulky po dobu 10*len ms */ { union REGS regs; regs.h.ah = 0x16; /* MOV AH,16h - služba 16h */ regs.x.cx = len; /* MOV CX, delka tonu v 10ms krocich */ regs.h.dl = tone[ton]; /* MOV DL, kód tónu-viz tabulka */ int86(0x61, ®s, ®s); /* INT 61h */ }