ZX Forum #04
19 ноября 1997

Мир звуков Спектрума - глава 4.6: Обработка внешних сигналов - оцифровка.

<b>Мир звуков Спектрума</b> - глава 4.6: Обработка внешних сигналов - оцифровка.
     4.6. Обработка внешних сигналов

   ZX-Spectrum предоставляет программистам
довольно  интересную  возможность - считы-
вать и сохранять в памяти звуковые  сигна-
лы, подаваемые на его магнитофонный  вход.
Эти фрагменты  можно воспроизводить с раз-
личной  скоростью, что,  несомненно, очень
интересно.  Правда,  качество  полученного
таким образом звука оставляет желать  луч-
шего,  а  его  максимальная   длительность
ограничивается несколькими  десятками  се-
кунд (просто-напросто кончаются 48K ОЗУ!)
   Но перейдем от слов к делу. Вот подпро-
грамма, записывающая звук в память:
1415.
 10            DI                 ; запрет прерываний
 20            LD      HL,25000   ; HL=адрес сохранения звука
 30            LD      DE,35000   ; DE=длительность звука
 40  LOOP1     LD      B,8        ; B=счетчик битов
 50  LOOP2     SLA     (HL)       ; скроллинг значения в памяти
 60            IN      A,(254)    ; ввести значение из порта 254
 70            BIT     6,A        ; проверить бит магнитофона
 80            JR      Z,NOSIGN   ; если 0, то перейти на NOSIGN
 90            SET     0,(HL)     ; установить бит D0 в памяти
100  NOSIGN    LD      C,3        ; C=задержка
110  PAUSE     DEC     C          ; C=C-1
120            JR      NZ,PAUSE   ; если C<>0, то цикл
130            DJNZ    LOOP2      ; продолжить цикл обработки
                                    байта
140            INC     HL         ; HL=HL+1
150            DEC     DE         ; DE=DE-1
160            LD      A,D        ; DE=
170            OR      E          ;    0 ?
180            JR      NZ,LOOP1   ; если нет, то цикл
190            EI                 ; разрешение прерываний
200            RET                ; возврат
2
   А это подпрограмма воспроизведения:
1415.
 10            DI                 ; запрет прерываний
 20            LD      HL,25000   ; HL=адрес сохраненного звука
 30            LD      DE,35000   ; DE=длительность звука
 40            NOP                ; резерв
 50            XOR     A          ; A=цвет бордюра (0)
 60  LOOP3     LD      B,8        ; B=счетчик битов
 70  LOOP4     AND     239        ; сброс бита D4 регистра A
 80            RLC     (HL)       ; скроллинг данных через флаг
                                    CY
 90            JR      NC,NOSGN   ; если флаг CY=0, то перейти
                                    на NOSGN
100            OR      16         ; установка бита D4 регистра A
110  NOSGN     OUT     (254),A    ; вывод A в порт 254
120            LD      C,3        ; C=задержка
130  PAUS2     DEC     C          ; C=C-1
140            JR      NZ,PAUS2   ; если C<>0, то цикл
150            DJNZ    LOOP4      ; продолжить цикл обработки
                                    байта
160            INC     HL         ; HL=HL+1
170            LD      C,A        ; сохранение A
180            DEC     DE         ; DE=DE-1
190            LD      A,D        ; DE=
200            OR      E          ;    0 ?
210            LD      A,C        ; восстановление A
220            JR      NZ,LOOP3   ; если DE<>0, то цикл
230            EI                 ; разрешение прерываний
240            RET                ; возврат
2
   Адреса данных и их длина должны  совпа-
дать в этих двух  подпрограммах.  Обратите
также внимание на то, что  они  используют
35 Кб памяти  с адреса  25000.  Поэтому  в
этой  области  ОЗУ  не должно быть никаких
данных. Сами подпрограммы тоже должны рас-
полагаться где-нибудь в другом месте.  Оп-
тимальным вариантом будет  такой:  перену-
меруйте строки второй  подпрограммы  начи-
ная с 210 и с шагом 10 (если Вы  работаете
в GENS4 - введите для этих  целей  команду
N210,10); соедините  то, что получилось, с
первой подпрограммой и  введите  следующие
строки:
1415.
  7            ORG    24900
 20            LD     HL,BUFFER
 30            LD     DE,LENGTH
220            LD     HL,BUFFER
230            LD     DE,LENGTH
450  LENGTH    EQU    35000     ; LENGTH=35000
460  BUFFER    NOP              ; здесь располагается буфер
2
   Проследите также, чтобы ассемблер  рас-
полагался приблизительно с адреса 40000. В
любом случае он будет стерт из памяти  при
вызове подпрограммы ввода  звука.  Поэтому
не стоит вызывать ее из обреченного ассем-
блера.
   Еще одно важное замечание: при  исполь-
