Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
抖动缓冲区的Java实现_Java_Algorithm_Buffer_Voip - Fatal编程技术网

抖动缓冲区的Java实现

抖动缓冲区的Java实现,java,algorithm,buffer,voip,Java,Algorithm,Buffer,Voip,我正在为我的VOIP应用程序寻找Java中的自适应抖动缓冲区实现。我为我的应用程序编写了一个固定的抖动缓冲区,但由于网络质量差,我或者遇到了缓冲区不足或者缓冲区溢出的问题 是否有任何基于Java的自适应抖动缓冲区实现可直接用于我的应用程序或用作参考 任何帮助都将不胜感激 谢谢我一直在研究这个问题(虽然是用C语言),就在我认为我已经解决了这个问题的时候,互联网变得很忙,或者在某个地方发生了变化,然后繁荣起来!又是一些断断续续的声音。好。我很确定我现在已经被打败了 使用下面的算法,我的声音质量非常非

我正在为我的VOIP应用程序寻找Java中的自适应抖动缓冲区实现。我为我的应用程序编写了一个固定的抖动缓冲区,但由于网络质量差,我或者遇到了缓冲区不足或者缓冲区溢出的问题

是否有任何基于Java的自适应抖动缓冲区实现可直接用于我的应用程序或用作参考

任何帮助都将不胜感激


谢谢

我一直在研究这个问题(虽然是用C语言),就在我认为我已经解决了这个问题的时候,互联网变得很忙,或者在某个地方发生了变化,然后繁荣起来!又是一些断断续续的声音。好。我很确定我现在已经被打败了

使用下面的算法,我的声音质量非常非常好。我将它与我在相同网络条件下运行的其他软电话进行了比较,它的性能明显更好

我要做的第一件事是尝试确定我们正在注册的PBX或其他SIP代理是否位于UA(软电话)的本地网络上

如果是,我将jitterbuffer定义为100ms,如果不是,我使用200ms。这样,如果可以的话,我可以限制我的延迟;即使是200毫秒也不会产生任何明显的会话问题或过度交谈

所以。然后,我使用任何可用类型的系统计数器,例如Windows=GetTickCount64(),用我的第一个数据包进入播放时的毫秒精度时间填充变量。让我们称之为变量“x”

然后当((GetTickCount64()-x)>jitterbuffer)为true时,我开始在该缓冲区上播放

正向固定长度抖动缓冲区实现。这里是棘手的一点

当我解码RTP帧(如从muLaw到PCM)以缓冲播放时,我计算音频帧的平均绝对振幅,并将其与播放帧一起保存

我是通过这样的结构来实现的:

typedef struct tagCCONNECTIONS {
    char binuse;
    struct sockaddr_in client;
    SOCKET socket;
    unsigned short media_index;
    UINT32 media_ts;
    long ssrc;
    unsigned long long lasttimestamp;
    int frames_buffered;
    int buffer_building;
    int starttime;
    int ssctr;
    struct {
            short pcm[160];
    } jb[AUDIO_BUFFER]; /* Buffered Audio frame array */
    char jbstatus[AUDIO_BUFFER]; /* An array containing the status of the data in the     CCONNETIONS::jb array */
    char jbsilence[AUDIO_BUFFER];
    int jbr,jbw; /* jbr = read position in CCONNECTIONS::jb array, jbw = write position     */
    short pcms[160];
    char status;
    /* These members are only used to buffer playback */
    PCMS *outraw;
    char *signal;
    WAVEHDR *preparedheaders;
    /**************************************************/
    DIALOGITEM *primary;
    int readptr;
    int writeptr;
} CCONNECTIONS;
好的,请注意tagCCONNECTIONS::jbsilence[AUDIO_BUFFER]结构成员。这样,对于tagCCONNECTIONS::jb[x].pcm[]中的每个解码音频帧,都会有相应的数据来判断该帧是否可以听到

