Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions examples/midi/midi-bytes-receive.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
MidiIn min;

if (!min.open(0)) {
me.exit();
}

int bytes[0];

while (min => now) {
while (min.recv(bytes)) {
chout <= "bytes: ";

for (auto byte : bytes) {
chout <= byte <= " ";
}

chout <= IO.newline();
}
}
10 changes: 10 additions & 0 deletions examples/midi/midi-bytes-send.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
MidiOut mout;

if (!mout.open(0)) {
me.exit();
}

// Full frame midi time code (MTC) message.
// SMPTE timecode: 01:02:03:04.20 (1 hour, 2 minutes, 3 seconds, 4 frames, 20 subframes).
// F0 7F 7F 01 01 01 02 03 04 14 F7
mout.send([ 0xF0, 0x7F, 0x7F, 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x14, 0xF7 ]);
37 changes: 37 additions & 0 deletions src/core/chuck_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,14 @@ t_CKBOOL init_class_Midi( Chuck_Env * env )
func->doc = "Return into the MidiMsg argument the next message in the queue from the device. Return 0 if the queue is empty or 1 if a message was in the queue and returned in the argument.";
if( !type_engine_import_mfun( env, func ) ) goto error;


// add recv()
func = make_new_mfun( "int", "recv", MidiIn_recv_bytes );
func->add_arg( "int[]", "bytes" );
func->doc = "Return into the int[] argument the next message in the queue from the device. Return 0 if the queue is empty or 1 if a message was in the queue and returned in the argument.";
if( !type_engine_import_mfun( env, func ) ) goto error;


// add can_wait()
func = make_new_mfun( "int", "can_wait", MidiIn_can_wait );
func->doc = "(internal) used by virtual machine for synthronization.";
Expand Down Expand Up @@ -880,6 +888,13 @@ t_CKBOOL init_class_Midi( Chuck_Env * env )
func->doc = "Send out a MIDI message using a MidiMsg.";
if( !type_engine_import_mfun( env, func ) ) goto error;

// add send()
func = make_new_mfun( "int", "send", MidiOut_send_bytes );
func->add_arg( "int[]", "data" );
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" );
Expand Down Expand Up @@ -2482,6 +2497,19 @@ CK_DLL_MFUN( MidiIn_recv )
}
}

CK_DLL_MFUN( MidiIn_recv_bytes )
{
MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data);
Chuck_ArrayInt * bytes = (Chuck_ArrayInt *)GET_NEXT_OBJECT(ARGS);
if( bytes == NULL )
{
RETURN->v_int = 0;
}
else
{
RETURN->v_int = min->recv( bytes );
}
}

CK_DLL_MFUN( MidiIn_can_wait )
{
Expand Down Expand Up @@ -2568,6 +2596,15 @@ CK_DLL_MFUN( MidiOut_send_msg )
RETURN->v_int = mout->send( &the_msg );
}


CK_DLL_MFUN( MidiOut_send_bytes )
{
MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
Chuck_ArrayInt * arr = (Chuck_ArrayInt *) GET_NEXT_OBJECT(ARGS);
RETURN->v_int = mout->send( arr );
}


CK_DLL_MFUN( MidiOut_noteOn ) // 1.5.2.5 (cviejo) added
{
MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
Expand Down
2 changes: 2 additions & 0 deletions src/core/chuck_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ CK_DLL_MFUN( MidiIn_num );
CK_DLL_MFUN( MidiIn_name );
CK_DLL_MFUN( MidiIn_printerr );
CK_DLL_MFUN( MidiIn_recv );
CK_DLL_MFUN( MidiIn_recv_bytes );
CK_DLL_MFUN( MidiIn_can_wait );


Expand All @@ -544,6 +545,7 @@ 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_send_bytes );
CK_DLL_MFUN( MidiOut_noteOn );
CK_DLL_MFUN( MidiOut_noteOff );
CK_DLL_MFUN( MidiOut_controlChange );
Expand Down
97 changes: 83 additions & 14 deletions src/core/midiio_rtmidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
#define MIDI_BUFFER_SIZE 8192

std::vector<RtMidiIn *> MidiInManager::the_mins;
std::vector< std::map< Chuck_VM *, CBufferAdvance * > > MidiInManager::the_bufs;
std::vector< std::map< Chuck_VM *, CBufferAdvanceVariable * > > MidiInManager::the_bufs;
std::vector<RtMidiOut *> MidiOutManager::the_mouts;
std::map< Chuck_VM *, CBufferSimple * > MidiInManager::m_event_buffers;

Expand Down Expand Up @@ -85,6 +85,32 @@ MidiOut::~MidiOut()



//-----------------------------------------------------------------------------
// name: send()
// desc: send an array of midi bytes
//-----------------------------------------------------------------------------
t_CKUINT MidiOut::send( Chuck_ArrayInt * arr )
{
if( !m_valid ) return 0;

t_CKINT length = arr->size();
t_CKUINT byte;

m_msg.clear();

for( int i = 0; i < length; i++ )
{
arr->get(i, &byte);
m_msg.push_back( byte );
}
mout->sendMessage( &m_msg );

return length;
}




