Digital Music Programming II: sndpower~




This lab demonstrates how to monitor the power of a signal in decibels, root-mean-squared amplitude, and peak amplitude.


Source Code Example Usage
sndpower.c


#include "ext.h"
#include "z_dsp.h"
#include <cmath>

typedef struct {
   t_pxobject msp_data;
   double     sum;
   long       count, chunk;
   void*      outputDb, outputRms, outputPeak;
} MyObject;

void* object_data;

void   main               (void);
void*  create_object      (long maxsize);
void   InputBang          (MyObject* mo);
void   InputChunkSize     (MyObject* mo, long value);
void   MessageDSP         (MyObject* mo, t_signal** signal, short* count);
void   MessageClear       (MyObject* mo);
t_int* Perform            (t_int *parameters);
void   outputAnalysis     (MyObject* mo);

void main(void) {
   setup((t_messlist**)&object_data, (method)create_object,
         (method)dsp_free, (short)sizeof(MyObject),
         NULL, A_LONG, A_NOTHING);
   addinx((method)InputChunkSize, 1);
   addmess((method)MessageDSP, "dsp", A_CANT, A_NOTHING);
   addmess((method)MessageClear, "clear", A_NOTHING);
   addbang((method)InputBang);
   dsp_initclass();
}

void* create_object(long chunksize) {
   MyObject *mo = (MyObject*)newobject(object_data);
   dsp_setup((t_pxobject*)mo, 1);
   outlet_new(mo->msp_data, "signal");
   intin(mo, 1);
   mo->outputPeak = floatout(mo);
   mo->outputRms  = floatout(mo);
   mo->outputDb   = floatout(mo);
   mo->chunk      = chunksize;
   MessageClear(mo);
   return mo;
}

void InputBang(MyObject* mo) {
   outputAnalysis(mo);
   MessageClear(mo);
}

void InputChunkSize(MyObject *mo, long value) {
   mo->chunk = value;
}

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

void MessageClear(MyObject* mo) {
   mo->count = 0;
   mo->sum   = 0.0;
}

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

   for (i=0; i<count; i++) {
      mo->sum += input[i] * input[i];
      output[i] = input[i];
      mo->count++;
      if ((mo->count >= mo->chunk) && (mo->chunk > 0)) {
         outputAnalysis(mo);
         MessageClear(mo);
      }
   }

   return parameters+paramcount+1;
}

void outputAnalysis(MyObject* mo) {
   float db, rms, peak;
   if (mo->sum <= 0.0) {
      db = -1000.0;
   } else {
      db = (float)(10.0 * log10(mo->sum/mo->count));
   }
   rms  = (float)sqrt(mo->sum / mo->count);
   peak = (float)(sqrt(2) * rms);
   outlet_float(mo->outputPeak, peak);
   outlet_float(mo->outputRms,  rms);
   outlet_float(mo->outputDb,   db);
}


Exercises

  1. Compile and test the sndpower~ object.

  2. Recreate the following patch and try different amplitudes for the sinwave:



  3. Use whitenoise instead of a sinewave in the above patch. How do the power measurements relate to the input noise amplitude?