Программа IOSOUND
Приведем исходный текст программы IOSOUND, генерирующую звук без использования таймера (листинг 5.3.). Эта программа формирует импульсы при помощи манипуляций с разрядом 1 порта 61h.
Листинг 5.3. Файл iosound\iosound.с
// =====================================================
// Генерация звукового сигнала через порты таймера
//
// (C) Фролов А.В, 1997
//
// E-mail: frolov@glas.apc.org
// WWW: http://www.glasnet.ru/~frolov
// или
// http://www.dials.ccas.ru/frolov
// =====================================================
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#define FREQUENCY 200
#define CYCLES 30000
int main(void)
{
// Во время генерации звука прерывания должны
// быть запрещены.
_disable();
_asm
{
// Загружаем количество циклов - периодов
// генерируемых импульсов
mov dx, CYCLES
// Отключаем громкоговоритель от таймера
in al, 61h
and al, 0feh
// Цикл формирования периода
sound_cycle:
// Формируем первый полупериод, подаем
// на громкоговоритель уровень 1
or al, 2
out 61h, al
// Формируем задержку
mov cx, FREQUENCY
first: loop first
// Формируем второй полупериод, подаем
// на громкоговоритель уровень 0
and al, 0fdh
out 61h, al
// Формируем задержку
mov cx, FREQUENCY
second: loop second
// Если сформированы не все периоды, переходим
// к формированию следующего периода.
dec dx
jnz sound_cycle
}
// Разрешаем прерывания
_enable();
// Выключаем громкоговоритель
outp(0x61, inp(0x61) & 0xfc);
return 0;
}
Так как в программе IOSOUND для формирования полупериодов используется задержка с помощью команды LOOP, высота генерируемого тона будет зависеть от производительности системы.
Такой зависимости можно избежать, если перед началом работы измерять производительность и соответствующим образом корректировать константу, загружаемую в регистр CX перед вызовом команды LOOP. Измерение производительности лучше всего выполнять с помощью таймера, определяя время выполнения команды LOOP.