自适应滤波器分块分段技术详解

前言

  先说下目的:对在频域计算FIR自适应滤波器,同时避免使用长滤波器时产生的大延迟的技术进行详细的分解。即要对滤波器分块又分段的过程进行细致的分析。这里假设读者有相应的LMS自适滤波器的基础

一、滤波器分析准备

  先从时域LMS滤波器说起,设列向量

\[{\bf{x}}(n) = {\left[ {x(n),x(n - 1),...,x(n - M + 1)} \right]^T}\]
\[{\bf{w}}(n) = {\left[ {{w_0}(n),{w_1}(n),...,{w_{M - 1}}(n)} \right]^T}\]

  这里列向量长度为M。考虑通过系数为w(n)的FIR滤波器对序列x(n)滤波,用卷积运算表示为\[y(n) = \sum\limits_{i = 0}^{M - 1} {{w_i}x(n - i)} \]

  写成向量形式:

\[y(n) = {{\bf{w}}^T}(n){\bf{x}}(n)\]

  简单从公式上,初学者其实不容易理解FIR滤波器的工作过程,这里换一种表达方式:把向量和矩阵用时间序列索引与符号来表示。应该就会比较好理解一些,对于序列:7,2,-3,-6,12,8,-7,-5,4,6。通过一个长度为4的FIR滤波器,输入向量 随时间序列的迭代变化表示为

\[\begin{array}{*{20}{c}}
{n = 0} \hfill & {{\bf{x}} = {{\left[ {\begin{array}{*{20}{c}}
7 & 0 & 0 & 0 \\
\end{array}} \right]}^T}} \hfill \\
{n = 1} \hfill & {{\bf{x}} = {{\left[ {\begin{array}{*{20}{c}}
2 & 7 & 0 & 0 \\
\end{array}} \right]}^T}} \hfill \\
{n = 2} \hfill & {{\bf{x}} = {{\left[ {\begin{array}{*{20}{c}}
{ - 3} & 2 & 7 & 0 \\
\end{array}} \right]}^T}} \hfill \\
{n = 3} \hfill & {{\bf{x}} = {{\left[ {\begin{array}{*{20}{c}}
{ - 6} & { - 3} & 2 & 7 \\
\end{array}} \right]}^T}} \hfill \\
{n = 4} \hfill & {{\bf{x}} = {{\left[ {\begin{array}{*{20}{c}}
{12} & { - 6} & { - 3} & 2 \\
\end{array}} \right]}^T}} \hfill \\
\end{array}\]

二、滤波器分块处理

  下面准备写成时间序列索引的形式(向量各元素用时间序列对应的索引号代替,如:[0 -1 -2 -3]T),这样有利于在接下来的分析中看的更清楚一些,对于矩阵,也会沿用这样的方式。

  先从频域矩阵分块处理说起,分块方法是一种批处理方法,为了说的更清楚一些,这里用一个示例来说明,设滤波器长度M = 6,块长度N = 4,表示每次批处理4个单元

\[\left[ {\begin{array}{*{20}{c}}
\hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill { - 5} \\
\hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} \\
\hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} \\
\hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} \\
\end{array}} \right]\left[ {\begin{array}{*{20}{c}}
{{w_0}} \hfill \\
{{w_1}} \hfill \\
{{w_2}} \hfill \\
{{w_3}} \hfill \\
{{w_4}} \hfill \\
{{w_5}} \hfill \\
\end{array}} \right] = \left[ {\begin{array}{*{20}{c}}
{{y_0}} \hfill \\
{{y_1}} \hfill \\
{{y_2}} \hfill \\
{{y_3}} \hfill \\
\end{array}} \right]\]

  观察输入向量组成的矩阵可以发现,这是一个Toeplitz矩阵。要转到频域进行处理,一个比较可行的方式是把Toeplitz矩阵转为循环矩阵。再利用DFT把循环矩阵对角化。

  那这个循环矩阵的大小是多少比较合适呢,由卷积过程可知,卷积后输出长度为L = M + N – 1 = 9,也就是说,用M + N – 1个卷积长度完全可以表达出来,也就是说循环矩阵C的大小为LxL应该是足够的。用循环矩阵表示如下:

