5.10.8. Звуковые платы

Звуковые платы, совместимые с теми или иными моделями Sound Blaster, выглядят как четыре независимых устройства:

□ DSP (Digital Signal Processor) - устройство, позволяющее выводить и счи­тывать оцифрованный звук; ' а микшер (Mixer) - система регуляторов громкости для всех каналов платы;

1МА№'       Сложные приемы программирования

□ FM (Frequency Modulation) или AdLib (по названию первой звуковой пла­ты) - устройство, позволяющее синтезировать звук из синусоидальных и треугольных волн. Слова типа OPL2 или OPL3 в описании платы - это и есть номера версии используемого FM-синтезатора;

□ MIDI (Music Instrumental Digital Interface) - стандартный интерфейс пере­дачи данных в музыкальной аппаратуре. Но в нашем случае рассматривает­ся GMIDI (обобщенный MIDI) - более качественная система генерации му­зыки, в которой используются не искусственные синусоидальные сигналы, а образцы звучания различных инструментов. К сожалению, качество этих образцов в большинстве дешевых плат оставляет желать лучшего.

Номера портов ввода-вывода, предоставляющих доступ ко всем этим устрой­ствам, отсчитываются от базового порта, обычно равного но допускаются также конфигурации с 2101т, 230h, 240h, 250h, 260h и 280h. Кроме того, интерфейс GMIDI использует другую серию портов, которая может начинаться как с 300h, так и с 330h. В описаниях портов мы будем считать, что базовыми являются 220h и 300h. Область портов интерфейса с AdLib начинается с 388h.

Существует большое число модификаций плат Sound Blaster, отличающихся, помимо всего прочего, набором поддерживаемых команд и портов ввода-вывода. После названия каждой команды или порта мы будем указывать сокращенное название платы, начиная с которой эта команда или порт поддерживается:

□ SB - Sound Blaster 1.0; а SB2 - Sound Blaster 2.0;

□ SBPro - Sound Blaster Pro;

□ SBPro2 - Sound Blaster Pro2;

□ SB 16 - Sound Blaster 16;

□ ASP - Sound Blaster 16 ASP;

□ AWE - Sound Blaster AWE32.

Программирование DSP

Цифровой процессор - наиболее важная часть звуковой платы. Именно с его помощью осуществляется вывод обычного оцифрованного звука, так же как и за­пись звука из внешнего источника в файл. Для своей работы, помимо описывае­мых в этом разделе портов, DSP использует прерывания и контроллер прямого

доступа к памяти DMA. Программирование DMA с примером программы, ис­пользующей его для воспроизведения звука, мы рассмотрим в разделе 5.10.9.

DSP обслуживается при помощи следующих портов:

226h для записи: сброс DSP (SB)

Запись в этот порт осуществляет полную переинициализацию DSP, прерывая все происходящие процессы. Операцию сброса DSP необходимо выполнить, по крайней мере, один раз после перезагрузки системы, чтобы его можно было ис­пользовать.

Процедура сброса осуществляется следующим образом:

1. В порт 226h записывается число 1 (начало инициализации).

2. Выдерживается пауза как минимум 3,3 мкс.

Программирование на уровне портов |,

3. В порт 226п записывается число 0 (конец инициализации).

4. Выдерживается пауза максимум 100мкс. В течение паузы можно выполнять чтение порта 22Еп. Когда в считываемом числе будет установлен бит 7 (дан­ные готовы), можно сразу переходить к пункту 5. В противном случае имеет смысл повторить процедуру, используя другой базовый порт.

5. Выполняется чтение из порта 22Ап. Если считанное число равно ОААЬ. - ББР был успешно инициализирован. В противном случае допускается вернуться к пункту 4, но по истечении 100 мкс после записи в 226Ь можно будет с уверен­ностью сказать, что ББР с базовым адресом 220п не существует или не работает.

22ЛН для чтения: чтение данных из ББР (БВ)

Чтение из этого порта используется для передачи всех возможных данных от ББР программам. Процедура чтения состоит из двух шагов:

Выполнять цикл чтения порта        пока бит 7 считываемого байта не ока­жется равным единице. 2. Выполнить чтение из порта 22Ап.

22СН для записи: запись данных и команд ББР (начиная с БВ)

Этот единственный порт используется для передачи всего множества команд ББР и для пересылки в него данных (аргументов команд). Процедура записи:

Выполнять цикл чтения порта пока бит 7 считываемого байта не ока-

жется равным нулю. 2. Выполнить запись в порт 22СЬ.

22С/г для чтения: готовность ББР для приема команды (БВ)

Если при чтении из этого порта бит 7 сброшен в ноль - ББР готов к приему оче­редного байта в порт 22Сп на запись. Значение остальных битов не определено.

22ЕН для чтения: готовность ББР для посылки данных (начиная с БВ)

Если при чтении из этого порта бит 7 установлен в единицу - ББР готов к пере­даче через порт 22Ап очередного байта.

22ЕН для чтения (тот же порт!): подтверждение обработки 8-битного прерыва­ния (БВ)

Обработчик прерывания, сгенерированного звуковой платой по окончании 8-битной операции, обязательно должен выполнить одно чтение из этого порта перед завершением (помимо обычной процедуры посылки сигнала ЕОІ в соответ­ствующий контроллер прерываний).

22Й1 для чтения: подтверждение обработки 16-битного прерывания (БВ16)

Обработчик прерывания, сгенерированного звуковой платой по окончании 16-битной операции, обязательно должен выполнить одно чтение из этого пор­та перед завершением (помимо обычной процедуры посылки сигнала ЕОІ в со­ответствующий контроллер прерываний).

