AudioRecordTool.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /****************************************************************************
  2. * Copyright 2019 Nreal Techonology Limited. All rights reserved.
  3. *
  4. * This file is part of NRSDK.
  5. *
  6. * https://www.nreal.ai/
  7. *
  8. *****************************************************************************/
  9. namespace NRKernal.Record
  10. {
  11. using System;
  12. using UnityEngine;
  13. using UnityEngine.Assertions;
  14. public class AudioRecordTool : MonoBehaviour
  15. {
  16. private byte[] m_CacheBuffer;
  17. private const int MaxBufferSize = 2048 * 20;
  18. private int m_ReadIndex, m_WriteIndex;
  19. public int RIndex { get { return m_ReadIndex; } }
  20. public int WIndex { get { return m_WriteIndex; } }
  21. private bool m_RecOutput = false;
  22. public bool IsRecording { get { return m_RecOutput; } }
  23. private int m_OutputSampleRate;
  24. public int SampleRate { get { return m_OutputSampleRate; } }
  25. void Awake()
  26. {
  27. m_ReadIndex = 0;
  28. m_WriteIndex = 0;
  29. m_OutputSampleRate = AudioSettings.GetConfiguration().sampleRate;
  30. //AudioSettings.GetDSPBufferSize(out bufferSize, out numBuffers);
  31. }
  32. protected void InitBuffer(int len)
  33. {
  34. m_CacheBuffer = new byte[len <= MaxBufferSize ? len : MaxBufferSize];
  35. }
  36. public void StartRecord()
  37. {
  38. m_RecOutput = true;
  39. }
  40. public void StopRecord()
  41. {
  42. m_RecOutput = false;
  43. }
  44. private void OnAudioFilterRead(float[] data, int channels)
  45. {
  46. if (m_RecOutput)
  47. {
  48. if (m_CacheBuffer == null)
  49. {
  50. InitBuffer(data.Length * 10);
  51. }
  52. ConvertToSinChaAndWrite(data, channels); //audio data is interlaced
  53. }
  54. }
  55. /// <summary>
  56. /// Only take the data of the first channel.
  57. /// </summary>
  58. /// <param name="dataSource"></param>
  59. /// <param name="channels"></param>
  60. private void ConvertToSinChaAndWrite(float[] dataSource, int channels)
  61. {
  62. var intData = new Int16[dataSource.Length / channels];
  63. //converting in 2 steps : float[] to Int16[], //then Int16[] to Byte[]
  64. var bytesData = new Byte[intData.Length * 2];
  65. //bytesData array is twice the size of
  66. //dataSource array because a float converted in Int16 is 2 bytes.
  67. var rescaleFactor = Int16.MaxValue; //to convert float to Int16
  68. var byteArr = new Byte[2];
  69. for (var i = 0; i < intData.Length; i++)
  70. {
  71. intData[i] = (Int16)(dataSource[i * 2] * rescaleFactor);
  72. byteArr = BitConverter.GetBytes(intData[i]);
  73. byteArr.CopyTo(bytesData, i * 2);
  74. }
  75. Write(bytesData);
  76. }
  77. /// <summary>
  78. /// Take all data of the channel.
  79. /// </summary>
  80. /// <param name="dataSource"></param>
  81. private void ConvertAndWrite(float[] dataSource)
  82. {
  83. var intData = new Int16[dataSource.Length];
  84. //converting in 2 steps : float[] to Int16[], //then Int16[] to Byte[]
  85. var bytesData = new Byte[dataSource.Length * 2];
  86. //bytesData array is twice the size of
  87. //dataSource array because a float converted in Int16 is 2 bytes.
  88. var rescaleFactor = 32767; //to convert float to Int16
  89. for (var i = 0; i < dataSource.Length; i++)
  90. {
  91. intData[i] = (Int16)(dataSource[i] * rescaleFactor);
  92. var byteArr = new Byte[2];
  93. byteArr = BitConverter.GetBytes(intData[i]);
  94. byteArr.CopyTo(bytesData, i * 2);
  95. }
  96. Write(bytesData);
  97. }
  98. protected void Write(byte[] bytesData)
  99. {
  100. lock (m_CacheBuffer)
  101. {
  102. if (m_WriteIndex + bytesData.Length <= m_CacheBuffer.Length)
  103. {
  104. Array.Copy(bytesData, 0, m_CacheBuffer, m_WriteIndex, bytesData.Length);
  105. m_WriteIndex += bytesData.Length;
  106. }
  107. else
  108. {
  109. int left = m_CacheBuffer.Length - m_WriteIndex;
  110. Assert.IsTrue(left >= 0);
  111. if (left > 0)
  112. {
  113. Array.Copy(bytesData, 0, m_CacheBuffer, m_WriteIndex, left);
  114. m_WriteIndex = 0;
  115. Array.Copy(bytesData, left, m_CacheBuffer, m_WriteIndex, bytesData.Length - left);
  116. m_WriteIndex += bytesData.Length - left;
  117. }
  118. else
  119. {
  120. m_WriteIndex = 0;
  121. Array.Copy(bytesData, 0, m_CacheBuffer, m_WriteIndex, bytesData.Length);
  122. m_WriteIndex += bytesData.Length;
  123. }
  124. }
  125. }
  126. }
  127. public bool Flush(ref byte[] outBytesData)
  128. {
  129. if (m_CacheBuffer == null || m_ReadIndex == m_WriteIndex)
  130. {
  131. return false;
  132. }
  133. lock (m_CacheBuffer)
  134. {
  135. int count = 0;
  136. if (m_ReadIndex < m_WriteIndex)
  137. {
  138. count = m_WriteIndex - m_ReadIndex;
  139. if (outBytesData == null || outBytesData.Length != count)
  140. {
  141. outBytesData = new byte[count];
  142. }
  143. Array.Copy(m_CacheBuffer, m_ReadIndex, outBytesData, 0, count);
  144. }
  145. else
  146. {
  147. int left = m_CacheBuffer.Length - m_ReadIndex;
  148. count = left + m_WriteIndex;
  149. Assert.IsTrue(left >= 0);
  150. if (outBytesData == null || outBytesData.Length != count)
  151. {
  152. outBytesData = new byte[count];
  153. }
  154. if (left == 0)
  155. {
  156. m_ReadIndex = 0;
  157. Assert.IsTrue(m_WriteIndex != 0);
  158. Array.Copy(m_CacheBuffer, m_ReadIndex, outBytesData, 0, count);
  159. }
  160. else
  161. {
  162. Array.Copy(m_CacheBuffer, m_ReadIndex, outBytesData, 0, m_CacheBuffer.Length - m_ReadIndex);
  163. Array.Copy(m_CacheBuffer, 0, outBytesData, m_CacheBuffer.Length - m_ReadIndex, m_WriteIndex);
  164. }
  165. }
  166. m_ReadIndex = m_WriteIndex;
  167. }
  168. return true;
  169. }
  170. }
  171. }