Program Listing for File dm_fx_biquad_filter.h¶
↰ Return to documentation for file (src/effects/dm_fx_biquad_filter.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_BIQUAD_FILTER_H
#define DM_FX_BIQUAD_FILTER_H
class fx_biquad_filter: public fx_effect {
private:
// Parameters
// important safety tip - don't put 8-bit enum types together as they need to exist on 16 or 32-bit memory boundaries
BIQUAD_FILTER_TYPE param_type;
float param_freq;
BIQUAD_FILTER_ORDER param_order;
float param_q;
float param_gain;
EFFECT_TRANSITION_SPEED param_speed;
fx_control_node node_ctrl_freq;
fx_control_node node_ctrl_q;
fx_control_node node_ctrl_gain;
void init(void) {
// Set class
type = FX_BIQUAD_FILTER;
// Set name
strcpy(effect_name, "biquad filter");
// Assign programmable node names
input = &node_input;
output = &node_output;
// Initialize parameter stack
int indx = 1;
param_stack[indx] = ¶m_type;
param_stack_types[indx++] = T_INT16;
param_stack[indx] = ¶m_speed;
param_stack_types[indx++] = T_INT16;
param_stack[indx] = ¶m_freq;
param_stack_types[indx++] = T_FLOAT;
param_stack[indx] = ¶m_q;
param_stack_types[indx++] = T_FLOAT;
param_stack[indx] = ¶m_gain;
param_stack_types[indx++] = T_FLOAT;
param_stack[indx] = ¶m_order;
param_stack_types[indx++] = T_INT16;
total_params = indx;
// Add addititonal nodes to the control stack
control_node_stack[total_control_nodes++] = &node_ctrl_freq;
control_node_stack[total_control_nodes++] = &node_ctrl_q;
control_node_stack[total_control_nodes++] = &node_ctrl_gain;
// Assign controls
freq = &node_ctrl_freq;
q = &node_ctrl_q;
gain = &node_ctrl_gain;
}
public:
fx_audio_node * input;
fx_audio_node * output;
fx_control_node * freq;
fx_control_node * q;
fx_control_node * gain;
fx_biquad_filter(float filt_freq, float filt_resonance, BIQUAD_FILTER_TYPE filt_type) :
node_ctrl_freq(NODE_IN, NODE_FLOAT, "node_ctrl_freq", this, FX_BIQUAD_PARAM_ID_FREQ),
node_ctrl_q(NODE_IN, NODE_FLOAT, "node_ctrl_q", this, FX_BIQUAD_PARAM_ID_Q),
node_ctrl_gain(NODE_IN, NODE_FLOAT, "node_ctrl_gain", this, FX_BIQUAD_PARAM_ID_GAIN) {
// Set parameters
param_freq = filt_freq;
if (filt_resonance <= 0.1) {
filt_resonance = 0.1;
} else if (filt_resonance > 20.0) {
filt_resonance = 20.0;
}
param_q = filt_resonance * 0.7071;
param_gain = 0.0;
param_type = filt_type;
param_speed = TRANS_MED;
param_order = BIQUAD_ORDER_2;
init();
}
fx_biquad_filter(float filt_freq, float filt_resonance, BIQUAD_FILTER_TYPE filt_type, BIQUAD_FILTER_ORDER order) :
node_ctrl_freq(NODE_IN, NODE_FLOAT, "node_ctrl_freq", this, FX_BIQUAD_PARAM_ID_FREQ),
node_ctrl_q(NODE_IN, NODE_FLOAT, "node_ctrl_q", this, FX_BIQUAD_PARAM_ID_Q),
node_ctrl_gain(NODE_IN, NODE_FLOAT, "node_ctrl_gain", this, FX_BIQUAD_PARAM_ID_GAIN) {
// Set parameters
param_freq = filt_freq;
if (filt_resonance <= 0.1) {
filt_resonance = 0.1;
} else if (filt_resonance > 20.0) {
filt_resonance = 20.0;
}
param_q = filt_resonance * 0.7071;
param_gain = 0.0;
param_type = filt_type;
param_speed = TRANS_MED;
param_order = order;
init();
}
fx_biquad_filter(float filt_freq, float filt_resonance, float filter_gain, BIQUAD_FILTER_TYPE filt_type, EFFECT_TRANSITION_SPEED trans_speed) :
node_ctrl_freq(NODE_IN, NODE_FLOAT, "node_ctrl_freq", this, FX_BIQUAD_PARAM_ID_FREQ),
node_ctrl_q(NODE_IN, NODE_FLOAT, "node_ctrl_q", this, FX_BIQUAD_PARAM_ID_Q),
node_ctrl_gain(NODE_IN, NODE_FLOAT, "node_ctrl_gain", this, FX_BIQUAD_PARAM_ID_GAIN) {
// Set parameters
param_freq = filt_freq;
if (filt_resonance <= 0.1) {
filt_resonance = 0.1;
} else if (filt_resonance > 20.0) {
filt_resonance = 20.0;
}
param_q = filt_resonance * 0.7071;
param_gain = filter_gain;
param_type = filt_type;
param_speed = trans_speed;
param_order = BIQUAD_ORDER_2;
init();
}
fx_biquad_filter(float filt_freq, float filt_resonance, float filter_gain_db, BIQUAD_FILTER_TYPE filt_type, EFFECT_TRANSITION_SPEED trans_speed, BIQUAD_FILTER_ORDER order) :
node_ctrl_freq(NODE_IN, NODE_FLOAT, "node_ctrl_freq", this, FX_BIQUAD_PARAM_ID_FREQ),
node_ctrl_q(NODE_IN, NODE_FLOAT, "node_ctrl_q", this, FX_BIQUAD_PARAM_ID_Q),
node_ctrl_gain(NODE_IN, NODE_FLOAT, "node_ctrl_gain", this, FX_BIQUAD_PARAM_ID_GAIN) {
// Set parameters
param_freq = filt_freq;
if (filt_resonance <= 0.1) {
filt_resonance = 0.1;
} else if (filt_resonance > 20.0) {
filt_resonance = 20.0;
}
param_q = filt_resonance * 0.7071;
param_gain = filter_gain_db;
param_type = filt_type;
param_speed = trans_speed;
param_order = order;
init();
}
void enable() {
CHECK_LAST_ENABLED();
param_enabled = true;
parent_canvas->spi_transmit_param(FX_BIQUAD_FILTER, instance_id, T_BOOL, FX_BIQUAD_PARAM_ID_ENABLED, (void *) ¶m_enabled);
}
void bypass() {
CHECK_LAST_DISABLED();
param_enabled = false;
parent_canvas->spi_transmit_param(FX_BIQUAD_FILTER, instance_id, T_BOOL, FX_BIQUAD_PARAM_ID_ENABLED, (void *) ¶m_enabled);
}
void set_freq(float freq) {
CHECK_LAST(freq, param_freq);
// If this node is being controlled by a controller, don't allow a direct write to it
if (node_ctrl_freq.connected) {
return;
}
param_freq = freq;
parent_canvas->spi_transmit_param(FX_BIQUAD_FILTER, instance_id, T_FLOAT, FX_BIQUAD_PARAM_ID_FREQ, ¶m_freq);
}
void set_q(float q) {
CHECK_LAST(q, param_q)
if (node_ctrl_q.connected) {
return;
}
param_q = q;
parent_canvas->spi_transmit_param(FX_BIQUAD_FILTER, instance_id, T_FLOAT, FX_BIQUAD_PARAM_ID_Q, ¶m_q);
}
void set_resonance(float filt_resonance) {
if (node_ctrl_q.connected) {
return;
}
if (filt_resonance <= 0.1) {
filt_resonance = 0.1;
} else if (filt_resonance > 20.0) {
filt_resonance = 20.0;
}
filt_resonance = filt_resonance * 0.7071;
CHECK_LAST(filt_resonance, param_q);
param_q = filt_resonance * 0.7071;
parent_canvas->spi_transmit_param(FX_BIQUAD_FILTER, instance_id, T_FLOAT, FX_BIQUAD_PARAM_ID_Q, ¶m_q);
}
void set_gain(float gain) {
CHECK_LAST(gain, param_gain);
if (node_ctrl_gain.connected) {
return;
}
param_gain = gain;
parent_canvas->spi_transmit_param(FX_BIQUAD_FILTER, instance_id, T_FLOAT, FX_BIQUAD_PARAM_ID_GAIN, ¶m_gain);
}
void print_params(void) {
// void print_parameter( void * val, char * name, PARAM_TYPES type)
Serial.println("Parameters:");
print_parameter( ¶m_enabled, "Enabled", T_BOOL );
print_parameter( ¶m_freq, "Frequency (Hz)", T_FLOAT );
print_parameter( ¶m_q, "Width/Q", T_FLOAT );
print_parameter( ¶m_gain, "Gain (db)", T_FLOAT );
print_parameter( ¶m_order, "Order (enumerated))", T_INT16 );
Serial.println("Control Routing:");
print_ctrl_node_status(&node_ctrl_freq);
print_ctrl_node_status(&node_ctrl_q);
print_ctrl_node_status(&node_ctrl_gain);
Serial.println("Audio Routing:");
print_audio_node_status(&node_input);
print_audio_node_status(&node_output);
Serial.println();
}
};
#endif // DM_FX_BIQUAD_FILTER_H