Digital Music Programming II: midismooth~




This lab demonstrates how to properly convert MIDI data to audio control-rate data by using a one-pole conditioning filter.

The difference equation for the midismooth~ object is:

   y[n] = k * x[n] + (1-k) * y[n-1]

The flowgraph for the filter is:

Magnitude Frequency Response of the filter when k = 0.001:


Source Code Example Usage
midismooth.c


#include "ext.h"
#include "z_dsp.h"

typedef struct {
   t_pxobject msp_data;
   float      k;
   float      min;
   float      max;
   long       input;
   float      scale;
   float      scaledinput;
   float      lastoutput;
} MyObject;

void*  object_data;

void   main             (void);
void*  create_object    (void);
void   InputMIDI        (MyObject* mo, long value);
void   InputGain        (MyObject* mo, float value);
void   InputMin         (MyObject* mo, float value);
void   InputMax         (MyObject* mo, float value);
void   MessageDSP       (MyObject* mo, t_signal** signal, short* count);
void   MessageClear     (MyObject* mo);
t_int* Perform          (t_int *parameters);
float  randfloat        (void);

void main(void) {
   setup((t_messlist**)&object_data, (method)create_object,
         (method)dsp_free, (short)sizeof(MyObject), NULL, A_NOTHING);
   addint((method)InputMIDI);
   addftx((method)InputGain, 3);
   addftx((method)InputMin,  2);
   addftx((method)InputMax,  1);
   addmess((method)MessageClear, "clear", A_NOTHING);
   addmess((method)MessageDSP,   "dsp", A_CANT, A_NOTHING);
   dsp_initclass();
}

void* create_object(void) {
   MyObject *mo = (MyObject*)newobject(object_data);
   dsp_setup((t_pxobject*)mo, 0);
   outlet_new((t_pxobject*)mo, "signal");
   floatin(mo, 1);
   floatin(mo, 2);
   floatin(mo, 3);
   mo->k           = 0.001;
   mo->min         = 0.0;
   mo->max         = 127.0;
   mo->lastoutput  = 0.0;
   mo->input       = 0;
   mo->scale       = (mo->max-mo->min+1.0)/127.0;
   mo->scaledinput = 0.0;
   return mo;
}

void InputMIDI(MyObject* mo, long value) {
   mo->input = value;
   mo->scaledinput = mo->input * mo->scale + mo->min;
   post("scaled value is: %f", mo->scaledinput);
}

void InputGain(MyObject *mo, float value) {
    mo->k = value;
}

void InputMin(MyObject *mo, float value) {
   float temp;
   mo->min = value;
   if (mo->min > mo->max) {
      temp = mo->min;
      mo->min = mo->max;
      mo->max = temp;
   }
   mo->scale = (mo->max-mo->min+1.0)/127.0;
   mo->scaledinput = mo->input * mo->scale + mo->min;
}

void InputMax(MyObject *mo, float value) {
   float temp;
   mo->max = value;
   if (mo->min > mo->max) {
      temp = mo->min;
      mo->min = mo->max;
      mo->max = temp;
   }
   mo->scale = (mo->max-mo->min+1.0)/127.0;
   mo->scaledinput = mo->input * mo->scale + mo->min;
}

void MessageDSP(MyObject* mo, t_signal** signal, short* count) {
   #pragma unused(count)
   dsp_add(Perform, 4, 4, mo, signal[0]->s_vec, signal[0]->s_n);
}

void MessageClear(MyObject* mo) {
   mo->lastoutput = 0.0;
}

t_int* Perform(t_int *parameters) {
   long      pcount = (long)     (parameters[1]);
   MyObject *mo     = (MyObject*)(parameters[2]);
   t_float  *output = (t_float*) (parameters[3]);
   long      count  = (int)      (parameters[4]);
   long      i;

   for (i=0; i<count; i++) {
      output[i] = mo->k * mo->scaledinput + (1.0-mo->k) * mo->lastoutput;
      mo->lastoutput = output[i];
   }

   return parameters+pcount+1;
}


Exercises

  1. Compile and test the midismooth~ object.

  2. Compare the sound when the filter gain is 0.001 and 1.0. How does the sound behave when the input MIDI values change?


  3. Try different values for k, such as 0.0, 1.0, 0.1, 0.9, 0.00001, etc. How does k affect the sound when the MIDI input is changed?

  4. Examine the help screen for the slide~ MSP object. What is the difference equation mentioned in the help window? How does that difference equation relate to the one for the midismooth~ object? Modify the midismooth~ object to create an object called midislide which has similar filter behaviors as the slide~ MSP object.