主要用於音樂可視化
教程已經很多了,但是沒有拖上來就能用的
直接提供組件,歡迎複製黏貼
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MusicSampler
{
public class MusicSampler : MonoBehaviour
{
#region Inspector
/// <summary>
/// 這個參數用於設置進行採樣的精度
/// </summary>
public SpectrumLength SpectrumCount = SpectrumLength.Spectrum256;
private int spectrumLength => (int)Mathf.Pow(2, ((int)SpectrumCount + 6));
/// <summary>
/// 這個屬性返回採樣得到的原始數據
/// </summary>
public float[] samples = new float[64];
private int[] sampleCount = new int[8];
/// <summary>
/// 這個參數用於設置將採樣的結果分爲幾組進行討論
/// </summary>
public uint BandCount = 8;
/// <summary>
/// 這個參數用於設置組別採樣數值減小時使用的平滑策略
/// </summary>
public BufferDecreasingType decreasingType = BufferDecreasingType.Jump;
/// <summary>
/// 這個參數用於設置在Slide和Falling設置下,組別採樣數值減小時每幀下降的大小。
/// </summary>
public float decreasing = 0.003f;
/// <summary>
/// 這個參數用於設置在Falling設置下,組別採樣數值減小時每幀下降時加速度的大小。
/// </summary>
public float DecreaseAcceleration = 0.2f;
/// <summary>
/// 這個參數用於設置組別採樣數值增大時使用的平滑策略
/// </summary>
public BufferIncreasingType increasingType = BufferIncreasingType.Jump;
/// <summary>
/// 這個參數用於設置在Slide設置下,組別採樣數值增大時每幀增加的大小。
/// </summary>
public float increasing = 0.003f;
/// <summary>
/// 這個屬性返回經過平滑和平均的幾組數據
/// </summary>
public float[] bands = new float[8];
private float[] freqBands = new float[8];
private float[] bandBuffers = new float[8];
private float[] bufferDecrease = new float[8];
/// <summary>
/// 這個屬性返回總平均採樣結果
/// </summary>
public float average
{
get
{
float average = 0;
for(int i = 0; i < BandCount; i++)
{
average += normalizedBands[i];
}
average /= BandCount;
return average;
}
}
private float[] bandHighest = new float[8];
/// <summary>
/// 這個屬性返回經過平滑、平均和歸一化的幾組數據
/// </summary>
public float[] normalizedBands = new float[8];
private float[] normalizedBandBuffers = new float[8];
#endregion
#region RequiredComponent
[SerializeField]
AudioSource AudioSource = null;
#endregion
#region LifePeriod
private void Start()
{
GetSampleCount();
}
private void OnValidate()
{
if (samples.Length != spectrumLength) samples = new float[spectrumLength];
if (bands.Length != BandCount) bands = new float[BandCount];
if (freqBands.Length != BandCount) freqBands = new float[BandCount];
if (bandBuffers.Length != BandCount) bandBuffers = new float[BandCount];
if (bufferDecrease.Length != BandCount) bufferDecrease = new float[BandCount];
if (bandHighest.Length != BandCount) bandHighest = new float[BandCount];
if (normalizedBands.Length != BandCount) normalizedBands = new float[BandCount];
if (normalizedBandBuffers.Length != BandCount) normalizedBandBuffers = new float[BandCount];
if (sampleCount.Length != BandCount) sampleCount = new int[BandCount];
}
private void Update()
{
GetSpectrums();
GetFrequencyBands();
GetNormalizedBands();
GetBandBuffers(increasingType, decreasingType);
BandNegativeCheck();
}
#endregion
#region Programs
private void GetSampleCount()
{
float acc = (((float)((int)SpectrumCount + 6)) / BandCount);
int sum = 0;
int last = 0;
for (int i = 0; i < BandCount - 1; i++)
{
int pow = (int)Mathf.Pow(2, acc * (i));
sampleCount[i] = pow - sum;
if (sampleCount[i] < last) sampleCount[i] = last;
sum += sampleCount[i];
last = sampleCount[i];
}
sampleCount[BandCount - 1] = samples.Length - sum;
}
private void GetSpectrums()
{
AudioSource.GetSpectrumData(samples, 0, FFTWindow.Blackman);
}
private void GetFrequencyBands()
{
int counter = 0;
for (int i = 0; i < BandCount; i++)
{
float average = 0;
for(int j = 0; j < sampleCount[i]; j++)
{
average += samples[counter] * (counter + 1);
counter++;
}
average /= sampleCount[i];
freqBands[i] = average * 10;
}
}
private void GetNormalizedBands()
{
for (int i = 0; i < BandCount; i++)
{
if (freqBands[i] > bandHighest[i])
{
bandHighest[i] = freqBands[i];
}
}
}
private void GetBandBuffers(BufferIncreasingType increasingType, BufferDecreasingType decreasingType)
{
for (int i = 0; i < BandCount; i++)
{
if (freqBands[i] > bandBuffers[i])
{
switch(increasingType)
{
case BufferIncreasingType.Jump:
bandBuffers[i] = freqBands[i];
bufferDecrease[i] = decreasing;
break;
case BufferIncreasingType.Slide:
bufferDecrease[i] = decreasing;
bandBuffers[i] += increasing;
break;
}
if (freqBands[i] < bandBuffers[i]) bandBuffers[i] = freqBands[i];
}
if (freqBands[i] < bandBuffers[i])
{
switch(decreasingType)
{
case BufferDecreasingType.Jump:
bandBuffers[i] = freqBands[i];
break;
case BufferDecreasingType.Falling:
bandBuffers[i] -= decreasing;
break;
case BufferDecreasingType.Slide:
bandBuffers[i] -= bufferDecrease[i];
bufferDecrease[i] *= 1 + DecreaseAcceleration;
break;
}
if (freqBands[i] > bandBuffers[i]) bandBuffers[i] = freqBands[i]; ;
}
bands[i] = bandBuffers[i];
if (bandHighest[i] == 0) continue;
normalizedBands[i] = (freqBands[i] / bandHighest[i]);
normalizedBandBuffers[i] = (bandBuffers[i] / bandHighest[i]);
if (normalizedBands[i] > normalizedBandBuffers[i])
{
switch (increasingType)
{
case BufferIncreasingType.Jump:
normalizedBandBuffers[i] = normalizedBands[i];
bufferDecrease[i] = decreasing;
break;
case BufferIncreasingType.Slide:
bufferDecrease[i] = decreasing;
normalizedBandBuffers[i] += increasing;
break;
}
if (normalizedBands[i] < normalizedBandBuffers[i]) normalizedBandBuffers[i] = normalizedBands[i];
}
if (normalizedBands[i] < normalizedBandBuffers[i])
{
switch (decreasingType)
{
case BufferDecreasingType.Jump:
normalizedBandBuffers[i] = normalizedBands[i];
break;
case BufferDecreasingType.Falling:
normalizedBandBuffers[i] -= decreasing;
break;
case BufferDecreasingType.Slide:
normalizedBandBuffers[i] -= bufferDecrease[i];
bufferDecrease[i] *= 1 + DecreaseAcceleration;
break;
}
if (normalizedBands[i] > normalizedBandBuffers[i]) normalizedBandBuffers[i] = normalizedBands[i];
}
normalizedBands[i] = normalizedBandBuffers[i];
}
}
private void BandNegativeCheck()
{
for(int i = 0; i < BandCount; i++)
{
if (bands[i] < 0)
{
bands[i] = 0;
}
if (normalizedBands[i] < 0)
{
normalizedBands[i] = 0;
}
}
}
#endregion
/// <summary>
/// 通過這個函數來生成一個MusicSampler,並初始化其播放的片段爲audioClip
/// </summary>
/// <param name="audioClip">播放的片段</param>
/// <returns></returns>
public static MusicSampler CreateSampler(AudioClip audioClip)
{
GameObject go = new GameObject("MusicPlayer");
AudioSource asr = go.AddComponent<AudioSource>();
asr.clip = audioClip;
asr.loop = false;
asr.Play();
MusicSampler ms = go.AddComponent<MusicSampler>();
return ms;
}
}
public enum SpectrumLength
{
Spectrum64, Spectrum128, Spectrum256, Spectrum512, Spectrum1024, Spectrum2048, Spectrum4096, Spectrum8192
}
public enum BufferDecreasingType
{
Jump, Slide, Falling
}
public enum BufferIncreasingType
{
Jump, Slide
}
}
直接掛到物體上然後調參數,可調的參數全部打了備註。使用時從bands或normalizedBands讀取頻段數值就可以了。