Skip to content

Commit

Permalink
fade with independent in/out times
Browse files Browse the repository at this point in the history
  • Loading branch information
awood314 committed Jul 19, 2024
1 parent 743a879 commit b2de8e9
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 38 deletions.
2 changes: 1 addition & 1 deletion runtime/elem/Runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ namespace elem
int createNode(js::Value const& nodeId, js::Value const& type);
int setProperty(js::Value const& nodeId, js::Value const& prop, js::Value const& v);
int appendChild(js::Value const& parentId, js::Value const& childId, js::Value const& childOutputChannel);
int activateRoots(js::Array const&);
int activateRoots(js::Array const& v);

BufferAllocator<FloatType> bufferAllocator;
std::shared_ptr<GraphRenderSequence<FloatType>> rtRenderSeq;
Expand Down
16 changes: 7 additions & 9 deletions runtime/elem/builtins/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ namespace elem

bool active()
{
return fadeOut.targetGain > 0.5;
return fade.on();
}

bool stillRunning()
{
return active() || !fadeOut.settled();
return active() || !fade.settled();
}

int setProperty(std::string const& key, js::Value const& val) override
Expand All @@ -36,8 +36,7 @@ namespace elem
if (!val.isBool())
return ReturnCode::InvalidPropertyType();

fadeIn.currentGain = val ? 0.0 : 1.0;
fadeOut.setTargetGain(val ? 1.0 : 0.0);
fade.setTargetGain(val ? 1.0 : 0.0);
}

if (key == "channel") {
Expand All @@ -48,14 +47,14 @@ namespace elem
if (!val.isNumber())
return ReturnCode::InvalidPropertyType();

fadeIn.setFadeTimeMs(GraphNode<FloatType>::getSampleRate(), static_cast<float>((js::Number) val));
fade.setFadeInTimeMs(GraphNode<FloatType>::getSampleRate(), static_cast<float>((js::Number) val));
}

if (key == "fadeOutMs") {
if (!val.isNumber())
return ReturnCode::InvalidPropertyType();

fadeOut.setFadeTimeMs(GraphNode<FloatType>::getSampleRate(), static_cast<float>((js::Number) val));
fade.setFadeOutTimeMs(GraphNode<FloatType>::getSampleRate(), static_cast<float>((js::Number) val));
}

return GraphNode<FloatType>::setProperty(key, val);
Expand All @@ -73,12 +72,11 @@ namespace elem
return (void) std::fill_n(outputData, numSamples, FloatType(0));

for (size_t i = 0; i < numSamples; ++i) {
outputData[i] = fadeIn(fadeOut(inputData[0][i]));
outputData[i] = fade(inputData[0][i]);
}
}

GainFade<FloatType> fadeIn = {GraphNode<FloatType>::getSampleRate(), 20, 1.0, 1.0};
GainFade<FloatType> fadeOut = {GraphNode<FloatType>::getSampleRate(), 20, 1.0, 1.0};
GainFade<FloatType> fade = {GraphNode<FloatType>::getSampleRate(), 20, 20, 0.0, 1.0};

std::atomic<int> channelIndex = -1;
};
Expand Down
71 changes: 44 additions & 27 deletions runtime/elem/builtins/helpers/GainFade.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,69 +6,86 @@
namespace elem
{

namespace detail {
inline double millisecondsToStep(double sampleRate, double ms) {
return ms > 1e-6 ? 1.0 / (sampleRate * ms / 1000.0) : 1.0;
}
}

template <typename FloatType>
struct GainFade
{
GainFade(double sampleRate, double fadeTimeMs, FloatType current = 0.0, FloatType target = 0.0)
GainFade(double sampleRate, double fadeInTimeMs, double fadeOutTimeMs, FloatType current = 0.0, FloatType target = 0.0)
: currentGain(current)
, targetGain(target)
{
setFadeTimeMs(sampleRate, fadeTimeMs);
setFadeInTimeMs(sampleRate, fadeInTimeMs);
setFadeOutTimeMs(sampleRate, fadeOutTimeMs);
}

GainFade(GainFade const& other)
: currentGain(other.currentGain), targetGain(other.targetGain), step(other.step)
: currentGain(other.currentGain.load())
, targetGain(other.targetGain.load())
, inStep(other.inStep.load())
, outStep(other.outStep.load())
{
}

void operator= (GainFade const& other)
{
currentGain = other.currentGain;
targetGain = other.targetGain;
step = other.step;
currentGain.store(other.currentGain.load());
targetGain.store(other.targetGain.load());
inStep.store(other.inStep.load());
outStep.store(other.outStep.load());
}

FloatType operator() (FloatType x) {
if (currentGain == targetGain)
return (currentGain * x);
auto const _currentGain = currentGain.load();
auto const _targetGain = targetGain.load();
if (_currentGain == _targetGain)
return (_currentGain * x);

auto y = x * currentGain;
currentGain = std::clamp(currentGain + step, FloatType(0), FloatType(1));
auto y = x * _currentGain;
auto const step = _currentGain < _targetGain ? inStep.load() : outStep.load();
currentGain.store(std::clamp(_currentGain + step, FloatType(0), FloatType(1)));

return y;
}

void setFadeTimeMs(double sampleRate, double fadeTimeMs)
{
step = FloatType(fadeTimeMs > FloatType(1e-6) ? 1.0 / (sampleRate * fadeTimeMs / 1000.0) : 1.0);
void setFadeInTimeMs(double sampleRate, double fadeInTimeMs) {
inStep.store(detail::millisecondsToStep(sampleRate, fadeInTimeMs));
}

void setTargetGain (FloatType g) {
targetGain = g;
void setFadeOutTimeMs(double sampleRate, double fadeOutTimeMs) {
outStep.store(detail::millisecondsToStep(sampleRate, fadeOutTimeMs));
}

void setCurrentGain(FloatType gain) {
currentGain.store(gain);
}

if (targetGain < currentGain) {
step = FloatType(-1) * std::abs(step);
} else {
step = std::abs(step);
}
void setTargetGain(FloatType gain) {
targetGain.store(gain);
}

bool on() {
return (targetGain > FloatType(0.5));
return (targetGain.load() > FloatType(0.5));
}

bool settled() {
return fpEqual(targetGain, currentGain);
return fpEqual(targetGain.load(), currentGain.load());
}

void reset() {
currentGain = FloatType(0);
targetGain = FloatType(0);
currentGain.store(FloatType(0));
targetGain.store(FloatType(0));
}

FloatType currentGain = 0;
FloatType targetGain = 0;
FloatType step = 0;
private:
std::atomic<FloatType> currentGain = 0;
std::atomic<FloatType> targetGain = 0;
std::atomic<FloatType> inStep = 0;
std::atomic<FloatType> outStep = 0;
};

} // namespace elem
2 changes: 1 addition & 1 deletion runtime/elem/builtins/mc/SampleSeq.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace elem
template <typename FloatType>
struct MCBufferReader {
MCBufferReader(double sampleRate, double fadeTime)
: fade(sampleRate, fadeTime)
: fade(sampleRate, fadeTime, fadeTime)
{
}

Expand Down

0 comments on commit b2de8e9

Please sign in to comment.