Skip to content

Commit

Permalink
Stutter: Add stutter_probability, stutter_advance_time
Browse files Browse the repository at this point in the history
  • Loading branch information
ideoforms committed Oct 12, 2024
1 parent dd3bc19 commit 18f7d44
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 20 deletions.
5 changes: 5 additions & 0 deletions source/include/signalflow/node/processors/delays/stutter.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class Stutter : public UnaryOpNode
Stutter(NodeRef input = 0.0,
NodeRef stutter_time = 0.1,
NodeRef stutter_count = 1,
NodeRef stutter_probability = 1.0,
NodeRef stutter_advance_time = 0.0,
NodeRef clock = nullptr,
float max_stutter_time = 1.0);
~Stutter() override;
Expand All @@ -29,6 +31,8 @@ class Stutter : public UnaryOpNode
private:
NodeRef stutter_time;
NodeRef stutter_count;
NodeRef stutter_probability;
NodeRef stutter_advance_time;
NodeRef clock;
float max_stutter_time;

Expand All @@ -37,6 +41,7 @@ class Stutter : public UnaryOpNode
std::vector<int> stutters_to_do;
std::vector<int> stutter_sample_buffer_offset;
std::vector<int> stutter_samples_remaining;
std::vector<int> stutter_sample_index;
};

REGISTER(Stutter, "stutter")
Expand Down
60 changes: 40 additions & 20 deletions source/src/node/processors/delays/stutter.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
#include "signalflow/core/graph.h"
#include "signalflow/core/random.h"
#include "signalflow/node/oscillators/constant.h"
#include "signalflow/node/processors/delays/stutter.h"

namespace signalflow
{

Stutter::Stutter(NodeRef input, NodeRef stutter_time, NodeRef stutter_count, NodeRef clock, float max_stutter_time)
: UnaryOpNode(input), stutter_time(stutter_time), stutter_count(stutter_count), clock(clock), max_stutter_time(max_stutter_time)
Stutter::Stutter(NodeRef input,
NodeRef stutter_time,
NodeRef stutter_count,
NodeRef stutter_probability,
NodeRef stutter_advance_time,
NodeRef clock,
float max_stutter_time)
: UnaryOpNode(input), stutter_time(stutter_time), stutter_count(stutter_count), stutter_probability(stutter_probability), stutter_advance_time(stutter_advance_time), clock(clock), max_stutter_time(max_stutter_time)
{
SIGNALFLOW_CHECK_GRAPH();

this->name = "stutter";
this->create_input("stutter_time", this->stutter_time);
this->create_input("stutter_count", this->stutter_count);
this->create_input("stutter_probability", this->stutter_probability);
this->create_input("stutter_advance_time", this->stutter_advance_time);
this->create_input("clock", this->clock);
this->alloc();
}
Expand All @@ -23,6 +32,7 @@ void Stutter::alloc()
this->stutter_sample_buffer_offset.resize(this->num_output_channels_allocated);
this->stutters_to_do.resize(this->num_output_channels_allocated);
this->stutter_samples_remaining.resize(this->num_output_channels_allocated);
this->stutter_sample_index.resize(this->num_output_channels_allocated);

int buffers_to_allocate = this->num_output_channels_allocated - buffers.size();
for (int i = 0; i < buffers_to_allocate; i++)
Expand All @@ -43,12 +53,17 @@ void Stutter::trigger(std::string name, float value)
{
if (name == SIGNALFLOW_DEFAULT_TRIGGER)
{
for (int channel = 0; channel < this->num_input_channels; channel++)
float probability = this->stutter_probability->out[0][0];
if (random_coin(probability))
{
this->stutter_index[channel] = 0;
this->stutters_to_do[channel] = this->stutter_count->out[channel][0];
this->stutter_samples_remaining[channel] = this->stutter_time->out[channel][0] * graph->get_sample_rate();
this->stutter_sample_buffer_offset[channel] = stutter_samples_remaining[channel];
for (int channel = 0; channel < this->num_input_channels; channel++)
{
this->stutter_index[channel] = 0;
this->stutters_to_do[channel] = this->stutter_count->out[channel][0];
this->stutter_samples_remaining[channel] = this->stutter_time->out[channel][0] * graph->get_sample_rate();
this->stutter_sample_buffer_offset[channel] = stutter_samples_remaining[channel];
this->stutter_sample_index[channel] = 0;
}
}
}
}
Expand All @@ -61,18 +76,26 @@ void Stutter::process(Buffer &out, int num_frames)
{
if (SIGNALFLOW_CHECK_CHANNEL_TRIGGER(this->clock, channel, frame))
{
this->stutter_index[channel] = 0;
this->stutters_to_do[channel] = this->stutter_count->out[channel][0];
this->stutter_samples_remaining[channel] = this->stutter_time->out[channel][0] * graph->get_sample_rate();
this->stutter_sample_buffer_offset[channel] = stutter_samples_remaining[channel];
float probability = this->stutter_probability->out[channel][frame];
if (random_coin(probability))
{
this->stutter_index[channel] = 0;
this->stutters_to_do[channel] = this->stutter_count->out[channel][0];
this->stutter_samples_remaining[channel] = this->stutter_time->out[channel][frame] * graph->get_sample_rate();
this->stutter_sample_buffer_offset[channel] = stutter_samples_remaining[channel];
this->stutter_sample_index[channel] = 0;
}
}

if (this->stutters_to_do[channel] > 0)
{
this->stutter_samples_remaining[channel]--;

this->stutter_sample_index[channel] += 1;

if (this->stutter_samples_remaining[channel] <= 0)
{
// one of the stutters has finished
this->stutter_index[channel] += 1;
if (this->stutter_index[channel] > this->stutters_to_do[channel])
{
Expand All @@ -92,8 +115,8 @@ void Stutter::process(Buffer &out, int num_frames)
}
else
{
// TODO this won't quite work
int buffer_sample_offset = -this->stutter_samples_remaining[channel];
float stutter_advance_samples = (this->stutter_advance_time->out[channel][frame] * this->stutter_index[channel]) * this->graph->get_sample_rate();
int buffer_sample_offset = -this->stutter_samples_remaining[channel] + stutter_advance_samples - this->stutter_sample_index[channel];
out[channel][frame] = this->buffers[channel]->get(buffer_sample_offset);
}
}
Expand All @@ -103,13 +126,10 @@ void Stutter::process(Buffer &out, int num_frames)
out[channel][frame] = this->input->out[channel][frame];
}

if (this->stutter_index[channel] == 0)
{
// stutter_index is zero in the first stutter or when we're not stuttering
this->buffers[channel]->append(this->input->out[channel][frame]);
}
}
}
this->buffers[channel]->append(this->input->out[channel][frame]);

} // foreach frame
} // foreach channel
}

}

0 comments on commit 18f7d44

Please sign in to comment.