Я работаю над аналогичным проектом. Исходя из всего, что я прочитал, и из личного опыта, ваш лучший вариант - работать с небольшими кусочками данных и отправлять их как можно скорее. Вы хотите, чтобы любая буферизация дрожания выполнялась на стороне приемника.
Для приложения VoIP характерно отправлять 50-100 пакетов в секунду. Для кодирования uLaw на 8000 Гц это привело бы к размеру пакета 80-160 байт. Это объясняется тем, что некоторые пакеты неизбежно будут отброшены, и вы хотите, чтобы влияние на получателя было как можно меньше. Таким образом, при 10 мс или 20 мс аудиоданных на пакет упавший пакет может привести к небольшому сбоям, но не так плохо, как потеря 2 тыс. Аудиоданных (~ 250 мс).
Кроме того, при большом размере пакета необходимо накапливать все данные у отправителя перед его отправкой. Таким образом, учитывая типичную задержку в сети 50 мс при 20 мс аудиоданных на пакет, получатель не будет слышать то, что говорит отправитель, как минимум 70 мс. А теперь представьте, что происходит, когда одновременно отправляется 250 мс звука. 270 мсек пройдет между отправителем, говорящим и получателем, воспроизводящим этот звук.
Пользователи, кажется, более и более снисходительны к потере пакетов здесь и там, что приводит к качеству звука ниже номинального, потому что качество звука большинства телефонов не так уж велико с самого начала. Тем не менее, пользователи также привыкли к очень низкой задержке в современных телефонных сетях, поэтому введение задержки туда и обратно даже в 250 мс может быть крайне неприятным.
Теперь, что касается реализации буферизации, я нашел хорошую стратегию, чтобы использовать Очередь (упс, используя .NET здесь :)), а затем обернуть это в класс, который отслеживает желаемое минимальное и максимальное количество пакетов в очередь. Используйте строгую блокировку, поскольку вы, скорее всего, будете получать к ней доступ из нескольких потоков. Если очередь «выходит из строя» и содержит нулевые пакеты (переполнение буфера), установите флаг и возвращайте ноль, пока количество пакетов не достигнет желаемого минимума. Однако ваш потребитель должен будет проверить, возвращено ли значение null, и ничего не помещать в буфер вывода. В качестве альтернативы ваш потребитель может отслеживать последний пакет и повторно ставить его в очередь, что может вызвать зацикливание звука, но в некоторых случаях это может «звучать» лучше, чем тишина. Вам придется делать это до тех пор, пока производитель не поместит достаточно пакетов в очередь, чтобы достичь минимума. Это приведет к более длительному периоду молчания для пользователя, но это обычно лучше, чем короткие, частые периоды молчания (прерывистость). Если вы получаете пакет пакетов, и производитель заполняет очередь (достигая желаемого максимума), вы можете либо начать игнорировать новые пакеты, либо отбросить достаточно пакетов с начала очереди, чтобы вернуться к минимуму.
Трудно выбрать эти минимальные / максимальные значения. Вы пытаетесь сбалансировать плавный звук (без потерь) с минимальной задержкой между отправителем и получателем. VoIP это весело, но это может быть разочарование! Удачи!