SoundFX.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. using UnityEngine;
  2. using UnityEngine.Audio;
  3. namespace OVR
  4. {
  5. public enum SoundFXNext {
  6. Random = 0,
  7. Sequential = 1,
  8. }
  9. public enum FreqHint {
  10. None = 0,
  11. Wide = 1,
  12. Narrow = 2,
  13. }
  14. public enum SoundPriority {
  15. VeryLow = -2,
  16. Low = -1,
  17. Default = 0,
  18. High = 1,
  19. VeryHigh = 2,
  20. }
  21. [System.Serializable]
  22. public class OSPProps {
  23. public OSPProps() {
  24. enableSpatialization = false;
  25. useFastOverride = false;
  26. gain = 0.0f;
  27. enableInvSquare = false;
  28. volumetric = 0.0f;
  29. invSquareFalloff = new Vector2( 1.0f, 25.0f );
  30. }
  31. [Tooltip( "Set to true to play the sound FX spatialized with binaural HRTF, default = false")]
  32. public bool enableSpatialization = false;
  33. [Tooltip( "Play the sound FX with reflections, default = false")]
  34. public bool useFastOverride = false;
  35. [Tooltip( "Boost the gain on the spatialized sound FX, default = 0.0")]
  36. [Range( 0.0f, 24.0f )]
  37. public float gain = 0.0f;
  38. [Tooltip("Enable Inverse Square attenuation curve, default = false")]
  39. public bool enableInvSquare = false;
  40. [Tooltip("Change the sound from point source (0.0f) to a spherical volume, default = 0.0")]
  41. [Range(0.0f, 1000.0f)]
  42. public float volumetric = 0.0f;
  43. [Tooltip("Set the near and far falloff value for the OSP attenuation curve, default = 1.0")]
  44. [MinMax ( 1.0f, 25.0f, 0.0f, 250.0f )]
  45. public Vector2 invSquareFalloff = new Vector2( 1.0f, 25.0f );
  46. }
  47. /*
  48. -----------------------
  49. SoundFX
  50. -----------------------
  51. */
  52. [System.Serializable]
  53. public class SoundFX {
  54. public SoundFX() {
  55. playback = SoundFXNext.Random;
  56. volume = 1.0f;
  57. pitchVariance = Vector2.one;
  58. falloffDistance = new Vector2( 1.0f, 25.0f );
  59. falloffCurve = AudioRolloffMode.Linear;
  60. volumeFalloffCurve = new AnimationCurve( new Keyframe[2] { new Keyframe( 0f, 1.0f ), new Keyframe( 1f, 1f ) } );
  61. reverbZoneMix = new AnimationCurve( new Keyframe[2] { new Keyframe( 0f, 1.0f ), new Keyframe( 1f, 1f ) } );
  62. spread = 0.0f;
  63. pctChanceToPlay = 1.0f;
  64. priority = SoundPriority.Default;
  65. delay = Vector2.zero;
  66. looping = false;
  67. ospProps = new OSPProps();
  68. }
  69. [Tooltip( "Each sound FX should have a unique name")]
  70. public string name = string.Empty;
  71. [Tooltip( "Sound diversity playback option when multiple audio clips are defined, default = Random")]
  72. public SoundFXNext playback = SoundFXNext.Random;
  73. [Tooltip( "Default volume for this sound FX, default = 1.0")]
  74. [Range (0.0f, 1.0f)]
  75. public float volume = 1.0f;
  76. [Tooltip( "Random pitch variance each time a sound FX is played, default = 1.0 (none)")]
  77. [MinMax ( 1.0f, 1.0f, 0.0f, 2.0f )]
  78. public Vector2 pitchVariance = Vector2.one;
  79. [Tooltip( "Falloff distance for the sound FX, default = 1m min to 25m max")]
  80. [MinMax ( 1.0f, 25.0f, 0.0f, 250.0f )]
  81. public Vector2 falloffDistance = new Vector2( 1.0f, 25.0f );
  82. [Tooltip( "Volume falloff curve - sets how the sound FX attenuates over distance, default = Linear")]
  83. public AudioRolloffMode falloffCurve = AudioRolloffMode.Linear;
  84. [Tooltip( "Defines the custom volume falloff curve")]
  85. public AnimationCurve volumeFalloffCurve = new AnimationCurve( new Keyframe[2] { new Keyframe( 0f, 1.0f ), new Keyframe( 1f, 1f ) } );
  86. [Tooltip( "The amount by which the signal from the AudioSource will be mixed into the global reverb associated with the Reverb Zones | Valid range is 0.0 - 1.1, default = 1.0" )]
  87. public AnimationCurve reverbZoneMix = new AnimationCurve( new Keyframe[2] { new Keyframe( 0f, 1.0f ), new Keyframe( 1f, 1f ) } );
  88. [Tooltip( "Sets the spread angle (in degrees) of a 3d stereo or multichannel sound in speaker space, default = 0")]
  89. [Range (0.0f, 360.0f)]
  90. public float spread = 0.0f;
  91. [Tooltip( "The percentage chance that this sound FX will play | 0.0 = none, 1.0 = 100%, default = 1.0")]
  92. [Range (0.0f, 1.0f)]
  93. public float pctChanceToPlay = 1.0f;
  94. [Tooltip( "Sets the priority for this sound to play and/or to override a currently playing sound FX, default = Default")]
  95. public SoundPriority priority = SoundPriority.Default;
  96. [Tooltip( "Specifies the default delay when this sound FX is played, default = 0.0 secs")]
  97. [MinMax ( 0.0f, 0.0f, 0.0f, 2.0f )]
  98. public Vector2 delay = Vector2.zero; // this overrides any delay passed into PlaySound() or PlaySoundAt()
  99. [Tooltip( "Set to true for the sound to loop continuously, default = false")]
  100. public bool looping = false;
  101. public OSPProps ospProps = new OSPProps();
  102. [Tooltip( "List of the audio clips assigned to this sound FX")]
  103. public AudioClip[] soundClips = new AudioClip[1];
  104. // editor only - unfortunately if we set it not to serialize, we can't query it from the editor
  105. public bool visibilityToggle = false;
  106. // runtime vars
  107. [System.NonSerialized]
  108. private SoundGroup soundGroup = null;
  109. private int lastIdx = -1;
  110. private int playingIdx = -1;
  111. public int Length { get { return soundClips.Length; } }
  112. public bool IsValid { get { return ( ( soundClips.Length != 0 ) && ( soundClips[0] != null ) ); } }
  113. public SoundGroup Group { get { return soundGroup; } set { soundGroup = value; } }
  114. public float MaxFalloffDistSquared { get { return falloffDistance.y * falloffDistance.y; } }
  115. public float GroupVolumeOverride { get { return ( soundGroup != null ) ? soundGroup.volumeOverride : 1.0f; } }
  116. /*
  117. -----------------------
  118. GetClip()
  119. -----------------------
  120. */
  121. public AudioClip GetClip() {
  122. if ( soundClips.Length == 0 ) {
  123. return null;
  124. } else if ( soundClips.Length == 1 ) {
  125. return soundClips[0];
  126. }
  127. if ( playback == SoundFXNext.Random ) {
  128. // random, but don't pick the last one
  129. int idx = Random.Range( 0, soundClips.Length );
  130. while ( idx == lastIdx ) {
  131. idx = Random.Range( 0, soundClips.Length );
  132. }
  133. lastIdx = idx;
  134. return soundClips[idx];
  135. } else {
  136. // sequential
  137. if ( ++lastIdx >= soundClips.Length ) {
  138. lastIdx = 0;
  139. }
  140. return soundClips[lastIdx];
  141. }
  142. }
  143. /*
  144. -----------------------
  145. GetMixerGroup()
  146. -----------------------
  147. */
  148. public AudioMixerGroup GetMixerGroup( AudioMixerGroup defaultMixerGroup ) {
  149. if ( soundGroup != null ) {
  150. return ( soundGroup.mixerGroup != null ) ? soundGroup.mixerGroup : defaultMixerGroup;
  151. }
  152. return defaultMixerGroup;
  153. }
  154. /*
  155. -----------------------
  156. ReachedGroupPlayLimit()
  157. -----------------------
  158. */
  159. public bool ReachedGroupPlayLimit() {
  160. if ( soundGroup != null ) {
  161. return !soundGroup.CanPlaySound();
  162. }
  163. return false;
  164. }
  165. /*
  166. -----------------------
  167. GetClipLength()
  168. -----------------------
  169. */
  170. public float GetClipLength( int idx ) {
  171. if ( ( idx == -1 ) || ( soundClips.Length == 0 ) || ( idx >= soundClips.Length ) || ( soundClips[idx] == null ) ) {
  172. return 0.0f;
  173. } else {
  174. return soundClips[idx].length;
  175. }
  176. }
  177. /*
  178. -----------------------
  179. GetPitch()
  180. -----------------------
  181. */
  182. public float GetPitch() {
  183. return Random.Range( pitchVariance.x, pitchVariance.y );
  184. }
  185. /*
  186. -----------------------
  187. PlaySound()
  188. -----------------------
  189. */
  190. public int PlaySound( float delaySecs = 0.0f ) {
  191. playingIdx = -1;
  192. if ( !IsValid ) {
  193. return playingIdx;
  194. }
  195. // check the random chance to play here to save the function calls
  196. if ( ( pctChanceToPlay > 0.99f ) || ( Random.value < pctChanceToPlay ) ) {
  197. if ( delay.y > 0.0f ) {
  198. delaySecs = Random.Range( delay.x, delay.y );
  199. }
  200. playingIdx = AudioManager.PlaySound( this, EmitterChannel.Any, delaySecs );
  201. }
  202. return playingIdx;
  203. }
  204. /*
  205. -----------------------
  206. PlaySoundAt()
  207. -----------------------
  208. */
  209. public int PlaySoundAt( Vector3 pos, float delaySecs = 0.0f, float volumeOverride = 1.0f, float pitchMultiplier = 1.0f ) {
  210. playingIdx = -1;
  211. if ( !IsValid ) {
  212. return playingIdx;
  213. }
  214. // check the random chance to play here to save the function calls
  215. if ( ( pctChanceToPlay > 0.99f ) || ( Random.value < pctChanceToPlay ) ) {
  216. if ( delay.y > 0.0f ) {
  217. delaySecs = Random.Range( delay.x, delay.y );
  218. }
  219. playingIdx = AudioManager.PlaySoundAt( pos, this, EmitterChannel.Any, delaySecs, volumeOverride, pitchMultiplier );
  220. }
  221. return playingIdx;
  222. }
  223. /*
  224. -----------------------
  225. SetOnFinished()
  226. get a callback when the sound is finished playing
  227. -----------------------
  228. */
  229. public void SetOnFinished( System.Action onFinished ) {
  230. if ( playingIdx > -1 ) {
  231. AudioManager.SetOnFinished( playingIdx, onFinished );
  232. }
  233. }
  234. /*
  235. -----------------------
  236. SetOnFinished()
  237. get a callback with an object parameter when the sound is finished playing
  238. -----------------------
  239. */
  240. public void SetOnFinished( System.Action<object> onFinished, object obj ) {
  241. if ( playingIdx > -1 ) {
  242. AudioManager.SetOnFinished( playingIdx, onFinished, obj );
  243. }
  244. }
  245. /*
  246. -----------------------
  247. StopSound()
  248. -----------------------
  249. */
  250. public bool StopSound() {
  251. bool stopped = false;
  252. if (playingIdx > -1){
  253. stopped = AudioManager.StopSound(playingIdx);
  254. playingIdx = -1;
  255. }
  256. return stopped;
  257. }
  258. /*
  259. -----------------------
  260. AttachToParent()
  261. -----------------------
  262. */
  263. public void AttachToParent( Transform parent) {
  264. if (playingIdx > -1) {
  265. AudioManager.AttachSoundToParent(playingIdx, parent);
  266. }
  267. }
  268. /*
  269. -----------------------
  270. DetachFromParent()
  271. -----------------------
  272. */
  273. public void DetachFromParent() {
  274. if (playingIdx > -1) {
  275. AudioManager.DetachSoundFromParent(playingIdx);
  276. }
  277. }
  278. }
  279. } // namespace OVR