Биперные дела
Решил вернуться к истокам и покопаться в Plip Plop-подобных одноголосых движках, с прослушивания музыки на которых началось моё увлечение биперной музыкой. Подобный звук был много где, для меня он начался с Ping Pong и Stardust, также он есть во многих играх Ocean, Topo Soft, Hewson и других.
Изучил код, разобрался с техникой. Вообще-то когда-то я сделал подобное сам, в Phaser1, но у меня было два канала, а свой код я тогда придумал с нуля, повторяя наблюдаемый результат — никогда не любил отладку и разбор чужого кода, и особо тогда не вникал.
Первый образчик кода генерации звука наблюдается собственно в движке Plip Plop, который изначально разработал Джонатан Смит, а потом доработал Пол Хьюз из Ocean. Но не только. В движке Topo Soft в точности такой же код, как и код звуков перкуссии, но эти движки отличаются обвязкой. Выглядит так (вариант из Beepola, туда попал лично от Хьюза):
BUZZ0
DEC BC
LD A,B
OR C
JP NZ,BUZZ2
BUZZ1
LD BC,0
EX AF,AF'
ADD A,16
OR BORDER_CLR
OUT (254),A
EX AF,AF'
JP BUZZ2
BUZZ2
DEC DE
LD A,D
OR E
JP NZ,BUZZ0
BUZZ3
LD DE,0
EX AF,AF'
ADD A,16
OR BORDER_CLR
OUT (254),A
EX AF,AF'
JP BUZZ0
Тут используется классическая для Спектрума система с декрементом счётчиков, но только они 16-битные. Как и в моём Phaser1, переполнение каждого счётчика меняет фазу сигнала, только из-за того, что тут один канал, она сразу же выводится на бипер. Никакого выравнивания таймингов и цикла по 8 тактам тут нет.
В движке Стива Тёрнера точно такой же принцип, но счётчики 8-битные:
loop
dec h
jr nz,l1
or #10
ld h,b
l1
dec l
jr nz,l2
or #10
ld l,c
l2
add a,8
and #10
out (#fe),a
srl a
dec e
jr nz,loop
Самое интересное для меня, впрочем — звуки перкуссии. Мне всегда очень нравился сочный «кррбдыщ» в вигре Score 3020 от Topo Soft, и я всё гадал, как же его сделали.
Вариации движков Ocean и Topo отличаются в этой части, но код почти одинаковый, меняются только параметры, а также реализация длительности звучания — где-то есть счётчик цикла, а где-то бесконечный цикл с выходом по прерыванию.
Томы отличаются одним параметром:
TOM1_
LD C,0
ld e,#32
TOM1_0
LD B,C
a7 DJNZ a7
LD A,16 | BORDER_CLR
OUT (254),A
LD A,C
ADD A,4 ;4 или 2
LD C,A
LD B,A
a8 DJNZ a8
LD A,BORDER_CLR
OUT (254),A
dec e
JR nz, TOM1_0
Более уникальные по коду звуки — короткий низкий барабан у Ocean. По сути это PWM-сэмпл, только хранится в начальном регистре C и играется по кругу:
BASS_ LD C,%00111111
ld e,#8
BASS_0 LD B,C
a3 DJNZ a3
LD A,16
OR BORDER_CLR
OUT (254),A
LD A,C
RRCA
LD C,A
LD B,A
a4 DJNZ a4
LD A,BORDER_CLR
OUT (254),A
dec e
JR nz, BASS_0
И «хэт» у Topo Soft. Логика не сильно понятна, но в качестве источника шума берётся содержимое ПЗУ:
BE6F:
ld e,#50
ld hl,#0118
BE74
ld c,(hl)
inc hl
ld b,#08
BE78:
rrc c
ld a,c
and #F0
ld d,a
ld a,(BORDER)
and #07
or d
out (#FE),a
djnz BE78
dec e
jr nz,BE74
И наконец, искомый «кррбдыщ», или просто шумовой ударник. Весь его секрет просто в удачном выборе фрагмента ПЗУ, данные из которого используются как PWM-сэмпл. То есть это чистая случайность, что он получился таким, каким получился.
SNARE_ LD HL,#f18 ;beepola #f18, stardust #280, score3020 #0118
ld e,#4B
SNARE_0 LD B,(HL)
a5 DJNZ a5
LD A,16 | BORDER_CLR
OUT (254),A
INC HL
LD B,(HL)
a6 DJNZ a6
LD A,BORDER_CLR
OUT (254),A
INC HL
dec e
JR nz, SNARE_0
К сожалению, шумовые ударники сделаны не алгоритмами, а по сути проигрыванием сэмлпов. Если поменять содержимое ПЗУ, например, запустить из 128К, их звук радикально меняется. В точности воспроизвести такое звучание без применения ПЗУ можно только вырезанием из него используемого ими фрагмента данных и вставкой в код движка.
1bit
oob
рабочее
phaser
z80
shiru8bit
Санёк Сушка | Саня, Тащи!, блин, как-то упустил из виду, можно же было вставить видео. Исправился, добавил!