Теперь рассмотрим команды ББР. Все они пересылаются в звуковую плату че­рез порт как описано выше. После команды могут следовать аргументы,шштм

Сложные приемы программирования

которые передаются таким же образом (включая ожидание готовности к приему команды).

04h: состояние DSP (устаревшая) (SB2 - SBPro2)

Возвращает информацию о текущей операции DSP: бит 0: динамик включен бит 1: стерео АЦП включен бит 2: всегда О

бит 3: происходит прямое воспроизведение 8-битного РСМ

бит 4: происходит воспроизведение 2-битного ADPCM через DMA

бит 5: происходит воспроизведение 2,6-битного ADPCM через DMA

бит 6: происходит воспроизведение 4-битного ADPCM через DMA

бит 7: происходит воспроизведение 8-битного РСМ через DMA 10h, NN: прямое воспроизведение 8-битного звука (SB)

Выводит очередной байт (NN) из несжатого 8-битного оцифрованного звука на воспроизведение. При использовании этого способа воспроизведения сама про­грамма должна заботиться о том, чтобы новые данные всегда были наготове (то есть не считывать их с диска в ходе работы) и чтобы байты пересылались в DSP с необходимой частотой. (В этом режиме поддерживаются частоты до 23 кГц.)

Процедура вывода проста:

1. Вывести в DSP команду ЮЬи очередной байт из оцифровки.

2. Подождать необходимое время и вернуться к пункту 1.

Чтобы выполнять пересылку байтов с заданной частотой, обычно перепрог­раммируют системный таймер, как будет показано в конце этого раздела. Но из-

за ограничений по качеству звука и высокой ресурсоемкости такой способ вос­произведения практически не используется.

14h, LO, HI: прямое воспроизведение 8-битного РСМ через DMA (SB) Начинает процесс воспроизведения данных, на которые настроен соответствую­щий канал DMA (см. раздел 5.10.9):

1. Установить обработчик прерывания от звуковой платы (и разрешить его

в контроллере прерываний).

2. Выполнить команду 40h или другим образом установить частоту оцифровки.

3. Выполнить команду ODlh (включить динамик). .  4, Настроить DMA (режим 48h + номер канала).

5. Выполнить команду 14h. Аргументы LO и HI - это младший и старший бай­ты длины проигрываемого участка минус один.

6. Из обработчика прерывания подтвердить его чтением порта 22Eh и посыл­кой байта 20h в соответствующий контроллер прерываний.

7. Выполнить команду 0D3h (выключить динамик).

На платах, начиная с БВ 16, для этого режима рекомендуется пользоваться ко­мандами ОС?п.тшш

16h, L0, НІ: прямое воспроизведение 2-битного ADPCM через DMA (SB) Начинает процесс воспроизведения данных аналогично команде но они долж­ны храниться в сжатом формате Creative ADPCM 2 bit. Длина, указываемая в каче­стве аргументов этой команды, равна (число_байтов + 2)/4. В качестве нулевого байта в процедуре распаковки ADPCM используется значение, которое применя­лось последней командой В остальном процедура воспроизведения аналогич­на команде l4h.

17h, LO, HI: прямое воспроизведение 2-битного ADPCM через DMA с новым ну­левым байтом (SB)

То же самое, что и l6h, но байт из данных будет рассматриваться как ну-

левой байт для процедуры распаковки ADPCM.

iCh: воспроизведение 8-битного РСМ через DMA с автоинициализацией (SB2)

Начинает режим воспроизведения с автоинициализацией - лучший из режимов,

предлагаемых звуковыми платами. В этом режиме DSP воспроизводит в цикле содержимое указанного участка памяти, мгновенно возвращаясь на начало, пока он не будет остановлен командой ODAh или новой командой воспроизведения через DMA. Весь секрет заключается в том, что плата генерирует прерывание не только при достижении конца блока, но и при достижении его середины. Таким образом, пока DSP проигрывает вторую половину буфера, мы можем прочитать следующие несколько килобайтов в первую половину, не останавливая воспроиз­ведение ни на миг:

1. Установить обработчик прерывания звуковой платы и разрешить его в кон­троллере прерываний.

2. Выполнить команду 40h или другим образом установить частоту оцифровки.

3. Выполнить команду 48h

(установить размер DMA-буфера = (число_байтов + 1)/2 - 1).

4. Выполнить команду ODlh (включить динамик).

5. Настроить DMA (режим 58h + номер канала).

6. Выполнить команду ICh.

7. В обработчике прерывания: заполнить следующую половину буфера.

8. В обработчике прерывания: подтвердить прерывание чтением из 22Eh и за­писью 20h в контроллер прерываний.

9. Подождать, пока не будут воспроизведены все данные.

10. Выполнить команду OD3h (выключить динамик).

11. Выполнить команду ODOh (остановить 8-битную DMA-передачу).

12. Выполнить команду ODAh (завершить режим автоинициализации).

13. Выполнить команду ODOh (остановить 8-битную DMA-передачу).

На платах, начиная с SBl6, для этого режима рекомендуется пользоваться ко­мандами OC?h.

lFh: воспроизведение 2-битного ADPCM через DMA с автоинициализацией

(SB2)

Аналог команды ICh, но данные хранятся в 2-битном формате ADPCM с нуле­вым байтом. Длина блока рассчитывается так:

длина = (число_байтов + 3)/4 + 1

длина блока = (длина + 1)/2 - 1

20h: прямое чтение 8-битных данных из АЦП (SB)

Команда предназначена для чтения оцифрованного звука из внешнего источни­ка. Используется следующая процедура:

1. Выполнить команду 20h.

2. Прочитать очередной байт.

3. Подождать необходимое время и вернуться к пункту 1. Проблемы с этой командой точно такие же, как и с 10h.

