//#define VERBOSE_LOGGING
|
|
using UnityEngine;
|
|
using System.Collections;
|
|
using System;
|
|
|
|
using Oculus.Platform;
|
|
|
|
public class BufferedAudioStream {
|
|
const bool VerboseLogging = false;
|
|
AudioSource audio;
|
|
|
|
float[] audioBuffer;
|
|
int writePos;
|
|
|
|
const float bufferLengthSeconds = 0.25f;
|
|
const int sampleRate = 48000;
|
|
const int bufferSize = (int)(sampleRate * bufferLengthSeconds);
|
|
const float playbackDelayTimeSeconds = 0.05f;
|
|
|
|
float playbackDelayRemaining;
|
|
float remainingBufferTime;
|
|
|
|
public BufferedAudioStream(AudioSource audio) {
|
|
audioBuffer = new float[bufferSize];
|
|
this.audio = audio;
|
|
|
|
audio.loop = true;
|
|
audio.clip = AudioClip.Create("", bufferSize, 1, sampleRate, false);
|
|
|
|
Stop();
|
|
}
|
|
|
|
public void Update () {
|
|
|
|
if(remainingBufferTime > 0)
|
|
{
|
|
#if VERBOSE_LOGGING
|
|
Debug.Log(string.Format("current time: {0}, remainingBufferTime: {1}", Time.time, remainingBufferTime));
|
|
#endif
|
|
|
|
if (!audio.isPlaying && remainingBufferTime > playbackDelayTimeSeconds)
|
|
{
|
|
playbackDelayRemaining -= Time.deltaTime;
|
|
if (playbackDelayRemaining <= 0)
|
|
{
|
|
#if VERBOSE_LOGGING
|
|
Debug.Log("Starting playback");
|
|
#endif
|
|
audio.Play();
|
|
}
|
|
}
|
|
|
|
if (audio.isPlaying)
|
|
{
|
|
remainingBufferTime -= Time.deltaTime;
|
|
if (remainingBufferTime < 0)
|
|
{
|
|
remainingBufferTime = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (remainingBufferTime <= 0)
|
|
{
|
|
if (audio.isPlaying)
|
|
{
|
|
Debug.Log("Buffer empty, stopping " + DateTime.Now);
|
|
Stop();
|
|
}
|
|
else
|
|
{
|
|
if (writePos != 0)
|
|
{
|
|
Debug.LogError("writePos non zero while not playing, how did this happen?");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Stop()
|
|
{
|
|
audio.Stop();
|
|
audio.time = 0;
|
|
writePos = 0;
|
|
playbackDelayRemaining = playbackDelayTimeSeconds;
|
|
}
|
|
|
|
public void AddData(float[] samples) {
|
|
int remainingWriteLength = samples.Length;
|
|
|
|
if(writePos > audioBuffer.Length) {
|
|
throw new Exception();
|
|
}
|
|
|
|
do {
|
|
int writeLength = remainingWriteLength;
|
|
int remainingSpace = audioBuffer.Length - writePos;
|
|
|
|
if(writeLength > remainingSpace) {
|
|
writeLength = remainingSpace;
|
|
}
|
|
|
|
Array.Copy(samples, 0, audioBuffer, writePos, writeLength);
|
|
|
|
remainingWriteLength -= writeLength;
|
|
writePos += writeLength;
|
|
if(writePos > audioBuffer.Length) {
|
|
throw new Exception();
|
|
}
|
|
if(writePos == audioBuffer.Length) {
|
|
writePos = 0;
|
|
}
|
|
} while(remainingWriteLength > 0);
|
|
|
|
#if VERBOSE_LOGGING
|
|
float prev = remainingBufferTime;
|
|
#endif
|
|
remainingBufferTime += (float)samples.Length / sampleRate;
|
|
#if VERBOSE_LOGGING
|
|
Debug.Log(string.Format("previous remaining: {0}, new remaining: {1}, added {2} samples", prev, remainingBufferTime, samples.Length));
|
|
#endif
|
|
audio.clip.SetData(audioBuffer, 0);
|
|
}
|
|
|
|
|
|
}
|