CBL: заливка буфера тишиной при открытии + щелчок на выходе из PoP

Две разные болячки, обе разобраны записью звука MAME в WAV.

libc: буфер CBL железо не чистит, а запись в порт управления сразу пускает
воспроизведение с нулевого слота — первые 256 сэмплов (23,4 мс) уходит то,
что лежало раньше.  Своими данными звук идёт лишь с третьей половины:
прерывание приходит на 128-м слоте и ставит указатель на противоположную
половину.  _cbl_prime заливает буфер тишиной сразу после включения (раньше
нельзя — запись проходит только при поднятом bit7).  В MAME это немо
(эмулируемый буфер стартует нулями при двухдополнительном ЦАП), на железе
это ровно тот мусор, что ловился на тестовых примерах CBL.

PoP: на выходе по ESC звучало ровно 11 мс шума на полной громкости — один
пропущенный блок (128 сэмплов).  Причина: pop_shutdown освобождал атласы и
графику через ESTEX при открытом звуке, насос не успевал долить.  Звук
гасим первым действием.  Проверено записью — всплеска больше нет.

Заодно записан разбор стартового всплеска (sound_plan.md §10): это не
мусор, а gate_closing_fast из левой комнаты, обрываемый soft_land.  Обрыв
одноголосьем — поведение оригинала (play_digi_sound начинается с
stop_digi, seg009.c:2402).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 16:23:06 +03:00
parent e0c86a96ef
commit f159aa47e1
5 changed files with 134 additions and 1 deletions
+6
View File
@@ -78,6 +78,12 @@ int cbl_open(uint8_t freq_code, uint8_t fmt, uint8_t pump_mode,
IRQ_DISABLE();
_irq_cbl_hook = (pump_mode == CBL_PUMP_ACCEL) ? _cbl_pump_accel : _cbl_pump_otir;
_cbl_ctrl((uint8_t)(0x90 | fmt | freq_code)); /* on + int + формат + частота */
/* ...и НЕМЕДЛЕННО забить буфер тишиной: железо пускает воспроизведение
* с нулевого слота той же записью в порт управления, а буфер хранит
* старое содержимое — без этого первые 23 мс уходит мусор. Заливка
* обязана быть внутри той же DI-скобки и сразу за включением (разбор —
* _cbl_prime.c). */
_cbl_prime((uint8_t)((fmt & CBL_FMT_MONO16) ? 0x00 : 0x80));
IRQ_ENABLE();
return 0;
}