Added VR libraries

This commit is contained in:
Chris Midkiff
2018-10-08 23:54:11 -04:00
parent d9eb2a9763
commit 7ce1036e39
1037 changed files with 195630 additions and 348 deletions

View File

@@ -0,0 +1,431 @@
// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// 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;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
/// This is the main GVR audio class that communicates with the native code implementation of
/// the audio system. Native functions of the system can only be called through this class to
/// preserve the internal system functionality. Public function calls are *not* thread-safe.
#if UNITY_2017_1_OR_NEWER
[System.Obsolete("GvrAudio is deprecated. Please upgrade to Resonance Audio (https://developers.google.com/resonance-audio/migrate).")]
#endif // UNITY_2017_1_OR_NEWER
public static class GvrAudio {
/// Audio system rendering quality.
public enum Quality {
Stereo = 0, ///< Stereo-only rendering
Low = 1, ///< Low quality binaural rendering (first-order HRTF)
High = 2 ///< High quality binaural rendering (third-order HRTF)
}
/// Native audio spatializer effect data.
public enum SpatializerData {
Id = 0, /// ID.
Type = 1, /// Spatializer type.
NumChannels = 2, /// Number of input channels.
ChannelSet = 3, /// Soundfield channel set.
Gain = 4, /// Gain.
DistanceAttenuation = 5, /// Computed distance attenuation.
MinDistance = 6, /// Minimum distance for distance-based attenuation.
ZeroOutput = 7, /// Should zero out the output buffer?
}
/// Native audio spatializer type.
public enum SpatializerType {
Source = 0, /// 3D sound object.
Soundfield = 1 /// First-order ambisonic soundfield.
}
/// System sampling rate.
public static int SampleRate {
get { return sampleRate; }
}
private static int sampleRate = -1;
/// System number of output channels.
public static int NumChannels {
get { return numChannels; }
}
private static int numChannels = -1;
/// System number of frames per buffer.
public static int FramesPerBuffer {
get { return framesPerBuffer; }
}
private static int framesPerBuffer = -1;
/// Initializes the audio system with the current audio configuration.
/// @note This should only be called from the main Unity thread.
public static void Initialize (GvrAudioListener listener, Quality quality) {
if (!initialized) {
// Initialize the audio system.
AudioConfiguration config = AudioSettings.GetConfiguration();
sampleRate = config.sampleRate;
numChannels = (int)config.speakerMode;
framesPerBuffer = config.dspBufferSize;
if (numChannels != (int)AudioSpeakerMode.Stereo) {
Debug.LogError("Only 'Stereo' speaker mode is supported by GVR Audio.");
return;
}
Initialize((int) quality, sampleRate, numChannels, framesPerBuffer);
listenerTransform = listener.transform;
initialized = true;
} else if (listener.transform != listenerTransform) {
Debug.LogError("Only one GvrAudioListener component is allowed in the scene.");
GvrAudioListener.Destroy(listener);
}
}
/// Shuts down the audio system.
/// @note This should only be called from the main Unity thread.
public static void Shutdown (GvrAudioListener listener) {
if (initialized && listener.transform == listenerTransform) {
initialized = false;
Shutdown();
sampleRate = -1;
numChannels = -1;
framesPerBuffer = -1;
listenerTransform = null;
}
}
/// Updates the audio listener.
/// @note This should only be called from the main Unity thread.
public static void UpdateAudioListener (float globalGainDb, LayerMask occlusionMask) {
if (initialized) {
occlusionMaskValue = occlusionMask.value;
SetListenerGain(ConvertAmplitudeFromDb(globalGainDb));
}
}
/// Creates a new first-order ambisonic soundfield with a unique id.
/// @note This should only be called from the main Unity thread.
public static int CreateAudioSoundfield () {
int soundfieldId = -1;
if (initialized) {
soundfieldId = CreateSoundfield(numFoaChannels);
}
return soundfieldId;
}
/// Updates the |soundfield| with given |id| and its properties.
/// @note This should only be called from the main Unity thread.
public static void UpdateAudioSoundfield (int id, GvrAudioSoundfield soundfield) {
if (initialized) {
SetSourceBypassRoomEffects(id, soundfield.bypassRoomEffects);
}
}
/// Creates a new audio source with a unique id.
/// @note This should only be called from the main Unity thread.
public static int CreateAudioSource (bool hrtfEnabled) {
int sourceId = -1;
if (initialized) {
sourceId = CreateSoundObject(hrtfEnabled);
}
return sourceId;
}
/// Destroys the audio source with given |id|.
/// @note This should only be called from the main Unity thread.
public static void DestroyAudioSource (int id) {
if (initialized) {
DestroySource(id);
}
}
/// Updates the audio |source| with given |id| and its properties.
/// @note This should only be called from the main Unity thread.
public static void UpdateAudioSource (int id, GvrAudioSource source, float currentOcclusion) {
if (initialized) {
SetSourceBypassRoomEffects(id, source.bypassRoomEffects);
SetSourceDirectivity(id, source.directivityAlpha, source.directivitySharpness);
SetSourceListenerDirectivity(id, source.listenerDirectivityAlpha,
source.listenerDirectivitySharpness);
SetSourceOcclusionIntensity(id, currentOcclusion);
}
}
/// Updates the room effects of the environment with given |room| properties.
/// @note This should only be called from the main Unity thread.
public static void UpdateAudioRoom(GvrAudioRoom room, bool roomEnabled) {
// Update the enabled rooms list.
if (roomEnabled) {
if (!enabledRooms.Contains(room)) {
enabledRooms.Add(room);
}
} else {
enabledRooms.Remove(room);
}
// Update the current room effects to be applied.
if(initialized) {
if (enabledRooms.Count > 0) {
GvrAudioRoom currentRoom = enabledRooms[enabledRooms.Count - 1];
RoomProperties roomProperties = GetRoomProperties(currentRoom);
// Pass the room properties into a pointer.
IntPtr roomPropertiesPtr = Marshal.AllocHGlobal(Marshal.SizeOf(roomProperties));
Marshal.StructureToPtr(roomProperties, roomPropertiesPtr, false);
SetRoomProperties(roomPropertiesPtr);
Marshal.FreeHGlobal(roomPropertiesPtr);
} else {
// Set the room properties to null, which will effectively disable the room effects.
SetRoomProperties(IntPtr.Zero);
}
}
}
/// Computes the occlusion intensity of a given |source| using point source detection.
/// @note This should only be called from the main Unity thread.
public static float ComputeOcclusion (Transform sourceTransform) {
float occlusion = 0.0f;
if (initialized) {
Vector3 listenerPosition = listenerTransform.position;
Vector3 sourceFromListener = sourceTransform.position - listenerPosition;
int numHits = Physics.RaycastNonAlloc(listenerPosition, sourceFromListener, occlusionHits,
sourceFromListener.magnitude, occlusionMaskValue);
for (int i = 0; i < numHits; ++i) {
if (occlusionHits[i].transform != listenerTransform &&
occlusionHits[i].transform != sourceTransform) {
occlusion += 1.0f;
}
}
}
return occlusion;
}
/// Converts given |db| value to its amplitude equivalent where 'dB = 20 * log10(amplitude)'.
public static float ConvertAmplitudeFromDb (float db) {
return Mathf.Pow(10.0f, 0.05f * db);
}
/// Generates a set of points to draw a 2D polar pattern.
public static Vector2[] Generate2dPolarPattern (float alpha, float order, int resolution) {
Vector2[] points = new Vector2[resolution];
float interval = 2.0f * Mathf.PI / resolution;
for (int i = 0; i < resolution; ++i) {
float theta = i * interval;
// Magnitude |r| for |theta| in radians.
float r = Mathf.Pow(Mathf.Abs((1 - alpha) + alpha * Mathf.Cos(theta)), order);
points[i] = new Vector2(r * Mathf.Sin(theta), r * Mathf.Cos(theta));
}
return points;
}
/// Returns whether the listener is currently inside the given |room| boundaries.
public static bool IsListenerInsideRoom(GvrAudioRoom room) {
bool isInside = false;
if(initialized) {
Vector3 relativePosition = listenerTransform.position - room.transform.position;
Quaternion rotationInverse = Quaternion.Inverse(room.transform.rotation);
bounds.size = Vector3.Scale(room.transform.lossyScale, room.size);
isInside = bounds.Contains(rotationInverse * relativePosition);
}
return isInside;
}
/// Listener directivity GUI color.
public static readonly Color listenerDirectivityColor = 0.65f * Color.magenta;
/// Source directivity GUI color.
public static readonly Color sourceDirectivityColor = 0.65f * Color.blue;
/// Minimum distance threshold between |minDistance| and |maxDistance|.
public const float distanceEpsilon = 0.01f;
/// Max distance limit that can be set for volume rolloff.
public const float maxDistanceLimit = 1000000.0f;
/// Min distance limit that can be set for volume rolloff.
public const float minDistanceLimit = 990099.0f;
/// Maximum allowed gain value in decibels.
public const float maxGainDb = 24.0f;
/// Minimum allowed gain value in decibels.
public const float minGainDb = -24.0f;
/// Maximum allowed reverb brightness modifier value.
public const float maxReverbBrightness = 1.0f;
/// Minimum allowed reverb brightness modifier value.
public const float minReverbBrightness = -1.0f;
/// Maximum allowed reverb time modifier value.
public const float maxReverbTime = 3.0f;
/// Maximum allowed reflectivity multiplier of a room surface material.
public const float maxReflectivity = 2.0f;
/// Maximum allowed number of raycast hits for occlusion computation per source.
public const int maxNumOcclusionHits = 12;
/// Source occlusion detection rate in seconds.
public const float occlusionDetectionInterval = 0.2f;
/// Number of first-order ambisonic input channels.
public const int numFoaChannels = 4;
[StructLayout(LayoutKind.Sequential)]
private struct RoomProperties {
// Center position of the room in world space.
public float positionX;
public float positionY;
public float positionZ;
// Rotation (quaternion) of the room in world space.
public float rotationX;
public float rotationY;
public float rotationZ;
public float rotationW;
// Size of the shoebox room in world space.
public float dimensionsX;
public float dimensionsY;
public float dimensionsZ;
// Material name of each surface of the shoebox room.
public GvrAudioRoom.SurfaceMaterial materialLeft;
public GvrAudioRoom.SurfaceMaterial materialRight;
public GvrAudioRoom.SurfaceMaterial materialBottom;
public GvrAudioRoom.SurfaceMaterial materialTop;
public GvrAudioRoom.SurfaceMaterial materialFront;
public GvrAudioRoom.SurfaceMaterial materialBack;
// User defined uniform scaling factor for reflectivity. This parameter has no effect when set
// to 1.0f.
public float reflectionScalar;
// User defined reverb tail gain multiplier. This parameter has no effect when set to 0.0f.
public float reverbGain;
// Adjusts the reverberation time across all frequency bands. RT60 values are multiplied by this
// factor. Has no effect when set to 1.0f.
public float reverbTime;
// Controls the slope of a line from the lowest to the highest RT60 values (increases high
// frequency RT60s when positive, decreases when negative). Has no effect when set to 0.0f.
public float reverbBrightness;
};
// Converts given |position| and |rotation| from Unity space to audio space.
private static void ConvertAudioTransformFromUnity (ref Vector3 position,
ref Quaternion rotation) {
transformMatrix = Pose3D.FlipHandedness(Matrix4x4.TRS(position, rotation, Vector3.one));
position = transformMatrix.GetColumn(3);
rotation = Quaternion.LookRotation(transformMatrix.GetColumn(2), transformMatrix.GetColumn(1));
}
// Returns room properties of the given |room|.
private static RoomProperties GetRoomProperties(GvrAudioRoom room) {
RoomProperties roomProperties;
Vector3 position = room.transform.position;
Quaternion rotation = room.transform.rotation;
Vector3 scale = Vector3.Scale(room.transform.lossyScale, room.size);
ConvertAudioTransformFromUnity(ref position, ref rotation);
roomProperties.positionX = position.x;
roomProperties.positionY = position.y;
roomProperties.positionZ = position.z;
roomProperties.rotationX = rotation.x;
roomProperties.rotationY = rotation.y;
roomProperties.rotationZ = rotation.z;
roomProperties.rotationW = rotation.w;
roomProperties.dimensionsX = scale.x;
roomProperties.dimensionsY = scale.y;
roomProperties.dimensionsZ = scale.z;
roomProperties.materialLeft = room.leftWall;
roomProperties.materialRight = room.rightWall;
roomProperties.materialBottom = room.floor;
roomProperties.materialTop = room.ceiling;
roomProperties.materialFront = room.frontWall;
roomProperties.materialBack = room.backWall;
roomProperties.reverbGain = ConvertAmplitudeFromDb(room.reverbGainDb);
roomProperties.reverbTime = room.reverbTime;
roomProperties.reverbBrightness = room.reverbBrightness;
roomProperties.reflectionScalar = room.reflectivity;
return roomProperties;
}
// Boundaries instance to be used in room detection logic.
private static Bounds bounds = new Bounds(Vector3.zero, Vector3.zero);
// Container to store the currently active rooms in the scene.
private static List<GvrAudioRoom> enabledRooms = new List<GvrAudioRoom>();
// Denotes whether the system is initialized properly.
private static bool initialized = false;
// Listener transform.
private static Transform listenerTransform = null;
// Pre-allocated raycast hit list for occlusion computation.
private static RaycastHit[] occlusionHits = new RaycastHit[maxNumOcclusionHits];
// Occlusion layer mask.
private static int occlusionMaskValue = -1;
// 4x4 transformation matrix to be used in transform space conversion.
private static Matrix4x4 transformMatrix = Matrix4x4.identity;
#if !UNITY_EDITOR && UNITY_IOS
private const string pluginName = "__Internal";
#else
private const string pluginName = "audioplugingvrunity";
#endif // !UNITY_EDITOR && UNITY_IOS
// Listener handlers.
[DllImport(pluginName)]
private static extern void SetListenerGain (float gain);
// Soundfield handlers.
[DllImport(pluginName)]
private static extern int CreateSoundfield (int numChannels);
// Source handlers.
[DllImport(pluginName)]
private static extern int CreateSoundObject (bool enableHrtf);
[DllImport(pluginName)]
private static extern void DestroySource (int sourceId);
[DllImport(pluginName)]
private static extern void SetSourceBypassRoomEffects (int sourceId, bool bypassRoomEffects);
[DllImport(pluginName)]
private static extern void SetSourceDirectivity (int sourceId, float alpha, float order);
[DllImport(pluginName)]
private static extern void SetSourceListenerDirectivity (int sourceId, float alpha, float order);
[DllImport(pluginName)]
private static extern void SetSourceOcclusionIntensity (int sourceId, float intensity);
// Room handlers.
[DllImport(pluginName)]
private static extern void SetRoomProperties (IntPtr roomProperties);
// System handlers.
[DllImport(pluginName)]
private static extern void Initialize (int quality, int sampleRate, int numChannels,
int framesPerBuffer);
[DllImport(pluginName)]
private static extern void Shutdown ();
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 84ad368148aad42938b2fdb28552e8ac
timeCreated: 1447961130
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,61 @@
// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// 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;
#pragma warning disable 0618 // Ignore GvrAudio* deprecation
/// GVR audio listener component that enhances AudioListener to provide advanced spatial audio
/// features.
///
/// There should be only one instance of this which is attached to the AudioListener's game object.
#if UNITY_2017_1_OR_NEWER
[System.Obsolete("Please upgrade to Resonance Audio (https://developers.google.com/resonance-audio/migrate).")]
#endif // UNITY_2017_1_OR_NEWER
[AddComponentMenu("GoogleVR/Audio/GvrAudioListener")]
public class GvrAudioListener : MonoBehaviour {
/// Global gain in decibels to be applied to the processed output.
public float globalGainDb = 0.0f;
/// Global layer mask to be used in occlusion detection.
public LayerMask occlusionMask = -1;
/// Audio rendering quality of the system.
[SerializeField]
private GvrAudio.Quality quality = GvrAudio.Quality.High;
void Awake () {
#if UNITY_EDITOR && UNITY_2017_1_OR_NEWER
Debug.LogWarningFormat(gameObject,
"Game object '{0}' uses deprecated {1} component.\nPlease upgrade to Resonance Audio ({2}).",
name, GetType().Name, "https://developers.google.com/resonance-audio/migrate");
#endif // UNITY_EDITOR && UNITY_2017_1_OR_NEWER
GvrAudio.Initialize(this, quality);
}
void OnEnable () {
GvrAudio.UpdateAudioListener(globalGainDb, occlusionMask);
}
void OnDestroy () {
GvrAudio.Shutdown(this);
}
void Update () {
GvrAudio.UpdateAudioListener(globalGainDb, occlusionMask);
}
}
#pragma warning restore 0618 // Restore warnings

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b1156c073149742478887bb24456f32d
timeCreated: 1447961345
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,115 @@
// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// 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;
#pragma warning disable 0618 // Ignore GvrAudio* deprecation
/// GVR audio room component that simulates environmental effects of a room with respect to the
/// properties of the attached game object.
#if UNITY_2017_1_OR_NEWER
[System.Obsolete("Please upgrade to Resonance Audio (https://developers.google.com/resonance-audio/migrate).")]
#endif // UNITY_2017_1_OR_NEWER
[AddComponentMenu("GoogleVR/Audio/GvrAudioRoom")]
public class GvrAudioRoom : MonoBehaviour {
/// Material type that determines the acoustic properties of a room surface.
public enum SurfaceMaterial {
Transparent = 0, ///< Transparent
AcousticCeilingTiles = 1, ///< Acoustic ceiling tiles
BrickBare = 2, ///< Brick, bare
BrickPainted = 3, ///< Brick, painted
ConcreteBlockCoarse = 4, ///< Concrete block, coarse
ConcreteBlockPainted = 5, ///< Concrete block, painted
CurtainHeavy = 6, ///< Curtain, heavy
FiberglassInsulation = 7, ///< Fiberglass insulation
GlassThin = 8, ///< Glass, thin
GlassThick = 9, ///< Glass, thick
Grass = 10, ///< Grass
LinoleumOnConcrete = 11, ///< Linoleum on concrete
Marble = 12, ///< Marble
Metal = 13, ///< Galvanized sheet metal
ParquetOnConcrete = 14, ///< Parquet on concrete
PlasterRough = 15, ///< Plaster, rough
PlasterSmooth = 16, ///< Plaster, smooth
PlywoodPanel = 17, ///< Plywood panel
PolishedConcreteOrTile = 18, ///< Polished concrete or tile
Sheetrock = 19, ///< Sheetrock
WaterOrIceSurface = 20, ///< Water or ice surface
WoodCeiling = 21, ///< Wood ceiling
WoodPanel = 22 ///< Wood panel
}
/// Room surface material in negative x direction.
public SurfaceMaterial leftWall = SurfaceMaterial.ConcreteBlockCoarse;
/// Room surface material in positive x direction.
public SurfaceMaterial rightWall = SurfaceMaterial.ConcreteBlockCoarse;
/// Room surface material in negative y direction.
public SurfaceMaterial floor = SurfaceMaterial.ParquetOnConcrete;
/// Room surface material in positive y direction.
public SurfaceMaterial ceiling = SurfaceMaterial.PlasterRough;
/// Room surface material in negative z direction.
public SurfaceMaterial backWall = SurfaceMaterial.ConcreteBlockCoarse;
/// Room surface material in positive z direction.
public SurfaceMaterial frontWall = SurfaceMaterial.ConcreteBlockCoarse;
/// Reflectivity scalar for each surface of the room.
public float reflectivity = 1.0f;
/// Reverb gain modifier in decibels.
public float reverbGainDb = 0.0f;
/// Reverb brightness modifier.
public float reverbBrightness = 0.0f;
/// Reverb time modifier.
public float reverbTime = 1.0f;
/// Size of the room (normalized with respect to scale of the game object).
public Vector3 size = Vector3.one;
void Awake() {
#if UNITY_EDITOR && UNITY_2017_1_OR_NEWER
Debug.LogWarningFormat(gameObject,
"Game object '{0}' uses deprecated {1} component.\nPlease upgrade to Resonance Audio ({2}).",
name, GetType().Name, "https://developers.google.com/resonance-audio/migrate");
#endif // UNITY_EDITOR && UNITY_2017_1_OR_NEWER
}
void OnEnable () {
GvrAudio.UpdateAudioRoom(this, GvrAudio.IsListenerInsideRoom(this));
}
void OnDisable () {
GvrAudio.UpdateAudioRoom(this, false);
}
void Update () {
GvrAudio.UpdateAudioRoom(this, GvrAudio.IsListenerInsideRoom(this));
}
void OnDrawGizmosSelected () {
// Draw shoebox model wireframe of the room.
Gizmos.color = Color.yellow;
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawWireCube(Vector3.zero, size);
}
}
#pragma warning restore 0618 // Restore warnings

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1d2722c2401e34d51bf5b473ef7aeefb
timeCreated: 1447961354
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,506 @@
// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// 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 UnityEngine.Audio;
using System.Collections;
#pragma warning disable 0618 // Ignore GvrAudio* deprecation
/// GVR soundfield component that allows playback of first-order ambisonic recordings. The audio
/// sample should be in Ambix (ACN-SN3D) format.
#if UNITY_2017_1_OR_NEWER
[System.Obsolete("Please upgrade to Resonance Audio (https://developers.google.com/resonance-audio/migrate).")]
#endif // UNITY_2017_1_OR_NEWER
[AddComponentMenu("GoogleVR/Audio/GvrAudioSoundfield")]
public class GvrAudioSoundfield : MonoBehaviour {
/// Denotes whether the room effects should be bypassed.
public bool bypassRoomEffects = true;
/// Input gain in decibels.
public float gainDb = 0.0f;
/// Play source on awake.
public bool playOnAwake = true;
/// The default AudioClip to play.
public AudioClip clip0102 {
get { return soundfieldClip0102; }
set {
soundfieldClip0102 = value;
if (audioSources != null && audioSources.Length > 0) {
audioSources[0].clip = soundfieldClip0102;
}
}
}
[SerializeField]
private AudioClip soundfieldClip0102 = null;
public AudioClip clip0304 {
get { return soundfieldClip0304; }
set {
soundfieldClip0304 = value;
if (audioSources != null && audioSources.Length > 0) {
audioSources[1].clip = soundfieldClip0304;
}
}
}
[SerializeField]
private AudioClip soundfieldClip0304 = null;
/// Is the clip playing right now (Read Only)?
public bool isPlaying {
get {
if(audioSources != null && audioSources.Length > 0) {
return audioSources[0].isPlaying;
}
return false;
}
}
/// Is the audio clip looping?
public bool loop {
get { return soundfieldLoop; }
set {
soundfieldLoop = value;
if(audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].loop = soundfieldLoop;
}
}
}
}
[SerializeField]
private bool soundfieldLoop = false;
/// Un- / Mutes the soundfield. Mute sets the volume=0, Un-Mute restore the original volume.
public bool mute {
get { return soundfieldMute; }
set {
soundfieldMute = value;
if(audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].mute = soundfieldMute;
}
}
}
}
[SerializeField]
private bool soundfieldMute = false;
/// The pitch of the audio source.
public float pitch {
get { return soundfieldPitch; }
set {
soundfieldPitch = value;
if(audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].pitch = soundfieldPitch;
}
}
}
}
[SerializeField]
[Range(-3.0f, 3.0f)]
private float soundfieldPitch = 1.0f;
/// Sets the priority of the soundfield.
public int priority {
get { return soundfieldPriority; }
set {
soundfieldPriority = value;
if(audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].priority = soundfieldPriority;
}
}
}
}
[SerializeField]
[Range(0, 256)]
private int soundfieldPriority = 32;
/// Sets how much this soundfield is affected by 3D spatialization calculations
/// (attenuation, doppler).
public float spatialBlend {
get { return soundfieldSpatialBlend; }
set {
soundfieldSpatialBlend = value;
if (audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].spatialBlend = soundfieldSpatialBlend;
}
}
}
}
[SerializeField]
[Range(0.0f, 1.0f)]
private float soundfieldSpatialBlend = 0.0f;
/// Sets the Doppler scale for this soundfield.
public float dopplerLevel {
get { return soundfieldDopplerLevel; }
set {
soundfieldDopplerLevel = value;
if(audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].dopplerLevel = soundfieldDopplerLevel;
}
}
}
}
[SerializeField]
[Range(0.0f, 5.0f)]
private float soundfieldDopplerLevel = 0.0f;
/// Playback position in seconds.
public float time {
get {
if(audioSources != null && audioSources.Length > 0) {
return audioSources[0].time;
}
return 0.0f;
}
set {
if(audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].time = value;
}
}
}
}
/// Playback position in PCM samples.
public int timeSamples {
get {
if(audioSources != null && audioSources.Length > 0) {
return audioSources[0].timeSamples;
}
return 0;
}
set {
if(audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].timeSamples = value;
}
}
}
}
/// The volume of the audio source (0.0 to 1.0).
public float volume {
get { return soundfieldVolume; }
set {
soundfieldVolume = value;
if(audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].volume = soundfieldVolume;
}
}
}
}
[SerializeField]
[Range(0.0f, 1.0f)]
private float soundfieldVolume = 1.0f;
/// Volume rolloff model with respect to the distance.
public AudioRolloffMode rolloffMode {
get { return soundfieldRolloffMode; }
set {
soundfieldRolloffMode = value;
if (audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].rolloffMode = soundfieldRolloffMode;
if (rolloffMode == AudioRolloffMode.Custom) {
// Custom rolloff is not supported, set the curve for no distance attenuation.
audioSources[channelSet].SetCustomCurve(
AudioSourceCurveType.CustomRolloff,
AnimationCurve.Linear(soundfieldMinDistance, 1.0f, soundfieldMaxDistance, 1.0f));
}
}
}
}
}
[SerializeField]
private AudioRolloffMode soundfieldRolloffMode = AudioRolloffMode.Logarithmic;
/// MaxDistance is the distance a sound stops attenuating at.
public float maxDistance {
get { return soundfieldMaxDistance; }
set {
soundfieldMaxDistance = Mathf.Clamp(value, soundfieldMinDistance + GvrAudio.distanceEpsilon,
GvrAudio.maxDistanceLimit);
if (audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].maxDistance = soundfieldMaxDistance;
}
}
}
}
[SerializeField]
private float soundfieldMaxDistance = 500.0f;
/// Within the Min distance the GvrAudioSource will cease to grow louder in volume.
public float minDistance {
get { return soundfieldMinDistance; }
set {
soundfieldMinDistance = Mathf.Clamp(value, 0.0f, GvrAudio.minDistanceLimit);
if (audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].minDistance = soundfieldMinDistance;
}
}
}
}
[SerializeField]
private float soundfieldMinDistance = 1.0f;
// Unique source id.
private int id = -1;
// Unity audio sources per each soundfield channel set.
private AudioSource[] audioSources = null;
// Denotes whether the source is currently paused or not.
private bool isPaused = false;
void Awake () {
#if UNITY_EDITOR && UNITY_2017_1_OR_NEWER
Debug.LogWarningFormat(gameObject,
"Game object '{0}' uses deprecated {1} component.\nPlease upgrade to Resonance Audio ({2}).",
name, GetType().Name, "https://developers.google.com/resonance-audio/migrate");
#endif // UNITY_EDITOR && UNITY_2017_1_OR_NEWER
// Route the source output to |GvrAudioMixer|.
AudioMixer mixer = (Resources.Load("GvrAudioMixer") as AudioMixer);
if(mixer == null) {
Debug.LogError("GVRAudioMixer could not be found in Resources. Make sure that the GVR SDK" +
"Unity package is imported properly.");
return;
}
audioSources = new AudioSource[GvrAudio.numFoaChannels / 2];
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
GameObject channelSetObject = new GameObject("Channel Set " + channelSet);
channelSetObject.transform.parent = gameObject.transform;
channelSetObject.transform.localPosition = Vector3.zero;
channelSetObject.transform.localRotation = Quaternion.identity;
channelSetObject.hideFlags = HideFlags.HideAndDontSave;
audioSources[channelSet] = channelSetObject.AddComponent<AudioSource>();
audioSources[channelSet].enabled = false;
audioSources[channelSet].playOnAwake = false;
audioSources[channelSet].bypassReverbZones = true;
#if UNITY_5_5_OR_NEWER
audioSources[channelSet].spatializePostEffects = true;
#endif // UNITY_5_5_OR_NEWER
audioSources[channelSet].outputAudioMixerGroup = mixer.FindMatchingGroups("Master")[0];
}
OnValidate();
}
void OnEnable () {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].enabled = true;
}
if (playOnAwake && !isPlaying && InitializeSoundfield()) {
Play();
}
}
void Start () {
if (playOnAwake && !isPlaying) {
Play();
}
}
void OnDisable () {
Stop();
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].enabled = false;
}
}
void OnDestroy () {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
Destroy(audioSources[channelSet].gameObject);
}
}
void OnApplicationPause (bool pauseStatus) {
if (pauseStatus) {
Pause();
} else {
UnPause();
}
}
void Update () {
// Update soundfield.
if (!isPlaying && !isPaused) {
Stop();
} else {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].SetSpatializerFloat((int) GvrAudio.SpatializerData.Gain,
GvrAudio.ConvertAmplitudeFromDb(gainDb));
audioSources[channelSet].SetSpatializerFloat((int) GvrAudio.SpatializerData.MinDistance,
soundfieldMinDistance);
}
GvrAudio.UpdateAudioSoundfield(id, this);
}
}
/// Pauses playing the clip.
public void Pause () {
if (audioSources != null) {
isPaused = true;
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].Pause();
}
}
}
/// Plays the clip.
public void Play () {
double dspTime = AudioSettings.dspTime;
PlayScheduled(dspTime);
}
/// Plays the clip with a delay specified in seconds.
public void PlayDelayed (float delay) {
double delayedDspTime = AudioSettings.dspTime + (double)delay;
PlayScheduled(delayedDspTime);
}
/// Plays the clip at a specific time on the absolute time-line that AudioSettings.dspTime reads
/// from.
public void PlayScheduled (double time) {
if (audioSources != null && InitializeSoundfield()) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].PlayScheduled(time);
}
isPaused = false;
} else {
Debug.LogWarning ("GVR Audio soundfield not initialized. Audio playback not supported " +
"until after Awake() and OnEnable(). Try calling from Start() instead.");
}
}
/// Changes the time at which a sound that has already been scheduled to play will end.
public void SetScheduledEndTime(double time) {
if (audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].SetScheduledEndTime(time);
}
}
}
/// Changes the time at which a sound that has already been scheduled to play will start.
public void SetScheduledStartTime(double time) {
if (audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].SetScheduledStartTime(time);
}
}
}
/// Stops playing the clip.
public void Stop () {
if(audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].Stop();
}
ShutdownSoundfield();
isPaused = false;
}
}
/// Unpauses the paused playback.
public void UnPause () {
if (audioSources != null) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
audioSources[channelSet].UnPause();
}
isPaused = false;
}
}
// Initializes the source.
private bool InitializeSoundfield () {
if (id < 0) {
id = GvrAudio.CreateAudioSoundfield();
if (id >= 0) {
GvrAudio.UpdateAudioSoundfield(id, this);
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
InitializeChannelSet(audioSources[channelSet], channelSet);
}
}
}
return id >= 0;
}
// Shuts down the source.
private void ShutdownSoundfield () {
if (id >= 0) {
for (int channelSet = 0; channelSet < audioSources.Length; ++channelSet) {
ShutdownChannelSet(audioSources[channelSet], channelSet);
}
GvrAudio.DestroyAudioSource(id);
id = -1;
}
}
// Initializes given channel set of the soundfield.
private void InitializeChannelSet(AudioSource source, int channelSet) {
source.spatialize = true;
source.SetSpatializerFloat((int) GvrAudio.SpatializerData.Type,
(float) GvrAudio.SpatializerType.Soundfield);
source.SetSpatializerFloat((int) GvrAudio.SpatializerData.NumChannels,
(float) GvrAudio.numFoaChannels);
source.SetSpatializerFloat((int) GvrAudio.SpatializerData.ChannelSet, (float) channelSet);
source.SetSpatializerFloat((int) GvrAudio.SpatializerData.Gain,
GvrAudio.ConvertAmplitudeFromDb(gainDb));
source.SetSpatializerFloat((int) GvrAudio.SpatializerData.MinDistance, soundfieldMinDistance);
source.SetSpatializerFloat((int) GvrAudio.SpatializerData.ZeroOutput, 0.0f);
// Soundfield id must be set after all the spatializer parameters, to ensure that the soundfield
// is properly initialized before processing.
source.SetSpatializerFloat((int) GvrAudio.SpatializerData.Id, (float) id);
}
// Shuts down given channel set of the soundfield.
private void ShutdownChannelSet(AudioSource source, int channelSet) {
source.SetSpatializerFloat((int) GvrAudio.SpatializerData.Id, -1.0f);
// Ensure that the output is zeroed after shutdown.
source.SetSpatializerFloat((int) GvrAudio.SpatializerData.ZeroOutput, 1.0f);
source.spatialize = false;
}
void OnDidApplyAnimationProperties () {
OnValidate();
}
void OnValidate () {
clip0102 = soundfieldClip0102;
clip0304 = soundfieldClip0304;
loop = soundfieldLoop;
mute = soundfieldMute;
pitch = soundfieldPitch;
priority = soundfieldPriority;
spatialBlend = soundfieldSpatialBlend;
volume = soundfieldVolume;
dopplerLevel = soundfieldDopplerLevel;
minDistance = soundfieldMinDistance;
maxDistance = soundfieldMaxDistance;
rolloffMode = soundfieldRolloffMode;
}
}
#pragma warning restore 0618 // Restore warnings

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d38f0664abc0c446a8fa0886ec2bcd12
timeCreated: 1466460492
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,575 @@
// Copyright 2016 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// 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 UnityEngine.Audio;
using System.Collections;
#pragma warning disable 0618 // Ignore GvrAudio* deprecation
/// GVR audio source component that enhances AudioSource to provide advanced spatial audio features.
#if UNITY_2017_1_OR_NEWER
[System.Obsolete("Please upgrade to Resonance Audio (https://developers.google.com/resonance-audio/migrate).")]
#endif // UNITY_2017_1_OR_NEWER
[AddComponentMenu("GoogleVR/Audio/GvrAudioSource")]
public class GvrAudioSource : MonoBehaviour {
/// Denotes whether the room effects should be bypassed.
public bool bypassRoomEffects = false;
/// Directivity pattern shaping factor.
public float directivityAlpha = 0.0f;
/// Directivity pattern order.
public float directivitySharpness = 1.0f;
/// Listener directivity pattern shaping factor.
public float listenerDirectivityAlpha = 0.0f;
/// Listener directivity pattern order.
public float listenerDirectivitySharpness = 1.0f;
/// Input gain in decibels.
public float gainDb = 0.0f;
/// Occlusion effect toggle.
public bool occlusionEnabled = false;
/// Play source on awake.
public bool playOnAwake = true;
/// The default AudioClip to play.
public AudioClip clip {
get { return sourceClip; }
set {
sourceClip = value;
if (audioSource != null) {
audioSource.clip = sourceClip;
}
}
}
[SerializeField]
private AudioClip sourceClip = null;
/// Is the clip playing right now (Read Only)?
public bool isPlaying {
get {
if (audioSource != null) {
return audioSource.isPlaying;
}
return false;
}
}
/// Is the audio clip looping?
public bool loop {
get { return sourceLoop; }
set {
sourceLoop = value;
if (audioSource != null) {
audioSource.loop = sourceLoop;
}
}
}
[SerializeField]
private bool sourceLoop = false;
/// Un- / Mutes the source. Mute sets the volume=0, Un-Mute restore the original volume.
public bool mute {
get { return sourceMute; }
set {
sourceMute = value;
if (audioSource != null) {
audioSource.mute = sourceMute;
}
}
}
[SerializeField]
private bool sourceMute = false;
/// The pitch of the audio source.
public float pitch {
get { return sourcePitch; }
set {
sourcePitch = value;
if (audioSource != null) {
audioSource.pitch = sourcePitch;
}
}
}
[SerializeField]
[Range(-3.0f, 3.0f)]
private float sourcePitch = 1.0f;
/// Sets the priority of the audio source.
public int priority {
get { return sourcePriority; }
set {
sourcePriority = value;
if(audioSource != null) {
audioSource.priority = sourcePriority;
}
}
}
[SerializeField]
[Range(0, 256)]
private int sourcePriority = 128;
/// Sets how much this source is affected by 3D spatialization calculations (attenuation, doppler).
public float spatialBlend {
get { return sourceSpatialBlend; }
set {
sourceSpatialBlend = value;
if (audioSource != null) {
audioSource.spatialBlend = sourceSpatialBlend;
}
}
}
[SerializeField]
[Range(0.0f, 1.0f)]
private float sourceSpatialBlend = 1.0f;
/// Sets the Doppler scale for this audio source.
public float dopplerLevel {
get { return sourceDopplerLevel; }
set {
sourceDopplerLevel = value;
if(audioSource != null) {
audioSource.dopplerLevel = sourceDopplerLevel;
}
}
}
[SerializeField]
[Range(0.0f, 5.0f)]
private float sourceDopplerLevel = 1.0f;
/// Sets the spread angle (in degrees) in 3D space.
public float spread {
get { return sourceSpread; }
set {
sourceSpread = value;
if(audioSource != null) {
audioSource.spread = sourceSpread;
}
}
}
[SerializeField]
[Range(0.0f, 360.0f)]
private float sourceSpread = 0.0f;
/// Playback position in seconds.
public float time {
get {
if(audioSource != null) {
return audioSource.time;
}
return 0.0f;
}
set {
if(audioSource != null) {
audioSource.time = value;
}
}
}
/// Playback position in PCM samples.
public int timeSamples {
get {
if(audioSource != null) {
return audioSource.timeSamples;
}
return 0;
}
set {
if(audioSource != null) {
audioSource.timeSamples = value;
}
}
}
/// The volume of the audio source (0.0 to 1.0).
public float volume {
get { return sourceVolume; }
set {
sourceVolume = value;
if (audioSource != null) {
audioSource.volume = sourceVolume;
}
}
}
[SerializeField]
[Range(0.0f, 1.0f)]
private float sourceVolume = 1.0f;
/// Volume rolloff model with respect to the distance.
public AudioRolloffMode rolloffMode {
get { return sourceRolloffMode; }
set {
sourceRolloffMode = value;
if (audioSource != null) {
audioSource.rolloffMode = sourceRolloffMode;
if (rolloffMode == AudioRolloffMode.Custom) {
// Custom rolloff is not supported, set the curve for no distance attenuation.
audioSource.SetCustomCurve(AudioSourceCurveType.CustomRolloff,
AnimationCurve.Linear(sourceMinDistance, 1.0f,
sourceMaxDistance, 1.0f));
}
}
}
}
[SerializeField]
private AudioRolloffMode sourceRolloffMode = AudioRolloffMode.Logarithmic;
/// MaxDistance is the distance a sound stops attenuating at.
public float maxDistance {
get { return sourceMaxDistance; }
set {
sourceMaxDistance = Mathf.Clamp(value, sourceMinDistance + GvrAudio.distanceEpsilon,
GvrAudio.maxDistanceLimit);
if(audioSource != null) {
audioSource.maxDistance = sourceMaxDistance;
}
}
}
[SerializeField]
private float sourceMaxDistance = 500.0f;
/// Within the Min distance the GvrAudioSource will cease to grow louder in volume.
public float minDistance {
get { return sourceMinDistance; }
set {
sourceMinDistance = Mathf.Clamp(value, 0.0f, GvrAudio.minDistanceLimit);
if(audioSource != null) {
audioSource.minDistance = sourceMinDistance;
}
}
}
[SerializeField]
private float sourceMinDistance = 1.0f;
/// Binaural (HRTF) rendering toggle.
[SerializeField]
private bool hrtfEnabled = true;
// Unity audio source attached to the game object.
[SerializeField]
private AudioSource audioSource = null;
// Unique source id.
private int id = -1;
// Current occlusion value;
private float currentOcclusion = 0.0f;
// Next occlusion update time in seconds.
private float nextOcclusionUpdate = 0.0f;
// Denotes whether the source is currently paused or not.
private bool isPaused = false;
void Awake () {
#if UNITY_EDITOR && UNITY_2017_1_OR_NEWER
Debug.LogWarningFormat(gameObject,
"Game object '{0}' uses deprecated {1} component.\nPlease upgrade to Resonance Audio ({2}).",
name, GetType().Name, "https://developers.google.com/resonance-audio/migrate");
#endif // UNITY_EDITOR && UNITY_2017_1_OR_NEWER
if (audioSource == null) {
// Ensure the audio source gets created once.
audioSource = gameObject.AddComponent<AudioSource>();
}
audioSource.enabled = false;
audioSource.hideFlags = HideFlags.HideInInspector | HideFlags.HideAndDontSave;
audioSource.playOnAwake = false;
audioSource.bypassReverbZones = true;
#if UNITY_5_5_OR_NEWER
audioSource.spatializePostEffects = true;
#endif // UNITY_5_5_OR_NEWER
OnValidate();
// Route the source output to |GvrAudioMixer|.
AudioMixer mixer = (Resources.Load("GvrAudioMixer") as AudioMixer);
if(mixer != null) {
audioSource.outputAudioMixerGroup = mixer.FindMatchingGroups("Master")[0];
} else {
Debug.LogError("GVRAudioMixer could not be found in Resources. Make sure that the GVR SDK " +
"Unity package is imported properly.");
}
}
void OnEnable () {
audioSource.enabled = true;
if (playOnAwake && !isPlaying && InitializeSource()) {
Play();
}
}
void Start () {
if (playOnAwake && !isPlaying) {
Play();
}
}
void OnDisable () {
Stop();
audioSource.enabled = false;
}
void OnDestroy () {
Destroy(audioSource);
}
void OnApplicationPause (bool pauseStatus) {
if (pauseStatus) {
Pause();
} else {
UnPause();
}
}
void Update () {
// Update occlusion state.
if (!occlusionEnabled) {
currentOcclusion = 0.0f;
} else if (Time.time >= nextOcclusionUpdate) {
nextOcclusionUpdate = Time.time + GvrAudio.occlusionDetectionInterval;
currentOcclusion = GvrAudio.ComputeOcclusion(transform);
}
// Update source.
if (!isPlaying && !isPaused) {
Stop();
} else {
audioSource.SetSpatializerFloat((int) GvrAudio.SpatializerData.Gain,
GvrAudio.ConvertAmplitudeFromDb(gainDb));
audioSource.SetSpatializerFloat((int) GvrAudio.SpatializerData.MinDistance,
sourceMinDistance);
GvrAudio.UpdateAudioSource(id, this, currentOcclusion);
}
}
/// Provides a block of the currently playing source's output data.
///
/// @note The array given in samples will be filled with the requested data before spatialization.
public void GetOutputData(float[] samples, int channel) {
if (audioSource != null) {
audioSource.GetOutputData(samples, channel);
}
}
/// Provides a block of the currently playing audio source's spectrum data.
///
/// @note The array given in samples will be filled with the requested data before spatialization.
public void GetSpectrumData(float[] samples, int channel, FFTWindow window) {
if (audioSource != null) {
audioSource.GetSpectrumData(samples, channel, window);
}
}
/// Pauses playing the clip.
public void Pause () {
if (audioSource != null) {
isPaused = true;
audioSource.Pause();
}
}
/// Plays the clip.
public void Play () {
if (audioSource != null && InitializeSource()) {
audioSource.Play();
isPaused = false;
} else {
Debug.LogWarning ("GVR Audio source not initialized. Audio playback not supported " +
"until after Awake() and OnEnable(). Try calling from Start() instead.");
}
}
/// Plays the clip with a delay specified in seconds.
public void PlayDelayed (float delay) {
if (audioSource != null && InitializeSource()) {
audioSource.PlayDelayed(delay);
isPaused = false;
} else {
Debug.LogWarning ("GVR Audio source not initialized. Audio playback not supported " +
"until after Awake() and OnEnable(). Try calling from Start() instead.");
}
}
/// Plays an AudioClip.
public void PlayOneShot (AudioClip clip) {
PlayOneShot(clip, 1.0f);
}
/// Plays an AudioClip, and scales its volume.
public void PlayOneShot (AudioClip clip, float volume) {
if (audioSource != null && InitializeSource()) {
audioSource.PlayOneShot(clip, volume);
isPaused = false;
} else {
Debug.LogWarning ("GVR Audio source not initialized. Audio playback not supported " +
"until after Awake() and OnEnable(). Try calling from Start() instead.");
}
}
/// Plays the clip at a specific time on the absolute time-line that AudioSettings.dspTime reads
/// from.
public void PlayScheduled (double time) {
if (audioSource != null && InitializeSource()) {
audioSource.PlayScheduled(time);
isPaused = false;
} else {
Debug.LogWarning ("GVR Audio source not initialized. Audio playback not supported " +
"until after Awake() and OnEnable(). Try calling from Start() instead.");
}
}
/// Changes the time at which a sound that has already been scheduled to play will end.
public void SetScheduledEndTime(double time) {
if (audioSource != null) {
audioSource.SetScheduledEndTime(time);
}
}
/// Changes the time at which a sound that has already been scheduled to play will start.
public void SetScheduledStartTime(double time) {
if (audioSource != null) {
audioSource.SetScheduledStartTime(time);
}
}
/// Stops playing the clip.
public void Stop () {
if (audioSource != null) {
audioSource.Stop();
ShutdownSource();
isPaused = true;
}
}
/// Unpauses the paused playback.
public void UnPause () {
if (audioSource != null) {
audioSource.UnPause();
isPaused = false;
}
}
// Initializes the source.
private bool InitializeSource () {
if (id < 0) {
id = GvrAudio.CreateAudioSource(hrtfEnabled);
if (id >= 0) {
GvrAudio.UpdateAudioSource(id, this, currentOcclusion);
audioSource.spatialize = true;
audioSource.SetSpatializerFloat((int) GvrAudio.SpatializerData.Type,
(float) GvrAudio.SpatializerType.Source);
audioSource.SetSpatializerFloat((int) GvrAudio.SpatializerData.Gain,
GvrAudio.ConvertAmplitudeFromDb(gainDb));
audioSource.SetSpatializerFloat((int) GvrAudio.SpatializerData.MinDistance,
sourceMinDistance);
audioSource.SetSpatializerFloat((int) GvrAudio.SpatializerData.ZeroOutput, 0.0f);
// Source id must be set after all the spatializer parameters, to ensure that the source is
// properly initialized before processing.
audioSource.SetSpatializerFloat((int) GvrAudio.SpatializerData.Id, (float) id);
}
}
return id >= 0;
}
// Shuts down the source.
private void ShutdownSource () {
if (id >= 0) {
audioSource.SetSpatializerFloat((int) GvrAudio.SpatializerData.Id, -1.0f);
// Ensure that the output is zeroed after shutdown.
audioSource.SetSpatializerFloat((int) GvrAudio.SpatializerData.ZeroOutput, 1.0f);
audioSource.spatialize = false;
GvrAudio.DestroyAudioSource(id);
id = -1;
}
}
void OnDidApplyAnimationProperties () {
OnValidate();
}
void OnValidate () {
clip = sourceClip;
loop = sourceLoop;
mute = sourceMute;
pitch = sourcePitch;
priority = sourcePriority;
spatialBlend = sourceSpatialBlend;
volume = sourceVolume;
dopplerLevel = sourceDopplerLevel;
spread = sourceSpread;
minDistance = sourceMinDistance;
maxDistance = sourceMaxDistance;
rolloffMode = sourceRolloffMode;
}
void OnDrawGizmosSelected () {
// Draw listener directivity gizmo.
// Note that this is a very suboptimal way of finding the component, to be used in Unity Editor
// only, should not be used to access the component in run time.
GvrAudioListener listener = FindObjectOfType<GvrAudioListener>();
if(listener != null) {
Gizmos.color = GvrAudio.listenerDirectivityColor;
DrawDirectivityGizmo(listener.transform, listenerDirectivityAlpha,
listenerDirectivitySharpness, 180);
}
// Draw source directivity gizmo.
Gizmos.color = GvrAudio.sourceDirectivityColor;
DrawDirectivityGizmo(transform, directivityAlpha, directivitySharpness, 180);
}
// Draws a 3D gizmo in the Scene View that shows the selected directivity pattern.
private void DrawDirectivityGizmo (Transform target, float alpha, float sharpness,
int resolution) {
Vector2[] points = GvrAudio.Generate2dPolarPattern(alpha, sharpness, resolution);
// Compute |vertices| from the polar pattern |points|.
int numVertices = resolution + 1;
Vector3[] vertices = new Vector3[numVertices];
vertices[0] = Vector3.zero;
for (int i = 0; i < points.Length; ++i) {
vertices[i + 1] = new Vector3(points[i].x, 0.0f, points[i].y);
}
// Generate |triangles| from |vertices|. Two triangles per each sweep to avoid backface culling.
int[] triangles = new int[6 * numVertices];
for (int i = 0; i < numVertices - 1; ++i) {
int index = 6 * i;
if (i < numVertices - 2) {
triangles[index] = 0;
triangles[index + 1] = i + 1;
triangles[index + 2] = i + 2;
} else {
// Last vertex is connected back to the first for the last triangle.
triangles[index] = 0;
triangles[index + 1] = numVertices - 1;
triangles[index + 2] = 1;
}
// The second triangle facing the opposite direction.
triangles[index + 3] = triangles[index];
triangles[index + 4] = triangles[index + 2];
triangles[index + 5] = triangles[index + 1];
}
// Construct a new mesh for the gizmo.
Mesh directivityGizmoMesh = new Mesh();
directivityGizmoMesh.hideFlags = HideFlags.DontSaveInEditor;
directivityGizmoMesh.vertices = vertices;
directivityGizmoMesh.triangles = triangles;
directivityGizmoMesh.RecalculateNormals();
// Draw the mesh.
Vector3 scale = 2.0f * Mathf.Max(target.lossyScale.x, target.lossyScale.z) * Vector3.one;
Gizmos.DrawMesh(directivityGizmoMesh, target.position, target.rotation, scale);
}
}
#pragma warning restore 0618 // Restore warnings

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6dbca64e524ea44f9b26142ec59aca8a
timeCreated: 1447961362
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: