Skip to content

Commit

Permalink
move cancel_ADC_spikes function in Edrumulus class
Browse files Browse the repository at this point in the history
  • Loading branch information
corrados committed Jun 12, 2024
1 parent 5f7151a commit 0552ad4
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 215 deletions.
166 changes: 165 additions & 1 deletion edrumulus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ Serial.println ( serial_print );
// ADC spike cancellation (do not use spike cancellation for rim switches since they have short peaks)
if ( ( spike_cancel_level > 0 ) && !is_rim_switch_input )
{
edrumulus_hardware.cancel_ADC_spikes ( sample[j], overload_detected[j], i, j, spike_cancel_level );
cancel_ADC_spikes ( sample[j], overload_detected[j], i, j, spike_cancel_level );
}
}

Expand Down Expand Up @@ -430,3 +430,167 @@ void Edrumulus::set_coupled_pad_idx ( const int pad_idx, const int new_idx )
any_coupling_used = ( coupled_pad_idx_primary >= 0 ) || ( coupled_pad_idx_rim_primary >= 0 );
}
}


void Edrumulus::cancel_ADC_spikes ( float& signal,
int& overload_detected,
const int pad_index,
const int input_channel_index,
const int level )
{
// remove single/dual sample spikes by checking if right before and right after the
// detected spike(s) we only have noise and no useful signal (since the ESP32 spikes
// mostly are on just one or two sample(s))
const int max_peak_threshold = 150; // maximum assumed ESP32 spike amplitude

const float signal_org = signal;
signal = prev_input4[pad_index][input_channel_index]; // normal return value in case no spike was detected
const int overload_detected_org = overload_detected;
overload_detected = prev_overload4[pad_index][input_channel_index]; // normal return value in case no spike was detected
const float input_abs = abs ( signal_org );
Espikestate input_state = ST_OTHER; // initialization value, might be overwritten

if ( input_abs < ADC_MAX_NOISE_AMPL )
{
input_state = ST_NOISE;
}
else if ( ( signal_org < max_peak_threshold ) && ( signal_org > 0 ) )
{
input_state = ST_SPIKE_HIGH;
}
else if ( ( signal_org > -max_peak_threshold ) && ( signal_org < 0 ) )
{
input_state = ST_SPIKE_LOW;
}

// check for single high spike sample case
if ( ( ( prev5_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev5_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) ) &&
( prev4_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) &&
( ( prev3_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev3_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) ) )
{
signal = 0.0f; // remove single spike
}

// check for single low spike sample case
if ( ( ( prev5_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev5_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) ) &&
( prev4_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) &&
( ( prev3_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev3_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) ) )
{
signal = 0.0f; // remove single spike
}

if ( level >= 2 )
{
// check for two sample spike case
if ( ( ( prev5_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev5_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) ) &&
( prev4_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) &&
( prev3_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) &&
( ( prev2_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev2_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) ) )
{
signal = 0.0f; // remove two sample spike
prev_input3[pad_index][input_channel_index] = 0.0f; // remove two sample spike
}

// check for two sample low spike case
if ( ( ( prev5_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev5_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) ) &&
( prev4_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) &&
( prev3_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) &&
( ( prev2_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev2_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) ) )
{
signal = 0.0f; // remove two sample spike
prev_input3[pad_index][input_channel_index] = 0.0f; // remove two sample spike
}
}

if ( level >= 3 )
{
// check for three sample high spike case
if ( ( ( prev5_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev5_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) ) &&
( prev4_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) &&
( prev3_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) &&
( prev2_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) &&
( ( prev1_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev1_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) ) )
{
signal = 0.0f; // remove three sample spike
prev_input3[pad_index][input_channel_index] = 0.0f; // remove three sample spike
prev_input2[pad_index][input_channel_index] = 0.0f; // remove three sample spike
}

// check for three sample low spike case
if ( ( ( prev5_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev5_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) ) &&
( prev4_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) &&
( prev3_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) &&
( prev2_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) &&
( ( prev1_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev1_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) ) )
{
signal = 0.0f; // remove three sample spike
prev_input3[pad_index][input_channel_index] = 0.0f; // remove three sample spike
prev_input2[pad_index][input_channel_index] = 0.0f; // remove three sample spike
}
}

if ( level >= 4 )
{
// check for four sample high spike case
if ( ( ( prev5_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev5_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) ) &&
( prev4_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) &&
( prev3_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) &&
( prev2_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) &&
( prev1_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) &&
( ( input_state == ST_NOISE ) || ( input_state == ST_SPIKE_LOW ) ) )
{
signal = 0.0f; // remove four sample spike
prev_input3[pad_index][input_channel_index] = 0.0f; // remove four sample spike
prev_input2[pad_index][input_channel_index] = 0.0f; // remove four sample spike
prev_input1[pad_index][input_channel_index] = 0.0f; // remove four sample spike
}

// check for four sample low spike case
if ( ( ( prev5_input_state[pad_index][input_channel_index] == ST_NOISE ) || ( prev5_input_state[pad_index][input_channel_index] == ST_SPIKE_HIGH ) ) &&
( prev4_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) &&
( prev3_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) &&
( prev2_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) &&
( prev1_input_state[pad_index][input_channel_index] == ST_SPIKE_LOW ) &&
( ( input_state == ST_NOISE ) || ( input_state == ST_SPIKE_HIGH ) ) )
{
signal = 0.0f; // remove four sample spike
prev_input3[pad_index][input_channel_index] = 0.0f; // remove four sample spike
prev_input2[pad_index][input_channel_index] = 0.0f; // remove four sample spike
prev_input1[pad_index][input_channel_index] = 0.0f; // remove four sample spike
}
}

// update five-step input signal memory where we store the last five states of
// the input signal and four previous untouched input samples
prev5_input_state[pad_index][input_channel_index] = prev4_input_state[pad_index][input_channel_index];
prev4_input_state[pad_index][input_channel_index] = prev3_input_state[pad_index][input_channel_index];
prev3_input_state[pad_index][input_channel_index] = prev2_input_state[pad_index][input_channel_index];
prev2_input_state[pad_index][input_channel_index] = prev1_input_state[pad_index][input_channel_index];
prev_input4[pad_index][input_channel_index] = prev_input3[pad_index][input_channel_index];
prev_input3[pad_index][input_channel_index] = prev_input2[pad_index][input_channel_index];
prev_input2[pad_index][input_channel_index] = prev_input1[pad_index][input_channel_index];
prev_overload4[pad_index][input_channel_index] = prev_overload3[pad_index][input_channel_index];
prev_overload3[pad_index][input_channel_index] = prev_overload2[pad_index][input_channel_index];
prev_overload2[pad_index][input_channel_index] = prev_overload1[pad_index][input_channel_index];

// adjust the latency of the algorithm according to the spike cancellation
// level, i.e., the higher the level, the higher the latency
if ( level >= 3 )
{
prev1_input_state[pad_index][input_channel_index] = input_state;
prev_input1[pad_index][input_channel_index] = signal_org;
prev_overload1[pad_index][input_channel_index] = overload_detected_org;
}
else if ( level >= 2 )
{
prev2_input_state[pad_index][input_channel_index] = input_state;
prev_input2[pad_index][input_channel_index] = signal_org;
prev_overload2[pad_index][input_channel_index] = overload_detected_org;
}
else
{
prev3_input_state[pad_index][input_channel_index] = input_state;
prev_input3[pad_index][input_channel_index] = signal_org;
prev_overload3[pad_index][input_channel_index] = overload_detected_org;
}
}
25 changes: 20 additions & 5 deletions edrumulus.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@

#pragma once

#define VERSION_MAJOR 0
#define VERSION_MINOR 9

//#define USE_SERIAL_DEBUG_PLOTTING

#include "Arduino.h"
#include "edrumulus_pad.h"
#include "edrumulus_util.h"
Expand Down Expand Up @@ -114,6 +109,12 @@ class Edrumulus
byte read_setting ( const int pad_index, const int address ) { return edrumulus_hardware.read_setting ( pad_index, address ); }

protected:
void cancel_ADC_spikes ( float& signal,
int& overload_detected,
const int pad_index,
const int input_channel_index,
const int level );

// constant definitions
const int Fs = 8000; // this is the most fundamental system parameter: system sampling rate
const float dc_offset_est_len_s = 1.25f; // length of initial DC offset estimation in seconds
Expand Down Expand Up @@ -179,4 +180,18 @@ class Edrumulus
int cancel_cnt;
int cancel_MIDI_velocity;
int cancel_pad_index;

Espikestate prev1_input_state[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
Espikestate prev2_input_state[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
Espikestate prev3_input_state[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
Espikestate prev4_input_state[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
Espikestate prev5_input_state[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
float prev_input1[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
float prev_input2[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
float prev_input3[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
float prev_input4[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
int prev_overload1[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
int prev_overload2[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
int prev_overload3[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
int prev_overload4[MAX_NUM_PADS][MAX_NUM_PAD_INPUTS];
};
Loading

0 comments on commit 0552ad4

Please sign in to comment.