Skip to content

udune/TMIProject

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Minchan Kim TMI Project Portfolio

TMI Project

Profile

시연영상 전체 기능 보기

시연영상 핵심 기능 보기

안녕하세요. 김민찬 입니다.

이 프로젝트는 '악기를 연주하고 녹음을 하는 방식으로 소리가 쌓이는 과정을 직접 느껴볼 수 있는'

악기 연주 콘텐츠를 만들어 본 프로젝트입니다.

사운드 매니저 (동적 할당)

코드 보기
======== 사운드 팩토리 ========

public class SoundFactory : MonoBehaviour
{
    Dictionary<string, GameObject> soundFileCache = new Dictionary<string, GameObject>();

    public GameObject Load(string resourcePath)
    {
        GameObject go = null;

        if (soundFileCache.ContainsKey(resourcePath))
        {
            go = soundFileCache[resourcePath];
        }
        else
        {
            go = Resources.Load<GameObject>(resourcePath);

            if (!go)
            {
                Debug.LogError("Resources Load Error! Path = " + resourcePath);
                return null;
            }

            soundFileCache.Add(resourcePath, go);
        }

        GameObject InstancedGO = Instantiate<GameObject>(go);
        string replaceName = InstancedGO.name.Replace("(Clone)", "");
        InstancedGO.name = replaceName;
        return InstancedGO;
    }
}

======== 사운드 매니저 ========

public class SoundManager : MonoBehaviour
{
    [SerializeField] SoundFactory soundFactory;

    [SerializeField] Dictionary<string, Queue<GameObject>> sounds = new Dictionary<string, Queue<GameObject>>();

    void Start()
    {
        for (int i = 0; i < SoundSystem.Instance.SoundMenu.SoundMenuData.Length; i++)
        {
            string instrumentName = SoundSystem.Instance.SoundMenu.SoundMenuData[i].instrumentName;
            int soundCacheCount = SoundSystem.Instance.SoundMenu.SoundMenuData[i].soundCacheCount;
            List<string> instrumentSoundPath = SoundSystem.Instance.SoundMenu.SoundMenuData[i].instrumentSoundPath;
            Transform parent = SoundSystem.Instance.SoundMenu.SoundMenuData[i].instrument;
            
            GenerateSound(instrumentName, soundCacheCount, instrumentSoundPath, parent);
        }
    }

    public bool GenerateSound(string instrumentName, int soundCacheCount, List<string> instrumentSoundPath, Transform parent)
    {
        if (sounds.ContainsKey(instrumentName))
        {
            Debug.LogWarning("Already Sound Generated Instrument = " + instrumentName);
            return false;
        }
        else
        {
            Queue<GameObject> queue = new Queue<GameObject>();
            List<string> soundPath = new List<string>();
            
            for (int i = 0; i < soundCacheCount; i++)
            {
                GameObject go = soundFactory.Load(SoundSystem.Instance.SoundMenu.SoundMenuPrefabPath);
            
                if (!go)
                {
                    Debug.LogError("SoundFactory GenerateSound Load Error!");
                    return false;
                }
            
                go.transform.SetParent(parent);
                go.transform.localScale = Vector3.one;
                go.transform.localPosition = new Vector3(transform.position.x, transform.position.y, 0);
                go.transform.localRotation = Quaternion.Euler(Vector3.zero);

                if (instrumentSoundPath[i] != String.Empty)
                {
                    AudioSource audio = go.AddComponent<AudioSource>();
                    audio.playOnAwake = false;
                    audio.clip = Resources.Load(instrumentSoundPath[i]) as AudioClip;
                }
                else
                {
                    go.AddComponent<AudioSource>();
                }

                queue.Enqueue(go);
            }
            
            sounds.Add(instrumentName, queue);
        }
        
        return true;
    }
}

======== 사운드 메뉴 ========

[System.Serializable]
public class SoundMenuData
{
    public string instrumentName;
    public Transform instrument;
    public int soundCacheCount;
    public List<string> instrumentSoundPath = new List<string>();
}

public class SoundMenu : MonoBehaviour
{
    [SerializeField] private string soundMenuPrefabPath;
    public string SoundMenuPrefabPath => soundMenuPrefabPath;
    
    [SerializeField] SoundMenuData[] soundMenus;
    public SoundMenuData[] SoundMenuData => soundMenus;
}

======== 사운드 ========

public class Sound : MonoBehaviour
{
    private bool isPlay = false;

    public void Play(GameObject sound)
    {
        sound.GetComponent<AudioSource>().Play();
    }

    public void InputSound(GameObject sound, GameObject player)
    {
        player.GetComponent<ControllerSound>().RightBall.GetComponent<AudioSource>().clip = sound.GetComponent<AudioSource>().clip;
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Controller"))
        {
            if (!isPlay)
            {
                isPlay = true;
                GetComponentInChildren<Transform>().Find("Marker").GetComponent<Image>().color = new Color(1,1,1,1);
                Play(this.gameObject);
            }

            StartCoroutine(PlayDelay());
        }
    }

    private void OnTriggerStay(Collider other)
    {
        if (other.gameObject.CompareTag("Controller"))
        {
            if (Controller.Instance.Menu2.GetState(SteamVR_Input_Sources.RightHand))
            {
                InputSound(this.gameObject, other.gameObject);
                other.gameObject.GetComponent<ControllerSound>().RightBall.GetComponent<PlayerBall>().ColorChange(true);
                other.gameObject.GetComponent<ControllerSound>().SoundMarker.transform.Find("SoundMarker").gameObject.SetActive(true);
            }
        }
    }

    private void OnTriggerExit(Collider other)
    {
        GetComponentInChildren<Transform>().Find("Marker").GetComponent<Image>().color = new Color(1,1,1,25.0f / 255.0f);
    }

    IEnumerator PlayDelay()
    {
        yield return new WaitForSeconds(1f);
        isPlay = false;
    }
}

사운드 옥타브 및 타입 변경

코드 보기
// 옥타브를 바꾸고 싶은 오디오소스가 달린 오브젝트
    [SerializeField] private GameObject[] sounds;
    //

    private const int plus = 12;
    private const int minus = -12;

    private string[] split;
    private int changeIndex;
    private string path;

    private int instCount;

    #endregion

    void Start()
    {

        if (GetComponentInParent<Instrument>().padList == null)
        {
            return;
        }

        instCount = GetComponentInParent<Instrument>().padList.Length;
        sounds = new GameObject[instCount];

        for (int i = 0; i < instCount; i++)
        {
            sounds[i] = GetComponentInParent<Instrument>().padList[i].gameObject;
        }
    }
    
    public void OnPlusOctave()
    {
        for (int i = 0; i < sounds.Length; i++)
        {
            sounds[i].GetComponent<AudioSource>().clip = OctaveChange(PathFinder(sounds[i].GetComponent<AudioSource>().clip.name, plus));
            sounds[i].GetComponent<InstrumentPad>().sound = sounds[i].GetComponent<AudioSource>().clip;
        }
    }

    public void OnMinusOctave()
    {
        for (int i = 0; i < sounds.Length; i++)
        {
            sounds[i].GetComponent<AudioSource>().clip = OctaveChange(PathFinder(sounds[i].GetComponent<AudioSource>().clip.name, minus));
            sounds[i].GetComponent<InstrumentPad>().sound = sounds[i].GetComponent<AudioSource>().clip;
        }
    }
	
private string PathFinder(string soundName, int changeNum)
    {
        char slash = '/';

        foreach (SoundMenuData soundMenuData in SoundSystem.Instance.SoundMenu.SoundMenuData)
        {
            for (int i = 0; i < soundMenuData.instrumentSoundPath.Count; i++)
            {
                split = soundMenuData.instrumentSoundPath[i].Split(slash);

                if (split.Last() == soundName)
                {
                    changeIndex = OctaveMath(i, changeNum, soundMenuData.instrumentSoundPath.Count);
                    path = soundMenuData.instrumentSoundPath[changeIndex];
                }
            }
        }
        return path;
    }

    private int OctaveMath(int index, int changeNum, int count)
    {
        int reIndex = index + changeNum;

        if (reIndex < 0 || reIndex >= count)
        {
            Debug.Log("Octave is too lower or higher");
            return index;
        }

        return reIndex;
    }

    private AudioClip OctaveChange(string resourcePath)
    {
        AudioClip audioClip = null;

        audioClip = Resources.Load<AudioClip>(resourcePath);
        if (!audioClip)
        {
            Debug.LogError("Resources Load Error! FilePath = " + resourcePath);
            return null;
        }

        return audioClip;
    }
	
