Digital Music Programming II: flip
This lab demonstrates how to switch the MIDI key number and
MIDI attack velocity so that the velocity controls pitch and the pitch
controls velocity.
A simple method of doing this is demonstrated in the following
patch:
Try out this patch. Whenever you play a loud note, a high note
will occur. Whenever you play a soft note, a low pitch will occur.
Also, if you play a high pitch, the resulting note will be loud, and
if you play a low note, the resulting pitch will be soft.
There is a bug in the above patch. Listen to a performance with
the above patch and determine what the bug is.
The following external object called flip flip fixes
the bug.
There are two inputs and two outputs for the flip object:
Inputs | Outputs |
1. MIDI Note Number | 1. MIDI Note Number
(from input 2) |
2. MIDI Attack Velocity | 2. MIDI Attack
Velocity (from input 1) |
Source Code
The first program below shows how to generate a monophonic flip program.
One note can be played at a time and not develope any bugs.
monoflip.c
#include "ext.h"
typedef struct {
t_object max_data;
long keyout;
long velin;
void* outputKeyNumber;
void* outputVelocity;
} MyObject;
void* object_data = NULL;
void* create_object (void);
void InputKeyNumber (MyObject* mo, long value);
void InputVelocity (MyObject* mo, long value);
void main(void) {
setup((t_messlist**)&object_data, (method)create_object,
NULL, sizeof(MyObject), NULL, A_NOTHING);
addint ((method)InputKeyNumber);
addinx ((method)InputVelocity, 1);
}
void* create_object(void) {
int i;
MyObject* mo = (MyObject*)newobject(object_data);
mo->velin = 0;
for (i=0; i<128; i++) mo->keymap[i] = 0;
mo->outputVelocity = intout(mo);
mo->outputKeyNumber = intout(mo);
intin(mo, 1);
return mo;
}
void InputKeyNumber(MyObject* mo, long value) {
if (mo->velin == 0) {
outlet_int(mo->outputVelocity, mo->velin);
outlet_int(mo->outputKeyNumber, mo->keyout);
} else {
outlet_int(mo->outputVelocity, value);
outlet_int(mo->outputKeyNumber, mo->velin);
mo->keyout = mo->velin;
}
}
void InputVelocity(MyObject* mo, long value) {
mo->velin = value;
}
|
Here is a fully polyphonic flip object which does not exhibit
the bug from monoflip.c or the plain
notein-noteout patch. Compare performance
using this object with the one above.
polyflip.c
#include "ext.h"
typedef struct {
t_object max_data;
long keymap[127];
long velin;
void* outputKeyNumber;
void* outputVelocity;
} MyObject;
void* object_data = NULL;
void* create_object (void);
void InputKeyNumber (MyObject* mo, long value);
void InputVelocity (MyObject* mo, long value);
long midilimit (long value);
void main(void) {
setup((t_messlist**)&object_data, (method)create_object,
NULL, sizeof(MyObject), NULL, A_NOTHING);
addint ((method)InputKeyNumber);
addinx ((method)InputVelocity, 1);
}
void* create_object(void) {
int i;
MyObject* mo = (MyObject*)newobject(object_data);
mo->velin = 0;
for (i=0; i<128; i++) mo->keymap[i] = 0;
mo->outputVelocity = intout(mo);
mo->outputKeyNumber = intout(mo);
intin(mo, 1);
return mo;
}
void InputKeyNumber(MyObject* mo, long value) {
value = midilimit(value);
if (mo->velin == 0) {
outlet_int(mo->outputVelocity, mo->velin);
outlet_int(mo->outputKeyNumber, mo->keymap[value]);
} else {
outlet_int(mo->outputVelocity, value);
outlet_int(mo->outputKeyNumber, mo->velin);
mo->keymap[value] = midilimit(mo->velin);
}
}
void InputVelocity(MyObject* mo, long value) {
mo->velin = value;
}
long midilimit(long value) {
if (value < 0) return 0;
if (value > 127) return 127;
return value;
}
|
Why is the midilimit function in polyflip.c
necessary?
Exercises
- Compile the two flip objects and test them with the following
patch:
using a sustained instrument such as organ.
- Write a Max patch which has the same behavior as the
flip object. Note that the following patch does not
have the same behavior:
- Write a program which mirrors the notes rather than switches the
key numbers and velocities. Add an input to the object for the
mirror position.
|