Немного о скважности, сидсаунде и всём таком
kowalski
Привет zxdemos.ru и лично Бог ААА!
После прошедшего неудочного в голосовании Multimatograf 2018 меня попросили рассказать о том, как именно мы (n1k-o , wbcbz7 и я) поиздевались над нашим любимым аигреком. Окей, начнём с самого начала — с того, как работает генератор тона.
Square Wave
Генератор тона AY/YM умеет вести обратный отсчёт, тикая 12-битным счётчиком, и выдавать на своём выходе ноль или единицу. Счётчик устроен так, что он переполняется по достижению половины периода, заданного нами в паре регистров периода тона. В этот момент состояние выхода генератора меняется на противоположное и отсчёт начинается сначала. Отметим сразу, что период генератора и частота получаемого тона связаны вот таким соотношением:
частота тона = частота чипа / (16 * период)
В итоге получается вот что:
Рис. 1: Меандр
Это та самая привычная уху правоверного спектрумиста square wave, или, по-русски говоря, меандр.
У меандра ширина импульса (та часть периода, на которой выход генератора в единице) равна половине периода. Именно так работает наш счётчик, и это обуславливает характерный тембр получаемого звука.
Отношение периода к длительности (ширине) импульса называют скважностью, и в нашем случае, как видно, она равна двум. Обычно более удобно использовать обратную скважности (и часто выражаемую в процентах) величину, называемую коэффициентом заполнения (duty cycle, DC). То есть, у нас DC = 1/2, или 50%.
На чипах AY/YM, в отличие от некоторых других, конструктивно нет возможности изменять скважность, получая иные тембры — логика счётчика такова, что на выходе мы имеем меандр и только меандр.
Но…
SID Sound
Кому первому на Atari ST в голову пришла эта мысль, мне достоверно установить не удалось. По всей вероятности, это был B.A.T. Ибо начало широкого распространения этой техники связывают с выпуском группой Synergy 27 сентября 1992 года шестого номера своего дискмага «DBA». В интро к нему, которое кодили как раз B.A.T и Rapido, звучала музыка легенды ST-сцены — Scavenger.
И ох, тысяча чертей, как же она звучала!
https://youtu.be/g_9rDlos0g4
Слышите этот берущий за душу lead с плывущим тембром, совершенно непохожим на меандровый выхлоп генератора YM?
Вот примерно так все тогда и офигели.
А вся фишка вот в чём. Представим, что у нас есть ещё один такой же генератор, работающий с той же частотой, что и наш генератор тона на чипе, но чуть сдвинутый по фазе:
Рис. 2: Опять меандр
Для ясности совместим обе волны, производимые генераторами, на одном рисунке:
Рис. 3: Меандр на меандре
А теперь, собственно, фокус. Если мы каким-то образом объединим выходы обоих генераторов по AND (то есть, единица на выходе будет только в том случае, когда она на выходах обеих генераторов сразу), то получится…
Рис. 4: Больше не меандр
Ага! Это уже не похоже на меандр, не так ли? Да, на рисунке DC = 25%.
Дело за малым — осталось понять, как это сделать и где взять воображаемый генератор.
На Atari ST всё просто. Там есть два пользовательских таймера, умеющих генерировать прерывание. Таймер устанавливается так, чтобы получить частоту, равную частоте тона. При приходе прерывания от него мы просто либо инвертируем бит в микшере, отвечающий за подмешивание тона в канал, либо XOR-им амплитуду канала с её первоначальным значением (получая, соответственно, то 0, то изначальную амплитуду). В итоге получается именно то, что мы хотели, но с маленьким нюансом. Таймер Atari нельзя установить абсолютно точно на требуемую частоту из-за набора предопределённых делителей. Поэтому возникает некоторая погрешность. Но нет худа без добра: именно эта погрешность из-за разницы в частотах создаёт эффект «плавания» скважности — тот самый характерный SID Sound.
На нашей же любимой платформе всё несколько более грустно. Так как сэр Синклер был одержим идеей сделать ZX Spectrum максимально дешёвым, таймеров у нас нет, как и многого другого, впрочем. Ну, не то, чтобы совсем нет… есть один. Большой и толстый таймер под названием Z80
Один из возможных способов повторения эффекта, который мы использовали — это точно выждать нужный интервал в тактах Z80 и произвести ту же манипуляцию с регистрами, что и на Atari ST. Не утомляя вас очевидными вычислениями, скажу сразу: поскольку частота PSG на наших родимых Пентагонах равна половине частоты Z80, требуемая задержка в тактах будет равна периоду тона, умноженному на 16. Вот так всё просто. И снова маленький нюанс: так как частоты Z80 и PSG кратны, то мы, в отличие от таймера Atari, получаем ровно нужную частоту. Что с этим делать, я думаю, понятно
Да: дополнительные тембры можно получить, сдвигая частоту программного генератора на N октав вверх/вниз, к примеру, побитовым сдвигом результата в тактах влево/вправо.
Custom duty cycle
А что, если мы хотим точную, а не «плавающую» скважность?
Тут всё довольно просто: мы выключаем генератор тона совсем и вместо этого генерируем тон самостоятельно, меняя значение регистра амплитуды — так же, как мы это делаем для воспроизведения цифровых сэмплов.
Думаю, понятно, как получить произвольную скважность: два интервала в тактах, во время первого генерим единицу, во время второго — ноль. Опять же, всё совершенно легко считается из периода тона.
Syncbuzzer
Более поздним и очень красивым по звучанию эффектом является Syncbuzzer.
Авторство этого эффекта (и ряда других) на Atari принадлежит ещё одной ST-легенде — Tao / Cream.
https://youtu.be/SYRKS6gcXes
В принципе, Карбо всё уже доходчиво изложил, так что повторяться не буду. Скажу лишь, что реализуется он практически так же, как и предыдущие. Генератор огибающей в нужный момент сбрасывается записью в регистр формы огибающей. Рассчитав момент сброса, можно получить очень интересные формы волны. Мы реализовали Syncbuzzer в своём плеере, но никак не использовали, ибо нервов на то, чтобы добавить ещё одну колонку в интерфейс Vortex Tracker, не хватило ни у меня, ни у wbcbz7 — а жаль. Ибо, повторюсь, звучит он шикарно.
Всё вместе
Возиться со сжатием дампа регистров я затеялся довольно давно, со времени своей первой 1К-интры, но особых успехов не достиг.
Все Америки уже были давным-давно открыты, так вышло и с идеей паковать LZ каждый регистр дампа по отдельности, которую я реализовал после того, как наткнулся на формат FYM для PC. Вроде бы вышло хорошо: размер упакованного дампа часто был близок к размеру исходного pt3-файла, а иногда и был даже меньше него. По скорости плеер, конечно, сильно уступал люто шустрому лидеру от psndcj и introspec , но по сжатию превосходил. Когда я рассказал о своих «успехах» introspec 'у, тот сообщил, что подобный пакер давным-давно написал psb , хоть и не релизил его (тем не менее, он как-то засветился в каких-то продах Гоблина). Ну, стоило ожидать. В итоге я забросил плеер в дальний угол диска и оставил там валяться до лучших времён.
Лучшие времена настали, когда я решил разобраться, как же на Atari ST получается такой непохожий на YM звук. Не помню уже, почему: видимо, опять слушал !cube и завидовал