#region 변수들

    List<string> typeInst = new List<string>(3);

    // 타입 바꾸려고 하는 오디오소스
    [SerializeField] private GameObject[] sounds;

    private string instName;
    private string typeName;
    private string typeFolder;

    private const string path = "Sounds";

    private bool isClassic = false;
    private bool isElectric = false;
    private int instCount;

    #endregion

    private void Start()
    {
        #region 시작시에 타입리스트 생성

        typeInst.Add("Bass");
        typeInst.Add("Guitar");
        typeInst.Add("Piano");

        #endregion

        if (GetComponentInParent<Instrument>().padList == null) return;

        instCount = GetComponentInParent<Instrument>().padList.Length;
        sounds = new GameObject[instCount];

        for (int i = 0; i < instCount; i++)
        {
            sounds[i] = GetComponentInParent<Instrument>().padList[i].gameObject;
        }
    }

    public void OnToClassicTypeChange()
    {
        if (isClassic) return;

        for (int i = 0; i < sounds.Length; i++)
        {
            sounds[i].GetComponent<AudioSource>().clip = TypeChange(TypeChangeParsing(sounds[i].GetComponent<AudioSource>().clip.name));
            sounds[i].GetComponent<InstrumentPad>().sound = sounds[i].GetComponent<AudioSource>().clip;
        }
    }

    public void OnToElectricTypeChange()
    {
        if (isElectric) return;

        for (int i = 0; i < sounds.Length; i++)
        {
            sounds[i].GetComponent<AudioSource>().clip = TypeChange(TypeChangeParsing(sounds[i].GetComponent<AudioSource>().clip.name));
            sounds[i].GetComponent<InstrumentPad>().sound = sounds[i].GetComponent<AudioSource>().clip;
        }
    }
	
private AudioClip TypeChange(string resourcePath)
    {
        AudioClip soundClip = null;

        soundClip = Resources.Load<AudioClip>(resourcePath);

        if (!soundClip)
        {
            return null;
        }

        return soundClip;
    }

    private string TypeChangeParsing(string clipName)
    {
        char slash = '/';
        char divide = '_';
        string[] splite = clipName.Split(divide);
        for (int i = 0; i < typeInst.Count; i++)
        {
            if (typeInst[i] == splite.First())
            {
                instName = typeInst[i];

                if (splite[1] == "Grand" || splite[1] == "Classic")
                {
                    typeFolder = instName + "Electric";
                    typeName = "Electric";

                    isClassic = true;
                    isElectric = false;
                }
                else if (splite[1] == "Electric")
                {
                    typeFolder = instName + "Classic";

                    if (instName == "Piano")
                    {
                        typeName = "Grand";
                    }
                    else if (instName == "Guitar" || instName == "Bass")
                    {
                        typeName = "Classic";
                    }

                    isClassic = false;
                    isElectric = true;
                }
            }
        }

        string resourcePath = path + slash + typeFolder + slash + instName + divide + typeName + divide + splite[2] +
                       divide + splite[3];

        return resourcePath;
    }

레코드 기능

코드 보기
public class TriggerEnterEvent
{
    public AudioClip sound;
    public float timeOffset;
    public float length;
    public bool isPlaying;
    private float startTime;
    public int padIndex;

    public TriggerEnterEvent(AudioClip sound, float recordStartTime, int padIndex)
    {
        this.timeOffset = Time.time - recordStartTime;
        this.sound = sound;
        startTime = Time.time;
        this.length = 0;
        this.padIndex = padIndex;
    }

    public void OnTriggerExit()
    {
        this.length = Time.time - startTime;
    }

    public bool isNowPlaying(float t)
    {
        return t >= timeOffset && t <= timeOffset + length;
    }
}

public struct Loop
{
    public float recordLength;
    public List<TriggerEnterEvent> record;

    public Loop(List<TriggerEnterEvent> record, float length)
    {
        this.recordLength = length;
        this.record = record;
    }
}

public class Record : MonoBehaviour
{
    private List<TriggerEnterEvent> record;

    [Tooltip("녹음버튼 누른시간")]
    public float recordStartTime;
    public bool isRecording;
    public bool isCounting;

