4

I'm currently using AudioKit's AKSamplerMetronome to generate and play Metronome sounds , now I need implement an callback to get current beat suppose If I'm having 5 beats I need to get current beat that is being played so that I can add some more functions based on the beat count , is there any callback available to achieve It ??

This is my current code

 // using AKSamplerMetronome
var metronome1 = AKSamplerMetronome()
var mixer = AKMixer()
// first sound called
let beatstart = Bundle.main.url(forResource: "mybeat", withExtension: "wav")
 // other sounds based on beat count
let beaten = Bundle.main.url(forResource: "others", withExtension: "wav")
// setting first sound and other beat sounds
metronome1.sound = McountSoundUrl
metronome1.downBeatSound = MoneSoundUrl
metronome1 >>> mixer
AudioKit.output = mixer
AudioKit.start()
RAM
  • 119
  • 1
  • 14

1 Answers1

4

You could do this easily enough with AKSequencer (I did something similar). I assigned one track of the sequencer to an AKMIDISampler, generating the metronome sound, and a second track that went to an AKCallbackInstrument.
In the track being sent to the AKCallbackInstrument, I encoded the beat information arbitrarily in the MIDI data, so for example, the MIDI data for the first beat has a MIDINote of 1, the second, MIDINote 2 (you could do this with the velocity). Then the callback function could would just look at all of the noteOn messages and get the current beat from the MIDI Note number, and respond accordingly. It's a little indirect, but it works.

// create the sequencer before hand (e.g., at init); calling play() immediately after creating it causes some odd behaviour
    let sequencer = AKSequencer()

    // set up the sampler and callbackInst
    let sampler = AKSynthSnare()
    // or for your own sample:
    // let sampler = AKMIDISampler()
    // sampler.loadWav("myMetronomeSound)
    let callbackInst = AKCallbackInstrument()
    AudioKit.output = sampler
    AudioKit.start()

    // create two tracks for the sequencer
    let metronomeTrack = sequencer.newTrack()
    metronomeTrack?.setMIDIOutput(sampler.midiIn)
    let callbackTrack = sequencer.newTrack()
    callbackTrack?.setMIDIOutput(callbackInst.midiIn)

    // create the MIDI data
    for i in 0 ..< 4 {
        // this will trigger the sampler on the four down beats
        metronomeTrack?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: Double(i)), duration: AKDuration(beats: 0.5))

        // set the midiNote number to the current beat number
        callbackTrack?.add(noteNumber: MIDINoteNumber(i), velocity: 100, position: AKDuration(beats: Double(i)), duration: AKDuration(beats: 0.5))
    }

    // set the callback
    callbackInst.callback = {status, noteNumber, velocity in
        guard status == .noteOn else { return }
        print("beat number: \(noteNumber + 1)")
        // e.g., resondToBeat(beatNum: noteNumber)
    }

    // get the sequencer ready
    sequencer.enableLooping(AKDuration(beats: 4))
    sequencer.setTempo(60)
    sequencer.play()
c_booth
  • 2,185
  • 1
  • 13
  • 22
  • Hi , Thank you ,but I'm very much new to swift and iOS development is there any sample code that can help me to overcome this ? – RAM Dec 04 '17 at 11:24
  • Hi , I have added my current code , can u please let me know where I was wrong – RAM Dec 06 '17 at 06:51
  • 1
    I'm suggesting that you not use AKSamplerMetronome (which has no obvious way to provide callbacks). Instead use an AKSequencer with AKMIDISampler for the sound and AKCallbackInstrument for the callback. The code that I provided shows exactly how to do that. What is it exactly that you want to do? – c_booth Dec 06 '17 at 08:22
  • Hi , how can i play two sound files using this ? for example i want to play an upbeat file at first sound and downbeat sound as other beat sound is it possible with this ? – RAM Jun 20 '18 at 10:58
  • 1
    Error: Invalid beat range or track is empty – HTron Jul 15 '18 at 13:22
  • I can only hear a Synthesizer sound instead of SynthSnare and see no output on the commandline from AKCallbackInstrument – HTron Jul 15 '18 at 14:24
  • @HSRF, if you are hearing an unexpected synth-like sound with AKSequencer then you probably haven't enabled background audio (you should be seeing a console msg about background mode). If you google the 'Invalid beat range' msg, the top hit is https://groups.google.com/forum/#!topic/audiokit/sJKysWnJkvY - beyond that you should probably post your own question, because the problem is likely in your own code. – c_booth Jul 15 '18 at 16:58
  • @c_booth oh yes, stupid me. forgot to enable the background mode... thank you! – HTron Jul 15 '18 at 17:46
  • But you cannot use play(at: with this, it the same as a regular metronome, you cannot synchronize it with other sound outputs, the whole point of using AKSamplerMetronome is to allow for it to be synchronized... – Carles Estevadeordal Oct 31 '20 at 01:09