\[\left[ {\begin{array}{*{20}{c}}
\hfill { - 5} & \hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} \\
\hfill { - 4} & \hfill { - 5} & \hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} \\
\hfill { - 3} & \hfill { - 4} & \hfill { - 5} & \hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} \\
\hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill { - 5} & \hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} \\
\hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill { - 5} & \hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 \\
\hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill { - 5} & \hfill 3 & \hfill 2 & \hfill 1 \\
\hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill { - 5} & \hfill 3 & \hfill 2 \\
\hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill { - 5} & \hfill 3 \\
\hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill { - 5} \\
\end{array}} \right]\left[ {\begin{array}{*{20}{c}}
{{w_0}} \\
{{w_1}} \\
{{w_2}} \\
{{w_3}} \\
{{w_4}} \\
{{w_5}} \\
0 \\
0 \\
0 \\
\end{array}} \right] = \left[ {\begin{array}{*{20}{c}}
\times \\
\times \\
\times \\
\times \\
\times \\
{{y_0}} \\
{{y_1}} \\
{{y_2}} \\
{{y_3}} \\
\end{array}} \right]\]

  这里输出向量中的X部分是循环卷积的结果,是要舍弃的部分。重写以上过程

\[{\bf{y}}(n) = P_{L \times L}^{01}C{\bf{\hat w}}(n) = P_{L \times L}^{01}{F^{ - 1}}FC{F^{ - 1}}F{\bf{\hat w}}(n)\]

  分解为4步:

  1. 是一个对角矩阵,在编程实现中,可以取循环矩阵C的第一列变换到频域来代替
  2. 是把后面补0后的滤波器系数变换到频域
  3. 是一个逆FFT变换
  4. 是为了只选取最后N个做为滤波器的输出结果,编程中做到这点很方便

  再看滤波器的更新过程,这里把步长参数省去

\[w(n + 1) = w(n) + \left[ {\begin{array}{*{20}{c}}
\hfill 0 & \hfill 1 & \hfill 2 & \hfill 3 \\
\hfill { - 1} & \hfill 0 & \hfill 1 & \hfill 2 \\
\hfill { - 2} & \hfill { - 1} & \hfill 0 & \hfill 1 \\
\hfill { - 3} & \hfill { - 2} & \hfill { - 1} & \hfill 0 \\
\hfill { - 4} & \hfill { - 3} & \hfill { - 2} & \hfill { - 1} \\
\hfill { - 5} & \hfill { - 4} & \hfill { - 3} & \hfill { - 2} \\
\end{array}} \right]\left[ {\begin{array}{*{20}{c}}
{{e_0}} \\
{{e_1}} \\
{{e_2}} \\
{{e_3}} \\
\end{array}} \right]\]

  用循环矩阵表示梯度向量的计算过程

\[\left[ {\begin{array}{*{20}{c}}
1 & 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 & 1 & 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 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\
\end{array}} \right]\left[ {\begin{array}{*{20}{c}}
\hfill { - 5} & \hfill { - 4} & \hfill { - 3} & \hfill { - 2} & \hfill { - 1} & \hfill 0 & \hfill 1 & \hfill 2 & \hfill 3 \\
\hfill 3 & \hfill { - 5} & \hfill { - 4} & \hfill { - 3} & \hfill { - 2} & \hfill { - 1} & \hfill 0 & \hfill 1 & \hfill 2 \\
\hfill 2 & \hfill 3 & \hfill { - 5} & \hfill { - 4} & \hfill { - 3} & \hfill { - 2} & \hfill { - 1} & \hfill 0 & \hfill 1 \\
\hfill 1 & \hfill 2 & \hfill 3 & \hfill { - 5} & \hfill { - 4} & \hfill { - 3} & \hfill { - 2} & \hfill { - 1} & \hfill 0 \\
\hfill 0 & \hfill 1 & \hfill 2 & \hfill 3 & \hfill { - 5} & \hfill { - 4} & \hfill { - 3} & \hfill { - 2} & \hfill { - 1} \\
\hfill { - 1} & \hfill 0 & \hfill 1 & \hfill 2 & \hfill 3 & \hfill { - 5} & \hfill { - 4} & \hfill { - 3} & \hfill { - 2} \\
\hfill { - 2} & \hfill { - 1} & \hfill 0 & \hfill 1 & \hfill 2 & \hfill 3 & \hfill { - 5} & \hfill { - 4} & \hfill { - 3} \\
\hfill { - 3} & \hfill { - 2} & \hfill { - 1} & \hfill 0 & \hfill 1 & \hfill 2 & \hfill 3 & \hfill { - 5} & \hfill { - 4} \\
\hfill { - 4} & \hfill { - 3} & \hfill { - 2} & \hfill { - 1} & \hfill 0 & \hfill 1 & \hfill 2 & \hfill 3 & \hfill { - 5} \\
\end{array}} \right]\left[ {\begin{array}{*{20}{c}}
0 \\
0 \\
0 \\
0 \\
0 \\
{{e_0}} \\
{{e_1}} \\
{{e_2}} \\
{{e_3}} \\
\end{array}} \right]\]

  重写滤波器系数更新公式如下:

