PJMEDIA 延迟缓冲区实现

PJMEDIA实现了一个自适应的延迟缓冲区,延迟缓冲区很像一个固定的抖动缓冲区,用于缓冲那些不按照确定时间间隔到达的帧,这样调用者就能够连续地从缓冲区获取到帧。当get()和put()操作并不是均匀地间隔进行,延迟缓冲区会十分有用,例如:调用者没有规律,急速地多次进行put操作然后又急速地多次进行get操作。有了延迟缓冲区,假设get和put操作速率不匹配,急速放入的帧总是能够被匀速地获取。

延迟缓冲区是自适应的,它通过不断学习来掌握用于实时音频流的最优延迟时间。一旦最优的延迟时间被确定,将这个时间用于音频流的缓冲区,当实际的语音样本过少或过多,就可以扩大或缩小语音样本数量,这样做不至于扭曲语音质量。

PJMEDIA 延迟缓冲区主要用在PJMED_SND_PORT、PJMEDIA_SPLITCOMB、PJMEDIA_CONF。使用WSOLA(波形相似的叠加)算法。

 

延迟缓冲区的外部接口定义了创建缓冲区,从缓冲区读(消费),向缓冲区写(生产),销毁缓冲区,重置缓冲区等操作。

延迟缓冲区的基本属性:

--每帧的样本数量(samples_per_frame)

--帧时长(ptime):ms为单位

--声道数量(channel_count)

--最大缓冲样本数量(max_cnt)

--缓冲样本的有效数量(eff_cnt):有效数量值在延迟和稳定之间保持最优平衡,根据突发级别计算而来。

延迟缓冲区的可学习属性:

--突发级别计数器:记载连续相同操作的次数,比如生产者连续做了3次写put操作,中间没有做读get操作,则计数器值为3。一旦发生造作切换,则重置为1。

--上次执行的操作:消费(get)还是生产(put),用于比较本次操作是否与上次相同,若相同,则突发级别计数器加1。

--最大突发级别:记载当前突发级别计数器的最大值。

--计算最大突发级别的定时器:初值设置为2000,每次操作发生了切换时,则自减当前突发级别计数器的值与ptime积的2倍

 

创建延迟缓冲区时,需要指定采样频率,每帧样本数(samples_per_frame),声道数量channel_count,最大缓冲多长时间的延迟max_delay(默认为400ms)。采样频率,每帧样本数,声道数量可以计算出ptime。方法如下:

帧时长:ptime = samples_per_frame * 1000 / clock_rate / channel_count;

最大缓冲样本数量:max_cnt=samples_per_frame * (max_delay / ptime);

缓冲样本的有效数量设置为最大缓冲样本数量的一半:eff_cnt = max_cnt/2;

最大突发级别的计算定时器时长设置为每隔2000ms计算一次。

 

1.根据最大突发级别重新计算有效样本数量

 

   当最大突发级别定时器的值小于等于0时,需要重新计算有效样本数量。

   

   new_eff_cnt = (max_level*samples_per_frame)  / 2;

   eff_cnt = (eff_cnt + new_eff_cnt *3) >> 2;

   为确保eff_cnt 是channel_count的倍数,需要对其做对其操作:

   if (eff_cnt % channel_count)
        eff_cnt += channel_count - (eff_cnt % channel_count);

   max_level重置为0;

   recalc_timer重置为初始值(2000);

 

2. 收缩(shrinking)延迟缓冲区

 

      收缩采用WSOLA算法,保证播放时间缩短,但是并不影响音调(频率)。收缩操作一个参数:收缩数量。

      当操作发生了切换,且当前操作是put时,如果缓冲区的长度(能够容纳的样本数量)大于eff_cnt与samples_per_frame的和,则缓冲区需要收缩。 收缩数量为samples_per_frame的一半。

      向缓冲区写数据之前要检查当前缓冲区的剩余空间是否容纳得下一帧样本数据。如果容纳不下,也要做收缩操作,收缩数量恰好保证能够放入一帧。如果收缩失败,则之间一定缓冲区指针来清除缓冲区中最老的数据。

 

      缓冲区的增长和缩小要依据快速增长和缓慢减小的平滑原则。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值