刚开始在Xcode中使用RtMIDI来制作一些MIDI内容。它工作正常,但遇到了绊脚石。
使用示例midiout.cpp而不修改任何内容:
查看库代码,除了sysex之外的所有MIDI事件都是使用os调用MIDIReceived发送的(在OSX上)。 Sysex事件使用MIDISendSysex发送。这是应该的。
现在,没有错误被抛出,一切正在按原样执行,MIDISendSysex调用没有失败 - 只是没有sysex事件到达目的地。他们只是消失在一个黑洞里!
是否有其他人遇到此问题或有任何帮助,建议,解决方法?
谢谢,
(Xcode 4.6.2,OSX 10.9.1,使用MIDIMonitor& MIDIPipe来监控MIDI端口上的流量,两者都显示未从midiout.cpp到达虚拟端口的sysex事件的相同结果)
好的,这是执行实际发送的sendMessage路由:
void MidiOutCore :: sendMessage( std::vector *message )
{
// ------------------------------------------------------------------------
// We use the MIDISendSysex() function to asynchronously send sysex
// messages. Otherwise, we use a single CoreMidi MIDIPacket.
// ------------------------------------------------------------------------
// error handling code removed for brevity
MIDITimeStamp timeStamp = AudioGetCurrentHostTime();
CoreMidiData *data = static_cast (apiData_);
OSStatus result;
// ------------------------------------------------------------------------
// IF EVENT IS SYSEX
// ------------------------------------------------------------------------
if ( message->at(0) == 0xF0 ) { // sysex start byte
while ( sysexBuffer != 0 ) usleep( 1000 ); // sleep 1 ms
sysexBuffer = new char[nBytes];
// Copy data to buffer.
for ( unsigned int i=0; iat(i);
// build sysex request
data->sysexreq.destination = data->destinationId; // destinaiondId is valid endpointref
data->sysexreq.data = (Byte *)sysexBuffer;
data->sysexreq.bytesToSend = nBytes;
data->sysexreq.complete = 0;
data->sysexreq.completionProc = sysexCompletionProc;
data->sysexreq.completionRefCon = &(data->sysexreq);
// send the data
// this works when we are connected to a 'real' MIDI port/device, but fails on a virtual port
// destinationId is an endpointref and valid and id is good
// tried to use data->endpoint (also an endpointref with id) but doesn't send either
result = MIDISendSysex( &(data->sysexreq) );
return;
}
// ------------------------------------------------------------------------
// IF EVENT IS NOT SYSEX
// ------------------------------------------------------------------------
MIDIPacketList packetList;
MIDIPacket *packet = MIDIPacketListInit( &packetList );
packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) );
// Send to any destinations that may have connected to us.
// this sends to virtual MIDI ports
if ( data->endpoint ) {
result = MIDIReceived( data->endpoint, &packetList );
if ( result != noErr ) {
errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations.";
RtMidi::error( RtError::WARNING, errorString_ );
}
}
// And send to an explicit destination port if we're connected.
// this sends to regular real MIDI devices we are connected to, not virtual ports
if ( connected_ ) {
result = MIDISend( data->port, data->destinationId, &packetList );
if ( result != noErr ) {
errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port.";
RtMidi::error( RtError::WARNING, errorString_ );
}
}
}
答案 0 :(得分:0)
跟进注释 - 这是RTMidi中的一个错误,应该在下一个版本中修复。这与以下事实有关:在CoreMIDI中,MIDISendSysex()调用不发送到虚拟端口,它只能在真实端口上工作。
我已根据CoreAdio邮件列表中此线程的建议,使用MIDIReceived()更新了RTMIDI的本地副本以处理sysex事件: http://lists.apple.com/archives/coreaudio-api/2006/Jan/msg00236.html
它现在将sysex发送到虚拟端口并按预期运行。