Справочник программиста на персональном компьютере фирмы IBM. Таймеры и звук
Страница 12. Генерация тона


     2.2.2 Генерация тона.


   Этот подраздел объясняет как производить звук, когда компьютер
не занят ничем другим; в [2.2.3]  показано как это сделать, когда
производятся  другие действия.  Забавно, но для программистов  на
ассемблере последнее проще.  Для  этого достаточно запрограммиро-
вать  микросхему  таймера  8253, которая работает  независимо  от
процессора.  В приведенном здесь методе процессор непосредственно
управляет динамиком, поэтому программе приходится выполнять рабо-
ту, которую может выполнять микросхема таймера.  Хотя этот способ
более  труден, но он допускает существенно больший  контроль  над
динамиком и  создание  большинства  специальных звуковых эффектов
[2.2.8] основывается на нем.

   Высокий уровень.


   Оператор Бейсика SOUND используется для генерации тона в широ-
ком диапазоне частот и длительностей. Частота дается в герцах (от
37  до 32767), а длительность в импульсах счетчика времени  суток
BIOS (от 0 до 65535), причем в  секунду происходит 18.2 импульса.
SOUND  440,91  воспроизводит ноту A в течение 5 секунд  (5*18.2).
Частоты первой октавы, начиная с ноты C(до) таковы:

                 C(до)              523.3
                 D(ре)              587.3
                 E(ми)              659.3
                 F(фа)              698.5
                 G(соль)            784.0
                 A(ля)              880.0
                 B(си)              987.7

Частоты  на октаву выше можно получить, удваивая эти значения, на
две октавы выше - еще раз удваивая  частоты.  И наоборот, частоты
на октаву ниже равны приблизительно половине этих значений (хоро-
шо настроенное пианино точно не  следует  арифметическим интерва-
лам).
   Благодаря своему генератору звука [2.2.1] PCjr может использо-
вать  оператор  SOUND для трех независимых каналов звука,  причем
может управляться громкость каждого  из них. В этом случае формат
оператора:  SOUND частота, длительность, громкость, канал.  Гром-
кость может меняться от 0  до  15,  по  умолчанию 8. Номер канала
может  меняться от 0 до 2, по умолчанию 0.  Поскольку PCjr  может
использовать возможности многоголосия и контроля звука только для
внешнего  динамика, то надо сначала разрешить этот динамик.   Это
делается с помощью оператора SOUND  ON.  SOUND OFF передает конт-
роль  внутреннему динамику.  Чтобы сыграть аккорд D-минор (ре-ми-
нор) (D-F-A) с малой громкостью, напишите:

100 SOUND ON             'разрешение внешнего динамика
110 SOUND 587,50,3,0     'нота ре
120 SOUND 699,50,3,1     'нота фа
130 SOUND 880,50,3,1     'нота ля

   Низкий уровень.


   Генерация звука с  помощью  адаптера  интерфейса  с периферией
8255  состоит во включении и выключении с желаемой частотой  бита
порта B, который связан с динамиком  (бит 1).  Порт B имеет адрес
61H (хотя AT не имеет микросхемы интерфейса с периферией 8255 как
таковой, он использует для этой  цели тот же адрес порта и тот же
бит).   Если  программа переключает значение  бита с  максимально
возможной частотой, то частота слишком высокая, чтобы быть полез-
ной.   Поэтому  между двумя переключениями надо вставлять  пустой
цикл.  Помните, что бит 0  порта  B  управляет  воротами канала 2
микросхемы  таймера, который в свою очередь  связан с  динамиком.
Поэтому этот бит  должен  быть  сброшен,  отсоединяясь  от канала
таймера. На рис. 2-4 показано как этот метод устанавливает часто-
ту звука.
   В следующем примере введены две переменные. Одна, обозначенная
"FREQUENCY",  используется  в  качестве  счетчика  в пустом цикле
между действиями включения и выключения.  Чем меньше ее значение,
тем быстрее происходит изменение бита и тем больше частота. Пере-
менная  же "NUMBER_CYCLES" устанавливает продолжительность  тона.
Она говорит сколько раз должен быть  повторен процесс включения и
выключения. Чем больше это число, тем дольше звучит данный звук.
   Отметим,  что для этой процедуры аппаратные прерывания  должны
быть  запрещены.   Причина этого в том,  что  прерывание  таймера
происходит с такой частотой и  регулярностью  (18.2 раза в секун-
ду),  что оно будет существенно влиять на частоту.  Имейте ввиду,
что пока прерывания  запрещены,  счетчик  времени  суток  BIOS не
будет  работать.  Если затем прочитать его значение, то оно будет
отличаться на некоторую  величину  от реального, до тех пор, пока
не будет сделано соответствующее изменение.

NUMBER_CYCLES  EQU   1000
FREQUENCY      EQU   300
PORT_B         EQU   61H
               CLI                 ;запрет прерываний
               MOV   DX,NUMBER_CYCLES  ;длительность тона в DX
               IN    AL,PORT_B     ;получаем значение из порта B
               AND   AL,11111110B  ;отключаем динамик от таймера
NEXT_CYCLE:    OR    AL,00000010B  ;включаем динамик
               OUT   PORT_B,AL     ;посылаем команду в порт B
               MOV   CX,FREQUENCY  ;задержка на пол-цикла в CX
FIRST_HALF:    LOOP  FIRST_HALF    ;делаем задержку
               AND   AL,11111101B  ;выключаем динамик
               OUT   PORT_B,AL     ;посылаем команду в порт B
               MOV   CX,FREQUENCY  ;задержка на пол-цикла в CX
SECOND_HALF:   LOOP  SECOND_HALF   ;делаем задержку
               DEC   DX            ;вычитаем единицу из счетчика
               JNZ   NEXT_CYCLE    ;если 0, то надо кончать
               STI                 ;разрешаем прерывания

 
« Предыдущая статья   Следующая статья »