В интернетах была откопана и разобрана куча YM5/6 дампов, тут-то и пригодилось то, что плеер умеет пошагово распаковывать и проигрывать за фиксированное число тактов. В итоге где-то прошлой осенью все дампы были успешно переконверчены на ZX, и SID Sound заиграл, как у себя дома. Надо сказать, что такое давно проворачивал Poke / Patisoners, аж эндцать лет назад — и даже грозился открыть исходники, но воз и ныне там. Ничего, мы и сами справились. Хотя, конечно же, интересно, как это было сделано у него.
Кидание наконверченным в друзей привело к появлению патча на Vortex Tracker от Артёма, позволявшего задавать 16 уровней скважности тона. И, конечно же, Олежа немедленно воспылал, запилив кавер на «Drunken Sailor» для тизера игры «Остров Сокровищ»:
https://youtu.be/6JM8WDRU8D8
Дальше было добавление в Вортекс SID Sound, дигисэмплов и кое-чего ещё. В воздухе к тому времени определённо что-то витало: все вдруг начали интересоваться звуком с Атари. Мы решили, что будет прикольно зарелизить на МФ что-нибудь эдакое, так что я запланировал отпуск на конец апреля, чтобы мы за пару недель успели подготовиться, попробовать сделать демо и съездить на пати.
Момент, в который у нас начал образовываться кавер на «Татарина», я как-то пропустил — всё получилось само собой ) Олежа, как всегда, был великолепен (название с подколом тоже на его совести, а атари-адидасное лого — на совести Артёма). И, как всегда, жизнь всё расставила по своим местам: вместо отпуска за две недели я написал «по собственному» за неделю до МФ и был занят передачей дел сменщику. В итоге из нашей затеи получилось скорее интро, чем демо, практически без визуальных эффектов и с кучей косяков по коду. Всё собиралось буквально в последнюю ночь, отсюда путаница со снапшотами и отсутствие нормального TRD. Ещё раз приношу всем извинения — в первую очередь Олеже, Артёму и Нюку с Нодеусом.
Так или иначе, хорошо ли, плохо ли, но мы это сделали.