    // Recorder count setting
    public Image recorderPlayImg;
    public Text recorderCountText;

    [Tooltip("녹음 진행시간")]
    public float recordingTime;
    public float padCount;

    public static Record Instance;
    public Metronome metronome;
    public Loop recordLoop;

    public RawImage recordBg;
    public Image trackGroup;
    public RectTransform recordBgTransform;

    public GameObject nodeUIprefab;
    public GameObject loopGroup;
    public GameObject deleteGroup;

    const float TRACKGROUP_HEIGHT = 1.2f;
    const float TRACKGROUP_WIDTH = 4f;
    const float SECONDS = 60f;

    private void Awake()
    {
        Instance = this;
    }

    private void Update()
    {


        if (isRecording)
        {
            recordingTime += Time.deltaTime;

            // Track Canvas 생성
            recordBgTransform.sizeDelta = new Vector2((recordingTime * TRACKGROUP_WIDTH / SECONDS), TRACKGROUP_HEIGHT);
            recordBg.uvRect = new Rect(0, 0, metronome.tempo, padCount);
        }
    }

    private void OnTriggerEnter(Collider other)
    {

        if (other.gameObject.tag == "Controller")
        {
            if (isRecording && !isCounting) Recording();
            else StartCountDown();
        }
    }

    [ContextMenu("StartCountDown")]
    public void StartCountDown()
    {
        recorderPlayImg.enabled = false;
        isCounting = true;
    }

    public void Recording()
    {
        isCounting = false;
        if (!isRecording)
        {
            recorderPlayImg.enabled = true;
            prevRowNote = -1;
            prevTopNote = -1;
            recordBgTransform.sizeDelta = new Vector2(0, TRACKGROUP_HEIGHT);
            recordingTime = 0;
            record = new List<TriggerEnterEvent>();
            isRecording = true;
            recordStartTime = Time.time;
        }
        else
        {
            isRecording = false;
            recordLoop = new Loop(record, Time.time - recordStartTime);
            metronome.recorder_BeatCount.fillAmount = 0;

            // 레코드 종료되면 Loop 그룹 생성
            GameObject loop = Instantiate(loopGroup);
            loop.transform.position = transform.position;
            loop.transform.rotation = transform.rotation;
            loop.GetComponent<RecordPlayer>().recordLoop = recordLoop;
            transform.position = new Vector3(transform.position.x, transform.position.y - 0.165f, transform.position.z);

            // Track을 Loop그룹으로 전달
            Image cloneTrack = Instantiate(trackGroup.gameObject, trackGroup.transform.parent).GetComponent<Image>();
            cloneTrack.transform.parent = loop.transform.GetChild(0).transform;
            cloneTrack.rectTransform.localPosition = new Vector2(80, 0);
            cloneTrack.rectTransform.localRotation = Quaternion.identity;
            trackGroup.rectTransform.sizeDelta = new Vector2(0, TRACKGROUP_HEIGHT);

            // Loop그룹으로 전달된 Track 우측에 Delete Object 생성
            GameObject deleteObj = Instantiate(deleteGroup);
            deleteObj.transform.parent = cloneTrack.transform;
            deleteObj.transform.localRotation = Quaternion.identity;
            deleteObj.GetComponent<RectTransform>().anchoredPosition = new Vector2(1.5f, 0);

            // delete z포지션 리셋
            Vector3 deletePosition = deleteObj.transform.localPosition;
            deletePosition.z = 0;
            deleteObj.transform.localPosition = deletePosition;

            // 레코드 Track node 초기화 부분
            Transform trackTile = trackGroup.transform.GetChild(0);
            for (int i = 1; i < trackTile.childCount; i++)
            {
                Destroy(trackTile.GetChild(i).gameObject);
            }
        }
    }

    int prevRowNote;
    int prevTopNote;

