Created
January 19, 2020 00:30
-
-
Save andretodman/e587093a5bb4125c64584a7c65a83ce8 to your computer and use it in GitHub Desktop.
An Objective-C midi event class that is part of a sequencer engine that I wrote for iOS before CoreMidi. The class saves actual universal midi event packages but allows initializing events with simple Int parameters. The sequencer engine is a circular buffer that stores events played at the eventTimeInTicks. CoreMidi was first available in iOS 4…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// MidiEvent.h - Part of a music sequencer audio engine framework written by Andre Todman. | |
// Used in several audio applications in the App Store (2007-2010). | |
// Created by Andre Todman on 8/8/09. | |
// | |
// Copyright 2009 Pubfuse Inc. All rights reserved. | |
/* ******************************************************************************************* *\ | |
* A midi event class that is part of a sequencer engine that I wrote for iOS before CoreMidi. * | |
* The class saves actual universal midi event packages but allows initializing events with * | |
* simple Int parameters. See: https://en.wikipedia.org/wiki/MIDI_1.0 * | |
* The sequencer engine is a circular buffer that stores events played at the eventTimeInTicks. * | |
* CoreMidi was first available in iOS 4.1 around 2010. * | |
\* ******************************************************************************************* */ | |
// Struct to store modes for offset event times. | |
// Each mode has different strengths that will trigger events with a different swing | |
// This allow a more natural feel during playback | |
struct swingQuantizeTime { | |
float closest_for_setting_0; | |
float closest_for_setting_1; | |
float closest_for_setting_2; | |
float closest_for_setting_3; | |
float closest_for_setting_4; | |
float closest_for_setting_5; | |
float closest_for_setting_6; | |
float closest_for_setting_7; | |
float closest_for_setting_8; | |
float closest_for_setting_9; | |
}; | |
/// Class to store a Midi Event with properties that use midi event messages | |
@interface MidiEvent : NSObject { | |
struct swingQuantizeTime quantizedTime; // value to snap event time to | |
NSNumber* on; // On or off | |
NSNumber* triggerPlay; // Trigger midi play message | |
NSNumber* triggerStop; // Trigger midi stop message | |
NSNumber* didPlay; // Save playback state each loop. | |
NSNumber* midiVelocity; // Volume for the event | |
NSNumber* beatPosition_0First_15ForLast; // Position of playback in simple 16/th beat mode | |
NSNumber* timeExact0__to_late7; // Offset event time randomly between abount to allow a natural feel | |
NSNumber* midiBar; // Bar in beats where the even is played | |
NSNumber* midiNote; // The value of the midi note, for example 63 for middle C | |
NSNumber* midiChan; // Midi Channel of the event | |
NSNumber* eventTimeInTicks; // The event time in ticks per beat | |
} | |
//- Generated getters & setters | |
@property(nonatomic,retain)NSNumber* on; | |
@property(nonatomic,retain)NSNumber* triggerPlay; | |
@property(nonatomic,retain)NSNumber* triggerStop; | |
@property(nonatomic,retain)NSNumber* didPlay; | |
@property(nonatomic,retain)NSNumber* midiVelocity; | |
@property(nonatomic,retain)NSNumber* beatPosition_0First_15ForLast; | |
@property(nonatomic,retain)NSNumber* timeExact0__to_late7; | |
@property(nonatomic,retain)NSNumber* midiBar; | |
@property(nonatomic,retain)NSNumber* midiNote; | |
@property(nonatomic,retain)NSNumber* midiChan; | |
@property(nonatomic,retain)NSNumber* eventTimeInTicks; | |
@property struct swingQuantizeTime quantizedTime; | |
/// Creates a new MidiEvent and initializes it's position of playback, the bar, the note on off display, and the assigned pad number | |
/// @param beatColNumber Position of playback in simple 16/th beat | |
/// @param precisionRowNumber Int that stores the position of playback for the event | |
/// @param theBarNumber Int that stores the bar of playback time | |
/// @param onOffOther_123 Int that stores on (1), off (0) or other (Custom Midi Message) state. | |
/// @param padNum The pad number that binds to the midi event. When pressed, allows the sequencer to save the event | |
-(id) initWithBeatNumber_0__to_15:(int)beatColNumber precision_0_to_7:(int)precisionRowNumber barNumber:(int)theBarNumber setOn1_off0__other2:(int)onOffOther_123 andPad:(int)padNum; | |
/// Returns the MidiEvent tickPerBeat as Float with swing time forin the current swing setting. | |
/// Changing during playback in the sequencer engine, you would hear a drummer play more relaxed, for example. | |
/// @param n Int Setting to use a for swing | |
-(float)getQuantizedTimeForSetting:(int)n; | |
/// Change MidiEvent and it's position of playback, the bar, the note on off display | |
/// @param beat Position of playback in simple 16/th beat | |
/// @param barNumber Int that stores the bar of playback time | |
/// @param timeExact Swing setting as in where 0 is exact playback time and 7 is late | |
-(void)setBeatPosition__0First_15ForLast:(int)beat andBar:(int)barNumber andTimeExact0__to_late7:(int)timeExact; | |
/// Sets note on/off | |
/// @param Set note on or off | |
-(void)setOn1_off0__other2:(int)n; | |
/// Get NoteOn,NoteOff or Other value | |
-(int)getOn1_off0__other2 ; | |
/// Set Quantization offset | |
/// @param n quantize number as Int | |
/// @param ev time in ticks of event | |
-(void)setQuantizeNumber:(int)n withTime:(float)ev; | |
/// Set bar in beat to play event | |
/// @param n Bar number to play the event at | |
-(void)setBar:(int)n; | |
/// Compare another event to see if it is equal | |
/// @param midi other event | |
-(BOOL)isEqual:(MidiEvent*)midi; | |
/// Copy another midi event | |
/// @param midi another midi event | |
-(void)copyEvent:(MidiEvent*)midi; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// MidiEvent.h - Part of a music sequencer audio engine framework written by Andre Todman. | |
// Used in several audio applications in the App Store (2007-2010). | |
// Created by Andre Todman on 8/8/09. | |
// | |
// Copyright 2009 Pubfuse Inc. All rights reserved. | |
/* ******************************************************************************************* *\ | |
* A midi event class that is part of a sequencer engine that I wrote for iOS before CoreMidi. * | |
* The class saves actual universal midi event packages but allows initializing events with * | |
* simple Int parameters. See: https://en.wikipedia.org/wiki/MIDI_1.0 * | |
* The sequencer engine is a circular buffer that stores events played at the eventTimeInTicks. * | |
* CoreMidi was first available in iOS 4.1 around 2010. * | |
\* ******************************************************************************************* */ | |
#import "MidiEvent.h" | |
@implementation MidiEvent | |
@synthesize on; | |
@synthesize triggerPlay; | |
@synthesize triggerStop; | |
@synthesize didPlay; | |
@synthesize midiVelocity; | |
@synthesize beatPosition_0First_15ForLast; | |
@synthesize timeExact0__to_late7; | |
@synthesize midiBar; | |
@synthesize midiNote; | |
@synthesize midiChan; | |
@synthesize eventTimeInTicks; | |
@synthesize quantizedTime; | |
/// Initializes a midi event | |
-(id) init { | |
if (self = [super init]) { | |
on = [[[NSNumber alloc]init ]retain] ; | |
triggerPlay = [[[NSNumber alloc]init ]retain] ; | |
triggerStop = [[[NSNumber alloc]init ]retain] ; | |
didPlay = [[[NSNumber alloc]init ]retain] ; | |
midiVelocity = [[[NSNumber alloc]init ]retain] ; | |
beatPosition_0First_15ForLast = [[[NSNumber alloc]init ]retain] ; | |
timeExact0__to_late7 = [[[NSNumber alloc]init ]retain] ; | |
midiBar = [[[NSNumber alloc]init ]retain] ; | |
midiNote = [[NSNumber alloc]init ] ; | |
midiChan = [[[NSNumber alloc]init ]retain] ; | |
eventTimeInTicks = [[[NSNumber alloc]init ]retain] ; | |
} | |
return self; | |
} | |
/// Creates a new MidiEvent and initializes it's position of playback, the bar, the note on off display, and the assigned pad number | |
/// @param beatColNumber Position of playback in simple 16/th beat | |
/// @param precisionRowNumber Int that stores the position of playback for the event | |
/// @param theBarNumber Int that stores the bar of playback time | |
/// @param onOffOther_123 Int that stores on (1), off (0) or other (Custom Midi Message) state. | |
/// @param padNum The pad number that binds to the midi event. When pressed, allows the sequencer to save the event | |
-(id) initWithBeatNumber_0__to_15:(int)beatColNumber precision_0_to_7:(int)precisionRowNumber barNumber:(int)theBarNumber setOn1_off0__other2:(int)onOffOther_123 andPad:(int)padNum{ | |
if (self = [super init]) { | |
[self setOn:[ NSNumber numberWithInt:-1]]; | |
[self setTriggerPlay:[ NSNumber numberWithBool:NO]]; | |
[self setTriggerStop:[ NSNumber numberWithBool:NO]]; | |
[self setDidPlay:[ NSNumber numberWithBool:NO]]; | |
[self setMidiVelocity:[ NSNumber numberWithFloat:1.0f]]; | |
[self setBeatPosition_0First_15ForLast:[ NSNumber numberWithInt:0]]; | |
[self setTimeExact0__to_late7:[ NSNumber numberWithInt:0]]; | |
[self setMidiBar:[ NSNumber numberWithInt:theBarNumber]]; | |
[self setMidiNote:[ NSNumber numberWithInt:padNum]]; | |
[self setMidiChan:[ NSNumber numberWithInt:0]]; | |
[self setEventTimeInTicks:[ NSNumber numberWithInt:0]]; | |
if(onOffOther_123 == 1){ | |
[self setOn:[ NSNumber numberWithBool:YES]]; | |
[self setTriggerPlay:[ NSNumber numberWithBool:YES]]; | |
[self setTriggerStop:[ NSNumber numberWithBool:NO]]; | |
} | |
else if(onOffOther_123 == 0){ | |
[self setOn:[ NSNumber numberWithBool:YES]]; | |
[self setTriggerPlay:[ NSNumber numberWithBool:NO]]; | |
[self setTriggerStop:[ NSNumber numberWithBool:YES]]; | |
} | |
else if(onOffOther_123 == 2){ | |
[self setOn:[ NSNumber numberWithBool:YES]]; | |
[self setTriggerPlay:[ NSNumber numberWithBool:NO]]; | |
[self setTriggerStop:[ NSNumber numberWithBool:NO]]; | |
} | |
} | |
return self; | |
} | |
/// Allows Initializing a saved object automatically when the app is loaded | |
/// @param coder the save encoded object to load | |
-(id) initWithCoder:(NSCoder *)coder { | |
[super init]; | |
on = [[coder decodeObjectForKey:@"on"] retain]; | |
triggerPlay = [[coder decodeObjectForKey:@"triggerPlay"] retain]; | |
triggerStop = [[coder decodeObjectForKey:@"triggerStop"] retain]; | |
didPlay = [[coder decodeObjectForKey:@"didPlay"] retain]; | |
midiVelocity = [[coder decodeObjectForKey:@"midiVelocity"] retain]; | |
beatPosition_0First_15ForLast= [[coder decodeObjectForKey:@"beatPosition_0First_15ForLast"] retain]; | |
timeExact0__to_late7= [[coder decodeObjectForKey:@"timeExact0__to_late7"] retain]; | |
midiBar= [[coder decodeObjectForKey:@"midiBar"] retain]; | |
midiNote= [[coder decodeObjectForKey:@"midiNote"] retain]; | |
midiChan= [[coder decodeObjectForKey:@"midiChan"] retain]; | |
eventTimeInTicks= [[coder decodeObjectForKey:@"eventTimeInTicks"] retain]; | |
return self; | |
} | |
/// Saves the current object and it's values | |
/// @param encoder encoded object ref | |
-(void) encodeWithCoder:(NSCoder *)encoder { | |
[encoder encodeObject:on forKey:@"on"]; | |
[encoder encodeObject:triggerPlay forKey:@"triggerPlay"]; | |
[encoder encodeObject:triggerStop forKey:@"triggerStop"]; | |
[encoder encodeObject:didPlay forKey:@"didPlay"]; | |
[encoder encodeObject:midiVelocity forKey:@"midiVelocity"]; | |
[encoder encodeObject:beatPosition_0First_15ForLast forKey:@"beatPosition_0First_15ForLast"]; | |
[encoder encodeObject:timeExact0__to_late7 forKey:@"timeExact0__to_late7"]; | |
[encoder encodeObject:midiBar forKey:@"midiBar"]; | |
[encoder encodeObject:midiNote forKey:@"midiNote"]; | |
[encoder encodeObject:midiChan forKey:@"midiChan"]; | |
[encoder encodeObject:eventTimeInTicks forKey:@"eventTimeInTicks"]; | |
} | |
/// Sets the midi note | |
/// @param n Value of the midi key, 63 is middle C | |
-(void)setNote:(int)n{ | |
[self setMidiNote:[ NSNumber numberWithInt:n]]; | |
} | |
/// Sets the midi channel | |
/// @param n New midi channel to use | |
-(void)setChan:(int)n{ | |
[self setMidiChan:[ NSNumber numberWithInt:n]]; | |
} | |
/// Sets Velocity to of the note | |
/// @param n Velocity amount | |
-(void)setVelocity:(float)n{ | |
[self setMidiVelocity:[ NSNumber numberWithFloat:n]]; | |
} | |
/// Returns the MidiEvent tickPerBeat as Float with swing time forin the current swing setting. | |
/// Changing during playback in the sequencer engine, you would hear a drummer play more relaxed, for example. | |
/// @param n Int Setting to use a for swing | |
-(float)getQuantizedTimeForSetting:(int)n{ | |
switch (n) { | |
case 0: | |
return quantizedTime.closest_for_setting_0; | |
break; | |
case 1: | |
return quantizedTime.closest_for_setting_1; | |
break; | |
case 2: | |
return quantizedTime.closest_for_setting_2; | |
break; | |
case 3: | |
return quantizedTime.closest_for_setting_3; | |
break; | |
case 4: | |
return quantizedTime.closest_for_setting_4; | |
break; | |
case 5: | |
return quantizedTime.closest_for_setting_5; | |
break; | |
case 6: | |
return quantizedTime.closest_for_setting_6; | |
break; | |
case 7: | |
return quantizedTime.closest_for_setting_7; | |
break; | |
case 8: | |
return quantizedTime.closest_for_setting_8; | |
break; | |
case 9: | |
return quantizedTime.closest_for_setting_9; | |
break; | |
default: | |
return -100; | |
break; | |
} | |
} | |
/// Change MidiEvent and it's position of playback, the bar, the note on off display | |
/// @param beat Position of playback in simple 16/th beat | |
/// @param barNumber Int that stores the bar of playback time | |
/// @param timeExact Swing setting as in where 0 is exact playback time and 7 is late | |
-(void)setBeatPosition__0First_15ForLast:(int)beat andBar:(int)barNumber andTimeExact0__to_late7:(int)timeExact{ | |
[self setBeatPosition_0First_15ForLast:[ NSNumber numberWithInt:beat]]; | |
[self setTimeExact0__to_late7:[ NSNumber numberWithInt:timeExact]]; | |
[self setBar: barNumber ]; | |
} | |
/// Set bar in beat to play event | |
/// @param n Bar number to play the event at | |
-(void)setBar:(int)n{ | |
[self setMidiBar:[ NSNumber numberWithInt:n]]; | |
} | |
/// Set Quantization offset | |
/// @param n quantize number as Int | |
/// @param ev time in ticks of event | |
-(void) setQuantizeNumber:(int)n withTime:(float)ev{ | |
switch (n) { | |
case 0: | |
quantizedTime.closest_for_setting_0 = ev; | |
break; | |
case 1: | |
quantizedTime.closest_for_setting_1= ev; | |
break; | |
case 2: | |
quantizedTime.closest_for_setting_2= ev; | |
break; | |
case 3: | |
quantizedTime.closest_for_setting_3= ev; | |
break; | |
case 4: | |
quantizedTime.closest_for_setting_4= ev; | |
break; | |
case 5: | |
quantizedTime.closest_for_setting_5= ev; | |
break; | |
case 6: | |
quantizedTime.closest_for_setting_6= ev; | |
break; | |
case 7: | |
quantizedTime.closest_for_setting_7= ev; | |
break; | |
case 8: | |
quantizedTime.closest_for_setting_8= ev; | |
break; | |
case 9: | |
quantizedTime.closest_for_setting_9= ev; | |
break; | |
} | |
} | |
/// Sets note on | |
-(void)setNoteOn{ | |
[self setOn:[ NSNumber numberWithBool:YES]]; | |
} | |
/// Sets note off | |
-(void)setNoteOff{ | |
[self setOn:[ NSNumber numberWithBool:YES]]; | |
} | |
/// Triggers a stop event when played if this is enabled | |
/// @param n set if enabled | |
-(void)shouldTriggerStop:(BOOL)n{ | |
[self setOn:[ NSNumber numberWithBool:YES]]; | |
[self setTriggerStop:[ NSNumber numberWithBool:n]]; | |
} | |
/// Deallocate objects | |
-(void)dealloc{ | |
[ on release]; | |
[ triggerPlay release]; | |
[ triggerStop release]; | |
[ didPlay release]; | |
[ midiVelocity release]; | |
[ beatPosition_0First_15ForLast release]; | |
[ timeExact0__to_late7 release]; | |
[ midiBar release]; | |
[ midiNote release]; | |
[ midiChan release]; | |
[ eventTimeInTicks release]; | |
[super dealloc]; | |
} | |
/// Sets note on/off | |
/// @param Set note on or off | |
-(void)setOn1_off0__other2:(int)n{ | |
if(n == 1){ | |
[self setOn:[ NSNumber numberWithBool:YES]]; | |
[self setTriggerPlay:[ NSNumber numberWithBool:YES]]; | |
[self setTriggerStop:[ NSNumber numberWithBool:NO]]; | |
} | |
else if(n == 0){ | |
[self setOn:[ NSNumber numberWithBool:YES]]; | |
[self setTriggerPlay:[ NSNumber numberWithBool:NO]]; | |
[self setTriggerStop:[ NSNumber numberWithBool:YES]]; | |
} | |
else if(n == 2){ | |
[self setOn:[ NSNumber numberWithBool:YES]]; | |
[self setTriggerPlay:[ NSNumber numberWithBool:NO]]; | |
[self setTriggerStop:[ NSNumber numberWithBool:NO]]; | |
} | |
} | |
/// Get NoteOn,NoteOff or Other value | |
-(int)getOn1_off0__other2{ | |
int result; | |
if(triggerPlay.boolValue == YES && triggerStop.boolValue ==NO){ | |
result =1 ; | |
} | |
else if(triggerPlay.boolValue == NO && triggerStop.boolValue ==YES){ | |
result =0; | |
} | |
else if(triggerPlay.boolValue == NO && triggerStop.boolValue ==NO){ | |
result =2; | |
} | |
return result; | |
} | |
/// Compare another event to see if it is equal | |
/// @param midi other event | |
-(BOOL)isEqual:(MidiEvent*)midi{ | |
BOOL result = NO; | |
if( | |
on == [midi on] && | |
triggerPlay == [midi triggerPlay] && | |
triggerStop == [midi triggerStop] && | |
didPlay == [midi didPlay] && | |
midiVelocity == [midi midiVelocity] && | |
beatPosition_0First_15ForLast == [midi beatPosition_0First_15ForLast] && | |
timeExact0__to_late7 == [midi timeExact0__to_late7] && | |
midiBar == [midi midiBar] && | |
midiNote == [midi midiNote] && | |
midiChan == [midi midiChan] && | |
eventTimeInTicks == [midi eventTimeInTicks] | |
)result = YES; | |
return result; | |
} | |
/// Copy another midi event | |
/// @param midi another midi event | |
-(void)copyEvent:(MidiEvent*)midi{ | |
on = [NSNumber numberWithBool:[midi on].boolValue]; | |
triggerPlay = [NSNumber numberWithBool:[midi triggerPlay].boolValue]; | |
triggerStop = [NSNumber numberWithBool:[midi triggerStop].boolValue]; | |
didPlay = [NSNumber numberWithBool:YES] ; | |
midiVelocity = [ NSNumber numberWithFloat: [midi midiVelocity].floatValue] ; | |
beatPosition_0First_15ForLast =[NSNumber numberWithInt: [midi beatPosition_0First_15ForLast].intValue] ; | |
timeExact0__to_late7 = [NSNumber numberWithInt: [midi timeExact0__to_late7].intValue] ; | |
midiBar = [NSNumber numberWithInt: [midi midiBar] .intValue]; | |
midiNote = [NSNumber numberWithInt: [midi midiNote].intValue] ; | |
midiChan = [NSNumber numberWithInt: [midi midiChan].intValue]; | |
eventTimeInTicks =[NSNumber numberWithInt: [midi eventTimeInTicks].intValue ] ; | |
quantizedTime = [midi quantizedTime]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment