0

I'm successfully loading a Sound Font (.sf2) to a MusicSequence when the MusicSequence it's loaded by file (.mid) like the following:

        //the interesting code ...

        NSString *midiFilePath = [[NSBundle mainBundle]
                                   pathForResource:@"song"
                                   ofType:@"mid"];

        // Create a new URL which points to the MIDI file
        NSURL * midiFileURL = [NSURL fileURLWithPath:filePath];


        MusicSequenceFileLoad(s, (__bridge CFURLRef) midiFileURL, 0, 0);

        // Create a new music player
        MusicPlayer  p;
        // Initialise the music player
        NewMusicPlayer(&p);

        // ************* Set the endpoint of the sequence to be our virtual endpoint
        MusicSequenceSetMIDIEndpoint(s, virtualEndpoint);

        // Load the sound font from file
        NSURL *presetURL = [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Full Grand Piano" ofType:@"sf2"]];

        // Initialise the sound font
        [self loadFromDLSOrSoundFont: (NSURL *)presetURL withPatch: (int)10];

        // Load the sequence into the music player
        MusicPlayerSetSequence(p, s);
        // Called to do some MusicPlayer setup. This just
        // reduces latency when MusicPlayerStart is called
        MusicPlayerPreroll(p);
        // Starts the music playing
        MusicPlayerStart(p);

        //code continues here ...


-(OSStatus) loadFromDLSOrSoundFont: (NSURL *)bankURL withPatch: (int)presetNumber {

    OSStatus result = noErr;

    // fill out a bank preset data structure
    AUSamplerBankPresetData bpdata;
    bpdata.bankURL  = (__bridge CFURLRef) bankURL;
    bpdata.bankMSB  = kAUSampler_DefaultMelodicBankMSB;
    bpdata.bankLSB  = kAUSampler_DefaultBankLSB;
    bpdata.presetID = (UInt8) presetNumber;

    // set the kAUSamplerProperty_LoadPresetFromBank property
    result = AudioUnitSetProperty(self.samplerUnit,
                          kAUSamplerProperty_LoadPresetFromBank,
                          kAudioUnitScope_Global,
                          0,
                          &bpdata,
                          sizeof(bpdata));

    // check for errors
    NSCAssert (result == noErr,
       @"Unable to set the preset property on the Sampler. Error code:%d '%.4s'",
       (int) result,
       (const char *)&result);

    return result;
    }

But If I want to apply the same to a MusicSequence with a MusicTrack build with MIDINoteMessages:

//the interesting code here

MusicSequenceNewTrack(musicSequence, &musicTrack);

MusicSequenceGetIndTrack(musicSequence, 0, &(musicTrack));

MIDINoteMessage aMessage;
aMessage.channel = 1;

aMessage.duration = 0.3f;
aMessage.velocity = 200;

for(int i=0; i<numerator; ++i)
{
    if (i==0) {
        aMessage.note = 80;
    }else {
        aMessage.note = 60;
    }

    MusicTrackNewMIDINoteEvent(musicTrack, i, &aMessage);
}

MusicSequenceSetMIDIEndpoint(musicSequence, virtualEndpoint);

// Load the sound font from file
NSURL *presetURL = [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Full Grand Piano" ofType:@"sf2"]];

// Initialise the sound font
[self loadFromDLSOrSoundFont: (NSURL *)presetURL withPatch: (int)10];

//code continues here

I'm getting a (lldb) error. Any idea how to solve this?

Pau Senabre
  • 4,155
  • 2
  • 27
  • 36

2 Answers2

1

This is the sound font relevant code from my github project. This loads the sound font into your sampler unit. If you need more on setting up the augraph see the project or read this post.

func loadSF2Preset(preset:UInt8)  {

    // This is the MuseCore soundfont. Change it to the one you have.
    if let bankURL = NSBundle.mainBundle().URLForResource("GeneralUser GS MuseScore v1.442", withExtension: "sf2") {
        var instdata = AUSamplerInstrumentData(fileURL: Unmanaged.passUnretained(bankURL),
            instrumentType: UInt8(kInstrumentType_DLSPreset),
            bankMSB: UInt8(kAUSampler_DefaultMelodicBankMSB),
            bankLSB: UInt8(kAUSampler_DefaultBankLSB),
            presetID: preset)


        var status = AudioUnitSetProperty(
            self.samplerUnit,
            AudioUnitPropertyID(kAUSamplerProperty_LoadInstrument),
            AudioUnitScope(kAudioUnitScope_Global),
            0,
            &instdata,
            UInt32(sizeof(AUSamplerInstrumentData)))
        CheckError(status)
    }
}

You associate the augraph with the MusicSequence like this

    MusicSequenceSetAUGraph(musicSequence, self.processingGraph)
Gene De Lisa
  • 3,628
  • 1
  • 21
  • 36
  • I converted the Swift code to Objective-C for my project, and add it after creating the AUGraph but seems not to work. [self createAUGraph]; [self configureAndStartAudioProcessingGraph: self.processingGraph]; NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"GeneralUser GS MuseScore v1.442" withExtension:@"sf2"]; [self loadFromPresetURL:fileURL]; – Pau Senabre Jul 21 '15 at 10:32
0

In my blog post on MIDI callbacks I've included a github project that has code to create a MusicSequence on the fly as you are trying to do.

Gene De Lisa
  • 3,628
  • 1
  • 21
  • 36
  • Thanks, it helped me understand how the read callback work, but I couldn't find any mention about loading a SoundFiles to MusicSequence in your blog. – Pau Senabre Jun 05 '15 at 14:22
  • Look at the project on github. that's where the complete code is along with the sound font code. I'll paste that into another answer since comments mangle code. – Gene De Lisa Jul 16 '15 at 19:45