<commit_before>﻿using System;
using UnityEngine;
using UnityEngine.Assertions;
using MemoryManagment;
using System.Collections.Generic;
using MovementEffects;
using UnityEngine.Audio;

public class AudioPool : MonoBehaviour
{
    public enum MixerGroup
    {
        Master,
        Music,
        SFX,
        Dialogue,
        VoiceClips,
        Ambient,
        Collectibles,
        Tunes,
        Menu
    }

    #region Internals
    [Header("Don't touch")]
    [SerializeField]
    GameObject m_emptyPrefab;
    [SerializeField]
    AudioMixerGroup[] m_mixerGroups;
    [Header("Settings")]
    [SerializeField]
    [Range(0.0f, 1.0f)]
    float m_overlapThreshold = 0.8f;

    public static AudioPool Instance { get; set; }
    GameObjectPool m_AudioSources;
    public static AudioClipSettings DefaultSettings;

    // Use this for initialization
    void Awake()
    {
        Assert.IsNull(Instance, "More than 1 instance of AudioPool detected. ONLY HAVE 1 IN THE SCENE PLZ");
        Instance = this;

        DefaultSettings = new AudioClipSettings();
        // Set up the object pool of audio sources
        m_AudioSources = new GameObjectPool(1, m_emptyPrefab, this.gameObject);
    }
    
    IEnumerator<float> StoreClip(CustomBehaviour cb)
    {
        while (cb.GetAudioSource.isPlaying)
        {
            yield return 0f;
        }
        cb.SelfStore();
    }

    /// <summary>
    /// Returns the Mixer Group linked with the enum entry provided
    /// </summary>
    public AudioMixerGroup GetMixerGroup(MixerGroup mg)
    {
        return m_mixerGroups[(int)mg];
    }
    #endregion

    /// <summary>
    /// Plays the given audio clip with a random pitch and volume as defined in the settings given.
    /// </summary>
    public void PlayRandom(AudioClip clip, Vector3 pos, AudioClipSettings settings)
    {
        var newSound = m_AudioSources.New(pos);
        var cb = newSound.GetComponent<CustomBehaviour>();
        var audSrc = cb.GetAudioSource;
        float randomPitch = UnityEngine.Random.Range(settings.MinPitch, settings.MaxPitch);
        float randomVol = UnityEngine.Random.Range(settings.MinVolume, settings.MaxVolume);

        newSound.transform.position = pos;
        audSrc.clip = clip;
        audSrc.pitch = randomPitch;
        audSrc.volume = randomVol;
        // If settings doesnt have a mixer assigned then use the Master Mixer
        //audSrc.outputAudioMixerGroup = settings.MixerGroup == null ? m_mixerGroups[0] : settings.MixerGroup;
        audSrc.outputAudioMixerGroup = settings.MixerGroup;

        newSound.SetActive(true);
        Timing.RunCoroutine(StoreClip(cb), Segment.SlowUpdate);
    }

    /// <summary>
    /// Plays the given audio clip in the position given.
    /// </summary>
    public void Play(AudioClip newClip, Vector3 pos)
    {
        PlayRandom(newClip, pos, DefaultSettings);
    }

    /// <summary>
    /// Plays a random clip from the given clips. With a random pitch and volume as defined in the settings given.
    /// </summary>
    public void PlayRandom(AudioClip[] clips, Vector3 pos, AudioClipSettings settings)
    {
        PlayRandom(clips[UnityEngine.Random.Range(0, clips.Length)], pos, settings);
    }
}

[Serializable]
public class AudioClipSettings
{
    [SerializeField]
    AudioPool.MixerGroup m_mixerGroup;
    [SerializeField]
    [Range(-3.0f, 3.0f)]
    float m_minPitch = 1.0f;
    [SerializeField]
    [Range(-3.0f, 3.0f)]
    float m_maxPitch = 1.0f;
    [SerializeField]
    [Range(0.0f, 1.0f)]
    float m_minVolume = 1.0f;
    [SerializeField]
    [Range(0.0f, 1.0f)]
    float m_maxVolume = 1.0f;
    
