5 感知加权与基音周期
Mem_Shift
这个函数的作用是
把先前保存的120个输入信号,与当前的240信号值,整成一个360的缓冲区buf,
并把当前的最后120个输入信号存入PrevData,
取buf的第60至299样值块(也就是一帧240)来做分析.
Wght_Lpc
构造感知加权滤波器
用lpc系数来构造形式如下
10 10
(1 - Σa(i) * 0.9^i * z^-1) / (1 - 1 - Σa(i) * 0.5^i * z^-1)
i=1 i=1
Error_Wght
构240个样值送入感知加权滤波器,得到感知加权后的语音信号
其计算过程不详述了,分为iir 和 fir两部分来运算,
代码完全根据加权滤波器的公式,照本宣科
然后做一些缓冲区拼接,将先前142个历史值,与当前的240个样值,拼起来(142跟基音周期有关,见下文)
/* Construct the buffer */
for ( i = 0 ; i < PitchMax ; i ++ )
Dpnt[i] = CodStat.PrevWgt[i] ;
for ( i = 0 ; i < Frame ; i ++ )
Dpnt[PitchMax+i] = DataBuff[i] ;
Vec_Norm
把信号归一化
Estim_Pitch
接下来就是基音周期搜索了.
采用的是自相关法来搜索基音周期的.
根据柯西定量 a^2+b^2 > 2ab 这样.
我们可以知道,一个语音信号的自相关值,一定会在它的基音周期处,达到最大值
(还有一种基音周期的估算法,叫做短时平均幅度差法,与自相关法不同的是,它在基音周期处,是谷值)
妇女150-300赫兹,儿童200-300赫兹);成年男子的声带长而厚,所以说话声音就低一些(60-200赫兹) 对应为采样率为
8000时 基音周期分别为26-133 (8000/60=133 8000/300=26),
itu对基音周期的搜索为 18-142
即PitchMin PitchMax的值
以下为一些声音频率的参考资料:
人说话时基频范围大约为100Hz~300Hz
深沉的男低音发出的最低音的频率可达65.4Hz。
花腔女高音发出的最高音的频率可达1177.2Hz。
人和一些动物的发声频率范围和听觉频率范围
名称 发声频率范围Δf/Hz 听觉频率范围Δf/Hz
人 65~1 100 20~20 000
狗 450~1 800 15~50 000
猫 760~1 500 60~6 500
蝙蝠 10 000~150 000 1 000~200 000
海豚 7 000~120 000 150~150 000
知更鸟 2 000~13 000 250~20 000
鱼 40~2 000 --- 鱼能发声吗?从没听过,呵呵
回到代码中来,723将语音帧分成两截分别求基音周期,每截为120样值点
j = PitchMax ;
for ( i = 0 ; i < SubFrames/2 ; i ++ ) {
Line.Olp[i] = Estim_Pitch( Dpnt, (Word16) j ) ;
VadStat.Polp[i+2] = Line.Olp[i] ;
j += 2*SubFrLen ;
}
Estim_Pitch采用的是自相关算法,即第一个峰值点的索引,就是基音周期了
即计算
n=119 n=119
( (Σ s[n] * s[n - j])^2 ) / (Σ s[n - j] * s[n - j]) 18<=j<=142
n=0 n=0
可以看出分母即能量 分子就是自相关函数
这里为了避开昂贵的除法运算,实际代码在比较是做了变形,
我们假设搜索目标值 分子为Da, 分母为Db, 当前搜索到的最大值分子为Ma, 分母为Mb
代码要做比较时,实际是这样的 Da*Mb - Db*Ma 结果大于零,来判断相应的值大小,推导很简单
根据不等式的性质直接推出
下面来看Estim_Pitch函数的实现过程
首先就是计算能量初始值,不用每次都将分母计算一遍,只需要在循环中更新能量即可(即添头,去尾)
/* Init the energy estimate */
Pr = Start - (Word16)PitchMin + (Word16)1 ;
Acc1 = (Word32) 0 ;
for ( j = 0 ; j < 2*SubFrLen ; j ++ )
Acc1 = L_mac( Acc1, Dpnt[Pr+j], Dpnt[Pr+j] ) ;
添头,去尾,达到更新能量的目的,也就是分母
/* Energy update */
Acc1 = L_msu( Acc1, Dpnt[Pr+2*SubFrLen], Dpnt[Pr+2*SubFrLen] ) ;
Acc1 = L_mac( Acc1, Dpnt[Pr], Dpnt[Pr] ) ;
计算自相关,这个也就是分子组成部分
/* Compute the cross */
Acc0 = (Word32) 0 ;
for ( j = 0 ; j < 2*SubFrLen ; j ++ )
Acc0 = L_mac( Acc0, Dpnt[Start+j], Dpnt[Pr+j] ) ;
接下来的代码比较绕,但是还是很容易理解的,
计算自相关的平方,得到了分子,并将其归一化
/* Compute Exp and mant of the cross */
Exp = norm_l( Acc0 ) ; //lsc 计算归一化分子所需要的左移位数
Acc0 = L_shl( Acc0, Exp ) ; //lsc 归一化分子
Exp = shl( Exp, (Word16) 1 ) ; //lsc 因为平方,所以指数在扩大两倍..
Ccr = round( Acc0 ) ;
Acc0 = L_mult( Ccr, Ccr ) ; //lsc 这里计算平方
Ccr = norm_l( Acc0 ) ; //lsc 再次归一化得到的结果
Acc0 = L_shl( Acc0, Ccr ) ;
Exp = add( Exp, Ccr ) ;
Ccr = extract_h( Acc0 ) ;
分母,即能量归一化
/* Do the same with energy */ //注意归一化后得到的指数的符号与原值是相反的,所以最大,相应为最小
Acc0 = Acc1 ;
Enr = norm_l( Acc0 ) ;
Acc0 = L_shl( Acc0, Enr ) ;
除法,对应分子分母的指数相减
Exp = sub( Exp, Enr ) ;
Enr = round( Acc0 ) ;
真值大于"1"的情况,所以右移一位后,又是归一化了,指数相应减少(因为是左移,这点要记住,否则你会认为指数应该加1)
if ( Ccr >= Enr ) {
Exp = sub( Exp, (Word16) 1 ) ;
Ccr = shr( Ccr, (Word16) 1 ) ;
}
接下来就是一段繁琐的比较代码,笔者分析了如下.大意就是比较大小
//lsc 指数小,说明值大,因为左移的
if ( Exp <= Mxp ) {
//lsc 绝对小,保存最大的自相关值以及相应的索引 大于1.25db的情况 即应该比最大值大1.33倍
if ( (Exp+1) < Mxp ) {//lsc 这是大4倍的情况,直接保留索引
Indx = (Word16) i ;
Mxp = Exp ;
Mcr = Ccr ;
Mnr = Enr ;
continue ;
}
if ( (Exp+1) == Mxp )//lsc 这是大两倍,需要整到同一个数量级,所在右移
Tmp = shr( Mcr, (Word16) 1 ) ;
else
Tmp = Mcr ;//lsc 指数一样,这就不用移了,可以直接相乘再相减判断大小
/* Compare with equal exponents */
Acc0 = L_mult( Ccr, Mnr ) ;
Acc0 = L_msu( Acc0, Enr, Tmp ) ;
if ( Acc0 > (Word32) 0 ) {
if ( ((Word16)i - Indx) < (Word16) PitchMin ) {//lsc 位置差别小于18,只要大,就选成
Indx = (Word16) i ;
Mxp = Exp ;
Mcr = Ccr ;
Mnr = Enr ;
}
else {//lsc 位置差别大于18,则还要考虑是否大了1.33倍,但这里似乎成了1.5倍...笔者怎么算都不符
Acc0 = L_mult( Ccr, Mnr ) ;
Acc0 = L_negate(L_shr( Acc0, (Word16) 2 ) ) ;
Acc0 = L_mac( Acc0, Ccr, Mnr ) ;
Acc0 = L_msu( Acc0, Enr, Tmp ) ;
if ( Acc0 > (Word32) 0 ) {
Indx = (Word16) i ;
Mxp = Exp ;
Mcr = Ccr ;
Mnr = Enr ;
}
}
}
}
最后返回得到的索引值 Indx 它就是基音周
为何要做这些?基音周期体现了语音数据的相关性,实际上后继的自适应码本,就是在基音周期的基础上进行搜索的,
通过对基音周期周围的历史5个激励源进行加成,得到自适应激励,笔者将在下一章分析这些,待续
林绍川
2011.05.16 于杭州
分享到:
相关推荐
自相关算法是一种在信号处理和音频分析中广泛使用的基音检测方法。基音,也称为基本频率,是声音信号中最深层次的振动频率,通常对应于声乐或乐器音调的最低频率。在MATLAB中实现自相关算法可以高效地检测到这个关键...
本文将深入探讨基音周期估计的概念、原理及其在LPC分析与合成中的应用,并重点介绍两种常见的基音周期估计方法:简单逆向滤波器轨迹(Simple Inverse Filtering Technique, SIFT)以及均值差分函数(Average ...
语音信号处理学习者使用,可以获取语音信号地基音周期。于MATLAB 语音信号处理实验
在语音处理领域,基音(Pitch)是衡量语音信号中元音部分重复频率的一个关键参数,它直接影响到语音的音高感知。自相关法是一种常用的技术,用于估计语音信号的基音周期。在这个项目中,我们将深入探讨如何利用...
1. **paper.doc**:可能是一篇关于AMDF方法的学术论文,详细阐述了AMDF的理论基础、计算过程以及实验结果,可能包括与其他基音检测方法的比较和性能评估。 2. **Test_Sentence.m**:这是一个MATLAB脚本,用于测试...
基音周期估计的各种方法,matlab代码。
在语音信号中,基音就是声音的基本周期,与人的声带振动频率有关,而倒谱法能够有效揭示这种周期性,帮助我们准确地定位基音周期。 在MATLAB中,执行倒谱分析通常涉及以下步骤: 1. **预处理**:对原始语音信号...
基音周期的matlab程序 内容: 1、增加语音帧的长度 L>2M(基音帧); 2、利用必要的前处理技术:前置滤波器或削波处理;
下面将详细介绍ACF基音检测以及基音周期检测的相关知识。 自相关函数(Autocorrelation Function,ACF)是统计学中的一个概念,它用于衡量一个信号与自身不同时间延迟版本之间的相似度。在音频分析中,ACF可以揭示...
自相关函数可以帮助确定信号的周期性,通过分析语音信号与自身在不同时间延迟下的相似度来估计基音周期。具体来说,通过求解语音信号在不同时间延迟下的相关性,当延迟等于基音周期时,自相关函数会出现一个峰值。...
基音周期估计是语音信号处理中的一个重要概念,主要用于识别和分析语音中的基本频率,即一个声音周期的持续时间。在中文语音中,基音周期通常对应于声母和韵母之间的停顿,对于理解语音的语义至关重要。本资源包含的...
### 基于小波变换的语音信号基音周期估计 #### 概述 基音周期作为语音信号处理中的一个重要参数,在语音信号的数字处理中扮演着至关重要的角色。无论是语音编码、识别还是合成,准确地估计出语音信号的基音周期都是...
在语音信号中,倒谱图能够清晰地显示出基音周期的峰,这些峰与语音的元音部分相对应,因为元音的基音周期变化较为明显。 接下来,MATLAB作为一种强大的数值计算和可视化环境,是进行语音信号处理的理想工具。在...
本文详细介绍了如何使用MATLAB实现语音信号的基音周期检测,并通过中心削波和三电平削波技术提高了检测的准确性。这些技术在语音信号处理领域有着广泛的应用前景,尤其是在自动语音识别和语音合成等方面。 通过上述...
此程序为matlab环境下的基音周期提取算法,通过该算法能够区分清音和浊音
【语音分析】短时自相关基音周期检测与LPC预测增益计算是信号处理领域中的重要技术,常用于语音识别、语音合成以及语音质量评估等应用。在本资料中,我们将深入探讨这两个核心概念,并结合提供的Matlab源码进行详细...
通过限制语音子帧基音周期值的搜索集合,实现了第一层隐写;利用搜索集合内基音周期取值的任意性,实现了第二层隐写。双层嵌入过程中,以最小化修改幅度为原则决定基音周期的取值,降低了隐写失真。实验结果表明,...