В чипе используются и логический, и арифметический сдвиги, поэтому я буду использовать их частные обозначения: lsr и asr. В ЯВУ обычно имеется только одна команда сдвига, например, shr в Паскале. На практике компилятор Delphi для 16-битных переменных генерирует арифметический сдвиг, а для 32-хбитных логический.





Как мы помним, один из главных компонентов оператора это генератор синусоиды, на вход которого подаются фаза и громкость. Ключевой момент устройства этого генератора в том, что амплитуда выходного сигнала находится в экспоненциальной зависимости от входной громкости. Если вы помните, такой же принцип встречался в работе SN76489. Запишем формулу генератора:
output = sin(phase) * exp(gain)
Умножение - достаточно сложная операция, но её можно обойти. Занесём синус под экспоненту, получим:
output = exp( log(sin(phase)) + gain)
Использование логарифмов позволяет заменить умножение сложением. Естественно, внутри чипа ни одна из сложных функций, содеращихся в формуле, не вычисляется. В этом случае применяются специально заготовленные таблицы. Мы можем обойтись двумя таблицами:
exp_tab - содержит значения показательной функции, например, 2^x, для определённого диапазона x. Диапазон подбирается так, что максимальное значение в таблице будет максимально возможным выходом генератора, а минимальное - близким к нулю числом. Т.к. мы работаем с цифровым чипом и точность ограничена, таким числом будет 0.
logsin_tab - содержит логарифмы значений синуса для разных фаз. Нам надо охватить фазы от 0 до 2*pi. На практике в таблице можно записать только первую четверть синусоиды, а остальные четверти восстановить простыми приёмами.
Тогда, имея эти таблицы, мы можем переписать формулу:
output = exp_tab[ logsin_tab[ phase ] + gain ]

Как мы убедимся в дальнейшем, именно такой подход с двумя таблицами используется в чипе.  Перед тем как перейти дальше, советую прочитать эту статью
http://docs.google.com/Doc?id=dd8kqn9f_13cqjkf4gp
Авторы декапсулировали чип YM3812 (можно сказать, родственник YM2612) и сумели по битам прочитать содержимое ПЗУ чипа - некоторых внутренних таблиц в оригинальном виде. В их числе оказались и таблицы exp_tab и logsin_tab. Видно, что в каждой таблице 256 значений (индекс 8-битовый). Там же приводятся формулы, по которым эти таблицы были рассчитаны создателями чипа.
Что плохо, авторы не совсем доходчиво объясняют, как этими таблицами пользоваться. Начнём с того, что в exp_tab имеется скрытый 10-й единичный бит, т.е. все значения надо увеличить на 1024. Во-вторых, YM, как и SN76489, для управления амплитудой использует не громкость, а аттенюацию, поэтому значения должны идти в убывающем порядке: нулевой аттенюации соответствует максимальый выход. Тогда exp_tab будет выглядеть так:
  x y
  0 2042
  1 2037
  2 2031
...
254 1027
255 1024
Если мы построим график, то увидим, что это убывающая показательная функция, причём она убывает со скоростью 2 раза на 256 отсчётов. Очевидно, что 256-й точке будет соответствовать значение 2042 / 2 = 1021, или по-другому: 2042 shr 1 = 1021. Ещё пример: значение 513-й точки равно значению 1-й, сдвинутое на 2 бита вправо (т.к. 513 = 1 + 2*256).
Таким образом, для вычисления выхода по заданной аттенюации можно использовать одну из формул:
out = exp_tab[ att mod 256 ] shr ( att div 256 )
out = exp_tab[ att and 255 ] shr ( att shr 8 )
out = exp_tab[ lo(att) ] shr hi(att)
Здесь функции lo и hi возвращают соответственно младший и старший байт переменной att.
На практике я столкнулся со случаем, когда hi(att) было больше 16 и функция shr давала неправильный результат, так что имейте в виду.

В ходе экспериментов выяснилось, что на самом деле точность операторов на 2 бита выше, поэтому в таблице надо приписать справа 2 бита (увеличить всё в 4 раза):
  x y
  0 8168
  1 8148
  2 8124
...
254 4108
255 4096
Раньше, если бы мы вычислили, например, exp_tab[ 257 ], то получили бы не 1018.5, а 1018, потеряв один бит. Теперь же exp_tab[ 257 ] = 4074.



