实时音频编解码之十七 Opus解码 SILK解码
Posted shichaog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实时音频编解码之十七 Opus解码 SILK解码相关的知识,希望对你有一定的参考价值。
本文谢绝任何形式转载,谢谢。
5.2 Silk解码流程
解码器线性预测层主要使用长短时预测合成滤波器对激励信号滤波实现,线性预测层内部的工作带宽为NB、MB以及WB,对于SWB以及FB的混合编码工作模式,线性预测层依然工作于WB带宽下,经过区间解码之后解码出区间编码的符号,根据这些符号解析得到SILK/CELT编码若干参数,对于语音帧,SILK编码的内容包括参数和激励,索引指是参数矢量化后码本的索引,码本的索引最终会映射为编码参数,如LTP,LSF参数等,SILK解码的流程如下,通过区间解码器解码之后获取信源编码信息,再根据解码的声道参数使用LTP和LPC滤波生成解码后的语音信号,生成的语音信号再根据设定的声道数和API Fs采样值重采样输出最终的音频信号,这一过程如图5-4所示。
图5-4 SILK解码框架
接下来的小节结合编码符号的意义和解码函数分析Opus普通帧SILK的解码过程,其函数调用关系如图5-5所示。
图5-5 Opus普通帧SILK的解码函数调用流程
5.2.1 LP层
Opus编码的最小单位是编码帧,一个编码帧的时长为10ms或20ms,一个Opus编码包可以包括多个编码帧,但是一个编码包最长含120ms的语音编码信息,Opus也可能包含Low Bit-Rate Redundancy (LBRR)帧,该帧是对先前SILK编码帧以更低比特率编码语音参数以用于抗丢包,如果编码比特流中存在LBRR,则其先于普通的SILK帧存放,逻辑上每个SILK帧由两个或四个5ms子帧组成,子帧之间的参数可以不一样,如激励的量化增益,pitch lag等。Opus编码帧内容存放的格式如表5-1所示。
符号 |
---|
Voice Activity Detection(VAD) Flag |
LBRR Flag |
Per-Frame LBRR Flag |
LBRR Frame(s) |
Regular SILK Frame(s) |
表5-1 Opus编码帧存放格式
表5-1的解析见如下代码片段注释。
//silk/dec_API.c
81 opus_int silk_Decode( // O 返回错误码
82 void* decState, // I/O 解码状态
83 silk_DecControlStruct* decControl, // I/O 控制结构
84 opus_int lostFlag, // I 0: 无丢包, 1 丢包, 2 解码 fec
85 opus_int newPacketFlag, // I 编码包第一次调用解码器标识
86 ec_dec *psRangeDec, // I/O 区间解码器数据结构
87 opus_int16 *samplesOut, // O 解码输出语音采样点向量
88 opus_int32 *nSamplesOut, // O 解码的采样点数量
89 int arch // I 运行时架构,利用CPU指令集加速
90 )
91
//TOC之后,紧接着解析VAD和LBRR
//当没有丢包,并且是解码第一个编码帧时,调用VAD和LBRR解析
174 if( lostFlag != FLAG_PACKET_LOST && channel_state[ 0 ].nFramesDecoded == 0 )
177 for( n = 0; n < decControl->nChannelsInternal; n++ )
178 for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ )
179 channel_state[ n ].VAD_flags[ i ] = ec_dec_bit_logp(psRangeDec, 1);
180
181 channel_state[ n ].LBRR_flag = ec_dec_bit_logp(psRangeDec, 1);
182
183 // 解码LBRR标志
184 for( n = 0; n < decControl->nChannelsInternal; n++ )
185 silk_memset( channel_state[ n ].LBRR_flags, 0, sizeof( channel_state[ n ].LBRR_flags ) );
186 if( channel_state[ n ].LBRR_flag )
187 if( channel_state[ n ].nFramesPerPacket == 1 )
188 channel_state[ n ].LBRR_flags[ 0 ] = 1;
189 else
190 LBRR_symbol = ec_dec_icdf( psRangeDec, silk_LBRR_flags_iCDF_ptr[ channel_state[ n ].nFramesPerPacket - 2 ], 8 ) + 1;
191 for( i = 0; i < channel_state[ n ].nFramesPerPacket; i++ )
192 channel_state[ n ].LBRR_flags[ i ] = silk_RSHIFT( LBRR_symbol, i ) & 1;
193
194
195
196
在LBRR标志被设置之后,再逐帧解析LBRR标志,这是因为一个编码包可以有多个编码帧(最长60ms),且在前帧是语音的情况下,当前编码帧才可能确实存在LBRR帧。对于10ms或者20ms帧,全局LBRR标志已经可以表达该帧LBRR标志信息,因而没有各编码帧的LBRR标志,对于40ms(两个20ms)或60ms(三个20ms),因而需要区分LBBR信息,这里使用的方法是概率密度(PDF)来表达,这一方法在后文很多地方见到,以40ms为例,由两个20ms帧组成,因而两个20ms帧共有四种LBRR组合情况,但是这四种情况出现的概率并不是一样的,因为只有语音帧才做LBRR,且全局LBRR已经指示该帧包含了LBRR帧,所以两个都未设置LBRR的情况是不存在的,因而概率是0,而两个都设置LBRR标志的概率最大为 150 / 256 ≈ 0.6 150/256≈0.6 150/256≈0.6,剩下两种情况的概率各约20%,其概率密度分布如表5-2所示,这里概率没用浮点数表示是为了节约存储空间,分母选择了256而非100之类的整数,这是因为256对于计算机而言,和其相关的一些乘法、除法运算可以通过移位方式实现,这节约了计算开销,而概率分布表可以通过从大量的数据样本中通过聚类等方式获取。
帧长 | |
---|---|
40ms | 0, 53, 53, 150/256 |
60ms | 0, 41, 20, 29, 41, 15, 28, 82/256 |
表5-2 LBRR标志概率密度分布 |
LBRR的编解码和普通的编解码流程非常相似,因而以紧接LBRR之后的普通帧分析为主,LBRR的编解码不展开分析,SILK普通帧不论VAD标志是否都会存在,这和LBRR是不一样的,SILK普通编码帧包括编码帧类型和量化类型、量化增益、短时预测滤波系数、Line Spectral Frequencies(LSFs)内插权重、LTP滤波器延迟和增益、线性同余生成器Linear Congruential Generator (LCG)初始值/种子,量化的激励信号位于这组信息之后,SILK帧编码符号的组成如表5-3所示:
符号 | 存在条件 | |
---|---|---|
Stereo Prediction Weights | 立体声且是Mid-channel帧 | |
Mid-only Flag | 立体声且是Mid-channel帧,普通SILK帧或者LBRR帧的VAD指示side channel非使能状态 | |
帧类型 | ||
子帧增益 | ||
归一化LSF阶段一索引 | ||
归一化LSF阶段二残差 | ||
归一化LSF内插权重 | 20ms帧 | |
主pitch延迟 | 语音帧 | |
子帧pitch包络 | 语音帧 | |
周期性索引 | 语音帧 | |
LTP滤波 | 语音帧 | |
LTP Scaling | ||
LCG seed | ||
Excitation Rate Level | ||
Excitation Pulse Counts | 非零脉冲计数 | |
Excitation Pulse Locations | ||
Excitation LSBs | ||
Excitation Signs | ||
表5-3 一个SILK帧的编码符号排列顺序 |
表中前两项是立体声才会有的,这是因为TOC的s字段指明了是否是立体声情况,当是非立体声时,这两个字段不会出现在编码比特流中,由于测试信号为单声道情况,且忽略它们并不影响对编解码的理解,为简单起见,不做介绍。编码比特流的解码实现于silk_decode_indices()和silk_decode_pulses()函数。
5.2.1.1 编码帧类型
编码帧类型包含了该编码帧的信号类型和量化偏移类型。如果当前编码帧的VAD标志(inactive编码帧)没有置位,则编码帧类型只有0和1两种情况,其解码使用表5-4第一行概率密度分布,如果置位了(表示有声音)则该编码帧类型的取值为2~5,帧类型的编码使用表5-4第二行的概率密度分布:
VAD 标志 | 说明 | |
---|---|---|
Inactive | 26, 230, 0, 0, 0, 0/256 | 对应于表5-5所示,只有前两项概率是非零的 |
Active | 0, 0, 24, 74, 148, 10/256 |
表5-4编码帧概率密度分布
根据如上概率密度分布表索引得到值对应的帧类型和量化偏移类型的值如下表5-5所示:
帧类型 | 信号类型 | 量化偏移类型 |
---|---|---|
0 | Inactive | Low |
1 | Inacvite | High |
2 | Unvoiced | Low |
3 | Unvoiced | High |
4 | Voiced | Low |
5 | Voiced | High |
表5-5: 编码帧类型和信号类型量化偏移对应表
//silk/decode_indices.c
35 void silk_decode_indices(
36 silk_decoder_state *psDec, // I/O State
37 ec_dec *psRangeDec, // I/O 区间解码数据结构
38 opus_int FrameIndex, // I 编码帧索引
39 opus_int decode_LBRR, // I 解码LBRR标志
40 opus_int condCoding // I 条件编码标志
41 )
42
//这段代码适用于LBRR帧和normal帧,这里或条件的意思是只要是VAD状态是被设置的帧就使用
//对于语音情况使用表5-4第二行的PDF解码
51 if( decode_LBRR || psDec->VAD_flags[ FrameIndex ] )
52 Ix = ec_dec_icdf( psRangeDec, silk_type_offset_VAD_iCDF, 8 ) + 2;
//对非语音情况使用表5-4第一行的PDF解码
53 else
54 Ix = ec_dec_icdf( psRangeDec, silk_type_offset_no_VAD_iCDF, 8 );
55
//根据解码的帧类型,按照表5-5获取信号类型和偏移类型
56 psDec->indices.signalType = (opus_int8)silk_RSHIFT( Ix, 1 );
57 psDec->indices.quantOffsetType = (opus_int8)( Ix & 1 );
153
5.2.1.2 子帧增益
SILK对每个5ms编码子帧增益进行量化编码,这些量化增益控制激励信号量化级之间的步长大小,也即控制重构语音质量。这里量化增益和语音帧的基频包络没有关系。为了节约量化比特位数,量化增益用六比特位宽的对数域值表示,其表示范围是1.94dB~88.21dB,这一范围的计算方法分别如式5-1和5-2所示,子帧增益分辨率是1.369dB。
20
log
1.25
=
1.938
式
5
−
1
20\\log1.25=1.938 式5-1
20log1.25=1.938式5−1
20
log
25728
=
88.208
式
5
−
2
20\\log25728=88.208 式5-2
20log25728=88.208式5−2
上述对数域浮点数要用32比特表示,为了节约带宽,将上述值量化到16比特,即Q16表示的值范围是81920(
2
16
∗
1.25
=
81920
2^16*1.25=81920
216∗1.25=81920)~1686110208。
子帧增益有独立编码和相对同声道前一子帧增益的编码两种情况,如下情况将采用独立编码:
-
每个SILK编码帧的第一个子帧
- 当SILK编码帧类型变化
- 前一个SILK帧未编码
独立子帧增益编码时,量化增益的高三个比特位使用表5-6所示概率密度分布解码,低三个比特使用表5-7所示的PDF解码。
信号类型 | |
---|---|
Inactive | 32,112,68,29,12,1,1,1/256 |
Unvoiced | 2,17,45,60,62,47,19,4/256 |
Voiced | 1,3,26,71,94,50,9,2/256 |
表5-6:独立子帧增益量化MSB编码PDF
32,32,32,32,32,32,32,32/256 |
表5-7:独立子帧增益量化LSB编码PDF
这6个比特组合成取值为0~63的增益索引值(gain_index),如果存在前一子帧增益,则当前编码帧增益使用下式加以限制。
log_gain = max(gain_index, previous_log_gain - 16) 式5-3
因为在前一个编码帧发生丢包的时候previous_log_gain并不存,所以式5-3的截断操作并不能通过码本方式去除,当解码器复位的时候会跳过这里的截断操。
对于非独立子帧增益量化编码,量化增益编码是相对同通道前一个编码子帧增益的编码,解码的索引值delta_gain_index的取值范围是0~40,其解码PDF是如表5-8所示。
6, 5, 11, 31, 132, 21, 8, 4, 3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1/256 |
表5-8: Delta 量化增益PDF
增益索引的解码实现代码如下:
//silk/decode_indices.c
35 void silk_decode_indices(
36 silk_decoder_state *psDec, // I/O State
37 ec_dec *psRangeDec, // I/O 区间解码数据结构
38 opus_int FrameIndex, // I 编码帧索引
39 opus_int decode_LBRR, // I 解码LBRR标志
40 opus_int condCoding // I 条件编码标志
41 )
42
60 // 解码增益
62 //有依赖编码子帧增益计算
63 if( condCoding == CODE_CONDITIONALLY )
64 //有依赖的子帧编码,使用表5-8 PDF解码
65 psDec->indices.GainsIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 );
//独立子帧编码,两个阶段,先是3个LSBs,然后是MSB位
66 else
//独立编码,根据信号类型使用表5-6的PDF解码MSB
68 psDec->indices.GainsIndices[ 0 ] = (opus_int8)silk_LSHIFT( ec_dec_icdf( psRangeDec, silk_gain_iCDF[ psDec->indices.signalType ], 8 ), 3 );
//独立编码方式,使用表5-7的PDF解码LSB
69 psDec->indices.GainsIndices[ 0 ] += (opus_int8)ec_dec_icdf( psRangeDec, silk_uniform8_iCDF, 8 );
70
71
//剩余的子帧由于前帧增益可参考,使用有依赖方式编码,PDF使用表5-8
73 for( i = 1; i < psDec->nb_subfr; i++ )
74 psDec->indices.GainsIndices[ i ] = (opus_int8)ec_dec_icdf( psRangeDec, silk_delta_gain_iCDF, 8 );
75
153
量化增益相对编码时,从前一个编码子帧计算当前编码子帧的量化增益如下:
log_gain = clamp(0, max(2*delta_gain_index - 16, previous_log_gain + delta_gain_index - 4), 63) 式 5-4
silk_gains_dequant()
函数(gain_quant.c)将第k个编码子帧的log_gain转转换到Q16的线性域的计算方法如下:
gain_Q16[k] = silk_log2lin((0x1D1C71*log_gain>>16) + 2090) 式 5-5
//silk/gain_quant.c
93 //标量增益去量化,增益在对数域上是均匀分布的
94 void silk_gains_dequant(
95 opus_int32 gain_Q16[ MAX_NB_SUBFR ], // O Q16量化的增益
96 const opus_int8 ind[ MAX_NB_SUBFR ], // I 增益索引
97 opus_int8 *prev_ind, // I/O 前一个编码帧的最后增益索引
98 const opus_int conditional, // I 如果该值等于1,表示是条件编码(差异)情况
99 const opus_int nb_subfr // I 编码子帧的数量,对应于量化子帧增益数量
100 )
101
102 opus_int k, ind_tmp, double_step_size_threshold;
104 for( k = 0; k < nb_subfr; k++ )
105 if( k == 0 && conditional == 0 )
//独立编码时,按式5-3计算增益
//为了防止音量突变,相邻两个子帧的增益差异应小于16个步长(~21.8 dB)
107 *prev_ind = silk_max_int( ind[ k ], *prev_ind - 16 );
108 else
109 // 条件编码情况,计算式5-4中的(delta_gain_index - 4)项
110 ind_tmp = ind[ k ] + MIN_DELTA_GAIN_QUANT;
111
112 // 式5-4中等号右侧max函数实现
113 double_step_size_threshold = 2 * MAX_DELTA_GAIN_QUANT - N_LEVELS_QGAIN + *prev_ind;
114 if( ind_tmp > double_step_size_threshold )
115 *prev_ind += silk_LSHIFT( ind_tmp, 1 ) - double_step_size_threshold;
116 else
117 *prev_ind += ind_tmp;
118
119
120 *prev_ind = silk_LIMIT_int( *prev_ind, 0, N_LEVELS_QGAIN - 1 );
121
122 // 式5-5,Q16缩放转换到线性域,3967 = 31 in Q7
123 gain_Q16[ k ] = silk_log2lin( silk_min_32( silk_SMULWB( INV_SCALE_Q16, *prev_ind ) + OFFSET, 3967 ) );
124
125
silk_log2lin()函数(log2lin.c)计算 2 i n l o g _ Q 7 / 128.0 2^inlog\\_Q7/128.0 2inlog_Q7/128.0的近似值。
5.2.1.3 NLSF和LPC系数
紧接编码子帧量化增益之后存放的是用于表示当前帧LPC系数的归一化LSF系数(NLSF),由1.4.4小节可知,使用LSF系数的原因是为了LPC滤波器的稳定性,跟据编码复杂度不同,LPC系数分为10阶和16阶,解码后的NLSF系数是Q15定标的0~1递增值,由于LPC是IIR滤波器系数,单位圆的边界是1,所有系数在单位圆内,故而这里称其为归一化LSF系数。为了减小码本大小使用两级矢量量化(Vector Quantization,VQ),第一章介绍了矢量量化方法,由于NB和MB使用10阶预测器,WB使用16阶预测器,因而使用不同两级码本译码,译码后LSF系数经过稳定化、帧间插值等处理之后转化为LPC系数,通过进一步处理以使LPC滤波器系数处在合适范围,以达到合成滤波稳定性的目的。
LSF第一阶段使用32个入口的码本对主要能量量化,第二阶段使用16个PDF对LSF残差信号的量化。
5.2.1.3.1 NLSF第一阶段解码
第一阶段VQ用表5-9,根据信号带宽和类型对32个入口的码本进行编码,编码的结果是针对整帧的单一索引I1,该索引是粗粒度的码本索引,用于选择第二阶段码本矢量的PDF和去除第二阶段帧间冗余的预测系数。
带宽 | 信号类型 | |
---|---|---|
NB或MB | Inactive 或 unvoiced | 44, 34, 30, 19, 21, 12, 11, 3, 3, 2, 16, 2, 2, 1, 5, 2, 1, 3, 3, 1, 1, 2, 2, 2, 3,1, 9, 9, 2, 7, 2, 1/256 |
NB 或MB | voiced | 1, 10, 1, 8, 3, 8, 8, 14, 13, 14, 1, 14, 12, 13, 11, 11, 12, 11, 10, 10, 11, 8, 9, 8, 7, 8, 1, 1, 6, 1, 6, 5/256 |
WB | Inactive 或 unvoiced | 31, 21, 3, 17, 1, 8, 17, 4, 1, 18, 16, 4, 2, 3, 1, 10, 1, 3, 16, 11, 16, 2, 2, 3, 2, 11, 1, 4, 9, 8, 7, 3/256 |
WB | Voiced | 1, 4, 16, 5, 18, 11, 5, 14, 15, 1, 3, 12, 13, 14, 15, 6, 14, 12, 2, 6, 1, 12, 12, 11, 10, 3, 10, 5, 1, 1, 1, 3/256 |
表5-9 第一阶段NLSF解码PDF
//silk/decode_indices.c
35 void silk_decode_indices(
36 silk_decoder_state *psDec, // I/O State
37 ec_dec *psRangeDec, // I/O 区间解码数据结构
38 opus_int FrameIndex, // I 编码帧索引
39 opus_int decode_LBRR, // I 解码LBRR标志
40 opus_int condCoding // I 条件编码标志
41 )
42
//阶段一解码,I1存放于psDec->indices.NLSFIndices[ 0 ]
80 psDec->indices.NLSFIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 );
//根据阶段1据解码得到的索引,解压熵编码表用到的预测权重值和索引值,
//由于预测权重对于NB/MB而言是在A和B之间选择,而WB是在C和D之间选择,
//二选一特性可以用高低比特位加以区分,其实现位于silk_NLSF_unpack函数。
81 silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] );
5.2.1.3.2 NLSF第二阶段解码
第二阶段的LSF残差信号共有16个PDF用于解码对应的系数,前八(ah)个用于NB和MB,后八(ip)个用于WB,如:
码本索引 | |
---|---|
a | 1, 1, 1, 15, 224, 11, 1, 1,1/256 |
… | |
h | 1, 1, 18, 63, 78, 58, 30, 6, 1/256 |
… | |
p | 1, 7, 21, 50, 77, 81, 17, 1, 1/256 |
表5-10 NLSF第二阶段索引解码PDF
依据复杂度的不同,LSF系数共有10个或者16个,每一个LSF系数相关的索引使用上面的ah或者ip中的一个PDF的解码,对于10个LSF系数索引的情况,其每个LSF索引使用a-h中的哪一个取决于第一阶段的索引值,比如当第一阶段的索引值等于0的时候,10个LSF系数的索引解码概率密度都使用a,PDF选择如表5-11所示,解码出来的索引值取值为[-4, 4],当索引值等于-4或者4时,使用区间解码器解码再解码一个索引值,并且将该值以相同的符号和-4或4相加,因PDF表有7个值,对应于[0,7],这样可以得到最终的第二阶段I2[k]索引值[-10,10]。
I1值 | LSF系数解码PDF |
---|---|
0 1 2 3 4 5 6 7 8 9 | |
0 | a a a a a a a a a a |
… | |
31 | e e f e f g f g f e |
表5-11 NB/MB NLSF阶段2PDF根据I1映射表
//silk/decode_indices.c
35 void silk_decode_indices(
36 silk_decoder_state *psDec, // I/O State
37 ec_dec *psRangeDec, // I/O 区间解码数据结构
38 opus_int FrameIndex, // I 编码帧索引
39 opus_int decode_LBRR, // I 解码LBRR标志
40 opus_int condCoding // I 条件编码标志
41 )
42
//NLSF系数解码,每一个NLSF系数的解码的PDF选择和阶段1的索引相关,存放在了ec_ix[ i ]变量
83 for( i = 0; i < psDec->psNLSF_CB->order; i++ )
//得到阶段2的I2索引值,位于[0,8]之间,对于最大值和最小值,则说明I2的索引值超出这一范围,需要再读入一个符号解码
//如果是0,则减运算,如果是8则加运算
84 Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
85 if( Ix == 0 )
86 Ix -= ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 );
87 else if( Ix == 2 * NLSF_QUANT_MAX_AMPLITUDE )
88 Ix += ec_dec_icdf( psRangeDec, silk_NLSF_EXT_iCDF, 8 );
89
//通过NLSF_QUANT_MAX_AMPLITUDE将I2索引值范围变为[-10,10]
90 psDec->indices.NLSFIndices[ i+1 ] = (opus_int8)( Ix - NLSF_QUANT_MAX_AMPLITUDE );
91
上述两个阶段解析出来的I2[k]通过silk_NLSF_decode() (NLSF_decode.c)映射为NLSF系数,在第一阶段的VQ以及一个后向预测步骤之后第二阶段的索引表示了量化残差,由于编码时后向预测过程从残差中减去一个预测,解码端必须实现其逆过程,表5-12给出了每个NLSF系数的预测权重,NB/MB以及WB各有两组预测权重。
系数索引 | A | B | C | D |
---|---|---|---|---|
0 | 179 | 116 | 175 | 68 |
1 | 138 | 67 | 148 | 62 |
… | … | … | … | … |
8 | 163 | 92 | 177 | 118 |
9 | 174 | 136 | ||
10 | 196 | 151 | ||
… | … | … | ||
14 | 182 | 155 |
表5-12 NLSF解码预测权重
预测逆过程实现于silk_NLSF_residual_dequant() (NLSF_decode.c)
函数,根据阶段一的索引I1选择一组预测权重,假设d_LPC是码本的阶数,如NB的阶数是10,WB的阶数是16,pred_Q8[k]是第k个LSF系数的权重,
0
≤
k
≤
d
_
L
P
C
−
1
0\\le k \\le d\\_LPC-1
0≤实时音频编解码之十二Opus编码-SILK编码-基频估计
实时音频编解码之十三 Opus编码-SILK编码-噪声整形分析