\[\begin{array}{l}
w(n + 1) = w(n) + P_{L \times L}^{10}{C^T}{{\bf{e}}_L} = w(n) + P_{L \times L}^{10}{F^{ - 1}}F{C^T}{F^{ - 1}}F{{\bf{e}}_L} \\
W(n + 1) = W(n) + FP_{L \times L}^{10}{F^{ - 1}}F{C^T}{F^{ - 1}}E \\
\end{array}\]

这里W向量是滤波器系数的频域表示。同样做4步分解:

  1. 仍然是一个对解矩阵,可取循环矩阵C的第一列变换到频域后再取共轭来实现
  2. E是把前面补0后的误差信号变换到频域
  3. 这步是比较麻烦的地方。如果为了计算量忽略这一步(webrtc的做法),就是不对梯度做约束,而speex是通过变换到时域再置后面部分为0来避免直接矩阵运算的,个人比较喜欢speex的实现方式。当然,由于这是一个定值,不考虑计算量的话,也可以直接在频域进行矩阵的乘法
  4. 与W(n)在频域相加

  至此,已经完成了滤波器分块的频域处理分析,但要注意的是,这里滤波器的长度是L = M + N – 1,分块处理转到频域虽然计算上方便了,但随着时域滤波器系数长度M和分块长度N越来越大,延时也会随之线性增大,接下来,就着手解决这个问题。

三、对滤波器进行分割(分段)

  当滤波器长度M很大,且使用一个比M小很多的块长度时,可以把卷积和的运算过程分割为多个块的和,用多个分块滤波器的和来合成最终的结果,这样处理就可以使滤波器的延时大幅度的缩短。以M = 8,P = 2,N = 4为例进行说明这个分割过程。也就是说,如果对一个长度M = 8的滤波器,把滤波器分成2个块,每块4个数据,可以把卷积过程写为

\[\begin{array}{l}
y(n) = \sum\limits_{l = 0}^{P - 1} {{y_l}(n)} \\
{y_l}(n) = \sum\limits_{i = 0}^{N - 1} {{w_{i + lN}}x(n - lN - i)} \\
\end{array}\]

  用矩阵的方式表示出来:

