低比特率的编解码器的制作方法

文档序号:2819952阅读:266来源:国知局
专利名称:低比特率的编解码器的制作方法
技术领域
本发明涉及信号的预测编码和解码,特别涉及代表诸如语音(speech)的声音、音频或视频的信号的预测编码和解码。

背景技术
像在基于网际协议的网络(主要是因特网或内部网)上的语音、音频或视频那样的在分组交换网络上的实时传输,由于众多特征而变得愈发吸引人。这些特征包括诸如较低的操作开支、容易集成新的服务和同一网络既用于非实时数据也用于实时数据等等。实时数据通常是语音、音频或视频信号,在分组交换系统中被转换成数字信号,即转换为比特流,其被划分成合适大小的部分,以便在分组交换网络上以数据分组从发送端传输到接收端。
由于分组交换网络原本是为非实时数据的传输而设计的,所以在这种网络上传输实时数据会造成某些问题。数据分组在传输中会丢失,因为它们会因阻塞问题或传输错误而被网络有意舍弃。在非实时应用中,由于可以重发丢失的分组,所以这不成问题。然而,对于对延迟敏感的实时应用来说,重发是不可能的解决方案。太晚到达的实时应用的分组无法被用来复原(reconstruct)相应信号,因为这个信号早已或本该被传递至接收端了,例如,被扬声器回放或在显示器屏幕上显示。因此,太晚到达的分组就等同于丢失的分组。
当传送如分组的实时信号时,丢失或延迟的数据分组的主要问题是在复原的信号中引入了失真。该失真是缘于以下事实丢失或延迟的分组所传达的信号片断无法被复原。
当传送信号时,最经常希望使用尽可能小的带宽。众所周知,许多信号具有包含冗余的模式(pattern)。适当的编码方法可避免冗余信息的传输,从而使信号传输的带宽更高效。利用这些冗余的通常的编码方法是预测编码方法。预测编码方法基于模式呈现间的依存(dependency)而对信号模式进行编码。它以固定比特率对发送信号进行编码并在信号质量和传输比特率之间有一个平衡。用于语音的预测编码方法的例子是线性预测编码(LinearPredictive Coding,LPC)和编码激励线性预测(Code Excited Linear Prediction,CELP),这两种编码方法皆是本领域的技术人员所熟知的。
在预测编码方案中,编码器状态取决于信号前面编码的部分。当与编码信号的分组化(packetization)相结合而使用预测编码时,丢失分组将导致错误传播,这是因为在接收端的预测编码器状态所依赖的信息将与丢失的分组一道丢失。这意味着后续分组的解码将以不正确的编码器状态开始。因此,由丢失分组而造成的错误将在信号的解码和复原期间传播。
解决这一错误传播问题的一种方式是在分组所包含的编码信号部分起始复位编码器状态。然而,这样的编码器状态的重置将导致复原信号的质量降级。减少丢失分组的影响的另一方式是当对信号进行编码时使用不同方案(scheme)来包含冗余信息。按这种方式在丢失分组后的编码器状态可被近似。然而,这种方案不仅需要更多的带宽用来传送编码信号,而且也仅是减少了丢失分组的影响。由于丢失分组的影响不能彻底消除,所以错误传播仍将存在并导致复原信号在感觉(perceptual)上的低质量。
现有技术预测编码器的另一问题是在例如语音信号的播音开始(voicingonset),从相对很低到很高的信号电平的信号骤变时的编码以及随后的复原。当对这种过渡进行编码时,难以使编码器状态反映出该骤变(suddentransition),更重要的是反映出过渡后的有音时期的开始。这又接着将导致在解码端的复原的信号质量的降级。


发明内容
本发明的一个目的在于至少克服一些上述与以分组来传输的信号的预测编码/解码相关的问题。
本发明的另一个目的是当具有从编码端发送来的编码信号部分的分组在解码端接收之前丢失时,能够改善与预测编码/解码相关的解码端的性能。
本发明的另一个目的是改善受到信号功率骤增的信号的预测编码和解码。
根据本发明,这些目的是由具有如所附权利要求书所定义的特征并代表本发明的不同方面的方法、设备和计算机可读媒体来实现的。
根据本发明,信号被划分成块并接着在逐块的基础上被编码,并最终被解码。该想法是要提供块的预测编码/解码,从而使编码/解码不取决于任何先前的块,同时仍能以信号的对应部分与信号的其它部分同样质量级别而再生的方式,提供该块的起始端的预测编码/解码。这是通过将块的编码和解码基于位于块的末端边界间某处的编码起始状态上而实现的。该起始状态是使用任何适宜的编码方法来进行编码/解码。如果确定第3部分存在,则使用任何预测编码方法对在起始状态并且在该块边界之间的各自侧的第2块部分和第3块部分进行编码/解码。为了方便在起始状态周围的这两个块部分的预测编码/解码,并且由于这两个块部分的编码/解码将基于同一起始状态,所以这两块部分在彼此相对的方向上进行编码/解码。例如,位于块的末端部分的块部分是沿信号模式在时间上的出现顺序来进行编码/解码的,而位于块的起始的另一部分是沿信号模式在时间上的反向出现顺序来进行编码/解码的,即从较晚出现的信号模式到较早出现的信号模式。
通过根据本发明在三个阶段来对块进行编码,可实现块之间的编码独立性,并总能方便块的起始端的正确预测编码/解码。这三个阶段是 *对块的第1部分进行编码,该编码的部分代表编码的起始状态。
*使用预测编码方法来对在编码的起始状态和块末端边界之一之间的第2块部分进行编码,该预测编码方法从起始状态到末端边界逐步地对这个第2块部分进行编码。
*确定编码的起始状态和另一个块末端边界之间是否存在第3块部分,如果存在,则使用预测编码方法来对第3块部分进行编码,该预测编码方法从起始状态到这个另一个末端边界逐步地对这个第3块部分进行编码。相对于与该块相关联的时间轴(time base),第3块部分和第2块部分的编码相比较是以相反方向进行编码的。
相应地,当再生对应的解码的信号块时,编码的块的解码是在三个阶段来进行的。
*对编码的起始状态进行解码。
*对块的编码的第2部分进行解码。使用基于起始状态的预测解码方法以用来再生位于起始状态和块的两端边界之一之间的块的第2部分。
*确定是否存在编码第3块部分,如果存在,则对这个块的编码的第3块部分进行解码。同样地,使用基于起始状态的预测解码方法来再生位于起始状态和块的两端边界的另一端之间的块的第3部分。相对于与该再生块关联的时间轴,块的这个第3部分和块的第2部分的再生相比较是以相反方向而再生的。
根据本发明而受到编码的信号要么相应于数字信号,要么相应于分析滤波的数字信号的剩余信号。该信号包括连续模式,其代表诸如语音或音频的声音,或其它可表现为连续模式的现象,例如视频或心电图(ECG)信号。于是,本发明适用于任何可被编码从而以彼此相关的连续状态来描述的连续模式。
更优地,起始状态的编码/解码使用不取决于信号先前部分的编码方法,于是使得该块对于定义起始状态的信息而言是独立的。然而,当本发明应用于LPC剩余域(residual domain)时,最好是将预测编码/解码也用于起始状态。通过假设在起始状态开始之前的解码信号中的量化噪声可被忽略,则可以从零状态开始预测编码器的错误加权或错误反馈滤波。这样可实现起始状态的独立编码。
更优地,信号块被划分成一组连续的间隔,并且选择起始状态以对应于那些具有最高信号能量的间隔的一个或更多连续的间隔。这意味着起始状态的编码/解码可向着具有相对较高信号能量的信号部分进行最优化。以这种方式,实现了其余块的编码/解码,从感觉的观点来看,它是很高效的,因为它可以基于以高精度进行编码/解码的起始状态。
本发明的一个优点是它使得预测编码以这种方式来进行即编码块独立于激励域(excitation domain)中的信息,即编码信息不会与任何先前编码块中的信息相关联。结果,在解码时,编码块的解码是基于编码块中独立的信息的。这意味着若携带编码块的分组在传输期间丢失了,则后续编码块的预测解码将不受丢失的分组中的丢失状态信息的影响。
于是,当携带编码块的分组在被解码端接收之前丢失时,本发明避免了以往的预测编码/解码在解码时遇到的错误传播问题。相应地,应用本发明的特征的编解码器将对分组的丢失变得更有鲁棒性(robust)。
更优地,选择起始状态以使其位于与最高信号功率相关联的块部分中。例如,在由有声和无声部分构成的语音信号中,这意味着在包括无声和有声部分的块中,起始状态将几乎完全位于块中的有声部分内。
在语音信号中,有声部分内的信号取样之间存在高相关性,而无声部分内的信号取样之间存在低相关性。无声部分和有声部分间的过渡区中的相关性很微弱而且难以利用。从感觉的观点来看,更重要的是当对信号的有声部分进行再生时,达到良好的波形匹配,而无声部分的波形匹配则不太重要。
传统预测编码器以同一顺序对信号表示进行操作,即利用信号源产生对应的信号。于是,任何代表特定时刻信号的编码器状态将与代表信号较早部分的先前编码器状态相关联。由于难以利用从无声时期到有声时期的过渡期间的相关性,所以传统的预测编码器的编码器状态将在这样的过渡随后的有声时期开始期间、包含给出原始信号的非常低劣近似的信息。结果,在解码端的语音信号的再生将为有声区的开始提供感觉上的降级的信号。
通过将起始状态几乎完全放置于(well within)块的有声区内,然后从起始状态向末端边界对块进行编码/解码,从而本发明能够更充分地利用有声区中的高相关性,以使收听受益。从无声到高度周期性的有声声音的过渡需要数个音调周期。当将起始状态几乎完全置于块的有声区内时,起始状态编码的高比特率将应用于已建立起高度周期性的音调周期,而不是应用于有声区域的第一音调周期之一。
在下面的说明中,本发明的上述和其它特点和优点将被更多地说明。



