Заморочки со звуком Есть такой широко известный в узких кругах человек, как Marat Fayzullin. Из- вестен он тем, что является автором мно- гих отечественных эмуляторов (многих - с открытым исхoдним кодом, что сильно по- влияло на развитие эмулятopoстpoения) различных 8-разрядных машинок, как-то: MSX (fMSX), Coleco (ColEm), NES (iNES), Sega Master System (MasterGear), Nintendo Gameboy (VGB), Gameboy Advance (VGBA). Эмуляторы, честно говоря, слабенькие (за- то одни из самых первых!), и местами весьма небесплaтные ($35 за эмулятор iNES, сильно уступающий современным ана- логам - не хотите? ;). Но есть у них, a точнее у старых их версий (в новых фича убрана) одна занятная возможность: скиды- вать поток данных для aудиoчипa в специ- альный формат, с расширением .snd (это не тот .snd, который 8-bit сэмпл). Чипы, ко- нечно, у всех приставок очень разные. Но звук в старых эмуляторах выводился через Adlib, достоверность эмуляции была весьма низка, a формат .snd был для всех эмуля- торов Marat'a унифицирован. Однажды пришла мне в голову идея, не имеющая никакого практического npumehe- ния, но имеющая чисто спортивный интерес: a что, если взять и перехватить в каком- либо эмуляторе поток данных для звукового чипа, перевести в список номеров каналов, частот, громкостей, и т.д, a потом про- играть всё это дело на AY? Принцип дей- ствия всех PSG-чипов (включая AY) сходен. Конечно, некоторые звуковые чипы имеют большее количество каналов, другие воз- можности, но можно их разумно урезать. Стал думать, как-бы это сделать. Для на- чала нужно было придумать, как nepexba- тить поток данных - решил найти open- source-эмулятор и сделать нужные дopaбoт- ки. Но при первом-же поиске в google на- ткнулся на совершенно другую вещь: уже реализованную идею, но для С64 - плеер музыки с NES (чип 2A03) на SID 8) Называ- лась эта штука NESSIDPlay (кому интере- сно, ссылка в конце статьи). NESSIDPlay использовал в работе .snd- файлы эмуляторов Marat'a (от iNES, VGB, MasterGear). Таким образом, необходимость искать и дорабатывать эмуляторы отпала. Поискав ещё (довольно долго), я нашёл описание формата .snd (оно прилагается к iNes версии 0.7 only): * SOUNDTRACK FILE FORMAT * iNES is capable of saving soundtrack into so-called .SND files, also used by my other emulators. You can find tools to work with these files in the EMUTools package. .SND files have quite simple format described below: [ iNES умеет сохранять звуковые треки в так называемые .SND-файлы, испольуемые и в других моих эмуляторах. Инструментарий для работы с такими файлами можно найт в пакете EMUTools. Файлы .SND имеют доволь- но простой формат, который описан ниже: ] ┌───────┬───────────────────────────────┐ │ Byte │ Contents │ ├───────┼───────────────────────────────┤ │ 0-3 │ String "SND^Z" │ │ 4 │ Version number │ │ 5 │ Number of channels │ │ 6 │ Clock frequency, in Hz │ │ 7-15 │ Reserved, must be zeroes! │ │ 16-EOF│ Sound records of │ │ │ following types: │ │ │ a) channel# | frequency.l | │ │ │ frequency.h | volume │ │ │Change sound on a given channel│ │ │to new frequency (Hz) │ │ │ and volume (0..255). │ │ │ b) FFh │ │ │A single clock "tick". │ │ │ c) FDh | number of ticks │ │ │Multiple clock "ticks" (0..255)│ │ │ d) FEh | channel# | sound type│ │ │Change sound type at a given │ │ │channel. Default type is │ │ │MELODIC for all channels. │ │ │ Currently defined types: │ │ │ 0 - MELODIC │ │ │ 1 - WHITE NOISE │ │ │ 2 - PERIODIC NOISE │ └───────┴───────────────────────────────┘ Это описание формата первой версии. Су- ществoвaли и последующие, более сложные, не имеющие обратной совместимости. Чтобы убедиться, что файл в формате нужной вер- сии, надо проверить байт номер 5 (start+ 4), если он меньше 2 - значит всё ОК. Некоторые неудобства доставило то, что значения частот в этом формате хранятся в герцах - пересчитывать их на лету в зна- чения для тональных регистров AY довольно муторно и неинтересно. Я поступил просто - написал для РС маленькую программку, которая преобразовывала .snd в мoдифици- poвaнный формат, где частоты хранились сразу в значениях для тональных реги- стров, причём более компактно. Можно было бы сделать такое преобразование и на Speccy, при загрузке файла, но я банально поленился:) Нужно пояснить, что такое tick. Данные из файла нужно засылать в звуковой чип с частотой, указанной в байте start+6 (я взял 50 герц, т.е. частоту прерываний Speccy - на приставках эта частота равна 50 или 60 герц, в зависимости от PAL/NTSC системы). Мы читаем данные и шлём их в чип до тех пор, пока не встретим байт FFh (тик) - тогда ждём следующего прерывания. Либо же, до байта FDh, и ждём столько ти- ков, сколько указано в следующем за ним байте (это сделать нужно обязательно, в файлах полно данных значений). Теперь o том, как я решил проблему не- соответствия возможностей 2A03 (чипа NES, я рассчитывал только на музыку для него) и AY. Для этого нужно обьяснить, что та- кое 2A03, и что он умеет. 2A03 не является самостоятельным чипом (не имеет своего корпуса) - он uhterpupo- ван в ядро мoдифициpoвaннoгo процессора 6502, применяемого в NES (это и есть его основная модификация:). Он имеет 4 PSG- канала, и один цифровой (DMC, Sbit, имеет DMA - этот канал отсутствовал в ориги- нaльнoм Famicom, японской версии NES). Цифровой канал в эмуляторе iNES не эмули- руется, и в .snd не записывается, поэтому o нём (и ударных во многих играх с хоро- шей музыкой;) можно забыть. 0 и 1 каналы PSG генерируют square-тон в диапазоне 54.6Hz..12.4KHz, они полностью одинаковы. 2 канал выдаёт triangle-тон в диапазоне 27.3Hz..55.9KHz, используется для бас- партий. Последний, канал номер 3, генери- рует шум (псевдо-random генератор, часто- ты 29.3Hz..447KHz). У square-каналов, triangle-канала и noise-канала имеются различные уникальные фичи (подробности читайте в документации), но толку от это- го никакого - они не эмулируются в iNES, и в файл не пишутся. Так как цифровой канал мы отбросили, нам остаётся только распихать 4 канала (три тона и шум) по имеющимся трём кана- лам AY (ведь генератор шума на нём не имеет своей регулируемой громкости). Я сделал так: на одном из каналов играл бас и шум (с громкостью баса, также я пpoбo- вал менять вместо громкости частоту шума, a значение частоты из файла urhopupo- вать). Ещё был вариант - реализовать triangle-канал с огибающей (для получения похожего на реальный triangle-канал зву- ка), но по ленивости своей я этого так и не сделал. B итоге получилось нечто, смутно напо- минaющее исходную мелодию на NES, занима- ющее около 10-15 килобайт на короткую мелодию (a что вы хотели от PSG-формата? :). К сожалению, исходники плеера угpoби- лись по независящим от меня причинам, и я не могу продемонстрировать это чудо в pa- боте. Но если кому-либо эта заморочка по- казалась интересной - ссылки на неoбхoди- мую информацию в конце статьи, ассемблер вам в руки:) Кстати, занятная информация для облада- телей приставок NES, построенных на дис- кpетных элементах (имеющих процессор в DIPЧO-корпусе). Вполне легко можно сде- лать псевдо-стерео выход: на первую ногу чипа выходит сигнал с обоих square-кана- лов, на вторую - triangle и шум. Паяльник вам в руки;) Напоследок скажу для тех, кто захочет произвести аналогичные эксперименты: не пытайтесь использовать форматы музыки от современных эмуляторов (типа .nsf) - это не поток команд для звукового чипа, a выдранный из игры плеер + данные (при проигрывании приходится эмулировать не только звуковой чип, но и процессор, и всё необходимое железо - аналогично AY- Emulator'у). Сайт Marat'a: http://fms.komkon.org/ NESSIDPlay: http://www.zyx.com/chrisc/nessidplay.html Описание 2A03: http://web.textfiles.com/ games/nessound.txt