Ну например сказано, что её аппаратная ЧД (частота дискретизации) - 48000. Может ли в реальном ЦАП, т.е. в реальном железе она плавать между 47800 и 47990?
Ситуация:
Вывожу звук одновременно с рисованием его графического представления (спектр-сонограмма). Графика выводится точно, хотя кадры ресуются не через равные промежутки времени (Qt-шный QTimer с его погрешностями). Точность позиции курсора на графике в каждом кадре обеспечивается за счёт того, что когда приходит запрос на рисование кадра, я беру точное текущее время с помощью вот такой функции:
long long getCurrentTimeMs(void)
{
boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time();
boost::posix_time::ptime epoch_start(boost::gregorian::date(1970,1,1));
boost::posix_time::time_duration dur = now - epoch_start;
return dur.total_milliseconds();
}
и на основании разницы со временем старта воспроизведения звука принимаю решение, какое место файла рисовать напротив курсора. Это элементарно сделать, зная его ЧД. Ну например если пришёл запрос на рисование кадра и я вижу, что с момента начала воспроизведения прошла 1 секунда, я должен нарисовать напротив курсора район 44100-го семпла, при ЧД=44100. То есть при любой неточной частоте кадров я рисую точную картинку.
Запускаю воспроизведение, смотрю на картинку, сопоставляя слышимое и видимое. В районе 150-й секунды становится заметно, что картинка уехала вперёд где-то на 1/10 секунды.
Если считать, что getCurrentTimeMs() даёт точное текущее время, то получается, что звуковуха воспроизводит немного медленнее, чем нужно. То есть аудиофилы на форумах не зря точность тактового генератора обсуждают?
Да, файл 44100, а звуковуха 48000. Ресемплинг делает ALSA где-то внутри себя - меня это мало волнует, т.к. пакеты семплов я ей поставляю по коллбеку исправно без тормозов, т.е. внутри аппаратуры пакеты семплов, которые ALSA у меня просит состыковываются идеально, иначе я бы щелчки слышал в наушниках.
Загрузка данных из файла - большими кусками, асинхронно, в отдельном потоке. ALSA просит очень мелкими кусками - по 940 семпла, я отдаю ей уже из готовых загруженных буферов (длина секунды по 4), то есть при обработке коллбека никто ничё с диска не читает, максимум - семафор дёргается, чтобы загрузку будущих отдалённых данных в фоне запускать.
Ещё есть известная в узких кругах софтина baudline, которая каким-то образом (по системным часам наверное) меряет ЧД при воспроизведении и записи. Наверное запихивает в ALSA пакеты и меряет, сколько данных ей удаётся пропихнуть в единицу времени... В общем в режиме «48000» она выдаёт колеблющееся число между 47995 и 48000.
Видео о происходящем: http://youtu.be/H3Fv0-6-oZs
P.S. Померял скорость трафика в семплах между модулем загрузки данных и модулем воспроизведения, получилось 44055.1...44066.2 семпла в секунду. До 44100 не дотягивает. Этот «трафик» определяется коллбеками от ALSA, никакой самодеятельности нет, щелчков в звуке тоже нет, всё слышно очень ровно, сколько ALSA просит, столько исправно даём без сбоев и тормозов.