покопался в коде AY8910, обнаружился баг в миксере, который тянется еще с первых версий ZXMAK :)
Пофиксил, хотел сделать релиз, но codeplex сейчас падает при попытке создать новый релиз.
Вид для печати
покопался в коде AY8910, обнаружился баг в миксере, который тянется еще с первых версий ZXMAK :)
Пофиксил, хотел сделать релиз, но codeplex сейчас падает при попытке создать новый релиз.
Зарелизил тестовую версию 2.8.6.7 TESTSYNC.
В эту-же версию вошли такие изменения:
- исправлен миксер и шум для AY8910;
- много разных фиксов и оптимизаций для стабильности синхронизации;
- изменен цикл эмуляции;
- исправлена поддержка 100 Гц дисплеев (и не только);
- исправлены Sprinter ULA и Memory, чтобы не падали если нет контроллера дисковода и т.п.;
- изменен механизм загрузки плагинов, теперь плагины грузятся из сборок перечисленных в plugins.config;
- добавлен отладчик GDB-Z80 server;
- много кода отрефакторено;
Тут довольно сильно затронут механизм синхронизации, поэтому к стабильным релизам пока относить не буду. При синхронизации от видео, теперь вызывается Present для каждого кадра. Нужно потестить как новый механизм работает на разных машинах.
Значительно изменился граф debug info. Теперь тут есть сетка, по горизонтали 25 фреймов, по вертикали 1 мс (белая сетка) или 10 мс (красная сетка).
Расчет данных для графа довольно тяжеловат, поэтому при включении debug info эмулятор кушает дополнительное процессорное время.
Просьба потестить как работает на разных машинах и выложить скрины с включенным debug info при синхронизации от видео.
Заодно просьба написать отзывы по поводу нового звука AY. :) Т.к. серьезно потестить исправленный вариант времени не было.
http://savepic.su/4846048.png
Легенда по графу:
Зеленый график - время между отображением кадров (Present);
Красный график - время затраченное на эмуляцию фрейма (теперь не включает в себя время на рендеринг текстуры и запись буфера в звуковую карту);
Желтая граница - время периода частоты обновления дисплея;
Сиреневая граница - время периода 50 Гц;
Белая сетка - вертикальный масштаб 1 мс на клетку, горизонтальный 25 кадров;
Красная сетка - вертикальный масштаб 10 мс на клетку, горизонтальный 25 кадров;
MinT/AvgT/MaxT - минимальное/среднее/максимальное время между отображением кадров (Present);
AvgE - среднее время эмуляции кадра;
MinL/AvgL/MaxL - минимальная/средняя/максимальная латентность планировщика операционной системы, отражает разницу между запрошенным временем на Thread.Sleep и реальным временем, через которое система вернула управление. Больше 0 - плохо, т.к. будут пропуски кадров. Сильно меньше нуля тоже плохо, т.к. процессор больше времени работает в холостую. Оптимальное значение -0.001...-1.000 мс
Значения вычисляются за период графа - 150 кадров.
А на дисплеях с 60 Гц, сейчас, с любыми настройками, будет не очень?
http://i.imgur.com/0gWCAPu.gif
для 60 Гц дисплея нужно интерполяцию кадров делать, чтобы получить плавный ресэмплинг. Это второй шаг. Сейчас задача добиться хорошей синхронизации.
Сейчас обновление на каждом кадре производится какраз специально для того, чтобы в дальнейшем обновлять кадры с временными коэфициентами для интерполяции.
По гифке не очень понятно, насколько стабильно держится AvgT? Что это за выброс в конце гифки?
Судя по времени обновления на графе, частота кадров реально 59.952 Гц. Если это так, то ресэмплинг сбивается, т.к. ориентируется на частоту, которую говорит DirectX - 59,000 Гц. Первое наблюдение, когда частота кадров дисплея не соответствует заявленной системой.
В реальности действительно так дергается?
выкладываю все тесты на 2.8.6.7.
скриншот с эмуляции Спринтера:
http://savepic.su/4844482.jpg
Обновил до версии 2.9.0.38062
Исправлена и переработана эмуляция AY8910 и звука.
Теперь для ау используется передискретизация.
Исправлены миксеры - общий и АY.
Качество звука выросло в разы :)
Частоту ay можно задавать любую (в разумных пределах), правда пока только вручную через файл конфигурации машины zxmak2.vmz
Интересно услышать ваше мнение по поводу качества звука в новой версии по сравнению с unreal например :)
Звук не слушал, но заглянул в исходники. Очень странный микшер- сложение сразу двухканальных семплов. Само по себе оно нормальное, но вот ненормированные коэффициенты в m_mixerPreset могут дать переполнение при сложении, что чревато переползанием левого канала в правый и клиппингом в правом канале (или наоборот, не суть важно).
Раз у тебя есть отличное событие OnVolumeChanged, заюзай его по полной- считай таблицу в 32768 элементов примерно следующим способом:
и потом в коде:Код:for (int idx = 0; idx != 32768; ++idx) {
int volA = vol_table[idx & 31] * volume / 65535;
int volB = vol_table[(idx >> 5) & 31] * volume / 65535;
int volC = vol_table[(idx >> 10) & 31] * volume / 65535;
int levAL = m_mixerPreset[0];
int levAR = m_mixerPreset[1];
int levBL = m_mixerPreset[2];
int levBR = m_mixerPreset[3];
int levCL = m_mixerPreset[4];
int levCR = m_mixerPreset[5];
int volL = (volA * levAL + volB * levBL + volC * levCL) / 300;
int volR = (volA * levAR + volB * levBR + volC * levCR) / 300;
m_volTable[idx] = volL + (volR << 16);
}
Вообще, mixA/mixB/mixC тоже можно считать практически параллельно, но это уже несколько сложнее.Код:var sample = m_volTable[(mixC << 10) | (mixB << 5) | mixA];
UpdateDac(m_lastTime, (ushort)sample, (ushort)(sample >> 16));
Для спринтера это нормально, у него графика прилично процессор ест, нужно оптимизировать.
Кстати как работает ковокс на спринтере? Насколько помню, у спринтера ковокс с буффером. С новым звуком добавить его поддержку думаю будет несложно. У SoundDeviceBase появились методы UpdateDac, принимающие время относительно кадра (от 0 до 1) и метод получающий текущее время кадра (тоже от 0 до 1). Т.е привязки к текущему такту нет - можно сразу пачками апдейты делать, главное время вычислить и с убывающим временем не обновлять :)
UpdateDac теперь несколько вариантов для signed 16 бит и для unsigned 16 бит.
---------- Post added at 12:33 ---------- Previous post was at 12:20 ----------
\
спасибо, я тоже это заметил, но пока эту часть не трогал, нужно будет пофиксить.
при использовании Акселя в Альтере, проц, можно сказать, прохлаждается.Цитата:
Для спринтера это нормально, у него графика прилично процессор ест, нужно оптимизировать.
есть "документация" и некоторые исходники того же ваф плеера. если в кратце, ковокс буферизированный, с возможностью задавать битность (8 или 16, но тут могу ошибиться).Цитата:
Кстати как работает ковокс на спринтере?
Цитата:
Covox с буферным ОЗУ.
Подключение буферного ОЗУ осуществляется по следующей схеме:
http://zx-pk.ru/attachment.php?attac...1&d=1422373114
Счетчик работает на частоте 15 или 22 килогерца, в зависимости от состояния порта конфигурации
Covox-а. Адрес мультиплексируется на момент записи в порт из процессора, все остальное время данные
из ОЗУ записываются в регистр ЦАП-а.
Ввод байтов в буферное ОЗУ осуществляется командой OTIR (OUTI), что позволяет ускорить вывод
звука и создать достаточно большие паузы для работы других частей программы. Так как при использовании
команды OTIR регистр B (который попадает на A15..A8 процессора) уменьшается, для нормальной работы
CBL счетчик считает «назад».
Для контроля за работой Covox-Blaster-а используется бит 7 порта #FE, в который выводится старший
бит счетчика. Блок ОЗУ 256 байт условно разбит на две банки по 128 байт, и бит 7 порта #FE указывает
какая из банок ОЗУ выводится в ЦАП в конкретный момент времени. Это используется программой вывода
для определения, нужно ли подгружать следующие 128 байт в буфер.
В плате Sp2000 COVOX-Blaster включен в основную прошивку и включается через порт управления
CBL - #4E. Запись в этот порт значения #80 приводит к включению режима CBL, #00 - включение
обычного COVOX-а. Другие биты порта #4E имеют значение и их следует выставлять в 0 для получения
описанного выше режима CBL. В дальнейшем этот порт будет устанавливать режимы Stereo, 8/16-bit и
частоту.