Мы выяснили, что выход оператора колеблется в пределах от 0 до 8168, и разобрались, как его вычислить по известному значению аттенюации.

Мы рассмотрели таблицу exp_tab. Она часто используется, но только самим генератором синусоиды. Все остальные вычислительные блоки используют её косвенно, подавая на вход генератора свой вклад в аттенюацию. Для удобства изложения условимся на будущее называть один шаг аттенюации 16-ричным центом, или просто центом. Число 0.01h есть 1/256, а таблица состоит из 256 значений. Кроме того, приращение в 256 (100h) центов даёт уменьшение амплитуды в 2 раза.

Перейдём к logsin_tab. Если посмотреть на формулу в статье, видно, что для вычисления используется фаза, сдвинутая на полцента. Это сделано для того, чтобы избежать бесконечности при вычислении log(sin(0)), а также для усреднения диксретных отсчётов фаз. Рассмотрим таблицу:
x y
  0 2137
  1 1731
  2 1543
...
254 0
255 0
Здесь выписаны значения аттенюаций для фаз синусоиды. Мы уже умеем работать с таблицей exp_tab, поэтому можем понять, что означают эти числа. Например, аттенюация 2137 превращается в число 25, а 0 - в 8168. Можете для интереса построить график exp_tab[ logsin_tab[ i ] ].  Таблица содержит только первую четверть синусоиды, последние значения с нулевой аттенюацией соответствуют верху синусоиды. Таким образом, полный период шаблона синусоиды (2*pi) содержит 1024 значения.
Вторая четверть получается переворачиванием таблицы и приведением индекса в диапазон 0..255. Т.к. индексы второй четверти лежат в диапазоне 256..511, мы получим:
gain_sin = logsin_tab[ 511 - phase ]
С отрицательным полупериодом синуса немного сложнее. Мы не можем дать отрицательное значение аттенюации, т.к. это неправильно и её значение будет использоваться для расчёта выхода по таблице exp_tab. Нам нужно, чтобы сам выход стал отрицательным. Поэтому при расчёте нижнего полупериода мы копируем верхний и меняем знак выхода:
output = - exp_tab[ gain + logsin_tab[ phase - 512 ] ]
В этом примере мы упростили вычисление для последней четверти (768..1023) как если бы таблица logsin_tab содержала 512 значений.

Схематически вычисление синусоиды можно изобразить так: фаза содержит 10 бит. Младшие 8 бит - это индекс в таблице. 8-й бит показывает четверть (1-2 или 3-4), 9-й - полупериод. 8-й бит "переворачивает" таблицу, 9-й бит меняет знак выхода. Т.к. 8-битный индекс умещается ровно в 1 байт, переворот таблицы легко осуществить инверсией индекса.
index = phase and 255
if bit(phase, 8) then index = not index
output = exp_tab[ gain + logsin_tab[ index ] ]
if bit(phase, 9) then output = -output
Обратим внимание, что используется отрицание выхода (дополнительный код), а не инверсия (обратный код). Это значит, что минимальный отрицательный выход оператора равен -8168, а не -8167.

Мы разобрались, как работает оператор, и выяснили, что диапазон его значений составляет -8168..+8168, т.е. точность оператора как минимум 14 бит.





Оператор имеет 20-битный счётчик фазы. Старшие 10 бит счётчика и составляют фазу для расчёта оператора. С течением времени, если для оператора задана ненулевая частота, счётчик фазы изменяется. Точность приращений составляет 1, но при расчёте фазы младшие 10 бит счётчика не учитываются - только при изменении самого счётчика.

Что происходит, когда один оператор модулирует другой? Как соотносятся выход модулятора и фаза модулируемого? Соотношение простое:
phase_in = M_output asr 1
Проще говоря, чтобы рассчитать входную фазу, надо разделить выход модулятора на 2. Обратим внимание, что здесь используется именно арифметический сдвиг, который в отличие от логического, сохраняет знак результата и всегда округляет в сторону меньшего числа. Поэтому для отрицательных чисел арифметический сдвиг ведёт себя немного по-другому, например:
1 asr 5 = 0
-1 asr 5 = -1
Если модуляторов несколько (алгоритмы 1-3), сначала их выход складывается, а результат пересчитывается в фазу. Суммарный выход двух модуляторов лежит в пределах от -16336 до +16336, т.е. промежуточный регистр должен быть как минимум 15-битным.
Как мы помним, эквивалентом полного периода (2*pi) является разность фаз в 1024 шага. Один модулятор может вносить в фазу модулируемого вклад вплоть +-4084 (около 8*pi), а 2 модулятора - в 2 раза больше.


