Skip to content

Commit

Permalink
Merge pull request #451 from cviejo/midiout-utility-functions
Browse files Browse the repository at this point in the history
added channel voice message to MidiOut
  • Loading branch information
gewang authored Jul 10, 2024
2 parents a55ce5c + d0bf2d5 commit 74e5ccd
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 21 deletions.
30 changes: 27 additions & 3 deletions VERSIONS
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ChucK VERSIONS log
- (updated) chugin API version from 10.1 to 10.2
- (added) chugin API for callback on shutdown
- (added) chugin API for setting array elements (thanks azaday)
- (added) overloaded constructors added (more to come)
- (added) overloaded constructors (more to come)
==================
Envelope( dur durationToTarget )
Construct an Envelope with duration to reach target (assumed to be 1.0);
Expand All @@ -33,14 +33,38 @@ ChucK VERSIONS log
==================
- (added) new member functions
==================
fun dur Envelope.ramp( dur durationToTarget, float target );
dur Envelope.ramp( dur durationToTarget, float target );
Over the given duration, ramp toward the specified target; returns the given
duration.
fun dur Envelope.ramp( float secondsToTarget, float target );
dur Envelope.ramp( float secondsToTarget, float target );
Over the given duration (in seconds), ramp toward the specified target; returns
the given duration.
==================
- (added) examples/basic/envelope2.ck -- to show Envelope.ramp() in action
- (added) new MIDI message voice message convenience functions (thanks @cviejo;
previously these are possible only through `MidiOut.send( MidiMsg msg )`:
==================
int MidiOut.send( int status, int data1, int data2 );
Send out a MIDI message consisting of one status byte and two data bytes.
int channelPressure(int channel, int pressure)
Send out a channelPressure message.
int controlChange(int channel, int controller, int value)
Send out a controlChange message.
int noteOff(int channel, int note, int velocity)
Send out a noteOff message.
int noteOn(int channel, int note, int velocity)
Send out a noteOn message.
int pitchBend(int channel, int value)
Send out a pitchBend message.
int pitchBend(int channel, int lsb, int msb)
Send out a pitchBend message with fine and coarse values.
int polyPressure(int channel, int note, int pressure)
Send out a polyPressure message.
int programChange(int channel, int program)
Send out a programChange message.
==================
- (added) examples/midi/midiout2.ck -- demonstrates using the above channel
voice messages
- (added) examples/deep/smb.ck -- a ChucK rendition of Super Mario Bros.
original theme by Koji Kondo; (meticulously) modeled in ChucK by
Wesley Burchell in 2017
Expand Down
1 change: 1 addition & 0 deletions examples/midi/midiout.ck
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// name: midiout.ck
// desc: example of sending MIDI messages
// note: for a good explanation of how MIDI messages work, see after the code
// also see midiout2.ck for sending by common channel voice message
//-----------------------------------------------------------------------------

// instantiate a MIDI out object
Expand Down
50 changes: 50 additions & 0 deletions examples/midi/midiout2.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//-----------------------------------------------------------------------------
// name: midiout2.ck
// desc: example of sending MIDI messages using MidiOut only
// requires: chuck-1.5.2.5 or higher | author: cviejo
// note: for a good explanation of how MIDI messages work and sending raw midi
// messages, see midiout.ck
//-----------------------------------------------------------------------------

// instantiate a MIDI out object
MidiOut mout;
// open a MIDI device for output
if( !mout.open(0) ) me.exit();

<<< "MIDI output device opened...", "" >>>;

// loop
while( true )
{
<<< "sending note on message...", "" >>>;
mout.noteOn( 0, 60, 127 );
1::second => now;

<<< "sending note off message...", "" >>>;
mout.noteOff( 0, 60, 0 );
1::second => now;

<<< "sending control change message...", "" >>>;
mout.controlChange( 0, 14, 127 );
1::second => now;

<<< "sending program change message...", "" >>>;
mout.programChange( 0, 6 );
1::second => now;

<<< "sending polyphonic key pressure (aftertouch)...", "" >>>;
mout.polyPressure( 0, 60, 127 );
1::second => now;

<<< "sending channel pressure (aftertouch)...", "" >>>;
mout.channelPressure( 0, 127 );
1::second => now;

<<< "sending pitch bend message...", "" >>>;
mout.pitchBend( 0, 96 ); // +50% or 1.00 semitone up
1::second => now;

<<< "sending fine resolution pitch bend message...", "" >>>;
mout.pitchBend( 0, 50, 96 ); // +51% or 1.01 semitone up
1::second => now;
}
156 changes: 152 additions & 4 deletions src/core/chuck_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ t_CKBOOL init_class_Midi( Chuck_Env * env )
type_engine_import_class_end( env );

// doc string
doc = "Class for sending out Midi messages.";
doc = "Class for sending out MIDI messages. Note that channel numbers are 0-based.";
// init base class
if( !type_engine_import_class_begin( env, "MidiOut", "Object",
env->global(), MidiOut_ctor, MidiOut_dtor, doc.c_str() ) )
Expand Down Expand Up @@ -864,14 +864,84 @@ t_CKBOOL init_class_Midi( Chuck_Env * env )
func->doc = "Set error printing (1 for on, 0 for off). On by default.";
if( !type_engine_import_mfun( env, func ) ) goto error;

// add send()
// add send() | 1.5.2.5 (ge) added
func = make_new_mfun( "int", "send", MidiOut_send );
func->add_arg( "int", "status" );
func->add_arg( "int", "data1" );
func->add_arg( "int", "data2" );
func->doc = "Send out a MIDI message consisting of one status byte and two data bytes.";
if( !type_engine_import_mfun( env, func ) ) goto error;

// add send()
func = make_new_mfun( "int", "send", MidiOut_send_msg );
func->add_arg( "MidiMsg", "msg" );
func->doc = "Send out a MidiMsg message.";
func->doc = "Send out a MIDI message using a MidiMsg.";
if( !type_engine_import_mfun( env, func ) ) goto error;

// add noteOn() | 1.5.2.5 (cviejo) added
func = make_new_mfun( "int", "noteOn", MidiOut_noteOn );
func->add_arg( "int", "channel" );
func->add_arg( "int", "note" );
func->add_arg( "int", "velocity" );
func->doc = "Send out a noteOn message.";
if( !type_engine_import_mfun( env, func ) ) goto error;

// add noteOff() | 1.5.2.5 (cviejo) added
func = make_new_mfun( "int", "noteOff", MidiOut_noteOff );
func->add_arg( "int", "channel" );
func->add_arg( "int", "note" );
func->add_arg( "int", "velocity" );
func->doc = "Send out a noteOff message.";
if( !type_engine_import_mfun( env, func ) ) goto error;

// add controlChange() | 1.5.2.5 (cviejo) added
func = make_new_mfun( "int", "controlChange", MidiOut_controlChange );
func->add_arg( "int", "channel" );
func->add_arg( "int", "controller" );
func->add_arg( "int", "value" );
func->doc = "Send out a controlChange message.";
if( !type_engine_import_mfun( env, func ) ) goto error;

// add programChange() | 1.5.2.5 (cviejo) added
func = make_new_mfun( "int", "programChange", MidiOut_programChange );
func->add_arg( "int", "channel" );
func->add_arg( "int", "program" );
func->doc = "Send out a programChange message.";
if( !type_engine_import_mfun( env, func ) ) goto error;

// add pitchBend() | 1.5.2.5 (cviejo) added
func = make_new_mfun( "int", "pitchBend", MidiOut_pitchBend );
func->add_arg( "int", "channel" );
func->add_arg( "int", "value" );
func->doc = "Send out a pitchBend message.";
if( !type_engine_import_mfun( env, func ) ) goto error;

// add pitchBend() - fine resolution | 1.5.2.5 (cviejo) added
func = make_new_mfun( "int", "pitchBend", MidiOut_pitchBend_fine );
func->add_arg( "int", "channel" );
func->add_arg( "int", "lsb" );
func->add_arg( "int", "msb" );
func->doc = "Send out a pitchBend message with fine and coarse values.";
if( !type_engine_import_mfun( env, func ) ) goto error;

// add polyPressure() | 1.5.2.5 (cviejo) added
func = make_new_mfun( "int", "polyPressure", MidiOut_polyPressure );
func->add_arg( "int", "channel" );
func->add_arg( "int", "note" );
func->add_arg( "int", "pressure" );
func->doc = "Send out a polyPressure message.";
if( !type_engine_import_mfun( env, func ) ) goto error;

// add channelPressure() | 1.5.2.5 (cviejo) added
func = make_new_mfun( "int", "channelPressure", MidiOut_channelPressure );
func->add_arg( "int", "channel" );
func->add_arg( "int", "pressure" );
func->doc = "Send out a channelPressure message.";
if( !type_engine_import_mfun( env, func ) ) goto error;

// add examples
if( !type_engine_import_add_ex( env, "midi/midiout.ck" ) ) goto error;
if( !type_engine_import_add_ex( env, "midi/midiout2.ck" ) ) goto error;

// add member variable
MidiOut_offset_data = type_engine_import_mvar( env, "int", "@MidiOut_data", FALSE );
Expand Down Expand Up @@ -2417,7 +2487,16 @@ CK_DLL_MFUN( MidiOut_printerr )
mout->set_suppress( !print_or_not );
}

