diff --git a/ProjectObsidian/ProtoFlux/Audio/AudioAdder.cs b/ProjectObsidian/ProtoFlux/Audio/AudioAdder.cs index 8374002..fb6479d 100644 --- a/ProjectObsidian/ProtoFlux/Audio/AudioAdder.cs +++ b/ProjectObsidian/ProtoFlux/Audio/AudioAdder.cs @@ -108,6 +108,7 @@ protected override void ProxyRemoved(AudioAdderProxy proxy, FrooxEngineContext c proxy.Slot.ActiveChanged -= _activeChangedHandler.Read(context); _enabledChangedHandler.Clear(context); _activeChangedHandler.Clear(context); + proxy.Active = false; } } @@ -133,20 +134,8 @@ public void Changed(FrooxEngineContext context) { return; } - if (!proxy.IsValid) - { - return; - } - try - { - context.World.UpdateManager.NestCurrentlyUpdating(proxy); - proxy.AudioInput = AudioInput.Evaluate(context); - proxy.AudioInput2 = AudioInput2.Evaluate(context); - } - finally - { - context.World.UpdateManager.PopCurrentlyUpdating(proxy); - } + proxy.AudioInput = AudioInput.Evaluate(context); + proxy.AudioInput2 = AudioInput2.Evaluate(context); } protected override void ComputeOutputs(FrooxEngineContext context) diff --git a/ProjectObsidian/ProtoFlux/Audio/TestAudio.cs b/ProjectObsidian/ProtoFlux/Audio/AudioMultiply.cs similarity index 53% rename from ProjectObsidian/ProtoFlux/Audio/TestAudio.cs rename to ProjectObsidian/ProtoFlux/Audio/AudioMultiply.cs index f2ed1f2..8688c5b 100644 --- a/ProjectObsidian/ProtoFlux/Audio/TestAudio.cs +++ b/ProjectObsidian/ProtoFlux/Audio/AudioMultiply.cs @@ -3,57 +3,51 @@ using ProtoFlux.Runtimes.Execution; using FrooxEngine.ProtoFlux; using FrooxEngine; +using Elements.Assets; +using Elements.Core; namespace ProtoFlux.Runtimes.Execution.Nodes.Obsidian.Audio { - public class TestAudioProxy : ProtoFluxEngineProxy + public class AudioMultiplyProxy : ProtoFluxEngineProxy, IAudioSource { - private AudioOutput _output; - private SineWaveClip _clip; - private AudioClipPlayer _player; - public readonly FieldDrive FreqDrive; - public readonly FieldDrive AmpDrive; - public bool Active - { - get { return _output.Enabled; } - set { _output.Enabled = value; } - } - public bool IsValid => _clip.FilterWorldElement() != null && FreqDrive.Target != null && FreqDrive.IsLinkValid && AmpDrive.Target != null && AmpDrive.IsLinkValid; - public float Frequency - { - get { return FreqDrive.Target.Value; } - set { FreqDrive.Target.Value = value; } - } - public float Amplitude - { - get { return AmpDrive.Target.Value; } - set { AmpDrive.Target.Value = value; } - } - protected override void OnAttach() + public IAudioSource AudioInput; + + public float Value; + + public bool Active; + + public bool IsActive => Active; + + public int ChannelCount => 1; + + public void Read(Span buffer) where S : unmanaged, IAudioSample { - _output = Slot.AttachComponent(); - _clip = Slot.AttachComponent(); - _player = Slot.AttachComponent(); - _player.Play(); - _player.Loop = true; - _player.Clip.Target = _clip; - _output.Source.Target = _player; - FreqDrive.Target = _clip.Frequency; - FreqDrive.Target.Value = 440f; - AmpDrive.Target = _clip.Amplitude; - AmpDrive.Target.Value = 1f; + Span newBuffer = stackalloc S[buffer.Length]; + newBuffer = buffer; + if (AudioInput != null) + { + AudioInput.Read(newBuffer); + } + else + { + newBuffer.Fill(default); + } + for (int i = 0; i < buffer.Length; i++) + { + newBuffer[i] = newBuffer[i].Multiply(Value); + } } } [NodeCategory("Obsidian/Audio")] - public class TestAudio : ProxyVoidNode, IExecutionChangeListener + public class AudioMultiply : ProxyVoidNode, IExecutionChangeListener { [ChangeListener] - [@DefaultValue(440f)] - public readonly ValueInput Frequency; + public readonly ObjectInput AudioInput; [ChangeListener] - [@DefaultValue(1f)] - public readonly ValueInput Amplitude; + public readonly ValueInput Value; + + public readonly ObjectOutput AudioOutput; private ObjectStore> _enabledChangedHandler; @@ -61,7 +55,7 @@ public class TestAudio : ProxyVoidNode, IExe public bool ValueListensToChanges { get; private set; } - private bool ShouldListen(TestAudioProxy proxy) + private bool ShouldListen(AudioMultiplyProxy proxy) { if (proxy.Enabled) { @@ -70,7 +64,7 @@ private bool ShouldListen(TestAudioProxy proxy) return false; } - protected override void ProxyAdded(TestAudioProxy proxy, FrooxEngineContext context) + protected override void ProxyAdded(AudioMultiplyProxy proxy, FrooxEngineContext context) { base.ProxyAdded(proxy, context); NodeContextPath path = context.CaptureContextPath(); @@ -95,9 +89,10 @@ protected override void ProxyAdded(TestAudioProxy proxy, FrooxEngineContext cont _enabledChangedHandler.Write(enabledHandler, context); _activeChangedHandler.Write(activeHandler, context); ValueListensToChanges = ShouldListen(proxy); + proxy.Active = ValueListensToChanges; } - protected override void ProxyRemoved(TestAudioProxy proxy, FrooxEngineContext context, bool inUseByAnotherInstance) + protected override void ProxyRemoved(AudioMultiplyProxy proxy, FrooxEngineContext context, bool inUseByAnotherInstance) { if (!inUseByAnotherInstance) { @@ -105,12 +100,13 @@ protected override void ProxyRemoved(TestAudioProxy proxy, FrooxEngineContext co proxy.Slot.ActiveChanged -= _activeChangedHandler.Read(context); _enabledChangedHandler.Clear(context); _activeChangedHandler.Clear(context); + proxy.Active = false; } } protected void UpdateListenerState(FrooxEngineContext context) { - TestAudioProxy proxy = GetProxy(context); + AudioMultiplyProxy proxy = GetProxy(context); if (proxy != null) { bool shouldListen = ShouldListen(proxy); @@ -125,25 +121,24 @@ protected void UpdateListenerState(FrooxEngineContext context) public void Changed(FrooxEngineContext context) { - TestAudioProxy proxy = GetProxy(context); + AudioMultiplyProxy proxy = GetProxy(context); if (proxy == null) { return; } - if (!proxy.IsValid) - { - return; - } - try - { - context.World.UpdateManager.NestCurrentlyUpdating(proxy); - proxy.Frequency = Frequency.Evaluate(context); - proxy.Amplitude = Amplitude.Evaluate(context); - } - finally - { - context.World.UpdateManager.PopCurrentlyUpdating(proxy); - } + proxy.AudioInput = AudioInput.Evaluate(context); + proxy.Value = Value.Evaluate(context); + } + + protected override void ComputeOutputs(FrooxEngineContext context) + { + AudioMultiplyProxy proxy = GetProxy(context); + AudioOutput.Write(proxy, context); + } + + public AudioMultiply() + { + AudioOutput = new ObjectOutput(this); } } } \ No newline at end of file diff --git a/ProjectObsidian/ProtoFlux/Audio/AudioSubtractor.cs b/ProjectObsidian/ProtoFlux/Audio/AudioSubtractor.cs index ef46f5d..25aed94 100644 --- a/ProjectObsidian/ProtoFlux/Audio/AudioSubtractor.cs +++ b/ProjectObsidian/ProtoFlux/Audio/AudioSubtractor.cs @@ -108,6 +108,7 @@ protected override void ProxyRemoved(AudioSubtractorProxy proxy, FrooxEngineCont proxy.Slot.ActiveChanged -= _activeChangedHandler.Read(context); _enabledChangedHandler.Clear(context); _activeChangedHandler.Clear(context); + proxy.Active = false; } } @@ -133,20 +134,8 @@ public void Changed(FrooxEngineContext context) { return; } - if (!proxy.IsValid) - { - return; - } - try - { - context.World.UpdateManager.NestCurrentlyUpdating(proxy); - proxy.AudioInput = AudioInput.Evaluate(context); - proxy.AudioInput2 = AudioInput2.Evaluate(context); - } - finally - { - context.World.UpdateManager.PopCurrentlyUpdating(proxy); - } + proxy.AudioInput = AudioInput.Evaluate(context); + proxy.AudioInput2 = AudioInput2.Evaluate(context); } protected override void ComputeOutputs(FrooxEngineContext context) diff --git a/ProjectObsidian/ProtoFlux/Audio/SineGenerator.cs b/ProjectObsidian/ProtoFlux/Audio/SineGenerator.cs index 9561730..abdc688 100644 --- a/ProjectObsidian/ProtoFlux/Audio/SineGenerator.cs +++ b/ProjectObsidian/ProtoFlux/Audio/SineGenerator.cs @@ -19,7 +19,7 @@ public class SineGeneratorProxy : ProtoFluxEngineProxy, IAudioSource public float Phase; - private float time; + public float time; private float[] tempBuffer; @@ -29,22 +29,16 @@ public class SineGeneratorProxy : ProtoFluxEngineProxy, IAudioSource public int ChannelCount => 1; - protected override void OnAwake() - { - base.OnAwake(); - Frequency = 440f; - Amplitude = 1f; - Phase = 0f; - } - + // TODO: Make this not advance time on each read + // If two things are reading this generator, it advances twice as fast public void Read(Span buffer) where S : unmanaged, IAudioSample { tempBuffer = tempBuffer.EnsureSize(buffer.Length); - time %= MathX.PI * 2f + Phase; + time %= MathX.PI * 2f; float advance = 1f / (float)base.Engine.AudioSystem.SampleRate * (MathX.PI * 2f) * (float)Frequency; for (int i = 0; i < buffer.Length; i++) { - tempBuffer[i] = MathX.Sin(time) * MathX.Clamp01(Amplitude); + tempBuffer[i] = MathX.Sin(time + Phase) * MathX.Clamp01(Amplitude); time += advance; } double position = 0.0; @@ -56,17 +50,22 @@ public void Read(Span buffer) where S : unmanaged, IAudioSample public class SineGenerator : ProxyVoidNode, IExecutionChangeListener { [ChangeListener] - [@DefaultValue(440f)] + [DefaultValueAttribute(440f)] public readonly ValueInput Frequency; [ChangeListener] - [@DefaultValue(1f)] + [DefaultValueAttribute(1f)] public readonly ValueInput Amplitude; [ChangeListener] - [@DefaultValue(0f)] + [DefaultValueAttribute(0f)] public readonly ValueInput Phase; + [PossibleContinuations(new string[] { "OnReset" })] + public readonly Operation Reset; + + public Continuation OnReset; + public readonly ObjectOutput AudioOutput; private ObjectStore> _enabledChangedHandler; @@ -120,6 +119,7 @@ protected override void ProxyRemoved(SineGeneratorProxy proxy, FrooxEngineContex proxy.Slot.ActiveChanged -= _activeChangedHandler.Read(context); _enabledChangedHandler.Clear(context); _activeChangedHandler.Clear(context); + proxy.Active = false; } } @@ -145,21 +145,9 @@ public void Changed(FrooxEngineContext context) { return; } - if (!proxy.IsValid) - { - return; - } - try - { - context.World.UpdateManager.NestCurrentlyUpdating(proxy); - proxy.Frequency = Frequency.Evaluate(context); - proxy.Amplitude = Amplitude.Evaluate(context); - proxy.Phase = Phase.Evaluate(context); - } - finally - { - context.World.UpdateManager.PopCurrentlyUpdating(proxy); - } + proxy.Frequency = Frequency.Evaluate(context, 440f); + proxy.Amplitude = Amplitude.Evaluate(context, 1f); + proxy.Phase = Phase.Evaluate(context, 0f); } protected override void ComputeOutputs(FrooxEngineContext context) @@ -168,9 +156,21 @@ protected override void ComputeOutputs(FrooxEngineContext context) AudioOutput.Write(proxy, context); } + private IOperation DoReset(FrooxEngineContext context) + { + SineGeneratorProxy proxy = GetProxy(context); + if (proxy == null) + { + return null; + } + proxy.time = 0f; + return OnReset.Target; + } + public SineGenerator() { AudioOutput = new ObjectOutput(this); + Reset = new Operation(this, 0); } } } \ No newline at end of file diff --git a/ProjectObsidian/ProtoFlux/Audio/Speaker.cs b/ProjectObsidian/ProtoFlux/Audio/Speaker.cs index cab8cb7..dce7807 100644 --- a/ProjectObsidian/ProtoFlux/Audio/Speaker.cs +++ b/ProjectObsidian/ProtoFlux/Audio/Speaker.cs @@ -8,36 +8,31 @@ namespace ProtoFlux.Runtimes.Execution.Nodes.Obsidian.Audio { public class SpeakerProxy : ProtoFluxEngineProxy { - private AudioOutput _output; + public readonly FieldDrive ActiveDrive; + public readonly FieldDrive VolDrive; + public readonly DriveRef> SourceDrive; public bool Active { - get { return Output?.Enabled ?? false; } - set { if (Output != null) Output.Enabled = value; } + get { return ActiveDrive.Target?.Value ?? false; } + set { if (ActiveDrive.Target != null && ActiveDrive.IsLinkValid) ActiveDrive.Target.Value = value; } } public float Volume { - get { return Output?.Volume.Value ?? 0f; } - set { if (Output != null) Output.Volume.Value = value; } + get { return VolDrive.Target?.Value ?? 0f; } + set { if (VolDrive.Target != null && VolDrive.IsLinkValid) VolDrive.Target.Value = value; } } public IAudioSource Source { - get { return Output?.Source.Target; } - set { if (Output != null) Output.Source.Target = value; } - } - public AudioOutput Output - { - get - { - if (_output == null) - { - _output = Slot.GetComponent(); - } - return _output; - } + get { return SourceDrive.Target?.Target; } + set { if (SourceDrive.Target != null && SourceDrive.IsLinkValid) SourceDrive.Target.Target = value; } } protected override void OnAttach() { - _output = Slot.AttachComponent(); + var output = Slot.AttachComponent(); + ActiveDrive.Target = output.EnabledField; + VolDrive.Target = output.Volume; + SourceDrive.Target = output.Source; + VolDrive.Target.Value = 1f; } } [NodeCategory("Obsidian/Audio")] @@ -47,6 +42,7 @@ public class Speaker : ProxyVoidNode, IExecuti public readonly ObjectInput Source; [ChangeListener] + [DefaultValueAttribute(1f)] public readonly ValueInput Volume; private ObjectStore> _enabledChangedHandler; @@ -89,7 +85,15 @@ protected override void ProxyAdded(SpeakerProxy proxy, FrooxEngineContext contex _enabledChangedHandler.Write(enabledHandler, context); _activeChangedHandler.Write(activeHandler, context); ValueListensToChanges = ShouldListen(proxy); - proxy.Active = ValueListensToChanges; + try + { + context.World.UpdateManager.NestCurrentlyUpdating(proxy); + proxy.Active = ValueListensToChanges; + } + finally + { + context.World.UpdateManager.PopCurrentlyUpdating(proxy); + } } protected override void ProxyRemoved(SpeakerProxy proxy, FrooxEngineContext context, bool inUseByAnotherInstance) @@ -100,6 +104,15 @@ protected override void ProxyRemoved(SpeakerProxy proxy, FrooxEngineContext cont proxy.Slot.ActiveChanged -= _activeChangedHandler.Read(context); _enabledChangedHandler.Clear(context); _activeChangedHandler.Clear(context); + try + { + context.World.UpdateManager.NestCurrentlyUpdating(proxy); + proxy.Active = false; + } + finally + { + context.World.UpdateManager.PopCurrentlyUpdating(proxy); + } } } @@ -113,7 +126,15 @@ protected void UpdateListenerState(FrooxEngineContext context) { ValueListensToChanges = shouldListen; context.Group.MarkChangeTrackingDirty(); - proxy.Active = shouldListen; + try + { + context.World.UpdateManager.NestCurrentlyUpdating(proxy); + proxy.Active = shouldListen; + } + finally + { + context.World.UpdateManager.PopCurrentlyUpdating(proxy); + } } } } @@ -125,15 +146,11 @@ public void Changed(FrooxEngineContext context) { return; } - if (!proxy.IsValid) - { - return; - } try { context.World.UpdateManager.NestCurrentlyUpdating(proxy); proxy.Source = Source.Evaluate(context); - proxy.Volume = Volume.Evaluate(context); + proxy.Volume = Volume.Evaluate(context, 1f); } finally {