//-----------------------------------------------------------------------------
// name: send()
// desc: send 1 byte midi message
Expand Down Expand Up @@ -543,8 +569,9 @@ t_CKBOOL MidiInManager::add_vm( Chuck_VM * vm, t_CKINT device_num,
}

// allocate the buffer
CBufferAdvance * cbuf = new CBufferAdvance;
if( !cbuf->initialize( MIDI_BUFFER_SIZE, sizeof(MidiMsg), m_event_buffers[vm] ) )
CBufferAdvanceVariable * cbuf = new CBufferAdvanceVariable;
// buffer size with an estimate of 3 bytes per message
if( !cbuf->initialize( MIDI_BUFFER_SIZE * 3, m_event_buffers[vm] ) )
{
if( !suppress_output )
EM_error2( 0, "MidiIn: couldn't allocate CBuffer for port %i...", device_num );
Expand Down Expand Up @@ -620,13 +647,58 @@ t_CKBOOL MidiIn::empty()


//-----------------------------------------------------------------------------
// name: get()
// desc: get message
// name: recv()
// desc: get a 3-byte midi message
//-----------------------------------------------------------------------------
t_CKUINT MidiIn::recv( MidiMsg * msg )
{
if( !m_valid ) return FALSE;
return m_buffer->get( msg, 1, m_read_index );

t_CKUINT size = m_buffer->getNextSize(m_read_index);

if( size == 0 ) return size;

// MSVC doesn't play well with VLAs, don't use t_CKBYTE tmp[size] here
std::vector<t_CKBYTE> tmp(size, 0);

m_buffer->get(tmp.data(), m_read_index);

for (t_CKUINT i = 0; i < size && i < 3; i++)
{
msg->data[i] = tmp[i];
}

return size;
}




//-----------------------------------------------------------------------------
// name: recv()
// desc: get a midi message of any byte length
//-----------------------------------------------------------------------------
t_CKUINT MidiIn::recv( Chuck_ArrayInt * arr )
{
if( !m_valid ) return FALSE;

t_CKUINT size = m_buffer->getNextSize(m_read_index);

if( size == 0 ) return 0;

std::vector<t_CKBYTE> tmp(size, 0);

// don't pass arr->m_vector.data() directly, that holds longs
m_buffer->get(tmp.data(), m_read_index);

arr->clear();

for (t_CKUINT i = 0; i < size; i++)
{
arr->push_back(tmp[i]);
}

return size;
}


Expand All @@ -651,21 +723,18 @@ void MidiInManager::cb_midi_input( double deltatime, std::vector<unsigned char>
EM_error2( 0, "MidiIn: couldn't find buffers for port %i...", device_num );
return;
}
MidiMsg m;
if( nBytes >= 1 ) m.data[0] = msg->at(0);
if( nBytes >= 2 ) m.data[1] = msg->at(1);
if( nBytes >= 3 ) m.data[2] = msg->at(2);

// put in all the buffers, make sure not active sensing
if( m.data[2] != 0xfe )
if( msg->back() != 0xfe )
{
for( std::map< Chuck_VM *, CBufferAdvance * >::iterator it =
for( std::map< Chuck_VM *, CBufferAdvanceVariable * >::iterator it =
the_bufs[device_num].begin(); it != the_bufs[device_num].end(); it++ )
{
CBufferAdvance * cbuf = it->second;
CBufferAdvanceVariable * cbuf = it->second;

if( cbuf != NULL )
{
cbuf->put( &m, 1 );
cbuf->put( msg->data(), msg->size() );
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/core/midiio_rtmidi.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,11 @@ class MidiOut
{ return m_suppress_output; }

public:

t_CKUINT send( t_CKBYTE status );
t_CKUINT send( t_CKBYTE status, t_CKBYTE data1 );
t_CKUINT send( t_CKBYTE status, t_CKBYTE data1, t_CKBYTE data2 );
t_CKUINT send( Chuck_ArrayInt * arr );
t_CKUINT send( const MidiMsg * msg );

public:
Expand Down Expand Up @@ -154,9 +156,10 @@ class MidiIn : public Chuck_Event
public:
t_CKBOOL empty();
t_CKUINT recv( MidiMsg * msg );
t_CKUINT recv( Chuck_ArrayInt * msg );

public:
CBufferAdvance * m_buffer;
CBufferAdvanceVariable * m_buffer;
t_CKUINT m_read_index;
RtMidiIn * min;
t_CKBOOL m_valid;
Expand Down Expand Up @@ -193,7 +196,7 @@ class MidiInManager
static t_CKBOOL add_vm( Chuck_VM * vm, t_CKINT device_num, t_CKBOOL suppress_output );

static std::vector<RtMidiIn *> the_mins;
static std::vector< std::map< Chuck_VM *, CBufferAdvance * > > the_bufs;
static std::vector< std::map< Chuck_VM *, CBufferAdvanceVariable * > > the_bufs;

public:
static std::map< Chuck_VM *, CBufferSimple * > m_event_buffers;
Expand Down
Loading
Loading