/* * VideoKit * Copyright © 2025 Yusuf Olokoba. All Rights Reserved. */ #nullable enable namespace VideoKit.Sources { using System; using UnityEngine; using Clocks; /// /// Media source for generating audio buffers from an `AudioSource` or `AudioListener` component. /// public sealed class AudioComponentSource : IDisposable { #region --Client API-- /// /// Create an audio buffer source from an AudioListener. /// /// Audio listener for the current scene. /// Handler to receive audio buffers. /// Clock for generating timestamps. public AudioComponentSource ( AudioListener listener, Action handler, IClock? clock = null ) : this(listener.gameObject, handler, clock) { } /// /// Create an audio buffer source from an AudioSource. /// /// Audio source to record. /// Handler to receive audio buffers. /// Clock for generating timestamps. public AudioComponentSource ( AudioSource source, Action handler, IClock? clock = null ) : this(source.gameObject, handler, clock) { } /// /// Close the media source and release resources. /// public void Dispose () => AudioSourceAttachment.DestroyImmediate(attachment); #endregion #region --Operations-- private readonly AudioSourceAttachment attachment; private AudioComponentSource (GameObject gameObject, Action handler, IClock? clock) { var sampleRate = AudioSettings.outputSampleRate; attachment = gameObject.AddComponent(); attachment.sampleBufferDelegate = (data, channels) => { using var audioBuffer = new AudioBuffer( sampleRate, channels, data, clock?.timestamp ?? 0L ); handler(audioBuffer); }; } private sealed class AudioSourceAttachment : MonoBehaviour { public Action? sampleBufferDelegate; private void OnAudioFilterRead (float[] data, int channels) { sampleBufferDelegate?.Invoke(data, channels); } } #endregion } }