using MusicPlayer to convert sysex bulk <-> std MIDI
using MusicPlayer to convert sysex bulk <-> std MIDI
- Subject: using MusicPlayer to convert sysex bulk <-> std MIDI
- From: Bill Dozier <email@hidden>
- Date: Tue, 18 Nov 2003 08:03:42 -0600
Hi all,
Here's some code I'm using to convert between sysex bulk data (what my
application, a sysex librarian/editor likes to work with) and standard
MIDI data (that my app can read and export). It would have saved me
several hours of work if I could have found a relevant example (or one
that I could recognize as relevant ;{>) of doing this, especially the
memory management part (which is poorly documented).
I wouldn't at all be surprised if there are better &/or simpler ways to
do this. I would be glad to post this on the wiki site if other folks
think it would be helpful to CA beginners like me.
Thanks,
Bill
#include <CoreMIDI/MIDIServices.h>
#import "SysexMIDIPacketListConverter.h"
#import <CoreAudio/HostTime.h>
#import <AudioToolbox/MusicPlayer.h>
#include <unistd.h>
//Not really a class...just a collection of functions. Would be nice
// if Obj-C had namespaces.
@interface SysexMIDIPacketListConverter : NSObject
{
}
+(MIDIPacketList *)packetListFromSysexDataArray:(NSArray *)dataArray
sysexPeriodMilliseconds:(int)period;
+(NSData *)bulkDataFromMIDI:(NSData *)midiData;
+(NSData *)MIDIFromMIDIPacketList:(MIDIPacketList *)packetList;
@end
@implementation SysexMIDIPacketListConverter
/**
*
* Build a MIDIPacketList from an array of sysex data chunks,
* each of which starts with 0xf0 and ends with 0xf7. The memory for the
* packet list is provided by an autoreleased NSData object.
*
*/
+(MIDIPacketList *)packetListFromSysexDataArray:(NSArray *)dataArray
sysexPeriodMilliseconds:(int)sysexDelayMilliseconds
{
NSMutableData *listBuffer = [[[NSMutableData alloc] init]
autorelease];
ByteCount listSize = 0;
NSEnumerator *e = [dataArray objectEnumerator];
NSData *data;
while(data = [e nextObject])
listSize += [data length] + sizeof(MIDIPacket);
listSize += sizeof(MIDIPacketList);
[listBuffer setLength:listSize];
MIDIPacketList *theList = (MIDIPacketList *)[listBuffer
mutableBytes];
MIDIPacket *current = MIDIPacketListInit(theList);
UInt64 time = 0;
const UInt64 delayNanos = sysexDelayMilliseconds * 1000000;
e = [dataArray objectEnumerator];
while(data = [e nextObject]) {
current = MIDIPacketListAdd(theList, listSize, current, time,
[data length], [data bytes]);
time = AudioConvertHostTimeToNanos(time);
time = AudioConvertNanosToHostTime(time + delayNanos);
}
return theList;
}
/**
*
* Create an autoreleased NSData of MIDI sysex bulk data from an input
packet list.
*/
+(NSData *)MIDIFromMIDIPacketList:(MIDIPacketList *)packetList
{
MusicSequence midiSequence;
NewMusicSequence(&midiSequence);
MusicTrack theTrack;
MusicSequenceNewTrack(midiSequence, &theTrack);
MIDIPacket *current = &packetList->packet[0];
size_t i = 0;
for (; i < packetList->numPackets; ++i) {
MIDIRawData *data = malloc(sizeof(MIDIRawData) +
current->length * sizeof(UInt8));
data->length = current->length;
size_t j = 0;
for(; j < current->length; j++)
data->data[j] = current->data[j];
MusicTrackNewMIDIRawDataEvent(theTrack, current->timeStamp,
data);
free(data);
current = MIDIPacketNext(current);
}
NSMutableData *buffer = [[NSMutableData alloc] init];
MusicSequenceSaveSMFData(midiSequence, (CFDataRef *)&buffer, 0);
DisposeMusicSequence(midiSequence);
NSData *ret = [NSData dataWith
Data:buffer];
[buffer release];
return ret;
}
/**
*
* Create an autoreleased NSData containing MIDI sysex bulk data from
* standard MIDI data.
*/
+(NSData *)bulkDataFromMIDI:(NSData *)midiData
{
MusicSequence midiSequence;
NewMusicSequence(&midiSequence);
MusicSequenceLoadSMFData(midiSequence, (CFDataRef)midiData);
UInt32 trackCount;
MusicSequenceGetTrackCount(midiSequence, &trackCount);
assert(trackCount == 1);
MusicTrack theTrack;
MusicSequenceGetIndTrack(midiSequence, (UInt32)0, &theTrack);
MusicEventIterator eventIterator;
NewMusicEventIterator(theTrack, &eventIterator);
BOOL moreEvents = NO;
MusicEventIteratorHasCurrentEvent(eventIterator, &moreEvents);
NSMutableData *listBuffer = [[[NSMutableData alloc] init]
autorelease];
while(moreEvents) {
void *eventData;
MusicTimeStamp timeStamp;
MusicEventType eventType;
UInt32 eventDataSize;
MusicEventIteratorGetEventInfo(eventIterator, &timeStamp,
&eventType, (const void
**)&eventData, &eventDataSize);
if(eventData && eventType == kMusicEventType_MIDIRawData) {
MIDIRawData *midiData = (MIDIRawData *)eventData;
[listBuffer appendBytes:midiData->data
length:midiData->length];
}
MusicEventIteratorNextEvent(eventIterator);
MusicEventIteratorHasCurrentEvent(eventIterator, &moreEvents);
}
DisposeMusicSequence(midiSequence);
return listBuffer;
}
@end
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.