Зменшення затримки звуку для музик у Linux (JACK, PipeWire)

Звідки береться затримка і як із нею домовлятись

Апаратне перехитрування затримки §

Якщо ви маєте підсилювач та інше потрібне обладнання, і, наприклад, ви просто хочете записати партію, а потім зробити реампінг чи додати ще якісь ефекти, то ви можете розділити сигнал (використавши чи подвійний кабель, чи ABY-педаль, чи самостійно спаяти розгалужувач), і один вивід записувати на комп’ютері, а інший пропустити через свою апаратуру та слухати. Це набагато зручніше.

Але якщо ви замінили все гітарне обладнання комп’ютером, то прийдеться боротися з затримкою, що я й описуватиму нижче.

Далі про те, як узагалі відбувається обробка й від чого затримка, бо я свого часу хотів це знати і не мав простого пояснення. Якщо вам то не цікаво, можете перейти до #конкретно змінюємо значення.

Рахуємо затримку §

Під час оцифровування з неперервної звукової хвилі з фіксованим інтервалом зберігають значення її амплітуди — семпл (зразок). Таке перетворення сигналу називається дискретизацією. Найчастіше в комп’ютерному аудіо використовується частота дискретизації 48 кГц (48000 семплів на секунду).

зразки (семпли) беруть через однаковий час
Кадр
це розмір семплу (в байтах), помножений на кількість каналів аудіо (у стерео 2 канали, в моно — 1).
Наприклад, для стереосистеми, 16-біт, 44.1 кГц, маємо семпл 16 бітів — 2 байти, тож кадр буде 2*2=4 (байти).
Період
кількість кадрів між кожним апаратним перериванням.

Більше про це тут і за посиланнями в кінці сторінки.

Затримка у процесі захоплення 1 §

Lc = n / f

Затримка програвання зважає ще на кількість періодів p:

Lp = n * p / f

Наприклад, ми обрали розмір буфера n=256, періодів p=2, і частота дискретизації f=48 кГц:

Lc = 256/48=5.(3), Lp = 256 * 2/48=10.(6), тоді весь час затримки буде дорівнювати 16 мс

Що за буфер? §

Мова про циклічний (кільцевий) буфер. Це структура даних, яка якраз тут використовується.

Джерело: вікіпедія

Уявіть кільце, поділене на сегменти, в які ми записуємо або з яких читаємо дані по колу (як у перегонах, можна уявити, що одне авто замальовує сектори на замкненій дорозі, а інше фотографує їх). Очевидно, коли ми запишемо дані у всі сегменти, то повернемось на початок і будемо перезаписувати старі сектори.

Повернімося до наших авто — якщо фотограф малюнків не встигатиме за художником, то він не збереже всі малюнки, адже авто, яке малює, просто перемалює деякі з них до того, як вони будуть зняті. Іншими словами, вказівник запису обжене вказівник зчитування, тому встигатиме переписати сегменти до того, як вони будуть зчитані. Так само, якщо запис відстане від читання, то теж будуть глюки, бо не буде, що читати.

Отже, чим менший розмір буфера, тим більший ризик такої фігні, але й менше часу витрачається на прохід одного кола, тому затримка сигналу менша.

Конкретно змінюємо значення §

Тепер ми знаємо, що для скорочення затримки нам потрібно зменшити розмір буфера та збільшити частоту дискретизації так, щоб при цьому не виникало X-run-ів.

X-run
скорочення від buffer over- або underrun, тобто пере- або недоповнення буферу. тобто програма не встигла або обробити дані з буферу, або надіслати їх у буфер. Вони звучать як різка просадка звуку (ляскання, клацання, тріск), та їх, очевидно, варто уникати.

Сучасні аудіоінтерфейси можуть працювати на високих частотах (до 192 Гц), і це, як бачимо, зручно, хоча варто зважати, що деякі плагіни/програми не працюють на певних частотах дискретизації, тому якщо щось не працює, повертайте, як було (зазвичай 41 чи 48 кГц). Також, очевидно, чим менша затримка звуку, тим більше енергії витрачається на його обробку.

Налаштувати все можна, наприклад, у конфігураційному файлі PipeWire:

    default.clock.rate          = значення # частота дискретизації (44100, 48000, 96000, 192000)
    default.clock.quantum       = значення # розмір буфера (..., 1024, 512, 256, 128, ..., 16, 8)

У графічних програмах зазвичай легко знайти потрібні кнопки buffer (buffer size, frames/period) та sample rate.

Бачимо, у Qjackctl можна налаштувати окремо кількість періодів у буфері й розмір періода

Мої експерименти показали, що розмір буфера 64 і нижче за частоти 96 кГц уже файно. 128 ще відчувається конкретно.

Що ще можна зробити? §

Корисно почитати §


  1. Рівняння з Арчвікі — рекомендую прочитати цю статтю повністю ↩︎