    public void AddPressButtonEvent(TriggerEnterEvent padEvent, Color padColor)
    {
        if (!isRecording)
        {
            return;
        }
        record.Add(padEvent);

        int lowestNote = record.Min(note => note.padIndex);
        int highestNote = record.Max(note => note.padIndex);
        int rowCount = Mathf.Max(highestNote - lowestNote + 1, 5);

        // Track node 출력 부분
        GameObject temp = Instantiate(nodeUIprefab, recordBg.rectTransform);
        float noteHeight = TRACKGROUP_HEIGHT / rowCount;
        temp.GetComponent<RectTransform>().sizeDelta = new Vector2((padEvent.length / SECONDS * TRACKGROUP_WIDTH) * 2, noteHeight);
        temp.GetComponent<RectTransform>().anchoredPosition = new Vector2((padEvent.timeOffset * TRACKGROUP_WIDTH / SECONDS), -(noteHeight * (highestNote - padEvent.padIndex)));
        
        //recordBg.uvRect = new Rect(0, 0, 50, noteHeight);
        
        temp.gameObject.name = padEvent.padIndex.ToString();
        temp.SetActive(true);
        temp.GetComponent<Image>().color = padColor;
        if (prevRowNote != lowestNote) SortingHeight(highestNote, noteHeight);
        if (prevTopNote != highestNote) SortingHeight(highestNote, noteHeight);
        prevTopNote = highestNote;
        prevRowNote = lowestNote;
    }

    public void SortingHeight(int highestNote, float noteHeight)
    {
        Vector2 temp;
        recordBg.GetComponentsInChildren<Image>()
            .Where(x => x.tag == "Node")
            .ToList()
            .ForEach(note =>
            {
                temp = note.rectTransform.sizeDelta;
                temp.y = noteHeight;
                note.rectTransform.sizeDelta = temp;

                temp = note.rectTransform.anchoredPosition;
                temp.y = -(noteHeight * (highestNote - int.Parse(note.gameObject.name)));
                note.rectTransform.anchoredPosition = temp;
            });
    }

    [ContextMenu("PrintLoopInfo")]
    public void PrintLoopInfo()
    {
        print($"length : {recordLoop.recordLength}");
        recordLoop.record.ForEach(note => print($"note info: [{note.sound.name}] : [{note.length}]"));
    }
}

컨트롤러의 그랩 및 스케일 변경

코드 보기
    void Update()
    {
        switch (Controller.Instance.GrabStates)
        {
            case Controller.GrabState.Grab:
            case Controller.GrabState.RightGrab:
            case Controller.GrabState.LeftGrab:
                UpdateGrab();
                break;
            case Controller.GrabState.Scale:
                UpdateScale();
                break;
        }
    }

    void UpdateGrab()
    {
        if (this.gameObject.name == Controller.WhichIsHand.rightHand)
        {
            TransformChange(SteamVR_Input_Sources.RightHand, Controller.Instance.IsRightGrab, Controller.Instance.GrabRightObj);
        }
        
        if (this.gameObject.name == Controller.WhichIsHand.leftHand)
        {
            TransformChange(SteamVR_Input_Sources.LeftHand, Controller.Instance.IsLeftGrab, Controller.Instance.GrabLeftObj);
        }
    }

    void TransformChange(SteamVR_Input_Sources hand, bool isGrab, GameObject grabObj)
    {
        if (Controller.Instance.Grab.GetState(hand) && isGrab)
        {
            if (grabObj == null)
            {
                Debug.LogError("Grab Object is null");
                return;
            }

            if (gameObject.transform.childCount > 0)
            {
                return;
            }

            grabObj.transform.parent = gameObject.transform;
        }
        else if (Controller.Instance.Grab.GetStateUp(hand) && isGrab)
        {
            if (gameObject.transform.childCount != 0)
            {
                if (GetComponentInChildren<Grab>().transform.parent.gameObject.CompareTag("Sample"))
                {
                    grabObj.transform.parent = sampleParent;
                }
                else if (GetComponentInChildren<Grab>().transform.parent.gameObject.CompareTag("Instrument"))
                {
                    grabObj.transform.parent = instrumentParent;
                }
                else if (GetComponentInChildren<Grab>().transform.parent.gameObject.CompareTag("Menu"))
                {
                    grabObj.transform.parent = menuParent;
                }
                else if (GetComponentInChildren<Grab>().transform.parent.gameObject.CompareTag("RampHead"))
                {
                    grabObj.transform.parent = rampParent;
                }
                else
                {
                    grabObj.transform.parent = null;
                }
            }

            if (this.gameObject.name == Controller.WhichIsHand.rightHand)
            {
                Controller.Instance.GrabStates = Controller.GrabState.Grab;
                Controller.Instance.IsRightGrab = false;
                Controller.Instance.GrabRightObj = null;
            }
            else if (this.gameObject.name == Controller.WhichIsHand.leftHand)
            {
                Controller.Instance.GrabStates = Controller.GrabState.Grab;
                Controller.Instance.IsLeftGrab = false;
                Controller.Instance.GrabLeftObj = null;
            }
        }
    }
    
    void UpdateScale()
    {
        ScaleChange(SteamVR_Input_Sources.RightHand, SteamVR_Input_Sources.LeftHand, Controller.Instance.IsRightScale, Controller.Instance.IsLeftScale, Controller.Instance.ScaleObj);
    }

    void ScaleChange(SteamVR_Input_Sources hand1, SteamVR_Input_Sources hand2, bool isRightScale, bool isLeftScale, GameObject scaleObj)
    {
        if (Controller.Instance.Grab.GetState(hand1) && Controller.Instance.Grab.GetState(hand2) && isRightScale && isLeftScale)
        {
            if (scaleObj == null)
            {
                Debug.LogError("Scale Obj is null");
                return;
            }
            
            if (gameObject.transform.childCount > 0)
            {
                return;
            }

            if (gameObject.transform.childCount != 0)
            {
                scaleObj.transform.parent = instrumentParent;
            }

            float ballDist = Vector3.Distance(rightBall.transform.position, leftBall.transform.position);
            float clampBallDist = Mathf.Clamp(ballDist, 0.5f, 1.0f);

            if (scaleObj.transform.localScale.x >= 0.5f && scaleObj.transform.localScale.x <= 1.0f)
            {
                scaleObj.transform.localScale = new Vector3(clampBallDist, clampBallDist, clampBallDist);
            }
            else if (scaleObj.transform.localScale.x < 0.5f)
            {
                scaleObj.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f);
            }
            else if (scaleObj.transform.localScale.x > 1.0f)
            {
                scaleObj.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
            }
        }
        else if (Controller.Instance.Grab.GetStateUp(hand1) || Controller.Instance.Grab.GetStateUp(hand2))
        {
            Controller.Instance.GrabStates = Controller.GrabState.Grab;
            Controller.Instance.IsRightScale = false;
            Controller.Instance.IsLeftScale = false;
            Controller.Instance.ScaleObj = null;
        }
    }
}