24h, LO, HI: чтение 8-битного PCM через DMA (SB)

Аналог команды 14h, но выполняет не воспроизведение, а запись звука. Последо­вательность действий идентична случаю с 14h, но используемый режим DMA -44h + номер канала.

2Ch: запись 8-битного РСМ через DMA с автоинициализацией (SB2) Аналог команды ICh, но выполняет не воспроизведение, а запись звука. Последо­вательность действий идентична случаю с ICh, но используемый режим DMA -54h + номер канала.

30h: прямое чтение MIDI (SB) Выполняет чтение очередного

\. Выполнить команду 30h.

2. Прочитать MIDI-событие (до 64 байт).

31h: чтение MIDI с прерыванием (SB)

Включает генерацию прерывания от звуковой платы при поступлении нового MIDI-события. Для этого необходимо:

1. Установить обработчик прерывания.

2. Выполнить команду 31h.

3. В обработчике прерывания: прочитать MIDI-событие.

4. В обработчике прерывания: подтвердить прерывание чтением из 22Eh и за­писью 20h в контроллер прерываний.

5. Выполнить команду 31h еще раз, чтобы отменить генерацию прерывания.

32h: прямое чтение MIDI-события с дельта-временем (SB) Выполняет чтение очередного MIDI-события и 24-битного дельта-времени, то есть времени в микросекундах, наступившего после предшествующего MIDI-со­бытия. (Считываются данные в следующем порядке: младший байт времени, средний байт времени, старший байт времени, MIDI-команда.) Именно в виде последовательности MIDI-событий, перед каждым из которых указано дельта-время, и записывается музыка в MIDI-файлах.

32h: чтение MIDI-события с дельта-временем с прерыванием (SB)

Включает/выключает генерацию прерываний от звуковой платы аналогично ко­манде 3lh, но при чтении MIDI-события передаются вместе с дельта-временами, как в команде 32h.

34h: режим прямого доступа к UART (SB2)

Отключает DSP, после чего все команды записи/чтения в его порты (используя

тот же механизм проверки готовности) рассматриваются как MIDI-события. Вы­вести DSP из этого режима можно только с помощью полной переинициализации.

37h: режим прямого доступа к UART с прерыванием (SB2) Переключает порты DSP на UART аналогично команде 34h, но каждый раз, ког­да новое готово для чтения, вызывается прерывание звуковой платы.

38h, MIDI: прямая       MIDI (SB)

Посылает одно MIDI-событие.

40h, ТС: установить временную константу (SB)

Устанавливает частоту оцифровки, используя однобайтную константу, рассчиты­ваемую следующим образом:

ТС = 256 - (1000000 / (число_каналов X частота)), где - l для моно и 2 для стерео.

41h, LO, HI: установить частоту оцифровки (SB16)

Аналогично 40h, но указывается истинное значение частоты (сначала младший,

потом старший байты). Число каналов определяется автоматически. Реальная частота тем не менее округляется до ближайшего возможного значения ТС.

45h: продолжить остановленное 8-битное воспроизведение через DMA (SB16)

Продолжает остановленное командой ODAh воспроизведение 8-битного звука

через DMA с автоинициализацией.

47h: продолжить остановленное 16-битное воспроизведение через DMA (SB16) Продолжает остановленное командой 0D9h воспроизведение 16-битного звука через DMA с автоинициализацией.

48h, LO, HI: установить размер буфера DMA (SB2)

Устанавливает число байтов минус один для следующей команды передачи через

DMA (сначала младший байт, затем старший).

74h, LO, HI: прямое воспроизведение 4-битного ADPCM через DMA (SB) Аналог 1бЬ,но используется 4-битный вариант формата Creative ADPCM.

75h, LO, HI: прямое воспроизведение 4-битного ADPCM через DMA с новым ну­левым байтом (SB)

Аналог 17h, но используется 4-битный вариант формата Creative ADPCM.

76h, LO, HI: прямое воспроизведение 2,6-битного ADPCM через DMA (SB) Аналог 16h, но используется 2,6-битный вариант формата Creative ADPCM.

77h, LO, HI: прямое воспроизведение 2,6-битного ADPCM через DMA с новым

нулевым байтом (SB)

Аналог l7h, но используется 2,6-битный вариант формата Creative ADPCM.

7Dh: воспроизведение 4-битного ADPCM через DMA с автоинициализацией (SB2) Аналог lFh, но используется 4-битный вариант формата Creative ADPCM.

7Fh: воспроизведение 2,6-битного ADPCM через DMA с автоинициализацией (SB2) Аналог lFh, но используется 2,6-битный вариант формата Creative ADPCM.

80h, LO, HI: заглушить DSP (SB)

Вывести указанное число байтов тишины с текущей частотой оцифровки. OB?h/OC?h MODE, LO, HI: обобщенный интерфейс к DSP l6)

Команды OB?h используются для 16-битных операций, команды OC?h - для

8-битных. Младшие четыре бита определяют режим: бит 0: всегда О

бит 1: используется FIFO

бит 2: используется автоинициализация DMA

бит 3: направление передачи (0 - воспроизведение, 1 - оцифровка)

Аргументы этой команды - режим, младший байт длины, старший байт дли­ны (перед указанной командой не требуется устанавливать размер DMA-буфера

специально).

В байте режима определены всего два бита (остальные должны быть равны нулю): бит 4: данные рассматриваются как числа со знаком бит З: режим стерео

Длина во всех случаях равна числу байтов минус один для 8-битных операций и числу слов минус один для 16-битных.

ODOh: остановить 8-битную DMA-операцию (SB)

Останавливает простую (без автоинициализации) 8-битную DMA-операцию.

