Skip to content

Commit

Permalink
midi incremental cc message support
Browse files Browse the repository at this point in the history
  • Loading branch information
gaborpapp committed Mar 28, 2011
1 parent c1f1299 commit 225f895
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGES
Expand Up @@ -5,6 +5,7 @@ Fluxus : (C) 2008 Dave Griffiths : dave at pawfal dot org : www.pawfal.org
* compressed texture support
* added (midi-program) and (midi-cc-event) by Hugo van Galen
* midi out support
* midi incremental cc messages (midi-set-cc-mode), (midi-get-cc-mode)
* updated to Racket
* added (draw-line)
* pixel primitives with more texture attachments for feedback effects and FFGL plugins
Expand Down
2 changes: 1 addition & 1 deletion docs/helpmap.scm

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion examples/midi-test.scm
Expand Up @@ -5,7 +5,7 @@

(display (midi-info))(newline)

(midi-init 1)
(midiin-open 0)

(define (midi-test)
(with-state
Expand Down
101 changes: 101 additions & 0 deletions modules/fluxus-midi/src/FluxusMIDI.cpp
Expand Up @@ -270,6 +270,103 @@ Scheme_Object *midiout_close(int argc, Scheme_Object **argv)
return scheme_void;
}

// StartFunctionDoc-en
// midi-set-cc-mode mode-symbol
// Returns: void
// Description:
// Sets the controller encoder mode. The mode can be 'absolute, 'doepfer or 'ableton.
// The default is 'absolute. 'doepfer and 'ableton are incremental encoding modes.
// Example:
// (midi-set-cc-mode 'ableton)
// EndFunctionDoc

Scheme_Object *midi_set_cc_mode(int argc, Scheme_Object **argv)
{
MZ_GC_DECL_REG(1);
MZ_GC_VAR_IN_REG(0, argv);
MZ_GC_REG();

if (!SCHEME_SYMBOLP(argv[0]))
scheme_wrong_type("midi-set-cc-mode", "symbol", 0, argc, argv);

string mode_str = scheme_symbol_name(argv[0]);

if (midilistener != NULL)
{
int mode = -1;

if (mode_str == "absolute")
{
mode = MIDIListener::MIDI_CC_ABSOLUTE;
}
else
if (mode_str == "doepfer")
{
mode = MIDIListener::MIDI_CC_DOEPFER;
}
else
if (mode_str == "ableton")
{
mode = MIDIListener::MIDI_CC_ABLETON;
}
else
{
cerr << "midi-set-cc-mode: unknown mode " << mode_str << endl;
}

if (mode != -1)
{
midilistener->set_cc_encoder_mode(mode);
}
}

MZ_GC_UNREG();
return scheme_void;
}

// StartFunctionDoc-en
// midi-get-cc-mode
// Returns: mode-symbol
// Description:
// Returns the controller encoder mode. The mode can be 'absolute, 'doepfer or 'ableton.
// Example:
// (define cc-mode (midi-get-cc-mode))
// EndFunctionDoc

Scheme_Object *midi_get_cc_mode(int argc, Scheme_Object **argv)
{
Scheme_Object *ret = NULL;
MZ_GC_DECL_REG(2);
MZ_GC_VAR_IN_REG(0, argv);
MZ_GC_VAR_IN_REG(1, ret);
MZ_GC_REG();

if (midilistener != NULL)
{
int mode = midilistener->get_cc_encoder_mode();

switch (mode)
{
case MIDIListener::MIDI_CC_ABSOLUTE:
ret = scheme_make_symbol("absolute");
break;
case MIDIListener::MIDI_CC_DOEPFER:
ret = scheme_make_symbol("doepfer");
break;
case MIDIListener::MIDI_CC_ABLETON:
ret = scheme_make_symbol("ableton");
break;
default:
cerr << "midi-get-cc-mode: unknown mode " << mode << endl;
ret = scheme_void;
break;
}
}

MZ_GC_UNREG();
return ret;
}

// StartFunctionDoc-en
// midi-cc channel-number controller-number
// Returns: controller-value-number
Expand Down Expand Up @@ -709,6 +806,10 @@ Scheme_Object *scheme_reload(Scheme_Env *env)

scheme_add_global("midi-info",
scheme_make_prim_w_arity(midi_info, "midi-info", 0, 0), menv);
scheme_add_global("midi-set-cc-mode",
scheme_make_prim_w_arity(midi_set_cc_mode, "midi-set-cc-mode", 1, 1), menv);
scheme_add_global("midi-get-cc-mode",
scheme_make_prim_w_arity(midi_get_cc_mode, "midi-get-cc-mode", 0, 0), menv);
scheme_add_global("midi-cc",
scheme_make_prim_w_arity(midi_cc, "midi-cc", 2, 2), menv);
scheme_add_global("midi-ccn",
Expand Down
72 changes: 60 additions & 12 deletions modules/fluxus-midi/src/MIDIListener.cpp
Expand Up @@ -51,15 +51,16 @@ void midi_callback(double deltatime, vector<unsigned char> *message,

MIDIListener::MIDIListener(int port /*= -1*/) :
midiin(NULL),
last_event("")
last_event(""),
cc_encoder_mode(MIDI_CC_ABSOLUTE)
{
init_midi();

if (port >= 0)
open(port);

/* allocate array for controller values and clear it */
cntrl_values = new unsigned char[MAX_CNTRL];
cntrl_values = new signed char[MAX_CNTRL];
fill(cntrl_values, cntrl_values + MAX_CNTRL, 0);

/* likewise for the per channel "program" values */
Expand Down Expand Up @@ -208,6 +209,24 @@ void MIDIListener::close()
}
}

/**
* Sets controller encoder mode
* \param mode MIDI_CC_ABSOLUTE, MIDI_CC_ABLETON or MIDI_CC_DOEPFER
**/
void MIDIListener::set_cc_encoder_mode(int mode)
{
cc_encoder_mode = mode;
}

/**
* Returns current controller encoder mode
* \retval mode MIDI_CC_ABSOLUTE, MIDI_CC_ABLETON or MIDI_CC_DOEPFER
**/
int MIDIListener::get_cc_encoder_mode(void)
{
return cc_encoder_mode;
}

/**
* Returns controller values.
* \param channel MIDI channel
Expand All @@ -223,8 +242,13 @@ int MIDIListener::get_cc(int channel, int cntrl_number)
return 0;
}

int i = (channel << 7) + cntrl_number;
pthread_mutex_lock(&mutex);
int v = cntrl_values[(channel << 7) + cntrl_number];
int v = cntrl_values[i];
if (cc_encoder_mode != MIDI_CC_ABSOLUTE)
{
cntrl_values[i] = 0;
}
pthread_mutex_unlock(&mutex);
return v;
}
Expand Down Expand Up @@ -264,8 +288,13 @@ float MIDIListener::get_ccn(int channel, int cntrl_number)
return 0;
}

int i = (channel << 7) + cntrl_number;
pthread_mutex_lock(&mutex);
float v = (float)cntrl_values[(channel << 7) + cntrl_number] / 127.0;
float v = (float)cntrl_values[i] / 127.0;
if (cc_encoder_mode != MIDI_CC_ABSOLUTE)
{
cntrl_values[i] = 0;
}
pthread_mutex_unlock(&mutex);
return v;
}
Expand Down Expand Up @@ -341,47 +370,47 @@ MIDIEvent *MIDIListener::get_cc_event(void)

int MIDIListener::get_bar(void)
{
pthread_mutex_lock(&mutex);
pthread_mutex_lock(&mutex);
int ret = bar;
pthread_mutex_unlock(&mutex);
return ret;
}

int MIDIListener::get_beat(void)
{
pthread_mutex_lock(&mutex);
pthread_mutex_lock(&mutex);
int ret = beat;
pthread_mutex_unlock(&mutex);
return ret;
}

int MIDIListener::get_pulse(void)
{
pthread_mutex_lock(&mutex);
pthread_mutex_lock(&mutex);
int ret = pulse;
pthread_mutex_unlock(&mutex);
return ret;
}

int MIDIListener::get_beats_per_bar()
{
pthread_mutex_lock(&mutex);
pthread_mutex_lock(&mutex);
int ret = beats_per_bar;
pthread_mutex_unlock(&mutex);
return ret;
}

int MIDIListener::get_clocks_per_beat()
{
pthread_mutex_lock(&mutex);
pthread_mutex_lock(&mutex);
int ret = clocks_per_beat;
pthread_mutex_unlock(&mutex);
return ret;
}

void MIDIListener::set_signature(int upper, int lower)
{
pthread_mutex_lock(&mutex);
pthread_mutex_lock(&mutex);
beats_per_bar = upper;
clocks_per_beat = (24*4)/lower;
pthread_mutex_unlock(&mutex);
Expand Down Expand Up @@ -449,10 +478,29 @@ void MIDIListener::callback(double deltatime, vector<unsigned char> *message)
case MIDIListener::MIDI_CONTROLLER:
if (count == 3)
{
int cntrl_number = (*message)[1]; /* controller number */
int cntrl_number; /* controller number */

if (cc_encoder_mode == MIDI_CC_DOEPFER)
cntrl_number = (*message)[2];
else
cntrl_number = (*message)[1];
/* array index from channel and controller number */
int i = (ch << 7) + cntrl_number;
int value = (*message)[2]; /* controller value */

int value; /* controller value */
if (cc_encoder_mode == MIDI_CC_DOEPFER)
{
value = (*message)[1] == 97 ? -1 : 1;
}
else
{
value = (*message)[2];
if ((cc_encoder_mode == MIDI_CC_ABLETON) && (value > 64))
{
value = 64 - value;
}
}

pthread_mutex_lock(&mutex);
cntrl_values[i] = value;
add_event(ch, cntrl_number, value);
Expand Down
15 changes: 14 additions & 1 deletion modules/fluxus-midi/src/MIDIListener.h
Expand Up @@ -63,6 +63,9 @@ class MIDIListener
void open(int port); /**< open a MIDI input connection */
void close(void); /**< close MIDI port */

void set_cc_encoder_mode(int mode);
int get_cc_encoder_mode(void);

int get_cc(int channel, int cntrl_number);
float get_ccn(int channel, int cntrl_number);
int get_program(int channel);
Expand Down Expand Up @@ -93,6 +96,13 @@ class MIDIListener
MIDI_CONTINUE = 0x0B,
MIDI_STOP = 0x0C
};
/** MIDI cc encoder types */
enum {
MIDI_CC_ABSOLUTE = 0,
MIDI_CC_DOEPFER, /* inc - cc#97 data=cc id, dec - cc#96, data=cc id */
MIDI_CC_ABLETON /* normal cc - data = 1-64 inc, 65-127 dec */
};

private:
void init_midi(void);
void add_note(int on_off, int ch, int note, int velocity);
Expand All @@ -107,16 +117,19 @@ class MIDIListener
string last_event; /**< last midi event as string */

/** array holding the current state of all, 16*128 controllers */
unsigned char *cntrl_values;
signed char *cntrl_values;

/** array holding program number of 16 channels **/
unsigned char *pgm_values;

deque<MIDINote *> midi_notes;
deque<MIDIEvent *> midi_events;

/* song position */
int bar, beat, pulse;
int beats_per_bar, clocks_per_beat;

int cc_encoder_mode;
};

#endif
Expand Down

0 comments on commit 225f895

Please sign in to comment.