Из газеты MSD #12, Уфа, 9 июля 2000 ПОСЛУШАЕМ Вишев Алекс/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