ShanxiKnowledgeBase/SXElectricalInspection/Assets/AVIDEO/AVideo/AVProVideo/Scripts/Internal/AudioOutputManager.cs

138 lines
3.7 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using System;
//-----------------------------------------------------------------------------
// Copyright 2015-2018 RenderHeads Ltd. All rights reserverd.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo
{
/// <summary>
/// A singleton to handle mulitple instances of the AudioOutput component
/// </summary>
public class AudioOutputManager
{
private static AudioOutputManager _instance = null;
public static AudioOutputManager Instance
{
get
{
if (_instance == null)
{
_instance = new AudioOutputManager();
}
return _instance;
}
}
private Dictionary<MediaPlayer, HashSet<AudioOutput>> _accessTrackers;
private Dictionary<MediaPlayer, float[]> _pcmData;
private AudioOutputManager()
{
_accessTrackers = new Dictionary<MediaPlayer, HashSet<AudioOutput>>();
_pcmData = new Dictionary<MediaPlayer, float[]>();
}
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<AudioOutput>();
}
//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);
}
}
}