private NetworkAudioSourceMessage GetNewMessage()
    {
        NetworkAudioSourceMessage message = new NetworkAudioSourceMessage();

        message.NetworkAudioSourceIdentifier = myIdentifier;
        return(message);
    }
    /// <summary>
    /// Unpause the paused playback of this AudioSource.
    /// </summary>
    public void UnPause()
    {
        NetworkAudioSourceMessage message = GetNewMessage();

        message.CallIdentifier = (byte)CallIdentifier.UnPause;

        Send(message);
    }
    /// <summary>
    /// Stops playing the clip.
    /// </summary>
    public void Stop()
    {
        NetworkAudioSourceMessage message = GetNewMessage();

        message.CallIdentifier = (byte)CallIdentifier.Stop;

        Send(message);
    }
    /// <summary>
    /// Fades out the AudioSource given a specified time.
    /// </summary>
    /// <param name="fadeTime">Time to fade out clip.</param>
    public void FadeOut(float fadeTime)
    {
        NetworkAudioSourceMessage message = GetNewMessage();

        message.CallIdentifier = (byte)CallIdentifier.FadeOut;
        message.Payload        = BitConverter.GetBytes(fadeTime);

        Send(message);
    }
    /// <summary>
    /// Plays the clip at a specific time on the absolute time-line that AudioSettings.dspTime reads from.
    /// </summary>
    /// <param name="time">Time in seconds on the absolute time-line that AudioSettings.dspTime refers to for when the sound should start playing.</param>
    public void PlayScheduled(double time)
    {
        NetworkAudioSourceMessage message = GetNewMessage();

        message.CallIdentifier = (byte)CallIdentifier.PlayScheduled;
        message.Payload        = BitConverter.GetBytes(time);

        Send(message);
    }
    /// <summary>
    /// Plays the clip with a delay specified in seconds. Users are advised to use this function instead of the old Play(delay) function
    /// that took a delay specified in samples relative to a reference rate of 44.1 kHz as an argument.
    /// </summary>
    /// <param name="delay">Delay time specified in seconds.</param>
    public void PlayDelayed(float delay)
    {
        NetworkAudioSourceMessage message = GetNewMessage();

        message.CallIdentifier = (byte)CallIdentifier.PlayDelayed;
        message.Payload        = BitConverter.GetBytes(delay);

        Send(message);
    }
 private void Send(NetworkAudioSourceMessage message)
 {
     if (isServer)
     {
         NetworkServer.SendToAll(NetworkAudioSourceMessageIdentifier, message);
     }
     else
     {
         NetworkManager.singleton.client.Send(NetworkAudioSourceMessageIdentifier, message);
     }
 }
    /// <summary>
    /// Fades the AudioSource from the current volume to a specified target volume given a specified time.
    /// </summary>
    /// <param name="fadeTime">Target volume to fade in to.</param>
    /// <param name="targetVolume">Time to fade in clip.</param>
    public void FadeIn(float targetVolume, float fadeTime)
    {
        NetworkAudioSourceMessage message = GetNewMessage();

        message.CallIdentifier = (byte)CallIdentifier.FadeIn;

        byte[] arrTargetVol = BitConverter.GetBytes(targetVolume);
        byte[] arrFadeTime  = BitConverter.GetBytes(fadeTime);
        message.Payload = new byte[8];
        Buffer.BlockCopy(arrTargetVol, 0, message.Payload, 0, 4);
        Buffer.BlockCopy(arrFadeTime, 0, message.Payload, 4, 4);

        Send(message);
    }
    /// <summary>
    /// Plays an AudioClip, and scales the AudioSource volume by volumeScale.
    /// </summary>
    /// <param name="clip">The clip being played.</param>
    /// <param name="volumeScale">The scale of the volume (0-1).</param>
    public void PlayOneShot(AudioClip clip, float volumeScale = 1.0F)
    {
        if (clip == null || !AudioClipToId.ContainsKey(clip))
        {
            Debug.Log("Clip not contained in NetworkAudioSource");
        }
        else
        {
            NetworkAudioSourceMessage message = GetNewMessage();
            message.CallIdentifier = (byte)CallIdentifier.PlayOneShot;
            int    audioClipId      = AudioClipToId[clip];
            byte[] clipByteArray    = BitConverter.GetBytes(audioClipId);
            byte[] volumeScaleArray = BitConverter.GetBytes(volumeScale);
            message.Payload = new byte[8];
            Buffer.BlockCopy(clipByteArray, 0, message.Payload, 0, 4);
            Buffer.BlockCopy(volumeScaleArray, 0, message.Payload, 4, 4);

            Send(message);
        }
    }
    private static void OnReceiveNetworkAudioSourceMessage(NetworkMessage message, bool isServer)
    {
        NetworkAudioSourceMessage networkAudioSourceMessage = message.ReadMessage <NetworkAudioSourceMessage>();

        if (isServer && message.conn != NetworkManager.singleton.client.connection)
        {
            NetworkServer.SendToAll(NetworkAudioSourceMessageIdentifier, networkAudioSourceMessage);
        }
        else
        {
            if (!NetworkedAudioSources.ContainsKey(networkAudioSourceMessage.NetworkAudioSourceIdentifier))
            {
                Debug.Log($"{networkAudioSourceMessage.NetworkAudioSourceIdentifier} not found, maybe game has not finished initialising.");
                return;
            }

            NetworkAudioSource targetAudioSource = NetworkedAudioSources[networkAudioSourceMessage.NetworkAudioSourceIdentifier];

            foreach (Tuple <NetworkAudioSource, float> audioSourceVolumePair in targetAudioSource.LinkedAudioSources)
            {
                NetworkAudioSource audioSource = audioSourceVolumePair.Item1;
                float dampingFactor            = audioSourceVolumePair.Item2;

                switch (networkAudioSourceMessage.CallIdentifier)
                {
                case (byte)CallIdentifier.Pause:
                    audioSource.NetworkedAudioSource.Pause();
                    break;

                case (byte)CallIdentifier.Stop:
                    audioSource.NetworkedAudioSource.Stop();
                    break;

                case (byte)CallIdentifier.UnPause:
                    audioSource.NetworkedAudioSource.UnPause();
                    break;

                case (byte)CallIdentifier.Play:
                    ulong playDelay = BitConverter.ToUInt64(networkAudioSourceMessage.Payload, 0);
                    audioSource.SetVolume(audioSource.originalVolume * dampingFactor, true);
                    audioSource.NetworkedAudioSource.Play(playDelay);
                    break;

                case (byte)CallIdentifier.PlayDelayed:
                    float playDelayedDelay = BitConverter.ToSingle(networkAudioSourceMessage.Payload, 0);
                    audioSource.NetworkedAudioSource.PlayDelayed(playDelayedDelay);
                    break;

                case (byte)CallIdentifier.PlayScheduled:
                    double playScheduledTime = BitConverter.ToDouble(networkAudioSourceMessage.Payload, 0);
                    audioSource.NetworkedAudioSource.PlayScheduled(playScheduledTime);
                    break;

                case (byte)CallIdentifier.PlayOneShot:
                    int   clipUid     = BitConverter.ToInt32(networkAudioSourceMessage.Payload, 0);
                    float volumeScale = BitConverter.ToSingle(networkAudioSourceMessage.Payload, 4) * dampingFactor;
                    if (!IdToAudioClip.ContainsKey(clipUid))
                    {
                        Debug.Log("Clip not contained in NetworkAudioSource");
                    }
                    else
                    {
                        AudioClip clip = IdToAudioClip[clipUid];
                        audioSource.NetworkedAudioSource.PlayOneShot(clip, volumeScale);
                    }
                    break;

                case (byte)CallIdentifier.Volume:
                    uint volume = BitConverter.ToUInt32(networkAudioSourceMessage.Payload, 0);
                    audioSource.SetVolume(volume, false);
                    break;

                case (byte)CallIdentifier.FadeOut:
                    float fadeTime = BitConverter.ToSingle(networkAudioSourceMessage.Payload, 0);
                    audioSource.StartCoroutine(audioSource.FadeOutRoutine(fadeTime, audioSource.originalVolume * dampingFactor));
                    break;

                case (byte)CallIdentifier.FadeIn:
                    float targetVol  = BitConverter.ToSingle(networkAudioSourceMessage.Payload, 0);
                    float fadeInTime = BitConverter.ToSingle(networkAudioSourceMessage.Payload, 4);
                    audioSource.StartCoroutine(audioSource.FadeInRoutine(targetVol, fadeInTime, audioSource.originalVolume * dampingFactor));
                    break;

                case (byte)CallIdentifier.Clip:
                    int clipId = BitConverter.ToInt32(networkAudioSourceMessage.Payload, 0);
                    if (!IdToAudioClip.ContainsKey(clipId))
                    {
                        Debug.Log("Clip not contained in NetworkAudioSource");
                    }
                    else
                    {
                        AudioClip clip = IdToAudioClip[clipId];
                        audioSource.NetworkedAudioSource.clip = clip;
                    }
                    break;

                case (byte)CallIdentifier.DopplerLevel:
                    float dopplerLevel = BitConverter.ToSingle(networkAudioSourceMessage.Payload, 0);
                    audioSource.NetworkedAudioSource.dopplerLevel = dopplerLevel;
                    break;

                case (byte)CallIdentifier.IgnoreListenerPause:
                    bool ignoreListenerPause = BitConverter.ToBoolean(networkAudioSourceMessage.Payload, 0);
                    audioSource.NetworkedAudioSource.ignoreListenerPause = ignoreListenerPause;
                    break;

                case (byte)CallIdentifier.IgnoreListenerVolume:
                    bool ignoreListenerVolume = BitConverter.ToBoolean(networkAudioSourceMessage.Payload, 0);
                    audioSource.NetworkedAudioSource.ignoreListenerVolume = ignoreListenerVolume;
                    break;

                case (byte)CallIdentifier.Loop:
                    bool loop = BitConverter.ToBoolean(networkAudioSourceMessage.Payload, 0);
                    audioSource.NetworkedAudioSource.loop = loop;
                    break;

                case (byte)CallIdentifier.Pitch:
                    float pitch = BitConverter.ToSingle(networkAudioSourceMessage.Payload, 0);
                    audioSource.NetworkedAudioSource.pitch = pitch;
                    break;

                case (byte)CallIdentifier.Time:
                    float time = BitConverter.ToSingle(networkAudioSourceMessage.Payload, 0);
                    audioSource.NetworkedAudioSource.time = time;
                    break;

                case (byte)CallIdentifier.TimeSamples:
                    int timeSamples = BitConverter.ToInt32(networkAudioSourceMessage.Payload, 0);
                    audioSource.NetworkedAudioSource.timeSamples = timeSamples;
                    break;
                }
            }
        }
    }