§ Вступление

Я давно уже пытался разобраться в том, как работает синтезатор AY-3-8910 от спектрума. Наконец-то мне это удалось сделать, и потому об этом хочу написать статью. Сам по себе звук этого синтезатора работает очень просто и состоит из трех компонентов, которые идут в таком порядке:
  • Базовая громкость (level)
  • Огибающая (envelope) - это некая форма сигнала (громкости)
  • Тон (tone) - это обычный меандр, то есть сигнал, который имеет состояние либо 0, либо 1 разной громкости и разной частоты
  • Шум (noise) - ну это шум, разной частоты, его формирование на самом деле опирается на уровень тона или огибающей
Устройство работает на основе регистров, которых у него 16 штук. Каждый регистр отвечает за свою определенную функцию. Всего существуют 3 канала - A, B, C. Тоны могут играть в разных каналах по-разному, но огибающая у них может быть только одна.

§ Регистры аудиопроцессора

Ниже перечислю регистры, которые используются:
R0  | Младшие 8 бит частоты тона  А[7:0]
R1  | Старшие 4 бита частоты тона A[11:8]
----+-----------------------------------------------------
R2  | Младшие 8 бит частоты тона  B[7:0]
R3  | Старшие 4 бита частоты тона B[11:8]
----+-----------------------------------------------------
R4  | Младшие 8 бит частоты тона  C[7:0]
R5  | Старшие 4 бита частоты тона C[11:8]
----+-----------------------------------------------------
R6  | Период шума (5 бит) от 0 до 31
----+-----------------------------------------------------
R7  | Управление активации канала
    | Бит 0 - если 0, то активирован тон A
    | Бит 1 - если 0, то активирован тон B
    | Бит 2 - если 0, то активирован тон C
    | Бит 3 - если 0, то активирован шум A
    | Бит 4 - если 0, то активирован шум B
    | Бит 5 - если 0, то активирован шум C
    | Бит 6 - если 0, то регистр R14 работает на вход, 1-на выход
    | Бит 7 - если 0, то регистр R15 работает на вход, 1-на выход
----+-----------------------------------------------------
R8  | Громкость канала A в битах 0..3.
    | Если бит 4 равен 1, то громкость берется из огибающей
R9  | Громкость канала B (аналогично)
R10 | Громкость канала C (аналогично)
----+-----------------------------------------------------
R11 | Младший байт периода огибающей
R12 | Старший байт периода огибающей
R13 | Тип огибающей (4 младших бита)
----+-----------------------------------------------------
R14 | Регистр IOA
R15 | Регистр IOB
Регистр IOA и IOB отведены как регистры общего назначения и там можно что-то хранить, если они настроены на вывод (биты 6 и 7 регистра R7).

§ Тактирование

Каждый внутренний цикл обработки нового тона или шума или огибающей вырабатывается каждые 32 цикла процессора. То есть, другими словами, каждый 32-й t-state процессора (цикл) вырабатывает цикл работы синтезатора, который выполняет некоторую полезную работу. Например увеличивает счетчики.

§ Запись в регистры

Запись в регистры осуществляется так: сначала выбирается номер регистра, для этого надо записать в порт 0xFFFD номер регистра AY, а потом в порт 0xBFFD записать данные:
1ld  bc, $fffd
2ld  a,  $00
3out (c), a  ; Запись номера регистра
4ld  b,  $bf
5ld  a,  $ff
6out (c), a  ; Запись значения
Стоит заметить, что при записи в регистр периода шума - шум сбрасывается, а также при записи в регистр R13 - огибающая тоже сбрасывает свои значения, то есть, она начинается заново.

§ Виды огибающих

Всего существует не так много видов для огибающих (envelope):
Вид огибающейЗначение 4-х битов регистра R13Пример звука
00xx
1001
01xx
1111
1000
1010
1011
1100
1101
1110
У огибающей есть период, он равен одному "всплеску". Всего огибающая проходит от 0 до 15 уровней громкости с разной скоростью, которая задается в регистрах R12:R11. Если там задан 1, то после каждого 32-го такта CPU будет добавляться или убавляться +1 к огибающей и она пройдет свой 16-уровневый цикл за 32x16 тактов процессора. Если период огибающей задан как 2, то пройдет свой период она за 32x16x2 циклов процессора и так далее. Максимальная длительность периода огибающей равна 32x16x65535 циклов процессора, что равно 33 554 432 тактов, а это приблизительно 9 секунд.
Что делает огибающая? Она просто задает громкость тону. Когда установлен 4-й бит в регистрах громкости R8-R10, то для тона используется громкость огибающей. Есть огибающие, которые заканчивают свое изменение (пример 00xx). Чтобы перезапустить ее, надо записать в регистр R13 новое значение.

