VR4RoboticArm2/VR4RoboticArm/Library/PackageCache/com.meta.xr.sdk.platform/Scripts/BufferedAudioStream.cs
IonutMocanu 48cccc22ad Main2
2025-09-08 11:13:29 +03:00

151 lines
5.6 KiB
C#

//#define VERBOSE_LOGGING
using UnityEngine;
using System.Collections;
using System;
using Oculus.Platform;
/// BufferedAudioStream provides a way to stream audio data from an AudioSource object.
/// It maintains an internal buffer and offers methods for updating and adding new data.
/// Update() updates playback based on remaining buffer time, while AddData() adds new data to the buffer,
/// wrapping around if necessary. This class is useful for real-time audio streaming, such as playing back
/// audio from a network connection or generating audio dynamically.
/// This class is used in VoipAudioSource, which has been deprecated. See details [here](https://developers.meta.com/horizon/blog/deprecating-oculus-rooms-api-in-march-2023/).
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;
/// The constructor of BufferedAudioStream takes an AudioSource object as a parameter and initializes the audio buffer with a specified size.
/// It also sets the loop property of the AudioSource object to true and creates an AudioClip object with the specified buffer size,
/// sample rate, and number of channels. This class is used in VoipAudioSource, which has been deprecated. See details [here](https://developers.meta.com/horizon/blog/deprecating-oculus-rooms-api-in-march-2023/).
public BufferedAudioStream(AudioSource audio)
{
audioBuffer = new float[bufferSize];
this.audio = audio;
audio.loop = true;
audio.clip = AudioClip.Create("", bufferSize, 1, sampleRate, false);
Stop();
}
/// This method updates the audio playback based on the remaining buffer time. If there is still buffer time remaining,
/// it checks if the audio should start playing and updates the playback delay timer. If the audio is currently playing,
/// it decrements the remaining buffer time. If the buffer is empty, it stops the audio playback and logs a message.
/// This method is used in VoipAudioSource which got drecated, which has been deprecated. See details [here](https://developers.meta.com/horizon/blog/deprecating-oculus-rooms-api-in-march-2023/).
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;
}
/// This method adds new audio data to the buffer. It takes an array of float samples as input and writes them to the internal audio buffer.
/// If there is not enough space in the buffer, it will wrap around to the beginning of the buffer. If the write position exceeds the buffer length,
/// an exception is thrown. The method returns the number of samples written to the buffer.
/// This method is used in VoipAudioSource which got drecated, which has been deprecated. See details [here](https://developers.meta.com/horizon/blog/deprecating-oculus-rooms-api-in-march-2023/).
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);
}
}