LINUX.ORG.RU

Синхронизация звука и анимации курсора аудио-редактора. Или звука + видео.


0

2

В большинстве звуковых карт есть отклонение генератора от стандартных частот семплирования. Например вместо 44100 может быть 43095. На слух никто никогда не услышит, но за пару минут воспроизведения звук может отстать от какого-нибудь движущегося курсора, который рассчитывал на 44100 и опирается на системные часы. Это вступление (-;

Мне требовалось синхронизировать курсор аудио-редактора со звуком. Хотелось, чтобы юзер слышав «тынц» видел как курсор пробегает по тынцу прямо в этот момент. Интерфейс - Qt 4.8, язык C++.

Решение было такое: по таймеру QTimer (точность которого побоку) происходило обновление виджета 30 или 60 раз в секунду, на котором бежал курсор. Во время выполнения функции отрисовки, вычислялась текущая позиция курсора на основе samplerate и текущего времени, которое в этой функции бралось из каких-то там часов, уже не помню каких, наверное какой-нибудь boost.

Точный фактический samplerate звуковухи мерял путём измерения средней скорости (за время ~10 секунд), с которой звуковуха пожирает семплы.

Без такого замера на большинстве испытываемых звуковух курсор постепенно уезжал.

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

Как в linux принято спрашивать текущую воспроизводимую позицию, если там есть ALSA/JACK/PulseAudio и наверное другие средства загнать семплы в звуковуху? Есть ли для каждого средство узнать точный момент начала вопроизведения или даже текущий воспроизводимый семпл? А то бывает, что приложение семплы в звуковуху отправило, пошло дальше работать, а звука ещё какое-то время нет.

Интересует также вопрос производительности. Тут есть 2 момента

1) ходить в ядро глядеть на часы относительно дорого. Хотя я в этом плохо разбираюсь, но почему-то у меня сформировалось такое ощущение.

2) Нужно как-то понять, когда именно рисовать виджет. Просто фигачить перерисовку по таймеру, как я, - это криво, т.к. у меня может быть кривой таймер и у меня могут сбиваться кадры - т.е. я могу нарисовать очередной кадр уже после того, как кадр ушёл в монитор. Тут тема широкая, скажите хоть какую-нибудь речь. Покадровой синхронизации конечно не требуется, т.к. на 100-герцовом мониторе мне незачем фигачить 100fps, ибо при 30 оно уже плавно. Другое дело, что когда я под виндой попытался дать 30 fps, оно выглядело как 15fps, хотя те же 30fps на линуксе выглядят очень плавно. В кино по-моему 24 и никто не жалуется особо, новые видеокамеры умеют 60 - это добавляет плавности, да. Конечно 30 и 60fps на глаз заметны, но не так, как разница между 15 и 30.

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

Спасибо.

★☆

Последнее исправление: kiverattes (всего исправлений: 1)

Решение было такое: по таймеру QTimer (точность которого побоку) происходило обновление виджета 30 или 60 раз в секунду, на котором бежал курсор. Во время выполнения функции отрисовки, вычислялась текущая позиция курсора на основе samplerate и текущего времени, которое в этой функции бралось из каких-то там часов, уже не помню каких, наверное какой-нибудь boost.

Нда, моск тут явно не включался

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

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

Harald ★★★★★
()

Вот если бы ты почитал примеры вывода звука для той же ALSA, то большая часть отпросов отпала сама собой ).

А так, в теории, раз у тебя аудиоредактор, то цепляйся к воспроизведению звука, как к эталонному таймеру. Ну и определись с какой точность тебе надо синхронизировать звук и изображение, ибо 100% точность не достижимо да и не нужно, т к восприятие человеком инерционно.

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

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

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

Зачем примеры вывода звука? Примеры вывода звука я почитал и вывод звука в ALSA наговнокодил. Вопрос в синхронизации, а не в выводе звука.

kiverattes ★☆
() автор топика

JACK

через jack transport, например

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

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

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

Зачем примеры вывода звука?

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

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

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

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

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

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

я с алсой дело не имел, но не поверю, что там нельзя контролировать размер порции сэмплов, засылаемой за один раз

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

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

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

Да, придётся ковыряться бессонными ночами, если никто не расколется, пока я буду другими делами заниматься.

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

Ты издеваешся?

Бьешь звук на одинаковые промежутки (к примеру на 4096 семплов). Каждый такой промежуток соответсвует позиции курсора. Запускаешь воспроизведение и при каждом интеррапте от альсы посылаешь сигнал на перерисовку курсора на следующей позиции. Что может быть проще?

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

Алса не гарантирует, что будет тебе интеррапт дёргать с равными промежутками времени (например может долго не дёргать, а потом резко по несколько раз подряд) или что будет воспроизводить прямо перед той позицией, которую ты отправил - она может нахомячить много семплов про запас вперёд, а воспроизводить далеко до того места, которое ты в последний раз отправлял. Тут нужен какой-то явный способ спросить «чё играет»?

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

Тут нужен какой-то явный способ спросить «чё играет»?

ALSA -> PCM Interface -> Status Functions

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

Алса не гарантирует, что будет тебе интеррапт дёргать с равными промежутками времени (например может долго не дёргать, а потом резко по несколько раз подряд)

Тебе вообще никто не гарантирует, что твоя программа будет получать процессорное время равномерно, ибо это не система Реального Времени!

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

Все верно, но по интерраптам можно довольно точно узнать, сколько семплов только что было проиграно.

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

Нельзя - интеррапты происходит, когда в буфере свободное место появилось, а буфер может быть на 2 секунды.

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

Да хоть 200 секунд! интеррапт будет, когда из буфера вычитается заданная порция данных, а не весь буфер.

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

Ладно. Я попробую что-нибудь сделать с этим, но когда-то эти интеррапты у меня не прижились из-за некросс-платформенности: под виндой интеррапты кривые: не позволяют внутри обработчика лочить мьютексы, поэтому от интерраптов я совсем отказался. Попробую сделать отслеживание текущей позиции на базе интерраптов, хотя как сказали выше - есть какой-то там ALSA -> PCM Interface -> Status Functions.

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

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

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

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

Я не говорю, что в винде что-то ненормально, я говорю что из обработчика прерывания нельзя пользоваться мьютексами. Точнее не мьютексами, извините, ошибся, а нельзя исполнять код, в котором идёт доступ к звуковому API. То есть, из обработчика прерывания от звукового API запрещается, например, слать данные в звуковое устройство. Это не direct sound, это какой-то древний звуковой API, а в винде много всяких новых модных.

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

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

kiverattes ★☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.