CK_DLL_MFUN( MidiOut_send )
CK_DLL_MFUN( MidiOut_send ) // 1.5.2.5 | (ge) added
{
MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
t_CKBYTE status = (t_CKBYTE)GET_NEXT_INT(ARGS);
t_CKBYTE data1 = (t_CKBYTE)GET_NEXT_INT(ARGS);
t_CKBYTE data2 = (t_CKBYTE)GET_NEXT_INT(ARGS);
RETURN->v_int = mout->send( status, data1, data2 );
}

CK_DLL_MFUN( MidiOut_send_msg )
{
MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS);
Expand All @@ -2428,6 +2507,75 @@ CK_DLL_MFUN( MidiOut_send )
RETURN->v_int = mout->send( &the_msg );
}

CK_DLL_MFUN( MidiOut_noteOn ) // 1.5.2.5 (cviejo) added
{
MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
t_CKINT channel = GET_NEXT_INT(ARGS);
t_CKINT note = GET_NEXT_INT(ARGS);
t_CKINT velocity = GET_NEXT_INT(ARGS);
RETURN->v_int = mout->noteon( channel, note, velocity );
}

CK_DLL_MFUN( MidiOut_noteOff )
{
MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
t_CKINT channel = GET_NEXT_INT(ARGS);
t_CKINT note = GET_NEXT_INT(ARGS);
t_CKINT velocity = GET_NEXT_INT(ARGS);
RETURN->v_int = mout->noteoff( channel, note, velocity );
}