배경 효과

코드 보기
[SerializeField] private static SoundBandManager instance = null;
    public static SoundBandManager Instance => instance;

    private void Awake()
    {
        if (instance != null)
        {
            Debug.LogError("singletone error!");
            Destroy(gameObject);
            return;
        }

        instance = this;
    }
    private const string path = "SoundBands/SoundBand";
    private int rnd;
    private float rndSpeed;
    [SerializeField] float rndSpeedMin;
    [SerializeField] float rndSpeedMax;

    void Start()
    {
        GenerateSoundBand();
        this.transform.eulerAngles = new Vector3(0, 90.0f, 0);
    }

    public GameObject Load(string resourcePath)
    {
        GameObject go = null;

        go = Resources.Load<GameObject>(resourcePath);
        if (!go)
        {
            Debug.LogError("Resources Load Error! filePath = " + resourcePath);
            return null;
        }

        GameObject instancedGo = go;
        instancedGo.name = instancedGo.name.Replace("(Clone)", "");
        return instancedGo;
    }

    public bool GenerateSoundBand()
    {
        for(int i = 0; i < 180; i++)
        {
            GameObject soundBand = Instantiate<GameObject>(Load(path));
            soundBand.SetActive(true);
            soundBand.transform.position = this.transform.position;
            soundBand.transform.parent = this.transform;
            soundBand.transform.position = Vector3.forward * 10.0f;
            //rnd = Random.Range(0, 90);
            rndSpeed = Random.Range(rndSpeedMin, rndSpeedMax);
            soundBand.GetComponent<SoundBand>().ScrollData.speed = rndSpeed;
            soundBand.GetComponent<LineRenderer>().material.SetColor("_TintColor", new Color(Random.value, Random.value, Random.value, 1.0f / 255.0f));
            this.transform.eulerAngles = new Vector3(0, i * 2.0f, 0);
            
        }

        return true;
    }

    public void HitColor(Color getColor)
    {
        SoundBand[] soundBands = GetComponentsInChildren<SoundBand>();

        foreach(SoundBand soundBand in soundBands)
        {
            soundBand.Target_r = getColor.r;
            soundBand.Target_g = getColor.g;
            soundBand.Target_b = getColor.b;
            soundBand.ChangeStart();
        }
    }