这意味着对于即将播放的每个音频帧,我们都有关于该帧是否可听见的信息

还有

#define READY 1
#define EMPTY 0
tagCCONNECTIONS::jbstatus[AUDIO_BUFFER]字段让我们知道正在播放的特定音频帧是准备好的还是空的。在缓冲区下溢的理论情况下,它可能是空的,在这种情况下,我们通常会等待它准备好,然后开始播放

现在在我播放音频的例行程序中…我有两个主要功能。一个名为pushframe(),另一个名为popframe()

打开网络连接并接收RTP的我的线程调用pushframe(),它将muLaw转换为PCM,计算帧的平均绝对振幅,并在无声时将其标记为静音,并将::jbstatus[x]标记为就绪

然后在播放音频的线程中,我们首先检查jitterbuffer时间是否已过期,再次检查

if ( ( GetTickCount64() - x ) > jitterbuffer ) {...}
然后,我们检查要播放的下一帧是否已准备就绪(意味着它确实已被填充)

然后,我们检查该帧之后的帧是否也准备就绪,以及是否可以听到或静音

***重要的

基本上,我们知道一个200毫秒的抖动缓冲器可以容纳10个20毫秒的音频帧

如果在初始200毫秒抖动缓冲延迟(保存音频)后的任何时候,我们排队的音频帧数下降到10(或jitterbuffer/20)以下,我们进入我称之为“buffer_building”模式。如果我们计划播放的下一个音频帧是静默的,我们会告诉程序抖动缓冲区还没有满,离满还有20毫秒,但我们继续播放我们现在播放的帧,因为我们看到的下一个帧是“静默的”…再次。我们只是不播放静默帧,而是使用静默时间段等待入站帧来重新填充缓冲区

tagCCONNECTIONS::lasttimestamp = GetTickCount64() - (jitterbuffer-20);
在“假定”的静默期间,这将有一段完全静默的时间,但允许缓冲区自我补充。然后,当我又满了10帧时,我会退出“buffer_building”模式,只播放音频

我进入“buffer_building”(缓冲区建筑)模式,即使我们距离一个完整的缓冲区只有一帧,因为可能会有一个唠叨不休的人在说话,也不会有太多的沉默。即使在“buffer_building”(缓冲区构建)模式下,也会很快耗尽缓冲区

现在…“什么是沉默?”我听到你问。在我的胡闹中,我将静默硬编码为平均绝对16位PCM振幅小于200的任何帧。我的估计如下:

int total_pcm_val=0;
/* int jbn= whatever frame we're on */
for (i=0;i<160;i++) {
    total_pcm_val+=ABS(cc->jb[jbn].pcm[i]);
}
total_pcm_val/=160;
if (total_pcm_val < 200) {
    cc->jbsilence[jbn] = 1;
}
int-total\u-pcm\u-val=0;
/*int jbn=无论我们在哪一帧上*/
对于(i=0;ijb[jbn].pcm[i]);
}
总数_pcm_val/=160;
如果(总pcm值<200){
cc->jbn[jbn]=1;
}

现在,我计划在这个连接上保持一个总的平均振幅,如果我们当前接收到的音频帧的振幅是整个平均振幅的5%或更少,那么我们认为帧是无声的,或者可能是2%……我不知道,但是如果有大量的风或背景噪声的话,“沉默”的定义可以适应。我必须处理这个问题,但我相信这是补充抖动缓冲的关键

当没有重要的信息要听时就去做,并保持真实的信息(他们的声音)清晰无误


我希望这有帮助。说到解释,我有点头脑混乱,但我非常非常满意我的VoIP应用程序的声音。

你到底有什么问题?估计所需的缓冲区大小?(排队论可能有帮助。)还是动态内存分配?或者别的什么?我希望能够根据当前抖动改变缓冲区大小。我可以计算变化的抖动并找到一个新的抖动值。但不知道怎样才能用来形容