LINUX.ORG.RU

Влияние метода копирования данных на качество звука

 , , ,


0

5

Привет, ЛОР!

Я тут нашёл на одном форуме серию постов о том, что выбор функции для работы с памятью и копирования данных в памяти в аудиоприложении довольно сильно влияет на качество звука. Скажи, этому есть какое-нибудь научное обоснование?

Ссылка: https://www.audioasylum.com/messages/pcaudio/119979/

Для Ъ:

  • Разные версии memcpy() приводят к разному качеству.
  • Код на C++ с new звучит лучше, чем сишный код с malloc().
  • Есть специальная оптимизированная для звука версия memcpy(), позволяющая избавиться от лишних шумов.

Скажи, ЛОР, насколько стоит этим заморачиваться в моём коде? Если у меня на одном и том же компьютеры запущены плеер и мой код, делающий что-то с памятью, может ли это быть причиной плохого звука? Если да, что с этим можно сделать?

Если у меня на одном и том же компьютеры запущены плеер и мой код, делающий что-то с памятью, может ли это быть причиной плохого звука?

Когда-то на каком-то компе я заметил, что движение мышки создает наводки, слышен гул. Подобного рода проблемы легко гуглятся, например https://forum.ixbt.com/topic.cgi?id=4:109849

Шум в звуковой тракт проникает из системы фильтрации по питанию.Но не из БП а видимо связано с разводкой на материнской плате.Слишком много и тесно компонентам на пятачке текстолита.А вообще проблема стара как мир.Раньше хорошо лечилось отключением неиспользуемых выходов,ну а если ничего не помогает,то заменой материнки.Хотя можно поломать голову и полечить паяльником систему фильтрации питания на плате.

То же самое может быть и с каким-то memcpy, который может влиять на энергопотребление.

Если да, что с этим можно сделать?

Лично я за то, что надо менять железо, если на нем работа кода портит звук. Или придумывать что-то с заземлением/экранированием/фильтрацией

SZT ★★★★★
()
Последнее исправление: SZT (всего исправлений: 1)
Ответ на: комментарий от pfg

Ну я не настоящий пейсатель аудио дров, но наверное это будет DMA зона. Если ты скажешь что-то в духе - этого аудио-потока там 500мб на пару минут, то конечно будешь прав, если говорить про пропускную способность, но вся магия мультимедия она во времени отклика и точности тайминга. А если буфер DAC карточки не 500мб, то будет как минимум момент инвалидации этого буфера. А 500мб он быть не может одноуровневым, ну точнее может быть и может, но по цене квартиры такие карточки стоили бы.

faq2
()
Последнее исправление: faq2 (всего исправлений: 1)
Ответ на: комментарий от faq2

Если ты скажешь что-то в духе - этого аудио-потока там 500мб на пару минут

Я тут посчитал на коленке. В несжатом виде звук 192kHz/32bit требует 768кб в секунду на канал. То есть, ты в принципе не так далеко ушёл по прикидкам.

Только я не представляю, зачем забивать буфер на 2 минуты вперёд, ну и вряд ли там такой жирный буфер будет.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от hateyoufeel

Только я не представляю, зачем забивать буфер на 2 минуты вперёд, ну и вряд ли там такой жирный буфер будет.

Так это и мой основной посыл про то, почему память узкое место.

Вот допустим у тебя трек на те же 2 минуты, если ты его полностью залил в одноуровневый буфер с нужной пропускной способностью и временем отклика, то дальше этот буфер разгебается линейно и перестаёт быть узким местом. Но, если трек на 4 минуты, а буфер только на 2, то мы опять приходим к точке, где буфер инвалидируется, либо к точке синхронизации r/w буфера.

Если буфер многоуровневый, то см. про side channel attacks например, чтобы понимать разницы.

Теперь давайте посчитаем немного 20Кгц это 50мкс лэйтенси начинает ролять, это вполне сопоставимо по задержкам которые могут привносить кэшмиссы, кэш это по-сути и есть многоуровневый буфер. Чем выше частота, тем меньшие задержки памяти будут вносить влияние, т.е. несущие 40Кгц это уже 25мкс. Дать частоту 20мкс(20 +/- 2 сильно проще) без вылетов в 99 квантиле только на операциях преимущественно только чтения и записи в память (без сложной арифметики, привет DAC), это уже нетривиальная инженерная задача на текущем оборудовании.

А теперь давайте ещё вспомним про требование, что звуковая подсистема по-хорошему должна быть немного компактней подсистемы вычислений общего назначения в потребительских устройствах.

faq2
()
Ответ на: комментарий от faq2

