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