Обратная связь.
Оператор1 каждого канала имеет цепь обратной связи. Выход оператора1 умножается на коэффициент обратной связи b и подаётся на его же вход. Мы имеем дело с дискретным устройством, поэтому от подачи выхода на вход и расчёта уже по новым входным данным проходит время, равное целому числу тактов. На практике для реализации обратной связи используется 2 промежуточных регистра-хранилища, fb1 и fb2. Запишем упрощённый алгоритм работы оператора1:
output1 = op1( phase + phase_fb, att )
fb2 = fb1
fb1 = output1
phase_fb = b * (fb1 + fb2)
Можно представить себе это как продвижение выхода оператора1 по цепочке регистров fb. fb1 хранит новое значение output, а fb2 - старое, полученное на предыдущем такте. Можно доказать, что регистров именно 2. Почему создатели чипа не обошлись одним регистром, неизвестно.
Осталось выяснить, что представляет собой коэффициент b. В японской документации приводятся следующие данные: степень ОС можно задавать от 0 до 7, соответствие уровней модуляции значениям ОС такое:
0 - OFF (ОС отключена)
1 - pi/16
2 - pi/8
...
7 - 4*pi
Мы знаем, что выход оператора может достигать 16*pi, а степень модуляции им - 8*pi. Можно предположить, что значение в таблице 4*pi говорит нам о том, что надо разделить выход на 4. На практике оказалось, что степень самомодуляции оператора1 тоже равна 8*pi, это эквивалентно делению его выхода на 2 (вспомните соответствие выхода модулятора входной фазе). Но т.к. мы сдвигаем сумму двух промежуточных регистров, каждый из которых содержит значение выхода, делить надо уже на 4. Другими словами, в таблице приводится "коэффициент" для каждого из промежуточных регистров. Перепишем таблицу:
0 - OFF
1 - 1/256
2 - 1/128
...
7 - 1/4
И последняя строчка алгоритма примет вид:
phase_fb = (fb1 + fb2) asr (9 - fb_level)

Как мы видим, в регистры fb1 и fb2 всегда заносится выход оператора1 без изменений, смена уровня фидбека никак не влияет на эти регистры. Предположительно, при отключении фидбека занесение значений в регистры fb1 и fb2 также не прекращается, изменения происходят уже дальше, а именно в регистр входной фазы фидбека насильно записывается значение 0.



TL.
TL можно задавать в пределах от 0 до $7F. Каждый шаг TL равен 32 центам exp_tab, т.е. увеличение TL на 8 даёт уменьшение амплитуды в 2 раза. Таким образом, с помощью TL можно задавать аттенюацию от 0 до 4064 цента с точностью в 32.
TL никак не связан с генератором огибающей, его аттенюация дополняет аттенюацию от ГО, он просто изменяет "масштаб" огибающей.




Частота, Block, FNum и т.д.
Теперь рассмотрим оператор в динамике. Как происходит генерация синусоиды? Оператор имеет 20-битный счётчик фазы, 10 старших бит составляют собственную фазу оператора. Это значение подаётся на вход ГСВ.
Частоту оператора можно регулировать с помощью следующих параметров:
- Блок (Октава), 3 бита
- Нота (F-Number), 11 бит
- Множитель, 4 бита

Блок и Нота - это переменные канала, а не оператора, поэтому они одинаковые для всех операторов одного канала. Множитель у каждого оператора свой.

Блок задаёт "октаву", а F-Number - ноту внутри неё. На самом деле, F-Number имеет больший диапазон, чем ноты одной октавы, но это неважно. В реальности шаг в одну октаву равен изменению частоты в 2 раза. Блок влияет на конечную частоту таким же образом.

