Created
January 19, 2016 00:07
-
-
Save haydenjameslee/4b405cf5e08d227de318 to your computer and use it in GitHub Desktop.
Gets PCM audio data from a CoherentUI browser in Unity3D and plays it through a Unity audio filter.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using Coherent.UI; | |
using System.IO; | |
using System; | |
using System.Runtime.InteropServices; | |
[RequireComponent(typeof(CoherentUIView))] | |
[RequireComponent(typeof(AudioSource))] | |
unsafe public class CoherentAudioPlayerFilter : MonoBehaviour | |
{ | |
public int BufferSize = 8192; | |
[Range(0, 2f)] public float gain = 1f; | |
View m_View; | |
UnityViewListener m_ViewListener; | |
new AudioSource audio; | |
int m_StreamId; | |
int m_BitDepth; | |
int m_Frequency; | |
int m_Channels; | |
bool isPlaying; | |
void Start () | |
{ | |
audio = GetComponent<AudioSource>(); | |
GetComponent<CoherentUIView>().OnViewCreated += InitBrowser; | |
} | |
void InitBrowser(View view) | |
{ | |
m_View = view; | |
m_ViewListener = GetComponent<CoherentUIView>().Listener; | |
m_ViewListener.AudioStreamCreated += this.OnAudioStreamCreated; | |
m_ViewListener.AudioStreamPlay += this.OnAudioStreamPlay; | |
m_ViewListener.AudioStreamPause += this.OnAudioStreamPause; | |
m_ViewListener.AudioStreamClose += this.OnAudioStreamClose; | |
} | |
void OnAudioFilterRead(float[] data, int channels) | |
{ | |
if (!isPlaying) return; | |
int numBytes = data.Length * 2; | |
IntPtr m_AudioBuffer = Marshal.AllocHGlobal(numBytes); | |
// When you need more data to play for stream #streamID | |
int timeout = 0; // A zero timeout means block until data is received | |
int received = m_View.GetAudioData(m_StreamId, m_AudioBuffer, numBytes, timeout); | |
if (received <= 0) | |
{ | |
// Negative values indicate an error; Zero is a valid return value if no data is present | |
return; | |
} | |
// Get a byte pointer from the unmanaged memory block. | |
byte* audioBufferBytePtr = (byte*)m_AudioBuffer.ToPointer(); | |
UnmanagedMemoryStream readStream = new UnmanagedMemoryStream(audioBufferBytePtr, received, numBytes, FileAccess.Read); | |
// Create a byte array to hold data from unmanaged memory. | |
byte[] managedData = new byte[received]; | |
// Read from unmanaged memory to the byte array. | |
readStream.Read(managedData, 0, received); | |
readStream.Close(); | |
// You now have your data in *managedData* and you can set it to the audio clip. | |
//WriteToConsole("manageddata", ArrayToString(managedData)); | |
float[] audioFloats = PCMBytesToFloats(managedData); | |
for (int i = 0; i < audioFloats.Length; i++) | |
{ | |
data[i] = audioFloats[i] * gain; | |
} | |
} | |
public void OnAudioStreamCreated(int streamId, int channels, int bitDepth, int frequency) | |
{ | |
Debug.Log("sid = " + streamId + " channels = " + channels + " bitdepth = " + bitDepth + " frequency = " + frequency); | |
m_StreamId = streamId; | |
m_Channels = channels; | |
m_BitDepth = bitDepth; | |
m_Frequency = frequency; | |
AudioClip audioClip = AudioClip.Create("browser-audio-" + streamId, BufferSize, m_Channels, 44000, false); | |
audio.clip = audioClip; | |
} | |
public void OnAudioStreamPlay(int streamId) | |
{ | |
Debug.Log("on audio stream play"); | |
isPlaying = true; | |
audio.Play(); | |
} | |
public void OnAudioStreamPause(int streamId) | |
{ | |
Debug.Log("on audio stream pause"); | |
isPlaying = false; | |
audio.Pause(); | |
} | |
public void OnAudioStreamClose(int streamId) | |
{ | |
Debug.Log("on audio stream close"); | |
isPlaying = false; | |
audio.Stop(); | |
} | |
static float[] PCMBytesToFloats(byte[] bytes) | |
{ | |
float[] floats = new float[bytes.Length / 2]; | |
for (int i = 0; i < bytes.Length; i += 2) | |
{ | |
short s = BitConverter.ToInt16(bytes, i); // convert 2 bytes to short | |
floats[i / 2] = ((float)s) / (float)32768; // convert short to float | |
} | |
return floats; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment