mixedinkey-opensource / MIKMIDI

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

MIKMIDISynthesizer loadSoundfontFromFileAtURL does not allow preset selection? #160

Open sigmonky opened 8 years ago

sigmonky commented 8 years ago

I am new to MIKMIDI so I may be wrong about this. But it appears that a loaded soundfont invariably defaults to a AUSamplerInstrumentData.presetID value of 0 and there is no way to assign another value to the presetID property that I can see. This makes multi-timbral soundfonts basically useless.

If this is indeed the case ( I hope I'm missing something ), I'd like to contribute a pull request that enables the client to provide a presetID value.

I just did a quick and dirty hack on the MIKMIDISynthesizer and was able to implement soundFont preset selection in my prototype app. In the prototype app, I have these two method calls. Each one loads in both a different soundFont and presetID specification:

- (BOOL)loadSoundfontFromFileAtURL:(NSURL *)fileURL presetID:(UInt8)presetID error:(NSError **)error
{
    error = error ? error : &(NSError *__autoreleasing){ nil };
    OSStatus err = noErr;

    if (self.componentDescription.componentSubType == kAudioUnitSubType_Sampler) {
        // fill out a bank preset data structure
        NSDictionary *typesByFileExtension = @{@"sf2" : @(kInstrumentType_SF2Preset),
                                               @"dls" : @(kInstrumentType_DLSPreset),
                                               @"aupreset" : @(kInstrumentType_AUPreset)};
        AUSamplerInstrumentData instrumentData;
        instrumentData.fileURL  = (__bridge CFURLRef)fileURL;
        instrumentData.instrumentType = [typesByFileExtension[[fileURL pathExtension]] intValue];
        instrumentData.bankMSB  = kAUSampler_DefaultMelodicBankMSB;
        instrumentData.bankLSB  = kAUSampler_DefaultBankLSB;
        instrumentData.presetID = presetID;
..........
}

If helpful, I can develop a more robust architecture and submit a pull request. Thinking it needs to have its own method signature for backwards compatibility.

armadsen commented 8 years ago

Hi Randy,

I'm on vacation right now, so my replies will be slow and limited.

Off the top of my head, I believe that what you're saying is true. MIKMIDI's development has largely been driven by Mixed In Key's own use of it, and we haven't used multi-timbral soundfonts which explains why this has been overlooked.

A pull request adding support would be very appreciated!

I'll be home next week and will be able to devote more attention to this.

armadsen commented 8 years ago

And yes, please do add a new method so that the old one remains available. It would be fine (and probably desirable) to have the existing method simply call through to the new one passing a default preset id (presumably 0).

Another potential approach would be to leave the soundfont loading method alone, and simply add an API for selecting a preset separately. That particularly seems desirable since switching presets shouldn't really require reloading the soundfont file from scratch, nor would it be nice to have to pass in the file URL every time you simply want to switch to a different voice.

Anyway, if you submit an initial pull request, we can use that as a good starting point for discussions about how best to implement this.