将信号分解为频谱的另一种方法

大家好,我想在这里谈谈一种音频信号分析算法,该算法可让您将信号解析为单独的波形,当然它不能提供100%的准确度,但是我认为结果还是不错的。

图片

最好在任何音乐上工作:


并链接到不同类型的其他示例。 灵魂的金属风龙卷风:


脱节:


因此,对于分解,您需要执行以下步骤:

-从原始信号中,您需要获得8个中间信号;
-从这些中间信号和原始信号中,您需要获得8个信号-层,可以将其分解为单独的波;
-计算每层中有多少个波及其幅度。

现在,有关每个阶段的更多信息:为了获得中间信号,您需要获取原始信号的导数。 本质上,这是离散函数的导数。 为了在原始信号的每个时刻找到它,您需要设置1个参数:该导数所在的时间段。 导数值是给定间隔中的斜率系数,例如可以通过最小二乘法找到。

需要计算8个不同周期的8个中间信号。 最简单的周期集:4、8、16、32、64、128、256、512。指定了周期后,对于每个信号样本,使用最小二乘公式计算导数。 这就像移动平均线,但这里不是移动平均线,而是当前间隔的移动导数。

因此,获得了8个导出信号和1个源。 现在,需要对8个微分信号中的每一个进行积分。 在这种情况下,这意味着每个后续样本等于所有先前样本的总和。 之后,获得8个中间层。

下一步是获得可以分解成单独的波的层。 所以现在您需要获得8层。 层的计算如下:

层0 =中间0输出信号
层1 =中间1-中间0
layer2 =中间2-中间1
layer3 =中间3-中间2
layer4 =中间4-中间3
layer5 =中间5-中间4
layer6 =中间6-中间5
layer7 =中间7-中间6
layer8 =中间7

最后一层没有区别,只是等于最后一个中间信号。

您可以尝试不同的方法,即从先前的中间信号计算后续的中间信号。 但是在当前程序中,使用了1个选项。

现在,要将图层解析为单独的波,您只需要计算值增加和减少的区域。 实际上,这些部分的持续时间就是它们的波长。 您只需跳过信号值恒定的信号部分。 要在一定间隔内找到频谱中信号的振幅,需要将所有波振幅乘以其长度相加。

图片

计算中间信号的代码如下所示:

这里waveize是样本数
signal []-具有原始信号的数组
SY = 0,SX = 0,SXX = 0,SXY = 0,Ky = 0-类型为float的变量
Step2 = STEP / 2,其中STEP是周期(4,8,16,32,64,128,256,512)

for(int i=Step2;i<wavesize-Step2;i++){ SY=0,SX=0,SXX=0,SXY=0,Ky=0; for(int j=i-Step2,fromZ=0;j<i+Step2;j++,fromZ++){ SX+=fromZ; SY+=signal[j]; SXX+=fromZ*fromZ; SXY+=fromZ*signal[j]; } Ky=float((STEP)*SXY-SX*SY)/float((STEP)*SXX-SX*SX); OutSignal[i]=OutSignal[i-1]+Ky; } 

要从另一个信号中减去一个信号,只需从每个信号中减去每个样本。
例如,对于0层:

 for(int i=0;i<wavesize-1;i++) layer0[i]=OutSignal0[i]-Signal[i]; 

如果将所有层加起来,最后一个带相反的符号,则会得到原始信号,从而将任何层相乘,就可以制作一个频率滤波器。 下一个问题是如何计算特定谐波的幅度。 事实是,在恒定的时间间隔(例如= 4000个样本)中,可能有很多短波,而相对较少的长波。

您当然可以找到每一层的平均幅度并相加。 但是这种方法不是很好,因为长波很少,并且它们的振幅通常非常大,并且在低频方向上振幅很不均匀。

在通过链接显示彩色音乐的程序中,每个谐波的振幅计算如下:波形的振幅*其长度。 同样,会出现不均匀性,但不如平均情况下强。

总的来说,我不认为一个人会将声音视为频谱的分解;相反,声音是由声像组成的,声像是由不同长度的波组成的。 因此,声音的音量实际上是声音所构成的所有波的平均音量。 但是,尚不清楚什么参数构成了声音图像,可能是平均频率,标准偏差或其他。

Source: https://habr.com/ru/post/zh-CN410357/


All Articles