Музыка: PCM-трек через CBL, первый экран истории озвучен
Путь C из sound_plan.md вместо ранее выбранного A (ноты спикера на AY). Причина смены: появились готовые записи DOS-версии, и строка «нужен синтезатор на хосте», из-за которой C считался дорогим, отпала — осталось `ffmpeg -ac 1 -ar 10937 -f u8`. Оцифровки музыки в самой игре нет вовсе: digisnd*.dat содержит только эффекты, музыка лежит MIDI под Adlib, так что конвертировать ресурс игры всё равно было не из чего. * toolchain/pop_pack_music.py — запись flac -> сырой u8 на 10 937,5 Гц (частота CBL, чтобы её не переключать никогда), нарезка на куски MUS\m<id>_<nn>.bin по 16 КБ: bank_load_file читает файл только целиком и только в одну страницу. Каталог -> pop_music_tbl.h; длина трека хранится ПОРЦИЯМИ по 128 байт — 169 КБ в uint16 не влезает, 1350 блоков влезает (32-бит арифметики на Z80 избегаем). * pop_music.c (банк 9) — загрузка трека в EMM и курсор; pop_sfx_fill (резидент) получил третий источник: эффект важнее музыки, музыка важнее тишины. Эффект музыку не сбрасывает — её курсор стоит, пока тот доигрывает, и она продолжается с места. * story_1_absence звучит на первом экране истории, где была тишина. Грузим ПОСЛЕ сборки картинки: чтение идёт через ESTEX, и при открытом CBL насос не успел бы долить блок. Проверено записью звука из MAME: корреляция огибающих с эталоном 0,836 при сдвиге 1,8 с, RMS 22,6 против 18,3 (разница — 8-битное квантование). Эффекты двери в PV-сцене после трека звучат по-прежнему. Бюджет: резидент +83 Б кода и +25 Б данных, запас W2 151 Б (кучи в приложении нет, malloc не слинкован); банк 9 занят на 88 %. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* pop_music.h — музыкальный трек через тот же CBL, что и эффекты.
|
||||
*
|
||||
* ПОЧЕМУ PCM, А НЕ AY. Оцифровки музыки в игре нет вовсе: digisnd*.dat
|
||||
* содержит только эффекты, музыка лежит MIDI под Adlib. Зато есть готовые
|
||||
* записи DOS-версии, и путь «запись -> сырой поток CBL» не требует ни
|
||||
* синтезатора на хосте, ни аранжировки под три канала AY (разбор вариантов
|
||||
* — ../docs/sound_plan.md §1). Плата известна: CBL один, поэтому пока
|
||||
* играет музыка, эффектов нет. Оригинал ведёт себя так же — play_sound
|
||||
* там глушит предыдущий звук.
|
||||
*
|
||||
* ГДЕ УМЕСТНО. Заставки и титры: эффектов там не бывает, картинка
|
||||
* статична, и загрузка сотни-другой килобайт с диска никому не мешает.
|
||||
* Музыка ПО ХОДУ игры (джинглы смерти, зелья) — отдельный вопрос, её
|
||||
* придётся либо гасить эффектами, либо уводить на AY.
|
||||
*
|
||||
* ФОРМАТ на диске — пачка кусков m<id>_<nn>.bin по 16 КБ (bank_load_file
|
||||
* читает файл только целиком и только в одну страницу). Каталог с
|
||||
* длинами генерирует toolchain/pop_pack_music.py в pop_music_tbl.h.
|
||||
*/
|
||||
#ifndef POP_MUSIC_H
|
||||
#define POP_MUSIC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Сколько страниц EMM держим под трек. Двадцать = 320 КБ, это все
|
||||
* заставочные треки, кроме финального «won» (115 с, 1,2 МБ): тот придётся
|
||||
* либо резать, либо стримить, и это отдельная задача. */
|
||||
#define POP_MUS_PAGES 20
|
||||
|
||||
/* Номера треков — нумерация оригинала (SDLPoP data/music/names.txt). */
|
||||
#define POP_MUS_STORY_1 55 /* «In the absence of the Sultan...» */
|
||||
|
||||
/* Курсор проигрывания — читает НАСОС (pop_sfx.c, резидент), пишет
|
||||
* загрузчик. Отдельный от эффектов: они звучат поверх музыки, а не
|
||||
* вместо неё, и у каждого свой источник. */
|
||||
extern uint8_t pop_mus_page[POP_MUS_PAGES]; /* физические страницы EMM */
|
||||
extern volatile uint8_t pop_mus_pg; /* индекс текущей страницы */
|
||||
extern volatile uint16_t pop_mus_ptr; /* адрес в окне W0 */
|
||||
extern volatile uint16_t pop_mus_left; /* байт до конца трека, 0 — молчим */
|
||||
|
||||
/* Загрузить трек в EMM (НЕ запускает). Звать там, где допустима пауза на
|
||||
* диск: CBL в это время обязан быть закрыт, иначе насос не успевает долить
|
||||
* блок и железо повторяет старый — на слух скрежет (pop_sfx.h).
|
||||
* 0 — готово, -1 — нет трека/памяти/файла. */
|
||||
int8_t pop_music_load(uint8_t id) __banked;
|
||||
|
||||
/* Отпустить страницы. Останавливает проигрывание, если оно шло. */
|
||||
void pop_music_free(void) __banked;
|
||||
|
||||
/* Пустить загруженный трек с начала / оборвать. */
|
||||
void pop_music_play(void) __banked;
|
||||
void pop_music_stop(void) __banked;
|
||||
|
||||
/* Трек ещё звучит? 0 — доиграл или не запускался. */
|
||||
uint8_t pop_music_busy(void) __banked;
|
||||
|
||||
#endif /* POP_MUSIC_H */
|
||||
Reference in New Issue
Block a user