Инструменты пользователя

Инструменты сайта


msx:basic_dialogue_programming_language:107

Это старая версия документа!


Первая страницаПредыдущая страницаНазад к обзоруСледующая страницаПоследняя страница

1.7. Программирование звуковых эффектов

FIXME

Мы уже говорили о возможностях работы с Программируемым Звуковым Генератором — PSG. Здесь мы расскажем Вам о работе с PSG при программировании в машинных кодах.

Вначале кратко повторим основные сведения.

Назначение регистров PSG Вы легко вспомните, если взгляните на таблицу:

Регистр Назначение
0 Младший байт частоты канала A
1 Старший байт частоты канала A
2 Младший байт частоты канала B
3 Старший байт частоты канала B
4 Младший байт частоты канала C
5 Старший байт частоты канала C
6 Частота шума
7 Выбор звучания каналов
8 Громкость канала A
9 Громкость канала B
10 Громкость канала C
11 Младший байт периода волны
12 Старший байт периода волны
13 Указатель формы волны
   Звуки бывают двух типов, которые мы назовем "звук" и "шум". За сочета-
ние звучания "звука" и "шума" отвечает 7-й регистр PSG:
   бит 7 бит 6   бит 5    бит 4    бит 3    бит 2    бит 1    бит 0
  ┌─────┬─────┬────────┬────────┬────────┬────────┬────────┬────────┐
  │  ∗  │  ∗  │ канал C│ канал B│ канал A│ канал C│ канал B│ канал A│
  └──▲──┴──▲──┴───▲────┴───▲────┴────▲───┴───▲────┴────▲───┴────▲───┘
     │     │      │        │         │       │         │        │
  Не используются └─── Выбор"шума"───┘       └── Выбор"звука" ──┘
   Частота звучания "звука" из некоторого канала (A,B или C) определяется
по следующей формуле:
        1789772.5 Гц
        ──────────── = значение в регистрах для канала A, B или C
         16·частота
   По той же формуле вычисляется частота звучания "шума"(значение берется
из регистра с номером 6).
   Период волны определяется по следующей формуле:
            1789772.5 Гц
           ───────────── = значение в регистрах 11 и 12.
             256·период
   Работа звукового генератора поддерживается процессором через порты вво-
