ZX Forum
#04
19 ноября 1997 |
|
Мир звуков Спектрума - глава 4.1: Программирование звуковых эффектов - Тон, Шум, Комплексы эффектов.
4.1. Программирование звуковых эффектов Вообще-то, программирование эффектов в кодах мало отличается от аналогичного за- нятия на бейсике, но Вы получаете значи- тельное преимущество за счет быстродей- ствия. Поэтому кроме чистого тона на ас- семблере можно создавать и шум. 4.1.1. Тон Начнем с эффектов, основанных на гене- рации тона. Что они из себя представляют? Примерно то же, что и эффекты на бейсике: звук с плавно изменяющейся частотой. Для полного сходства можно даже использовать ту же подпрограмму из ПЗУ:1415. 10 LD B,30 ; B=количество нот 20 LD HL,100 ; HL=начальная частота 30 LOOP LD DE,2 ; DE=длительность 40 PUSH HL ; сохранение HL 50 PUSH BC ; сохранение BC 60 CALL 949 ; вызов подпрограммы ПЗУ 70 POP BC ; восстановление BC 80 POP HL ; восстановление HL 90 LD DE,25 ; DE=шаг изменения частоты 100 ADD HL,DE ; увеличение HL 110 DJNZ LOOP ; цикл 120 RET ; возврат в бейсик 2 Скорее всего, Вы заметили, что в этом эффекте не запрещаются прерывания, а ка- чество сигнала ничуть не ухудшилось (см. главу "Как получается звук"). Дело в том, что вызываемая подпрограмма все необходи- мое делает сама. Если Вы уже успели набрать и запустить этот фрагмент, то, наверное, ощутили раз- ницу в звучании, причем не в пользу бейси- ка. Несколько модифицировать данный эффект можно, изменяя не всю частоту, а только ее младший байт: 1415. 10 LD B,60 ; B=количество нот 20 LD C,50 ; C=шаг изменения частоты 30 LD HL,300 ; HL=начальная частота 40 LOOP LD DE,10 ; DE=длительность 50 PUSH HL ; сохранение HL 60 PUSH BC ; сохранение BC 70 CALL 949 ; вызов подпрограммы ПЗУ 80 POP BC ; восстановление BC 90 POP HL ; восстановление HL 100 LD A,L ; увели- 110 ADD C ; чение 120 LD L,A ; L 130 DJNZ LOOP ; цикл 140 RET ; возврат в бейсик 2 От использования подпрограмм ПЗУ перей- дем к созданию собственных. Звучание пре- дыдущих примеров можно сделать более плав- ным и протяжным: 1415. 10 DI ; запрет прерываний 20 XOR A ; A=цвет бордюра (0) 30 LD B,255 ; B=начальная частота 40 LD C,255 ; C=длительность 50 BEEP XOR 16 ; инвертирование бита D4 60 OUT (254),A ; вывод A в порт 254 70 PUSH BC ; сохранение BC 80 LOOP DJNZ LOOP ; задержка 90 POP BC ; восстановление BC 100 DEC B ; уменьшение B 110 DEC C ; C=C-1 120 JR NZ,BEEP ; если C<>0, то цикл 130 EI ; разрешение прерываний 140 RET ; возврат в бейсик 2 Возможности этого эффекта легко увели- чиваются: 1415. 10 DI ; запрет прерываний 20 XOR A ; A=цвет бордюра (0) 30 LD B,255 ; B=количество нот 40 LD C,1 ; C=начальная частота 50 LOOP1 PUSH BC ; сохранение BC 60 LD B,5 ; B=длительность 70 LOOP2 XOR 16 ; инвертирование бита D4 80 OUT (254),A ; вывод A в порт 254 90 PUSH BC ; сохранение BC 100 LD B,C ; B=C 110 LOOP3 DJNZ LOOP3 ; задержка 120 POP BC ; восстановление BC 130 DJNZ LOOP2 ; цикл 140 POP BC ; восстановление BC 150 INC C ; увеличение C 160 DJNZ LOOP1 ; второй цикл 170 EI ; разрешение прерываний 180 RET ; возврат в бейсик 2 Скорее всего, Вы заметили, что в первом варианте задержка уменьшается, а во втором увеличивается. Ничто не мешает Вам сменить направление ее изменения. Для этого только стоит выбрать команду DEC (уменьшение) или INC (увеличение). Также можно настроить и длительность, начальную частоту и т.п. Можно изменить шаг смещения частоты: 1415. 10 DI ; запрет прерываний 20 XOR A ; A=цвет бордюра (0) 30 LD B,255 ; B=начальная частота 40 LD C,255 ; C=длительность 50 BEEP XOR 16 ; инвертирование бита D4 60 OUT (254),A ; вывод A в порт 254 70 PUSH BC ; сохранение BC 80 LOOP DJNZ LOOP ; задержка 90 POP BC ; восстановление BC 100 EX AF,AF' ; смена регистров A и F на альтернативные 110 LD A,B ; A=B 120 SUB 3 ; A=A-3 130 LD B,A ; B=A 140 EX AF,AF' ; обратная смена регистров 150 DEC C ; C=C-1 160 JR NZ,BEEP ; если C<>0, то цикл 170 EI ; разрешение прерываний 180 RET ; возврат в бейсик 2 Теперь воспользуемся свободой действий, которую нам предоставляет программирование в кодах. Напишем нестандартную процедуру воспроизведения: 1415. 10 DI ; запрет прерываний 20 LD D,10 ; D=задержка 1 30 LD E,100 ; E=задержка 2 40 LD C,255 ; C=длительность 50 XOR A ; A=цвет бордюра (0) 60 LOOP1 XOR 16 ; инвертирование бита D4 70 OUT (254),A ; вывод A в порт 254 80 LD B,D ; B=D 90 LOOP2 DJNZ LOOP2 ; задержка 100 XOR 16 ; инвертирование бита D4 110 OUT (254),A ; вывод A в порт 254 120 LD B,E ; B=E 130 LOOP3 DJNZ LOOP3 ; задержка 140 INC D ; увеличение D 150 INC E ; увеличение E 160 DEC C ; C=C-1 170 JR NZ,LOOP1 ; если C<>0, то цикл 180 EI ; разрешение прерываний 190 RET ; возврат в бейсик 2 Здесь тоже можно долго и старательно варьировать параметры (см. Приложение 1 - Flowing 2). Довольно интересный эффект получает- ся при использовании регистра R, значение младших семи битов которого увеличивается после выполнения очередного машинного цик- ла. Этот эффект можно условно назвать "по- лушумом". Вот пример такого эффекта: 1415. 10 DI ; запрет прерываний 20 LD C,53 ; C=задержка 1 30 LD B,207 ; B=задержка 2 40 LD E,203 ; E=длительность 50 LD D,0 ; D=цвет бордюра 60 LD A,128 ; A=темп (0/128) 70 LD R,A ; R=A 80 BEGIN LD A,R ; A=R 90 PAUS1 DEC A ; A=A-1 100 JR NZ,PAUS1 ; если A<>0, то цикл 110 LD A,D ; A=D 120 OR 16 ; установка бита D4 130 OUT (254),A ; вывод A в порт 254 140 LD A,C ; A=C 150 PAUS2 DEC A ; A=A-1 160 JR NZ,PAUS2 ; если A<>0, то цикл 170 LD A,D ; A=D 180 OUT (254),A ; вывод A в порт 254 190 LD A,B ; A=B 200 PAUS3 DEC A ; A=A-1 210 JR NZ,PAUS3 ; если A<>0, то цикл 220 INC C ; C=C+1 230 INC B ; B=B+1 240 DEC E ; E=E-1 250 JR NZ,BEGIN ; если E<>0, то цикл 260 EI ; разрешение прерываний 270 RET ; возврат 2 Значения в строках 20 и 30 определяют задержки между перепадами уровня, в строке 40 - длительность эффекта, в строке 50 - цвет бордюра, а в строке 60 - темп. В строке 60 имеет смысл употреблять только значения 0 и 128, так как все остальные будут аналогичны этим. В строках 220 и 230 Вы можете установить закон изменения обеих задержек (команды INC, DEC и NOP с регис- трами B и C в любой комбинации). Если Вы не запутались во всех этих при- мерах, то перейдем к генерации шума. Если же Вы все-таки ничего не поняли, то сове- тую испытать эти эффекты и поизменять их параметры. 4.1.2. Шум Что из себя представляет шум? Это пос- ледовательность импульсов случайной дли- тельности. Поэтому для его создания нам понадобятся случайные данные. Где их взять? Единственный подходящий источник - ПЗУ, в котором записан интерпретатор бей- сика. ПЗУ расположено с адреса 0 до 16383 (#3FFF). Правда, значения эти будут не совсем случайные, точнее совсем не случай- ные, но нас они устроят. Создавать шум можно двумя разными спо- собами. Они немного отличаются по звуча- нию. Первый из них состоит в выводе в порт значений, прочитанных из ПЗУ. Второй же - в использовании этих значений в качестве задержки. При генерации шума любым из этих спосо- бов прерывания запрещать не обязательно, так как в шуме потрескивание слышно не бу- дет. При использовании первого способа из каждого байта можно извлечь данные на во- семь проходов цикла воспроизведения, но это не выгодно с программной точки зрения. Поэтому, в большинстве эффектов из байта берется одно значение. Например: 1415. 10 LD HL,0 ; HL=адрес ПЗУ 20 LD BC,1000 ; BC=длительность 30 BEGIN PUSH BC ; сохранение BC 40 LD A,(HL) ; A=содержимое ячейки ПЗУ 50 AND 240 ; сброс битов бордюра 60 OUT (254),A ; вывод A в порт 254 70 LD B,50 ; B=частота 80 LOOP DJNZ LOOP ; задержка 90 INC HL ; HL=HL+1 100 POP BC ; восстановление BC 110 DEC BC ; BC=BC-1 120 LD A,B ; BC= 130 OR C ; 0 ? 140 JR NZ,BEGIN ; цикл 150 RET ; возврат в бейсик 2 Пример применения второго способа: 1415. 10 LD HL,0 ; HL=адрес ПЗУ 20 LD BC,1000 ; BC=длительность 30 XOR A ; A=цвет бордюра (0) 40 BEGIN PUSH BC ; сохранение BC 50 XOR 16 ; инвертирование бита D4 60 OUT (254),A ; вывод A в порт 254 70 LD B,(HL) ; B=содержимое ячейки ПЗУ 80 LOOP1 DJNZ LOOP1 ; задержка 90 LD B,40 ; B=частота 100 LOOP2 DJNZ LOOP2 ; задержка 110 INC HL ; HL=HL+1 120 POP BC ; восстановление BC 130 DEC BC ; BC=BC-1 140 LD D,A ; сохранение A 150 LD A,B ; BC= 160 OR C ; 0 ? 170 LD A,D ; восстановление A 180 JR NZ,BEGIN ; цикл 190 RET ; возврат в бейсик 2 Если в этих эффектах команду INC HL за- менить на INC L, то их звучание станет как бы скачущим. Это происходит из-за того, что данные берутся не из всего заданного объема ПЗУ, а из его части размером 256 байт. Причем, когда эта часть кончается, чтение продолжается с ее начала. Попробуйте поизменять другие параметры. Следующий шаг - шум с изменяющейся час- тотой. Выглядеть это будет примерно так: 1415. 10 LD HL,0 ; HL=адрес ПЗУ 20 LD B,100 ; B=длина эффекта 30 LD C,10 ; C=начальная частота 40 LOOP1 PUSH BC ; сохранение BC 50 LD B,20 ; B=длительность 60 LOOP2 LD A,(HL) ; A=содержимое ячейки ПЗУ 70 AND 240 ; сброс битов бордюра 80 OUT (254),A ; вывод A в порт 254 90 PUSH BC ; сохранение BC 100 LD B,C ; B=C 110 LOOP3 DJNZ LOOP3 ; задержка 120 INC HL ; HL=HL+1 130 POP BC ; восстановление BC 1415.140 DJNZ LOOP2 ; цикл 150 POP BC ; восстановление BC 160 INC C ; увеличение задержки 170 DJNZ LOOP1 ; цикл 180 RET ; возврат в бейсик 2 Этот эффект тоже можно изменить до не- узнаваемости: сменить длину, частоту, дли- тельность, шаг смещения частоты, направле- ние смещения частоты (команда INC C или DEC C), вид шума (команда INC HL или INC L). Еще один вариант шумового эффекта: 1415. 10 LD HL,0 ; HL=адрес ПЗУ 20 LD D,100 ; D=задержка 1 30 LD E,10 ; E=задержка 2 40 LD C,255 ; C=длительность 50 XOR A ; A=цвет бордюра (0) 60 BEGIN XOR 16 ; инвертирование бита D4 70 OUT (254),A ; вывод A в порт 254 80 LD B,(HL) ; B=содержимое ячейки ПЗУ 90 LOOP1 DJNZ LOOP1 ; задержка 1 100 LD B,D ; B=D 110 LOOP2 DJNZ LOOP2 ; задержка 2 120 XOR 16 ; инвертирование бита D4 130 OUT (254),A ; вывод A в порт 254 140 LD B,(HL) ; B=содержимое ячейки ПЗУ 150 LOOP3 DJNZ LOOP3 ; задержка 3 160 LD B,E ; B=E 170 LOOP4 DJNZ LOOP4 ; задержка 4 180 INC HL ; HL=HL+1 190 INC D ; увеличение D 200 INC E ; увеличение E 210 DEC C ; C=C-1 220 JR NZ,BEGIN ; если C<>0, то цикл 230 RET ; возврат в бейсик 2 Над этим примером можно издеваться так же долго, как и над всеми предыдущими. Все эффекты, приведенные в данной гла- ве, можно рассматривать как заготовки. Чтобы получить конечные варианты, Вам, возможно, придется потрудиться. Как уже было сказано, все они имеют огромное чис- ло вариантов. Кроме того, Вы можете объе- динить несколько эффектов вместе, или вы- зывать их на выполнение в цикле и т.п. Все основные принципы комбинации эффектов пе- речислены в главе 2.1. Все эффекты написаны так, чтобы можно было изменять максимальное число пара- метров. В случаях конкретного применения их можно значительно упрощать. Вот пример скомбинированного и упрощенного эффекта: 1415. 10 DI ; запрет прерываний 20 LD E,100 ; E=длительность цикла 30 LD C,0 ; C=цвет бордюра 40 LD B,4 ; B=число циклов 50 LD L,1 ; L=смещение частоты 60 LD H,30 ; H=начальная частота 70 LOOP1 LD D,E ; D=E 80 LOOP2 LD A,C ; A=C 90 XOR 16 ; инвертирование бита D4 100 OUT (254),A ; вывод A в порт 254 110 LD C,A ; C=A 120 LD A,H ; A=H 130 ADD A,L ; прибавить L к A 140 LD H,A ; H=A 150 LOOP3 DEC A ; A=A-1 160 JR NZ,LOOP3 ; если A<>0, то цикл 170 DEC D ; D=D-1 180 JR NZ,LOOP2 ; если D<>0, то цикл 190 LD A,L ; A=L 200 NEG ; изменение знака регистра A 210 LD L,A ; L=A 220 DJNZ LOOP1 ; цикл 230 EI ; разрешение прерываний 240 RET ; возврат 2 Все вышеприведенные эффекты Вы можете настроить под собственные нужды. Например, изменить цвет бордюра или сделать так, чтобы сигнал кроме динамика выводился на магнитофон (для этого все команды XOR 16 надо заменить на XOR 24, а AND 240 на AND 248). 4.1.3. Комплексы эффектов Обычно в играх (да и в любых других программах) используется не один и не два звуковых эффекта, а гораздо больше. Поэто- му эффекты удобно объединять в группы (комплексы) и вызывать их на исполнение одной подпрограммой, передавая ей в качес- тве параметра номер эффекта. Если эффекты разнообразны и воспроизво- дятся различными подпрограммами, то в таб- лице эффектов лучше всего хранить адреса этих подпрограмм. В таком случае для вос- произведения эффектов можно воспользовать- ся такой подпрограммой: 1415. 10 ADD A,A ; A=A*2 20 LD E,A ; DE 30 LD D,0 ; =A 40 LD HL,TABLE ; HL=адрес таблицы 50 ADD HL,DE ; HL=HL+DE 60 LD E,(HL) ; DE= 70 INC HL ; адрес 80 LD D,(HL) ; подпрограммы 90 EX DE,HL ; обменять значениями HL и DE 100 JP (HL) ; вызов подпрограммы эффекта 110 TABLE DEFW ... ; таблица адресов 2 Перед вызовом этой подпрограммы в ре- гистр A надо занести номер эффекта. Не за- будьте также заполнить таблицу адресами эффектов. Естественно, сами эффекты дол- жны располагаться по указанным адресам. Ни в коем случае не стоит указывать номер эф- фекта больше числа описанных в таблице подпрограмм, иначе компьютер "зависнет" или "сбросится". Учтите также, что эта подпрограмма может работать максимум со 127 эффектами. Если эффекты однотипные и воспроизво- дятся одной и той же подпрограммой, то в таблице эффектов можно хранить параметры этой подпрограммы. Вот пример, использую- щий данный способ: 1415. 10 LD E,A ; A 20 ADD A,A ; = 30 ADD A,E ; A*3 40 LD E,A ; DE 50 LD D,0 ; =A 60 LD HL,TABLE ; HL=адрес таблицы 70 ADD HL,DE ; HL=HL+DE 80 LD C,(HL) ; C=длительность 90 INC HL ; HL=HL+1 100 LD E,(HL) ; E=частота 110 INC HL ; HL=HL+1 120 LD A,(HL) ; A=изменение частоты 130 LD (CHNG),A ; установка изменения частоты 140 DI ; запрет прерываний 150 XOR A ; A=цвет бордюра (0) 160 BEGIN XOR 16 ; инвертирование бита D4 170 OUT (254),A ; вывод A в порт 254 180 LD B,E ; B=E 190 PAUSE DJNZ PAUSE ; задержка 200 CHNG NOP ; резерв для изменения частоты 210 DEC C ; C=C-1 220 JR NZ,BEGIN ; если C<>0, то цикл 230 EI ; разрешение прерываний 240 RET ; возврат 250 TABLE DEFB 0,0,28 ; таблица 260 DEFB 0,0,29 ; 270 DEFB 0,128,28 ; эффектов 280 DEFB 0,128,29 ; 2 Перед вызовом этой подпрограммы в ре- гистр A надо занести номер эффекта. В при- веденной программе уже созданы четыре эф- фекта, но Вы можете изменить их или увели- чить их число. При вызове эффекта, номер которого больше числа описанных подпрог- рамм, также может произойти что-нибудь ужасное. В этом примере на описание эффекта от- водится три байта. Первый байт - длитель- ность эффекта, второй - начальная частота, а третий - способ изменения частоты. Тре- тий байт может принимать значения 0, 28 и 29. Что означает, соответственно, сохране- ние, увеличение и уменьшение частоты. За- носить какие-либо другие значения в этот байт не стоит, так как это может привести к непредсказуемым последствиям. Приведенная программа является только примером. Вы можете настроить ее для рабо- ты с абсолютно любым эффектом. Эта подпрограмма может работать макси- мум с 85 эффектами. В обеих приведенных подпрограммах нуме- рация эффектов начинается с нуля.
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября