signal.library
Class SignalFilter

java.lang.Object
  extended by signal.library.SignalFilter

public class SignalFilter
extends Object

Processing implementation of the One Euro Filter [Casiez 2012] http://www.lifl.fr/~casiez/publications/CHI2012-casiez.pdf

+Example
/*
 * This example demonstrates the use of the filterUnitFloat() function
 * to filter a single signal (simulated here with Perlin noise)
 * 
 */

// Add the library to the sketch
import signal.library.*;

// -----------------------------------------------------
// Create the filter
   SignalFilter myFilter;
// -----------------------------------------------------

// Main OneEuroFilter parameters
float minCutoff = 0.05; // decrease this to get rid of slow speed jitter
float beta      = 4.0;  // increase this to get rid of high speed lag

float xPos = 0;

float sourceSignal, sourceSignalPrev;
float noisySignal, noisySignalPrev;
float filteredSignal, filteredSignalPrev;

void setup() {

  size(512, 512);
  
  background(180);

  // -----------------------------------------------------
  // Initialize the filter
     myFilter = new SignalFilter(this);
  // -----------------------------------------------------
}


void draw()
{
  
  // Pass the parameters to the filter
  myFilter.setMinCutoff(minCutoff);
  myFilter.setBeta(beta);
  
  // Save previous values (needed to draw the lines)
  sourceSignalPrev = sourceSignal;
  filteredSignalPrev = filteredSignal;
  noisySignalPrev = noisySignal;

  // Generate simulated signal based on Perlin noise
  sourceSignal = noise(frameCount / 250.0);
  noisySignal = sourceSignal + ( noise(frameCount) - 0.5 )  / 10.0;

  
  // -----------------------------------------------------
  // Filter the signal [THIS IS THE IMPORTANT LINE HERE!]
     filteredSignal = myFilter.filterUnitFloat( noisySignal );
  // -----------------------------------------------------
  
  

  float textBgHeight = 30;
  color textBgColor = color(150);

  // Compute x positions to draw the plot line
  float x1 = xPos-0.1;
  float x2 = xPos;  
  
  float sectionSize = height / 3.0;

  // Draw original signal
  noStroke();
  fill(255);
  float ySource1 = map(sourceSignalPrev, 0.0, 1.0, textBgHeight, sectionSize);
  float ySource2 = map(sourceSignal, 0.0, 1.0, textBgHeight, sectionSize);
  stroke(255);
  line(x1, ySource1, x2, ySource2);
  noStroke();
  fill(textBgColor);
  rect(0, 0, width, textBgHeight );
  fill(255);
  text( "Original signal", 10, 20 );

  // Draw noisy signal
  pushMatrix();
  translate(0, sectionSize);
  noStroke();
  fill(255);
  float yNoisy1 = map(noisySignalPrev, 0.0, 1.0, textBgHeight, sectionSize);
  float yNoisy2 = map(noisySignal, 0.0, 1.0, textBgHeight, sectionSize);
  stroke(255);
  line(x1, yNoisy1, x2, yNoisy2);
  noStroke();
  fill(textBgColor);
  rect(0, 0, width, textBgHeight );
  fill(255);
  text( "Noisy signal", 10, 20 );
  popMatrix();

  // Draw filtered signal
  pushMatrix();
  translate(0, sectionSize * 2.0);
  noStroke();
  float yFiltered1 = map(filteredSignalPrev, 0.0, 1.0, textBgHeight, sectionSize);
  float yFiltered2 = map(filteredSignal, 0.0, 1.0, textBgHeight, sectionSize);
  stroke(255);
  line(x1, yFiltered1, x2, yFiltered2);
  noStroke();
  fill(textBgColor);
  rect(0, 0, width, textBgHeight );
  fill(255);
  text( "Filtered signal", 10, 20 );
  popMatrix();


  // Output the values to the console for debug
  println( " " );
  println( "source   = " + sourceSignal );
  println( "noisy    = " + noisySignal );
  println( "filtered = " + filteredSignal );
  
  // Move the head to the right
  xPos += 1;

  // Wrap condition
  if ( xPos > width ) {
    background(180); // clear screen
    xPos = 0.0;      // move back to the left
  }
}

Constructor Summary
SignalFilter(PApplet theParent)
          Call this constructor in the setup() method of your sketch to initialize and start the library.
SignalFilter(PApplet theParent, int size)
          Call this constructor in the setup() method of your sketch to initialize and start the library.
 
Method Summary
 PVector filterCoord2D(float coordX, float coordY, float scaleX, float scaleY)
          Convenience method to filter 2D coordinate values passed as floats
 PVector filterCoord2D(PVector noisyVector, float scaleX, float scaleY)
          Convenience method to filter 2D coordinate values passed as a PVector
 PVector filterCoord3D(float coordX, float coordY, float coordZ, float scaleX, float scaleY, float scaleZ)
          Convenience method to filter 3D coordinate values passed as float
 PVector filterCoord3D(PVector noisyVector, float scaleX, float scaleY, float scaleZ)
          Convenience method to filter 3D coordinate values passed as a PVector
 float[] filterUnitArray(float[] noisyArray)
          Return filtered values for the given float[] array Note: values have to be at the unit scale [0.0, 1.0]
 float filterUnitFloat(float noisyFloat)
          Return filtered value for the given float Note: value has to be at the unit scale [0.0, 1.0]
 PVector filterUnitVector(PVector noisyVector)
          Return filtered values for the given PVector Note: values have to be at the unit scale [0.0, 1.0]
 void setBeta(float b)
          Set the Beta (cutoff slope) parameter for all filtering channels
 void setDerivateCutoff(float dc)
          Set the derivative cutoff for all filtering channels
 void setFrequency(float f)
          Set the frequency for all filtering channels
 void setMinCutoff(float mc)
          Set the minimum cutoff for all the filtering channels
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

SignalFilter

public SignalFilter(PApplet theParent)
Call this constructor in the setup() method of your sketch to initialize and start the library.

Parameters:
theParent - Your sketch's PApplet object
+Example
/*
 * This example demonstrates the use of the filterUnitFloat() function
 * to filter a single signal (simulated here with Perlin noise)
 * 
 */

// Add the library to the sketch
import signal.library.*;

// -----------------------------------------------------
// Create the filter
   SignalFilter myFilter;
// -----------------------------------------------------

// Main OneEuroFilter parameters
float minCutoff = 0.05; // decrease this to get rid of slow speed jitter
float beta      = 4.0;  // increase this to get rid of high speed lag

float xPos = 0;

float sourceSignal, sourceSignalPrev;
float noisySignal, noisySignalPrev;
float filteredSignal, filteredSignalPrev;

void setup() {

  size(512, 512);
  
  background(180);

  // -----------------------------------------------------
  // Initialize the filter
     myFilter = new SignalFilter(this);
  // -----------------------------------------------------
}


void draw()
{
  
  // Pass the parameters to the filter
  myFilter.setMinCutoff(minCutoff);
  myFilter.setBeta(beta);
  
  // Save previous values (needed to draw the lines)
  sourceSignalPrev = sourceSignal;
  filteredSignalPrev = filteredSignal;
  noisySignalPrev = noisySignal;

  // Generate simulated signal based on Perlin noise
  sourceSignal = noise(frameCount / 250.0);
  noisySignal = sourceSignal + ( noise(frameCount) - 0.5 )  / 10.0;

  
  // -----------------------------------------------------
  // Filter the signal [THIS IS THE IMPORTANT LINE HERE!]
     filteredSignal = myFilter.filterUnitFloat( noisySignal );
  // -----------------------------------------------------
  
  

  float textBgHeight = 30;
  color textBgColor = color(150);

  // Compute x positions to draw the plot line
  float x1 = xPos-0.1;
  float x2 = xPos;  
  
  float sectionSize = height / 3.0;

  // Draw original signal
  noStroke();
  fill(255);
  float ySource1 = map(sourceSignalPrev, 0.0, 1.0, textBgHeight, sectionSize);
  float ySource2 = map(sourceSignal, 0.0, 1.0, textBgHeight, sectionSize);
  stroke(255);
  line(x1, ySource1, x2, ySource2);
  noStroke();
  fill(textBgColor);
  rect(0, 0, width, textBgHeight );
  fill(255);
  text( "Original signal", 10, 20 );

  // Draw noisy signal
  pushMatrix();
  translate(0, sectionSize);
  noStroke();
  fill(255);
  float yNoisy1 = map(noisySignalPrev, 0.0, 1.0, textBgHeight, sectionSize);
  float yNoisy2 = map(noisySignal, 0.0, 1.0, textBgHeight, sectionSize);
  stroke(255);
  line(x1, yNoisy1, x2, yNoisy2);
  noStroke();
  fill(textBgColor);
  rect(0, 0, width, textBgHeight );
  fill(255);
  text( "Noisy signal", 10, 20 );
  popMatrix();

  // Draw filtered signal
  pushMatrix();
  translate(0, sectionSize * 2.0);
  noStroke();
  float yFiltered1 = map(filteredSignalPrev, 0.0, 1.0, textBgHeight, sectionSize);
  float yFiltered2 = map(filteredSignal, 0.0, 1.0, textBgHeight, sectionSize);
  stroke(255);
  line(x1, yFiltered1, x2, yFiltered2);
  noStroke();
  fill(textBgColor);
  rect(0, 0, width, textBgHeight );
  fill(255);
  text( "Filtered signal", 10, 20 );
  popMatrix();


  // Output the values to the console for debug
  println( " " );
  println( "source   = " + sourceSignal );
  println( "noisy    = " + noisySignal );
  println( "filtered = " + filteredSignal );
  
  // Move the head to the right
  xPos += 1;

  // Wrap condition
  if ( xPos > width ) {
    background(180); // clear screen
    xPos = 0.0;      // move back to the left
  }
}

SignalFilter

public SignalFilter(PApplet theParent,
                    int size)
Call this constructor in the setup() method of your sketch to initialize and start the library.

Parameters:
theParent - Your sketch's PApplet object
size - number of filtering channels
+Example
/*
 * This example demonstrates the use of the filterUnitArray() 
 * function to deal with any number of signals. 
 * 
 * Dark grey circles   -> Source signals (simulated using Perlin noise) 
 * Jittery circles     -> Noisy signals
 * Small white circles -> Filtered signals 
 * 
 */

import signal.library.*;

// -----------------------------------------------------
// Create the filters
   SignalFilter myFilters;
// -----------------------------------------------------

// Main OneEuroFilter parameters
float minCutoff = 0.5;  // decrease this to get rid of slow speed jitter
float beta      = 13.0; // increase this to get rid of high speed lag

// How many parallel signals do we want?
int numChannels = 15;

// Edit this to simulate different types 
// of signal/noise combinations
float signalSpeed = 3.0;
float noiseStrenght = 0.08;
float noiseSpeed = 0.8;

// Signal channels
float[] sourceSignals;
float[] noisySignals;
float[] filteredSignals;

// Used to randomize the noise channels
float[] noiseOffsets;

void setup() {

  size(512, 512);
  
  noFill();
  
  // Initialize the signal arrays
  sourceSignals   = new float[numChannels]; // Simulated signals based on Perlin noise
  noisySignals    = new float[numChannels]; // Simulated signals with added high frequency noise
  filteredSignals = new float[numChannels]; // The filtered signals to be generated 

  // -----------------------------------------------------
  // Initialize the filters
     myFilters = new SignalFilter(this, numChannels);
  // -----------------------------------------------------
  
  
  // Randomize the position of each simulated signal on the noise spectrum
  noiseOffsets = new float[numChannels];
  for(int i = 0; i < numChannels; i++) { 
    noiseOffsets[i] = random(1000000);
  }

  
}


void draw()
{

  background(155);
  
  // Pass the parameters to the filter
  myFilters.setMinCutoff(minCutoff);
  myFilters.setBeta(beta);
  
  // Create the individual dummy signals (don't worry too much about those lines)
  for(int currentChannel = 0; currentChannel < numChannels; currentChannel++) { 
    sourceSignals[currentChannel] = noise( ( frameCount + noiseOffsets[currentChannel] )  / 500.0 * signalSpeed );
    noisySignals[currentChannel] = sourceSignals[currentChannel] + ( noise(frameCount * noiseSpeed + (float)currentChannel) - 0.5 )  * noiseStrenght;
  }

  
  // -----------------------------------------------------------
  // Filter the signals array [THIS IS THE IMPORTANT LINE HERE!]
     filteredSignals = myFilters.filterUnitArray( noisySignals );
  // -----------------------------------------------------------


  // How large should each element be?
  float w = width/(float)numChannels;

  // Draw rectangles for each signal
  for(int currentChannel = 0; currentChannel < numChannels; currentChannel++) {
    
    float x = w * (float)currentChannel;
    float ySource   = height - ( sourceSignals[currentChannel] * height );
    float yNoisy    = height - ( noisySignals[currentChannel] * height );
    float yFiltered = height - ( filteredSignals[currentChannel] * height );
    
    noStroke();
    
    // Noisy signal
    fill(130);
    ellipse(x + w/2, yNoisy, w, w);
    
    // Original signal
    fill(100);
    ellipse(x + w/2, ySource, w, w);
    
    // Filtered signal
    fill(200);
    ellipse(x + w/2, yFiltered, w * 0.6, w * 0.6);
    
  }


}
Method Detail

filterUnitVector

public PVector filterUnitVector(PVector noisyVector)
Return filtered values for the given PVector Note: values have to be at the unit scale [0.0, 1.0]

Parameters:
noisyVector -
Returns:
filteredVector

filterUnitFloat

public float filterUnitFloat(float noisyFloat)
Return filtered value for the given float Note: value has to be at the unit scale [0.0, 1.0]

Parameters:
noisyFloat -
Returns:
filteredFloat

filterUnitArray

public float[] filterUnitArray(float[] noisyArray)
Return filtered values for the given float[] array Note: values have to be at the unit scale [0.0, 1.0]

Parameters:
noisyArray -
Returns:
filteredArray

filterCoord2D

public PVector filterCoord2D(PVector noisyVector,
                             float scaleX,
                             float scaleY)
Convenience method to filter 2D coordinate values passed as a PVector

Parameters:
noisyVector - coordinates as a PVector
scaleX - width of the coordinate space
scaleY - height of the coordinate space
Returns:
filteredVector

filterCoord2D

public PVector filterCoord2D(float coordX,
                             float coordY,
                             float scaleX,
                             float scaleY)
Convenience method to filter 2D coordinate values passed as floats

Parameters:
coordX - coordinate on the X-axis as a float
coordY - coordinate on the Y-axis as a float
scaleX - width of the coordinate space
scaleY - height of the coordinate space
Returns:
filteredVector

filterCoord3D

public PVector filterCoord3D(PVector noisyVector,
                             float scaleX,
                             float scaleY,
                             float scaleZ)
Convenience method to filter 3D coordinate values passed as a PVector

Parameters:
noisyVector -
Returns:
filteredVector

filterCoord3D

public PVector filterCoord3D(float coordX,
                             float coordY,
                             float coordZ,
                             float scaleX,
                             float scaleY,
                             float scaleZ)
Convenience method to filter 3D coordinate values passed as float

Parameters:
coordX - coordinate on the X-axis as a float
coordY - coordinate on the Y-axis as a float
coordZ - coordinate on the Z-axis as a float
scaleX - width of the coordinate space
scaleY - height of the coordinate space
scaleZ - depth of the coordinate space
Returns:
filteredVector

setFrequency

public void setFrequency(float f)
Set the frequency for all filtering channels

Parameters:
f - Frequency parameter of the OneEuro Filter

setMinCutoff

public void setMinCutoff(float mc)
Set the minimum cutoff for all the filtering channels

Parameters:
mc - Minimum cutoff (intercept) parameter of the OneEuro Filter

setBeta

public void setBeta(float b)
Set the Beta (cutoff slope) parameter for all filtering channels

Parameters:
b - Beta (cutoff slope) parameter of the OneEuro Filter

setDerivateCutoff

public void setDerivateCutoff(float dc)
Set the derivative cutoff for all filtering channels

Parameters:
b - Cutoff for derivative parameter of the OneEuro Filter


Processing library signalFilter by Raphael de Courville. (c) 2013