Я завершил анализ системы передискретизации, применяемой в эмуляторе ZXMAK. В комментариях написано, что она позаимствована из UnrealSpeccy - если так, то и синтез звука UnrealSpeccy должен иметь те же достоинства и недостатки.
Код передискретизации находится в файле SoundDeviceBase.cs. Реализуемый алгоритм передискретизации (с точки зрения ЦОС) таков:
1) Сначала происходит интерполяция методом удержания (Hold Interpolation) с исходной частоты дискретизации (равной тактовой частоте Z80) на промежуточную частоту, которая в 64 раза выше выходной. Если выходная 44100Гц - то промежуточная частота будет около 2,82МГц. Это делается в строках 313 и 323 SoundDeviceBase.cs
2) Затем применяется ФНЧ, FIR-фильтр 127 порядка (128 коэффициентов). Прилагаю графики его АЧХ. Общий вид, область перехода между пропусканием и подавлением, и отдельно полоса пропускания. Фильтр реализован, главным образом, в функции FlushFrame().
3) После фильтра частота дискретизации уменьшается в 64 раза, т.е. приводится к стандартной частоте звуковой карты. Это также происходит в функции FlushFrame().
Применяются некоторые трюки. Автор кода воспользовался кусочным постоянством входных сигналов для оптимизации. В буферах хранятся не сами сигналы, а только их фронты. Поэтому и происходит вычисление частичных сумм коэффициентов фильтра в конструкторе SoundDeviceBase().
Что за тип фильтра применяется - не могу точно сказать. Если вывести график его коэффициентов - то получится что-то похожее на приподнятый косинус или обрезанную функцию Гаусса. Можно выяснить точно с помощью методов нелинейной аппроксимации, но в этом может быть разве что исторический интерес.
Теперь по поводу возможностей улучшения:
1) Интерполяция методом удержания до фильтра - существенный источник алиасинга. Если применить ее не до, а после фильтра - то уже искажений станет меньше. А если применить вместо неё интерполяцию многочленом или структурой фильтра Фарроу - то станет намного лучше.
2) Можно пересчитать и оптимизировать коэффициенты фильтра даже без повышения его порядка. Фактически, сейчас фильтр имеет частоту среза по уровню -3дБ около 15кГц. Его переходная полоса идет от 15 до примерно 50кГц. Подавление в полосе подавления - около 46дБ. Остаточные сигналы от 22050 до 50кГц отражаются в слышимую область в виде алиасинга.
Фильтр можно существенно улучшить без или с незначительным повышением вычислительных затрат на его работу.
Я готов все это сделать, но C# - не мой язык программирования. Я бы написал алгоритмы объектно-ориентированно на Си
ZXMAK: ты мог бы потом перевести их на C# или вызывать через интерфейс на Си, и встроить потом в свой эмулятор?




Ответить с цитированием
Размещение рекламы на форуме способствует его дальнейшему развитию 