В документации приводится формула для вычисления F-Number, необходимого для генерации нужной частоты fnote:
F-Number = (144 * fnote * 2^20 / MC) / 2^(B-1)
Здесь MC - это частота работы чипа (7.67 МГц). Главный вычислительный цикл длится 144 такта, частота семплирования одного канала CC (Channel Clock) равна 53 кГц.
F-Number = (fnote * 2^20 / CC) / 2^(B-1)
Нас интересует обратная формула: какую частоту мы получим по заданным Block и F-Number?
fnote = F-Number * (CC / 2^20) * 2^(B-1)
Вспомним, что счётчик фазы имеет 20 бит точности. Минимальное приращение счётчика - единица, поэтому прежде чем возникнет его переполнение (начало нового периода), сумма приращений должна составить 1048576 (2^20). Частота семплирования одного канала, она же частота пересчёта счётчика, равна 53 кГц. Если мы с каждым тактом будем увеличивать счётчик на 1, то переполнение наступит через 1048576 тактов, поэтому мимнимальная частота, которую может выдать оператор, равна:
53 кГц / 1048576 = 0.05 Гц
Меньшей частоты достичь нельз Из-за ограниченной точности. Нулевые приращения не пирведут к изменению фазы, и оператор будет выдавать постоянный сигнал ("нулевая частота").

Если не принимать во внимание вклад Блока, то приращением к счётчику как раз и служит F-Number.
Судя по формуле, Блок может давать от -1-й до 6-й октавы (0-я октава означает отсутствие смещения). Блок = 0 уменьшает конечную частоту в 2 раза, Блок = 1 увеличивает в 2 раза и т.д. Запишем формулу вычисления инкремента для обоих случаев:
Increment = F-Number lsr 1, если блок = 0
Increment = F-Number lsl (Block - 1), если блок = 1..7
Или в общем виде:
Increment = F-Number lsl 6 lsr (7 - Block)

Случай Block = 0 приводит к потере точности, поэтому если F-Number = 1 и Block = 0, мы получим нулевую частоту (1 lsr 1 = 0).

F-Number 11 бит, Блок = 7 даёт сдвиг на 6 бит влево, таким образом, выходное значение как минимум 17 бит. F-Number позволяет регулировать частоту от 0 до $7FF, с использованием Блока - до $1FFC0.


Множитель даёт дополнительное умножение частоты от 0.5 до 15. В документации приведена таблица. Множитель = 0 уменьшает частоту в 2 раза, и здесь опять возможна потеря точности.
Increment = Increment * MULT_TAB[ mult ]
Чтобы не разбивать применение множителя к частоте на 2 случая (когда множитель = 0 частота делится), можно записать формулу в общем виде:
Increment = Increment * (2 * MULT_TAB[ mult ]) lsr 1
Выражение (2 * MULT_TAB[ mult ]) эквивалентно умножение всей таблицы на 2, что позволяет нам избавиться от вещественного числа 0.5 - оно превратится в 1.




Detune.
Расстройка позволяет получить небольшое искажение частоты. Параметр Detune 3 бита, в документации приведена таблица соотвествия Detune и степени расстройки FD.
Заметим, что вторая значения из правой половины таблицы являются является именно отрицанием, а не инверсией значений из левой половины, поэтому Detune = 4 даёт FD = 0, а Detune 7 даёт FD = -3.

Какой вклад вносит FD в конечную частоту? Величина вклада зависит от исходной частоты, для определения её вводится понятия Код клавиши (КК, Key-code). Это 5-битовое значение, старшие 3 бита берутся из Блока, а младшие 2 бита вычисляются по формуле:
KC1 = F10
KC0 = F10 * (F9 + F8 + F7) + !(F10*F9*F8*F7)
Здесь Fn - n-й бит F-Number (10 - самый старший бит), а знаками показаны логические операции (умножение = конъюнкция, сложение = дизъюнкция, отрицание = инверсия).
На практике проще пользоваться готовой таблицей:
const
  KEYCODE_TAB : array[ 0..15 ] of u8 = (0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3);
Индексом массива служат старшие 4 бита F-Number.

В документации приведена таблица расстроек частоты по известным FD и полному Key-code (Блок и ещё 2 бита), только для положительных FD. Значения в таблице - расстройка частоты в герцах. Как мы помним, частота в 0.053 Гц - это единичное приращение счётчика.

С Detune связан интересный момент: если частота слишком низкая, то отрицательный FD вызовет обратное переполнение. Раньше мы вычислили, что переменная Increment после применения Блока должна быть минимум 17 бит. Это на самом деле так, и значения частоты, близкие к $1FFFF, полученные после обратного переполнение с использованием FD доказывают нам это.





