过零率是指信号沿线的符号变化率,即信号从正变为负或向后变化的速率。
过零率zn可用于:
1-区分浊音/清音
从静态背景噪声中分离出清音语音。
这是一个简单(但有效)的方法来区分
浊音区和清音区:
• Voiced region: lower zero-crossing rate
• Unvoiced region: higher zero-crossing rate
下面是我使用的代码:
public double evaluate(){
int numZC=0;
int size=signals.length;
for (int i=0; i<size-1; i++){
if((signals[i]>=0 && signals[i+1]<0) || (signals[i]<0 && signals[i+1]>=0)){
numZC++;
}
}
return numZC/lengthInSecond;
}
我的问题是:
1-我使用过零的目的是消除信号中的清音部分,,,这个代码返回过零率。那我该怎么做呢?啊!
2-我怎么知道“低”过零率是多少,“高”过零率是多少???
最佳答案
最基本的问题是,虽然你已经找到了一种方法来计算样本块的过零率,但是你不能用它来区分该块中的声音,因为它只给你一个数字来描述你的整个块。
一个可能的解决方案是把你的大区块分成小区块,然后再进行这些工作。如果你这样做,你很快就会发现,你随意制造的小积木不符合清音和浊音的整洁类别,简单地移除一个积木或将积木的音量设置为零,就会留下“断断续续”的声音,甚至是刺耳的点击声,而且不会像你喜欢的那样干净地划分词类。
这可能是一个有价值的起点,因为它更接近您现有的代码,但从长远来看,它将无法解决,除非您只是想做一些粗略的事情(在这种情况下,这可能是足够好的!)是的。
要解决这个问题,您可能需要考虑计算“瞬时过零率”1,该1更新每个样本的ZR。
你想要什么还不清楚。“消除”是什么意思?你想保持沉默还是跳过这些部分?对于静默,只需将不需要的部分替换为零。要跳过,只需删除这些样本。当然,你最终还是会点击和弹出,但我想你知道如何摆脱这一点。如果没有,也许您可以阅读linear interpolation.请记住,您几乎肯定要应用一些启发式方法,如“不要删除小于n个样本的任何部分”。My goal of using zero crossing is to eliminate the unvoiced part of the signal,,, and this code gives back the ZERO-CROSSING RATE. SO how will i do that?!
我想一个好的阈值大概在400赫兹左右,但语言不是我的专长。此外,它会因说话人的不同而有所不同,也可能因语言和其他因素而有所不同。我建议你自己做些样品看看。
这个名字有点误导人,你可以说“不存在瞬时过零率”。我来这里不是为了争论这个问题,我想用这个短语,因为它表达了我的意思,我希望你能理解它。只要说你应该尽最大努力尽可能频繁地更新ZR就够了。像这样的事情:
int lastSign = 0;
int lastCrossing = 0;
float nextZeroCrossing( float newSample ) {
int thisSign = newSample > 0 ? 1 : -1 ;
if( thisSign != lastSign ) {
lastSign = thisSign;
//zero crossing has happened. Update our estimate of Zr using lastCrossing and return that
} else {
++lastCrossing;
//zero crossing has not happened. Return existing Zr
}
}
您可能希望“平滑”nextzerocrossing()的输出,因为它往往会跳跃很多次。一个简单的指数或移动平均滤波器将工作得很好。