簡單的使用一個Mesh來顯示波形,使用一個List來保存舊資料,就可以達到這樣類似流動的效果了。
實作測試
首先預備一些參數使用
public CreatePlane plane; //準備好的Mesh public AudioSource source; //音源 private int samples = 1024; //採樣的層數,需要2的次方,看需求設定,越大當然越耗效能 private List<float[]> datas = new List<float[]>(); //為了讓Mesh有波動的效果,所以用個List保留採樣過的資料 private int minLength; //這邊網格的寬只有50,所以計算每個點之間間格的採樣層數
網格寬的邊上50個點,每個點要代表一個Hz參數,如果只有用0~49的話,採樣的陣列資料float[1024]只有取得前50個,這不是我所想要的情況,所以稍微計算一下間隔。
Mathf.FloorToInt(1024f / 50f); 使用Floor取得整數可以避免造成index超出陣列。
接著把 float[] 丟入Unity提供的GetSpectrumData(),取得採樣後,把這個 float[] 資料存下來,存到 List<float[]> datas裡面,之後要把這個List裡面的每個資料作為Mesh的每一個橫斷面上點的Y座標來用。
最後把這個List的數值作為Y軸座標,計算調整後設定到整張Mesh各個點上,接著更新整張Mesh就完成了。
簡單製作3D圖形化音樂顯示器Code
public class AudioVisualization : MonoBehaviour { //這邊我使用前一篇製作的Mesh,可以看自己的需求,使用內建的Plane或自己製作一個來用 public CreatePlane plane; public AudioSource source; //音源 private int samples = 1024; //採樣的層數,需要2的次方, private List<float[]> datas = new List<float[]>(); //為了讓Mesh有波動的效果,所以用個List保留採樣過的資料 private int minLength; //這邊網格的寬我只有使用50,所以計算每個點之間間格的採樣層數 void Start() { minLength = Mathf.FloorToInt((float)samples / (float)plane.lengthX); //計算間隔 for(int i = 0; i < plane.lengthY; ++i) datas.Add (new float[samples]); //先準備完整數量的空白List } void Update () { GetFreq(); UpdateMesh(); } void GetFreq() { float[] newFreqData = new float[samples]; source.GetSpectrumData(newFreqData, 0, FFTWindow.BlackmanHarris); //把取得的採樣加入List然後簡單做個判斷避免List過長,刪除舊的資料 datas.Add (newFreqData); if(datas.Count > plane.lengthY) datas.RemoveAt(0); } void UpdateMesh() { for(int y = 0; y < plane.lengthY; ++y) { float[] lineSamples = datas[y]; //從List當從取得橫斷面的採樣 for(int x = 0; x < plane.lengthX; ++x) { float sample = lineSamples[x*minLength]; //取得採樣其中一點的數值 plane.matrix[(y*plane.lengthX) + x].y = Mathf.Clamp(sample * (0.5f*((x+1)*(x+1))), 0f, 5f); //簡單做個放大,並且設定最大值 } } plane.mesh.vertices = plane.matrix; //Update mesh } }
No comments:
Post a Comment