图1表示在分组交换网络上用于传输声音的系统的发送部分的概要; 图2表示在分组交换网络上用于传输声音的系统的接收部分的概要; 图3表示剩余信号块的例子; 图4表示用于对图3的剩余进行编码的起始状态的整数(integer)子块和更高的解析度目标; 图5表示根据本发明的实施例的对起始状态进行编码的编码器的功能框图; 图6表示对应于图5的编码器实行解码操作的解码器的功能框图; 图7表示从起始状态向块末端边界的信号的编码;和 图8表示本发明的实施例有利地利用的自适应密码本搜索的功能框图。

具体实施例方式 根据本发明的编码和解码功能通常包含于具有编码器部分和解码器部分的编解码器中。参照图1和2,在用于在分组交换网络上传输声音系统中表示本发明的实施例。
在图1中,根据本发明操作的编码器130包含于发送系统中。在这个系统中,声波由麦克风110拾取并转换成模拟电信号115。这个信号被A/D转换器120取样和数字化,以产生取样的信号125。取样的信号被输入编码器130。从编码器的输出是数据分组135。每个数据分组包含关于取样的块的压缩信息。经由控制器140,数据分组被递交至分组交换网络。
在图2中,根据本发明操作的解码器270包含于接收系统中。在这个系统中,数据分组由控制器250从分组交换网络接收,并存储于抖动(jitter)缓冲器260。从抖动缓冲器将数据分组265提供给解码器270。解码器的输出是取样的数字信号275。每个数据分组得到信号取样的一个块。取样的数字信号被输入D/A转换器280,结果得到模拟电信号285。这个信号可被递交至含有扬声器的声音转换器290,结果得到再生的声波。
编解码器的本质上是线性预测编码(LPC),其已知有别于(known from)自适应预测编码(APC)和代码激励线性预测(CELP)。然而,根据本发明的编解码器却使用了起始状态,即使用定位在信号块内的序列取样,以初始化信号块的剩余部分的编码。本发明的原理遵循LPC的开环综合分析(analysis-synthesis)方法、以及闭环综合分析方法,其是已知有别于CELP的。在感觉加权的域(perceptually weighted domain)中的开环编码提供了一种综合分析的替代选择,以得到编码噪声的感觉加权。当与综合分析做比较时,这个方法提供了提出的方案的语音质量和计算复杂度之间的有利的折衷(compromise)。在感觉加权域中的开环编码将在本说明书的后面进行说明。
编码器 在图1的实施例中,编码器的输入是数字信号125。这个信号可采取以8Hz取样并去除了直流(DC)分量的16位统一脉冲码调制(PCM)的格式。该输入被分割成例如240个取样的块。每个块又被再细分成例如6个连续子块,每个子块有40个取样。
原则上可使用任何方法来从信号块中提取频谱包络(spectral envelop),而不脱离本发明的精神。一种方法的概括如下对于每个输入块,编码器进行一定数量的(例如2次)线性预测编码(LPC)分析,每次使用例如10的阶数(order)。结果使得LPC系数被编码,最好是以线性频谱频率(LSF)的形式来编码。LSF的编码是本领域的技术人员是熟知的。这个编码可利用各组系数之间的相关性,例如,通过使用某些组的预测编码。LPC分析可利用不同的、并且可能是不对称的窗函数,从而在窗的平滑和居中与在编码中引入的超前延迟(lookahead delay)之间得到良好的折衷。量化的LPC显示可有利地被内插(interpolate)以得到大量平滑地随时间变化的LSF系数组。随后,使用被变换成用于分析滤波器的系数的、量化且平滑地内插的LSF系数,得到LPC剩余。
剩余信号块315的例子及其分隔成的子块316、317、318、319、320和321如图3所示,子块的数量仅是示例性的。在这个图中的时间轴上的各间隔表示1个子块。图3中示例的剩余块中起始状态的目标识别如图4所示。在一种简单的实施中,这个目标可以被识别成剩余的2个连续子块317和318,其展现了块内任何2个连续子块的最大能量。此外,通过识别2个子块间隔内可能预定长度的连续取样325的子集,目标的长度可进一步被缩短并以更高的时间解析度进行定位(localize)。最好是将这样的子集选择为在2个子块间隔中拖曳或拖尾(trailing or tailing)的预定数量的例如58个取样。同样地,拖曳或拖尾的子集间的选择也可基于最大能量标准。
起始状态的编码 在不脱离本发明精神的情况下,起始状态基本上可以用任何编码方法来编码。
根据本发明的实施例,使用了具有预测噪声整形的标量量化(scalarquantization),如图5所示。按本发明,标量量化用全通滤波器520来预先极化,该全通滤波器520被设计成将在所有取样上的取样能量扩展到起始状态中。已经发现,这导致了在低速率绑定标量量化器的过载和颗粒噪声之间的良好平衡。这样的全通滤波器的简单设计是这样得到的沿时间正向应用LPC综合滤波器,并沿时间反向应用对应的LPC分析滤波器。具体地说,当量化的LPC分析滤波器是Aq(z)时,具有系数516。则全通滤波器520由Aq(z^-1)/Aq(z)给出。对于在解码器中这个滤波器的逆操作来说,应当使用编码的LPC系数,并且滤波应当是起始状态的长度的圆周卷积。起始状态编码器的其余部分是本领域的技术人员熟知的滤波的目标525由归一化530归一化,以展示预定的最大振幅,以得到归一化的目标535和量化归一化的因数536的指数。量化误差的加权被划分成归一化目标535的滤波540和量化目标556的滤波560,由此对于每个取样从加权目标545中减去瞬变(ringing)或零输入响应566,以得出量化目标547,其被输入量化器550。结果得到量化的起始状态的指数555序列。
可将噪声整形加权滤波器540和560应用于这个实施例中。最好是将同样的噪声整形应用于起始状态的编码中,以及后述的剩余信号块的后续编码中。例如,噪声整形可以这样来实施在使用等于A(z/L1)/(Aq(z)*Aq(z/L2))的加权滤波器对量化误差进行加权之后,最小化量化误差,其中A(z)是在可能的初始带宽扩展后的非量化的LPC分析滤波器,Aq(z)是量化的LPC分析滤波器,而L1和L2是带宽扩展系数,其可分别有利地被设置成L1=0.8和L2=0.6。这个滤波中需要的全部LPC和加权系数在图5中在输入546和565采集。一种当剩余编码以后述的第3替代方法来完成时的有用的具有更短脉冲响应的替代选择是设置L1=1.0和L2=0.4。
以下是起始状态编码器的C代码示例实施。
void StateSearchW(/*状态的编码*/float*residual,/*(i)目标剩余向量,即图5中的信号515*/  float*syntDenum,/*(i)图5中的信号516、546和565的lpc系数*/  float*weightNum,/*(i)图5中的信号546和565的加权滤波器的分子*/  float*weightDenum,/*(i)图5中的信号546和565的加权滤波器的分母*/  int*idxForMax,/*(o)最大振幅的量化器指数,即图5中的信号536*/  int*idxVec,/*(o)量化指数的向量,即图5中的信号555*/  int len/*(i)全部向量的长度,例如58*/);  void AbsQuantW(float*in,float*syntDenum,float*weightNum,float*weightDenum,int*out,int len){   float*target,targetBuf[FILTERORDER+STATE_LEN],  *SyntOut,syntOutBuf[FILTERORDER+STATE LEN],  *WeightOut,weightOutBuf[FILTERORDER+STATE_LEN],  toQ,xq;  int n;  int index;  memset(targetBuf,0,FILTERORDER*sizeof(float));<!-- SIPO <DP n="8"> --><dp n="d8"/>  memset(syntOutBuf,0,FILTERORDER*sizeof(float));  memset(weightOutBuf,0,FILTERORDER*sizeof(float));  target=&amp;targetBuf[FILTERORDER];  syntOut=&amp;syntOutBuf[FILTERORDER];  weightOut=&amp;weightOutBuf[FILTERORDER];  for(n=0;n<len;n++){  if(N==STATE_LEN/2{  syntDenum+=(FILTERORDER+1);  weightNum+=(FILTERORDER+1);  weightDenum+=(FILTERORDER+1);  }  AllPoleFilter(&amp;in[n],weightDenum,1,FILTERORDER);  /*这个函数进行向量in的全极性滤波,结果返回到同一向量中*/  /*这是图5中的滤波540*/  syntOut[n]=0.0;  AllPoleFilter(&amp;syntOut[n],weightDenum,1,FLILTERORDER);  /*这是图5中的滤波560*/  /*量化器*/  toQ=in[n]-syntOut[n];/*这是从信号545中减去信号566以得到图5中的信号547*/  sort_sq(&amp;xq,&amp;index,toQ,states3,8);  /*这个函数进行标量量化*/  /*这是图5中的函数550*/  out[n]=index;  syntOut[n]=state_sq3[out[n]];  AllPoleFilter(&amp;syntOut[N],weightDenum,1,FILTERORDER);<!-- SIPO <DP n="9"> --><dp n="d9"/>  /*这更新了图5中的加权滤波器560,用于下一取样*/  }  }  void StateSearchW(float*residual,float*syntDenum,float*weightNum,float*weightDenum,int*idxForMax,int*idxVec,int len){  float dtmp,maxVal,tmpbuf[FILTERORDER+2*STATE_LEN],*tmp,numerator[1+FILTERORDER],foutbuf[FILTERORDER+2*STATELEN],*fout;  int k,utmp;  in index;  memset(tmpbuf,0,FILTERORDER*sizeof(float));  memset(foutbuf,0,FILTERORDER*sizeof(float));  for(K=0;K<T;FILTERORDER;k++){  numerator[k]=syntDenum[FILTERORDER-k];  }  numerator[FILTERORDER]=synthDenum
;  tmp=&amp;tmpbuf[FILTERORDER];  fout=&amp;foutbuf[FILTERORDER];  /*从这里*/  memcpy(tmp,residual,len*sizeof(float));  memset(tmp+len,0,len*sizeof(float));  ZeroPoleFilter(tmp,numerator,syntDenum,2*len,FILTERORDER,fout);  /*这个函数进行tmp的零极性滤波并将滤波的向量返回到fout中*/  for(k=0;k<len;k++){  fout[k]+=fout[k+len];  }<!-- SIPO <DP n="10"> --><dp n="d10"/>  /*到这里是图5中的全通滤波520*/  maxVal=fout
;  for(K=L;K<LT;LEN;k++){  if(fout[k]*fout[k]>maxVal*maxVal){  maxVal=fout[k];  }  }  maxVal=(float)fabs(maxVal);  if(maxVal<T;10.0)(  maxval=10.0;  )  maxVal=(float)log10(maxVal);  sort_sq(&amp;dtmp,&amp;index,maxVal,state_frgq,64);  /*这个函数进行平方值的排序*/  maxVal=state_frgq[index];  utmp=index;  *idxForMax=utmp;  maxVal=(float)pow(10,maxVal);  maxval=(float)(4.5)/maxVal;  for(k=0;K<len;k++){  fout[K]=maxVal;/*这是图5中的归一化530*0/  }  AbsQuantW(fout,syntDenum,weightNum,weightDenum,idxVec,len);  } 起始状态的解码 起始状态的解码自然遵循应用在起始状态的编码的方法。对应于图5中编码方法的解码方法如图6所示。首先在标量密码本620中查找指数615,结果得到量化的起始状态625的复原(reconstruction)。量化的起始状态接着使用量化的归一化因数626的指数进行去归一化630。这产生了去归一化的起始状态635,其被输入采用系数636的逆全通滤波器640,结果得到解码的起始状态645。以下是起始状态解码的C代码示例。
void StateConstructW(/*对语音剩余的一种状态进行解码*/  int idxForMax,/*(i)最大振幅的量化的7比特指数,即图6中的信号626*/  int*idxVec,/*(i)量化指数的向量,即图6中的信号615*/  float*SyntDenum,/*(i)综合滤波器分母,即图6中的信号636*/  float*out,/*(o)解码的状态向量,即图6中的信号645*/  int len/*(i)状态向量的长度,例如58*/  )  {  float max Val,tmpbuf[FILTERORDER+2*STATE_LEN],*tmp,numerator[FILTERORDER+1];  float foutbuf[FILTERORDER+2*STATE_LEN],*fout;  intk,tmpi;  maxVal=state_frgq[idxForMax];  maxVal=(float)pow(10,maxVal)/(float)4.5;  memset(tmpbuf,0,FILTERORDER*sizeof(float));  memset(foutbuf,0,FILTERORDER*sizeof(float));  for(k=0;K<LT;FILTERORDER;k++){  numerator[k]=syntDenum[FILTERORDER-k];  }  numerator[FILTERORDER]=syntDenum
;  tmp=&amp;tmpbuf[FILTERORDER];  fout=&amp;foutbuf[FILTERORDER];  for(k=0;K<LT;len;k++){  tmpi=len-l-k;<!-- SIPO <DP n="12"> --><dp n="d12"/>  tmp[K]=maxVal*state_sq3[idxVec[tmpi]];  /*这是图6中的操作620和630*/  )  /*从这里*/  memset(tmp+len,0,len*sizeof(float));  ZeroPoleFilter(tmp,numerator,syntDenum,2*len,FILTERORDER,fout);  for(k=0;k<len;k++)(  Out[k]=fout[len-L-K]+fout[2*len-l-K];}  /*到这里是图6中的操作640*/} 从起始状态向块边界的编码 在本发明的范围内,块的剩余取样可有多种方式来编码,这些方式都是利用了作为编码算法的状态的初始化的起始状态。最好地,线性预测算法可被用于剩余取样的编码。特别地,自适应密码本的应用使得在有声语音段期间有效地利用起始状态。在这种情况下,编码的起始状态被用来填充(populate)自适应密码本。而且,使用起始状态有利地进行错误加权滤波器的状态的初始化。这种初始化的具体细节可由本领域的技术人员熟知的多种方式来做。
从起始状态向块边界的编码由图7中的信号来示例。
在基于子块的实施例中,其中起始状态被识别成预定长度的间隔、直到由许多子块定义的间隔的一端,则最好是首先对剩余间隔应用自适应密码本算法,以达到由许多子块定义的整个间隔的编码。例如,起始状态715是信号645的例子,并且是起始状态目标325的解码的显示,该起始状态715被扩展至整数子块长度起始状态725。此后,这些子块被用作块A-B中的剩余子块的编码的起始状态(子块的数量仅是示例性的)。
这个编码可从编码时间上较晚的子块来开始,或可从编码时间上较早的子块来开始。尽管两种选择在本发明的范围内都是颇有可能的,但我们只详细地说明以时间上较晚的子块的编码来开始的实施例。
时间上较晚的子块的编码 如果块含有时间上晚于为起始状态编码的子块的子块,则自适应密码本和加权滤波器从用于编码时间上较晚的子块的起始状态进行初始化。这些子块的每个都被后续编码。在例子中,这将导致图7的信号735。
若多于一个子块在时间上晚于在该块中的整数子块起始状态,则自适应密码本存储器用编码的LPC激励来更新,以准备下一子块的编码。这是由本领域的技术人员熟知的方法来完成的。
时间上较早的子块的编码 如果块含有在时间上早于为起始状态编码的子块的子块,则将与应用于时间上较晚的子块的程序等同的程序应用于逆时间块(time-reversed block),以对这些子块进行编码。区别在于当与时间上较晚子块的编码进行比较时,现在不仅是起始状态,而且在时间上晚于起始状态的LPC激励都被应用于自适应密码本和感觉加权滤波器的初始化。在例子中,这将使信号735扩展成完全编码的显示745,即结果得到的LPC剩余315的解码显示。信号745构成解码器的LPC激励。
本发明的编码步骤已对图3~5中的语音LPC剩余信号做了示例。然而,在不脱离本发明范围的总体思想的情况下,这些步骤也适用于其它信号,例如时域中未滤波的声音信号或EKG等医疗信号。
从起始状态向块边界编码的C代码示例 void iLBC_encode(/*主编码器函数*/  float*speech,/*(i)语音数据向量*/  unsigned char*bytes,/*(o)编码的数据位*/  float*block,/*(o)解码的语音向量*/  int mode,/*(i)1用于标准编码、2用于冗余编码*/  float*decresidual,/*(o)增益适配前的解码剩余(对冗余编码单位有用)*/  float*syntdenum,/*(o)解码的综合滤波器(对冗余编码单位有用)*/  float*weightnum,/*(o)加权分子(对冗余编码单位有用)*/  float*weightdenum/*(o)加权分母(对冗余编码单位有用)*/  )  {  float data[BLOCKL];  float residual[BLOCKL],reverseResidual[BLOCKL];<!-- SIPO <DP n="14"> --><dp n="d14"/>  float weightnum[NSUB*(FILTERORDER+1)],weightdenum[NSUB*(FILTERORDER+1)];  int start,idxForMax,idxVec[STATE_LEN];  float reverseDecresidual[BLOCKL],mem[MEML];  int n,k,kk,meml_gotten,Nfor,Nback,i;  int dummy=0;  int gain_index [NSTAGES*NASUB],extra_gain_index[NSTAGES];  int cb_index[NSTAGES*NASUB],extra_cb_index[NSTAGES];  int lsf_i[LSF_NSPLIT*LPC_N];  unsigned char*pbytes;  int diff,start_pos,state-first;  float en1,en2;  int index,gc_index;  int subcount,subframe;  float weightState[FILTERORDER];  memcpy(data,block,BLOCKL*sizeof(float));  /*输入数据的LPC*/  LPCencode(syntdenum,weightnum,weightdenum,lsf-i,data);  /*这个函数进行LPC分析和量化,并平滑LPC系数的内插*/  /*得到剩余的逆滤波器*/  for(n=0;n<NSUB;n++){  anaFilter(&amp;data[N*SUBL],&amp;syntdenum[n*(FILTERORDER+L)],SUBL,&amp;residual[n*SUBL])  }  /*这个函数使用量化和内插的LPC系数来进行LPC分析滤波*/  /*此刻的剩余是例如图3中的信号315的信号*/<!-- SIPO <DP n="15"> --><dp n="d15"/>  /*找出状态位置*/  start=FrameClassify(residual);  /*这个函数以整数子帧的解析度来定位起始状态*/  /*变量start表示整数个子块中信号317,318(图4)的开始*/  /*检查状态是否在2个子帧的第1或最末部分*/  diff=STATE_LEN-TATE_SHORT_LEN;  en1=0;  index=(START-1)*SUBL;  for(i=0;i<STATE_SHORT_LEN;i++)en1+=residual[INDEX+i]*residual[INDEX+i];  en2=0;  index=(start-1)*SUBL+diff;  for(i=0;i<STATE_SHORT_LEN;i++)en2+=residual[index+i]*residual[INDEX+i];  if(en1>en2){  state-first=1;  start_pos=(start-1)*SUBL;  }else(  state-first=0;  start_pos=(start-1)*SUBL+diff;  }  /*变量start_pos现表示在整数数量的取样中的信号325(图4)的开始*/  /*状态的标量量化*/  StateSearchW(&amp;residual[start_pos],  &amp;syntdenum[(start-1)*(FILTERORDER+1)],  &amp;weightnum[(start-1)*(FILTERORDER+1)],  &amp;weightdenum[(start-1)*(FILTERORDER+1)],  &amp;idxForMax,idxVec,STATE_SHORT_LEN);  /*这个函数对起始状态进行编码(详见本说明书的上文)*/<!-- SIPO <DP n="16"> --><dp n="d16"/>  StateConstructW(idxForMax,idxVec,  &amp;syntdenum[(start-1)*(FILTERORDER+1)),  &amp;decresidual[start_pos],STATE_SHORT_LEN);  /*这个函数对起始状态进行解码*/  /*此刻的解码剩余含有例如图7中的信号715那样的信号*/  /*状态中的预测量化*/  if(state-first){/*将自适应部分放在最末*/  /*设置存储器*/  memset(mem,0,(MEML-STATE_SHORT_LEN)*sizeof(float));  memcpy(mem+MEML-STATE_SHORT_LEN,  decresidual+start_pos,STATE_SHORT_LEN*sizeof(float));  memset(weightState,0,FILTERORDER*sizeof(float));  /*对子帧进行编码*/  iCB Search{extra_cb_index,extra_gain_index,  &amp;residual[start_pos+STATE_SHORT_LEN],  mem+MEML-stMemL,stMemL,diff,NSTAGES,  &amp;syntdenum[(start-1)*(FILTERORDER+1)],  &amp;weightnum[(start-1)*(FILTERORDER+1)],  &amp;weightdenum[(start-1)*(FILTERODER+1)],weightState};  /*这个函数进行整形和增益指数的加权的多级搜索*/  /*构建解码的向量*/  iCBConstruct{&amp;decresidual[start_pos+STATE_SHORT_LEN],extra_cb_index,extra_gain_index,mem+MEML-stMemL,stMemL,diff,NSTAGES);  /*这个函数对多级编码进行解码*/  }<!-- SIPO <DP n="17"> --><dp n="d17"/>  else(/*将自适应部分放在开始*/  /*创建用于预测的逆向量*/  for(k=o;k<diff;k++){  reverseResidual[k]=residual[(start+1)*SUBL-1-(k+STATE_SHORT_LEN)];  reverseDecresidual[k]=decresidual[(start+1)*SUBL-1-(k+STATE_SHORT_LEN)];  }  /*设置存储器*/  meml_gotten=STATE_SHORT_LEN;  for(k=0;k<meml_gotten;k++){mem[MEML-L-K]=decresidual[start_pos+k];}  memset(mem,0,(MEML-k)*sizeof(float));  memset(weightState,0,FILTERORDER*sizeof(float));  /*对子帧进行编码*/  iCBSearch(extra_cb_index,extra_gain_index,reverseResidual,mem+MEML-stMemL,stMemL,diff,NSTAGES,  &amp;syntdenum[(start-1)*(FILTERORDER+1)],  &amp;weightnum[(stat-1)*(FILTERORDER+1)],  &amp;weightdenum[(start-1)*(FILTERORDER+1)],weightState);  /*构建解码的向量*/  iCBConstruct(reverseDecresidual,extra_cb_index,extra_gain_index,MEM+MEML-STMEML,stMemL,diff,NSTAGES);  /*从逆向量中得到解码剩余*/  for(k=0;k<diff;k++){  decresidual[start_pos-l-k]=reverseDecresidual[k];<!-- SIPO <DP n="18"> --><dp n="d18"/>  }  }  /*此刻的解码剩余含有例如图7中的信号725那样的信号*/  /*预测子帧的计数器*/subcount=0;  /*正向子帧的预测*/  Nfor=NSUB-start-1;  if(Nfor>0){  /*设置存储器*/  memset(mem,0,(MEML-STATELEN)*sizeof(float));  memcpy(mem+MEML-STATE_LEN,decresidual+(start-1)*SUBL,STATE_LEN*sizeof(float));  memset(weightState,0,FILTERORDER*sizeof(float));  /*在子帧上循环而编码*/  for(subframe=0;subframe<Nfor;SUBFRAME++){  /*编码子帧*/  iCBSearch(cb_index+subcount*NSTAGES,  gain_index+subcount*NSTAGES,  &amp;residual[(start+1+subframe)*SUBL],  mem+MEML-memLf[subcount],memLf[subcount],SUBL,NSTAGES,  &amp;syntdenum[(start+1+subframe)*(FILTERORDER+1)],  &amp;weightnum[(start+1+subframe)*(FILTERORDER+1)],  &amp;weightdenum[(start+1+subframe)*(FILTERORDER+1)],weightState);  /*构建解码的向量*/  iCBConstruct(&amp;decresidual[(start+1+subframe)*SUBL],cb_index+subcount*NSTAGES,gain_index+subcount*NSTAGES,mem+MEML-memLf[subcount],memLf[subcount],SUBL,NSTAGES);<!-- SIPO <DP n="19"> --><dp n="d19"/>  /*更新存储器*/  memcpy(mem,mem+SUBL,(MEML-SUBL)*sizeof(float));  memcpy(mem+MEML-SUBL,&amp;decresidual[(start+1+subframe)*SUBL],SUBL*sizeof(float));  memset(weightState,0,FILTERORDER*sizeof(float));subcount++;  }  }  /*此刻的解码剩余含有例如图7中的信号735那样的信号*/  /*子帧的反向预测*/  Nback=start-1;  if(Nback>0){  /*创建逆次序向量*/  for(n=0;n<Nback;n++){  for(k=0;K<LT;SUBL;k++){  reverseResidual[N*SUBL+k]=residual[(start-1)*SUBL-1-n*SUBL-k];  reverseDecresidual[N*SUBL+k]=decresidual[(start-1)*SUBL-1-n*SUB-k];}  /*设置存储器*/  meml_gotten=SUBL*(NSUB+1-start);  if(meml_gotten>MEML){meml_gotten=MEML;}  for(k=0;k<meml_gotten;k++){mem[MEML-1-k]=decresidual[(start-1)*SUBL+k];}  memset(mem,0,(MEML-k)*sizeof(float));  memset(weightState,0,FILTERORDER*sizeof(float));  /*在子帧上循环而编码*/  for(subframe=0;subframe<Nback;subframe++){<!-- SIPO <DP n="20"> --><dp n="d20"/>  /*对子帧进行编码*/  iCBSearch(cb_index+subcount*NSTAGES,  gain_index+subcount*NSTAGES,  &amp;reverseResidual[subframe*SUBL],  mem+MEML-memLf[subcount],memLf[subcount],SUBL,NSTAGES,  &amp;syntdenum[(start-1-subframe)*(FILTERORDER+1)],  &amp;weightnum[(start-1-subframe)*(FILTERORDER+1)],  &amp;weightdenum[(start-1-subframe)*(FILTERORDER+1)],weightState);  /*构建解码的向量*/  iCBConstruct(&amp;reverseDecresidual[subframe*SUBL],cb_index+subcount*NSTAGES,gain_indexl+subcount*NSTAGES,mem+MEML-memLf[subcount],memLf[subcount],SUBL,NSTAGES);  /*更新存储器*/  memcpy(mem,mem+SUBL,(MEML-SUBL)*sizeof(float));  memcpy(mem+MEML-SUBL,&amp;reverseDecresidual[subframe*SUBL],  SUBL*sizeof(float));  memset(weightState,0,FILTERORDER*sizeof(float));subcount++;}  /*从逆向量中得到解码剩余*/  for(i=0;i<SUBL*Nback;i++)  decresidual[SUBL*Nback-i-1]=reverseDecresidual[i];  }  /*此刻的解码剩余含有例如图7中的信号745那样的信号*/  ..将信息打包成字节  } 加权的自适应密码本搜索 在已说明的正向和反向编码程序中,自适应密码本搜索可在非加权的剩余域中进行,或可应用现有的综合分析加权。我们在这里详细说明适用于自适应密码本的第3方法。这种方法提供了综合分析的替代选择,并给出了性能和计算复杂度之间的良好折衷。该方法包括在构建自适应密码本之前的自适应密码本存储器和目标信号的预加权,以及之后的搜索密码本指数。
这种方法与综合分析比较其优点在于对密码本存储器的加权滤波导致较少的计算,少于自适应密码本的综合分析编码的零状态滤波器迭代(recursion)所需的计算。这个方法的缺陷在于加权密码本向量会具有零输入分量,其是来自密码本存储器中的过去取样,而不像在综合分析中那样是来自解码的信号的过去取样。这个负面影响可通过这样设计加权滤波器来压低即让加权滤波器在密码本向量的长度上、与零状态分量相比在零输入分量上具有低能量。A(z/L1)/(Aq(z)*Aq(z/L2))形式的加权滤波器的有利的参数是设置L1=1.0和L2=0.4。
第3方法的实施以图8来表示。首先自适应密码本存储器815和量化目标816在时间820上衔接(concatenate),结果得到缓冲825。这个缓冲器接着使用加权LPC系数836来加权滤波的830。加权缓冲器835接着分离840为对应于存储器和对应于目标的时间取样。加权的存储器845接着被用来搭建自适应密码本850。如本领域的技术人员所熟知的,自适应密码本855不需要与加权存储器845在物理存储器位置上不同,因为时移密码本向量与存储器缓冲中的时移取样可由相同方式来寻址。
以下是用于加权密码本搜索的这个第3方法的C代码示例实施。
void iCBSearch(/*自适应密码本搜索*/  int*index,/*(o)向量l指数。这是图8中的信号865*/  int*gain_index,/*(o)向量增益指数。这是图8中的信号866*/  float*target,/*(i)量化目标。这是图8中的信号816*/  float*mem,/*(i)自适应密码本的存储器。这是图8中的信号815*/  int 1Mem,/*(i)存储器的长度*/  int 1Target,/*(i)目标向量的长度*/  int nStages,/*(i)量化级数*/  float*weightDenum,/*(i)加权滤波器分母系数。这是图8中的信号836*/  float*weightState/*(i)用于目标滤波的加权滤波器的状态。这是图8中的<!-- SIPO <DP n="22"> --><dp n="d22"/>滤波830的状态*/  )  (  int i,j,icount,stage,best_index;  float max_measure,gain,measure,crossDot,invDot;  float gains[NSTAGES];  float cb[(MEML+SUBL+1)*CBEXPAND*SUBL];  int base_index,sInd,eInd,base_size;  /*用于加权*/  float buf[MEML+SUBL+2*FILTERORDER];  base_size=1Mem-1Target+1;  if(1Target==SUBL)  base size=1Mem-1Target+1+1Target/2;  memcpy(buf,weightState,sizeof(float)*FILTERORDER);  memcpy(&amp;buf[FILTERORDER],mem,1Mem*sizeof(float));  memcpy(&amp;buf[FILTERORDER+1Mem],target,1Target*sizeof(float));  /*此刻的buf是图8中的信号825*/  AllPoleFilter(&amp;buf[FILTERORDER],weightDenum,1Mem+1Target,FILTERORDER);  /*这个函数对buf做全极性滤波。所得结果返回到buf中。这是图8中的函数830*/  /*此刻的buf是图8中的信号835*/  /*构建所需的CB和目标*/  createCB(&amp;buf[FILTERORDER],cb,1Mem,1Target);  memcpy(target,&amp;buf[FILTERORDER+LMEM],1Target*sizeof(float));  /*此刻的目标是图8中的信号846而cb是图8中的信号855*/  /*级上的主循环*/<!-- SIPO <DP n="23"> --><dp n="d23"/>  /*此循环执行图8中的函数860*/  for(stage=0;stage<nStages;stage++){  max_measure=(float)-10000000.0;  bes_index=0;  for(icount=0;icount<base_size;icount++){  crossDot=0.0;  invDot=0.0;  for(j=0;j<1Target;j++){  crossDot+=target[j]*cb[icount*1Target+j];  invDot+=cb[icount*1Target+j]*cb[icount*1Target+j];  }  invDot=(float)1.0/(invDot+EPS);  if(stage==0){  measure=(float)-10000000.0;  if(crossDot>0.0)  measure=crossDot*crossDot*invDot;  }  else{  measure=crossDot*crossDot*invDot;  }  if(measure>max_measure){  best_index=icount;  max_measure=measure;  gain=crossDot*invDot;  }  }  base_index=best_index;  if(RESRANGE=-1){/*无限制搜索*/  sInd=0;  eInd=base_size-1;<!-- SIPO <DP n="24"> --><dp n="d24"/>  }  else{  sInd=base_index-RESRANGE/2;  if(sInd<0)sInd=0;  eInd=sInd+RESRANGE;  if(eInd>=base_size){  eInd=base_size-1;  sInd=eInd-RESRANGE;  }  }  for(i=1;I<CBEXPAND;I++){  sInd+=base_size;  eInd+=base_size;  for(icount=sInd;icount<=eInd;icount++){  crossDot=0.0;  invDot=0.0;  for(j=0;j<1Target;j++){  crossDot+=target[j]*CB[icount*1Target+j];  invDot+=  cb[icount*1Target+j]*CB[icount*1Target+j];  }  invDot=(float)1.0/(invDot+EPS);  if(stage=0){  measure=(float)-10000000.0;  if(crossDot>0.0)  measure=crossDot*crossDot*invDot;  )  else{  measure=crossDot*crossDot*invDot;  }if(measure>max_measure){  best_index=icount;<!-- SIPO <DP n="25"> --><dp n="d25"/>  max_measure=measure;  gain=crossDot*invDot;  }  }  }  index[stage]=best_index;  /*index是图8中的信号865*/  /*增益量化*/  if(stage==0){  if(gain<0.0)gain=0.0;  if(gain>1.0)gain=1.0;  gain=gainquant(gain,1.0,1 6,&amp;gain_index[stage]);  /*这个函数搜索增益量化的最佳指数*/  /*gain_index是图8中的信号866*/  }  else{  if(fabs(gain)>fabs(gains[stage-1])){  gain=gain*(float)fabs(gains[stage-1])/(float)fabs(gain);  }  gain=gainquant(gain,(float)fabs(gains[stage-1]),8,&amp;gain_index[stage]);  /*这个函数搜索增益量化的最佳指数*/  /*gain_index是图8中的信号866*/  }  /*更新目标*/  for(j=0;j<1Target;j++)target[j]-=gain*cb[index[stage]*1Target+j];  gains[stage]=gain;  }/*结束主循环for(stage=0;…*/  } 解码器 本发明所涵盖的解码器是任何与根据上述的编码器合作的解码器。这种解码器将从编码数据中提取起始状态的位置。它将对起始状态进行解码,并将它用作用来对剩余信号帧进行解码的存储器的初始化。在没有接收到数据分组的情况下,分组丢失弥补是很有利的。
以下是解码器的C代码示例实施。
void ILBC_decode(/*主解码器函数*/float*decblock,/*(o)解码的信号块*/unsigned char*bytes,/*(i)编码的信号位*/  int bytes_are_good/*(i)若字节是正确的数据则为1否则为0*/  ){  float reverseDecresidual[BLOCKL],mem[MEML];  int n,k,meml_gotten,Nfor,Nback,i;  int diff,start_pos;  int subcount,subframe;  float factor;  float std_decresidual,one_minus_factor_scaled;  int gaussstart;  diff=STATE LEN-TATE_SHORT_LEN;  if(state_first==1)start_pos=(start-1)*SUBL;  else start_pos=(start-1)*SUBL+diff;  StateConstructW(idxForMax,idx Vec,  &amp;syntdenum[(start-1)*(FILTERORDER+1)],  &amp;decresidual[start_pos],STATE_SHORT_LEN);  /*这个函数对起始状态进行解码*/  if(state_first){/*将自适应部分放在最末*/<!-- SIPO <DP n="27"> --><dp n="d27"/>  /*设置存储器*/  memset(mem,0,(MEML-STATE_SHORT_LEN)*sizeof(float));  memcpy(mem+MEML-STATE_SHORT_LEN,decresidual+start_pos,STATE_SHORT_LEN*sizeof(float));  /*构建解码向量*/  iCBConstruct(&amp;decresidual[startpos+STATE_SHORT_LEN],  extra_cb_index,extra_gain_index,  mem+MEML-stMemL,stMemL,diff,NSTAGES);  /*这个函数对剩余的帧进行解码*/  }  else{/*将自适应部分放在开始*/  /*创建用于预测的逆向量*/  for(k=0;k<diff;k++){  reverseDecresidual[K]=decresidual[(start+1)*SUBL-1-(K+STATE_SHORT_LEN)];  }  /*设置存储器*/  meml_gotten=STATE_SHORT_LEN;  for(k=0;k<meml_gotten;k++){MEM[MEML-l-k]=decresidualstart_pos+k};  memset(mem,0,(MEML-k)*sizeof(float));  /*构建解码的向量*/  iCBConstruct(reverseDecresidual,extra_cb_index,extra_gain_index,mem+MEML-stMemL,stMemL,diff,NSTAGES);  /*从逆向量中得到解码的剩余*/  for(k=0;k<diff;k++){<!-- SIPO <DP n="28"> --><dp n="d28"/>  decresidual[start_pos-l-k]=reverseDecresidual[K];  }  }  /*用于预测子帧的计数器*/  subcount=0;  /*递交子帧的预测*/  Nfor=NSUB-start-1;  if(Nfor>0){  /*设置存储器*/  memset(mem,0,(MEML-STATE_LEN)*sizeof(float));  memcpy(MEM+MEML-STATE_LEN,decresidual+(start-1)*SUBL,STATE_LEN*sizeof(float));  /*在要编码的子帧上的循环*/  for(subframe=0;subframe<Nfor;subframe++){  /*构建解码的向量*/  iCBConstruct(&amp;decresidual[(start+1+subframe)*SUBL],cb_index+subcount*NSTAGES,gain_index+subcount*NSTAGES,mem+MEML-memLf[subcount],memLf[subcount],SUBL,NSTAGES);  /*更新存储器*/  memcpy(mem,mem+SUBL,(MEML-SUBL)*sizeof(float));  memcpy(mem+MEML-SUBL,&amp;decresdiaul[(start+1+subframe)*SUBL],SLBL*sizeof(float));  subcount++;  }  }<!-- SIPO <DP n="29"> --><dp n="d29"/>  /*子帧的反向预测*/  Nback=start-1;  if(Nback>0){  /*创建逆次序向量*/  for(n=0;n<Nback;n++){  for(k=0;K<SUBL;K++){  reverseDecresidual[n*SUBL+k]=decresidual[(start-l)*SUBL-1-n*SUBL-k];  }  }  /*设置存储器*/  meml_gotten=SUBL*(NSUB+L-START);  if(meml_gotten>MEML){meml_gotten=MEML;}  for(k=0;K<meml_gotten;k++){mem[MEML-l-k]=decresidual[(start-l)*SUBL+k];}  memset(mem,0,(MEML-k)*sizeof(float));  /*在要解码的帧上的循环*/  for(subframe=0;subframe<Nback;subframe++){  /*构建解码的向量*/  iCBConstruct(&amp;reverseDecresidual[subframe*SUBL],cb_index+subcount*NSTAGES,gain_index+subcount*NSTAGES,mem+MEML-memLf[subcount],memLf[subcount],SUBL,NSTAGES);  /*更新存储器*/  memcpy(mem,mem+SUBL,(MEML-SUBL)*sizeof(float));  memcpy(mem+MEML-SUBL,&amp;reverseDecresidual[subframe*SUBL],SUBL*sizeof(float));<!-- SIPO <DP n="30"> --><dp n="d30"/>  subcount++;  }  /*从逆向量中得到解码的剩余*/  for(i=0;i<SUBL*Nback;i++)  decresidual[SUBL*Nback-i-1]=reverseDecresidual[i];  }  factor=(float)(gc_index+1)/(float)16.0;  for(i=0;i<STATE_SHORT_LEN;i++)decresidual[startpos+i]*=factor;  factor*=1.5;  if(factor<1.0){  std_decresidual=0.0;  for(i=0;i<BLOCKL;i++)std_decresidual+=decresidual[i]*decresidual[i];  std_decresidual/=BLOCKL;  std_decresidual=(float)sqrt(std_decresidual);  one_minus_factor_scaled=(float)sqrt(1-factor*factor)*std_decresidual;  gaussstart=(int)ceil(decresidual
)%(GAUSS_NOISE_L-BLOCKL);  for(i=0;i<BLOCKL;i++)decresidual[i]+=  one_minus_factor_scaled*gaussnoise[gaussstart+i];  }  }  void iLBC_decode(float*decblock,unsigned char*bytes,intbytes_are_good)  {  static float old_syntdenum[(FILTERORDER+1)*NSUB]={<!-- SIPO <DP n="31"> --><dp n="d31"/>  1,0,0,0,0,0,0,0,0,0,0,  1,0,0,0,0,0,0,0,0,0,0,  1,0,0,0,0,0,0,0,0,0,  1,0,0,0,0,0,0,0,0,0,0,  1,0,0,0,0,0,0,0,0,0,0,  1,0,0,0,0,0,0,0,0,0,0);  static int last_lag=20;  float data[BLOCKL];  float lsfunq[FILTERORDER*LPC_N];  float PLCresidual[BLOCKL],PLClpc[FILTERORDER+1];  float zeros[BLOCKL],one[FILTERORDER+1];  int k,kk,i,start,idxForMax;  int idxVec[STATE_LEN];  int dummy=0,check;  int gain_index[NASUB*NSTAGES],extra_gain_index [NSTAGES];  int cb_index[NSTAGES*NASUB],extra_cb_index[NSTAGES];  int lsf_i[LSF_NSPLIT*LPC_N];  int state_first,gc_index;  unsigned char*pbytes;  float weightnum[(FILTERORDER+1)*NSUB],weightdenum[(FILTERORDER+1)*NSUB];  int order plus one;  if(bytes_are_good){  ..从字节中提取参数  SimplelsfUNQ(lsfunq,lsf-i);  /*这个函数对LSF域中的LPC系数进行解码*/  check=LSF_check(lsfunq,FILTERORDER,LPCN);  /*这个函数检查LPC滤波器的稳定性*/  DecoderInterpolateLSF(syntdenum,lsfunq,FILTERORDER);  /*这个函数在块上内插LPC滤波器*/<!-- SIPO <DP n="32"> --><dp n="d32"/>  Decode(decresidual,start,idxForMax,idxVec,syntdenum,cb_index,gain_index,extra_cb_index,extra_gain_index,state_first,gc_index);  /*这个函数包含于上*/  /*准备plc用于未来的损失*/  doThePLC(PLCresidual,PLClpc,0,decresidual,syntdenum+(FILTERORDER+1)*(NSUB-1),NSUB,SUBL,last_lag,start);  /*这个函数处理分组损失弥补*/  memcpy(decresidual,PLCresidual,BLOCKL*sizeof(float));}else{  /*分组损失弥补*/  memset(zeros,0,BLOCKL*sizeof(float));  one
=1;  memset(one+1,0,FILTERORDER*sizeof(float));  start=0;  doThePLC(PLCresidual,PLClpc,1,zeros,one,NSUB,SUBL,last_lag,start);  memcpy(decresidual,PLCresidual,BLOCKL*sizeof(float));  order_plus_one=FILTERORDER+1;  for(i=0;i<NSUB;i++)  memcpy(syntdenum+(i*order_plus_one)+1,PLClpc+1,FILTERORDER*sizeof(float));  )  ..解码的剩余的后滤波  for(i=0;I<NSUB;i++)  syntFilter(decresidual+I*SUBL,syntdenum+i*(FILTERORDER+1),SUBL);  /*这个函数进行解码的剩余的综合滤波*/memcpy(decblock,decresidual,BLOCKL*sizeof(float));memcpy(old_syntdenum,syntdenum,NSUB*(FILTERORDER+1)*sizeof(float));}
权利要求
1.一种对被划分为连续的块的信号进行编码的方法,其中该方法包括应用于块的以下步骤
对该块的第一部分进行编码,该第一部分位于该块的两端边界之间的某处,从而获得该块的编码的起始状态;
使用基于所述编码的起始状态的预测编码方法对该块的第二部分进行编码,并朝所述两端边界之一的方向逐步地对所述第二部分进行编码;和
确定在所述起始状态和所述两端边界的另一个之间是否存在任何信号取样,如果存在,则使用基于所述编码的起始状态的预测编码方法对包括这些取样的该块的第三部分进行编码,并朝所述两端边界的另一个的方向逐步地对所述第三部分进行编码,从而所述第三部分相对于与该块关联的时间轴,与所述第二部分的编码相比是以相反方向编码的。
2.根据权利要求1所述的方法,其中对所述第三部分的编码除了基于所述编码的起始状态,还基于该块的编码的第二部分的至少一部分。
3.根据权利要求1或2所述的方法,其中所述第二部分沿着所述时间轴朝位于该块末端的所述两端边界之一的方向进行编码。
4.根据权利要求1或2所述的方法,其中所述第二部分逆着所述时间轴朝位于该块开始的所述两端边界之一的方向进行编码。
5.根据权利要求1~4的任何一个所述的方法,其中该起始状态的编码基于任何其中编码不取决于或使之不取决于该信号的任何先前的编码的块的编码方法。
6.根据权利要求1~5的任何一个所述的方法,其中所述第二和第三部分的预测编码包括从激励域到编码的信号域的综合滤波的附加步骤。
7.根据权利要求1~5的任何一个所述的方法,其中所述信号是分析滤波的数字信号的剩余信号。
8.根据权利要求7所述的方法,其中该起始状态的编码基于具有噪声整形的预测编码,使得其预测编码不取决于在相应于该块的所述第一部分的剩余信号的部分之前的剩余信号的任何编码部分。
9.根据权利要求1~8的任何一个所述的方法,其中该起始状态在编码之前进行全通滤波,以便在该起始状态的取样之中更平均地分配能量。
10.根据权利要求1~9的任何一个所述的方法,其中该方法以将应用于块的同样步骤应用于子块的方式来对由块的所述第一部分组成的子块进行编码,从而使用迭代编码。
11.根据权利要求1~10的任何一个所述的方法,包括将该块分割成一组连续的间隔,其中该块的所述第一部分的编码包括对两端边界之间的一个或更多连续的间隔进行编码,以获得所述编码的起始状态。
12.根据权利要求11所述的方法,其中所述一个或更多连续的间隔是在具有最高信号能量的那些间隔之中选择的。
13.根据权利要求1~12的任何一个所述的方法,其中第二和第三部分的编码基于以下任何编码方法线性预测编码(LPC);代码激励线性预测(CELP);具有一个或更多自适应密码本级的CELP;自激励线性预测(SELP);或多脉冲线性预测编码(MP-LPC)。
14.根据权利要求1~13的任何一个所述的方法,其中第二和第三部分的编码基于在自适应密码本的构建之前的自适应密码本存储器和目标信号的预加权。
15.根据权利要求1~14的任何一个所述的方法,其中所述信号是语音信号。
16.根据权利要求1~14的任何一个所述的方法,其中所述信号是音频信号。
17.一种用来对被划分为连续的块的信号进行预测编码的设备,其中该设备包括装置,该装置用来对每个所述块执行根据权利要求1~16的任何一个所述的方法的步骤。
18.一种计算机可读媒体,其存储了用来对被划分为连续的块的信号进行预测编码的计算机可执行组件,其中该计算机可执行组件对每个所述块执行根据权利要求1~16的任何一个所述的方法的步骤。
19.一种对编码信号进行解码的方法,其中在编码端的信号在每个块的编码之前被划分为连续的块,其中该方法包括应用于编码块的用于再生对应的解码块的以下步骤
对编码的起始状态进行解码,用来再生位于要再生的块的两端边界之间的某处的起始状态;
使用基于所述起始状态的预测解码方法,对该块的编码的第二部分进行解码,用于逐步地朝所述两端边界之一的方向再生所述第二部分;和
确定编码块是否包括编码的第三部分,如果包括,则使用基于所述起始状态的预测解码方法对该编码第三部分进行解码,用来逐步地朝所述两端边界的另一个方向再生第三部分,从而所述第三部分相对于与该块相关联的时间轴,与块的第二部分的再生相比是以相反方向再生的。
20.根据权利要求19所述的方法,其中所述第三部分的解码除了基于所述起始状态,还基于该块的解码的第二部分的至少一部分。
21.根据权利要求19或20所述的方法,其中所述第二部分沿着所述时间轴朝位于块末端的所述两端边界之一的方向进行再生。
22.根据权利要求19或20所述的方法,其中所述第二部分逆着所述时间轴朝位于块开始的所述两端边界之一的方向进行再生。
23.根据权利要求19~22的任何一个所述的方法,其中对该起始状态的解码基于任何其中再生起始状态不取决于信号的任何先前的再生部分的解码方法。
24.根据权利要求19~23的任何一个所述的方法,其中所述第二和第三部分的解码包括从激励域到解码的信号域的综合滤波的附加步骤,该第二和第三部分的综合滤波是以与该块的第二和第三部分的再生相同的顺序执行的。
25.根据权利要求19~23的任何一个所述的方法,其中所述信号是分析滤波的数字信号的剩余信号。
26.根据权利要求19~25的任何一个所述的方法,其中所述第一、第二和第三部分的解码之后是从激励域到解码的信号域的综合滤波的附加步骤,其中该块的综合滤波是以在时间上首先出现的所述两端边界之一到在时间上较晚出现的另一边界的顺序执行的。
27.根据权利要求25或26所述的方法,其中第一部分的解码基于具有噪声整形的预测编码,其解码再生起始状态不取决于在相应于所述起始状态的剩余信号的部分之前的剩余信号的任何先前的再生部分。
28.根据权利要求19~27的任何一个所述的方法,其中起始状态是在所述第一部分的所述解码之后的被全通滤波,以便进一步地集中能量。
29.根据权利要求19~28的任何一个所述的方法,其中该方法以将应用于块的同样步骤应用于子块的方式来对由所述编码的起始状态组成的子块进行解码,从而使用迭代解码。
30.根据权利要求19~29的任何一个所述的方法,其中第二和第三部分的解码基于以下任何解码方法线性预测编码(LPC);代码激励线性预测(CELP);具有一个或更多自适应密码本的CELP;自激励线性预测(SELP);或多脉冲线性预测编码(MP-LPC)。
31.根据权利要求19~30的任何一个所述的方法,其中所述信号是语音信号。
32.根据权利要求19~30的任何一个所述的方法,其中所述信号是音频信号。
33.一种用来对编码的信号进行预测解码的设备,该信号在编码端在每个块的编码之前被划分为连续的块,其中该设备包括装置,该装置用来对每个编码块执行根据权利要求19~32的任何一个所述的方法的步骤,以再生对应的解码块。
34.一种计算机可读媒体,其存储了用来对编码的信号进行预测解码的计算机可执行组件,该信号在编码端在每个块的编码之前被划分为连续的块,其中该计算机可执行组件对每个编码块执行根据权利要求19~32的任何一个所述的方法的步骤,以再生对应的解码块。
全文摘要
本发明涉及预测编码/解码操作的改善,该操作是对在分组交换网络上传输的信号执行的。该信号是以这样的方式逐块编码的即块A-B是不取决于任何先前块而预测编码的。位于该块的末端边界A和B之间某处的起始状态(715)使用任何适宜的编码方法来编码。然后围绕该起始状态的两块部分基于该起始状态、并在彼此相反的方向上进行预测编码,从而结果得到块A-B的完全编码的显示(745)。在解码端,执行对应的解码操作。
文档编号G10L19/02GK1615509SQ0282718
公开日2005年5月11日 申请日期2002年12月3日 优先权日2001年12月4日
发明者索伦·V·安德森, 罗尔·哈根, 巴斯蒂安·克莱杰恩 申请人:环球Ip音响欧洲公司, 环球Ip音响公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1