\[\left[ {\begin{array}{*{20}{c}}
\hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill | & \hfill { - 4} & \hfill { - 5} & \hfill { - 6} & \hfill { - 7} \\
\hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill | & \hfill { - 3} & \hfill { - 4} & \hfill { - 5} & \hfill { - 6} \\
\hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill | & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill { - 5} \\
\hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill | & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} \\
\end{array}} \right]\left[ {\frac{{\begin{array}{*{20}{c}}
{{w_0}} \\
{{w_1}} \\
{{w_2}} \\
{{w_3}} \\
\end{array}}}{{\begin{array}{*{20}{c}}
{{w_4}} \\
{{w_5}} \\
{{w_6}} \\
{{w_7}} \\
\end{array}}}} \right] \Rightarrow \begin{array}{*{20}{c}}
{\left[ {\begin{array}{*{20}{c}}
\hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} \\
\hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} \\
\hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} \\
\hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 \\
\end{array}} \right]\left[ {\begin{array}{*{20}{c}}
{{w_0}} \\
{{w_1}} \\
{{w_2}} \\
{{w_3}} \\
\end{array}} \right] = \left[ {\begin{array}{*{20}{c}}
{{y_{\begin{array}{*{20}{c}}
0 & 0 \\
\end{array}}}} \\
{{y_{\begin{array}{*{20}{c}}
0 & 1 \\
\end{array}}}} \\
{{y_{\begin{array}{*{20}{c}}
0 & 2 \\
\end{array}}}} \\
{{y_{\begin{array}{*{20}{c}}
0 & 3 \\
\end{array}}}} \\
\end{array}} \right]} \\
{\left[ {\begin{array}{*{20}{c}}
\hfill { - 4} & \hfill { - 5} & \hfill { - 6} & \hfill { - 7} \\
\hfill { - 3} & \hfill { - 4} & \hfill { - 5} & \hfill { - 6} \\
\hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill { - 5} \\
\hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} \\
\end{array}} \right]\left[ {\begin{array}{*{20}{c}}
{{w_4}} \\
{{w_5}} \\
{{w_6}} \\
{{w_7}} \\
\end{array}} \right] = \left[ {\begin{array}{*{20}{c}}
{{y_{\begin{array}{*{20}{c}}
1 & 0 \\
\end{array}}}} \\
{{y_{\begin{array}{*{20}{c}}
1 & 1 \\
\end{array}}}} \\
{{y_{\begin{array}{*{20}{c}}
1 & 2 \\
\end{array}}}} \\
{{y_{\begin{array}{*{20}{c}}
1 & 3 \\
\end{array}}}} \\
\end{array}} \right]} \\
\end{array}\]

\[\begin{array}{*{20}{c}}
{{y_0} = {y_{\begin{array}{*{20}{c}}
0 & 0 \\
\end{array}}} + {y_{\begin{array}{*{20}{c}}
1 & 0 \\
\end{array}}}} \\
{{y_1} = {y_{\begin{array}{*{20}{c}}
0 & 1 \\
\end{array}}} + {y_{\begin{array}{*{20}{c}}
1 & 1 \\
\end{array}}}} \\
{{y_2} = {y_{\begin{array}{*{20}{c}}
0 & 2 \\
\end{array}}} + {y_{\begin{array}{*{20}{c}}
1 & 2 \\
\end{array}}}} \\
{{y_3} = {y_{\begin{array}{*{20}{c}}
0 & 3 \\
\end{array}}} + {y_{\begin{array}{*{20}{c}}
1 & 3 \\
\end{array}}}} \\
\end{array}\]

  接下来再分别把这两个分割出来的NxN矩阵块分别转换为循环矩阵的形式。(这里只写出第一个,第二个块有兴趣的朋友自己推吧)

\[\left[ {\begin{array}{*{20}{c}}
\hfill { - 3} & \hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} \\
\hfill { - 2} & \hfill { - 3} & \hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} \\
\hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 \\
\hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill 3 & \hfill 2 & \hfill 1 \\
\hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill 3 & \hfill 2 \\
\hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill 3 \\
\hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} \\
\end{array}} \right]\left[ {\begin{array}{*{20}{c}}
{{w_0}} \\
{{w_1}} \\
{{w_2}} \\
{{w_3}} \\
0 \\
0 \\
0 \\
\end{array}} \right] = \left[ {\begin{array}{*{20}{c}}
\times \\
\times \\
\times \\
{{y_{\begin{array}{*{20}{c}}
0 & 0 \\
\end{array}}}} \\
{{y_{\begin{array}{*{20}{c}}
0 & 1 \\
\end{array}}}} \\
{{y_{\begin{array}{*{20}{c}}
0 & 2 \\
\end{array}}}} \\
{{y_{\begin{array}{*{20}{c}}
0 & 3 \\
\end{array}}}} \\
\end{array}} \right]\]

  这样就可以方便的转到频域进行处理,再把每块的处理结果相加,就完成了分段分块的频域卷积运算。滤波器的系数更新也是同理

  另外,虽然2N-1个长度的频域复向量足以完成必要的卷积过程,实际算法中FFT长度通常取2N,这样计算更方便,这时分割后的第一个块的循环矩阵如下所示:

