//----------- Public Events -----------

        // TODO: Figure out how will this work if there are multiple paremeters affecting the same audio property.
        public static void SetParameter(AudioEvent audioEvent, AudioParameterData audioParameterData, AudioSourceData audioSourceData, float parameterValue)
        {
            for (int i = 0; i < audioParameterData.audioPropertyCurves.Count; ++i)
            {
                AudioParameterData.AudioPropertyCurve audioPropertyCurve = audioParameterData.audioPropertyCurves[i];
                bool  validAudioProperty = true;
                float value = audioPropertyCurve.curve.Evaluate(parameterValue);

                // TODO: Clamp values;
                switch (audioPropertyCurve.audioProperty)
                {
                case AudioProperty.VOLUME:
                    audioEvent.audioSource.volume = audioEvent.volume * value;
                    break;

                case AudioProperty.PITCH:
                    audioEvent.audioSource.pitch = audioEvent.pitch * value;
                    break;

                default:
                    validAudioProperty = false;
                    break;
                }

                if (validAudioProperty)
                {
                    audioEvent.StoreAudioPropertyValue(audioPropertyCurve.audioProperty, value);
                }
            }
        }
        /// <summary>
        /// Set parameter on an audio event.
        /// </summary>
        /// <param name="audioEvent">Audio event reference.</param>
        /// <param name="parameterName">Parameter name.</param>
        /// <param name="parameterValue">Parameter value.</param>
        public void SetParameter(AudioEvent audioEvent, string parameterName, float parameterValue)
        {
            // See if we have a valid parameter.
            if (!_audioParametersInfo.ContainsKey(parameterName))
            {
                Debug.LogError("Parameter " + parameterName.ToString() + " is not defined for this audio behavior.");
                return;
            }

            AudioParameter.SetParameter(audioEvent, _audioParametersInfo[parameterName], _audioSourcesInfo[audioEvent.audioSource], parameterValue);
        }
        /// <summary>
        /// Plays the specified event.
        /// </summary>
        public AudioEvent PlaySound(string eventName, AudioSource audioSource = null)
        {
            AudioEvent audioEvent = PrepareAudioEvent(eventName, audioSource);

            audioEvent.audioSource.Play();
            if (OnPlaySound != null)
            {
                OnPlaySound(audioEvent);
            }
            return(audioEvent);
        }
        /// <summary>
        /// Plays the specified event, and fades in sound over a period of time.
        /// </summary>
        /// <returns>Audio event.</returns>
        /// <param name="eventName">Event name.</param>
        /// <param name="fadeInDuration">Fade in duration.</param>
        /// <param name="audioSource">Audio source.</param>
        public AudioEvent PlayAndFadeInSound(string eventName, float fadeInDuration, AudioSource audioSource = null)
        {
            AudioEvent audioEvent = PrepareAudioEvent(eventName, audioSource);

            audioEvent.audioSource.volume = 0.0f;
            audioEvent.audioSource.Play();
            if (OnPlaySound != null)
            {
                OnPlaySound(audioEvent);
            }
            FadeInAudio(audioEvent.audioSource, fadeInDuration);
            return(audioEvent);
        }
        //----------- Private Methods -----------

        private AudioEvent PrepareAudioEvent(string eventName, AudioSource audioSource = null)
        {
            if (audioSource == null)
            {
                audioSource = GetNextAudioSource();
            }

            InitAudioSource(audioSource);

            audioSource.clip = GetAudioClip(eventName);

            if (audioSource.clip == null)
            {
                return(new AudioEvent());
            }

            audioSource.pitch  = _audioSourcesInfo[audioSource].defaultPitch * GetPitch(eventName);
            audioSource.volume = _audioSourcesInfo[audioSource].defaultVolume * GetVolume(eventName);

            AudioEvent audioEvent = new AudioEvent()
            {
                eventName     = eventName,
                audioSource   = audioSource,
                clip          = audioSource.clip,
                audioBehavior = this,
                pitch         = audioSource.pitch,
                volume        = audioSource.volume
            };

            // Save the playing event info to the local registry...
            if (_audioEvents.ContainsKey(audioSource))
            {
                _audioEvents[audioSource] = audioEvent;
            }
            else
            {
                _audioEvents.Add(audioSource, audioEvent);
            }

            // ...and the global registry
            if (_allAudioEvents.ContainsKey(audioSource))
            {
                _allAudioEvents[audioSource] = audioEvent;
            }
            else
            {
                _allAudioEvents.Add(audioSource, audioEvent);
            }

            return(audioEvent);
        }
        public AudioEvent PlaySoundAt(string eventName, Vector3 playAt, AudioSource audioSource = null)
        {
            AudioEvent audioEvent = PrepareAudioEvent(eventName, audioSource);

            audioEvent.audioSource.transform.SetParent(null);
            audioEvent.audioSource.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
            audioEvent.audioSource.transform.position   = playAt;
            audioEvent.audioSource.Play();
            if (OnPlaySound != null)
            {
                OnPlaySound(audioEvent);
            }
            return(audioEvent);
        }
        /// <summary>
        /// Attach sound source to a game object as a child and play sound.
        /// </summary>
        /// <returns>The sound attached.</returns>
        /// <param name="eventName">Event name.</param>
        /// <param name="attachTo">Attach to.</param>
        /// <param name="audioSource">Audio source.</param>
        public AudioEvent PlaySoundAttached(string eventName, GameObject attachTo, AudioSource audioSource = null)
        {
            AudioEvent audioEvent = PrepareAudioEvent(eventName, audioSource);

            audioEvent.audioSource.transform.SetParent(null);
            audioEvent.audioSource.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
            audioEvent.audioSource.transform.SetParent(attachTo.transform, false);
            audioEvent.audioSource.Play();
            if (OnPlaySound != null)
            {
                OnPlaySound(audioEvent);
            }
            return(audioEvent);
        }