Насколько это реально на самом деле услышать, это конечно тема для отдельного разговора, т.к. по-сути как раз проблема в том, что метрика «это звучит хорошо», она прям ну ооочень субъективная. То, что синтетически можно замерять эти пропадающие сэмплы - я практически уверен, хотя повторюсь не спец я по звуковому оборудованию от слова совсем, но уверен, что самая трики часть там всё равно организация памяти, и она 100% не идеальная для какой-то разумной стоимости оборудования, тем более если не стоит задача воспроизводить треки фиксированной длинны.

faq2
()
Ответ на: комментарий от faq2

Если кратко - все написанное неверно чуть менее чем полностью.

При выводе всегда буфер загружается наперед. Сначала заполнили его, потом, пока оттуда медленно играет - заполняем дальше.

Каких либо задержек и провалов семплов там вообще возникать не должно.

Провалиться может только весь буфер целиком, если не успеть его заполнить наперед. Тогда пропадет сразу скажем 1024 семпла, это будет явно слышно как хороший щелчок.

James_Holden ★★★★
()

ну как, известная ж тема.

если на hdd хранить - микроконтраст и детальность усиливаются, а на ssd - сцена шире.

и смотря чем копировать. если на сишечке прогу писать для копирования - высокие прозрачные, слоистость, все дела. джава бархатистости к звуку добавляет. крестами не копируй , низы со средними в кашу сливаются и сцены нет. а раст так вообще все в неразличимое говно превращает.

так что сишечкой раз псят копирнул, джавой полирнул сверху и попер теплый ламповый, аж до мурашек.

olelookoe ★★★
()
Ответ на: комментарий от James_Holden

Провал буфера это совсем другого уровня флуктуация, это ты сразу услышишь.

Вот смотри, у тебя из-за вылетов в лэйтенси памяти, затрат на синхронизацию и т.п. для текущего момента времени появилась задержка 2мкс(200 L3 кэш миссов). Пусть она получается в среднем раз в 10 обращений к буферу. Через ~400 обращений (для частоты 20Khz) и через ~200 для частоты(44Khz) тебе надо принять решение - выкинуть сэмпл или копить задержку 50мкс по времени синхронизации например с видеорядом. Т.е. через ~1 262 часа проигрывания ты получишь задержку в одну секунду если не будешь выкидывать приблизительно каждый ~200ый сэмпл( как раз в зависимости от качества буфера).

Надеюсь я в правильную сторону поделил и умножил :)

Подробности тут и тут.

faq2
()
Последнее исправление: faq2 (всего исправлений: 1)
Ответ на: комментарий от faq2

Ну и я все ещё недоумеваю - с какого лешего у тебя накапливаются задержки кеш миссов, если буферизация «наперед» - их съедает.

Воспроизведение семплов идет в итоге со скоростью в зависимости от тактового генератора в аудиокарте. Причем тут кеш я вообще не понял.

James_Holden ★★★★
()
Ответ на: комментарий от James_Holden

В какой момент происходит «дописывание в буфер», сколько «времени» оно занимает и может параллельно(не конкурентно, а именно параллельно) DAC взять следующий сэмпл на конвертацию?

faq2
()
Ответ на: комментарий от James_Holden

Так потому, что задержку в софт-реалтайм системах никто не растит, делают либо процедуру восстановления снэпшота, либо выбрасывают кадр, в зависимости от прикладной области. В мультимедия непонятно вообще, что может быть снэпшотом, поэтому насколько я понимаю всегда выбрасывается кадр.

faq2
()
Ответ на: комментарий от faq2

Буфер внутри карты - двойной как минимум. Пока играет первая половина - ты должен записать вторую половину. Ты можешь сделать это чуть раньше, чуть позже - не важно. В это время играет то что уже загружено в аудиокарту.

и может параллельно(не конкурентно, а именно параллельно) DAC взять следующий сэмпл на конвертацию?

Естественно, он параллельно с записью во вторую половину, все из первой половины буфера и читает. А как еще.

Отклонения момента записи в буфер при этом в пределах времени воспроизведения этой половины - ни на что не влияют, никакие семплы там не выпадают.

James_Holden ★★★★
()
Последнее исправление: James_Holden (всего исправлений: 1)
Ответ на: комментарий от James_Holden

Хм, интересно, каким таким волшебным образом данные из первого буфера оказываются во втором и в какой момент времени? И опять получается возникает вопрос - может ли DAC в этот момент параллельно взять следующий сэмпл из самого распоследнего буфера, и каково время этой синхронизации между буферами.

faq2
()
Ответ на: комментарий от faq2

Еще раз. Один буфер длиной 2048 семплов чтобы было понятно.

Сначала ты пишешь в него 1024 семпла. DAC начинает их играть.

Пока они не отыграли, в любой момент, чуть раньше или позже - неважно, ты пишешь семплы с 1024 по 2047.

