feat: added fmod

This commit is contained in:
Gerard Gascón 2024-04-17 23:19:16 +02:00
parent c803300dce
commit 3471c31c32
416 changed files with 39455 additions and 171 deletions

View file

@ -0,0 +1,15 @@
{
"name": "FMODUnityResonance",
"references": [
"FMODUnity"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 44d09cf463b68274884d8a3c8a94e528
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,290 @@
// Copyright 2017 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.Runtime.InteropServices;
using FMODUnity;
namespace FMODUnityResonance
{
/// This is the main Resonance Audio class that communicates with the FMOD Unity integration. Native
/// functions of the system can only be called through this class to preserve the internal system
/// functionality.
public static class FmodResonanceAudio
{
/// 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;
// Right-handed to left-handed matrix converter (and vice versa).
private static readonly Matrix4x4 flipZ = Matrix4x4.Scale(new Vector3(1, 1, -1));
// Get a handle to the Resonance Audio Listener FMOD Plugin.
private static readonly string listenerPluginName = "Resonance Audio Listener";
// Size of |RoomProperties| struct in bytes.
private static readonly int roomPropertiesSize = FMOD.MarshalHelper.SizeOf(typeof(RoomProperties));
// Plugin data parameter index for the room properties.
private static readonly int roomPropertiesIndex = 1;
// 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<FmodResonanceAudioRoom> enabledRooms = new List<FmodResonanceAudioRoom>();
// Current listener position.
private static FMOD.VECTOR listenerPositionFmod = new FMOD.VECTOR();
// FMOD Resonance Audio Listener Plugin.
private static FMOD.DSP listenerPlugin;
/// 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(FmodResonanceAudioRoom 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 (enabledRooms.Count > 0)
{
FmodResonanceAudioRoom currentRoom = enabledRooms[enabledRooms.Count - 1];
RoomProperties roomProperties = GetRoomProperties(currentRoom);
// Pass the room properties into a pointer.
IntPtr roomPropertiesPtr = Marshal.AllocHGlobal(roomPropertiesSize);
Marshal.StructureToPtr(roomProperties, roomPropertiesPtr, false);
ListenerPlugin.setParameterData(roomPropertiesIndex, GetBytes(roomPropertiesPtr,
roomPropertiesSize));
Marshal.FreeHGlobal(roomPropertiesPtr);
}
else
{
// Set the room properties to a null room, which will effectively disable the room effects.
ListenerPlugin.setParameterData(roomPropertiesIndex, GetBytes(IntPtr.Zero, 0));
}
}
/// Returns whether the listener is currently inside the given |room| boundaries.
public static bool IsListenerInsideRoom(FmodResonanceAudioRoom room)
{
// Compute the room position relative to the listener.
FMOD.VECTOR unused;
RuntimeManager.CoreSystem.get3DListenerAttributes(0, out listenerPositionFmod, out unused,
out unused, out unused);
Vector3 listenerPosition = new Vector3(listenerPositionFmod.x, listenerPositionFmod.y,
listenerPositionFmod.z);
Vector3 relativePosition = listenerPosition - room.transform.position;
Quaternion rotationInverse = Quaternion.Inverse(room.transform.rotation);
// Set the size of the room as the boundary and return whether the listener is inside.
bounds.size = Vector3.Scale(room.transform.lossyScale, room.Size);
return bounds.Contains(rotationInverse * relativePosition);
}
[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 FmodResonanceAudioRoom.SurfaceMaterial MaterialLeft;
public FmodResonanceAudioRoom.SurfaceMaterial MaterialRight;
public FmodResonanceAudioRoom.SurfaceMaterial MaterialBottom;
public FmodResonanceAudioRoom.SurfaceMaterial MaterialTop;
public FmodResonanceAudioRoom.SurfaceMaterial MaterialFront;
public FmodResonanceAudioRoom.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;
};
// Returns the FMOD Resonance Audio Listener Plugin.
private static FMOD.DSP ListenerPlugin
{
get
{
if (!listenerPlugin.hasHandle())
{
listenerPlugin = Initialize();
}
return listenerPlugin;
}
}
// Converts given |db| value to its amplitude equivalent where 'dB = 20 * log10(amplitude)'.
private static float ConvertAmplitudeFromDb(float db)
{
return Mathf.Pow(10.0f, 0.05f * db);
}
// Converts given |position| and |rotation| from Unity space to audio space.
private static void ConvertAudioTransformFromUnity(ref Vector3 position,
ref Quaternion rotation)
{
// Compose the transformation matrix.
Matrix4x4 transformMatrix = Matrix4x4.TRS(position, rotation, Vector3.one);
// Convert the transformation matrix from left-handed to right-handed.
transformMatrix = flipZ * transformMatrix * flipZ;
// Update |position| and |rotation| respectively.
position = transformMatrix.GetColumn(3);
rotation = Quaternion.LookRotation(transformMatrix.GetColumn(2), transformMatrix.GetColumn(1));
}
// Returns a byte array of |length| created from |ptr|.
private static byte[] GetBytes(IntPtr ptr, int length)
{
if (ptr != IntPtr.Zero)
{
byte[] byteArray = new byte[length];
Marshal.Copy(ptr, byteArray, 0, length);
return byteArray;
}
// Return an empty array if the pointer is null.
return new byte[1];
}
// Returns room properties of the given |room|.
private static RoomProperties GetRoomProperties(FmodResonanceAudioRoom 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;
}
// Initializes and returns the FMOD Resonance Audio Listener Plugin.
private static FMOD.DSP Initialize()
{
// Search through all busses on in banks.
int numBanks = 0;
FMOD.DSP dsp = new FMOD.DSP();
FMOD.Studio.Bank[] banks = null;
RuntimeManager.StudioSystem.getBankCount(out numBanks);
RuntimeManager.StudioSystem.getBankList(out banks);
for (int currentBank = 0; currentBank < numBanks; ++currentBank)
{
int numBusses = 0;
FMOD.Studio.Bus[] busses = null;
banks[currentBank].getBusCount(out numBusses);
banks[currentBank].getBusList(out busses);
for (int currentBus = 0; currentBus < numBusses; ++currentBus)
{
// Make sure the channel group of the current bus is assigned properly.
string busPath = null;
busses[currentBus].getPath(out busPath);
RuntimeManager.StudioSystem.getBus(busPath, out busses[currentBus]);
busses[currentBus].lockChannelGroup();
RuntimeManager.StudioSystem.flushCommands();
FMOD.ChannelGroup channelGroup;
busses[currentBus].getChannelGroup(out channelGroup);
if (channelGroup.hasHandle())
{
int numDsps = 0;
channelGroup.getNumDSPs(out numDsps);
for (int currentDsp = 0; currentDsp < numDsps; ++currentDsp)
{
channelGroup.getDSP(currentDsp, out dsp);
string dspNameSb;
int unusedInt = 0;
uint unusedUint = 0;
dsp.getInfo(out dspNameSb, out unusedUint, out unusedInt, out unusedInt, out unusedInt);
if (dspNameSb.ToString().Equals(listenerPluginName) && dsp.hasHandle())
{
return dsp;
}
}
}
busses[currentBus].unlockChannelGroup();
}
}
RuntimeUtils.DebugLogError(listenerPluginName + " not found in the FMOD project.");
return dsp;
}
}
}

View file

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

View file

@ -0,0 +1,121 @@
// Copyright 2017 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.Serialization;
using System.Collections;
namespace FMODUnityResonance
{
/// Resonance Audio room component that simulates environmental effects of a room with respect to
/// the properties of the attached game object.
[AddComponentMenu("ResonanceAudio/FmodResonanceAudioRoom")]
public class FmodResonanceAudioRoom : 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.
[FormerlySerializedAs("leftWall")]
public SurfaceMaterial LeftWall = SurfaceMaterial.ConcreteBlockCoarse;
/// Room surface material in positive x direction.
[FormerlySerializedAs("rightWall")]
public SurfaceMaterial RightWall = SurfaceMaterial.ConcreteBlockCoarse;
/// Room surface material in negative y direction.
[FormerlySerializedAs("floor")]
public SurfaceMaterial Floor = SurfaceMaterial.ParquetOnConcrete;
/// Room surface material in positive y direction.
[FormerlySerializedAs("ceiling")]
public SurfaceMaterial Ceiling = SurfaceMaterial.PlasterRough;
/// Room surface material in negative z direction.
[FormerlySerializedAs("backWall")]
public SurfaceMaterial BackWall = SurfaceMaterial.ConcreteBlockCoarse;
/// Room surface material in positive z direction.
[FormerlySerializedAs("frontWall")]
public SurfaceMaterial FrontWall = SurfaceMaterial.ConcreteBlockCoarse;
/// Reflectivity scalar for each surface of the room.
[FormerlySerializedAs("reflectivity")]
public float Reflectivity = 1.0f;
/// Reverb gain modifier in decibels.
[FormerlySerializedAs("reverbGainDb")]
public float ReverbGainDb = 0.0f;
/// Reverb brightness modifier.
[FormerlySerializedAs("reverbBrightness")]
public float ReverbBrightness = 0.0f;
/// Reverb time modifier.
[FormerlySerializedAs("reverbTime")]
public float ReverbTime = 1.0f;
/// Size of the room (normalized with respect to scale of the game object).
[FormerlySerializedAs("size")]
public Vector3 Size = Vector3.one;
private void OnEnable()
{
FmodResonanceAudio.UpdateAudioRoom(this, FmodResonanceAudio.IsListenerInsideRoom(this));
}
private void OnDisable()
{
FmodResonanceAudio.UpdateAudioRoom(this, false);
}
private void Update()
{
FmodResonanceAudio.UpdateAudioRoom(this, FmodResonanceAudio.IsListenerInsideRoom(this));
}
private void OnDrawGizmosSelected()
{
// Draw shoebox model wireframe of the room.
Gizmos.color = Color.yellow;
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawWireCube(Vector3.zero, Size);
}
}
}

View file

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