Digital Sounds на Спектруме
music by DNK
(C)PSB SOFTWARE/HALLOWEEN
_______________________________
Peчь в этой статье пойдет o том, как
заставить SPECCY воспроизводить oцифрo-
ванные звуки. В первую очередь эта статья
посвящена тем, у кого есть ковокс, sound-
drive или, на худой конец, AY.
Немного теории...Из школьного курса фи-
зики Вы знаете, что звук представляет со-
бой волну, изменяющуюся по синусoидальнo-
му закону. Амплитуда такой волны опреде-
ляет громкость звука, а частота - его вы-
coty.
Итак, нам нужно устройство, которое мо-
жет превратить волну в аналоговый сигнал
(т.e. сигнал, изменяющийся по напряже-
нию). Это устройство называется ЦАП (Циф-
ро-Аналоговый Преобразователь) или covox.
ЦАПы бывают 8-ми битные, 4-х битные,
10,12,16 и, может быть, еще какие-нибудь
- не знаю. Нас же интересуют только 4-х и
8-ми битные (т.к. 4-х битный ЦАП есть в
AY, а 8-ми битным ЦАПом является ковокс).
8 и 4 бита - очень удобно, потому что для
хранения и передачи данных используется
либо целый байт, либо его половина.
Задача ЦАП установить на выходе напря-
жение от 0 до N (от -n до +n) вольт, где
N определяется типом ЦАПа, но нам это не
важно. Чем выше разрядность ЦАПа, тем ка-
чeствeннee можно воспроизвести звук.
Звуковая волна хранится в цифровых дан-
ных в виде значений от 0 до 255 (0-15 для
AY). За ноль принято 128 (т.e. на самом
деле 0 - это -128, а 255 - это +127). Та-
кая волна называется бeззнакoвoй.
Таким образом, кидая в порт ковокса
значения из тела сэмпла (звука), получаем
на выходе звук. Это можно сделать такой
программкой:
DI ;чтоб ничто не беспокоило нашу программу
LD HL,INS_ADR ;начальный адрес сэмпла
LD BC,INS_END-INS_ADR ;длина сэмпла
LOOP LD A,(HL) ;берем байт из тела сэмпла
OUT (#XX),A ;кидаем его в порт ковокса
;(для пентагона #FB, для скорпа - #DD, см. ниже прим.)
DEFS NN ;заполняем NOP'ами память для задерж-
;ки, попробуйте 20-100.
INC HL ;след.байт в сэмпле
DEC BC ;уменьшаем длину на единицу.
LD A,B ;проверяем ее на ноль
OR C
JR NZ,LOOP ;если еще не весь инструмент проиг-
;рал, то повторяем...
..... ;делаем что надо,
;например EI
RET ;No comments
INS_ADR INCBIN FileName ;подгружаем сэмпл (берем его, к при-
;меру, из библиотеки ред.Instrument)
INS_END ;следующий за инструментом байт.
Вот так, собственно, воспроизводится
звук. Ho что нам это дает? Мы ведь не мо-
жем заставить компьютер сказать какое-ни-
будь слово. А вот в PC'шных играх... А
что? Берем PC'шные *.WAV файлы и скачива-
ем их в TR-DOS. Проигрывание wav-файлов
практически ничем не отличается от обыч-
ного сэмпла. У wav-файла есть заголовок.
Причем он бывает разной длины. Вот те
данные, которые мне удалось "выудить":
#00-#03 string "RIFF"
#04-#07 length_of_something
#08-#0F string "WAVEmft "
#10-#17 ----------
#18-#19 rate, kHz
#1A-#1В ----------
#1C-#1D rate, kHz
#1E-#21 ----------
#22 digits, bit
#23 ----------
#24-#27 strings "data" or "fact"
#28-#2В sound_length length_of_something
#2C-#2F WAVE! string "data"
#30-#33 WAVE! sound_length
#..-#.. WAAAAVEEEE!
Так как описания заголовка wav-файла у
меня нет, я не знаю, какая информация
скрывается за прoчeрками. Rate (частота
оцифровки) встречается два раза, но как
показала практика, верный из них второй.
Rate может быть 44100, 22050, 11025, 8000
кГц. Это частота, с которой из АЦП (Ана-
лого-Цифровой Преобразователь) брались
данные. Rate также можно измерять в [байт
в секунду]. Digits показывает, скольки
битный звук. Далее по обстоятельствам:
если с #24-#27 находится слово "data", то
с #28-#2В находится четыре байта длины
звука (в Low-end format, т.e. как на
Спектруме - сначала самый младший байт),
затем само тело звука. Если же с #24-#27
находится "fact", то далее длина непонят-
но чего, "data", длина звука и, наконец,
сам звук. Заголовок в этом случае занима-
ет на 8 байт больше. После самого звука
могут идти текст и графика (так уж приду-
мал Microsoft).
Итак, проигрывание wav'ов отличается от
обычных сэмплов фиксированным количеством
NOP'ов в нашей программе. Это количество
NOP'ов зависит как от Rate, так и от час-
тoты работы компа (количество тактов за
прерывание). Его (количество) можно рас-
читать так:
7+11+4*X+6+6+4+4+12=50+4*X - количество
тактов за один цикл
программы (4*X -
такты, занимаемые
NOP'ами; при жела-
нии можно использо-
вать другие коман-
ды, но расчет может
получиться другим).
TPI*50 - количество тактов
Z80 в секунду (TPI
- Tacts Per Inter-
rupt); TPI можно
измерить с помощью
Jemmini comander
или какой-нибудь
программы.
Rate*(4*X+50) - количество так-
тов, нужное для вы-
вода Rate байт
(т.e. 8000..44100
байт), т.e. то ко-
личество байт, ко-
торое должно про-
звучать в секунду.
T.к. Rate измеряется [байт в секунду],
получаем:
Rate*(4*X+50)=TPI*50
Используя знания по математике, получа-
ем то, что хотели:
25*(TPI-Rate)
X=INT -------------
2*Rate
Вот так можно вычислить количество
NOP'ов. Однако следует учесть, что у раз-
ных моделей Спектрумов бывают разные TPI.
Поэтому, если Вы решили делать программу
со своим голосом, то лучше определяйте
TPI программно.
Кстати, файлы *.WAV бывают разные: сте-
рео, моно, в формате PCM, ADPCM и т.п.
Сказанное выше относится к моно *.WAV
файлам в формате PCM (если мне не изменя-
ет RAM)...
Еще в моей практике встречались файлы
*.AIF. Когда я попытался проиграть его
таким образом, у меня ничего не вышло.
Анализируя заголовок, я увидел, что длина
файла записана в Hi-end формате, т.e. со
старшим байтом с начала. Я подумал, что
это Амижный файл (а может и правда Амиж-
ный?), но потом прочитал в книге, что это
файлы "обычные для Apple Computer". Дело
в том, что данные в таких файлах содер-
жатся "со знаком" (signed sample), то
есть в виде чисел от -128 до +127 (1 -
это 1, а -1 - это 255 и т.д.). Как же нам
привести информацию к нужному виду? Надо
просто "проксорить" данные на #80 (проще
говоря - поменять знак). Это можно сде-
лать прямо перед OUT'ом:
.....
LOOP LD A,(HL) ;берем байт
XOR #80 ;меняем знак
OUT (#XX),A ;кидаем его куда надо
.....
Ну вот. Теперь Вы можете озвучивать ва-
ши программы. Интересно так же "химичить"
со звуками (делать рeвeрбeрацию и т.п.).
Можно смешать несколько звуков. Это дела-
ется так:
.....
LOOP LD A,(DE) ;берем байт из сэмпла #1
ADD A,(HL) ;складываем его с байтом из сэмпла #2
;(возьмите какой-нибуд голос,поставьте DE
;на начало, а HL попробуйте поставить на
;2000 байт подальше DE, BC уменьшите на
RRA ;2000) делим полученное на 2 (если проще,
;то находим среднее арифметическое).
OUT (#XX),A ;кидаем куда надо
.....
Хорошо, на ковокс мы научились выдавать
звуки, а как же быть с AY? C ним пoслoж-
нее. Во-первых, в AY 4-х битный ЦАП, а
во-вторых при увеличении N (ампл.) на
единицу, сигнал на выходе увеличивается
не на 1/16 (!). Поэтому нужно преобразо-
вать звук из 8 бит в 4 да еще по специ-
альной таблице. Делается это следующим
образом:
.....
LD BC,#FFFD ;для начала нужно установить 8,9 или 10
LD A,8 ;регистр AY'а
OUT (C),A
LD D,HB_TABLE ;в регистр D зано сим старший байт нашей
;таблицы (адрес должен быть круглый,
;т.е. #8000, #7400, #8300 и т.п.)
LOOP LD E,(HL) ;после этой команды в DE находится
;адрес в таблице, в котором лежит нужное
;нам число
LD A,(DE) ;берем это число
OUT (#FD),A ;кидаем его в AY
.....
HB_TABLE DEFS 4,#A0 ;эта таблица была взята из AY_PLAYER'а
DEFS 5,#A1 ;редактора SAMPLE TRACKER v2.1
DEFS 5,#A2
DEFS 5,#A3 ;размер таблицы 25б байт
DEFS б,#A4
DEFS 7,#A5 ;следует заметить, что данный прием
DEFS 12,#Аб ;не работает на "старых" скорпах из-за
DEFS 12,#A7 ;слишком умной дешифрации;
DEFS 8,#A8 ;чтобы все работало, надо вместо чисел
DEFS 1б,#A9 ;#A0..#AF записать просто 0..15, а в
DEFS 24,#AA ;программе сделать правильный вывод в
DEFS 17,#AB ;AY: Ld bc,#bffd; out (c),а...
DEFS 23,#AC
DEFS 32,#AD
DEFS 39,#AE
DEFS 41,#AF
Можно также обойтись без таблицы: oтб-
pocutb младшие 4 бита, но качество звука
будет значительно хуже.
.....
LOOP LD A,(HL) ;берем байт
AND #F0 ;оставляем только 4 старших бита
RRCA ;перемещаем их ма место младших
RRCA
RRCA
RRCA
OR #A0 ;получаем байт #AX (опять же для скорпов
;требуется переделка)
OUT (#FD),A ;кидаем его в AY
.....
Ну вот, я Вам рассказал почти все, что
знаю сам. Если Вы все поняли, то ничто не
мешает Вам "похимичить" со звуками, ну а
если у Вас есть еще и АЦП (и не один(?)),
то тут можно фантазировать до бeскoнeч-
ности (наложение голоса с эхом на какой-
нибудь звук (голос на аранжировку) в RE-
ALTIME и т.п.).
Разумеется, нельзя ограничиваться толь-
ко этим материалом, т.к. я писал его, ос-
нoвываясь на личном опыте, и, возможно,
кто-нибудь дополнит или/и продолжит эту
тему.
Some info: ZX-SPECTRUM - это вообще та-
кая машина, на которой практически нет
стандарта (это я про Pentagon, Scorpion,
Кау, Profi и т.д.): расширение памяти
сделано по разному, ROM - разные, TPI...
Ковокс тоже не исключение. На Пентагоне
его обычно цепляют на порт #FB (ZX-Lprint
III interface), на Скорпе вместо #FB -
#DD, а у кого-нибудь еще какой-нибудь
порт. C таким же успехом можно использо-
вать Soundrive и General Sound, только их
нужно инициализировать. Для лучшего пони-
мания см. таблицу:
+------------------+---------------+-------------+
| название железа | инициализация | порт вывода |
+------------------+---------------+-------------+
| Pentagon's COVOX | ------------- | #FB |
+------------------+---------------+-------------+
| Scorpion's COVOX | ------------- | #DD |
+------------------+---------------+-------------+
| Profi COVOX | out (#7F),#80 | #3F #5F |
+------------------+---------------+-------------|
| Flash Soundrive | out (#3F),#80 | #0F #1F |
| | out (#7F),#80 | #4F #5F |
+------------------+---------------+-------------+
| General Sound | out (#BB),#0E | #B3 |
+------------------+---------------+-------------+
Объясняю для тех, кто не совсем разoб-
рался. В самом начале программы Вы должны
проинициализировать устройство, на кото-
рое будут передаваться данные (если это
обычный ковокс, то ничего делать не на-
до). Затем в нашей программе вместо #XX
ставите указанный в таблице порт. Напри-
мер:
DI
LD A,#80 ;инициализируем
OUT (#3F),A ;SOUNDRIVE
OUT (#7F),A
LD HL,SMP_ADR
LD BC,SMP_LEN
LOOP LD A,(HL)
OUT (#0F),A ;вместо #0F могут быть #1F, #4F, или #5F
DEFS 28 ;или любое другое число
INC HL
DEC BC
LD A,B
OR C
JR NZ,LOOP
EI
RET
General Sound тоже может работать в ре-
жиме ковокса, но у него дело со звуками
обстоит побогаче. Поэтому лучше использо-
вать возможности GS работы со звуками,
чем ковокс. А уж если Вы выбираете ко-
bokc, то в программе не помешает настрой-
щик, но это уже дело Ваше, может быть Вы
и делать ничего не собираетесь...
Вот, собственно, и все. Я надеюсь Вы
все поняли из вышесказанного, и, может
быть, кто-то расскажет, как делать наво-
рoчeнныe эффекты со звуками...
With best wishes, PSB
of Halloween.
_______________________________
Other articles: