#if UNITY_2017_3_OR_NEWER #define AVPRO_MOVIECAPTURE_OFFLINE_AUDIOCAPTURE #endif #if UNITY_2019_3_OR_NEWER #define UNITY_NATIVEARRAY_GETSUBARRAY_SUPPORT #endif #if AVPRO_MOVIECAPTURE_OFFLINE_AUDIOCAPTURE using UnityEngine; #if UNITY_2018_1_OR_NEWER using Unity.Collections; #else using UnityEngine.Collections; #endif //----------------------------------------------------------------------------- // Copyright 2012-2022 RenderHeads Ltd. All rights reserved. //----------------------------------------------------------------------------- namespace RenderHeads.Media.AVProMovieCapture { /// /// Encodes audio directly from AudioRenderer (https://docs.unity3d.com/ScriptReference/AudioRenderer.html) /// While capturing, audio playback in Unity becomes muted /// [AddComponentMenu("AVPro Movie Capture/Audio/Capture Audio (From AudioRenderer)", 500)] public class CaptureAudioFromAudioRenderer : UnityAudioCapture { [SerializeField] CaptureBase _capture = null; private int _unityAudioChannelCount; private bool _isRendererRecording; public CaptureBase Capture { get { return _capture; } set { _capture = value; } } public override int SampleRate { get { return AudioSettings.outputSampleRate; } } public override int ChannelCount { get { return _unityAudioChannelCount; } } public override void PrepareCapture() { _unityAudioChannelCount = GetUnityAudioChannelCount(); } #if UNITY_NATIVEARRAY_GETSUBARRAY_SUPPORT private NativeArray _audioBuffer; #endif private NativeArray GetAudioBufferOfLength(int length) { #if UNITY_NATIVEARRAY_GETSUBARRAY_SUPPORT if (_audioBuffer.Length < length) { Debug.Log("Creating new audio buffer with length: " + length); if (_audioBuffer.IsCreated) _audioBuffer.Dispose(); _audioBuffer = new NativeArray(length, Allocator.Persistent); } return _audioBuffer.GetSubArray(0, length); #else return new NativeArray(length, Allocator.TempJob); #endif } private void DisposeAudioBuffer(NativeArray buffer) { #if !UNITY_NATIVEARRAY_GETSUBARRAY_SUPPORT buffer.Dispose(); #endif } public override void StartCapture() { if (_capture == null) { Debug.LogWarning("[AVProMovieCapture] CaptureAudioFromAudioRenderer has no Capture source set"); return; } if (!_isRendererRecording) { #if UNITY_NATIVEARRAY_GETSUBARRAY_SUPPORT // Allocate a big buffer for capturing the audio into _audioBuffer = new NativeArray(65536, Allocator.Persistent); #endif AudioRenderer.Start(); _isRendererRecording = true; } FlushBuffer(); } public override void StopCapture() { if (_isRendererRecording) { _isRendererRecording = false; AudioRenderer.Stop(); #if UNITY_NATIVEARRAY_GETSUBARRAY_SUPPORT _audioBuffer.Dispose(); #endif } } public override void FlushBuffer() { int sampleFrameCount = AudioRenderer.GetSampleCountForCaptureFrame(); int sampleCount = sampleFrameCount * _unityAudioChannelCount; NativeArray buffer = GetAudioBufferOfLength(sampleCount); AudioRenderer.Render(buffer); DisposeAudioBuffer(buffer); } void Update() { if (_isRendererRecording && _capture != null && _capture.IsCapturing() && !_capture.IsPaused()) { int sampleFrameCount = AudioRenderer.GetSampleCountForCaptureFrame(); int sampleCount = sampleFrameCount * _unityAudioChannelCount; NativeArray buffer = GetAudioBufferOfLength(sampleCount); if (AudioRenderer.Render(buffer)) { _capture.EncodeAudio(buffer); } DisposeAudioBuffer(buffer); } } } } #endif // AVPRO_MOVIECAPTURE_OFFLINE_AUDIOCAPTURE