\[\left[ {\begin{array}{*{20}{c}}
\hfill { - 4} & \hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} \\
\hfill { - 3} & \hfill { - 4} & \hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} \\
\hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} \\
\hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 \\
\hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill 3 & \hfill 2 & \hfill 1 \\
\hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill 3 & \hfill 2 \\
\hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} & \hfill 3 \\
\hfill 3 & \hfill 2 & \hfill 1 & \hfill 0 & \hfill { - 1} & \hfill { - 2} & \hfill { - 3} & \hfill { - 4} \\
\end{array}} \right]\left[ {\begin{array}{*{20}{c}}
{{w_0}} \\
{{w_1}} \\
{{w_2}} \\
{{w_3}} \\
0 \\
0 \\
0 \\
0 \\
\end{array}} \right] = \left[ {\begin{array}{*{20}{c}}
\times \\
\times \\
\times \\
\times \\
{{y_{\begin{array}{*{20}{c}}
0 & 0 \\
\end{array}}}} \\
{{y_{\begin{array}{*{20}{c}}
0 & 1 \\
\end{array}}}} \\
{{y_{\begin{array}{*{20}{c}}
0 & 2 \\
\end{array}}}} \\
{{y_{\begin{array}{*{20}{c}}
0 & 3 \\
\end{array}}}} \\
\end{array}} \right]\]

  另一个分割块也是同理,这里不再详细列出来,有兴趣的朋友可以自己手画一遍玩玩,上图有一个小细节的哦,循环矩阵的对角元素可以是任意的,不影响最终效果,但通常大家都取前一个块的第一个元素。

  剩下的活,就是前面转到频域的处理过程了,不再详述。

  最后还有一个问题,是不是分割(段)越多越好,也不再详细分析了,直接给出结果:不是分割数P越大越好。由于分割过程改变了输入向量,也就改变了输入向量相关矩阵特征值的扩散度(条件数)。当P越大时,特征值的扩散度就越大,算法收敛就越慢,也更容易出现发散的可能。

参考文献:

  1. Advances in Network and Acoustic Echo Cancellation
  2. Adaptive Filters Theory and Applications Second Edition
  3. Adaptive Signal Processing Applications to Real-World Problems

原文地址:https://www.cnblogs.com/icoolmedia/p/mdf_detailed.html

时间: 2024-10-14 17:20:24

自适应滤波器分块分段技术详解的相关文章

CDN技术详解及实现原理

