过零率是信号沿符号变化的速率,即信号从正变为负或反向变化的速率。
过零率 Zn 可用于:
1-区分浊音/清音 2-将清音语音与静态背景噪音分开。
这是一种简单(但有效)的方法来区分 浊音和清音语音区域:
• 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-我如何知道“低”过零率是多少以及“高”过零率是多少???
最佳答案
根本问题是,虽然您找到了一种计算样本 block 过零率的方法,但您无法使用它来区分该 block 内的声音,因为它只为您提供一个描述整个样本的数字。 block 。
一个可能的解决方案是将大块分成小块,然后对这些 block 进行处理。如果你这样做,你很快就会发现你随意制作的小块不符合浊音和清音的整齐类别,并且简单地删除一个 block 或将一个 block 的音量设置为零会让你感到“不连贯”声音甚至刺耳的咔嗒声,并且不会像您希望的那样清晰地划分词性。
这可能是一个值得一开始的观点,因为它更接近您现有的代码,但从长远来看它不会起作用,除非您只是想做一些粗略的事情(在这种情况下,这可能是足够好!)。
要解决此问题,您可能需要考虑计算“瞬时过零率”1,以更新每个样本的 Zr。
我使用过零的目标是消除信号的清音部分,并且此代码返回过零率。那么我该怎么做?!
目前尚不清楚你想要什么。你所说的“消除”是什么意思?您想要安静还是想跳过这些部分?要保持静音,只需将不需要的部分替换为零即可。要跳过,只需删除这些样本即可。当然,您最终仍然会听到咔哒声和弹出声,但我假设您知道如何消除这种情况。如果没有,也许你可以阅读 linear interpolation.请记住,您几乎肯定必须应用一些启发式方法,例如“不要删除小于 n 个样本的任何部分”。我如何知道“低”过零率是多少,“高”过零率是多少???
我猜一个好的阈值会大约在 400Hz 左右,但语音不是我的专长。此外,它会因说话者的不同而略有不同,也可能因语言和其他因素而有所不同。我建议您制作一些 sample 并亲自看看。
1 这个名称有点误导,你可以说“不存在瞬时过零率”。我不是来争论这一点的;相反,我想使用这个短语,因为它表达了我的意思,我希望你能理解它。我只想说,您应该尽最大努力尽可能多地更新 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() 的输出,因为它往往会跳跃很多。简单的指数或移动平均滤波器效果很好。
关于java - 使用过零率区分浊音/清音语音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17533480/