using System.Collections.Generic; using UnityEngine; using System; //----------------------------------------------------------------------------- // Copyright 2015-2018 RenderHeads Ltd. All rights reserverd. //----------------------------------------------------------------------------- namespace RenderHeads.Media.AVProVideo { /// /// A singleton to handle mulitple instances of the AudioOutput component /// public class AudioOutputManager { private static AudioOutputManager _instance = null; public static AudioOutputManager Instance { get { if (_instance == null) { _instance = new AudioOutputManager(); } return _instance; } } private Dictionary> _accessTrackers; private Dictionary _pcmData; private AudioOutputManager() { _accessTrackers = new Dictionary>(); _pcmData = new Dictionary(); } public void RequestAudio(AudioOutput _outputComponent, MediaPlayer mediaPlayer, float[] data, int channelMask, int totalChannels, AudioOutput.AudioOutputMode audioOutputMode) { if (mediaPlayer == null || mediaPlayer.Control == null || !mediaPlayer.Control.IsPlaying()) { return; } int channels = mediaPlayer.Control.GetNumAudioChannels(); if(channels <= 0) { return; } //total samples requested should be multiple of channels #if (UNITY_5 && !UNITY_5_0) || UNITY_5_4_OR_NEWER Debug.Assert(data.Length % totalChannels == 0); #endif if (!_accessTrackers.ContainsKey(mediaPlayer)) { _accessTrackers[mediaPlayer] = new HashSet(); } //requests data if it hasn't been requested yet for the current cycle if (_accessTrackers[mediaPlayer].Contains(_outputComponent) || _accessTrackers[mediaPlayer].Count == 0 || _pcmData[mediaPlayer] == null) { _accessTrackers[mediaPlayer].Clear(); int actualDataRequired = data.Length / totalChannels * channels; _pcmData[mediaPlayer] = new float[actualDataRequired]; GrabAudio(mediaPlayer, _pcmData[mediaPlayer], channels); _accessTrackers[mediaPlayer].Add(_outputComponent); } //calculate how many samples and what channels are needed and then copy over the data int samples = Math.Min(data.Length / totalChannels, _pcmData[mediaPlayer].Length / channels); int storedPos = 0; int requestedPos = 0; //multiple mode, copies over audio from desired channels into the same channels on the audiosource if (audioOutputMode == AudioOutput.AudioOutputMode.Multiple) { int lesserChannels = Math.Min(channels, totalChannels); for (int i = 0; i < samples; ++i) { for (int j = 0; j < lesserChannels; ++j) { if ((1 << j & channelMask) > 0) { data[requestedPos + j] = _pcmData[mediaPlayer][storedPos + j]; } } storedPos += channels; requestedPos += totalChannels; } } //Mono mode, copies over single channel to all output channels else if(audioOutputMode == AudioOutput.AudioOutputMode.Single) { int desiredChannel = 0; for (int i = 0; i < 8; ++i) { if ((channelMask & (1 << i)) > 0) { desiredChannel = i; break; } } if(desiredChannel < channels) { for (int i = 0; i < samples; ++i) { for (int j = 0; j < totalChannels; ++j) { data[requestedPos + j] = _pcmData[mediaPlayer][storedPos + desiredChannel]; } storedPos += channels; requestedPos += totalChannels; } } } } private void GrabAudio(MediaPlayer player, float[] data, int channels) { player.Control.GrabAudio(data, data.Length, channels); } } }