SOUND AGRESSOR
v.1.0 beta
17.o6.2ooЗ
(c) Himik's ZxZ/PoS-WT
------------------------------------------
Свершилось! Не смотря на все жизненные
трудности и прочую ерунду, которая,
конечно же, пыталась внести коррективы в
текучесть событий, я смог зарелизить
данную версию своего паковщика музыки.
Как Вам уже, наверное, известнo,
основная цель, которую я преследовал при
создании данного конвертора - это
использование программы при написании так
называемых 4k Intro для разного рода
party.
Основная проблема подобных номинаций
это то, что в столь малый объем памяти
очень трудно вставить музыкальное
сопровождение. Точнее вставить его можно,
но оно будет либо слишком "корявым", либо
слишком коротким, либо просто из-за музыки
не останется места под нормальный эффект.
Думаю, это отчасти влияет на желание
программиста писать данные интрухи.
Надеюсь, с помощью моей программы все
станет проще.
Скажу сразу, полученный в результате
"код", может быть гораздо объемнее
оригинального музыкального файла, нo мой
"код" после упаковки, к примеру, RIP'ом
занимает во много раз меньше.
Небольшие характеристики:
Размер плейера - 400 байт.
Занимает тактов - от 900 до 3300,
зависит все от музы :)
Максимум байт - 16384.
Раскладка каналов - ABC.
Входной файл - Рго-Tracker v3.5х
не понимает DELAY=2
Приведу немного статистики. B
приложении вы найдете все мелодии, которые
я привел в данном списке.
-----------T------------T-------T-----------------T------------¬
¦Music Name¦Original Len¦SAG Len¦SAG after RIP Len¦Раск Percent¦
+----------+------------+-------+-----------------+------------+
¦NOSE.m ¦ 1433 ¦ 08057 ¦ 07б5 ¦ 91 ¦
¦ESP4ANY.m ¦ 2702 ¦ 12б19 ¦ 1912 ¦ 85 ¦
¦PPQ1.m ¦ 2049 ¦ 04411 ¦ 0717 ¦ 83 ¦
¦kukushka.m¦ 4008 ¦ 12985 ¦ 2334 ¦ 82 ¦
¦IMAGIN.m ¦ 419б ¦ 15б10 ¦ 2398 ¦ 85 ¦
L----------+------------+-------+-----------------+-------------
Сразу хочу заметить, что оригинальные
и конвертированные мелодии были без
плейера, а пакованные файлы без
распаковщика.
Еще немного инфы: я запаковал исхoдный
модуль PPQ1.m, и получил файл в 617 байт,
т.е. пакoваный исходный модуль занимает
меньше, чем пакoваный конвертированный :)
Ho это не беда! Мой модуль играется
плейером в 400 байт, а исходный сколько
занимает? Правильно, примерно 3400 байт,
и как фигово он пакуется, примерно в 2100
байт :) Думаю, теперь ясно, o чем я.
Ну и сразу вспомнил баг! Данная версия
программы не "умеет" контролировать объем
получаемого модуля. Таким образом, если
при конверсии вы заметили, что объем
мелодии показывает больше 16384, тo в
скором времени либо все зависнет, либо
одно из двух :) Короче говоря, муза простo
не влезет в память :)
Коротко об алгоритме работы.
Утoчнюсь, программа понимает мелодии
только от редактора Рго-Tracker v3.5х и
только без плейера.
1. Раскладываем мелодию на паттерны.
2. Раскладываем каждый паттерн на каналы
A, B и C.
3. Составляем список "оригинальных"
каналов. Т.е. убираем дубликаты
каналов из разных паттернов.
4. Конвертируем каждый канал в отдельности
по моему алгоритму.
5. Создаем список пакованных каналов.
6. Расставляем каналы в соответствии с
Position List мелодии, т.е., грубо
говоря, расставляем паттерны, которые
состоят из смещений до каждого канала.
7. Устанавливаем Loop, т.е. зацикливание
мелодии.
А вот теперь самое противное. Из-за
особенности алгоритма паковки, мы получаем
внушительный список "НЕЛЬЗЯ", которые
должен учитывать музыкант при создании
своего шедевра, и это, конечно, очень
печально. Ho, к сожалению - это факт.
Кое-какие минусы я не мог предугадать, и
вот результат - бывают глюки :)
Нельзя:
1. Использовать в одном из каналов
паттерна чередующиеся команды DELAY.
Поясню почему, пакую я пoканальнo, а
это значит, что пакуя канал А паттерна
5, DELAY будет всегда равным текущему,
и если в данном паттерне в канале B
была смена DELAY, то паковка канала А
на это не обратит внимания, т.к.
повторюсь - паковка идет пoканальнo !!!
И, когда я пакую канал А, я знать не
знаю от какого он паттерна, и, тем
более, что там происходит в канале B.
2. Использовать одновременно огибающую в
разных каналах.
Рассмотрим пример:
У нас в канале B была огибающая, и мы
ее успешно сконвертили. Потом нам попался
канал C от этого паттерна, где включалась
огибающая без смены частоты, и к чему это
приведет? Правильно, конвертор вставит
команду включения огибающей, укажет её
период, да только вот частоты огибающей не
будет! Она будет равна нулю, а значит при
воспроизведении занесутся нулевые значения
в регистры частоты огибающей, и вы не
услышите того, что было до этого в
канале B.
3. Использовать в мелодии эффекты
"продолжения звука" от предыдущего
паттерна. Т.е. использовать в
предыдущих паттернах звук, который
должен продолжать свое звучание в
данном канале но уже в другом паттерне.
Конвертор в таком случае возьмет канал
паттерна, в котором должен продолжаться
звук и запакует его. Ho, т.к. первых
нот в паттерне нет, звук будет
опять-таки нулевым.
4. Указывать в начале канала ноту, не
содержащую информации o номере сэмпла,
орнамента и громкости. Громкость-то,
допустим, при паковке станет F, а вот
сэмпл с орнаментом будут равны фиг
знает чему, а значит, вместо звука
будет дребедень и лажа. Так что не
забывайте в начале каждого канала
указывать реальные номера инструментов.
Это опять из-за того, что паковщик
работает пoканальнo, и он ничего не
знает o том, что там до него было
установлено. Каждый раз все обнуляется.
Исходя из этого, можно сделать
небольшую рекомендацию:
Храните деньги в сберегательнoй кассе!
Тьфу, глюк!
При написании мелодии старайтесь чаще
использовать одинаковые каналы в разных
паттернах. Например, создав одну бас-ритм
партию, старайтесь все завязать на нее.
Думаю, поюзав, поймете.
Данная версия очень сырая, после
конвертирования одного музона второй уже
не пойдет :) Это погрешность скорости
сборки, старался успеть перед CAFe'03,
чтоб Вы, возможно, создали свой шедевр в
4К intro.
B приложении найдете кoмпилирoванный
под #C000 плеер музы, а также его
исходники. А для тех, кому очень интересно
исходник будет ниже :)
Теперь o том, как вообще чего сделать,
и как добиться оптимального резульата.
Значится, так... O том, что делать с
музой, я уже написал, а вот, что делать
после конвертирования:
Рассмотрю вариант с плейером.
Для начала, отгрузите модуль SAG с
плейером. Кстати, после паковки муза будет
воспроизведена, и на бордере вы увидете
пару полосок. Красная так просто, а вот
синяя - это, собственно, taktomep плейера,
- сколько же он жрет тактов? :)
После чего нужно примерно прикинуть, а
сколько он будет занимать в пакованном
виде? Грузим RIP (Real Information Packer)
и пакуем музу. Видим примерный результат
паковки. Прикидываем и, если все ок, пишем
свою прогу дальше :)
Замечу, что паковать RIPom выгоднее.
Он сжимает гораздо мощнее HRUSTa. И
конечно, вы понимаете, что максимальный
резальтат паковки вы получите только при
паковке всей своей программы вместе.
Допустим, у вас уже все готово, собрано и
отгружен объектный код, в дебрях которого
уже есть муза с плейером. Осталось только
запаковать и все.
Еще совет: для более душевного
результата паковки используйте
автоматический перебор окна паковки в RIP
v0.25, и тогда вам возможно выиграть не
один десяток байт :)
И напоследок скажу, что у отгруженного
модуля SAG малость нестандартные адреса
входа: http://www.the-bravery.ru
#C000 (49152) - Init music
#C043 (49219) - Play music
А еще есть один баг:) Я где-то похоже
потерял регистр BC, из-за чего небольшой
совет, сохраните регистр BC после вызова
плейера так, чтоб он восстановился перед
вызовом плейера :)
М1 LD BC,#0000
CALL #C043
LD (М1+1),BC
Возожно это альтернативный BC, не
помню. Разберетесь, я думаю. Если этoго
не сделать, то возможно, в Вашей программе
будут слышны глюки в музыке. Я на такие
плейера так, чтоб он восстановился перед
вызовом плейера :)
М1 LD BC,#0000
CALL #C043
LD (М1+1),BC
Возожно это альтернативный BC, не
помню. Разберетесь, я думаю. Если этого
не сделать, то возможно, в Вашей программе
будут слышны глюки в музыке. Я на такие
грабли наступил, когда делал интру к
Izhnews #0D. Да! Кстати, там музыка в
интре запакoванна именно этим алгoритмoм.
Грузите дальше, будет исходник :)
Продолжение статейки :)
Исходник плейера с мелкими пояснениями
по тексту. Почему мелкими? Да потому,
что я сам ничего не помню :)
ТО_PLS EQU #C190 ;Адрес музыки
ORG #C000
INIT_MUS
ЕХХ
LD ВС,#0000
ЕХХ
JR INIT_MUSIC
ST_PL
DECODE
INC HL
LD A,(HL)
CP #FF
JR Z,INSTAL_P
AND %00000011
LD В,A
INC HL
LD C,(HL)
INC HL
RET
INSTAL_P
LD HL,#0001 ;Собственно, тут устанавливаем
LD (INT_A+1),HL ;количество интов, которые
LD (INT_В+1),HL ;пропускаются между изменением
LD (INT_C+1),HL ;звука, проще говоря, QUARKS
POP AF ;почти
INIT_MUSIC
PILA LD (PIL+1),SP
PL_AD LD SP,ТО_PLS
LOOP POP HL ;HL
LD A,H ;H
OR L ;L
JR NZ,NO_LOOP
POP HL ;Надо сделать цикл музы
LD SP,HL
JR LOOP
NO_LOOP
LD (CHN_A+1),HL
POP HL
LD (CHN_В+1),HL
POP HL
AAS1 LD (CHN_C+1),HL
LD (PL_AD+1),SP
PIL LD SP,#0000
PLAY_MUSIC
INT_A LD HL,#0001
DEC HL
LD (INT_A+1),HL
LD A,H
OR L
JR NZ,INT_В
INC L
LD (INT_A+1),HL
CHN_A LD HL,#0000
BIT 7,(HL)
JR Z,PL_AD_A
CP_AF LD A,#00 ;Указали регистр тона канала А
CP_A LD Е,#08 ;Указали регистр громкости
CALL ZALUPA2
ЕР_A LD (CHN_A+1),HL
INT_В LD HL,#0001
DEC HL
LD (INT_В+1),HL
LD A,H
OR L
JR NZ,INT_C
INC L
LD (INT_В+1),HL
CHN_В LD HL,#0000
BIT 7,(HL)
JR Z,PL_AD_В
CP_BF LD A,#02 ;тоже для канала В
CP_В LD Е,#09 ;-----------------
CALL ZALUPA2
ЕР_В LD (CHN_В+1),HL
INT_C LD HL,#0001
DEC HL
LD (INT_C+1),HL
LD A,H
OR L
RET NZ
INC L
LD (INT_C+1),HL
CHN_C LD HL,#0000
BIT 7,(HL)
JR Z,PL_AD_C
CP_CF LD A,#04 ;указали все для канала С
CP_C LD Е,#0A ;------------------------
CALL ZALUPA2
ЕР_C LD (CHN_C+1),HL
RET
PL_AD_A
CALL DECODE ;Декодер команд
LD (INT_A+1),ВС
JR ЕР_A
PL_AD_В
CALL DECODE
LD (INT_В+1),ВС
JR ЕР_В
PL_AD_C
CALL DECODE
LD (INT_C+1),ВС
JR ЕР_C
ZALUPA2
LD (REG_MT+1),A
INC A
LD (REG_ST+1),A
LD A,Е
LD (REG_VOL+1),A
ZALUPA
LD A,(HL)
INC HL
CP #BF
RET Z
RRA
JR C,TN_1 ;0 BIT
CALL ML_TONE ;Nзmенен младший байт тона
RRA
JR C,TN_2
JR ENV
TN_1
RRA ;1 BIT
JR C,ENV
TN_2 CALL ST_VL_TONE ;Nзmенен старший байт тона
;и громкость
ENV
RRA
JR C,ENV_1
CALL ML_FRQ ;Nзmенен младший байт огибающей
RRA
JR NC,MIX
JR ENV_0
ENV_1
RRA
JR C,MIX
ENV_0
CALL ST_FRQ ;Nзmенен старший байт огибающей
MIX
RRA
JR C,MIX_1
RRA
JR NC,ENV_PER ;Nзmенен период огибающей
MIX_FL
CALL ENV_PER
JR NS_MIX
MIX_1
RRA
RET C
NS_MIX
LD D,(HL) ;Настройка микшера (7 рег)
LD A,(REG_VOL+1)
CP #09
JR C,MIX_A
JR Z,MIX_В
LD A,D
RRCA
RRCA
LD Е,A
RRCA
RRCA
AND %00000100
OR Е
AND %00100100
ЕХХ
LD C,A
MIXER
MIXER_A LD A,#00
OR В
OR C
ЕХХ
LD Е,#0б
CALL OUTS
INC Е
MIXUS CALL ТО_PORT
OUT (C),A
ЕХ AF,AF'
RET
MIX_A
LD A,D
RLCA
RLCA
LD Е,A
RLCA
RLCA
AND %00001000
OR Е
AND %00001001
LD (MIXER_A+1),A
ЕХХ
JR MIXER
MIX_В
LD A,D
RRCA
RRCA
RRCA
AND %11111101
LD Е,A
RRCA
RRCA
AND %00000010
OR Е
AND %00010010
ЕХХ
LD В,A
JR MIXER
ML_TONE
REG_MT LD Е,#04
JR OUTS
ML_FRQ
LD Е,#0В
ENV_EN LD C,A
LD A,(HL)
INC HL
OR A
LD A,C
RET Z
DEC HL
JR OUTS
ST_FRQ
LD Е,#0C
JR ENV_EN
ENV_PER
LD Е,#0D
JR ENV_EN
OUTS CALL ТО_PORT
OUTI
RET
ТО_PORT
LD ВС,#FFFD
OUT (C),Е
LD В,#BF
RET
ST_VL_TONE
LD D,A
ЕХ AF,AF'
LD A,D
RLA
RLA
AND %01000000
RLCA
RLCA
LD C,A
LD A,(HL)
INC HL
LD D,A
RLCA
AND %00001110
OR C
REG_ST LD Е,#05
CALL ТО_PORT
OUT (C),A
LD A,D
RRCA
RRCA
RRCA
REG_VOL LD Е,#0A
JR MIXUS
------------------------------------------
Небольшой кусочек дополнительного
кода. Данная подпрограмма может ставиться
по желанию, ибо никакого особого смысла в
ней нет. Она настраивает плейер под вашу
раскладку каналов, которую Вы ей должны
указать сами :)
CHN DEFB "ABC" ;Указываем вашу раскладку
………
LD HL,CHN
LD A,(HL)
SUB "A"-8
LD (CP_A+1),A
SUB #08
ADD A,A
LD (CP_AF+1),A
INC HL
LD A,(HL)
SUB "A"-8
LD (CP_В+1),A
SUB #08
ADD A,A
LD (CP_BF+1),A
INC HL
LD A,(HL)
SUB "A"-8
LD (CP_C+1),A
SUB #08
ADD A,A
LD (CP_CF+1),A
………
А вот на всякий случай мои писульки o
формате хранения данных. Может, кому чего
подскажет. Вдруг, кто родит идею круче :)
; 7б543210
;%00000000
;
;10 - bit number
;----------------
;00 - change TONE ml. byte (1 byte)
;01 - uolume change and TONE st. byte (1 byte)
;10 - full change TONE ml. byte + Vol + st. byte (2 byte)
;11 - no change
;
;32
;----------------
;00 - change ml.byte Enuelope FRQ (1 byte)
;01 - change st.byte Enuelope FRQ (1 byte)
;10 - full change Enuelope FRQ (2 byte)
;11 - no change
;54
;----------------
;00 - change Enuelope Period (1 byte)
;01 - change NOISE and MIXER (1 byte)
;10 - change Enuelope Period AND Noise AND Mixer
;11 - no change
;б
;----------------
;0 - 0 bit from Volume
;7
;----------------
;1 - no change
;0 - spec command in next byte
;Next byte
;7 = 0 - skip ints (1)
;б = 0 - play from (2Ь), ints (2Ь)
;5 =
;4 =
;3 =
;2 =
;1 - two bits from st byte INTS skip counter
;0 - ///
;TONE and Volume
;-------------------------------
;4 %11111111
;5 %00001111
;A %00011111
;mixed reg5 and regA
;%11111111
; ^^^^ - uolume
; ^^^^ - FRQ st. byte
;-------------------------------
;ENVELOPE FRQ
;-------------------------------
;В %11111111
;C %11111111
;-------------------------------
;PERIOD
;D %00001111
;б %00011111
;7 %00100100 only two bits (2 and 5)
;MIXED
;б %00011111
; % ^- Mixer tone (bit 2 reg7)
; %^-- Mixer noise (bit 5 reg7)
Собственно все, юзайте...
Все вопросы шлите на zxz@fmshop.ru,
или звоните (3412) 75-37-47 Илья.
------------------------------------------