音符起始点检测(音频节奏检测)(3)

原文链接:Onset Detection Part 3: Plotting

如果不能可视化的看到音频发生的变化,处理和分析音频将是非常单调乏味的。例如,我们可能想要可视化的看到样本的振幅变化。为了满足这种需要,我编写了一个非常简单的基于Swing的类Plot。它允许我们很容易地将一个或多个浮点数数组绘制到一个窗口,并在此过程中进行缩放,以保证我们可以看到一些音频的变化。签名如下:

public class Plot
{
   public Plot( String title, int width, int height );
   public void clear( );
   public void plot( float[] samples, float samplesPerPixel, Color color );
}

一如既往这是一个非常小巧类,它有足够的方法能够完成任务。在创建 Plot 对象时,传入它的标题以及窗口的宽度和高度(以像素为单位)。要绘制值数组,可以使用plot .plot()方法。这个方法的第一个参数是我们要绘制的样本数组。注意,这里的样本并不一定意味着PCM样本。你可以把任何你想要的东西传进来。下一个参数定义了图中单位像素应该使用多少个数组的样本。这样就允许您在x轴上缩放绘图。最后一个参数是绘制样本的颜色。如果要擦除到目前为止绘制的内容,只需调用Plot.clear()。注意,如果您绘制多个数组,它们都应该有相同的scale系数。例如,绘制两个值在[- 1,1]范围内的数组是ok的。如果绘制两个数组,一个在[-1,1]范围内,另一个在[0,200]范围内,这样做很不明智。请记住这一点。在本系列中,我们将只绘制相同比例的数组。如果要绘制不同比例的数组,应该为每个图使用不同的plot实例。而且,Plot类只使用Swing(译注:Swing是一个用于开发Java应用程序用户界面的开发工具包。),速度非常慢。您不应该使用它来可视化实时数据,因为它不能同步的完成处理。

现在让我们做一些有趣的事情,并绘制存储在“samples/”文件夹(PlotExample)中的所有歌曲样本:

public class PlotExample 
{
   public static void main( String[] argv ) throws FileNotFoundException, Exception
   {
      WaveDecoder decoder = new WaveDecoder( new FileInputStream( "samples/sample.wav" ) );
      ArrayList<Float> allSamples = new ArrayList<Float>( );
      float[] samples = new float[1024];
		
      while( decoder.readSamples( samples ) > 0 )
      {
         for( int i = 0; i < samples.length; i++ )
            allSamples.add( samples[i] );
      }
		
      samples = new float[allSamples.size()];
      for( int i = 0; i < samples.length; i++ )
         samples[i] = allSamples.get(i);
		
      Plot plot = new Plot( "Wave Plot", 512, 512 );
      plot.plot( samples, 44100 / 100, Color.red );
   }
}

首先,我们 new 一个 wave 解码器,它将为我们提供 wave 文件的 PCM 数据。ArrayList allSamples将用于(缓慢地)读取解码器中的所有样本数据。ArrayList 能够自动调整类内的 array 数组大小,我们又偷懒了。注意,这样做不是一个好主意,因为我们必须将 float 转换为它的近亲 Float,Float 是一个对象实例。这个转化的过程叫做自动装箱,很讨厌(译注:自动装箱会影响效率,程序员都讨厌它)。在读取所有样本之后,我们将 ArrayList 转换为 float[] 数组,以便绘制它们。最后两行实例化了这个 Plot 并绘制了我们刚刚读取的样本。注意Plot.plot()的第二个参数。它告诉Plot在最终输出中,44100 / 100 = 441个样本使用一个像素。每个像素都显示了 0.001 秒的声音序列的振幅(译注:我猜是0.01秒)。您可以尝试使用这个参数来获得对波形的更细粒度的观察(警告:如果您将 samplePerPixel 参数设置得非常低,那么生成的图像将非常大,那么您需要为vm(译注:可能是jvm,Java虚拟机)提供更多的堆内存!)这是这个程序的输出:

图片来自原文,谁能告诉我咋把水印去了?

这是音频文件中所有样本的振幅图。它没有给我们很多关于onsets的信息。看起来一团糟。让我们看看当我们将采样像素设置为一个较低的值时,我们能得到了什么结果(这样我们就可以在图中获得更大的分辨率(采样像素 = 44100/1000):

图片来自原文,谁能告诉我咋把水印去了?

现在看来,声音中似乎有一个结构!作为第一个猜测,这个峰值似乎表明了一个突然爆发的声音,可能是来自鼓的。然而,要检测这种形式的峰值是相当困难的。在下一篇文章中,我们将看到如何获得一种形式的样本,使我们的分析更轻松一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值