diff --git a/Utilities.Audio/Packages/com.utilities.audio/Runtime/IEncoder.cs b/Utilities.Audio/Packages/com.utilities.audio/Runtime/IEncoder.cs index bea62c6..fdda345 100644 --- a/Utilities.Audio/Packages/com.utilities.audio/Runtime/IEncoder.cs +++ b/Utilities.Audio/Packages/com.utilities.audio/Runtime/IEncoder.cs @@ -17,7 +17,7 @@ public interface IEncoder /// The event raised when buffer data is ready to write. /// . /// Used to determine where this method was called from. - Task StreamRecordingAsync(ClipData microphoneClipData, Action> bufferCallback, CancellationToken cancellationToken, [CallerMemberName] string callingMethodName = null); + Task StreamRecordingAsync(ClipData microphoneClipData, Func, Task> bufferCallback, CancellationToken cancellationToken, [CallerMemberName] string callingMethodName = null); /// /// Streams audio microphone recording input to disk. diff --git a/Utilities.Audio/Packages/com.utilities.audio/Runtime/PCMEncoder.cs b/Utilities.Audio/Packages/com.utilities.audio/Runtime/PCMEncoder.cs index 61ca346..c04d90d 100644 --- a/Utilities.Audio/Packages/com.utilities.audio/Runtime/PCMEncoder.cs +++ b/Utilities.Audio/Packages/com.utilities.audio/Runtime/PCMEncoder.cs @@ -216,7 +216,7 @@ public static float[] Resample(float[] samples, int inputSamplingRate, int outpu /// [Preserve] - public async Task StreamRecordingAsync(ClipData clipData, Action> bufferCallback, CancellationToken cancellationToken, string callingMethodName = null) + public async Task StreamRecordingAsync(ClipData clipData, Func, Task> bufferCallback, CancellationToken cancellationToken, string callingMethodName = null) { if (callingMethodName != nameof(RecordingManager.StartRecordingStreamAsync)) { @@ -291,7 +291,11 @@ public async Task> StreamSaveToDiskAsync(ClipData clipD { try { - (finalSamples, totalSampleCount) = await InternalStreamRecordAsync(clipData, finalSamples, buffer => writer.Write(buffer.Span), cancellationToken); + (finalSamples, totalSampleCount) = await InternalStreamRecordAsync(clipData, finalSamples, async buffer => + { + writer.Write(buffer.Span); + await Task.Yield(); + }, cancellationToken).ConfigureAwait(true); } finally { @@ -352,7 +356,7 @@ public async Task> StreamSaveToDiskAsync(ClipData clipD return result; } - private static async Task<(float[], int)> InternalStreamRecordAsync(ClipData clipData, float[] finalSamples, Action> bufferCallback, CancellationToken cancellationToken) + private static async Task<(float[], int)> InternalStreamRecordAsync(ClipData clipData, float[] finalSamples, Func, Task> bufferCallback, CancellationToken cancellationToken) { try { @@ -400,11 +404,21 @@ public async Task> StreamSaveToDiskAsync(ClipData clipD var bufferIndex = (lastMicrophonePosition + i) % clipData.BufferSize; // Wrap around index. var value = sampleBuffer[bufferIndex]; var sample = (short)(Math.Max(-1f, Math.Min(1f, value)) * short.MaxValue); - bufferCallback.Invoke(new ReadOnlyMemory(new[] + var sampleData = new ReadOnlyMemory(new[] { (byte)(sample & byte.MaxValue), (byte)(sample >> 8 & byte.MaxValue) - })); + }); + + try + { + await bufferCallback.Invoke(sampleData).ConfigureAwait(false); + } + catch (Exception e) + { + Debug.LogException(new Exception($"[{nameof(PCMEncoder)}] error occurred when buffering audio", e)); + } + if (finalSamples is { Length: > 0 }) { finalSamples[sampleCount * clipData.Channels + i] = sampleBuffer[bufferIndex]; diff --git a/Utilities.Audio/Packages/com.utilities.audio/Runtime/RecordingManager.cs b/Utilities.Audio/Packages/com.utilities.audio/Runtime/RecordingManager.cs index 0a0507a..07209ff 100644 --- a/Utilities.Audio/Packages/com.utilities.audio/Runtime/RecordingManager.cs +++ b/Utilities.Audio/Packages/com.utilities.audio/Runtime/RecordingManager.cs @@ -298,7 +298,7 @@ public static async Task> StartRecordingAsync /// /// The buffer callback with new sample data. /// Optional, task cancellation token. - public static async void StartRecordingStream(Action> bufferCallback, CancellationToken cancellationToken = default) where TEncoder : IEncoder + public static async void StartRecordingStream(Func, Task> bufferCallback, CancellationToken cancellationToken = default) where TEncoder : IEncoder => await StartRecordingStreamAsync(bufferCallback, cancellationToken).ConfigureAwait(true); /// @@ -306,7 +306,7 @@ public static async void StartRecordingStream(Action /// The buffer callback with new sample data. /// Optional, task cancellation token. - public static async Task StartRecordingStreamAsync(Action> bufferCallback, CancellationToken cancellationToken = default) where TEncoder : IEncoder + public static async Task StartRecordingStreamAsync(Func, Task> bufferCallback, CancellationToken cancellationToken = default) where TEncoder : IEncoder { if (IsBusy) { diff --git a/Utilities.Audio/Packages/com.utilities.audio/package.json b/Utilities.Audio/Packages/com.utilities.audio/package.json index 5a43bd1..f4b538d 100644 --- a/Utilities.Audio/Packages/com.utilities.audio/package.json +++ b/Utilities.Audio/Packages/com.utilities.audio/package.json @@ -3,7 +3,7 @@ "displayName": "Utilities.Audio", "description": "A simple package for audio extensions and utilities.", "keywords": [], - "version": "2.0.0", + "version": "2.0.1", "unity": "2021.3", "documentationUrl": "https://github.com/RageAgainstThePixel/com.utilities.audio#documentation", "changelogUrl": "https://github.com/RageAgainstThePixel/com.utilities.audio/releases",