CaptureAudioFromAudioClip.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. //-----------------------------------------------------------------------------
  5. // Copyright 2012-2022 RenderHeads Ltd. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. namespace RenderHeads.Media.AVProMovieCapture
  8. {
  9. /// <summary>
  10. /// Encodes audio directly from an AudioClip
  11. /// Requires AudioCaptureSource.Manual to be set on the Capture component
  12. /// Make sure the AudioClip sample rate and channel count matches that of the Capture component
  13. /// Designed to work in offline capture mode
  14. /// </summary>
  15. [AddComponentMenu("AVPro Movie Capture/Audio/Capture Audio (From AudioClip)", 500)]
  16. public class CaptureAudioFromAudioClip : MonoBehaviour
  17. {
  18. [SerializeField] CaptureBase _capture = null;
  19. [SerializeField] AudioClip _audioClip = null;
  20. //[SerializeField] bool _loopAudio = false;
  21. private int _videoOffsetInSamples = 0;
  22. private int _committedFrames = 0;
  23. private int _committedSamples = 0;
  24. private int _lastCommittedSample = -1;
  25. private float[] _frameBuffer = null;
  26. void OnEnable()
  27. {
  28. _lastCommittedSample = -1;
  29. if (_audioClip && _capture)
  30. {
  31. if (_audioClip.frequency != _capture.ManualAudioSampleRate)
  32. {
  33. Debug.LogError(string.Format("[AVProMovieCapture] AudioClip audio frequency {0} doesn't match the encoding frequency {1}", _audioClip.frequency, _capture.ManualAudioSampleRate));
  34. }
  35. if (_audioClip.channels != _capture.ManualAudioChannelCount)
  36. {
  37. Debug.LogError(string.Format("[AVProMovieCapture] AudioClip audio channelCount {0} doesn't match the encoding channelCount {1}", _audioClip.channels, _capture.ManualAudioChannelCount));
  38. }
  39. }
  40. }
  41. void Update()
  42. {
  43. if (_capture != null && _capture.IsCapturing())
  44. {
  45. float[] samples = GetAudioSamplesForFrame();
  46. if (samples != null)
  47. {
  48. _capture.EncodeAudio(samples);
  49. }
  50. _committedFrames++;
  51. }
  52. }
  53. private float[] GetAudioSamplesForFrame()
  54. {
  55. float[] result = null;
  56. if (_audioClip != null && _audioClip.samples > 0)
  57. {
  58. int sampleCommitSize = (int)(_capture.ManualAudioSampleRate / _capture.FrameRate);
  59. float videoRenderTime = (float)_committedFrames / _capture.FrameRate;
  60. float videoTimeInSamples = videoRenderTime * (float)_audioClip.frequency;
  61. if (_lastCommittedSample < videoTimeInSamples && videoTimeInSamples >= 0)
  62. {
  63. int startSampleIndex = (_lastCommittedSample + 1) - _videoOffsetInSamples;
  64. int endSampleIndex = startSampleIndex + sampleCommitSize - 1;
  65. int requiredSamples = (_audioClip.channels * sampleCommitSize);
  66. if (_lastCommittedSample < _audioClip.samples - 1)
  67. {
  68. if (endSampleIndex >= _audioClip.samples)
  69. {
  70. // We've reached the end of the clip samples, so just grab what remains
  71. requiredSamples = (_audioClip.channels * (_audioClip.samples - startSampleIndex));
  72. }
  73. // Allocate buffer if needed
  74. if (_frameBuffer == null || _frameBuffer.Length != requiredSamples)
  75. {
  76. _frameBuffer = new float[requiredSamples];
  77. }
  78. _audioClip.GetData(_frameBuffer, startSampleIndex);
  79. _committedSamples++;
  80. _lastCommittedSample = (_committedSamples * sampleCommitSize) - 1;
  81. }
  82. else
  83. {
  84. // We've reached the end of the audio clip, so just create empty audio data
  85. requiredSamples = (_audioClip.channels * sampleCommitSize);
  86. // Allocate buffer if needed
  87. if (_frameBuffer == null || _frameBuffer.Length != requiredSamples)
  88. {
  89. _frameBuffer = new float[requiredSamples];
  90. }
  91. }
  92. result = _frameBuffer;
  93. }
  94. }
  95. return result;
  96. }
  97. }
  98. }