138 lines
3.7 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
|