유니티 Audio Spectrum에서 얻은 데이터들을 대역 별로 나누기 #기초

아래 스펙트럼 대역에 대한 내용을 보고 와주세요!

 

유니티 Audio Spectrum 이론에 대해서 #기초

오디오 스펙트럼이란 악기나 음악에 포함된 음향에너지를 주파수별로 나타낸 것을 뜻합니다. 오디오 스펙트럼을 가지고 무엇을 할 수 있냐? 오디오 스펙트럼을 분석해서 아래 사진처럼 비쥬얼

wlsdn629.tistory.com

 

Audio Spectrum에서 얻은 데이터들을 대역 별로 나누기

 

 

움짤을 보면 아시겠지만 서브 베이스랑 베이스, 미드 레인지(하)가 가장 강하네요!


AudioPeer 수정

이전 Audio Peer 코드는 이전 글을 참고해주세요.

2024.03.25 - [Unity/Study] - 유니티 Audio Spectrum을 이용한 큐브 스케일 변화 시키기 #기초

 

using UnityEngine;

public class AudioPeer : MonoBehaviour
{
    public static AudioPeer Instance;
    
    public enum AudioChannel
    {
        Left = 0,      
        Right = 1,       
        Center = 2,     
        LFE = 3,        
        RearLeft = 4,   
        RearRight = 5    
    }
    
    [Header("[Ref]")]
    [SerializeField] private AudioSource audioSource;
    
    [Space(3)]
    [Header("[Value]")]
    [SerializeField, Tooltip("첫 번째 (왼쪽) 스테레오 채널 또는 모노 채널 \n두 번째 (오른쪽) 스테레오 채널 \n센터 채널 \nLFE (저주파 효과) 채널 \n후방 왼쪽 채널 \n후방 오른쪽 채널")] private AudioChannel channel = AudioChannel.Left;
    [Range(3, 12)] public int Pow = 8;
    [SerializeField] private int FreqBandSize = 8;
    public int FreqBandPower = 1;
    
    [Space(3)]
    [Header("[OutPut]")]
    public float[] Samples;
    public float[] FreqBand;
    
    private void Awake()
    {
        Instance = this;
        Samples = new float[(int)Mathf.Pow(2,Pow)];
        FreqBand = new float[FreqBandSize];
    }
    
    private void Update()
    {
        GetSpectrumAudioSource();
        MakeFrequencyBand();
    }
    
    private void GetSpectrumAudioSource()
    {
        audioSource.GetSpectrumData(samples: Samples, channel: (int)channel, FFTWindow.Blackman);
    }
    
    private void MakeFrequencyBand()
    {
        int count = 0;
        for (int i = 0; i < 8; i++)
        {
            float average = 0;
            int sampleCount = (int)Mathf.Pow(2, i) * 2;
            if (i == 7)
            {
                sampleCount += 2;
            }

            for (int j = 0; j < sampleCount; j++)
            {
                average += Samples[count];
                count++;
            }

            average /= sampleCount;
            FreqBand[i] = average * FreqBandPower;
        }
    }
}

 

새롭게 추가된 함수는 MakeFrequencyBand입니다.

이 함수는 Sample의 개수를 512개를 예시로 합니다.

 

512개로 한 이유는 2을 한 번 제곱할 때 마다 대역이 나뉜다고 생각하시면 되고, 서브 베이스부터 하이 레인지까지 총 8개가 존재하므로 2의 8제곱인 512로 정했습니다.

 

각 제곱별로 평균을 내어 FreqBand에 집어 넣어 주었습니다.


SpawnCubes 수정

이전 Spawn Cubes 스크립트도 이전 글을 참고해주세요.

using UnityEngine;
using UnityEngine.UIElements;

public class SpawnCubes : MonoBehaviour
{
    [SerializeField] private GameObject radiusObject;
    [SerializeField] private GameObject paramCube;
    private GameObject[] spawnedRadiusObjects;
    private GameObject[] spawnedParamCube;

    public float Radius = 3f;
    
    [SerializeField] private float sizePower = 10f;
    [SerializeField] private float minYScale = 1f;
    
    private float x = 0.3f;
    private float z = 0.3f;
    private int SampleLength;
    private bool isStart;
    private int length;
    
    private void Start()
    {
        SampleLength = AudioPeer.Instance.Samples.Length;
        length = AudioPeer.Instance.FreqBand.Length;
    }
    
    private void Spawn()
    {
        spawnedRadiusObjects = new GameObject[SampleLength];
        
        for (int i = 0; i < SampleLength; i++)
        {
            float angle = i * 360f / SampleLength;
            transform.rotation = Quaternion.Euler(0, angle, 0);
            
            GameObject go = Instantiate(radiusObject, transform.forward * Radius, Quaternion.identity);
            go.name = "Cube" + i;
            spawnedRadiusObjects[i] = go;
        }

        spawnedParamCube = new GameObject[length];
        
        for (int i = 0; i < length; i++)
        {
            GameObject go = Instantiate(paramCube, new Vector3((-length / 2f) + i * 1.3f, 0, 0), Quaternion.identity);
            go.name = "ParamCube" + i;
            spawnedParamCube[i] = go;
        }
        
        isStart = true;
    }


    private void Update()
    {
        if (!isStart) return;
        
        for (int i = 0; i < SampleLength; i++)
        {
            spawnedRadiusObjects[i].transform.localScale = new Vector3(x, (AudioPeer.Instance.Samples[i] * sizePower) + minYScale, z);
        }
        
        for (int i = 0; i < length; i++)
        {
            spawnedParamCube[i].transform.localScale = new Vector3(0.5f, (AudioPeer.Instance.FreqBand[i] * sizePower) + minYScale, 0.5f);
        }
    }
}

 

달라진 점은 Update에서 FreqBand, 밴드별로 나뉜 것을 참조해서 총 8개의 큐브의 사이즈를 조절하는 것이 추가되었다는 것입니다.