включить динамик (SB) Разрешает работу выхода на динамик (колонки и т. д.). После сброса DSP этот канал выключен.

OD3h: выключить динамик (SB)

Отключает выход на динамик (колонки и т. д.).

OD4h: продолжить 8-битную DMA-операцию (SB) Продолжает DMA-операцию, остановленную командой ODOh.

OD5h: остановить 16-битную DMA-операцию (SB)

Останавливает простую (без ^ автоинициализации) 16-битную DMA-операцию.

OD6h: продолжить 16-битную DMA-операцию (SB) Продолжает DMA-операцию, остановленную командой OD5h.

0D8h: определить состояние динамика (SB)

Возвращает 00h, если динамик выключен; OFFh, если включен.

OD9h: завершить 16-битную DMA-операцию с автоинициализацией (SB16) Эта команда завершает операцию только после окончания воспроизведения теку­щего блока. Для немедленного прекращения воспроизведения необходимо выпол­нить последовательно команды OD3h, OD5h, OD9h и OD5h.

ODAh: завершить 8-битную DMA-операцию с автоинициализацией (SB2) Аналог OD9h, но для 8-битных операций.

OEOh, BYTE: проверка наличия DSP на этом порту (SB2)

Любой байт, посланный как аргумент к этой команде, возвращается при чтении из DSP в виде своего побитового дополнения (DSP выполняет над ним операцию NOT).

определение номера версии DSP (SB) Возвращает последовательно старший и младший номера версии DSP: 1.7-SB 2.0 - SB2 3.0 - SBPro 3.? - SBPro2 4.0? - SB16

4.11 - SB16SCSI-2

4.12 - AWE32

OE3h: чтение Copyright DSP (SBPro2)

Возвращает ASCIZ-строку с информацией Copyright данной платы.

OE4h, BYTE: запись в тестовый регистр (SB2)

Помещает байт в специальный неиспользуемый регистр, который сохраняется даже после переинициализации DSP.

OE8h: чтение из тестового регистра (SB2)

Возвращает байт, помещенный ранее в тестовый регистр командой OE4h.

генерация синусоидального сигнала (SB) Запускает DSP на воспроизведение синусоидального сигнала с частотой около 2 кГц, который можно прервать только сбросом DSP.

OF2h: запрос на прерывание в 8-битном режиме (SB)

Генерирует прерывание от звуковой карты. В качестве подтверждения от обработ­чика ожидается чтение из порта 22Eh.

OF3h: запрос на прерывание в 16-битном режиме (SB)

Генерирует прерывание от звуковой карты. В качестве подтверждения от обработ­чика ожидается чтение из порта 22Fh,

OFBh: состояние DSP (SB16)

Возвращает байт состояния текущей DSP-операции:

бит 0: 8-битное воспроизведение через DMA

бит 1: 8-битное чтение через DMA

Сложные приемы программирования

бит 2: 16-битное воспроизведение через DMA бит 3: 16-битное чтение через DMA бит 4: динамик включен биты 5-6: не определены

бит 7: ТС модифицирована (может быть ноль, если предыдущая команда 40h пыталась установить неподдерживаемую частоту)

OFCh: дополнительная информация (SB16)

Возвращает дополнительный байт состояния текущей DMA-операции:

бит 1: синхронный режим (одновременная запись и воспроизведение) .  бит 2:8-битный режим с автоинициализацией бит 4: 16-битный режим с автоинициализацией

OFDh: последняя выполненная команда (SB16) Возвращает последнюю успешную команду DSP.

Программирование микшера

Это устройство предназначено для регулирования громкости на всех каналах, используемых звуковой платой.

Для управления микшером служат всего два порта ввода-вывода.

224h для записи: выбор регистра микшера (SBPro)

Запись в этот порт выбирает номер регистра, к которому будет осуществляться доступ при последующих обращениях к порту 225h.

225h для чтения и записи: чтение/запись регистра микшера (SBPro) Чтение и запись в этот порт приводят к чтению и записи в соответствующий ре­' гистр микшера. Рассмотрим их назначение.

Регистр ООЬ для записи: сброс и инициализация (SBPro)

Выбор этого регистра в порту 224h начинает инициализацию. Следует подождать как минимум 100 мкс, а затем записать в порт 225h число 0lh (команда «завер­шить инициализацию»).

Регистр Olh для чтения: состояние микшера (SBPro)

Возвращает последний номер регистра.

Регистр 04h для чтения и записи: уровень (SBPro)

биты 4-0: уровень правого ЦАП биты 7-4: уровень левого ЦАП

Регистр    для чтения и записи: уровень микрофона (SBPro) биты 2-0: уровень микрофона

Регистр 22h для чтения и записи: общий уровень (SBPro) биты 4-0: правый общий уровень биты 7-4: левый общий уровень

Программирование на уровне портов .ШВН

Регистр 26h для чтения и записи: уровень FM (SBPro) биты 4-0: правый уровень FM биты 7-4: левый уровень FM

Регистр 28h для чтения и записи: уровень CD audio (SBPro) биты 4-0: правый уровень CD audio

биты 7-4: левый уровень CD audio

Регистр 2Eh для чтения и записи: уровень линейного входа (SBPro) биты 4-0: уровень правого линейного входа биты 7-4: уровень левого линейного входа

Регистр 30h для чтения и записи: левый общий уровень (SB16) биты 7-1: левый общий уровень

Регистр 31h для чтения и записи: правый общий уровень (SB16) биты 7-1: правый общий уровень

Регистр 32h для чтения и записи: левый уровень ЦАП (SB16) биты 7-1: левый уровень ЦАП

Регистр 33h для чтения и записи: правый уровень ЦАП (SB16) биты 7-1: правый уровень ЦАП

