基于光谱通量的节拍检测算法

前段时间在研究节拍检测,网上的都解释得不怎么详细,但是都有原文链接,靠着划词翻译勉强看懂了,下面写一些自己的理解。

所谓节拍检测其实就是峰值判断,原理是设定一个时间范围(假设是1ms),用当前1ms内的“音量值”与前后1ms的“音量值”做比较(暂时叫音量值比较好理解),如果比前后都要大很多(实际不是那么简单),那么这1ms就可以标记为节拍。比如鼓点听起来是不是比较大声。在这里插入图片描述
时间范围(窗口):
一般音乐每秒采样44100次,一秒就会有44100个采样,我们以1024个采样为一个窗口(可能人能感觉到的最短声音时间是1024/44100秒,),一秒大约就会有44个窗口,一首3分钟的歌就大约会有7920个窗口,我们要做的是根据窗口的“音量值”来进行一些操作,然后判断该窗口是不是一个节拍。
音量值的获取(光谱通量):
在时域上,音乐信号是杂乱无章的波形,就算分割成时间片也难以做出比较,所以我们就要将窗口里的信号采样通过快速傅里叶转换到频域上再进行比较(fft会调用函数就可以),1024个样本转换到频域上会有513个频率点(频率箱),然后再将该窗口上的频谱与上一个窗口的频谱差分,就会得到该窗口的“音量值”,也就是光谱通量(我觉得应该叫频谱通量但spectral翻译是光谱。。)。
以下是差分算法:
spectrum是该窗口的频谱,spectralFlux用来存放整一首歌每个窗口的光谱通量。
`

     float flux = 0;
      for( int i = 0; i < spectrum.length; i++ )	
     {
        float value = (spectrum[i] - lastSpectrum[i]);
        flux += value < 0? 0: value;//value<0则等于0
     }
     spectralFlux.add( flux );	`

节拍点的获取:

现在我们有了每个窗口的光谱通量,接下来我们可以判断该窗口是不是节拍点了,不是简单的前后比较,而是使用阈值(threshold)方法判断该窗口是不是节拍点,就是把该窗口的后10个窗口(这个可以自己定)的光谱通量加起来取一个平均值,平均值再乘一个比例就是阈值,然后判断该窗口的光谱通量是否大于阈值,如果是,那么基本就是节拍点了。
获取阈值:

 for( int i = 0; i < spectralFlux.size(); i++ )
      {
         int start = Math.max( 0, i - THRESHOLD_WINDOW_SIZE );
         int end = Math.min( spectralFlux.size() - 1, i + THRESHOLD_WINDOW_SIZE );
         float mean = 0;
         for( int j = start; j <= end; j++ )
            mean += spectralFlux.get(j);
         mean /= (end - start);
         threshold.add( mean * MULTIPLIER );
      }

红线是光谱通量,绿线是阈值
在这里插入图片描述

比较大小:

for( int i = 0; i < threshold.size(); i++ )
{
   if( threshold.get(i) <= spectralFlux.get(i) )
      prunnedSpectralFlux.add( spectralFlux.get(i) - threshold.get(i) );
   else
      prunnedSpectralFlux.add( (float)0 );
}

阈值处理后,我们再判断一下后面一格有没有大于当前的值,没有的话就真的是节拍点了:peaks用来存放整一首歌每个窗口的节拍点

for( int i = 0; i < prunnedSpectralFlux.size() - 1; i++ )
{
   if( prunnedSpectralFlux.get(i) > prunnedSpectralFlux.get(i+1) )
      peaks.add( prunnedSpectralFlux.get(i) );
   else
      peaks.add( (float)0 );				
}

最后的效果:
在这里插入图片描述

参考文献

[1] http://www.badlogicgames.com/wordpress/?p=161
[2] https://blog.csdn.net/highmiao_19/article/details/85010391
这里面有个unity的demo 写得非常好 [3]https://blog.csdn.net/frankfchaaa/article/details/82224048

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
光谱目标检测算法主要是针对高光谱遥感图像中的目标进行检测与识别。由于高光谱图像具有较高的光谱分辨率,可以提供物体的光谱特征,因此在目标检测中具有一定的优势。而MATLAB工具箱是一种功能强大的科学计算软件,包含了丰富的图像处理工具。在高光谱目标检测算法中,MATLAB工具箱可以起到辅助处理和分析的作用。 MATLAB工具箱提供了多种高光谱图像处理方法,可以对高光谱图像进行预处理、特征提取、分类等操作。其中常用的高光谱目标检测算法包括如下几种: 1. 基于像素的算法:该算法将高光谱图像中的每个像素点视为一个样本,通过统计和分析像素的光谱特征,根据预设的目标光谱信息进行目标检测。常用的像素级目标检测算法光谱角度匹配法、最小二乘法等。 2. 基于像素邻域的算法:该算法将高光谱图像中的每个像素点及其周围邻域像素作为一个样本,通过分析像素间的空间和光谱信息来实现目标检测。常用的像素邻域级目标检测算法有单像素匹配和多像素匹配等。 3. 基于光谱特征的算法:该算法主要通过分析高光谱图像中的光谱曲线来实现目标检测。常用的光谱特征包括光谱角度、光谱植被指数等。 MATLAB工具箱中提供了丰富的函数库和工具箱,可以方便地实现这些算法。通过编写相应的程序,在MATLAB环境下进行高光谱图像的读取、处理、分析和可视化,可以有效地实现高光谱目标检测算法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值