1.7. П р о г р а м м и р о в а н и е з в у к о в ы х э ф ф е к т о в Мы уже говорили о возможностях работы с Программируемым Звуковым Гене- ратором - PSG . Здесь мы расскажем Вам о работе с PSG при программирова- нии в машинных кодах. Вначале кратко п о в т о р и м основные сведения. Назначение регистров PSG Вы легко вспомните, если взгляните на таблицу: XWWWWWWWWWRWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWY V Регистр V Н а з н а ч е н и е V TWWWWWWWWWUWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWS V 0 V Младший байт частоты канала A V V 1 V Старший байт частоты канала A V V 2 V Младший байт частоты канала B V V 3 V Старший байт частоты канала B V V 4 V Младший байт частоты канала C V V 5 V Старший байт частоты канала C V V 6 V Частота шума V V 7 V Выбор звучания каналов V V 8 V Громкость канала A V V 9 V Громкость канала B V V 10 V Громкость канала C V V 11 V Младший байт периода волны V V 12 V Старший байт периода волны V V 13 V Указатель формы волны V ZWWWWWWWWWQWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW[ Звуки бывают двух типов, которые мы назовем "звук" и "шум". За сочета- ние звучания "звука" и "шума" отвечает 7-й регистр PSG: бит 7 бит 6 бит 5 бит 4 бит 3 бит 2 бит 1 бит 0 XWWWWWRWWWWWRWWWWWWWWRWWWWWWWWRWWWWWWWWRWWWWWWWWRWWWWWWWWRWWWWWWWWY V O V O V канал CV канал BV канал AV канал CV канал BV канал AV ZWW▌WWQWW▌WWQWWW▌WWWWQWWW▌WWWWQWWWW▌WWWQWWW▌WWWWQWWWW▌WWWQWWWW▌WWW[ V V V V V V V V Не используются ZWWW Выбор"шума"WWW[ ZWW Выбор"звука" WW[ Частота звучания "звука" из некоторого канала (A,B или C) определяется по следующей формуле: 1789772.5 Гц WWWWWWWWWWWW = значение в регистрах для канала A, B или C 16Gчастота По той же формуле вычисляется частота звучания "шума"(значение берется из регистра с номером 6). Период волны определяется по следующей формуле: 1789772.5 Гц WWWWWWWWWWWWW = значение в регистрах 11 и 12. 256Gпериод Работа звукового генератора поддерживается процессором через порты вво- да-вывода со следующими адресами: XWWWWWWRWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWY V Порт V Н а з н а ч е н и е V TWWWWWWUWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWS V A0h V Номер регистра PSG для записи числа V V A1h V Число для записи в отмеченный регистр V V A2h V Последнее число, записанное в PSG V ZWWWWWWQWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW[ Существует два способа записи чисел в PSG средствами языка MSX-BASIC: ═) SOUND reg, data ║) OUT &HA0,reg:OUT &HA1,data П р и м е р 1. Программа в машинных кодах, записывающая число 254 в WWWWWWWWWWWWW звуко-генератор (в регистр 0). 10 CLEAR 200,&HF000:DEFUSR=&HF000 20 DATA 3E,00 :' LD A,0 30 DATA D3,A0 :' OUT (A0h),A 40 DATA 3E,FE :' LD A,FEh 50 DATA D3,A1 :' OUT (A1h),A 60 DATA C9 :' RET 70 DATA RET 80 READ Z$ 90 IF Z$="RET" THEN 110 100 POKE &HF000+T,VAL("&h"+Z$):T=T+1:GOTO 80 110 A=USR(A) Следующая таблица поможет Вам при моделировании оператора PLAY в ма- шинных кодах (данные приведены для канала A): XWWWWWWWRWWWWRWWWWWRWWWWWY XWWWWWWWRWWWWRWWWWWRWWWWWY VОктава VНотаVРег.0VРег.1V VОктава VНотаVРег.0VРег.1V TWWWWWWWUWWWWUWWWWWUWWWWWS TWWWWWWWUWWWWUWWWWWUWWWWWS V V C V 93 V 13 V V V C V 214 V 0 V V O1 V C# V 156 V 12 V V O5 V C# V 202 V 0 V V V D V 231 V 11 V V V D V 190 V 0 V V(контр-V D# V 60 V 11 V V (вто- V D# V 180 V 0 V Vоктава)V E V 155 V 10 V V рая) V E V 170 V 0 V V V F V 2 V 10 V V V F V 160 V 0 V V V F# V 115 V 9 V V V F# V 151 V 0 V V V G V 235 V 8 V V V G V 143 V 0 V V V G# V 107 V 8 V V V G# V 135 V 0 V V V A V 242 V 7 V V V A V 127 V 0 V V V A# V 128 V 7 V V V A# V 120 V 0 V V V B V 20 V 7 V V V B V 113 V 0 V TWWWWWWWUWWWWUWWWWWUWWWWWS TWWWWWWWUWWWWUWWWWWUWWWWWS V V C V 175 V 6 V V V C V 107 V 0 V V O2 V C# V 78 V 6 V V O6 V C# V 101 V 0 V V V D V 244 V 5 V V V D V 95 V 0 V V (боль-V D# V 158 V 5 V V (тре- V D# V 90 V 0 V V шая) V E V 78 V 5 V V тья) V E V 85 V 0 V V V F V 1 V 5 V V V F V 80 V 0 V V V F# V 186 V 4 V V V F# V 76 V 0 V V V G V 118 V 4 V V V G V 71 V 0 V V V G# V 54 V 4 V V V G# V 67 V 0 V V V A V 249 V 3 V V V A V 64 V 0 V V V A# V 192 V 3 V V V A# V 60 V 0 V V V B V 138 V 3 V V V B V 57 V 0 V TWWWWWWWUWWWWUWWWWWUWWWWWS TWWWWWWWUWWWWUWWWWWUWWWWWS V V C V 87 V 3 V V V C V 53 V 0 V V O3 V C# V 39 V 3 V V O7 V C# V 50 V 0 V V V D V 250 V 2 V V V D V 48 V 0 V V(малая)V D# V 207 V 2 V V (чет- V D# V 45 V 0 V V V E V 167 V 2 V V вер- V E V 42 V 0 V V V F V 129 V 2 V V тая) V F V 40 V 0 V V V F# V 93 V 2 V V V F# V 38 V 0 V V V G V 59 V 2 V V V G V 36 V 0 V V V G# V 27 V 2 V V V G# V 34 V 0 V V V A V 253 V 1 V V V A V 32 V 0 V V V A# V 224 V 1 V V V A# V 30 V 0 V V V B V 197 V 1 V V V B V 28 V 0 V TWWWWWWWUWWWWUWWWWWUWWWWWS TWWWWWWWUWWWWUWWWWWUWWWWWS V V C V 172 V 1 V V V C V 27 V 0 V V O4 V C# V 148 V 1 V V O8 V C# V 25 V 0 V V V D V 125 V 1 V V V D V 24 V 0 V V (пер- V D# V 104 V 1 V V(пятая)V D# V 22 V 0 V V вая) V E V 83 V 1 V V V E V 21 V 0 V V V F V 64 V 1 V V V F V 20 V 0 V V V F# V 46 V 1 V V V F# V 19 V 0 V V V G V 29 V 1 V V V G V 18 V 0 V V V G# V 13 V 1 V V V G# V 17 V 0 V V V A V 254 V 0 V V V A V 16 V 0 V V V A# V 240 V 0 V V V A# V 15 V 0 V V V B V 227 V 0 V V V B V 14 V 0 V ZWWWWWWWQWWWWQWWWWWQWWWWW[ TWWWWWWWUWWWWUWWWWWUWWWWWS V(шестая) - V 13 V 0 V ZWWWWWWWQWWWWQWWWWWQWWWWW[ П р и м е р 2. Программа, позволяющая прочесть данные из звукогенера- WWWWWWWWWWWWWW тора и проверить приведенную таблицу. 10 CLEAR 200,&HF000:DEFUSR=&HF000 20 DATA CD,1F,52 :'CALL 521F ; 30 DATA CD,96,00 :'CALL 0096 ; Чтение числа из PSG 40 DATA 26,00 :'LD H,0 ; 50 DATA 6F :'LD L,A ; 60 DATA C3,99,2F,"RET" :'JP 2F99 ; 70 READ Z$ 80 IF Z$="RET" THEN 100 90 POKE &HF000+T,VAL("&h"+Z$):T=T+1:GOTO 70 100 PLAY "O4 C#" 110 PRINT USR(0);USR(1) 'Читаем содержимое 0-го и 1-го регистров Ф о н о в о е м у з ы к а л ь н о е с о п р о в о ж д е н и е \fc (Данный раздел написан А.Н.Никитиным) \f-c- Существует несколько вариантов реализации фонового сопровождения про- граммы. Вспомним один из рутинных вариантов воплощения фонового музыкаль- ного сопровождения. Зная, что длительность нот намного превышает время вы- полнения процессором арифметических операций, можно установить соответст- вие между музыкальной длительностью и определенным количеством арифмети- ческих операций, выполняемых процессором. Далее остается последовательно вставлять музыкальные фрагменты (их длина, разумеется, должна быть ограни- чена настолько,чтобы программа не "зависала"!) между операторами основной программы. Ясно, что такой способ вызывает массу неудобств: значительно усложняется редактирование программы, программирование требует огромных затрат времени и труда, об универсальности программы не может быть и речи. Предлогаемый нами алгоритм реализации фонового музыкального сопровожде- ния полностью и с к л ю ч а е т перечисленные неудобства! Расскажем Вам идею алгоритма. Во время работы процессор совершает мас- кируемые прерывания частотой 5О Гц и опрашивает область ловушек (hooks),а точнее происходят обращения (CALL ...) по адресам FD9Ah, FD9Fh. Напомним Вам, что эти прерывания разрешаются командой ассемблера EI, а запрещаются командой DI. Начальный адрес Таблицы ловушек - &hFD9A. По этому адресу си- стемной области хранится подпрограмма перехода на программу сетевого обме- на у компьютеров серии MSX-2 и число &HC9(машинный код команды RET) у ком- пьютеров серии MSX-1, поэтому при обращении к данной ловушке либо из под- программы обработки прерываний (которая расположена по адресу 0038h),либо из Вашей программы означает мгновенный возврат в основную программу (если MSX-2 не ведет "сетевой диалог"). Если по адресу FD9Ah "положить" подпрограмму: RST 30h DEFB N_slot DEFW Adres RET , где N_slot - это номер слота, в котором будет расположена Ваша программа, а Adres - это адрес Вашей подпрограммы обработки прерываний, то 50 раз в секунду управление будет передаваться Вашей подпрограмме, в которой можно управлять музыкой, печатью, графикой или опрашивать клавиатуру. Вообще говоря,число 50 не очень удобно для точного отсчета музыкальной длительности (так как 50 не делится на 8, 16, 32; в этом смысле идеальным было бы число 64), но при сравнении длительностей между собой (а не с мет- рономом) искажение звука практически незаметно. Структура музыкальной подпрограммы довольно проста: она должна обраба- тывать данные и управлять музыкальными очередями. Вся сложность состоит в том, чтобы построить такую структуру музыкальных данных, которая удовлет- воряла бы следующим требованиям: объем данных должен быть минимальным,воз- можности управления музыкальным генератором должны быть большими, должны присутствовать элементы программирования (циклы,переходы и т.д.), должно выполняться большинство музыкальных выражений (Legato, Staccato и т.д.). В предложенном ниже описании структуры музыкальных данных, мы постара- лись удовлетворить лишь части названных требований.Структура данных очень напоминает стандарт MIDI-интерфейса(Musical Instrument Digital Interface). Порядок размещения данных в очереди следующий: <Команда>,{Данное},{Данное},<Команда>,{Данное},{Данное},... Следует отметить, что {Данное} может быть опущено. Приведем описание команд и данных. К о м а н д а 0. Установка частоты (высоты) звучания: 1 полубайт - команда 00 ; 2 полубайт - номер ноты 1╤12. К о м а н д а 1. Микширование (регистр 7 PSG,по умолчанию - &hb10111000): 1 полубайт - команда 01 , 2 полубайт - формальный , следующий байт - байт состояния (структура аналогична структуре данных, находящихся в регистре 7): &b10 OOO OOO ▌▌▌ ▌▌▌ VVV VVV cba cba - номера каналов Шум Сигнал К о м а н д а 2. Установка темпа воспроизведения (по умолчанию - 1): 1 полубайт - команда 02 ; 2 полубайт - данное (1╤2). К о м а н д а 3. Установка амплитуды звучания (по умолчанию - 8): 1 полубайт - команда 03, 2 полубайт - данное (0╤15) (амплитуда = данное + 1). К о м а н д а 4. Установка частоты шума (по умолчанию - 20): 1 полубайт - команда 04, 2 полубайт - данное (1╤15, частота = данноеG2). К о м а н д а 5. Установка формы волны (пакета): 1 полубайт - команда 05 , 2 полубайт - данное (1╤15). К о м а н д а 6. Установка значения для 11 регистра PSG(по умолчанию-100) 1 полубайт - команда 06, 2 полубайт - данное (0╤15, значение = данное G 10). К о м а н д а 7. Установка значения для 12 регистра PSG(по умолчанию-10): 1 полубайт - команда 07, 2 полубайт - данное (0╤15, значение=данноеG2). К о м а н д а 8. Установка текущей длительности звучания: 1 полубайт - команда 08, 2 полубайт - данное (1╤15), где 1 - целая с точкой, 2 - целая, 3 - половинная с точкой, 4 - половинная, 5 - четвертная с точкой, 6 - четвертная, 7 - восьмая с точкой, 8 - восьмая, 9 - шестнадцатая с точкой, 10 - шестнадцатая, 11 - тридцатьвторая с точкой, 12 - тридцатьвторая. К о м а н д а 9. Пауза: 1 полубайт - команда 09, 2 полубайт - формальный. К о м а н д а 10. Переход (CALL или JUMP) по адресу данных 1 полубайт - команда 10 , 2 полубайт - формальный, следующие два байта- относительный адрес данных от расположения всех музыкальных данных. К о м а н д а 11. Возврат из подпрограммы (адреса хранятся "у себя") Возвращаться можно сколь угодно раз (ибо это не стек)! 1 полубайт - команда 11 , 2 полубайт - формальный. К о м а н д а 12. Стоп, выключить канал: 1 полубайт - команда 12, 2 полубайт - формальный. К о м а н д а 13. Установка текущей октавы: 1 полубайт - команда 13, 2 полубайт - номер октавы (1,2,3,...,8). К о м а н д а 14. Прием игры (Staccato, Legato): 1 полубайт - команда 14, 2 полубайт - 1, если Staccato и 0, если Legato. Заметим, что числа от 2 до 15 могут выражать и другие приемы игры! К о м а н д а 15. Резервная: 1 полубайт - команда 15, 2 полубайт - ... (можно использовать как пере- дачу других команд, т.е. 15-я команда становится п р е ф и к с н о й). Таким образом, Ваша подпрограмма должна распознавать номер команды, ис- полнять ее, исходя из параметров, следующих за командой и помещать указа- тель данных на следующую команду. Если Вы желаете увеличить музыкальные возможности программы,а команд (в полубайт можно поместить число от 0 до 15) не хватает, то необходимо выделить префиксную команду (например, 15-ю, так как она резервная)и теперь порядок размещения данных в очереди станет следующим: <Команда>,<Команда>,{данное},{данное},... <Команда>,<Команда>,{данное},{данное},... Кроме аппаратной реализации фонового музыкального сопровождения,сущест- вует и программная. Вся прелесть аппаратной реализации в том, что уменьше- ние длительности нот происходит в режиме реального времени.Программно мож- но запараллелить многие процессы (в том числе и музыку): Process: CALL ... CALL Music CALL ... JR Process , но дело в том, что тактовая частота процесора гораздо выше, чем частота маскируемых прерываний и без задержки (которая очень часто просто не нужна) казалось бы не обойтись. Н о в ы х о д е с т ь! Маскируемые прерывания оставляют след в области системных переменных, и этим можно воспользоваться. Ячейка с адресом 0FC9Eh (Jiffy) хранит этот след. Содержимое Jiffy (2 байта) при каждом новом прерывании увеличивает- ся на единицу, а значит, момент нового "тика" (это выражение произошло из принципа работы подпрограммы часов компьютера)всегда можно регистрировать. В Приложении приведена программа обработки музыкальных очередей, на- писанная на ассемблере Z80 для компьютера MSX-2.