Program Listing for File dm_fx_arpeggiator.h¶
↰ Return to documentation for file (src/effects/dm_fx_arpeggiator.h
)
// Copyright (c) 2020 Run Jump Labs LLC. All right reserved.
// This code is licensed under MIT license (see license.txt for details)
#ifndef DM_FX_ARPEGGIATOR_H
#define DM_FX_ARPEGGIATOR_H
class fx_arpeggiator: public fx_effect {
private:
// Parameters
float param_time_scale;
float param_period_ms;
uint16_t param_total_steps;
ARP_STEP param_arp_steps[ARP_MAX_STEPS];
// Control nodes
fx_control_node node_ctrl_time_scale;
fx_control_node node_ctrl_period_ms;
fx_control_node node_ctrl_freq;
fx_control_node node_ctrl_vol;
fx_control_node node_ctrl_param_1;
fx_control_node node_ctrl_param_2;
fx_control_node node_ctrl_start;
void init(void) {
// Set class
type = FX_ARPEGGIATOR;
// Set name
strcpy(effect_name, "arpeggiator");
// Initialize parameter stack
int indx = 1;
param_stack[indx] = ¶m_total_steps;
param_stack_types[indx++] = T_INT16;
for (int i=0;i<param_total_steps;i++) {
param_stack[indx] = ¶m_arp_steps[i].freq;
param_stack_types[indx++] = T_FLOAT;
param_stack[indx] = ¶m_arp_steps[i].vol;
param_stack_types[indx++] = T_FLOAT;
param_stack[indx] = ¶m_arp_steps[i].dur;
param_stack_types[indx++] = T_FLOAT;
param_stack[indx] = ¶m_arp_steps[i].param_1;
param_stack_types[indx++] = T_FLOAT;
param_stack[indx] = ¶m_arp_steps[i].param_2;
param_stack_types[indx++] = T_FLOAT;
}
total_params = indx;
// Assign controls
time_scale = &node_ctrl_time_scale;
period_ms = &node_ctrl_period_ms;
freq = &node_ctrl_freq;
vol = &node_ctrl_vol;
param_1 = &node_ctrl_param_1;
param_2 = &node_ctrl_param_2;
start = &node_ctrl_start;
// Add addiitonal notes to the control stack
control_node_stack[total_control_nodes++] = &node_ctrl_time_scale;
control_node_stack[total_control_nodes++] = &node_ctrl_period_ms;
control_node_stack[total_control_nodes++] = &node_ctrl_freq;
control_node_stack[total_control_nodes++] = &node_ctrl_vol;
control_node_stack[total_control_nodes++] = &node_ctrl_param_1;
control_node_stack[total_control_nodes++] = &node_ctrl_param_2;
control_node_stack[total_control_nodes++] = &node_ctrl_start;
}
void serialize_arps(void) {
}
public:
fx_control_node * time_scale;
fx_control_node * period_ms;
fx_control_node * freq;
fx_control_node * vol;
fx_control_node * param_1;
fx_control_node * param_2;
fx_control_node * start;
fx_arpeggiator( int total_steps, ARP_STEP * steps) :
node_ctrl_time_scale(NODE_IN, NODE_FLOAT, "node_ctrl_time_scale", this, FX_ARPEGGIATOR_PARAM_ID_TIME_SCALE),
node_ctrl_period_ms(NODE_IN, NODE_FLOAT, "node_ctrl_period_ms", this, FX_ARPEGGIATOR_PARAM_ID_PERIOD),
node_ctrl_freq(NODE_OUT, NODE_FLOAT, "node_ctrl_freq", this, FX_ARPEGGIATOR_PARAM_ID_FREQ),
node_ctrl_vol(NODE_OUT, NODE_FLOAT, "node_ctrl_vol", this, FX_ARPEGGIATOR_PARAM_ID_VOL),
node_ctrl_param_1(NODE_OUT, NODE_FLOAT, "node_ctrl_param_1", this, FX_ARPEGGIATOR_PARAM_ID_PARAM_1),
node_ctrl_param_2(NODE_OUT, NODE_FLOAT, "node_ctrl_param_2", this, FX_ARPEGGIATOR_PARAM_ID_PARAM_2),
node_ctrl_start(NODE_IN, NODE_FLOAT, "node_ctrl_start", this, FX_ARPEGGIATOR_PARAM_ID_RESTART) {
if (total_steps > ARP_MAX_STEPS) {
DEBUG_MSG("Maximum number of arpeggiator steps is 16", MSG_ERROR);
display_error_status(ERROR_CODE_ILLEGAL_ROUTING);
}
param_total_steps = total_steps;
param_time_scale = 1.0;
for (int i=0;i<total_steps;i++) {
param_arp_steps[i].freq = steps[i].freq;
param_arp_steps[i].vol = steps[i].vol;
param_arp_steps[i].dur = steps[i].dur;
param_arp_steps[i].param_1 = steps[i].param_1;
param_arp_steps[i].param_2 = steps[i].param_2;
}
init();
}
void set_time_scale(float new_time_scale) {
CHECK_LAST(new_time_scale, param_time_scale);
// If this node is being controlled by a controller, don't allow a direct write to it
if (node_ctrl_time_scale.connected) {
return;
}
param_time_scale = new_time_scale;
parent_canvas->spi_transmit_param(FX_ARPEGGIATOR, instance_id, T_FLOAT, FX_ARPEGGIATOR_PARAM_ID_TIME_SCALE, (void *) ¶m_time_scale);
}
void set_duration_ms(float new_duration) {
CHECK_LAST(new_duration, param_period_ms);
// If this node is being controlled by a controller, don't allow a direct write to it
if (node_ctrl_period_ms.connected) {
return;
}
param_period_ms = new_duration;
parent_canvas->spi_transmit_param(FX_ARPEGGIATOR, instance_id, T_FLOAT, FX_ARPEGGIATOR_PARAM_ID_PERIOD, (void *) ¶m_period_ms);
}
void print_params(void) {
// void print_parameter( void * val, char * name, PARAM_TYPES type)
Serial.println("Parameters:");
print_parameter( ¶m_total_steps, "Total steps", T_INT16 );
Serial.println("relative frequency, volume, duration (ms), param1, param2");
for (int i=0;i<param_total_steps;i++) {
Serial.print(" ");
Serial.print(i);
Serial.print(": ");
Serial.print(param_arp_steps[i].freq);
Serial.print(", ");
Serial.print(param_arp_steps[i].vol);
Serial.print(", ");
Serial.print(param_arp_steps[i].dur);
Serial.print(", ");
Serial.print(param_arp_steps[i].param_1);
Serial.print(", ");
Serial.println(param_arp_steps[i].param_2);
}
Serial.println("Control Routing:");
print_ctrl_node_status(&node_ctrl_time_scale);
print_ctrl_node_status(&node_ctrl_period_ms);
print_ctrl_node_status(&node_ctrl_freq);
print_ctrl_node_status(&node_ctrl_vol);
print_ctrl_node_status(&node_ctrl_param_1);
print_ctrl_node_status(&node_ctrl_param_2);
Serial.println(instance_id);
Serial.println(total_params);
Serial.println();
}
};
#endif // DM_FX_ARPEGGIATOR_H