// --------------------------------------------------------------------------------------------------------------------
//
// Copyright (c) VRMADA, All rights reserved.
//
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using UltimateXR.Exceptions;
using UltimateXR.Extensions.System;
using UltimateXR.Extensions.System.IO;
using UltimateXR.Extensions.Unity.IO;
using UnityEngine;
namespace UltimateXR.Extensions.Unity.Audio
{
///
/// Audio extensions.
///
public static partial class AudioClipExt
{
#region Public Methods
///
/// Ubiquitously plays an .
///
///
/// This function creates an but automatically disposes of it once the clip has finished
/// playing.
///
/// Reference to the sound clip file that will be played.
/// How loud the sound is at a distance of one world unit (one meter) [0.0, 1.0].
/// Delay time specified in seconds.
///
/// Amount of change in pitch due to slowdown/speed up of the Audio Clip. Value 1 is normal playback speed.
///
/// Start offset in seconds
/// The just created temporal .
///
public static AudioSource PlayClip(AudioClip self,
float volume = 1.0f,
float delay = 0.0f,
float pitch = 1.0f,
float offsetSeconds = 0.0f)
{
return AudioSourceExt.PlayClip(self, volume, delay, pitch, offsetSeconds);
}
///
/// Plays an AudioClip at a given position in world space.
///
///
/// This function creates an but automatically disposes of it once the clip has finished
/// playing.
///
/// Reference to the sound clip file that will be played.
/// Position in world space from which sound originates.
/// How loud the sound is at a distance of one world unit (one meter) [0.0, 1.0].
/// Delay time specified in seconds.
///
/// Amount of change in pitch due to slowdown/speed up of the Audio Clip. Value 1 is normal playback
/// speed.
///
/// Sets how much the 3D engine has an effect on the audio source [0.0, 1.0].
/// Start offset in seconds
/// The just created temporal .
///
public static AudioSource PlayClipAtPoint(AudioClip self,
Vector3 point,
float volume = 1.0f,
float delay = 0.0f,
float pitch = 1.0f,
float spatialBlend = AudioSourceExt.SpatialBlend3D,
float offsetSeconds = 0.0f)
{
return AudioSourceExt.PlayClipAtPoint(self, point, volume, delay, pitch, spatialBlend, offsetSeconds);
}
///
/// Asynchronous and ubiquitously plays the .
///
///
/// This function creates an but automatically disposes of it once the clip has finished
/// playing.
///
/// Reference to the sound clip file that will be played.
/// How loud the sound is at a distance of one world unit (one meter) [0.0, 1.0].
/// Delay time specified in seconds.
///
/// Amount of change in pitch due to slowdown/speed up of the Audio Clip. Value 1 is normal playback
/// speed.
///
/// Start offset in seconds
/// to stop playing.
/// An awaitable .
///
public static Task PlayAsync(this AudioClip self,
float volume = 1.0f,
float delay = 0.0f,
float pitch = 1.0f,
float offsetSeconds = 0.0f,
CancellationToken ct = default)
{
return AudioSourceExt.PlayClipAsync(self, volume, delay, pitch, offsetSeconds, ct);
}
///
/// Asynchronously plays the at a given position in world space.
///
///
/// This function creates an but automatically disposes of it once the clip has finished
/// playing.
///
/// Reference to the sound clip file that will be played.
/// Position in world space from which sound originates.
/// How loud the sound is at a distance of one world unit (one meter) [0.0, 1.0].
/// Delay time specified in seconds.
///
/// Amount of change in pitch due to slowdown/speed up of the Audio Clip. Value 1 is normal playback
/// speed.
///
/// Sets how much the 3D engine has an effect on the audio source [0.0, 1.0].
/// Start offset in seconds
/// to stop playing.
/// An awaitable .
///
public static Task PlayAtPointAsync(this AudioClip self,
Vector3 point,
float volume = 1.0f,
float delay = 0.0f,
float pitch = 1.0f,
float spatialBlend = AudioSourceExt.SpatialBlend3D,
float offsetSeconds = 0.0f,
CancellationToken ct = default)
{
return AudioSourceExt.PlayClipAtPointAsync(self, point, volume, delay, pitch, spatialBlend, offsetSeconds, ct);
}
///
/// Creates an from a PCM stream.
///
/// The source stream
/// The name assigned to the clip
/// The object
public static AudioClip FromPcmStream(Stream sourceStream, string clipName = "pcm")
{
clipName.ThrowIfNullOrWhitespace(nameof(clipName));
byte[] bytes = new byte[sourceStream.Length];
sourceStream.Read(bytes, 0, bytes.Length);
return FromPcmBytes(bytes, clipName);
}
///
/// Creates an from a PCM stream asynchronously.
///
/// The source stream
/// The name assigned to the clip
/// The optional cancellation token, to cancel the task
/// An awaitable task that returns the object
public static async Task FromPcmStreamAsync(Stream sourceStream, string clipName = "pcm", CancellationToken ct = default)
{
clipName.ThrowIfNullOrWhitespace(nameof(clipName));
byte[] bytes = new byte[sourceStream.Length];
await sourceStream.ReadAsync(bytes, 0, bytes.Length, ct);
return await FromPcmBytesAsync(bytes, clipName, ct);
}
///
/// Creates an from a PCM byte array.
///
/// The source data
/// The name assigned to the clip
/// The object
public static AudioClip FromPcmBytes(byte[] bytes, string clipName = "pcm")
{
clipName.ThrowIfNullOrWhitespace(nameof(clipName));
var pcmData = PcmData.FromBytes(bytes);
var audioClip = AudioClip.Create(clipName, pcmData.Length, pcmData.Channels, pcmData.SampleRate, false);
audioClip.SetData(pcmData.Value, 0);
return audioClip;
}
///
/// Creates an from a PCM byte array asynchronously.
///
/// The source data
/// The name assigned to the clip
/// The optional cancellation token, to cancel the task
/// An awaitable task that returns the object
public static async Task FromPcmBytesAsync(byte[] bytes, string clipName = "pcm", CancellationToken ct = default)
{
clipName.ThrowIfNullOrWhitespace(nameof(clipName));
var pcmData = await Task.Run(() => PcmData.FromBytes(bytes), ct);
var audioClip = AudioClip.Create(clipName, pcmData.Length, pcmData.Channels, pcmData.SampleRate, false);
audioClip.SetData(pcmData.Value, 0);
return audioClip;
}
///
/// Asynchronously reads and loads an into memory from a given
///
/// Full path for file
/// The optional cancellation token, to cancel the task
/// Loaded
///
/// HttpError flag is on
///
///
/// NetworkError flag is on
///
///
/// The task was canceled using
///
public static Task FromFile(string uri, CancellationToken ct = default)
{
ct.ThrowIfCancellationRequested();
uri.ThrowIfNullOrWhitespace(nameof(uri));
try
{
return UnityWebRequestExt.LoadAudioClipAsync(uri, ct);
}
catch (UwrException e)
{
throw new FileNotFoundException(e.Message, uri, e);
}
}
///
/// Asynchronously reads and loads an into memory from a given
/// pointing to a file with PCM bytes.
///
/// Full path with the PCM bytes
/// Optional cancellation token to cancel the task
/// Loaded
///
/// HttpError flag is on
///
///
/// NetworkError flag is on
///
///
/// The task was canceled using
///
public static async Task FromPcmFile(string uri, CancellationToken ct = default)
{
string fileName = Path.GetFileNameWithoutExtension(uri);
byte[] bytes = await FileExt.Read(uri, ct);
return await FromPcmBytesAsync(bytes, fileName, ct);
}
///
/// Creates a object from a stream containing PCM data.
///
/// PCM data
/// The name that will be assigned to the clip
/// object
public static StreamedPcmClip CreatePcmStreamed(Stream pcmStream, string clipName = "pcm")
{
return StreamedPcmClip.Create(pcmStream, clipName);
}
#endregion
}
}