mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
Fix instrument pausing when outside PVS range (#6113)
This commit is contained in:
committed by
GitHub
parent
c3f4b9bd67
commit
9f0dad80e4
@@ -42,7 +42,7 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
[Dependency] private readonly IRuntimeLog _runtime = default!;
|
||||
|
||||
private AudioSystem _audioSys = default!;
|
||||
private SharedPhysicsSystem _broadPhaseSystem = default!;
|
||||
private SharedPhysicsSystem _physics = default!;
|
||||
private SharedTransformSystem _xformSystem = default!;
|
||||
|
||||
public IReadOnlyList<IMidiRenderer> Renderers
|
||||
@@ -81,7 +81,7 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
private Thread? _midiThread;
|
||||
private ISawmill _midiSawmill = default!;
|
||||
private float _gain = 0f;
|
||||
private bool _volumeDirty = true;
|
||||
private bool _gainDirty = true;
|
||||
|
||||
// Not reliable until Fluidsynth is initialized!
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
@@ -96,7 +96,7 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
return;
|
||||
|
||||
_cfgMan.SetCVar(CVars.MidiVolume, clamped);
|
||||
_volumeDirty = true;
|
||||
_gainDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,8 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
"/usr/share/sounds/sf2/TimGM6mb.sf2",
|
||||
};
|
||||
|
||||
private static readonly string WindowsSoundfont = $@"{Environment.GetEnvironmentVariable("SystemRoot")}\system32\drivers\gm.dls";
|
||||
private static readonly string WindowsSoundfont =
|
||||
$@"{Environment.GetEnvironmentVariable("SystemRoot")}\system32\drivers\gm.dls";
|
||||
|
||||
private const string OsxSoundfont =
|
||||
"/System/Library/Components/CoreAudio.component/Contents/Resources/gs_instruments.dls";
|
||||
@@ -145,11 +146,13 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
{
|
||||
if (FluidsynthInitialized || _failedInitialize) return;
|
||||
|
||||
_cfgMan.OnValueChanged(CVars.MidiVolume, value =>
|
||||
{
|
||||
_gain = value;
|
||||
_volumeDirty = true;
|
||||
}, true);
|
||||
_cfgMan.OnValueChanged(CVars.MidiVolume,
|
||||
value =>
|
||||
{
|
||||
_gain = value;
|
||||
_gainDirty = true;
|
||||
},
|
||||
true);
|
||||
|
||||
_midiSawmill = _logger.GetSawmill("midi");
|
||||
#if DEBUG
|
||||
@@ -167,13 +170,15 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
// not a directory, preserve the old file and create an actual directory
|
||||
else if (!_resourceManager.UserData.IsDir(CustomSoundfontDirectory))
|
||||
{
|
||||
_resourceManager.UserData.Rename(CustomSoundfontDirectory, CustomSoundfontDirectory.WithName(CustomSoundfontDirectory.Filename + ".old"));
|
||||
_resourceManager.UserData.Rename(CustomSoundfontDirectory,
|
||||
CustomSoundfontDirectory.WithName(CustomSoundfontDirectory.Filename + ".old"));
|
||||
_resourceManager.UserData.CreateDir(CustomSoundfontDirectory);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
NFluidsynth.Logger.SetLoggerMethod(_loggerDelegate); // Will cause a safe DllNotFoundException if not available.
|
||||
NFluidsynth.Logger
|
||||
.SetLoggerMethod(_loggerDelegate); // Will cause a safe DllNotFoundException if not available.
|
||||
|
||||
_settings = new Settings();
|
||||
_settings["synth.sample-rate"].DoubleValue = 44100;
|
||||
@@ -193,7 +198,7 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
//_settings["synth.verbose"].IntValue = 1; // Useful for debugging.
|
||||
|
||||
var midiParallel = _cfgMan.GetCVar(CVars.MidiParallelism);
|
||||
_settings["synth.polyphony"].IntValue = Math.Clamp(1024 + (int)(Math.Log2(midiParallel) * 2048), 1, 65535);
|
||||
_settings["synth.polyphony"].IntValue = Math.Clamp(1024 + (int) (Math.Log2(midiParallel) * 2048), 1, 65535);
|
||||
_settings["synth.cpu-cores"].IntValue = Math.Clamp(midiParallel, 1, 256);
|
||||
|
||||
_midiSawmill.Debug($"Synth Cores: {_settings["synth.cpu-cores"].IntValue}");
|
||||
@@ -219,7 +224,7 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
};
|
||||
|
||||
_audioSys = _entityManager.EntitySysManager.GetEntitySystem<AudioSystem>();
|
||||
_broadPhaseSystem = _entityManager.EntitySysManager.GetEntitySystem<SharedPhysicsSystem>();
|
||||
_physics = _entityManager.EntitySysManager.GetEntitySystem<SharedPhysicsSystem>();
|
||||
_xformSystem = _entityManager.System<SharedTransformSystem>();
|
||||
_entityManager.GetEntityQuery<PhysicsComponent>();
|
||||
_entityManager.GetEntityQuery<TransformComponent>();
|
||||
@@ -263,7 +268,8 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
{
|
||||
soundfontLoader.SetCallbacks(_soundfontLoaderCallbacks);
|
||||
|
||||
var renderer = new MidiRenderer(_settings!, soundfontLoader, mono, this, _audio, _taskManager, _midiSawmill);
|
||||
var renderer =
|
||||
new MidiRenderer(_settings!, soundfontLoader, mono, this, _audio, _taskManager, _midiSawmill);
|
||||
|
||||
LoadSoundFontSetup(renderer);
|
||||
|
||||
@@ -273,6 +279,7 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
{
|
||||
_renderers.Add(renderer);
|
||||
}
|
||||
|
||||
return renderer;
|
||||
}
|
||||
finally
|
||||
@@ -309,99 +316,23 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
|
||||
_updateSemaphore.Release();
|
||||
|
||||
_volumeDirty = false;
|
||||
_gainDirty = false;
|
||||
}
|
||||
|
||||
private void UpdateRenderer(IMidiRenderer renderer, MapCoordinates listener)
|
||||
{
|
||||
// TODO: This should be sharing more code with AudioSystem.
|
||||
try
|
||||
{
|
||||
if (renderer.Disposed)
|
||||
return;
|
||||
|
||||
if (_volumeDirty)
|
||||
{
|
||||
renderer.Source.Gain = Gain;
|
||||
}
|
||||
|
||||
if (!renderer.Mono)
|
||||
{
|
||||
renderer.Source.Global = true;
|
||||
return;
|
||||
}
|
||||
|
||||
MapCoordinates mapPos;
|
||||
|
||||
if (renderer.TrackingEntity is {} trackedEntity && !_entityManager.Deleted(trackedEntity))
|
||||
{
|
||||
renderer.TrackingCoordinates = _xformSystem.GetMapCoordinates(renderer.TrackingEntity.Value);
|
||||
|
||||
// Pause it if the attached entity is paused.
|
||||
if (_entityManager.IsPaused(renderer.TrackingEntity))
|
||||
{
|
||||
renderer.Source.Pause();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (renderer.TrackingCoordinates == null)
|
||||
{
|
||||
renderer.Source.Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
mapPos = renderer.TrackingCoordinates.Value;
|
||||
|
||||
// If it's on a different map then just mute it, not pause.
|
||||
if (mapPos.MapId == MapId.Nullspace || mapPos.MapId != listener.MapId)
|
||||
{
|
||||
renderer.Source.Gain = 0f;
|
||||
return;
|
||||
}
|
||||
|
||||
// Was previously muted maybe so try unmuting it?
|
||||
if (renderer.Source.Gain == 0f)
|
||||
{
|
||||
renderer.Source.Gain = Gain;
|
||||
}
|
||||
|
||||
var worldPos = mapPos.Position;
|
||||
var delta = worldPos - listener.Position;
|
||||
var distance = delta.Length();
|
||||
|
||||
// Update position
|
||||
// Out of range so just clip it for us.
|
||||
if (distance > renderer.Source.MaxDistance)
|
||||
{
|
||||
// Still keeps the source playing, just with no volume.
|
||||
renderer.Source.Gain = 0f;
|
||||
return;
|
||||
}
|
||||
|
||||
// Same imprecision suppression as audiosystem.
|
||||
if (distance > 0f && distance < 0.01f)
|
||||
{
|
||||
worldPos = listener.Position;
|
||||
delta = Vector2.Zero;
|
||||
distance = 0f;
|
||||
}
|
||||
|
||||
renderer.Source.Position = worldPos;
|
||||
|
||||
// Update velocity (doppler).
|
||||
if (!_entityManager.Deleted(renderer.TrackingEntity))
|
||||
{
|
||||
var velocity = _broadPhaseSystem.GetMapLinearVelocity(renderer.TrackingEntity.Value);
|
||||
renderer.Source.Velocity = velocity;
|
||||
}
|
||||
if (!renderer.Source.Global)
|
||||
UpdateLocalRenderer(renderer, listener);
|
||||
else
|
||||
{
|
||||
renderer.Source.Velocity = Vector2.Zero;
|
||||
}
|
||||
|
||||
// Update occlusion
|
||||
var occlusion = _audioSys.GetOcclusion(listener, delta, distance, renderer.TrackingEntity);
|
||||
renderer.Source.Occlusion = occlusion;
|
||||
UpdateGlobalRenderer(renderer);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -409,6 +340,58 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLocalRenderer(IMidiRenderer renderer, MapCoordinates listener)
|
||||
{
|
||||
if (_entityManager.Deleted(renderer.TrackingEntity) || _entityManager.IsPaused(renderer.TrackingEntity))
|
||||
{
|
||||
renderer.Source.Gain = 0f;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
MapCoordinates mapCoords = _xformSystem.GetMapCoordinates(renderer.TrackingEntity.Value);
|
||||
renderer.TrackingCoordinates = mapCoords;
|
||||
|
||||
if (mapCoords.MapId == MapId.Nullspace || mapCoords.MapId != listener.MapId)
|
||||
{
|
||||
renderer.Source.Gain = 0f;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 mapPosition = mapCoords.Position;
|
||||
Vector2 listenerDelta = mapPosition - listener.Position;
|
||||
var listenerDeltaLength = listenerDelta.Length();
|
||||
|
||||
if (listenerDeltaLength > renderer.Source.MaxDistance)
|
||||
{
|
||||
renderer.Source.Gain = 0f;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (listenerDeltaLength is > 0f and < 0.01f)
|
||||
{
|
||||
mapPosition = listener.Position;
|
||||
listenerDelta = Vector2.Zero;
|
||||
listenerDeltaLength = 0f;
|
||||
}
|
||||
|
||||
if (_gainDirty || renderer.Source.Gain == 0f)
|
||||
renderer.Source.Gain = Gain;
|
||||
|
||||
renderer.Source.Position = mapPosition;
|
||||
renderer.Source.Velocity = _physics.GetMapLinearVelocity(renderer.TrackingEntity.Value);
|
||||
renderer.Source.Occlusion =
|
||||
_audioSys.GetOcclusion(listener, listenerDelta, listenerDeltaLength, renderer.TrackingEntity);
|
||||
}
|
||||
|
||||
private void UpdateGlobalRenderer(IMidiRenderer renderer)
|
||||
{
|
||||
if (_gainDirty)
|
||||
renderer.Source.Gain = Gain;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main method for the thread rendering the midi audio.
|
||||
/// </summary>
|
||||
@@ -428,7 +411,7 @@ internal sealed partial class MidiManager : IMidiManager
|
||||
{
|
||||
if (!renderer.Disposed)
|
||||
{
|
||||
if (renderer.Master is { Disposed: true })
|
||||
if (renderer.Master is {Disposed: true})
|
||||
renderer.Master = null;
|
||||
|
||||
renderer.Render();
|
||||
|
||||
Reference in New Issue
Block a user