音符起始點檢測(音頻節奏檢測)(3)

原文鏈接:https://www.badlogicgames.com/wordpress/?p=129

原文鏈接: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):

圖片來自原文,誰能告訴我咋把水印去了?

現在看來,聲音中似乎有一個結構!作爲第一個猜測,這個峯值似乎表明了一個突然爆發的聲音,可能是來自鼓的。然而,要檢測這種形式的峯值是相當困難的。在下一篇文章中,我們將看到如何獲得一種形式的樣本,使我們的分析更輕鬆一些。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章