// // Copyright: Copyright 2003 Craig Stuart Sapp // Programmer: Craig Stuart Sapp // Creation Date: Sat Feb 8 14:00:32 PST 2003 // Last Modified: Sat Feb 8 14:22:05 PST 2003 // Filename: duration.c // Web Address: http://peabody.sapp.org/class/dmp2/lab/duration/duration.c // Syntax: C; Max4/MSP2 External Object; CodeWarrior 6.0 // OS: Mac OS 9; PPC // // Description: Measure the duration of input notes. // #include "ext.h" typedef struct { t_object max_data; // Max/MSP data, MUST come first in struct long ontimes[127]; // onset times for notes coming into object long velin; // current input velocity void* outputKeyNumber; // output the note number of the note void* outputDuration; // output the duration of note in milliseconds } MyObject; void* object_data = NULL; // function declarations: void* create_object (void); void InputKeyNumber (MyObject* mo, long value); void InputVelocity (MyObject* mo, long value); void MessageClear (MyObject* mo); long midilimit (long value); ///////////////////////////////////////////////////////////////////////// // // Initialization functions // ////////////////////////////// // // main -- called once when the object is created in a patcher window. // void main(void) { setup((t_messlist**)&object_data, (method)create_object, NULL, sizeof(MyObject), NULL, A_NOTHING); addint ((method)InputKeyNumber); // inlet 1 addinx ((method)InputVelocity, 1); // inlet 2 addmess((method)MessageClear, "clear", A_NOTHING); } ////////////////////////////// // // create_object -- create the data storage for the mydiff object and // and setup input 1. // void* create_object(void) { MyObject* mo = (MyObject*)newobject(object_data); MessageClear(mo); mo->velin = 0; mo->outputDuration = intout(mo); // outlet 2 mo->outputKeyNumber = intout(mo); // outlet 1 intin(mo, 1); // inlet 2 return mo; } ///////////////////////////////////////////////////////////////////////// // // Behavior functions // ////////////////////////////// // // InputKeyNumber -- behavior of the object when a new number comes // in on inlet 1. If the message is a note-on, then store // the time that the note came in. If the message is a note-off, // then report the duration of the note. // void InputKeyNumber(MyObject* mo, long value) { long curtime = gettime(); value = midilimit(value); if (mo->velin == 0 && mo->ontimes[value] >= 0) { // a note was turned off outlet_int(mo->outputDuration, curtime - mo->ontimes[value]); outlet_int(mo->outputKeyNumber, value); mo->ontimes[value] = -1; } else if (mo->velin > 0 && mo->ontimes[value] >= 0) { // a note is replayed, but no note-off occured outlet_int(mo->outputDuration, curtime - mo->ontimes[value]); outlet_int(mo->outputKeyNumber, value); mo->ontimes[value] = curtime; } else if (mo->velin > 0) { // a note was turned on mo->ontimes[value] = curtime; } } ////////////////////////////// // // InputVelocity -- behavior of the object when a new number comes // in on inlet 2. // void InputVelocity(MyObject* mo, long value) { mo->velin = value; } ////////////////////////////// // // MessageClear -- behavior of the object when a "clear" message // is received by the object. // void MessageClear(MyObject* mo) { int i; for (i=0; i<128; i++) { mo->ontimes[i] = -1; } } ///////////////////////////////////////////////////////////////////////// // // Non-interface functions: // ////////////////////////////// // // midilimit -- limit a number to the range from 0 to 127. // if the input is less than 0, return 0. // if the input is greater than 127, return 127. // long midilimit(long value) { if (value < 0) return 0; if (value > 127) return 127; return value; }