зовании  этих  подпрограмм  следите, чтобы
выражение  BUFFER+LENGTH  не  было  больше
65535, иначе часть звуковых данных  просто
не  запишется, а  вместо  них  Вы услышите
шум.
   В строке 100 первой  подпрограммы  и  в
строке 120 второй в  регистр  C  заносится
задержка между выборками данных. Если  эти
два значения  равны, то  звук  будет  вос-
производиться с реальной  скоростью.  Если
второе число меньше первого, то  звук  бу-
дет ускорен, а  если  больше  -  замедлен.
Причем, чем меньше задержка в  подпрограм-
ме ввода, тем выше качество вводимого сиг-
нала, но меньше его длительность.
   Байт резерва в подпрограмме воспроизве-
дения  предназначен  для   переворачивания
звука, то есть проигрывания его с конца на
начало. Для включения этого  эффекта  надо
заменить операцию NOP в этом байте на  ADD
HL,DE, а INC HL в строке 160 на DEC HL.
   Существует и другой способ записи  зву-
ка. Он основан на  подсчете  звуковых  им-
пульсов. Перед первым способом он не имеет
никаких  особых  преимуществ, за  исключе-
нием возможности  незначительного  пониже-
ния уровня шума. Вот подпрограмма, записы-
вающая звук вторым способом:
1415.
 10            DI                 ; запрет прерываний
 20            LD      HL,25000   ; HL=адрес сохранения звука
 30            LD      DE,35000   ; DE=длительность звука
 40            LD      BC,511     ; C - буфер, B - счетчик
 50  LOOP1     IN      A,(254)    ; ввод значения из порта 254
 60            EXX                ; смена набора регистров
 70            LD      B,1        ; B=задержка
 80  PAUSE     DJNZ    PAUSE      ; задержка
 90            EXX                ; смена набора регистров
100            BIT     6,A        ; проверить бит магнитофона
110            LD      A,0        ; A=0
120            JR      NZ,SIGN    ; если бит D6=1, то перейти
                                    на SIGN
130            DEC     A          ; A=255
140  SIGN      CP      C          ; A=C (предыдущему значению) ?
150            JR      NZ,WRITE   ; если нет, то перейти на
                                    WRITE
160            INC     B          ; B=B+1 (счетчик импульсов)
170            JR      NZ,LOOP1   ; если B<>0, то цикл
180  WRITE     DEC     B          ; B=B-1
190            JR      NZ,POKE    ; если B<>0, то перейти на
                                    POKE
200            LD      B,2        ; B=2
210            CPL                ; инвертирование A
220            LD      C,A        ; C=A
230            JR      LOOP1      ; перейти на LOOP1
240  POKE      INC     B          ; B=B+1
250            LD      (HL),B     ; запись значения в память
260            LD      B,1        ; B=1
270            LD      C,A        ; C=A
280            INC     HL         ; HL=HL+1
290            DEC     DE         ; DE=DE-1
300            LD      A,D        ; DE=
310            OR      E          ;    0 ?
320            JR      NZ,LOOP1   ; если нет, то цикл
330            EI                 ; разрешение прерываний
340            RET                ; возврат
2
   В строке 20 задается  адрес  сохранения
звука, в строке 30 - длительность вводимо-
го звука, в строке 70 - задержка между вы-
борками сигнала.
   Строки 180 - 240 обеспечивают шумопони-
жение.
   В регистре C сохраняется значение  пре-
дыдущей выборки, а регистр B служит  счет-
чиком одинаковых выборок.
   А вот подпрограмма воспроизведения:
1415.
 10            DI                 ; запрет прерываний
 20            LD      HL,25000   ; HL=адрес сохраненного звука
 30            LD      DE,35000   ; DE=длительность звука
 40            NOP                ; резерв
 50            XOR     A          ; A=цвет бордюра (0)
 60  LOOP2     LD      B,(HL)     ; B=очередная длительность
 70  LOOP3     OUT     (254),A    ; вывод A в порт 254
 80            EXX                ; смена набора регистров
 90            LD      B,1        ; B=задержка
100  PAUS2     DJNZ    PAUS2      ; задержка
110            EXX                ; смена набора регистров
120            CALL    124        ; компенсационная
130            BIT     0,(HL)     ;   задержка
140            DJNZ    LOOP3      ; цикл
150            LD      B,(HL)     ; B=текущая длительность
160            DEC     B          ; B=
170            INC     B          ;   0 ?
180            JR      Z,CONT     ; если да, то перейти на CONT
190            XOR     16         ; инвертирование бита D4
200  CONT      INC     HL         ; HL=HL+1
210            DEC     DE         ; DE=DE-1
220            LD      B,A        ; сохранение A
230            LD      A,D        ; DE=
240            OR      E          ;    0 ?
250            LD      A,B        ; восстановление A
260            JR      NZ,LOOP2   ; если DE<>0, то цикл
270            EI                 ; разрешение прерываний
280            RET                ; возврат
2
   В строке 20 задается адрес  сохраненно-