LFO.
LFO (low frequency oscillator) позволяет модулировать частоту и амплитуду операторов с небольшой частотой модуляции и тем самым получать эффекты "вибрато" и "тремоло". В этом его отличие от операторов, т.к. если вы помните, оператор модулирует ФАЗУ другого.
Другое отличие в том, что оператор - это генератор синусоиды, а LFO - генератор треугольной волны.
Функционально это независимый вычислительный блок. Входные параметры:
- исходная частота оператора и степень частотной модуляции
- степень амплитудной модуляции
- собственная частота LFO
На выходе имеем:
- приращение к частоте, знаковое
- приращение к громкости (аттенюация). Это значение беззнаковое и всегда >= 0, т.е. LFO может только ослаблять выход оператора.

Соответственно входам и выходам в LFO реализованы две преобразующие функции:
- вычисления приращения к частоте по исходной частоте и степени частнотной модуляции
- вычисления приращения к громкости по степени амплитудной модуляции

LFO имеет внутри счётчик фазы треугольника. На практике он представляет собой два счётчика, один показывает, на какой ступеньке треугольника мы находимся, а второй считает такты (как в генераторе квадратной волны). Когда второй счётчик достигает порога, он сбрасывается, а первый счётчик увеличивается.

В документации рассмотрен байт управления LFO.
LFO_FREQ - 3 бита
LFO_On - 1 бит

 бита LFO_On на

В документации приводится таблиц соответствия 

Следующая таблица
  LFO_STEPS:array[0..7] of u8 = (108, 77,  71,  67,  62,  44,  8,  5);







Генератор огибающей создаёт 10-битовое значение, которое служит для регулирования громкости оператора. 1 шаг выхода ГО равен 4 центам, это значит, что ГО может задавать аттенюацию от 0 до 4092 цента с точностью в 4 цента.
Огибающая состоит из 4 фаз:
1) атака (attack)
2) первичное затухание (decay)
3) поддержка (sustain)
4) фаза отпускания (release)
Некоторые считают, что есть ещё 5-я фаза - когда оператор "полностью выключен" и производит нулевой сигнал (точнее, выключена огибающая). Я не разделяю такую точку зрения и считаю, что нет никакой особой фазы, а огибающая на самом деле находится в фазе отпускания, а значение ГО равно 1023, что опять же даёт нулевой выход.

Остановимся подробней на каждой фазе и посмотрим, что происходит при включении/выключении оператора.
Заметим, что нельзя "включить" уже включенный оператор, так же как и выключить уже выключенный. Это значит, что событие Key On для включённого оператора (Key Off - для выключенного) не даст никакого эффекта. Так же и в реальном мире: прежде чем заново нажать клавишу, её надо отпустить, и наоборот.

В фазах 2-4 громкость падает, причём линейно. Для каждой фазы можно задать свою скорость падения громкости. В фазе атаки громкость быстро растёт по сложной формуле, похожей на экспоненциальную: вначале кривая громксти выпуклая вниз, затем наблюдается плавный перегиб.

С самого начала, при старте чипа, все операторы находятся в "выключенном" состоянии, т.е. ГО даёт максимальную атенюацию. При срабатывании события Key On, огибающая переходит в фазу атаки: громкость растёт, пока не дойдёт до максимума, другими словами, нулевой аттенюации.
Когда огибающая достигнет максимального уровня, наступает фаза первичного затухания: громкость постепенно падает до уровня поддержки SL. При достижении этого уровня наступает фаза поддержки: громкость опять же падает, но с другой скоростью и на этот раз до нуля. Предположительно, если SL совпадает с максимумом, фаза атаки перетекает в Sustain, минуя Decay.
При выключении оператора (Key Off), независимо от текущего состояния, огибающая сразу переходит в фазу отпускания.

KS - 2 бита
AR - 5 бит
SR - 5 бит
DR - 5 бит
RR - 4 бита

Частота RR приводится к 5-битовому значению по формуле:
RRn = 2*RR + 1

KS - это масштаб скорости. По нему вычисляется дополнительная скорость Rks, которая вносит свой вклад в конечную скорость изменения огибающей. В документации приводится таблица вычисления Rks. На Rks влияют Блок и 2 старших бита Ноты (биты 9-10). Можно записать эту таблицу в виде простого алгоритма:
block_note = 4*Block + bitfield(Note, 9, 2)
Rks = block_note lsr (3 - KS)

Окончательное значение скорости вычисляется как
Rate = 2*R + Rks
При этом:
- если R = 0, то Rate = 0
- максимальное значение Rate 63