Skip to content

Commit

Permalink
Merge pull request #68 from Nytra/audioWork
Browse files Browse the repository at this point in the history
Add ADSR Envelope node and adjust frequency modulator's modulation range
  • Loading branch information
Xlinka authored Dec 30, 2024
2 parents bac01eb + 12cb151 commit 6e7b125
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 3 deletions.
6 changes: 3 additions & 3 deletions ProjectObsidian/Components/Audio/FrequencyModulator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Obsidian.Components.Audio
[Category(new string[] { "Obsidian/Audio" })]
public class FrequencyModulator : Component, IAudioSource, IWorldElement
{
[Range(0f, 1000f, "0.00")]
[Range(0f, 5f, "0.00")]
public readonly Sync<float> ModulationIndex;

public readonly SyncRef<IAudioSource> CarrierSource;
Expand Down Expand Up @@ -35,7 +35,7 @@ public int ChannelCount
protected override void OnAwake()
{
base.OnAwake();
ModulationIndex.Value = 100f; // Default modulation index
ModulationIndex.Value = 1f; // Default modulation index
}

public void Read<S>(Span<S> buffer) where S : unmanaged, IAudioSample<S>
Expand Down Expand Up @@ -74,7 +74,7 @@ public void Read<S>(Span<S> buffer) where S : unmanaged, IAudioSample<S>
float modulatedValue = (float)(carrierValue * Math.Sin(2 * Math.PI * modulationIndex * modulatorValue));

// Write modulated value to the buffer
buffer[i] = buffer[i].Bias(buffer[i].AbsoluteAmplitude - modulatedValue);
buffer[i] = buffer[i].Bias(buffer[i].AbsoluteAmplitude - modulatedValue);
}
}
}
Expand Down
75 changes: 75 additions & 0 deletions ProjectObsidian/ProtoFlux/Math/ADSR_Envelope.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System;
using ProtoFlux.Core;
using ProtoFlux.Runtimes.Execution;
using FrooxEngine.ProtoFlux;
using FrooxEngine;
using System.Threading.Tasks;
using Elements.Core;

namespace ProtoFlux.Runtimes.Execution.Nodes.Obsidian.Math
{
[NodeCategory("Obsidian/Math")]
public class ADSR_Envelope : AsyncActionNode<FrooxEngineContext>
{
public readonly ValueInput<float> AttackTime;
public readonly ValueInput<float> DecayTime;
public readonly ValueInput<float> SustainTime;
public readonly ValueInput<float> SustainValue;
public readonly ValueInput<float> ReleaseTime;

[DefaultValueAttribute(CurvePreset.Smooth)]
public ValueInput<CurvePreset> Curve;

public ObjectInput<IField<float>> Target;

public AsyncCall OnStarted;

public Continuation OnDone;

protected override async Task<IOperation> RunAsync(FrooxEngineContext context)
{
IField<float> field = Target.Evaluate(context);
if (field == null)
{
return null;
}

CurvePreset curve = Curve.Evaluate(context, CurvePreset.Smooth);
float attackTime = AttackTime.Evaluate(context);
float decayTime = DecayTime.Evaluate(context);
float sustainValue = SustainValue.Evaluate(context);
float sustainTime = SustainTime.Evaluate(context);
float releaseTime = ReleaseTime.Evaluate(context);

// ATTACK: tween from 0 to 1 over attackTime seconds
TaskCompletionSource<bool> completion = new TaskCompletionSource<bool>();
field.TweenFromTo(0f, 1f, attackTime, curve, null, delegate
{
completion.SetResult(result: true);
});
await OnStarted.ExecuteAsync(context);
await completion.Task;

// DECAY: tween from 1 to min(sustainValue, 1) over decayTime seconds
TaskCompletionSource<bool> completion2 = new TaskCompletionSource<bool>();
field.TweenFromTo(1f, MathX.Min(sustainValue, 1f), decayTime, curve, null, delegate
{
completion2.SetResult(result: true);
});
await completion2.Task;

// SUSTAIN: stay at min(sustainValue, 1) for sustainTime seconds
await Task.Delay(TimeSpan.FromSeconds(sustainTime));

// RELEASE: tween from min(sustainValue, 1) to 0 over releaseTime seconds
TaskCompletionSource<bool> completion3 = new TaskCompletionSource<bool>();
field.TweenFromTo(MathX.Min(sustainValue, 1f), 0f, releaseTime, curve, null, delegate
{
completion3.SetResult(result: true);
});
await completion3.Task;

return OnDone.Target;
}
}
}

0 comments on commit 6e7b125

Please sign in to comment.