    public float MinPitch
    {
        get { return m_minPitch; }
        set
        {
            m_minPitch = Mathf.Clamp(value, -3.0f, 3.0f);
        }
    }
    
    public float MaxPitch
    {
        get { return m_maxPitch; }
        set
        {
            m_maxPitch = Mathf.Clamp(value, -3.0f, 3.0f);
        }
    }
    
    public float MinVolume
    {
        get { return m_minVolume; }
        set
        {
            m_minVolume = Mathf.Clamp(value, 0.0f, 10.0f);
        }
    }
    
    public float MaxVolume
    {
        get { return m_maxVolume; }
        set
        {
            m_maxVolume = Mathf.Clamp(value, 0.0f, 1.0f);
        }
    }

    public AudioMixerGroup MixerGroup
    {
        get
        {
            return AudioPool.Instance.GetMixerGroup(m_mixerGroup);<commit_msg>Added support for single instance audio clips to AudioPool - If single instance then they wont be allowed to play simultaneously - How soon after they can be played again is defined by the class inspector variable OverlapThreshold - SingleInstance or not is defined with the AudioClipSettings<commit_after>﻿using System;
using UnityEngine;
using UnityEngine.Assertions;
using MemoryManagment;
using System.Collections.Generic;
using MovementEffects;
using UnityEngine.Audio;

public class AudioPool : MonoBehaviour
{
    public enum MixerGroup
    {
        Master,
        Music,
        SFX,
        Dialogue,
        VoiceClips,
        Ambient,
        Collectibles,
        Tunes,
        Menu
    }

    #region Internals
    [Header("Don't touch")]
    [SerializeField]
    GameObject m_emptyPrefab;
    [SerializeField]
    [Tooltip("Match these with the MixerGroup enum")]
    AudioMixerGroup[] m_mixerGroups;
    [Header("Settings")]
    // How much time must pass before a single instance audioclip can play again
    // Note this ends when the clip stops playing regardless of how high you set this
    [SerializeField]
    [Range(0.0f, 1.0f)]
    float m_overlapThreshold = 0.1f;

    // A reference to this object
    public static AudioPool Instance { get; set; }
    // The pool which holds all one shot audiosources in the game
    GameObjectPool m_AudioSources;
    // Audio settings set to default values, free to use throughout the codebase
    public static AudioClipSettings DefaultSettings;
    // A list of singleinstance audio clips that are currently playing
    List<AudioSource> m_activeClips = new List<AudioSource>();
    // 

    // Use this for initialization
    void Awake()
    {
        Assert.IsNull(Instance, "More than 1 instance of AudioPool detected. ONLY HAVE 1 IN THE SCENE PLZ");
        Instance = this;

        DefaultSettings = new AudioClipSettings();
        // Set up the object pool of audio sources
        m_AudioSources = new GameObjectPool(1, m_emptyPrefab, this.gameObject);
    }
    
    IEnumerator<float> StoreClip(CustomBehaviour cb)
    {
        while (cb.GetAudioSource.isPlaying)
        {
            yield return 0f;
        }
        cb.SelfStore();
    }

    /// <summary>
    /// Returns the Mixer Group linked with the enum entry provided
    /// </summary>
    public AudioMixerGroup GetMixerGroup(MixerGroup mg)
    {
        return m_mixerGroups[(int)mg];
    }
    #endregion

    /// <summary>
    /// Plays the given audio clip with a random pitch and volume as defined in the settings given.
    /// </summary>
    public AudioSource PlayRandom(AudioClip clip, Vector3 pos, AudioClipSettings settings)
    {
        if (settings.SingleInstance && m_activeClips.Count > 0)
        {
            // Search the list for the matching audio clip
            for (int i = 0; i < m_activeClips.Count; i++)
            {
                if (m_activeClips[i].clip.GetInstanceID() == clip.GetInstanceID())
                {
                    // Found and overlap period not over yet
                    // End the function and skip the audio clip
                    if (m_activeClips[i].time < m_overlapThreshold && m_activeClips[i].isPlaying)
                    {
                        Debug.Log(m_activeClips[i].time);
                        return null;
                    }
                    // Found and overlap is over
                    else
                    {
                        Debug.Log("removed time: " + m_activeClips[i].time);
                        m_activeClips.RemoveAt(i);
                        break;
                    }
                }
            }
        }

        GameObject newSound = m_AudioSources.New(pos);
        var cb = newSound.GetComponent<CustomBehaviour>();
        var audSrc = cb.GetAudioSource;
        float randomPitch = UnityEngine.Random.Range(settings.MinPitch, settings.MaxPitch);
        float randomVol = UnityEngine.Random.Range(settings.MinVolume, settings.MaxVolume);

        newSound.transform.position = pos;
        audSrc.clip = clip;
        audSrc.pitch = randomPitch;
        audSrc.volume = randomVol;
        audSrc.outputAudioMixerGroup = settings.MixerGroup;

        if (settings.SingleInstance)
        {
            m_activeClips.Add(audSrc);
        }

        newSound.SetActive(true);
        Timing.RunCoroutine(StoreClip(cb), Segment.SlowUpdate);

        return audSrc;       
    }

    /// <summary>
    /// Plays the given audio clip in the position given.
    /// </summary>
    public AudioSource Play(AudioClip newClip, Vector3 pos)
    {
        return PlayRandom(newClip, pos, DefaultSettings);
    }

    /// <summary>
    /// Plays a random clip from the given clips. With a random pitch and volume as defined in the settings given.
    /// </summary>
    public AudioSource PlayRandom(AudioClip[] clips, Vector3 pos, AudioClipSettings settings)
    {
        return PlayRandom(clips[UnityEngine.Random.Range(0, clips.Length)], pos, settings);
    }
}

[Serializable]
public class AudioClipSettings
{
    [SerializeField]
    AudioPool.MixerGroup m_mixerGroup;
    [Header("Randomization")]
    [SerializeField]
    [Range(-3.0f, 3.0f)]
    float m_minPitch = 1.0f;
    [SerializeField]
    [Range(-3.0f, 3.0f)]
    float m_maxPitch = 1.0f;
    [SerializeField]
    [Range(0.0f, 1.0f)]
    float m_minVolume = 1.0f;
    [SerializeField]
    [Range(0.0f, 1.0f)]
    float m_maxVolume = 1.0f;
    [SerializeField]
    public bool SingleInstance = false;
    [Header("Pitch Cycle")]
    [SerializeField]
    float m_pitchCycleStep = 0.1f;
    [SerializeField]
    float m_pitchCycleCap = 1.5f;

    public float MinPitch
    {
        get { return m_minPitch; }
        set
        {
            m_minPitch = Mathf.Clamp(value, -3.0f, 3.0f);
        }
    }
    
    public float MaxPitch
    {
        get { return m_maxPitch; }
        set
        {
            m_maxPitch = Mathf.Clamp(value, -3.0f, 3.0f);
        }
    }
    
    public float MinVolume
    {
        get { return m_minVolume; }
        set
        {
            m_minVolume = Mathf.Clamp(value, 0.0f, 1.0f);
        }
    }
    
    public float MaxVolume
    {
        get { return m_maxVolume; }
        set
        {
            m_maxVolume = Mathf.Clamp(value, 0.0f, 1.0f);
        }
    }

    public AudioMixerGroup MixerGroup
    {
        get
        {
            return AudioPool.Instance.GetMixerGroup(m_mixerGroup);
{'fraction_non_alphanumeric': 0.09067618263336079, 'fraction_numerical': 0.010613962851130022, 'mean_word_length': 2.08669867269133, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5263817', 'n_tokens_mistral': 3295, 'n_tokens_neox': 3218, 'n_words': 849}