forked from microsoft/MixedRealityToolkit-Unity
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAudioEmitter.cs
More file actions
139 lines (117 loc) · 5.24 KB
/
AudioEmitter.cs
File metadata and controls
139 lines (117 loc) · 5.24 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
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
using System;
using System.Collections.Generic;
using UnityEngine;
namespace HoloToolkit.Unity
{
/// <summary>
/// Class which supports IAudioInfluencers being used with audio sources.
/// </summary>
[RequireComponent(typeof(AudioSource))]
public class AudioEmitter : MonoBehaviour
{
[Tooltip("Time, in seconds, between audio influence updates. 0 indicates to update every frame.")]
[Range(0.0f, 1.0f)]
public float UpdateInterval = 0.25f;
[Tooltip("Maximum distance, in m, to look when attempting to find the user and any influencers.")]
[Range(1.0f, 50.0f)]
public float MaxDistance = 20.0f;
[Tooltip("Maximum number of objects that will be considered when looking for influencers.")]
[Range(1, 25)]
[SerializeField]
private int MaxObjects = 10;
// Time of last audio processing update.
private DateTime lastUpdate = DateTime.MinValue;
/// <summary>
/// The source of the audio.
/// </summary>
private AudioSource audioSource;
/// <summary>
/// The initial volume level of the audio source.
/// </summary>
private float initialAudioSourceVolume;
/// <summary>
/// The hits returned by Physics.RaycastAll
/// </summary>
private RaycastHit[] hits;
/// <summary>
/// The collection of previously applied audio influencers.
/// </summary>
private List<IAudioInfluencer> previousInfluencers = new List<IAudioInfluencer>();
private void Awake()
{
audioSource = gameObject.GetComponent<AudioSource>();
initialAudioSourceVolume = audioSource.volume;
// Pre-allocate the array that will be used to collect RaycastHit structures.
hits = new RaycastHit[MaxObjects];
}
private void Update()
{
DateTime now = DateTime.Now;
// Audio influences are not updated every frame.
if ((UpdateInterval * 1000.0f) <= (now - lastUpdate).Milliseconds)
{
audioSource.volume = initialAudioSourceVolume;
// Get the audio influencers that should apply to the audio source.
List<IAudioInfluencer> influencers = GetInfluencers();
foreach (IAudioInfluencer influencer in influencers)
{
// Apply the influencer's effect.
influencer.ApplyEffect(gameObject, audioSource);
}
// Find and remove the audio influencers that are to be removed from the audio source.
List<IAudioInfluencer> influencersToRemove = new List<IAudioInfluencer>();
foreach (IAudioInfluencer prev in previousInfluencers)
{
if (!influencers.Contains(prev))
{
influencersToRemove.Add(prev);
}
}
RemoveInfluencers(influencersToRemove);
previousInfluencers = influencers;
lastUpdate = now;
}
}
/// <summary>
/// Removes the effects applied by specified audio influencers.
/// </summary>
/// <param name="influencers">Collection of IAudioInfluencer objects.</param>
private void RemoveInfluencers(List<IAudioInfluencer> influencers)
{
foreach (IAudioInfluencer influencer in influencers)
{
influencer.RemoveEffect(gameObject, audioSource);
}
}
/// <summary>
/// Finds the IAudioInfluencer objects that are to be applied to the audio source.
/// </summary>
/// <returns>Collection of IAudioInfluencer objects.</returns>
private List<IAudioInfluencer> GetInfluencers()
{
List<IAudioInfluencer> influencers = new List<IAudioInfluencer>();
Transform cameraTransform = CameraCache.Main.transform;
// For influencers that take effect only when between the emitter and the user, perform a raycast
// from the user toward the object.
Vector3 direction = (gameObject.transform.position - cameraTransform.position).normalized;
float distance = Vector3.Distance(cameraTransform.position, gameObject.transform.position);
int count = Physics.RaycastNonAlloc(cameraTransform.position,
direction,
hits,
distance,
Physics.DefaultRaycastLayers,
QueryTriggerInteraction.Ignore);
for (int i = 0; i < count; i++)
{
IAudioInfluencer ai = hits[i].collider.gameObject.GetComponentInParent<IAudioInfluencer>();
if (ai != null)
{
influencers.Add(ai);
}
}
return influencers;
}
}
}