Assignment for RMIT Mixed Reality in 2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
5.0 KiB

  1. /************************************************************************************
  2. Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
  3. Licensed under the Oculus Utilities SDK License Version 1.31 (the "License"); you may not use
  4. the Utilities SDK except in compliance with the License, which is provided at the time of installation
  5. or download, or which otherwise accompanies this software in either electronic or hard copy form.
  6. You may obtain a copy of the License at
  7. https://developer.oculus.com/licenses/utilities-1.31
  8. Unless required by applicable law or agreed to in writing, the Utilities SDK distributed
  9. under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
  10. ANY KIND, either express or implied. See the License for the specific language governing
  11. permissions and limitations under the License.
  12. ************************************************************************************/
  13. using UnityEngine;
  14. using System.Collections;
  15. /// <summary>
  16. /// A PCM buffer of data for a haptics effect.
  17. /// </summary>
  18. public class OVRHapticsClip
  19. {
  20. /// <summary>
  21. /// The current number of samples in the clip.
  22. /// </summary>
  23. public int Count { get; private set; }
  24. /// <summary>
  25. /// The maximum number of samples the clip can store.
  26. /// </summary>
  27. public int Capacity { get; private set; }
  28. /// <summary>
  29. /// The raw haptics data.
  30. /// </summary>
  31. public byte[] Samples { get; private set; }
  32. public OVRHapticsClip()
  33. {
  34. Capacity = OVRHaptics.Config.MaximumBufferSamplesCount;
  35. Samples = new byte[Capacity * OVRHaptics.Config.SampleSizeInBytes];
  36. }
  37. /// <summary>
  38. /// Creates a clip with the specified capacity.
  39. /// </summary>
  40. public OVRHapticsClip(int capacity)
  41. {
  42. Capacity = (capacity >= 0) ? capacity : 0;
  43. Samples = new byte[Capacity * OVRHaptics.Config.SampleSizeInBytes];
  44. }
  45. /// <summary>
  46. /// Creates a clip with the specified data.
  47. /// </summary>
  48. public OVRHapticsClip(byte[] samples, int samplesCount)
  49. {
  50. Samples = samples;
  51. Capacity = Samples.Length / OVRHaptics.Config.SampleSizeInBytes;
  52. Count = (samplesCount >= 0) ? samplesCount : 0;
  53. }
  54. /// <summary>
  55. /// Creates a clip by mixing the specified clips.
  56. /// </summary>
  57. public OVRHapticsClip(OVRHapticsClip a, OVRHapticsClip b)
  58. {
  59. int maxCount = a.Count;
  60. if (b.Count > maxCount)
  61. maxCount = b.Count;
  62. Capacity = maxCount;
  63. Samples = new byte[Capacity * OVRHaptics.Config.SampleSizeInBytes];
  64. for (int i = 0; i < a.Count || i < b.Count; i++)
  65. {
  66. if (OVRHaptics.Config.SampleSizeInBytes == 1)
  67. {
  68. byte sample = 0; // TODO support multi-byte samples
  69. if ((i < a.Count) && (i < b.Count))
  70. sample = (byte)(Mathf.Clamp(a.Samples[i] + b.Samples[i], 0, System.Byte.MaxValue)); // TODO support multi-byte samples
  71. else if (i < a.Count)
  72. sample = a.Samples[i]; // TODO support multi-byte samples
  73. else if (i < b.Count)
  74. sample = b.Samples[i]; // TODO support multi-byte samples
  75. WriteSample(sample); // TODO support multi-byte samples
  76. }
  77. }
  78. }
  79. /// <summary>
  80. /// Creates a haptics clip from the specified audio clip.
  81. /// </summary>
  82. public OVRHapticsClip(AudioClip audioClip, int channel = 0)
  83. {
  84. float[] audioData = new float[audioClip.samples * audioClip.channels];
  85. audioClip.GetData(audioData, 0);
  86. InitializeFromAudioFloatTrack(audioData, audioClip.frequency, audioClip.channels, channel);
  87. }
  88. /// <summary>
  89. /// Adds the specified sample to the end of the clip.
  90. /// </summary>
  91. public void WriteSample(byte sample) // TODO support multi-byte samples
  92. {
  93. if (Count >= Capacity)
  94. {
  95. //Debug.LogError("Attempted to write OVRHapticsClip sample out of range - Count:" + Count + " Capacity:" + Capacity);
  96. return;
  97. }
  98. if (OVRHaptics.Config.SampleSizeInBytes == 1)
  99. {
  100. Samples[Count * OVRHaptics.Config.SampleSizeInBytes] = sample; // TODO support multi-byte samples
  101. }
  102. Count++;
  103. }
  104. /// <summary>
  105. /// Clears the clip and resets its size to 0.
  106. /// </summary>
  107. public void Reset()
  108. {
  109. Count = 0;
  110. }
  111. private void InitializeFromAudioFloatTrack(float[] sourceData, double sourceFrequency, int sourceChannelCount, int sourceChannel)
  112. {
  113. double stepSizePrecise = (sourceFrequency + 1e-6) / OVRHaptics.Config.SampleRateHz;
  114. if (stepSizePrecise < 1.0)
  115. return;
  116. int stepSize = (int)stepSizePrecise;
  117. double stepSizeError = stepSizePrecise - stepSize;
  118. double accumulatedStepSizeError = 0.0f;
  119. int length = sourceData.Length;
  120. Count = 0;
  121. Capacity = length / sourceChannelCount / stepSize + 1;
  122. Samples = new byte[Capacity * OVRHaptics.Config.SampleSizeInBytes];
  123. int i = sourceChannel % sourceChannelCount;
  124. while (i < length)
  125. {
  126. if (OVRHaptics.Config.SampleSizeInBytes == 1)
  127. {
  128. WriteSample((byte)(Mathf.Clamp01(Mathf.Abs(sourceData[i])) * System.Byte.MaxValue)); // TODO support multi-byte samples
  129. }
  130. i+= stepSize * sourceChannelCount;
  131. accumulatedStepSizeError += stepSizeError;
  132. if ((int)accumulatedStepSizeError > 0)
  133. {
  134. i+= (int)accumulatedStepSizeError * sourceChannelCount;
  135. accumulatedStepSizeError = accumulatedStepSizeError - (int)accumulatedStepSizeError;
  136. }
  137. }
  138. }
  139. }