реализация звуковго jitter-буфера
От: Аноним  
Дата: 05.02.07 18:40
Оценка:
Привет, не подскажет-ли кто-нибудь как правильно реализовывать механизм работы с jitter-буфером?
задача простая, принимать по сети голосовые пакеты и записывать их в кольцевой буфер звуковухи по средством DirectSound, проблема в том что некоторые пакеты приходят с небольшим опозданием, а некоторые чуть раньше и если их при получении сразу же писать в буфер звуковухи, то звук получается неровный, иногда следующий пакет затирает окончание предыдущего, иногда образуется разрыв, напрашивается решение с промежуточным буфером, но как конкретно это реализовывать не совсем понятно, нужно-ли просто складавать туда голосовые пакеты а потом доставать оттуда по таймеру или как-то иначе, в общем может быть есть какой-то всем известный алгоритм или пример реализации?
Re: реализация звуковго jitter-буфера
От: ANM Россия  
Дата: 05.02.07 20:47
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Привет, не подскажет-ли кто-нибудь как правильно реализовывать механизм работы с jitter-буфером?

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

1. Делается FIFO-буфер размером N.
2. Принимаются и накапливаются сэмплы в буфере до N/2. (операция put)
3. Начинается воспроизведение из буфера. (операция get)
4. Поступающие сэмплы складываются в буфер.
5. В процессе воспроизведения сэмплы убираются из буфера.

Но останется классическая проблема с разностью частот передатчика и приемника, называемая "коррекция jitter-буфера".
т.е. Ft/Fr != 1 (Ft частота ЦАП передатчика, Fr частота АЦП приемника), идеального решения этой проблемы не существует, есть много разных способов разной степени сложности и качества результата.
Re[2]: реализация звуковго jitter-буфера
От: Аноним  
Дата: 06.02.07 15:57
Оценка:
ANM>1. Делается FIFO-буфер размером N.
ANM>2. Принимаются и накапливаются сэмплы в буфере до N/2. (операция put)
ANM>3. Начинается воспроизведение из буфера. (операция get)
ANM>4. Поступающие сэмплы складываются в буфер.
ANM>5. В процессе воспроизведения сэмплы убираются из буфера.

ANM>Но останется классическая проблема с разностью частот передатчика и приемника, называемая "коррекция jitter-буфера".

ANM>т.е. Ft/Fr != 1 (Ft частота ЦАП передатчика, Fr частота АЦП приемника), идеального решения этой проблемы не существует, есть много разных способов разной степени сложности и качества результата.

Спасибо за ответ, что-то подобное я и пробовал сделать,но постоянно получал различного-рода дифекты в звучании, такое впечатление что "скорость поступления входящего звука была больше скорости его воспроизведения", что в принципе не понятно, т.к. звук-то записывался одним источником за тоже время за какое его нужно было воспроизвести...?
Видимо это и есть следствие этой проблемы Ft/Fr != 1.
Можно ли по подробнее о способах борьбы с этой проблемой, или ссылочку где почитать можно, google на вскидку ничего толкового не выдал..
Re: реализация звуковго jitter-буфера
От: Morpheus_  
Дата: 06.02.07 18:07
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Привет, не подскажет-ли кто-нибудь как правильно реализовывать механизм работы с jitter-буфером?

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

приходящие пакеты складывать в Queue. При запуске записать в буфер несколько пустых пакетов, после чего в callback вызываемом по окончании проигрывания буфера делать Dequeue следующего пакета и писать его в буфер.
Проблема будет в несоответствии частот кварцевого резонатора звуковой карты на машине где звук проигрывается и где звук записывается...
Если на машине где звук проигрывается частота кварца чуть больше то наступит момент когда все пакеты будут проиграны, а новые еще не успели прийти. Если наоброт, то Queue будет постоянно расти, пока не наступит out of memory...
Соответственно изредка будут щелчки и похрипывания, как это решить толком не знаю.
Есть идея вести какуюто переменную в которой расчитывать критерий запаздывания/ускорения и по нему выкусывать или вставлять лишние сэмплы в пакеты, но при этом пакеты прийдется коцать и собирать новые
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: реализация звуковго jitter-буфера
От: ANM Россия  
Дата: 06.02.07 18:33
Оценка:
А>Спасибо за ответ, что-то подобное я и пробовал сделать,но постоянно получал различного-рода дифекты в звучании, такое впечатление что "скорость поступления входящего звука была больше скорости его воспроизведения", что в принципе не понятно, т.к. звук-то записывался одним источником за тоже время за какое его нужно было воспроизвести...?

