Domanda

I am quite a novice when it comes to AudioUnits, so please forgive me if my question is very basic.

I am using the MusicDevice AudioUnit to playback some notes. I am using MusicDeviceMIDIEvent to send the note-on and note-off messages. It works well. Sometimes more than one note should sound simultaneously, so I may send two note-on messages in a row. Sometimes these notes happen to have the same pitch. Then when I want to turn off one of the notes, I send a note-off event for this pitch. But this message turns off all notes of the pitch. Of course this behavior makes a lot of sense, but I wanted to ask how people normally deal with this issue.

Should I use different channels for simultaneous notes? Or manage the notes manually, say with a counted set which holds the pitches currently playing, and only send the note-off event after the last instance of a pitch should stop playing? Or something else entirely?

EDIT:

Since this is on the iOS, I have to use kAudioUnitSubType_Sampler as the AudioUnit subType. While the documentation only mentions that this type is mono-timbral, I now suspect it is also monophonic. This of course would explain the behavior. Still I wonder how I would go about this is if I actually had an polyphonic instrument.

EDIT 2:

I did some more tests, and it seems to me now that sending a note-off message on any channel stops all notes with the same pitch on all channels. I took the apple example code at http://developer.apple.com/library/ios/#samplecode/LoadPresetDemo/Introduction/Intro.html and modified the stopPlay[low/mid/high]Note methods to send the note-off messages on some random channel (if you must know, on channels 7,8, and 9, respectively). It still stops the notes, despite the fact that the note-on messages are being sent on channel 0. Is this expected behavior?

Just to make sure I am not making a stupid mistake, these are the methods that send note-on and note-off messages:

- (IBAction) startPlayLowNote:(id)sender {

    UInt32 noteNum = kLowNote;
    UInt32 onVelocity = 127;
    UInt32 noteCommand =    kMIDIMessage_NoteOn << 4 | 0;

    OSStatus result = noErr;
    require_noerr (result = MusicDeviceMIDIEvent (self.samplerUnit, noteCommand, noteNum, onVelocity, 0), logTheError);

    logTheError:
    if (result != noErr) NSLog (@"Unable to start playing the low note. Error code: %d '%.4s'\n", (int) result, (const char *)&result);
}



- (IBAction) stopPlayLowNote:(id)sender {

    //note the channel!
    UInt32 noteNum = kLowNote;
    UInt32 noteCommand =    kMIDIMessage_NoteOff << 4 | 7;

    OSStatus result = noErr;
    require_noerr (result = MusicDeviceMIDIEvent (self.samplerUnit, noteCommand, noteNum, 0, 0), logTheError);

    logTheError:
    if (result != noErr) NSLog (@"Unable to stop playing the low note. Error code: %d '%.4s'\n", (int) result, (const char *)&result);
}
È stato utile?

Soluzione

I'm pretty sure that the behavior for a note off after two note on events of the same pitch on the same channel is undefined. Some instruments might turn off both notes and some might turn off one and require a second note off to turn off the other.

If you really need to have two simultaneous notes of the same pitch, they should be on different channels.

Edit regarding posted code

I tried the sample project in your link and changed the channel the same way you did in your posted code. It turns out that kAudioUnitSubType_Sampler is indeed mono-timbral, so it ignores the MIDI channel parameter. So if you want to have two simultaneous notes of the same pitch with kAudioUnitSubType_Sampler, you'll have to create two separate instances.

Note that kAudioUnitSubType_Sampler is not monophonic. It is polyphonic since it can play multiple pitches simultaneously.

Altri suggerimenti

What about using MusicDevice.h's MusicDeviceStartNote() and MusicDeviceStopNote()? It uses a unique token for the note so you should be able to distinguish between two of the same pitch.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top