mixedinkey-opensource / MIKMIDI

MIDI Library for Swift and Objective-C Mac and iOS apps.
Other
492 stars 95 forks source link

Note Off command not working #291

Open pnome opened 4 years ago

pnome commented 4 years ago

I’m sure this is just something I’m not understanding, but I used the following code to try and play a note for 2 seconds. The note off command is never implemented.

I can add a third command for a different note on after 3 seconds, and I’ll end up hearing both. They just never turn off.

Can somebody help me understand what I’m doing wrong? Thanks!

`- (IBAction)sendNote:(id)sender//testing {

MIKMIDIClientDestinationEndpoint *destinationEndpoint = [[MIKMIDIClientDestinationEndpoint alloc] initWithName:@"SimpleVirtualSynth" receivedMessagesHandler:nil];
self.synthesizer = [[MIKMIDIEndpointSynthesizer alloc] initWithClientDestinationEndpoint:destinationEndpoint];

NSDate *date = [NSDate date];
MIKMIDINoteOnCommand *noteOn = [MIKMIDINoteOnCommand noteOnCommandWithNote:60 velocity:127 channel:0 timestamp:date];
MIKMIDINoteOffCommand *noteOff = [MIKMIDINoteOffCommand noteOffCommandWithNote:60 velocity:0 channel:0 timestamp:[date dateByAddingTimeInterval:2.0]];

MIKMIDIDeviceManager *dm = [MIKMIDIDeviceManager sharedDeviceManager];
NSError *error = nil;
if (![dm sendCommands:@[noteOn,noteOff] toEndpoint:destinationEndpoint error:&error]) {
    NSLog(@"Unable to send note to %@: %@", destinationEndpoint, error);
}

} `

armadsen commented 4 years ago

Hi @pnome,

MIKMIDIClientDestinationEndpoint is a virtual endpoint used to receive events from other apps running on the system. You can't send MIDI commands to it that way. In any case, MIKMIDIEndpointSynthesizer is specifically for synthesizing events coming into your app from an external source (either other apps or a hardware device). If you just want to synthesize local MIDI, use plain MIKMIDISynthesizer. Try this:

- (IBAction)sendNote:(id)sender//testing
{
    NSError *error = nil;
    self.synthesizer = [[MIKMIDISynthesizer alloc] initWithError:&error];
    if (!self.synthesizer) {
        NSLog(@"Error creating synthesizer: %@", error);
    }

    NSDate *date = [NSDate date];
    MIKMIDINoteOnCommand *noteOn = [MIKMIDINoteOnCommand noteOnCommandWithNote:60 velocity:127 channel:0 timestamp:date];
    MIKMIDINoteOffCommand *noteOff = [MIKMIDINoteOffCommand noteOffCommandWithNote:60 velocity:0 channel:0 timestamp:[date dateByAddingTimeInterval:2.0]];

    [self.synthesizer handleMIDIMessages:@[noteOn, noteOff]];
}
pnome commented 4 years ago

Hi @armadsen ,

I tried that, and I'm experiencing the same problem. I tested by adding a second note to play at [date dateByAddingTimeInterval:4.0] with noteOff at [date dateByAddingTimeInterval:4.0]

When I run the code, both notes play immediately, and never turn off. As if all supplied midi notes are being handled immediately, rather than paying attention to the supplied timestamps.

You can see it in action here: https://www.youtube.com/watch?v=Zzpm2neuBRA

Any suggestions? Thanks again, Joe

armadsen commented 4 years ago

Hi Joe,

Interesting. I wrote the code I sent in a little test app that works fine. I didn't realize you were on iOS (I tested on macOS). It should work exactly the same, but perhaps there's an iOS-specific bug there. I'll dig a little more later this afternoon and will have more for you.

pnome commented 4 years ago

Hi Andrew, Just wondering if you made any progress with this. I'd love to use MIDI in my app, and this seems like the way to go, but I can't get past this issue at the moment. Thanks, Joe

pnome commented 4 years ago

Hi @armadsen, I hope all's well. Did you ever figure out if you could get it working on iOS?

Best, Joe