OVRHapticsClip.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. using UnityEngine;
  2. using System.Collections;
  3. /// <summary>
  4. /// A PCM buffer of data for a haptics effect.
  5. /// </summary>
  6. public class OVRHapticsClip
  7. {
  8. /// <summary>
  9. /// The current number of samples in the clip.
  10. /// </summary>
  11. public int Count { get; private set; }
  12. /// <summary>
  13. /// The maximum number of samples the clip can store.
  14. /// </summary>
  15. public int Capacity { get; private set; }
  16. /// <summary>
  17. /// The raw haptics data.
  18. /// </summary>
  19. public byte[] Samples { get; private set; }
  20. public OVRHapticsClip()
  21. {
  22. Capacity = OVRHaptics.Config.MaximumBufferSamplesCount;
  23. Samples = new byte[Capacity * OVRHaptics.Config.SampleSizeInBytes];
  24. }
  25. /// <summary>
  26. /// Creates a clip with the specified capacity.
  27. /// </summary>
  28. public OVRHapticsClip(int capacity)
  29. {
  30. Capacity = (capacity >= 0) ? capacity : 0;
  31. Samples = new byte[Capacity * OVRHaptics.Config.SampleSizeInBytes];
  32. }
  33. /// <summary>
  34. /// Creates a clip with the specified data.
  35. /// </summary>
  36. public OVRHapticsClip(byte[] samples, int samplesCount)
  37. {
  38. Samples = samples;
  39. Capacity = Samples.Length / OVRHaptics.Config.SampleSizeInBytes;
  40. Count = (samplesCount >= 0) ? samplesCount : 0;
  41. }
  42. /// <summary>
  43. /// Creates a clip by mixing the specified clips.
  44. /// </summary>
  45. public OVRHapticsClip(OVRHapticsClip a, OVRHapticsClip b)
  46. {
  47. int maxCount = a.Count;
  48. if (b.Count > maxCount)
  49. maxCount = b.Count;
  50. Capacity = maxCount;
  51. Samples = new byte[Capacity * OVRHaptics.Config.SampleSizeInBytes];
  52. for (int i = 0; i < a.Count || i < b.Count; i++)
  53. {
  54. if (OVRHaptics.Config.SampleSizeInBytes == 1)
  55. {
  56. byte sample = 0; // TODO support multi-byte samples
  57. if ((i < a.Count) && (i < b.Count))
  58. sample = (byte)(Mathf.Clamp(a.Samples[i] + b.Samples[i], 0, System.Byte.MaxValue)); // TODO support multi-byte samples
  59. else if (i < a.Count)
  60. sample = a.Samples[i]; // TODO support multi-byte samples
  61. else if (i < b.Count)
  62. sample = b.Samples[i]; // TODO support multi-byte samples
  63. WriteSample(sample); // TODO support multi-byte samples
  64. }
  65. }
  66. }
  67. /// <summary>
  68. /// Creates a haptics clip from the specified audio clip.
  69. /// </summary>
  70. public OVRHapticsClip(AudioClip audioClip, int channel = 0)
  71. {
  72. float[] audioData = new float[audioClip.samples * audioClip.channels];
  73. audioClip.GetData(audioData, 0);
  74. InitializeFromAudioFloatTrack(audioData, audioClip.frequency, audioClip.channels, channel);
  75. }
  76. /// <summary>
  77. /// Adds the specified sample to the end of the clip.
  78. /// </summary>
  79. public void WriteSample(byte sample) // TODO support multi-byte samples
  80. {
  81. if (Count >= Capacity)
  82. {
  83. //Debug.LogError("Attempted to write OVRHapticsClip sample out of range - Count:" + Count + " Capacity:" + Capacity);
  84. return;
  85. }
  86. if (OVRHaptics.Config.SampleSizeInBytes == 1)
  87. {
  88. Samples[Count * OVRHaptics.Config.SampleSizeInBytes] = sample; // TODO support multi-byte samples
  89. }
  90. Count++;
  91. }
  92. /// <summary>
  93. /// Clears the clip and resets its size to 0.
  94. /// </summary>
  95. public void Reset()
  96. {
  97. Count = 0;
  98. }
  99. private void InitializeFromAudioFloatTrack(float[] sourceData, double sourceFrequency, int sourceChannelCount, int sourceChannel)
  100. {
  101. double stepSizePrecise = (sourceFrequency + 1e-6) / OVRHaptics.Config.SampleRateHz;
  102. if (stepSizePrecise < 1.0)
  103. return;
  104. int stepSize = (int)stepSizePrecise;
  105. double stepSizeError = stepSizePrecise - stepSize;
  106. double accumulatedStepSizeError = 0.0f;
  107. int length = sourceData.Length;
  108. Count = 0;
  109. Capacity = length / sourceChannelCount / stepSize + 1;
  110. Samples = new byte[Capacity * OVRHaptics.Config.SampleSizeInBytes];
  111. int i = sourceChannel % sourceChannelCount;
  112. while (i < length)
  113. {
  114. if (OVRHaptics.Config.SampleSizeInBytes == 1)
  115. {
  116. WriteSample((byte)(Mathf.Clamp01(Mathf.Abs(sourceData[i])) * System.Byte.MaxValue)); // TODO support multi-byte samples
  117. }
  118. i+= stepSize * sourceChannelCount;
  119. accumulatedStepSizeError += stepSizeError;
  120. if ((int)accumulatedStepSizeError > 0)
  121. {
  122. i+= (int)accumulatedStepSizeError * sourceChannelCount;
  123. accumulatedStepSizeError = accumulatedStepSizeError - (int)accumulatedStepSizeError;
  124. }
  125. }
  126. }
  127. }