го звука, в строке 30 - его  длительность,
а в строке 90 - задержка  между  выборками
(она же - скорость воспроизведения).
   Байт резерва, как и  раньше, предназна-
чен  для  обратного  воспроизведения.  Для
включения  этого  эффекта  надо   заменить

операцию NOP в этом байте на  ADD HL,DE, а
INC HL в строке 200 на DEC HL.
   Строки 120 и 130 нужны только для  вре-
менной синхронизации с подпрограммой запи-
си звука (по адресу 124 находится  команда
RET).
   Все сказанное относительно задержки ме-
жду выборками и распределения  памяти  для
подпрограмм,  использующих  первый  способ
записи, справедливо и для подпрограмм, ис-
пользующих второй способ.
   Особенностью подпрограмм  второго  типа
является то, что длительность записываемо-
го звука зависит не только от объема выде-
ленной памяти, но и от самого  звука.  Чем
меньше перепадов  уровней  в  записываемом
звуке (иными словами - чем меньше его сре-
дняя частота), тем  более  продолжительный
звук можно записать. Например, если  запи-
сывать одну "тишину", то памяти хватит  на
несколько минут!
   Вы можете произвольно  менять  адрес  и
длину  запоминаемого  звука, но  при  этом
необходимо быть предельно осторожным и  не
испортить жизненно важные области ОЗУ, та-
кие как стек или системные переменные бей-
сика.
   Звук, записанный этими  подпрограммами,
можно сохранить на ленте или диске  с  по-
мощью  обычных  команд записи, а затем за-
гружать по мере надобности.
   Так как даже не очень длинный  звуковой
фрагмент занимает в  памяти  много  места,
возникает естественное желание  как-нибудь
его сократить.  Спешу Вас обрадовать - это
возможно!  Звуковые  данные  очень  хорошо
компрессируются по любому  алгоритму.  Для
этого  можно  использовать  даже  экранные
компрессоры. Неплохо было  бы  их  немного
модифицировать для  такого  использования,
но, если Вы  не сможете  это  сделать, дам
несколько советов. Во-первых, без  измене-
ния компрессора можно  сжимать  только  те
файлы, размер  которых  меньше  или  равен
6912 байтам  (если  какой-либо  компрессор
отказывается принимать файлы с длиной  от-
личной от 6912 б., то дополните их до дан-
ного  размера  нулями).  Во-вторых, обычно
компрессоры при распаковке картинки  поме-
щают ее прямо в  область  экрана.  Поэтому
придется данные  перемещать  оттуда  в  их
"родной" адрес. Это можно  сделать  с  по-
мощью следующей подпрограммы:
1415.
 10            LD      HL,16384   ;
 20            LD      DE,16385   ; очистка
 30            LD      BC,6911    ;
 40            LD      (HL),L     ; экрана
 50            LDIR               ;
 60            CALL    DECOMP     ; вызов декомпрессора
 70            LD      HL,16384   ; HL=откуда перемещать
 80            LD      DE,ADDR    ; DE=куда перемещать
 90            LD      BC,LENGTH  ; BC=сколько перемещать
100            LDIR               ; перемещение данных
110            CALL    3435       ; вызов подпрограммы CLS
120            RET                ; возврат
2
   Данные будут на экране  такое  короткое
время, что Вы, скорее  всего, этого  и  не
заметите (при достаточно быстрой процедуре
декомпрессии).
   И в заключение приведу текст  программы
на бейсике, загружающей и  воспроизводящей
звук с оптимальными параметрами:

   10 CLEAR VAL "24899": PRINT "Wait please..."
   20 FOR A=VAL "24900" TO VAL "24972": READ D: POKE A,D: NEXT A
   30 CLS: PRINT "Press any key, then speak...": PAUSE NOT PI
   40 CLS: RANDOMIZE USR VAL "24900"
   50 CLS: PRINT "Press any key to replay...": PAUSE NOT PI
   60 CLS: RANDOMIZE USR VAL "24934": GOTO VAL "30"
   70 DATA 243,33,141,97,17,114,158,6,8,203,38,219,254,203,119,
           40,2,203,198,14,1,13,32,253,16,239,35,27,122,179,32,
           231,251,201
   80 DATA 243,33,141,97,17,114,158,0,62,7,6,8,230,239,203,6,48,
           2,246,16,211,254,14,1,13,32,253,16,239,35,27,79,122,
           179,121,32,229,251,201

   Если Вы захотите включить воспроизведе-
