Digital Music Programming II: Assignment 1
For this assignment, you will create a Max object, called
voice, which will keep track of note-offs for a monophonic
voice.
The object will remember the last note that was sent through it.
When a new note is sent into the object, it will check to see if the
last note needs to be turned off. If so, it will send a note off
for the last note that came in and then it will send the new note
message.
Below is a picture of the object you will write. There
are two inputs and two outputs detailed in the table below.
Inputs:
- A MIDI note number to played.
- An attack velocity for the note.
|
Outputs:
- The MIDI note number that came from the input (and possibly
the previous note number to turn off).
- The attack velocity that came from the input (and possiblly
a zero velocity to turn off the previous note.
|
|
As an example of how the voice object will work, consider
the following example. First play the note C on a synthesizer by
going through the object to noteout. Next, play the note
D
Other things to consider when implementing the voice object:
- If the last note message sent out was a note-off, then the voice object
will not send an additional note-off message.
- Optionally, have the voice object accept bang messages
which will turn off the current note in memory.
- Extra Credit: Have the object respond to the "off" message
which will turn off the current note it has in memory.
- Extra Credit: Add an inlet and outlet for MIDI channel
number to keep track of voices which change to different
channels.
Code Template
Either write your own program, or fill in the sections in the
following program shell:
//
// Programmer: YOUR NAME HERE
// Filename: voice.c
// Syntax: C; Max4/MSP2 External Object; CodeWarrior 6.0
// OS: Mac OS 9; PPC
//
// Description: Monophonic voice manager.
//
#include "ext.h"
typedef struct {
t_object maxData; // Max/MSP data, MUST come first in struct
long curkey; // Current note being played
long curvel; // Current velocity of note being played
long invel; // velocity input value (temp storage)
void* outputKeyNumber; // output bang function pointer
void* outputVelocity; // output bang function pointer
} MyObject;
void* objectdata = NULL;
// function declarations:
void* create_object (void);
void InputBang (MyObject* mo);
void InputKeyNumber (MyObject* mo, long value);
void InputVelocity (MyObject* mo, long value);
/////////////////////////////////////////////////////////////////////////
//
// Initialization functions
//
//////////////////////////////
//
// main -- called once when the object is created in a patcher window.
//
void main(void) {
setup((t_messlist**)&objectdata, (method)create_object, NULL,
sizeof(MyObject), NULL, A_DEFLONG, A_NOTHING);
addbang((method)InputBang);
addint ((method)InputKeyNumber);
addinx ((method)InputVelocity, 1);
}
//////////////////////////////
//
// create_object -- create the data storage for the mydiff object and
// and setup input 1.
//
void* create_object(void) {
MyObject *mo;
mo = (MyObject*)newobject(objectdata);
mo->outputVelocity = intout(mo); // create outlet 2
mo->outputKeyNumber = intout(mo); // create outlet 1
intin(mo, 1); // create inlet 2
return mo;
}
/////////////////////////////////////////////////////////////////////////
//
// Behavior functions
//
//////////////////////////////
//
// InputBang -- behavior of the object when a "bang" message is received.
// Turn off the current note if it is playing (has a non-zero
// velocity).
//
void InputBang(MyObject* mo) {
}
//////////////////////////////
//
// InputKeyNumber -- what to do when a new key number comes in.
// When a new note number comes into the object do these things:
// (1) check to see if the last note should be turned off.
// (2) if current note is still on, then send a note off message
// to the outlets.
// (3) send the input note to the outlets.
// (4) store the input note into the current note memory.
//
void InputKeyNumber(MyObject* mo, long value) {
}
//////////////////////////////
//
// InputVelocity -- what to do when a new velocity value comes in.
// Store the velocity in a temporary location, but don't erase the last
// velocity that was sent out with the last note out.
//
void InputVelocity(MyObject* mo, long value) {
}
|
Email me the source code for your program when it is finished.
After you have compiled it and tested it in Max.
|