DAC прочитав первые 1024 семпла начинает читать дальше семплы с 1024 по 2047, совершенно бесшовно.

В это время, пока он не дошел до 2047 семпла, ты должен успеть заменить первые 1024 семпла на новые. Чуть раньше или позже - не важно.

DAC дочитав до 2047 семпла, тут же и бесшовно перепрыгивает на 0 семпл и все повторяется с начала.

Это называется - кольцевой буфер. Внутри него никакие данные уже не копируются. DAC строчит семплы с постоянной скоростью из буфера. Точные мо енты времени, когда ты загружаешь данные в буфер - тут вообще не важны.

James_Holden ★★★★
()
Ответ на: комментарий от James_Holden

совершенно бесшовно

Так не бывает, вопрос только в абсолютных величинах, такого «бесшовного» переключения. Либо расскажи как это реализовано, чтобы прям за 0пикосекунд оно было например.

Вот 1024 сэмпла это хорошая точка отсчёта, с неё можно что-то посчитать уже, ток я размер сэмпла не знаю.

faq2
()
Ответ на: комментарий от faq2

Либо расскажи как это реализовано, чтобы прям за 0пикосекунд оно было например.

Бесшовно - это не значит за 0 пикосекунд конечно. Давай считать.

Пусть частота дискретизации - 44100 герц. Значит, один семпл звучит 1/44100 секунды = 22,67 микросекунд (округленно). Вот за это время DAC должен перескочить.

А теперь - ты точно хорошо представляешь, как работает оперативная память? Выставляем адрес на шину адреса, появляется содержимое ячейки на шине данных. Это занимает некоторое время.

А теперь скажи, есть ли разница по затратам времени - изменить адрес на шине адреса на предыдущий + 1, или изменить адрес на шине адреса на 0 (ноль)? Да неужели есть? А какая ему разница? (речь о памяти карты, тут нету кешей и миссов)

То есть, если DAC успевает прочитать из памяти каждый следующий семпл, то он успеет и перескочить с конца буфера на начало. За 22,67 микросекунд.

Это называется не кольцевой буфер, а двойная буферизация.

Нет, это именно кольцевой буфер. Смотри картинки по своим же ссылкам. Там ясно и понятно - нарисован перескок с последней ячейки в первую. Двойная буферизация, как правило, предполагает наличие двух буферов с копированием данных между ними. Тут такого нет, буфер один но пишется в два присеста.

James_Holden ★★★★
()
Последнее исправление: James_Holden (всего исправлений: 1)
Ответ на: комментарий от James_Holden

А размер сэмпла то какой? В 100% случаев 1024 сэмпла записываются в следующий буфер быстрее времени переключения?

Двойная буферизация, как правило, предполагает наличие двух буферов с копированием данных между ними.

Нет, с копированием данных в устройство ввода-вывода, пока ты пишешь в буфер 1, буфер 2 выводится («копируется») на устройство(в его память).

faq2
()
Последнее исправление: faq2 (всего исправлений: 1)
Ответ на: комментарий от faq2

В 100% случаев 1024 сэмпла записываются в следующий буфер быстрее времени переключения?

Ты все равно почему-то не понимаешь главного. Ему не нужно записать быстрее времени переключения. Ему нужно записать быстрее, чем кончится первая половина буфера. А это 23 МИЛЛИсекунды (1024 семпла). За 23 миллисекунды то, он конечно в 100% случаев успевает. Это гигантское время.

А пишет в этот буфер кто? Даже если RNG, у него своя шина есть какая-то.

Да без разницы кто пишет, за зазор в десятки миллисекунд ты по-любому успеешь писать.

James_Holden ★★★★
()
Ответ на: комментарий от James_Holden

О! Вот так понятно.

Но всё-равно непонятно - для чего тогда нужны частоты выше 44Кгц?

Да без разницы кто пишет, за зазор в десятки миллисекунд ты по-любому успеешь писать.

Строго говоря нет, но это уже будут спекуляции, такую задержку и правда сложно накопить.

faq2
()
Ответ на: комментарий от faq2

Строго говоря нет, но это уже будут спекуляции

Строго говоря нет, конечно. Бывает что с буфером 1024 не успевает. Но при воспроизведении, его же всегда можно увеличить если надо.

Вот при работе на запись в Ardour, я использую буфер всего 128 семплов (и даже 64) и вот там да, проблемы. Но промахи - слышны явно, как щелчки.

При воспроизведении файлов буфер и ~8000 семплов плееры ставить могут, тогда все ровно.

Но всё-равно непонятно - для чего тогда нужны частоты выше 44Кгц?

Ну это уже другая проблема. Кратко - они нужны для записи ультразвука. А зачем его писать?