да-вывода со следующими адресами:
             ┌──────┬───────────────────────────────────────┐
             │ Порт │          Н а з н а ч е н и е          │
             ├──────┼───────────────────────────────────────┤
             │  A0h │ Номер регистра PSG для записи числа   │
             │  A1h │ Число для записи в отмеченный регистр │
             │  A2h │ Последнее число, записанное в PSG     │
             └──────┴───────────────────────────────────────┘
   Существует два способа записи чисел в PSG средствами языка MSX-BASIC:
   α) SOUND reg, data
   β) OUT &HA0,reg:OUT &HA1,data
   П р и м е р 1.  Программа в машинных кодах, записывающая число  254  в
   ─────────────   звуко-генератор (в регистр 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):






       ┌───────┬────┬─────┬─────┐     ┌───────┬────┬─────┬─────┐
       │Октава │Нота│Рег.0│Рег.1│     │Октава │Нота│Рег.0│Рег.1│
       ├───────┼────┼─────┼─────┤     ├───────┼────┼─────┼─────┤
       │       │ C  │  93 │ 13  │     │       │ C  │ 214 │  0  │
       │  O1   │ C# │ 156 │ 12  │     │  O5   │ C# │ 202 │  0  │
       │       │ D  │ 231 │ 11  │     │       │ D  │ 190 │  0  │
       │(контр-│ D# │  60 │ 11  │     │ (вто- │ D# │ 180 │  0  │
       │октава)│ E  │ 155 │ 10  │     │  рая) │ E  │ 170 │  0  │
       │       │ F  │   2 │ 10  │     │       │ F  │ 160 │  0  │
       │       │ F# │ 115 │  9  │     │       │ F# │ 151 │  0  │
       │       │ G  │ 235 │  8  │     │       │ G  │ 143 │  0  │
       │       │ G# │ 107 │  8  │     │       │ G# │ 135 │  0  │
       │       │ A  │ 242 │  7  │     │       │ A  │ 127 │  0  │
       │       │ A# │ 128 │  7  │     │       │ A# │ 120 │  0  │
       │       │ B  │  20 │  7  │     │       │ B  │ 113 │  0  │
       ├───────┼────┼─────┼─────┤     ├───────┼────┼─────┼─────┤
       │       │ C  │ 175 │  6  │     │       │ C  │ 107 │  0  │
       │  O2   │ C# │  78 │  6  │     │  O6   │ C# │ 101 │  0  │
       │       │ D  │ 244 │  5  │     │       │ D  │  95 │  0  │
       │ (боль-│ D# │ 158 │  5  │     │ (тре- │ D# │  90 │  0  │
       │  шая) │ E  │  78 │  5  │     │  тья) │ E  │  85 │  0  │
       │       │ F  │   1 │  5  │     │       │ F  │  80 │  0  │
       │       │ F# │ 186 │  4  │     │       │ F# │  76 │  0  │
       │       │ G  │ 118 │  4  │     │       │ G  │  71 │  0  │
       │       │ G# │  54 │  4  │     │       │ G# │  67 │  0  │
       │       │ A  │ 249 │  3  │     │       │ A  │  64 │  0  │
       │       │ A# │ 192 │  3  │     │       │ A# │  60 │  0  │
       │       │ B  │ 138 │  3  │     │       │ B  │  57 │  0  │
       ├───────┼────┼─────┼─────┤     ├───────┼────┼─────┼─────┤
       │       │ C  │  87 │  3  │     │       │ C  │  53 │  0  │
       │  O3   │ C# │  39 │  3  │     │  O7   │ C# │  50 │  0  │
       │       │ D  │ 250 │  2  │     │       │ D  │  48 │  0  │
       │(малая)│ D# │ 207 │  2  │     │ (чет- │ D# │  45 │  0  │
       │       │ E  │ 167 │  2  │     │  вер- │ E  │  42 │  0  │
       │       │ F  │ 129 │  2  │     │  тая) │ F  │  40 │  0  │
       │       │ F# │  93 │  2  │     │       │ F# │  38 │  0  │
       │       │ G  │  59 │  2  │     │       │ G  │  36 │  0  │
       │       │ G# │  27 │  2  │     │       │ G# │  34 │  0  │
       │       │ A  │ 253 │  1  │     │       │ A  │  32 │  0  │
       │       │ A# │ 224 │  1  │     │       │ A# │  30 │  0  │
       │       │ B  │ 197 │  1  │     │       │ B  │  28 │  0  │
       ├───────┼────┼─────┼─────┤     ├───────┼────┼─────┼─────┤
       │       │ C  │ 172 │  1  │     │       │ C  │  27 │  0  │
       │  O4   │ C# │ 148 │  1  │     │  O8   │ C# │  25 │  0  │
       │       │ D  │ 125 │  1  │     │       │ D  │  24 │  0  │
       │ (пер- │ D# │ 104 │  1  │     │(пятая)│ D# │  22 │  0  │
       │  вая) │ E  │  83 │  1  │     │       │ E  │  21 │  0  │
       │       │ F  │  64 │  1  │     │       │ F  │  20 │  0  │
       │       │ F# │  46 │  1  │     │       │ F# │  19 │  0  │
       │       │ G  │  29 │  1  │     │       │ G  │  18 │  0  │
       │       │ G# │  13 │  1  │     │       │ G# │  17 │  0  │
       │       │ A  │ 254 │  0  │     │       │ A  │  16 │  0  │
       │       │ A# │ 240 │  0  │     │       │ A# │  15 │  0  │
       │       │ B  │ 227 │  0  │     │       │ B  │  14 │  0  │
       └───────┴────┴─────┴─────┘     ├───────┼────┼─────┼─────┤
                                      │(шестая)  - │  13 │  0  │
                                      └───────┴────┴─────┴─────┘

   П р и м е р 2.  Программа, позволяющая прочесть данные  из звукогенера-
   ──────────────  тора и проверить приведенную таблицу.
   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 ∗∗∗ ∗∗∗
                 ▲▲▲ ▲▲▲
                 │││ │││
                 cba cba - номера каналов
                 Шум Сигнал
К о м а н д а  2. Установка темпа воспроизведения (по умолчанию - 1):
   1 полубайт - команда 02 ; 2 полубайт - данное (1÷2).
К о м а н д а  3. Установка амплитуды звучания (по умолчанию - 8):
   1 полубайт - команда 03,
   2 полубайт - данное  (0÷15) (амплитуда = данное + 1).
К о м а н д а  4. Установка частоты шума (по умолчанию - 20):
   1 полубайт - команда 04,
   2 полубайт - данное (1÷15, частота = данное·2).
К о м а н д а  5. Установка формы волны (пакета):
   1 полубайт - команда 05 , 2 полубайт - данное (1÷15).
К о м а н д а  6. Установка значения для 11 регистра PSG(по умолчанию-100)
   1 полубайт - команда 06,
   2 полубайт - данное (0÷15, значение = данное · 10).
К о м а н д а  7. Установка значения для 12 регистра PSG(по умолчанию-10):
   1 полубайт - команда 07, 2 полубайт - данное (0÷15, значение=данное·2).
К о м а н д а  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.

Первая страницаПредыдущая страницаНазад к обзоруСледующая страницаПоследняя страница

msx/basic_dialogue_programming_language/107.1674491365.txt.gz · Последние изменения: 2023-01-23 19:29 — GreyWolf