Регистр 34h для чтения и записи: левый уровень FM (SB16)

биты 7-1: левый уровень FM

Регистр' 35h для чтения и записи: правый уровень FM (SB16)

биты 7-1: правый уровень FM

Регистр 36h для чтения и записи: левый уровень CD audio (SB16) биты 7-1: левый уровень CD audio

Регистр 37h для чтения и записи: правый уровень CD audio (SB16) биты 7-1: правый уровень CD audio

Регистр 38h для чтения и записи: левый уровень линейного входа (SB16) биты 7-1: левый уровень линейного входа

Регистр 39h для чтения и записи: правый уровень линейного входа (SB16) биты 7-1: правый уровень линейного входа

Регистр 3Ah для чтения и записи: уровень микрофона (SB16) биты 7-3: уровень микрофона

Регистр 3Bh для чтения и записи:, уровень динамика PC (SB16) биты 7-5: уровень динамика PC

Регистр 3Ch для чтения и записи: управление выводом (SB16) бит 0: микрофон включен бит 1: правый канал CD audio включен

бит 2: левый канал CD audio включен

бит З: правый канал линейного входа включен бит 4: левый канал линейного входа включен биты 7-5: нули

Регистр 3Dh для чтения и записи: управление левым каналом ввода (SB 16)

бит 0: микрофон включен

бит 1: правый канал CD audio включен

бит 2: левый канал CD audio включен

бит З: правый канал линейного входа включен

бит 4: левый канал линейного входа включен бит 5: правый канал FM включен бит 6: левый канал FM включен

бит 7: нуль

Регистр 3Eh для чтения и записи: управление правым каналом ввода (SB16)

бит 0: микрофон включен

бит 1: правый канал CD audio включен

бит 2: левый канал CD audio включен

бит 3: правый канал линейного входа включен

бит 4: левый канал линейного входа включен бит 5: правый канал FM включен бит 6: левый канал FM включен бит 7: нуль

Регистр 3Fh для чтения и записи: уровень усиления в левом канале ввода (SB16) биты 7-5: усиление в левом канале ввода

Регистр 40h для чтения и записи: уровень усиления в правом канале ввода (SB 16) биты 7-5: усиление в правом канале ввода

Регистр 41h для чтения и записи: уровень усиления в левом канале вывода (SB16) биты 7-5: усиление в левом канале вывода

Регистр 42h для чтения и записи: уровень усиления в правом канале вывода 16) биты 7-5: усиление в правом канале вывода

Регистр 43h для чтения и записи: автоматическая подстройка усиления (SB 16) бит 0: автоматическая подстройка усиления

Регистр 44h для чтения и записи: уровень усиления высоких частот слева 16) биты 7-4: усиление высоких частот слева

Регистр 45h для чтения и записи: уровень усиления высоких частот справа (SB16) биты 7-4: усиление высоких частот справа

Регистр 46h для чтения и записи: уровень усиления басов слева

биты 7-4: усиление басов слева

Регистр 47h для чтения и записи: уровень усиления басов справа (SB16)

биты 7-4: усиление басов справа

Программирование на уровне портов ИМЯ

Регистр 80h для чтения и записи: выбор прерывания (SB16) бит 0: IRQ2 бит 1: IRQ5 бит 2: IRQ7 бит 3: IRQ10 биты 7-4: всегда 1

Эта установка сохраняется при сбросе микшера или даже при «горячей» пере­загрузке компьютера.

Регистр 81h для чтения и записи: выбор DMA (SB16) бит 0: 8-битный DMAO бит 1: 8-битный DMA1 бит 2: О

бит 3: 8-битный DMA3

бит 4: О

бит 5: 16-битный DMA5 бит 6: 16-битный DMA6 бит 7: 16-битный DMA7

Данная установка сохраняется при сбросе микшера или даже при «горячей» перезагрузке компьютера.

Регистр 82h для чтения: состояние прерывания (SB16)

бит 0: происходит обработка прерывания от 8-битной операции бит 2: происходит обработка прерывания от 16-битной операции бит 3: происходит обработка прерывания операции MPU-401 биты 7-4: зарезервированы

Частотный синтез (программирование AdLib)

. Синтезатор, расположенный на звуковой плате и отвечающий за FM-музы-ку, управляется тремя портами - портом состояния, выбора регистра и портом данных. Для совместимости с различными платами они дублируются несколь­ко раз.

228h, 388h для чтения: порт состояния FM (SB)

220h для чтения: порт состояния левого канала FM (SBPro)

222h, 38Ah для чтения: порт состояния правого канала FM (SBPro)

Определяет, закончился ли отсчет FM-таймеров и какого именно.

биты 4-0: всегда О

бит 5: таймер 2 (период - 230 мкс) сработал бит 6: таймер 1 (период - 80 мкс) сработал бит 7: один из таймеров сработал

228h, 388h для записи: выбор регистра FM (SB)

220h для записи: выбор регистра левого канала FM (SBPro)

222h, 38Ah для записи: выбор регистра правого канала FM (SBPro)

Запись числа в этот порт выбирает, с каким регистром синтезатора будут ра­ботать последующие команды записи в порт данных.

Процедура записи числа в регистр БМ выглядит следующим образом:

1. Выполнить запись в порт выбора регистра.

2. Подождать как минимум 3,3 мкс.

3. Выполнить запись в порт данных.

4. Подождать как минимум 23 мкс перед любой другой операцией со звуковой платой.

На современных платах эти паузы можно сделать меньше. Так, если использу­ется синтезатор ОРЬ3, требуемое значение пауз - 0,1 и 0,28 мкс.

229п, 389Н для записи: запись в регистр БМ (БВ)

