-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #444 from fight4dream/feat/audioSourceHapticPulser
feat(Haptics): create haptic pattern based on AudioSource
- Loading branch information
Showing
5 changed files
with
179 additions
and
53 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
namespace Zinnia.Haptics | ||
{ | ||
using UnityEngine; | ||
using System.Collections; | ||
using Malimbe.PropertySerializationAttribute; | ||
using Malimbe.XmlDocumentationAttribute; | ||
|
||
/// <summary> | ||
/// Creates a haptic pattern based on the waveform of an <see cref="UnityEngine.AudioSource"/> and utilizes a <see cref="Haptics.HapticPulser"/> to create the effect. | ||
/// </summary> | ||
public class AudioSourceHapticPulser : RoutineHapticPulser | ||
{ | ||
/// <summary> | ||
/// The waveform to represent the haptic pattern. | ||
/// </summary> | ||
[Serialized] | ||
[field: DocumentedByXml] | ||
public AudioSource AudioSource { get; set; } | ||
|
||
/// <summary> | ||
/// <see cref="AudioSettings.dspTime"/> of the last <see cref="OnAudioFilterRead"/>. | ||
/// </summary> | ||
protected double filterReadDspTime; | ||
/// <summary> | ||
/// Audio data array of the last <see cref="OnAudioFilterRead"/>. | ||
/// </summary> | ||
protected float[] filterReadData; | ||
/// <summary> | ||
/// Number of channels of the last <see cref="OnAudioFilterRead"/>. | ||
/// </summary> | ||
protected int filterReadChannels; | ||
|
||
/// <inheritdoc /> | ||
public override bool IsActive() | ||
{ | ||
return base.IsActive() && AudioSource != null; | ||
} | ||
|
||
/// <summary> | ||
/// Enumerates through <see cref="AudioSource"/> and pulses for each amplitude of the wave. | ||
/// </summary> | ||
/// <returns>An Enumerator to manage the running of the Coroutine.</returns> | ||
protected override IEnumerator HapticProcessRoutine() | ||
{ | ||
int outputSampleRate = AudioSettings.outputSampleRate; | ||
while (AudioSource.isPlaying) | ||
{ | ||
int sampleIndex = (int)((AudioSettings.dspTime - filterReadDspTime) * outputSampleRate); | ||
float currentSample = 0; | ||
if (filterReadData != null && sampleIndex * filterReadChannels < filterReadData.Length) | ||
{ | ||
for (int i = 0; i < filterReadChannels; ++i) | ||
{ | ||
currentSample += filterReadData[sampleIndex + i]; | ||
} | ||
currentSample /= filterReadChannels; | ||
} | ||
HapticPulser.Intensity = currentSample * IntensityMultiplier; | ||
HapticPulser.Begin(); | ||
yield return null; | ||
} | ||
ResetIntensity(); | ||
} | ||
|
||
/// <summary> | ||
/// Store currently playing audio data and additional data. | ||
/// </summary> | ||
/// <param name="data">An array of floats comprising the audio data.</param> | ||
/// <param name="channels">An int that stores the number of channels of audio data passed to this delegate.</param> | ||
protected virtual void OnAudioFilterRead(float[] data, int channels) | ||
{ | ||
filterReadDspTime = AudioSettings.dspTime; | ||
filterReadData = data; | ||
filterReadChannels = channels; | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
namespace Zinnia.Haptics | ||
{ | ||
using UnityEngine; | ||
using System.Collections; | ||
using Malimbe.PropertySerializationAttribute; | ||
using Malimbe.XmlDocumentationAttribute; | ||
|
||
/// <summary> | ||
/// Creates a haptic pattern based on a custom routine and utilizes a <see cref="Haptics.HapticPulser"/> to create the effect. | ||
/// </summary> | ||
public abstract class RoutineHapticPulser : HapticProcess | ||
{ | ||
/// <summary> | ||
/// The pulse process to utilize. | ||
/// </summary> | ||
[Serialized] | ||
[field: DocumentedByXml] | ||
public HapticPulser HapticPulser { get; set; } | ||
/// <summary> | ||
/// Multiplies the current audio peak to affect the wave intensity. | ||
/// </summary> | ||
[Serialized] | ||
[field: DocumentedByXml] | ||
public float IntensityMultiplier { get; set; } = 1f; | ||
|
||
/// <summary> | ||
/// A reference to the started routine. | ||
/// </summary> | ||
protected Coroutine hapticRoutine; | ||
/// <summary> | ||
/// The original intensity of <see cref="HapticPulser"/> to reset back to after the process is complete. | ||
/// </summary> | ||
protected float cachedIntensity; | ||
|
||
/// <inheritdoc /> | ||
public override bool IsActive() | ||
{ | ||
return base.IsActive() && HapticPulser != null && HapticPulser.IsActive(); | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override void DoBegin() | ||
{ | ||
cachedIntensity = HapticPulser.Intensity; | ||
hapticRoutine = StartCoroutine(HapticProcessRoutine()); | ||
} | ||
|
||
/// <inheritdoc /> | ||
protected override void DoCancel() | ||
{ | ||
if (hapticRoutine == null) | ||
{ | ||
return; | ||
} | ||
|
||
StopCoroutine(hapticRoutine); | ||
hapticRoutine = null; | ||
HapticPulser.Cancel(); | ||
ResetIntensity(); | ||
} | ||
|
||
/// <summary> | ||
/// Resets the <see cref="Haptics.HapticPulser.Intensity"/> back to its original value. | ||
/// </summary> | ||
protected virtual void ResetIntensity() | ||
{ | ||
HapticPulser.Intensity = cachedIntensity; | ||
} | ||
|
||
/// <summary> | ||
/// A custom routine to generate a haptic pattern. | ||
/// </summary> | ||
/// <returns>An Enumerator to manage the running of the Coroutine.</returns> | ||
protected abstract IEnumerator HapticProcessRoutine(); | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.