фикс аудиобуфера
игры под crossover трещат, если устройство вывода не работает на 88.2 или 96 кгц, а bluetooth и большинство usb-устройств так не умеют. дело никогда не было в частоте. дело в длине буфера, и её можно исправить на любой частоте.
симптом
треск в звуке игры и рваный микрофон в голосовом чате. обычный совет — выставить 96 кгц в «настройке audio-midi». bluetooth-гарнитура предлагает только 44.1 кгц, usb-микрофон — 44.1 или 48.
причина
wine будит игру каждые 10 мс, и движок держит в очереди один-два таких периода. coreaudio забирает 512 кадров за цикл ввода-вывода: 11.6 мс при 44.1 кгц, 10.7 мс при 48 кгц. это длиннее одного периода, очередь пустеет, и wine дополняет пробел тишиной. при 96 кгц те же 512 кадров длятся 5.3 мс, и очередь не пустеет.
у записи зеркальная проблема: wine отдаёт один пакет в 10 мс за цикл и выбрасывает излишек.
замеры
проба играет и записывает так же, как sdl, по 15 с на прогон. для воспроизведения считается вставленная тишина, для записи — потерянный звук.
| устройство | без фикса | с фиксом |
|---|---|---|
| bluetooth-гарнитура, 44.1 кгц | 6.0–6.3 % | 0.1 % |
| usb-выход, 48 кгц | 1.8–2.2 % | 0.1–0.2 % |
| встроенные динамики, 48 кгц | 1.8–2.2 % | 0.0–0.1 % |
| встроенные динамики, 96 кгц | 0.1 % | — |
| usb-микрофон, 48 кгц | 6.9 % | 0.2 % |
| usb-микрофон, 44.1 кгц | 6.4 % | 0.1 % |
вторая половина обычного совета — поставить микрофон на 44.1 кгц — не помогла: на 44.1 кгц терялось столько же, сколько на 48.
фикс
размер буфера ввода-вывода задаётся отдельно для каждого процесса, поэтому его нужно выставлять изнутри игры. обёртка заменяет winecoreaudio.so из wine, реэкспортирует настоящий драйвер и при загрузке просит у coreaudio буфер 5.33 мс на каждом устройстве: 256 кадров при 48 кгц, 235 при 44.1.
Float64 hz; // текущая частота устройства
UInt32 frames = hz * io_ms / 1000; // 5.33 мс на любой частоте
AudioObjectSetPropertyData(device, &buffer_frame_size,
0, NULL, sizeof frames, &frames);что меняется на диске
lib/wine/x86_64-unix/winecoreaudio.soстановится обёрткойwinecoreaudio.so.orig— нетронутый оригиналwinecoreaudio_real.so— копия, которую загружает обёрткаmgf_audio_io_msхранит длину буфера: процессы wine запускает crossover, и передать её через переменные окружения нечем
ограничения
- действует для процессов wine, запущенных после изменения. перезапустите steam и игру.
- если входом выбран собственный микрофон bluetooth-гарнитуры, macos переводит её в режим 16 кгц моно. никакой буфер этого не исправит. выберите другой микрофон в карточке «аудиоустройства».
аудиобуфер ввода-выводав настройках меняет длину. 0 возвращает значение coreaudio.