| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 | //-----------------------------------------------------------------------------// Copyright 2015-2023 RenderHeads Ltd.  All rights reserved.//-----------------------------------------------------------------------------using UnityEngine;namespace RenderHeads.Media.AVProVideo{	/// <summary>	/// Audio is grabbed from the MediaPlayer and rendered via Unity AudioSource	/// This allows audio to have 3D spatial control, effects applied and to be spatialised for VR	/// Currently supported on Windows and UWP (Media Foundation API only), macOS, iOS, tvOS and Android (ExoPlayer API only)	/// </summary>	[RequireComponent(typeof(AudioSource))]	[AddComponentMenu("AVPro Video/Audio Output", 400)]	[HelpURL("https://www.renderheads.com/products/avpro-video/")]	public class AudioOutput : MonoBehaviour	{		public enum AudioOutputMode		{			OneToAllChannels,			MultipleChannels		}		[SerializeField] MediaPlayer _mediaPlayer = null;		[SerializeField] AudioOutputMode _audioOutputMode = AudioOutputMode.MultipleChannels;		[HideInInspector, SerializeField] int _channelMask = 0xffff;		[SerializeField] bool _supportPositionalAudio = false;		public MediaPlayer Player		{			get { return _mediaPlayer; }			set { ChangeMediaPlayer(value); }		}		public AudioOutputMode OutputMode		{			get { return _audioOutputMode; }			set { _audioOutputMode = value; }		}		public int ChannelMask		{			get { return _channelMask; }			set { _channelMask = value; }		}		private AudioSource _audioSource;		void Awake()		{			_audioSource = this.GetComponent<AudioSource>();			Debug.Assert(_audioSource != null);		}		void Start()		{			AudioSettings.OnAudioConfigurationChanged += OnAudioConfigurationChanged;			ChangeMediaPlayer(_mediaPlayer);		}		void OnAudioConfigurationChanged(bool deviceChanged)		{			if (_mediaPlayer == null || _mediaPlayer.Control == null)				return;			_mediaPlayer.Control.AudioConfigurationChanged(deviceChanged);		}		void OnDestroy()		{			ChangeMediaPlayer(null);		}		void Update()		{			if (_mediaPlayer != null && _mediaPlayer.Control != null && _mediaPlayer.Control.IsPlaying())			{				ApplyAudioSettings(_mediaPlayer, _audioSource);			}		}		public AudioSource GetAudioSource()		{			return _audioSource;		}		public void ChangeMediaPlayer(MediaPlayer newPlayer)		{			// When changing the media player, handle event subscriptions			if (_mediaPlayer != null)			{				_mediaPlayer.AudioSource = null;				_mediaPlayer.Events.RemoveListener(OnMediaPlayerEvent);				_mediaPlayer = null;			}			_mediaPlayer = newPlayer;			if (_mediaPlayer != null)			{				_mediaPlayer.Events.AddListener(OnMediaPlayerEvent);				_mediaPlayer.AudioSource = _audioSource;			}			if (_supportPositionalAudio)			{				if (_audioSource.clip == null)				{					// Position audio is implemented from hints found on this thread:					// https://forum.unity.com/threads/onaudiofilterread-sound-spatialisation.362782/					int frameCount = 2048 * 10;					int sampleCount = frameCount * Helper.GetUnityAudioSpeakerCount();					AudioClip clip = AudioClip.Create("dummy", frameCount, Helper.GetUnityAudioSpeakerCount(), Helper.GetUnityAudioSampleRate(), false);					float[] samples = new float[sampleCount];					for (int i = 0; i < samples.Length; i++) { samples[i] = 1f; }					clip.SetData(samples, 0);					_audioSource.clip = clip;					_audioSource.loop = true;				}			}			else if (_audioSource.clip != null)			{				_audioSource.clip = null;			}		}		// Callback function to handle events		private void OnMediaPlayerEvent(MediaPlayer mp, MediaPlayerEvent.EventType et, ErrorCode errorCode)		{			switch (et)			{				case MediaPlayerEvent.EventType.Closing:					_audioSource.Stop();					break;				case MediaPlayerEvent.EventType.Started:					ApplyAudioSettings(_mediaPlayer, _audioSource);					_audioSource.Play();					break;			}		}		private static void ApplyAudioSettings(MediaPlayer player, AudioSource audioSource)		{			// Apply volume and mute from the MediaPlayer to the AudioSource			if (audioSource != null && player != null && player.Control != null)			{				float volume = player.Control.GetVolume();				bool isMuted = player.Control.IsMuted();				float rate = player.Control.GetPlaybackRate();				audioSource.volume = volume;				audioSource.mute = isMuted;				audioSource.pitch = rate;			}		}#if (UNITY_EDITOR_WIN || UNITY_EDITOR_OSX) || (!UNITY_EDITOR && (UNITY_STANDALONE_WIN || UNITY_WSA_10_0 || UNITY_STANDALONE_OSX || UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS || UNITY_ANDROID))		void OnAudioFilterRead(float[] audioData, int channelCount)		{			AudioOutputManager.Instance.RequestAudio(this, _mediaPlayer, audioData, channelCount, _channelMask, _audioOutputMode, _supportPositionalAudio);		}#endif	}}
 |