221Ь для записи: запись в регистр левого канала БМ (БВРго)

223п, 38ВН для записи: запись в регистр правого канала (8ВРго)

Всего в этих синтезаторах доступно 244 регистра - от 01Ь до 0Р5Ь. Рассмот­рим наиболее полезные.

Регистр ОШ: тестовый регистр биты 4-0: О

бит 5: БМ микросхема контролирует форму волны "   биты 7-6: О

Регистр 02Ь: счетчик первого таймера

Значение этого счетчика увеличивается на единицу каждые 80 мкс. Когда ре­гистр переполняется, вырабатывается прерывание таймера ШСЮ и устанавли­ваются биты 7 и 6 в порту состояния.

Регистр 03Ь: счетчик второго таймера

Значение этого счетчика увеличивается на единицу каждые 320 мкс. Когда регистр переполняется, вырабатывается прерывание таймера ШСЮ и устанав­ливаются биты 7 и 5 в порту состояния.

Регистр 04Ь: регистр управления таймером

бит 0: установка бита запускает первый таймер (с начальным значением счет­чика, помещенным в регистр 02Ь)

бит 1: установка бита запускает второй таймер (с начальным значением счет­чика, помещенным в регистр

биты 4-2: зарезервированы

бит 5: маска второго таймера - установка этого бита запрещает включение вто­рого таймера при установке бита 1

бит 6: маска первого таймера - установка этого бита запрещает включение первого таймера при установке бита О

бит 7: сброс флагов для обоих таймеров

Регистр 08Ь: включение режимов СБМ и КеузрШ: биты 5-0: зарезервированы бит 6: включение режима кеузрШ бит 7: 1 - режим СБМ; 0 - режим БМ

Программирование на уровне портов ЦЩЩ

Режим CSM (синусоидально-волновой синтез речи) применялся на платах AdLib без DSP для воспроизведения оцифрованного звука (с очень плохим качеством).

Следующие регистры описываются группами - по одному на голос.

Регистры 20h - 35h: различные настройки режимов

биты 3-0: какая гармоника будет создавать звук (или модуляцию) относитель­но точно установленной частоты голоса:

0 - одной октавой ниже

1 - с точно установленной частотой голоса

2 — одной октавой выше

3 - октавой и квинтой выше

4 - двумя октавами выше

5 - двумя октавами и большой терцией выше

6 - двумя октавами и квинтой выше

7 - двумя октавами и малой септимой выше

8 - тремя октавами выше

9 - тремя октавами и большой секундой выше А, В - тремя октавами и большой терцией выше С, D - тремя октавами и квинтой выше

Е, F - тремя октавами и большой септимой выше бит 4: режим keyboard scaling - если он выбран, длина звука сокращается и он

повышается

бит 5: продление стадии поддержки звука (то есть он не затухает сразу после

нарастания)

бит 6: включает режим вибрато (его глубина контролируется флагом в регис­тре OBDh)

бит 7: применение амплитудной модуляции (ее глубина контролируется фла­гом в регистре OBDh)

Регистры 40h - 55h: управление уровнями выхода

биты 5-0: общий выходной уровень канала (00000 - максимум, 11111 - мини­мум)

биты 7-6: понижение выходного уровня с повышением частоты:

00 - не понижать

10 - 1,5 дБ на октаву

01 - 3 дБ на октаву

11 - 7 дБ на октаву

Регистры 60h - 75h: темп нарастания/спада

биты 3-0: темп спада (0 - минимум, F - максимум) биты 7-4: темп нарастания (0 - минимум, F - максимум)

Регистры 80h - 95h: уровень поддержки/темп отпускания биты 3-0: темп отпускания (0 - минимум, F - максимум) биты 7-4: уровень поддержки (0 - минимум, F - максимум)

Регистры OAOh - OA8h: нота (младший байт) биты 7-0: биты 7-0 номера ноты

Регистры OBOh - OB8h: октава и нота (старшие биты) биты 1-0: биты 9-8 номера ноты биты 4-2: номер октавы бит 5: включить звук в этом канале

Значение 10-битного номера ноты соответствует следующим реальным нотам (для четвертой октавы): 016Bh - С# (277,2 Гц) 0181h - D (293,7 Гц) 0198h-D# (311,1Гц) OlBOh - Е (329,6 Гц) OlCAh - F (349,2 Гц) 01E5h - F# (370,0 Гц) 0202h - G (392,0 Гц) 0220h- G# (415,3 Гц) 0241h- A(440,0 Гц) 0263h - A# (466,2 Гц) 0287h - В (493,9 Гц) 02AEh - С (523,3 Гц)

Регистры      - OC8h: обратная связь/алгоритм

бит 0: 0 - первый оператор модулирует второй, 1 -<- оба оператора непосредст­венно производят звук биты 3-1: сила обратной связи. Если это поле ненулевое, первый оператор будет посылать долю выходного сигнала обратно в себя

Регистр OBDh: глубины модуляций/ритм бит 0: включен HiHat бит 1: включен Cymbal бит 2: включен Tam-tam бит 3: включен Snare drum бит 4: включен Bass drum

бит 5: 1 - включен ритм (6 голосов на мелодию), 0 - ритм выключен (9 голо­сов на мелодию) бит 6: глубина вибрато

бит 7: глубина амплитудной модуляции (1-4,8 дБ; 0-1 дБ)

Регистры 0E0h - OF5h: выбор формы волны

биты 1-0:форма волны, использующаяся, если бит 5 регистра 01Ьустановлен в 1. 00: синусоида

01: синусоида без отрицательной половины

02: абсолютное значение синусоиды (нижние полуволны отражены вверх)

11 .тшлообразныеимпульсытшт

Чтобы извлечь из FM простой звук, выполним такую последовательность действий:

1. Обнулим все регистры (грубый способ инициализации AdLib). Канал 0 будет использоваться для голоса:

2. Запишем в регистр 20h число Olh - кратность модуляции 1.

3. Запишем в регистр 40h число 10h - уровень модуляции 40 дБ.

4. Запишем в регистр 60h число OFOh - нарастание быстрое, спад - долгий.

5. Запишем в регистр 80h число 77h - поддержка и отпускание средние.

6. Запишем в регистр OAOh число 98h - нота D#. Канал 3 будет использоваться для несущей:

7. Запишем в регистр 023h число Olh - кратность несущей 1.

8. Запишем в регистр 043h число OOh - максимальная громкость для несущей (47 дБ).

9. Запишем в регистр 063h число OFOh - нарастание среднее, спад - долгий. 10. Запишем в регистр 083h число 77h - поддержка и отпускание - средние. И. Запишем в. регистр OBOh число 03lh - установить октаву, старшие биты

ноты и включить голос. С этого момента синтезатор звучит. 12. Запишем в регистр OBOh число llh (или любое с нулевым битом 5) для вы­ключения звука.

Пример программы

Программирование современных звуковых плат - весьма сложное занятие, поэтому в качестве примера рассмотрим одну часто применяемую операцию -воспроизведение оцифрованного звука. С этой целью потребуется программиро­вать только DSP. Для вывода звука через звуковую плату может использоваться один из трех режимов: прямой вывод (команда когда программа должна

сама с нужной частотой посылать отдельные байты из оцифрованного звука в DSP; простой DMA-режим, когда выводится блок данных, после чего вызыва­ется прерывание; и DMA с автоинициализацией, когда данные выводятся непре­рывно и после вывода каждого блока вызывается прерывание. Именно в этом порядке увеличивается качество воспроизводимого звука. Так как мы пока не умеем работать с DMA, рассмотрим первый способ.

Чтобы вывести оцифрованные данные с нужной частотой в DSP, придется

перепрограммировать канал 0 системного таймера на требуемую частоту и уста­новить собственный обработчик прерывания 08h. При этом будет нарушена ра­бота системных часов, хотя можно не выключать совсем старый обработчик, а передавать ему управление примерно 18,2 раза в секунду, то есть, в частности, при каждом 604-м вызове нашего обработчика на частоте 11 025 Гц. Покажем, как это сделать на примере простой программы, которая именно таким спосо­бом воспроизведет файл c:\windows\media\tada.wav (или c:\windows\tada.wav, если вы измените соответствующую директиву        в начале программы).

; wavdir.asm

; Воспроизводит файл c:\windows\media\tada.wav,  не исполвзуя DMA. ; Нормалвно работает толвко под DOS в реалвном режиме

; (то есть не в окне DOS (Windows)

;  подобными программами).

FILESPEC equ "c:\windows\media\tada.

SBPORT equ 220h

tiny

. code

.186

100h

Сложные программирования

не под EMM386 , QEMM или другими

org start:

call jc

mov

call call call

mov

call

dsp_reset

no.blaster

bl,0D1h

dsp_write

open_file hook_int8 bx,5

reprogram_pit

wav" ;  Имя файла tada.wav с полным путем  (замените на

для старых версий Windows).

Базовый порт звуковой платы (замените, .

если у вас он отличается).

Для pusha/popa. COM-ripo грамма.

Сброс и инициализация

Команда DSP Включить звук.

Открыть и прочитать tada.wav. Перехватить прерывание таймера.

Делитель таймера для частоты 22 050 Hz

(на  самом деле соответствует 23   867 Hz).

Перепрограммировать таймер.

main_loop:

cmp je

mov call call no_blaster:

ret

buffer_addr

old_int08h finished_flag

filename

; Обработчик INT ; Посылает байты int08h_handler

; Основной цикл. byte ptr finished_flag,0

mainJLoop ; Выполняется, пока finished_flag равен нулю.

Ъх.ОРРт ; Делителв таймера для частоты

гергодгапрурИ      ;  Перепрограммироватв таймер. гевбоге_1ггс8       ; Восстановитв ШСЮ.

18,2 Hz.

d.w offset buffer Адрес текущего играемого байта.

dd ? Старый обработчик INT 08h (IRQO).

db 0 Флаг завершения.

db FILESPEC, 0 Имя файла tada.wav с полным путем.

(IRQO). из буфера в proc far

звуковую

pusha

:

Сохранить регистры.

cmp

byte ptr cs:finished flag, 1

; Если флаг уже 1,

je

exit_handler

; ничего не делать.

mov

di.word ptr cs:buffer_addr

;   Иначе:   DI = адрес текущего байта.

mov

bl,10h ;

Команда DSP 10h.

call

■ dsp_write ;

Непосредственный 8-битный вывод.

mov

bl.byte ptr cs:[di] ;

BL = байт данных для вывода.

call

dsp_write

 

inc

di ;

DI = адрес следующего байта.

cmp

di,offset buffer+27459 ;

_27 459  - длина звука в tada.wav.

mm

jb

mov

not_finished:

mov

exit_handler:

• mov

out popa

iret

int08h_handler not_finished

byte ptr cs:finished_flag,l

word ptr cs:buffer_addr,di

; Если весь буфер пройден,

; установить флаг в 1.

; Иначе:

; сохранить текущий адрес.

al,2Oh 2Oh,al

endp

; Завершить обработчик аппаратного прерывания, ;  послав неспецифичный ЕСЯ (см.  раздел 5.10.10). ; регистры.

і Процедура dsp_reset.

і Сброс и инициализация DSP.

dsp_reset

proc near

 

mov

dx,SBPORT+6

і Порт      - регистр сброса DSP.

mov

al, 1

і Запись единицы в        начинает инициализацию.

out

dx, al

 

mov

cx, 40

і Небольшая пауза.

dsploop:

 

 

in

al, dx

 

loop

dsploop

 

mov

al,0

і Запись нуля завершает инициализацию.

out

dx.al

і Теперь DSP готов к работе.

і Проверить, есть ли DSP вообще.

 

add

dx,8

і Порт      - состояние буфера чтения DSP.

mov

cx,100

 

check port:

 

 

in

al, dx

Прочитать состояние буфера.

and

al,80h

Проверить бит 7.

jz

port_not_ready

Если ноль - порт еще не

sub

dx,4

Иначе: порт 22Ah - чтение данных из DSP.

in

al, dx

 

add

dx,4

И снова порт

cmp

al.OAAh

Если прочиталось число AAh - DSP присутствует

 

 

и действительно готов к работе.

je

good_reset

 

port_not_ready:

 

 

loop

check_port

і  Если нет - повторить проверку 100 раз

bad_reset:

 

 

stc

 

і и сдаться.

ret

 

;  Выход с CF = 1 .

good_reset:

 

 

clc

 

і Если инициализация прошла успешно,

ret

 

і  выход с CF = 0.

dsp_reset

endp

 

і Процедура dsp_write.

 

Посылает байт

из BL в DSP.

 

dsp_write

proc near

 

mov

dx,SBP0RT+0Ch

Порт 22Ch - ввод данных/команд DSP.

write_loop:

Сложные приемы программирования

Подождать готовности буфера записи DSP.

in

al, dx

Прочитать порт 22Сп

and

al,80h

и проверить бит 7.

jnz

write_loop

. Если он не ноль -

mov

al.bl

Иначе:

out

dx, al

послать данные.

ret e

endp

 

подождать еще.

Процедура гергодгат_рів.

Перепрограммирует канал 0 системного таймера

Вход: 8Х = делитель частоты.

на новую частоту.

reprogram_pit cli

mov

out mov out

mov

out sti ret

reprogram_pit ;

proc

near

al,00110110b

43h,al

al.bl 40h,al al.bh 40h,al

Запретить прерывания.

Канал 0,  запись младшего и старшего байтов, режим работы 3, формат счетчика - двоичный. Послать это в регистр команд первого таймера. Младший байт делителя -в регистр данных канала 0. И старший байт -туда же.

Теперв ЩО вызывается с частотой 1 193 180/ВХ Ш.

endp

Процедура hook_int8. ; Перехватывает прерывание hook_int8

INT 08h

 

proc near

 

mov

ax,3508h

АН = 35п, АЬ = номер прерывания.

int

21h

Получить адрес старого обработчика.

mov

word ptr bx

Сохранить его в оШпШгі.

mov

word ptr old_int08h+2,es

 

mov

ax,2508h

АН = 25И, АЬ = номер'прерывания.

mov

dx,offset int08h_handler

П8:ОХ - адрес обработчика.

int

21h

Установить обработчик.

ret

 

 

hook_int8

endp

; Процедура restore_int8.

;  Восстанавливает прерывание INT 08h  (IRQ0).

restore_int8

mov Ids

int

ret

restore int8 proc near ax,2508h

ptr

21h

old_int08h

АН = 25п, АЬ = номер прерывания. ПОЗОЫХ - адрес обработчика. Установить старый обработчик.

endp

;   Процедура open_file.

;  Открывает файл filename и

; tada.wav, в буфер buffer. open_file proc near

mov ax,3D00h

копирует звуковые данные из считая его файлом

; AH

3Dh, AL

00.

-

-

Программирование на уровне портов

itiov

dx,offset filename

ББ^Х - АЗСіг-имя файла с путем.

int

21 h

Открыты файл для чтения.

jc

■error.exit

Если не удалосы открыты файл - выйти.

mov

bx, ax

Идентификатор файла в ВХ.

mov

ax,4200h

АН = 42п, АЬ = 0.

mov

cx, 0

СХЭХ - новое значение указателя.

mov

dx,38h               ;  По этому адресу начинаются данные в tada.wav.

int

' 21h

Переместить файловый указатель.

mov

ah, 3FH

АН = 3Fh.

mov

сх, 27459           ;  Это - длина звуковых данных в файле tada.wav.

mov

buffer

05: ОХ - адрес буфера.

int

21h

Чтение файла.

ret

 

 

error_exit:

 

Если не удалосы открыты файл.

mov

ah,9

АН = 09п.

mov

dx, offset notopenmsg ■

Э8:ВХ = сообщение об ошибке.

int

21h

Открыты файл для чтения.

int

20h

Конец программы.

notopenmsg

db      "Ошибка при открытии '$'

open_file

endp

 

buffer:

 

Здесь начинается буфер длиной 27 459 ба

end

start

 

Если вы скомпилировали программу latency.asm из раздела 5.10.5 и попробова­ли запустить ее в разных условиях, то могли заметить, что под Windows 95, а также под EMM386 и в некоторых других ситуациях пауза между реальным срабатыва­нием прерывания таймера и запуском обработчика может оказаться весьма зна­чительной и варьироваться с течением времени, так что качество звука, выводимого нашей программой wavdir.asm, окажется под EMM386 очень плохим, а в DOS-задаче под Windows 95 вообще получится протяжный хрип. Чтобы этого избежать, а так­же чтобы указывать точную скорость оцифровки звука и выводить 16-битный звук, нужно обратиться к программированию контроллера DMA (пример про­граммы, выводящей звук при помощи ,DMA, см. в конце следующего раздела).