Двоичная модуляция - часть 2 utz translated by Lord Vader Табличные звуковые эффекты Табличные эффекты (например, арпеджио или огибающие) делаются довольно просто и поучительно - и вы должны узнать об этом. Рассмотрим,как обычно меняется счётчик нот в звуковом цикле: (пример 8) loop ... ;вывод звука dec bc ;BC - счётчик длины ld a,b or c ;достиг 0? jr nz,loop Несмотря на то,что обычно звуковой цикл 'должен' содержать постоянное число так─ тов, изменение счётчика длины ноты в два приёма обычно сходит с рук: (пример 9) loop ... ;вывод звука dec c ;младший байт длины ноты jr nz,loop (...) ;тут можно ещё какой-то код djnz loop;старший байт длины ноты Таким макаром мы немного ускорили внут─ ренний звуковой цикл, а в качестве бонуса теперь можно делать разные трюки перед уменьшением старшего байта счётчика - ска─ жем,менять коэффициенты заполнения изпри─ мера 7. Или что угодно ещё.Но не наглейте: 50-80 тактов тут - это разумный максимум. Такое прокатывает потому, что период,с ко─ торым выполняется этот добавочный код, составляет примерно 61 Гц для звукового цикла в224 такта - практически в неслыши─ мом инфразвуковом диапазоне.Даже с больши─ ми бас-динамиками модуляцию с такой часто─ той вы вряд ли услышите. Однако если ваш звуковой цикл сильно быстрее пресловутых 224 тактов, таким подходом можно испортить звук. Шум Я уже упоминал, что в Squeeker plus до─ бавил шум.Сейчас шум довольно редко встре─ чается в биперных движках, и музыканты жа─ луются, что из-за этого не могут сделать хорошие ударные. Это непорядок, ведь полу─ чить шум довольно легко. Думаете про слу─ чайные значения из ПЗУ? Даже проще! Вот как получить шум всего за8 тактов: (пример 10) add hl,de;обновляем сумматор канала ;(как обычно) rlc h ;ГПСЧ для бедных за 8 тактов ... Да,RLC H после обновления сумматора канала - вполне достаточно для более-менее пристойного подобия белого шума. Конечно, нужна подходящая константа вDE, но она легко подбирается. Например,для224-такто─ вого движка с таблицей частот, отстроенной на 440 Гц, частоты нот в диапазоне C-4.. C-6 дают подходящие константы для DE. Недостаток данного метода - невозможно по─ лучить заметное изменение высоты шума, но всё же лучше иметь такой шум,чем никакого, правда? Конечно, если постараться, то можно и изменять высоту шума,ценой большего расхо─ да тактов. Основная идея - при помощи пре─ скалера пропускать обновления сумматора: (пример 11) ld b,mask;маска пропуска: ;#AA - пропускать каждое 2-е обновление loop rlc b jp nc,_skip add hl,de rlc h _skip ... Выглядит не очень. Всё ещё ищу способ получше,если у вас есть идеи - поделитесь! Phaser'ы и ШИМомания После создания своего Squeeker Plus, я заинтересовался движком Shiru Phaser. Меня интересовало, можно ли совместить технику этого движка с моим Squeeker'ом. Техника Phaser'а следующая: (пример 12) loop add hl,de;обновляем сумматоры ld a,h ;и сравниваем их с cp #80 ;коэффициентом заполнения sbc a,a ;(как обычно) ld ixl,a ;сохраняем результат add iy,bc;ещё один сумматор ld a,iyh ;всё как обычно cp #80 sbc a,a xor ixl ;ксорим 2 результата out (#fe),a ... jr loop В зависимости от соотношения между де─ лителями в DE и BC возникают различные 'фазовые' эффекты,которые можно услышать в движке Shiru "Phaser1". Позднее оказалось, что заменяяXOR на OR или AND, можно полу─ чить ещё один набор оригинальных тембров. Такая модификация уже применялась в движ─ ках Phaser2 и PhaserЗ. Очевидный недостаток Phaser'а состоит в том, что он ест много тактов и занимает много регистров. К счастью,мой Squeeker не очень требователен к тактам,и даже регист─ ры получилось сохранять в буферы в памяти. Удивительно, но суммарный эффект обоих ме─ тодов превзошёл ожидания! Результатом стал новый движок под названием PhaseSqueek. Он обладает широкими звуковыми возможностями (например,в нём есть табличные эффекты для всех звуковых параметров), но на практике он почти бесполезен, так как единственный метод писать в нём музыку - числами в ис─ ходнике.Может быть,когда-то и появится ре─ дактор, поддерживающий этот движок. Вдохновившись движком PhaseSqueek, я стал выяснять, чего ещё можно добиться от метода Phaser. Работая над HoustonTracker2 (мой трекер для графических калькуляторов TI:http://irrlichtproject.de/houston ), я придумал некоторые трюки для модуляции ко─ эффициента заполнения и теперь решил ском─ бинировать их с методом Phaser'а. Итак, встречайте "Earth Shaker"! (пример 13) ld b,#80 ;коэффициент заполнения loop add hl,de ;понятно что ld a,#4 ;модуляция коэффициента ;заполнения xor b ;под названием "Earth Shaker" ld b,a;новый коэффициент! cp h;применяем этот коэффициент как sbc a,a;обычно out (#fe),a ... jr loop В большинстве случаев такая 'модуляция' даст отвратительный паразитный тон. Но при очень малых значений модулятора (например, 1..3), получаются аккорды!Данную модуляцию я назвал "Earth Shaker", т.к. подобная мо─ дуляция лежит в основе одноимённого бипер─ ного движка. Конечно, в этом движке дела обстоят чуть сложнее (благодаря чему каже─ тся,что появляются2 почти независимых ка─ нала). Конкретнее,применяются модуляторы с эффективной величиной менее единицы. Это довольно затратно по тактам и не подходит для метода "чередования каналов"(см.выше). Играясь далее с такими модуляторами, я обнаружил ещё один трюк,дающий весьма ори─ гинальное звучание. Суть в синхронизации модуляции коэффициентов заполнения c осно─ вной частотой (тоном), который играется в модулируемом канале, типа вот этого: (пример 14) ld b,#10;см. пример 13 loop add hl,de sbc a,a;синхронизируемся с тоном ;канала and #20;так модуляция коэффициента xor b ;будет происходить один раз ;за период тона ... ;далее опять как в примере 13 В результате в звуке появляются слыши─ мые субгармоники (половина частоты тона, четверть и т. д.), а звучание напоминает орган Хаммонда. Чем больше величина моду─ ляции для коэффициента заполнения, тем си─ льнее эффект. В итоге я скомбинировал это с Phaser'ом и получил движок, названный PhaserX, ещё один забавно звучащий движок, не применимый на практике. В этом движке я сделал ещё один трюк,который я уже исполь─ зовал ранее,а именно SIDsound. Суть в том, что в вышеприведённом кодеxor b меняется наadd a,b и используется модулятор 1 или 2. Почти такой же эффект достигается в Phaser'е при установкеBC=DE+/-1. Кстати, можно регулировать коэффициент заполнения и в методе Phaser'а (без срав─ нения с коэффициентами), для этого частоты каналов устанавливаются на одинаковую ве─ личину(BC=DE) , но сумматоры имеют разные начальные значения(HL, IY) . Упрощённая генерация тона После того, как от Shiru я узнал о спо─ собе задавать коэффициент заполнения фазо─ вым способом,я начал размышлять над разли─ чными вещами,вокруг и около синтеза звука. Конец этих размышлений ознаменовался таким кодом: (пример 15) add hl,de ld a,h out (#fe),a Как? Что даёт такой странный код? А то, что задав делитель вDE менее #1000, мы получим некоторый симметричный меандр в бите бипера. Получается, что разрешение такого синтеза составляет всего лишь12 бит (точно такое же разрешение в AY, так что всё в порядке). Если каждая нота в треке непосредственно хранит этот делитель (а именно так и стоит делать, т. к. лукап по таблице занимает время и добавляет не─ который шум), то у нас есть4 дополнитель─ ных (пока) неиспользуемых бита для побоч─ ной информации. А что если приспособить их для хранения коэффициента заполнения? (пример 16) add hl,de ld a,h add a,#8;смещение 0..#10 ;(ср. с IY/HL в примере 12) xor h ;делаем 'фазовый' xor out (#fe),a Такой метод позволяет задавать коэффи─ циент заполнения фазовым способом (как описано в предыдущей главе). Важно то, что второй делитель и второй сумматор тут от─ сутствуют, при этом отсутствующий второй делитель "совпадает" с первым,а отсутству─ ющий второй сумматор "имеет" всегда посто─ янное смещение относительно первого. Давайте добавим контроль над гармоника─ ми, даже с большей гибкостью, чем в методе "Earth Shaker"? rrca ;субгармоника, ;1-я гармоника с rlca и т.д. or h Давайте ещё поиграемся с разными непо─ нятными командами Z80? daa and h Дерзайте. Мне стало понятно, что в такой упрощён─ ный генератор можно добавить практически любой алгоритм, который только можно вооб─ разить, и это даст какой-то интересный эф─ фект. В конце 2016 года я это и сделал - написал движок wtbeep, который предлагает 32 алгоритма,переключаемых на лету. В нас─ тоящее время я продолжаю развивать такой 'упрощённый' подход, играясь также и с уп─ рощённым цифровым движком(см. пример 5). Заключение Довольно долгое время в прошлом 1-бит─ ная музыка была в тени 'настоящей' чип- музыки. Бипер всегда считался неполноцен─ ным,эдаким "аигреком бедного человека". По аналогии можно сказать, что Squeeker - это "гитара бедного человека",а zbmod - "амиж─ ная Paula бедного человека". Следующим шагом, к которому я стремился, должен был стать "FM-синтез бедного человка". Однако, написав wtbeep, я понял одну вещь: нако─ нец-то 1-битная музыка повзрослела (про─ цесс взросления начался с движков Tritone, Phaser и им подобных). Я считаю,что бипер─ ная музыка уже достигла такого уровня, что нет нужды повторять в ней какой-либо дру─ гой метод синтеза. Она заслужила своё соб─ ственное название - двоично-модулированный синтез. Ссылки http://www.randomflux.info/1bit (Форум '1-bit' биперистов) https://github.com/utz82/ ZX-Spectrum-1-Bit-Routines (все мои движки) https://soundcloud.com/irrlicht-project (звучание биперных движков) https://utz82.github.io/bintracker/ (открытый кросс-платформенный трекер с низкоуровневыми звуковыми драйверами и фронт-энд для Music Data Abstraction Language (MDAL))