§ Тоны

Тоны - это основные "инструменты" для проигрывания музыки. Они представляют из себя прямоугольный сигнал, частота которого задается точно так же, как и огибащей, то есть каждые N x 32 тактов процессора меняется тон на противоположный. К примеру если период тона равен 100, то через каждые 3200 такта процессора он будет переброшен из 0 и 1, из 1 в 0. Громкость тона задается либо огибающей (если выбран бит 4), либо собственным значением в регистрах r8..r10. Тон активируется через регистр R7.

§ Шумы

Шум активируется когда активирован соответствующий бит в регистре R7 (должен быть притянут к 0 для активации). Шум работает точно так же, как и все остальное. Есть период шума, который активирует его через каждые 32 x N тактов процессора, где N-это значение периода шума (от 0 до 15). Чем большее значение периода шума, тем он более низкий по частоте.
Шум делает следующее - он через каждый случайный промежуток времени (естественно, с некоторой частотой), из тона удаляет громкость. Собственно, всё, там работает шум.
И вообще так работает весь звуковой чип. Тут больше подводных камней вроде как и нет.

§ Варианты использования

Поскольку в AY три канала, можно использовать их для генерации различного вида тона. Например на канал A установить огибающую пилообразного сигнала и получить "бас", на B - обычный тон без изменений, на канал C поставить шум. Естественно, здесь будут некоторые ограничения. Там где огибающая, невозможно настроить громкость, к тому же у нее будет несущий тон, что будет искажать звук. Ну и конечно все каналы находятся на разных сторонах, один слева, другой посереди и третий справа.
Пример на Бейсике, как программировать один тон:
110 LET r=65533: LET d=49149
220 OUT r,2:  OUT d,255
330 OUT r,3:  OUT d,3
440 OUT r,9:  OUT d,16
550 OUT r,7:  OUT d,253
660 OUT r,11: OUT d,0
770 OUT r,12: OUT d,32
880 OUT r,13: OUT d,0
В регистр 2 и 3 (строки 20-30) пишется число 0x3FF (1023), которые будут равны частоте тона для среднего канала B. Рассчитаем эту частоту. Зная, что каждые 32 такта меняется состояние тона, можно сказать, что полный период он проходит за 64 такта (CPU). Поскольку процессор совершает 3500000 тактов в секунду, то 3500000 / (64*1023) ~ 53 герца. Это довольно низкая частота, но уровень слышимости человеческого уха составляет около 20 Гц.
В строке 40 в регистр 9 пишется громкость канала B. Она задана огибающей (число 16 активирует бит 4).
В строке 50 записано число 253, что в двоичном виде равно 11111101. Бит номер 1 активирует тон (так как там число 0), все остальные каналы заглушены.
В строках 60-70 записывается период огибающей, равный 0x2000. Рассчитаем ее длительность. Поскольку вся огибающая проходит за 16 периодов, то 0x2000 x 16 x 32 (машинный циклов CPU на каждую единицу периода) = 4194304 тактов CPU, то занимает по длительности 4194304 / 3500000 ~ 1,19 секунд.
Ну и в 80 строке записываем команду огибающей - 0000b, что соответствует затуханию тона с 15 по 0 громкости и остановкой на 0.

§ Семплированный режим

Существует режим работы, при котором возможно выдавать любые звуки, словно это обычная звуковая карта. Его реализация сложна на практике, но реальна. Этот режим предполагает отключение всех тонов, огибающей и шума, кроме громкости каналов. Изменяя уровень громкости каждые 1/8000, 1/11025, 1/22050 или 1/44100, можно создавать на выходе дискретизированный сигнал так же, как это было бы при обычном WAV-файле

§ Уровни громкости

В AY уровни громкости не являются линейными. В таблице приведено соответствие уровня громкости в регистрах (от 0 до 15) и реальном уровню громкости на выходе (от 0 до 65535).
Уровень V
0x0000  0 0.000
0x0385  1 0.013
0x053D  2 0.020
0x0770  3 0.029
0x0AD7  4 0.042
0x0FD5  5 0.061
0x15B0  6 0.084
0x230C  7 0.136
0x2B4C  8 0.169
0x43C1  9 0.264
0x5A4B  A 0.352
0x732F  B 0.449
0x9204  C 0.570
0xAFF1  D 0.687
0xD921  E 0.848
0xFFFF  F 1.000

§ Дефолтные значения регистров при сбросе

При сбросе все регистры равняются 0, кроме регистра 7, который равен FFh (255)

§ Приложения