# Audio Visualizing

{% embed url="https://gyazo.com/3420f6d8713012b8a0b3a85a8a7e7ac1" %}
The environment reacts based on the audio volume and pitch.
{% endembed %}

## Volume

Anouk added a script that could recognize different pitches in the audio input. I was able to determine the volume of the audio using that script and implemented several interactions that depended on the volume.



```
    private float GetVolume() // finds the loudest pitch to determine the volume of the sound
    {
        float loudestPitch = 0f;

        for (int i = 0; i < AudioPeer._bandBuffer.Length; i++)
        {
            if (AudioPeer._bandBuffer[i] > loudestPitch)
            {
                loudestPitch = AudioPeer._bandBuffer[i];
            }
        }
        return loudestPitch;
    }
```

## Changing object colors

I thought it could be interesting to change a material color between two colors depending on the amount of audio volume. So I made a script that could change a specific material color. After getting it to work I noticed that it would flicker pretty quickly, because the audio volume could change rather quickly depending on the audio input. To fix this issue I made a tiny delay in getting the volume from the GetVolume() function and interpolated between the previous and current volume colors to get a smooth transition. After I implemented that I showed it to my team.

I got the feedback that I didn't have to change the actual material color, but could just change the color of the specific instance of the material on a mesh. My code didn't work with that in mind, however I agreed that that would be more useful so I decided to refactor my code.

After refactoring the code worked perfectly.&#x20;

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ColorManager : MonoBehaviour
{
    public int amountOfColorPairs;

    [SerializeField]
    private List<GameObject> objectsToColor;
    [SerializeField]
    private List<GameObject> objectsToColorContainers;

    [SerializeField]
    private List<Color> minColor;
    [SerializeField]
    private List<Color> maxColor;
    [SerializeField]
    private List<Color> currentColor;

    [SerializeField]
    private VolumeManager volumeManager;
    [SerializeField]
    private float delayTime = .25f;
    private bool delayActive;
    private float colorAudioVolume;
    private float lerpSpeed = 0.1f;

    // Start is called before the first frame update
    void Awake()
    {
        GetAllChildren();
        for (int i = 0; i < minColor.Count; i++) // fill the currentColor list so we can change the items later
        {
            currentColor.Add(minColor[i]);
        }
        amountOfColorPairs = currentColor.Count;
    }

    void Update()
    {
        if (!delayActive)
        {
            StartCoroutine(Delay());
        }
        ChangeMaterialColor();
    }

    IEnumerator Delay() // adds a delay on getting the volume so we get time to lerp between colors so it doesn't flicker
    {
        delayActive = true;
        yield return new WaitForSeconds(delayTime);

        colorAudioVolume = volumeManager.volume;
        DetermineMaterialColor();

        delayActive = false;
    }

    private void GetAllChildren()
    {
        for (int i = 0; i < transform.childCount; i++)
        {
            if (transform.GetChild(i).GetComponent<ColorIndex>())
            {
                objectsToColor.Add(transform.GetChild(i).gameObject);
            }
        }

        if (objectsToColorContainers.Count > 0)
        {
            for (int i = 0; i < objectsToColorContainers.Count; i++) // makes it possible to add containers to the list for ease of use.
            {
                for (int j = 0; j < objectsToColorContainers[i].transform.childCount; j++)
                {
                    if (objectsToColorContainers[i].transform.GetChild(j).GetComponent<ColorIndex>())
                    {
                        objectsToColor.Add(objectsToColorContainers[i].transform.GetChild(j).gameObject);
                    }
                }
            }
        }
    }

    private void ChangeMaterialColor()
    {
        for (int i = 0; i < objectsToColor.Count; i++)
        {
            Color color = objectsToColor[i].GetComponent<MeshRenderer>().material.color;
            Color newColor = currentColor[objectsToColor[i].GetComponent<ColorIndex>().colorIndex];
            objectsToColor[i].GetComponent<MeshRenderer>().material.color = Color.Lerp(color, newColor, lerpSpeed);
        }
    }

    private void DetermineMaterialColor()
    {
        for (int i = 0; i < currentColor.Count; i++)
        {
            float red = CalculateSingleColor(minColor[i].r, maxColor[i].r);
            float green = CalculateSingleColor(minColor[i].g, maxColor[i].g);
            float blue = CalculateSingleColor(minColor[i].b, maxColor[i].b);

            currentColor[i] = new Color(red, green, blue); // the new current color, the object will use this color in ChangeMaterialColor()
        }
    }

    private float CalculateSingleColor(float minColor, float maxColor)
    {
        float colorScale = colorAudioVolume / 3f; // volume is a value between [0-10], RGB colors in unity are between [0-1]
        float inBetweenColor = maxColor - minColor;
        float newColor = inBetweenColor = minColor + (inBetweenColor * colorScale);
        return newColor;
    }
}

```