Допустим у тебя частота дискретизации 48000 герц. Ты пишешь сигнал с частотой… 40000 герц (так неправильно, это против теоремы Котельникова). Что запишется?

40000 - 24000 = 16000 герц. То есть на записи, вместо неслышимого ухом ультразвука, получится хорошо слышимые 16000 герц! Это очень плохо.

С этим борются, ставя фильтр перед АЦП который режет ультразвук. Но любой фильтр режет не идеально, он и нормальный звук портит, и ультразвук не полностью давит. Поэтому можно иначе - ты просто задираешь частоту дискретизации, и ультразвук пишется и воспроизводится как есть, ухом не слышен.

Откуда он возьмется? Хорошие микрофоны его дают, да и винил - сигнал с винила до 50000 герц выбросы содержать может. Вот чтобы это все не полезло в слышимую область - может применяться высокая частота дискретизации.

Плюс к этому - 192 000 герц дискретизация нужна при сведении. Любой нелинейный эффект, например сатуратор - порождает ультразвук из обычного звука. И если обработку вести на 44100 герц, то этот порожденный ультразвук полезет опять в слышимую область.

Потом, после окончания сведения и мастеринга, можно пройти по треку ооочень хорошим программным цифровым фильтром ультразвука, который его отрежет, и снизить частоту дискретизации до стандартных 44100 герц.

James_Holden ★★★★
()
Последнее исправление: James_Holden (всего исправлений: 1)
Ответ на: комментарий от faq2

Синхронизация в кольцевом буфере бесплатная а делают её волшебные гномики?

Каэш. Тебе надо только сравнивать указатели и следить, чтобы не было overflow или underflow.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от James_Holden

Поэтому можно иначе - ты просто задираешь частоту дискретизации, и ультразвук пишется и воспроизводится как есть, ухом не слышен.

Воспроизводить его никто не будет. Просто отрезать его в цифре гораздо проще, чем low-pass фильтром при записи. Так-то у тебя всё равно этот фильтр будет: либо в цифре, либо в аппаратуре, либо прямо в твоём ухе, которое в ультразвук не может.

hateyoufeel ★★★★★
() автор топика
Ответ на: комментарий от faq2

Т.е. смысла слушать на частотах выше 44кгц особо нет?

Только если у тебя есть собака. Или ручной дельфин. Или летучая мышь, на худой конец.

Ну и алиасинг никто не отменял.

hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от James_Holden

Чуть раньше или позже - не важно.

Можно позанудствовать? Раньше - нельзя (в общем случае Вы не знаете где именно внутри первого chunk идёт playback). Позже - тоже нельзя (будет «срыв»). Но идея - абсолютно правильная, примерно так все и делают.

bugfixer ★★★★★
()
Ответ на: комментарий от Aceler

Используй внешний ЦАП.

Там где нужно адекватное время реакции на «крутилки» - внешний ЦАП сам по себе не поможет. По факту - всё что больше 10milli ощущается очень даже.

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

в общем случае Вы не знаете где именно внутри первого chunk идёт playback

А часы на что?

ПоделИтесь идеальным НЧ фильтром, плз?

Идеальным? Нет. Но срезать с 192kHz до 44kHz можно без потери качества. В конце концов, НЧ фильтр – это просто усреднение.

hateyoufeel ★★★★★
() автор топика
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Идеальным? Нет. Но срезать с 192kHz до 44kHz можно без потери качества. В конце концов, НЧ фильтр – это просто усреднение.

Вы не понимаете, и явно не подкованы в теории / схемотехнике / практике. Снова зайду издалека - какого порядка фильтр нужен чтобы «надёжно» отрезать 44.1kHz от 20kHz?

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

Раньше - нельзя (в общем случае Вы не знаете где именно внутри первого chunk идёт playback). Позже - тоже нельзя (будет «срыв»).

Конечно, я имел в виду - можно в пределах допустимых границ. За них выйти, конечно, нельзя.

James_Holden ★★★★
()
Ответ на: комментарий от faq2

И ещё - нафига для таких идеальных систем, в условиях, что твоё ухо может 20к в секунду сэмплов только различить, вводят частоты сэмплинга 44, 192 и далее?

Ухо не 20к семплов различает, а до 20кГц слышит. Чтобы закодировать дискретными отсчётами 20кГц, _необходим_ 40кГц частота дискретизации.

Waterlaz ★★★★★
()
Ответ на: комментарий от hateyoufeel

DSD можно в wavpack упаковать, чтобы меньше места занимал. Альбом в DSD64 занимает примерно как DVD-диск. Вот DSD256 или даже DSD512 жрут очень много места даже в wavpack.

Но судя по цене железа, которое сможет такой формат не только прочитать, но качественно воспроизвести, то цена карты памяти как-то уже не играет роли. Расходник. 🤣

Radjah ★★★★★
()