CDN技术详解 一本好的入门书是带你进入陌生领域的明灯,<CDN技术详解>绝对是带你进入CDN行业的那盏最亮的明灯.因此,虽然只是纯粹的重点抄录,我也要把<CDN技术详解>的精华放上网.公诸同好. 第一章    引言    “第一公里”是指万维网流量向用户传送的第一个出口,是网站服务器接入互联网的链路所能提供的带宽.这个带宽决定了一个 网站能为用户提供的访问速度和并发访问量.如果业务繁忙,用户的访问数越多,拥塞越严重,网站会在最需要向用户提供服务时失去用户.(还有“中间一公里” 和

实现高性能纠删码引擎 | 纠删码技术详解(下)

作者介绍: 徐祥曦,七牛云工程师,独立开发了多套高性能纠删码/再生码编码引擎.柳青,华中科技大学博士,研究方向为基于纠删码的分布式存储系统. 前言: 在上篇<如何选择纠删码编码引擎>中,我们简单了解了 Reed-Solomon Codes(RS 码)的编/解码过程,以及编码引擎的评判标准.但并没有就具体实现进行展开,本篇作为<纠删码技术详解>的下篇,我们将主要探讨工程实现的问题. 这里先简单提炼一下实现高性能纠删码引擎的要点:首先,根据编码理论将矩阵以及有限域的运算工程化,接下来主

Protocol Buffer技术详解(Java实例)

Protocol Buffer技术详解(Java实例) 该篇Blog和上一篇(C++实例)基本相同,只是面向于我们团队中的Java工程师,毕竟我们项目的前端部分是基于Android开发的,而且我们研发团队中目前主要使用的开发语言就是C++.Java和Python,其中Python主要用于编写各种工具程序.然而为了保证该篇Blog的完整性和独立性,我仍然会将上一篇Blog中已经出现的内容再一次赘述,同时对于Java中特有的部分也会着重介绍.          一.生成目标语言代码.      下面

CSS3中的弹性流体盒模型技术详解(一)

从这篇文章开始,会利用几个篇幅,我将跟大家分享 从CSS1到CSS3都是如何实现页面布局的(当然,所指的范畴是利用CSS技术). 由于盒子模型技术内容比较多,这篇文章我将着重讲解知识点. 下一篇文章,我会带领大家开发一个兼容 pc端浏览器和 移动端浏览器的弹性布局web界面的实例.希望大家能从中领受到CSS3在布局方面的强大功能. 好了,长话短说,现在开始我们的<CSS3中的弹性流体盒模型技术详解>之旅吧! 在讲解CSS3中新增的弹性布局属性之前,我们先回顾一下CSS1 和 CSS2中都已经定

【H.264/AVC视频编解码技术详解】十三、熵编码算法(4):H.264使用CAVLC解析宏块的残差数据

<H.264/AVC视频编解码技术详解>视频教程已经在"CSDN学院"上线,视频中详述了H.264的背景.标准协议和实现,并通过一个实战工程的形式对H.264的标准进行解析和实现,欢迎观看! "纸上得来终觉浅,绝知此事要躬行",只有自己按照标准文档以代码的形式操作一遍,才能对视频压缩编码标准的思想和方法有足够深刻的理解和体会! 链接地址:H.264/AVC视频编解码技术详解 GitHub代码地址:点击这里 1. H.264的CAVLC解析宏块残差数据的流

杀毒与免杀技术详解之三:特征码免杀实战

1.前言 在前篇<杀毒与免杀技术详解之二:特征码定位-工具及原理 >中,笔者主要介绍了MyCCL这个特征码定位工具的使用方式,并对它的原理进行了一步步的分析解释,最后讲了学习这一工具的意义和作用.今天,在这实战篇中,我们将应用前面学到的知识,以几个市面上的特征码杀毒引擎为例,进行实战的免杀.同时也非常欢迎诸位朋友指点,互相学习.进步! 2.实战环境 实验主机: Vmware 11虚拟机 操作系统: XP sp3 实验用具: MyCCL 2.1.C32Asm.一份病毒样本(encode.exe)

【H.264/AVC视频编解码技术详解】十三、熵编码算法(3):CAVLC原理

<H.264/AVC视频编解码技术详解>视频教程已经在"CSDN学院"上线,视频中详述了H.264的背景.标准协议和实现,并通过一个实战工程的形式对H.264的标准进行解析和实现,欢迎观看! "纸上得来终觉浅,绝知此事要躬行",只有自己按照标准文档以代码的形式操作一遍,才能对视频压缩编码标准的思想和方法有足够深刻的理解和体会! 链接地址:H.264/AVC视频编解码技术详解 GitHub代码地址:点击这里 上下文自适应的变长编码(Context-base

CSS3中的弹性流体盒模型技术详解

先回顾一下CSS1 和 CSS2中都已经定义了哪些布局方面的属性,这样也会增加我们理解弹性布局. 其实我们现在有很多一部分人,你们刚刚接触CSS层叠样式表,或者接触有一段时间了,但是却没有很好的去消化与理解.可能平时你们还一直在使用table,然后通过不断了合并单元格来实现网页布局.希望我今天的这篇文章能彻底改变大家的观念. Q:如何理解盒子模型? A:大家可以想一想,在现实生活中,如果我们拿一个盒子来装东西,那么盒子里面的东西是不是跟这个盒子之间会有空隙呢?站在里面物品的角度,则它们之间的间隙

Linux磁盘阵列技术详解(二)--raid 1创建

我在Linux磁盘阵列技术详解(一)里已经详细介绍了几种RAID磁盘阵列方式,原理以及创建raid 0 的详细步骤.那么这篇文档就着重讲解如何创建raid 1的技术: 步骤如下: ① 分区 同样我们还是以一块硬盘的不同分区为例,实际工作中应该是不同的硬盘才对. 具体分区步骤不再赘述! 分区后结果如下图所示: ② 创建raid 1 mdadm -C -v /dev/md1 -l 1 -n 2 -x 1 /dev/sdc1 /dev/sdc2 /dev/sdc3 或者 mdadm -C -v /de