Нет. Допустим звук сэмрлируется с частотой 8001 Гц, а воспроизводится с частотой 7999 Гц.

А>Видимо это и есть следствие этой проблемы Ft/Fr != 1.

А>Можно ли по подробнее о способах борьбы с этой проблемой, или ссылочку где почитать можно, google на вскидку ничего толкового не выдал..

Прочтите RFC 1889, там более подробно изложена проблема. Универсального метода решения нет, все сильно зависит от конкретного случая.
Re[4]: реализация звуковго jitter-буфера
От: Аноним  
Дата: 06.02.07 18:53
Оценка:
ANM>Нет. Допустим звук сэмрлируется с частотой 8001 Гц, а воспроизводится с частотой 7999 Гц.

Т.е. если я правильно понимаю, получается что звук одинаковой продолжительности по времени(например 1 секунда), отцифрованный на разных звуковухах будет занимать разное количество байт, а его воспроизведение на третьей карте может длиться вовсе не 1 секунду а больше или меньше?
Re[5]: реализация звуковго jitter-буфера
От: ANM Россия  
Дата: 06.02.07 19:41
Оценка:
Здравствуйте, Аноним, Вы писали:

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


Совершенно верно.
Re[2]: реализация звуковго jitter-буфера
От: Аноним  
Дата: 06.02.07 19:49
Оценка:
Здравствуйте, Morpheus_, Вы писали:

M_>Здравствуйте, <Аноним>, Вы писали:


А>>Привет, не подскажет-ли кто-нибудь как правильно реализовывать механизм работы с jitter-буфером?

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

M_>приходящие пакеты складывать в Queue. При запуске записать в буфер несколько пустых пакетов, после чего в callback вызываемом по окончании проигрывания буфера делать Dequeue следующего пакета и писать его в буфер.

M_>Проблема будет в несоответствии частот кварцевого резонатора звуковой карты на машине где звук проигрывается и где звук записывается...
M_>Если на машине где звук проигрывается частота кварца чуть больше то наступит момент когда все пакеты будут проиграны, а новые еще не успели прийти. Если наоброт, то Queue будет постоянно расти, пока не наступит out of memory...
M_>Соответственно изредка будут щелчки и похрипывания, как это решить толком не знаю.
M_>Есть идея вести какуюто переменную в которой расчитывать критерий запаздывания/ускорения и по нему выкусывать или вставлять лишние сэмплы в пакеты, но при этом пакеты прийдется коцать и собирать новые

А если попробовать корректировать свойство Buffer.Frequency буффера воспроизведения ?
Re[6]: реализация звуковго jitter-буфера
От: Morpheus_  
Дата: 07.02.07 10:11
Оценка:
Здравствуйте, ANM, Вы писали:

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


ANM>Совершенно верно.


разница будет очень мала, на небольших отрезках времени ее вообще не будет. Но чем больше время записи, тем больше накопится разница, в какойто момент она станет равна одному лишнему байту, еще через какоето время двум, трем и т.д.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[7]: реализация звуковго jitter-буфера
От: postfix  
Дата: 07.02.07 18:43
Оценка:
а как насчёт такой идеи: динамически подстраивать частоту SecondaryBuffer с помощью свойства Frequency, например следить за степенью заполнения jitter-буфера и при его переполнении увеличивать Frequency на 1% от начального значения а при полном опустошении наоборот уменьшать её на 1%, так после нескольких повторов буфер подстроится под нужную скорость проигрывания входящих звуковых пакетов..?
Re[8]: реализация звуковго jitter-буфера
От: ANM Россия  
Дата: 07.02.07 20:17
Оценка:
Здравствуйте, postfix, Вы писали:

P>а как насчёт такой идеи: динамически подстраивать частоту SecondaryBuffer с помощью свойства Frequency, например следить за степенью заполнения jitter-буфера и при его переполнении увеличивать Frequency на 1% от начального значения а при полном опустошении наоборот уменьшать её на 1%, так после нескольких повторов буфер подстроится под нужную скорость проигрывания входящих звуковых пакетов..?


Не сработает, Frequency нельзя менять с большой точностью. Как бы вообще там не оказался фиксированный набор частот.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.