ние "наоборот", вставьте в  эту  программу
следующую строку:

   45 POKE VAL "24941",VAL "25": POKE VAL "24963",VAL "43"

   Для отключения  этого  эффекта  удалите
данную строку и перезапустите программу.
   Непривычная запись чисел в  этой  прог-
рамме приводит  к  экономии  памяти.  Так,
выражение "24900" занимает 11 байт, а "VAL
"24900"" - только 8  ("NOT  PI"  равняется
нулю).



Другие статьи номера:

Help - Описание оболочки электронного издания "ZX-FORUM 4".

Секреты успешного дизайна - глава для книги "Дизайн Ваших программ"

Экранные эффекты - Бегущая строка из R-Type.

Экранные эффекты - гашения экрана из Zynaps.

Экранные эффекты - "сворачивание" экрана из Comando Tracer.

Экранные эффекты - плавное "затухание" экрана из Сommando Tracer.

Экранные эффекты - модификация символьного набора для получения оригинального стилизованного шрифта из игры Rockstar.

Экранные эффекты - "выбегающая строка" из игры Rockstar.

Экранные эффекты - "наливающийся" экран из игры Rockstar.

Экранные эффекты - сложный многоступенчатый эффект из игры Bubbler.

Новые 40 лучших процедур - скроллинг экрана, слияние двух картинок, инвертирование экрана, поворот символов, замена атрибутов, заливка замкнутого контура, вычисление адресов в экране, копирование части экрана и т.д.

Технология спрайтов - часть 1: введение.

Технология спрайтов - часть 2: охота на спрайты (поиск и выдирание).

Технология спрайтов - часть 3: форматы спрайтов.

Технология спрайтов - часть 4: форматы спрайтов с маской.

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

Технология спрайтов - часть 6: подготовка данных к печати.

Технология спрайтов - часть 8: печать спрайтов (координаты заданы в знакоместах).

Технология спрайтов - часть 9: печать спрайтов (координаты заданы в пикселях).

Технология спрайтов - часть 10: обзор программ для работы со спрайтами и графикой.

Мир звуков Спектрума - глава 1: Физика звука.

Мир звуков Спектрума - глава 2: Оператор BEEP, Создание эффектов на BEEPе, Создание музыки на BEEPе.

Мир звуков Спектрума - глава 3: Как получается звук (устройство BEEP'ра и способы звукоизвлечения).

Мир звуков Спектрума - глава 4: Программирование звука на ассемблере.

Мир звуков Спектрума - глава 4.1: Программирование звуковых эффектов - Тон, Шум, Комплексы эффектов.

Мир звуков Спектрума - глава 4.2: Программирование звуковых эффектов - Управление громкостью.

Мир звуков Спектрума - глава 4.3: Программирование звуковых эффектов - Управление тембром.

Мир звуков Спектрума - глава 4.4: Программирование звуковых эффектов - Программирование музыки.

Мир звуков Спектрума - глава 4.5: Программирование звуковых эффектов - Многоголосые мелодии (полифония).

Мир звуков Спектрума - глава 4.6: Обработка внешних сигналов - оцифровка.

Мир звуков Спектрума - глава 4.7: Обработка внешних сигналов - Реверберация.

Мир звуков Спектрума - глава 4.8: Синтезирование речи.

Мир звуков Спектрума - глава 4.9: воспроизведение звука на прерываниях.

Мир звуков Спектрума - глава 5: Оператор PLAY для музыкального сопроцессора AY- 3-8910 (AY-3-8912).

Мир звуков Спектрума - глава 5.1: Создание эффектов оператором PLAY.

Мир звуков Спектрума - глава 5.2: Создание музыки на PLAYе.

Мир звуков Спектрума - глава 6.1: описание регистров музыкального сопроцессора AY- 3-8910 (AY-3-8912).

Мир звуков Спектрума - глава 6.2: Программирование эффектов и музыки под музыкальный сопроцессор AY- 3-8910 (AY-3-8912).

Мир звуков Спектрума - глава 7: Обзор программного обеспечения ZX-Spectrum для создания звуков и музыки.

Мир звуков Спектрума - глава 7.1: Редактор звуковых эффектов SUPER SOUND.

Мир звуков Спектрума - глава 7.2: Музыкальный редактор Wham the Music Box.

Мир звуков Спектрума - приложения 1, 2: листинги звуковых эффектов SUPER SOUND'а, советы по использованию ассемблера.


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

Похожие статьи:
Fun - история как Slip/Ottodix познакомился с DemiChron со Владивостока.
От авторов - Первоапрельские приколы в номере.
VIRUS - ...наших бьют! Вот, дожились! Месяца три уже, как с моими дисками происходит неладное.
Обмен опытом - Управляющие символы и последовательности управляющих символов в принтерах стандарта Epson.
Программирование - Стрелочка.

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