MSD #12
08 июня 2000

Программирование - вывод цифрового звука на AY.

                              
                    ПОСЛУШАЕМ 
                              


Вишев Алекс/MSD/20.12.99(c)


   Благородной целью сего послания является просветить народ
о технологии работы с цифровым звуком. Приступим.



             Немного науки.


  Если вы не в ладах с физикой, то священный долг вашего по-
корного слуги напомнить вам о том, что из себя представляет
звук. Итак, звук - это механическое колебание распростроняе-
мое в упругой среде и воспринимаемое органами слуха. Музы-
кальные звуки характеризуются высотой тона, громкостью и
тембром. Высота тона соответствует его частоте: чем больше
частота, тем выше тон звука. Громкость звука обусловливается
силой звука, которая в свою очередь определяется амплитудой
колебания звуковой волны. Звук будет тем громче, чем больше
амплитуда колебания. Звуки исходящие от различных источников
неодинаковы по тембру, т.е. по окраске.
  Для нас же частота - это периодичность выкидывания очеред-
ного байта в AY. При всем при этом, частота формируется уже
в процессе звучания сэмпла (таким образом является возможным
проигрывание однажды оцифрованого сэмпла на разных нотах и
октавах).


                Начало.


  Поговорим о работе с AY (ковоксы еще так редки...). Самое
простое, что можно придумать, - это вывод сэмпла в один
канал AY.
  Кстати, сэмпл представляет из себя определенный набор бай-
тов, несущих информацию об амплитуде звука.
  Продолжим. AY обладает лишь шестнадцатью уровнями громкос-
ти (4 бита, 16 уровней), а сэмплы, как правило, бывают
восьмибитными (256 уровней). Из этого следует, что их надо
конвертировать в четырехбитный формат. Но не все так просто,
так как у AY, при увеличении громкости на единицу, таковая
возрастает не на 1/16. Этот печальный факт подводит нас к
тому, что для конвертирования придется завести специальную
таблицу. Здесь она не приводится, а интересующихся отсылаю
в ZX FORMAT 8.
  Вот простейшая процедурка для проигрывания одного сэмпла.
Здесь предполагается, что сэмпл конвертирован. Если нет, то
звук будет некачественным.


        DI           ;запретим прерывания
        LD HL,sample ;начало звука в памяти
        LD DE,lenght ;его длина
        LD BC,#FFFD  ;порт для записи номера регистра AY
        LD A,8       ;регистр громкости АY канал А
        OUT (C),A    ;установим
        LD B,#BF     ;BC=#BFFD - порт записи в регистры AY
   LOOP LD A,(HL)    ;возьмем байт
        OUT (C),A    ;кинем в порт
        INC HL       ;
        DEFS 20      ;задержка, дла выставления частоты, чем
                     ;больше - тем ниже тон
        DEC DE
        LD A,D
        OR E         ;DE=0 ?
        JR NZ,LOOP   ;продолжим цикл
        EI           ;разрешим прерывания
        RET


            Многоканальный звук.


  Теперь переходим к самому интересному. Как вы могли наблю-
дать, частота звука по такому методу может устанавливаться
только для одного звукового канала. Как же нам быть, ведь в
АY их три ? А быть нам очень просто. Правда для этого пона-
добится еще один регистр. Например вот так:


        LD A,D    ;регистр D используется как счетчик пере-
LOW     ADD A,0   ;полнений. В HL адрес инструмента.
        LD D,A    ;Как только регистр D переполнится
        LD A,L    ;произойдет увеличение HL на единицу
HIGH    ADC A,1   ;дополнительно к этому будет происходить
        LD L,A    ;увеличение HL на количество HIGH за
        ADC A,H   ;каждый проход плейера
        SUB L
        LD H,A


  Таким образом, нам нужна специальная таблица, в которой
будут содержаться байты LOW и HIGH для каждой ноты каждой
октавы.


                Плейер.


  Вот теперь по-моему совсем все просто. Итак, мы имеем
где-то в памяти таблицу нот, таблицу адресов сэмплов и,
собственно говоря, список нот, на которых надо проигрывать
мелодию. Также мы имеем сам плейер, как основной модуль
программы, и процедурку на прерываниях, которая будет зани-
маться тем, что заменять параметры LOW и HIGH, а также
адреса сэмплов для каждого звукового канала.

  Устанавливаем прерывания на адрес вашей процедурки, кото-
рая меняет пораметры LOW и HIGH. В HL - адрес инструмента.
Как промежуточный счетчик используется D. Сэмплы должны быть
конвертированными. К каждому байту сэмпла необходимо приба-
вить #А0, что связано с особенностями дешифрации, так как
звук выводить мы будем по младшей половинке порта AY. В кон-
це сэмпла должно быть определенное количество нулей, по ко-
торым определяется конец сэмпла. Это количество равняется
самому большому значению HIGH, используемому в вашем плейере
+1. Вот приблизительно как это будет выглядеть:


BEGIN
        LD BC,#FFFD
A_CHAN  LD A,8
        OUT (C),A    ;канал А

     LD A,80     ;если под сэмплы используется 128-ая память
     OUT (#FD),A ;переключим страницу памяти. Где 80 - нуле-
                 ;вая страница, 81 - первая и т.д.

     LD A,(HL)   ;берем байт сэмпла
VOL  SUB 1       ;этой командой мы ловим два зайца.
                 ;Во-первых,
                 ;мы определяем конец сэмпла, а во-вторых,
                 ;здесь можно выставлять громкость звучания.
                 ;Чем больше VOL - тем тише звук, но не > 15

        JR C,NOT_SMP;обход, если сэмпл кончился
        OUT (#FD),A};выводим звук
        LD A,D     };частота
LOW     ADD A,0    }
        LD D,A     }
        LD A,L     }
HIGH    ADC A,1    }
        LD L,A     }
        ADC A,H    }
        SUB L      }
        LD H,A     }
B_CHAN  LD A,9      ;канал B
        OUT (C),A   ;
        ............;и т. д. для всех звуковых каналов.
        ............;
        ............;
        JP BEGIN
NOT_SMP             ;выставляем задержку равную выполнению }
                    ;что необходимо для того, чтобы не сби-
                    ;вать частоту звука в других каналах,
                    ;если инструмент кончился.
                    ;Аналогично для всех каналов
        JP B_CHAN


  Далее следует процедура, работающая на прерываниях и как я
уже говорил меняющая параметры в плейере. Темп, с которым
будет играть мелодия, выставляется тоже очень просто,
например так:



INT     PUSH AF   ;запомним AF
TEMP    LD A,10   ;счетчик темпа. 50 прерываний в секунду/10
        DEC A     ;уменьшим
        JR Z,OK     ;если ноль, то запустить процедуру
        LD (TEMP+1),A;иначе запомнить счетчик
        POP AF
        RETI         ;выйти из прерывания в плейер
OK      LD A,10
        LD (TEMP+1),A
        .............;пошла процедура


  Вот вроде бы все тонкости я осветил. Далее дело техники. А
написать после этого свой цифровой радактор по-моему - раз
плюнуть. Единственное, что я еще имею вам сказать - необхо-
димо, чтобы плейер и прога на прерываниях работала макси-
мально быстро. Побольше экспериментируйте, и может быть
когда-нибудь вы напишите самый крутой digital редактор на
Спектруме. Ариведерчи.


                               Вишев Алекс/MSD/20.12.99 18:4




Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Объявления - Я всех приветствую и рад встрече с Вами.
ZX+Dendy - возвращение к напечатанному.
Mother Yolpa Gives Birth

В этот день...   21 октября