샘플 오디오 비주얼라이저

코드 보기
	void Start () {
		#region initialising arrays
		sampleArrayLeft = new float[nSamples];
		sampleArrayRight = new float[nSamples];

		bands = new float[nBands];
		bandBuffer = new float[nBands];

		bufferDecrease = new float[nBands];

		bandHighest = new float[nBands];
		audioBand = new float[nBands];
		audioBandBuffer = new float[nBands];
		#endregion

		sampleNodes = GetComponentsInChildren<SampleNode>().ToList();

		for (int i = 0; i < sampleNodes.Count; i++)
		{
			int num = i + 1;
			sampleNodes[i].gameObject.name = "SampleNode" + num;
		}
		
		aSource = GetComponent<AudioSource> ();
		AudioProfile (profilevalue);

		aSource.Play ();

	}

	void AudioProfile(float highest){
		for (int i = 0; i < nBands; i++) {
			bandHighest [i] = highest;
		}
		
	}
	
	void Update () {
		aSource.GetSpectrumData (sampleArrayLeft, 0, FFTWindow.BlackmanHarris);
		aSource.GetSpectrumData (sampleArrayRight, 1, FFTWindow.BlackmanHarris);
		FrequencyDivider ();
		CreateBandBuffer ();
		CreateAudioBands ();

		int index = -1;
		float min = float.MinValue;
		if (aSource.isPlaying)
		{
			for (int i = 0; i < audioBand.Length; i++)
			{
				float value = audioBand[i];
				if (value > min)
				{
					min = value;
					index = i;
				}
			}
				
			float beatPower = audioBand[index];
			float beatPowerClamp = Mathf.Clamp01(beatPower);
			Vector3 target = new Vector3(1 + beatPowerClamp, 1 + beatPowerClamp, 1 + beatPowerClamp);
			float targetGlow = beatPowerClamp * 255.0f;
			GameObject beatSampleNode = sampleNodes[index].gameObject;
			beatSampleNode.GetComponent<SampleNode>().SendData(beatSampleNode.name, target, targetGlow);
		}
	}
	void CreateAudioBands()
	{
		// Getting the highest band value
		for (int i = 0; i < nBands; i++) {
			if(bands[i] > bandHighest[i])
			{
				bandHighest [i] = bands [i];
			}
		}

		for (int i = 0; i < nBands; i++) {
			audioBand [i] = Mathf.Abs(bands [i] / bandHighest [i]);
			audioBandBuffer [i] = Mathf.Abs(bandBuffer [i] / bandHighest [i]);
		}
	}
		
	void CreateBandBuffer ()
	{
		for (int i = 0; i < nBands; i++) {

			if(bands[i] > bandBuffer [i])
			{
				bandBuffer [i] = bands [i];
				bufferDecrease [i] = 0.005f;
			} 
			else if(bands[i] < bandBuffer [i])
			{
				bandBuffer [i] -= bufferDecrease [i];
				bufferDecrease [i] *= 1.05f; // 20% increase
			}
		}
	}

	void FrequencyDivider(){
		int sampleCount = 0;
		int currentCount = 0;
		float average = 0;
		for (int i = 0; i < nBands; i++) {
			sampleCount = (int)Mathf.Pow(2, i + 1);

			for (int j = 0; j < sampleCount; j++) {
				average += sampleArrayLeft [currentCount] + sampleArrayRight[currentCount];
				currentCount++;
			}
			average = average / currentCount;
			bands [i] = average;
		}
	}

	void GetAmplitude()
	{
		float currentAmplitude = 0;
		float currentAmpBuffer = 0;
		for (int i = 0; i < nBands; i++) {
			currentAmplitude += audioBand [i];
			currentAmpBuffer += audioBandBuffer [i];
		}

		if(currentAmplitude > amplitudeHighest)
		{
			amplitudeHighest = currentAmplitude;
		}

		amplitude = (currentAmplitude / amplitudeHighest);
		amplitudeBuffer = (currentAmpBuffer / amplitudeHighest);
	}
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors