2016-11-28 260 views
4

我正在創建一個基於節奏的音樂遊戲,您應該在其中理論上可以選擇任何您想要的歌曲。這是使用C#在Unity(5.4.1)中創建的。音樂的音高檢測

實時檢測到的歌曲的音高,並通過可視化器顯示給用戶。

我遇到的問題是我已經創建了一個可視化器,但是這幾乎沒有顯示高音部分的音符。我擔心這是因爲(與大多數音樂一樣),一次播放多個音高(爲了測試,我正在使用Darude Sandstorm,同時等待音響人員給我音樂)。最終,我希望這個音高檢測能夠告訴用戶是否擊中高音,中音或低音。

我使用 GetComponent<FFT>().PitchValue;AudioListener.GetSpectrumData(2048, 0, FFTWindow.Hamming);

我猜令人擔心的是,它只是不能對歌曲做了一些曾經在正在播放的間距(即基地覆蓋的高音嘗試)。

我很樂意聽到任何建議,或知道是否有人已經克服了類似的問題。

這是我正在使用的一個例子,我已經嘗試了許多不同的在線解決方案(其中一些信息實際上來自於代碼註釋中鏈接的教程),我打算全面參考如果我繼續走這條道路(我現在一直在做這個兼職工作幾個星期)。它使一個漂亮的可視化,但我似乎無法充分利用它。這可以很好地作爲一個沒有if else陳述的可視化工具,這正是我目前正在做一些試驗和錯誤的地方。我下面this tutorial

//the class{ 
    using UnityEngine; 
    using System.Collections; 
    public class soundspectrume : MonoBehaviour { 
    public GameObject prefab; // the cube prefab 
    public int numberOfObjects = 25; // number of cubes to make visualizer 
    public float radius = 5f; // radius of circle 
    public GameObject[] cubes; //array of the created cubes 
    public float PitchValue; 
    public Color mycolour; 

    void Start() 
    { 
     PitchValue = GameObject.Find("Main Camera").GetComponent<FFT>().PitchValue;//this declares the pitch value but it will always be 0 as it is declared before the musics intro on start 
     for (int i = 0; i < numberOfObjects; i++) //loop to create the cubes 
     { 
      float angle = i * Mathf.PI * 2/numberOfObjects; 
      Vector3 pos = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)) * radius; // this code is from unity docs https://docs.unity3d.com/Manual/InstantiatingPrefabs.html 
      Instantiate(prefab, pos, Quaternion.identity); //instanciate's cubes 
     } 
     cubes = GameObject.FindGameObjectsWithTag("cube"); 
    } 

// Update is called once per frame 
    void Update() { 
     PitchValue = GameObject.Find("Main Camera").GetComponent<FFT>().PitchValue; 
     print(PitchValue); 
     float[] spectrum = AudioListener.GetSpectrumData(2048, 0, FFTWindow.Hamming); // always move sample to power of 2, max will make cubes move without punch lower numbers less control. 
     for (int i = 0; i < numberOfObjects; i++) 
     { 
      if (PitchValue <= 200) 
      { 
       Vector3 previousscale = cubes[i].transform.localScale; 
       previousscale.y = spectrum[i] * 500; //take spectrum number and multiply, higher frequency songs will need greater multiplier 
       cubes[i].transform.localScale = previousscale; 
      } 
      else if (PitchValue >= 201) 
      { 
       Vector3 previousscale = cubes[i].transform.localScale; 
       previousscale.y = spectrum[i] * 1; //take spectrum number and multiply, higher frequency songs will need greater multiplier 
       cubes[i].transform.localScale = previousscale; 
      } 
      else if (PitchValue >= 500) 
      { 
       Vector3 previousscale = cubes[i].transform.localScale; 
       previousscale.y = spectrum[i] * 100; //take spectrum number and multiply, higher frequency songs will need greater multiplier 
       cubes[i].transform.localScale = previousscale; 
      } 
     } 
    } 
} 

Attached image with some of the pitch output values printed

感謝到目前爲止評論,對不起,我沒有在一開始

+0

什麼是你用你的聲音拾取?平均筆記本電腦沒有內置大麥克風。 – RBarryYoung

+0

@RBarryYoung我相信他們正在使用mp3或類似的文件格式,然後獲得'AudioSource'的頻譜數據,使用'AudioListener'作爲中間節目 –

+0

@RBarryYoungI的確使用MP3。我將音高數據設置爲在更新時打印,並且它似乎正在返回一系列值(0-654.000) –

回答

0

那裏正在研究類似的東西附着在這種情況下,任何人,我設法在使用數組訪問FFT頻譜數據時分離這些音高。

歡迎任何反饋。

我通過學習FFT如何工作(認真推薦可汗學院)並找到這個真棒傢伙視頻 - https://www.youtube.com/watch?v=V_8JSWVT36k,發現它在JS中做同樣的事情。

using UnityEngine; 
using System.Collections; 

public class SPECTRUMANALYZER : MonoBehaviour 
{ 
    void Update() 
    { 
     float[] spectrum = new float[1024]; 
     AudioListener.GetSpectrumData(spectrum, 0, FFTWindow.Rectangular); 
     float l1 = spectrum [0] + spectrum [2] + spectrum [4]; 
     float l2 = spectrum [10] + spectrum [11] + spectrum [12]; 
     float l3 = spectrum[20] + spectrum [21] + spectrum [22]; 
     float l4 = spectrum [40] + spectrum [41] + spectrum [42] + spectrum [43]; 
     float l5 = spectrum [80] + spectrum [81] + spectrum [82] + spectrum [83]; 
     float l6 = spectrum [160] + spectrum [161] + spectrum [162] + spectrum [163]; 
     float l7 = spectrum [320] + spectrum [321] + spectrum [322] + spectrum [323]; 
     Debug.Log(l7); 
     GameObject [] cubes = GameObject.FindGameObjectsWithTag("CUBE"); 

    for(int i = 1; i < cubes.Length; i++) 
    { 
     switch (i) 
     { 
      case 1: 
       cubes[i].gameObject.transform.localScale = new Vector3(1, l1 * 100, 0.5f); // base drum 
       break; 
      case 2: 
       cubes[i].gameObject.transform.localScale = new Vector3(1, l2 * 200, 0.5f); // base guitar 
       break; 
      case 3: 
       cubes[i].gameObject.transform.localScale = new Vector3(1, l3 * 400, 0.5f); 
       break; 
      case 4: 
       cubes[i].gameObject.transform.localScale = new Vector3(1, l4 * 800, 0.5f); 
       break; 
      case 5: 
       cubes[i].gameObject.transform.localScale = new Vector3(1, l5 * 1600, 0.5f); 
       break; 
      case 6: 
       cubes[i].gameObject.transform.localScale = new Vector3(1, l6 * 3200, 0.5f); 
       break; 
      case 7: 
       cubes[i].gameObject.transform.localScale = new Vector3(1, l7 * 6400, 0.5f); //*tsk tsk tsk 
       break; 
     }   
    } 
} 

}