CK_DLL_MFUN( MidiOut_controlChange )
{
MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
t_CKINT channel = GET_NEXT_INT(ARGS);
t_CKINT control = GET_NEXT_INT(ARGS);
t_CKINT value = GET_NEXT_INT(ARGS);
RETURN->v_int = mout->ctrlchange( channel, control, value );
}

CK_DLL_MFUN( MidiOut_programChange )
{
MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
t_CKINT channel = GET_NEXT_INT(ARGS);
t_CKINT program = GET_NEXT_INT(ARGS);
RETURN->v_int = mout->progchange( channel, program );
}

CK_DLL_MFUN( MidiOut_pitchBend )
{
MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
t_CKINT channel = GET_NEXT_INT(ARGS);
t_CKINT value = GET_NEXT_INT(ARGS);
RETURN->v_int = mout->pitchbend( channel, value );
}

CK_DLL_MFUN( MidiOut_pitchBend_fine )
{
MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
t_CKINT channel = GET_NEXT_INT(ARGS);
t_CKINT lsb = GET_NEXT_INT(ARGS);
t_CKINT msb = GET_NEXT_INT(ARGS);
RETURN->v_int = mout->pitchbendFine( channel, lsb, msb );
}

CK_DLL_MFUN( MidiOut_polyPressure )
{
MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
t_CKINT channel = GET_NEXT_INT(ARGS);
t_CKINT note = GET_NEXT_INT(ARGS);
t_CKINT pressure = GET_NEXT_INT(ARGS);
RETURN->v_int = mout->polypress( channel, note, pressure );
}

CK_DLL_MFUN( MidiOut_channelPressure )
{
MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
t_CKINT channel = GET_NEXT_INT(ARGS);
t_CKINT pressure = GET_NEXT_INT(ARGS);
RETURN->v_int = mout->chanpress( channel, pressure );
}

#endif // __DISABLE_MIDI__


Expand Down
9 changes: 9 additions & 0 deletions src/core/chuck_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,15 @@ CK_DLL_MFUN( MidiOut_num );
CK_DLL_MFUN( MidiOut_name );
CK_DLL_MFUN( MidiOut_printerr );
CK_DLL_MFUN( MidiOut_send );
CK_DLL_MFUN( MidiOut_send_msg );
CK_DLL_MFUN( MidiOut_noteOn );
CK_DLL_MFUN( MidiOut_noteOff );
CK_DLL_MFUN( MidiOut_controlChange );
CK_DLL_MFUN( MidiOut_programChange );
CK_DLL_MFUN( MidiOut_pitchBend );
CK_DLL_MFUN( MidiOut_pitchBend_fine );
CK_DLL_MFUN( MidiOut_polyPressure );
CK_DLL_MFUN( MidiOut_channelPressure );
#endif // __DISABLE_MIDI__


Expand Down
Loading

0 comments on commit 74e5ccd

Please sign in to comment.