How is the AKSequencer setup in AudioKit > 4.8? - audiokit

An example of how to set up the latest version of AKSequencer is not available, so I had to assume a few things based in the previous version.
I have the following implementation for the AKAppleSequencer that works and there's audio output:
let track = sequencer.newTrack()
track?.setMIDIOutput(sampler.midiIn)
track?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: 1), duration: AKDuration(beats: 0.25))
sequencer.enableLooping(AKDuration(beats: 4))
sequencer.setTempo(self.defaultTempo)
sequencer.play()
Meanwhile, what I supposed to be enough for the latest AKSequencer has no audio output:
let track: AKSequencerTrack = self.sequencer.addTrack(for: self.sampler)
track.add(noteNumber: 60, velocity: 100, position: 1, duration: 1)
sequencer.length = 4
sequencer.loopEnabled = true
sequencer.tempo = 60
sequencer.play()
Both cases have the sampler connected to the mainMixer and are assigned to the AudioKit.output.
Since this doesn't work for the latest AKSequencer, I thought that the maybe plugging the AKSequencerTrack to the mainMixer and unplugging the sampler to the mainMixer could do? But didn't work!
mainMixer.connect(input: track)
Running out of alternatives! So, after looking for AKSequencerTrack found someone else reporting the same issue (Why is the new AKSequencer not producing any sound?), so tried:
mainMixer.connect(input: sampler)
mainMixer.connect(input: track)
Again, no sound! There's also a link to this related topic, which is similar to my previous attempt, which there's no output (How to play MIDI with AudioKit's new AKSequencer), but just to make sure changed to use the AKSampler and loaded a local sound:
sampler.loadSFZ(url: Bundle.main.url(forResource: "clock", withExtension: "wav")!)
Another failure...! There's no sound.
I'm running AudioKit 4.9.5
Just to keep my sanity, there's a method .play in AKSequencerTrack, what happens if I call it?
track.play()
No sound! Ok, what if I change the sampler back to AKSnareSynth?
let t: AKSynthSnare = AKSynthSnare()
sequencer.addTrack(for: t)
Did it play? Nope!
Do I have output at all in non AKSequencer? Yes:
let t: AKSynthSnare = AKSynthSnare()
self.mainMixer.connect(input: t)
t.play(noteNumber: 60,
velocity: MIDIVelocity(127),
channel: MIDIChannel(1))
What about the .isPlaying is it Truthy?
for track in self.sequencer.tracks {
mainMixer.connect(input: track)
track.play()
print("> > > > track.isPlaying: \(track.isPlaying)")
}
Yes, the isPlaying returns true:
> > > > track.isPlaying: true
But, nope, there's no sound!
I think the AKSequencer is a dark box for now and shouldn't be used unless someone posts an example in Github (which I searched for in source-codes but nothing at the time of writing). Or maybe I'm doing something wrong I don't know, just wasted a day of my life trying different things.

#c_booth provided the answer in the following post ( AudioKit: Using the new AKSequencer with any variety of the callback instruments )
Seems that the loop, tempo are set in the track not the sequencer itself,
// set up a track
let track = seq.addTrack(for: cbInst)
for i in 0 ..< 4 {
track.add(noteNumber: 60, position: Double(i), duration: 0.5)
}
track.length = 4.0
track.loopEnabled = true

Related

Issue with AudioKit v5 oscillator frequency ramp

I'm new to AudioKit and am using v5. The oscillator frequency ramp doesn't seem to work as expected. The following example has 2 successive ramps. First it ramps 440-880, but then sounds like it goes 880-660 instead of 440-660.
If I comment out osc.$frequency.ramp(to: 660.0, duration: 1.0), it ramps 440-880, then ramps extremely quickly to 440 but gets there.
Seems like something isn't resetting after the ramp.
(The sleeps are only for testing.)
Is this a bug? Is there something else I should be doing? Any insight would be much appreciated! Thanks!
import Cocoa
import AudioKit
class Test {
let akEngine = AudioEngine()
let osc = Oscillator()
func setup() {
osc.amplitude = 0.1
akEngine.output = osc
do {
try akEngine.start()
} catch {
print("Couldn't start AudioEngine.")
}
osc.frequency = 440.0
osc.start()
osc.$frequency.ramp(to: 880.0, duration: 1.0)
sleep(2)
osc.stop()
sleep(1)
osc.frequency = 440.0
osc.start()
osc.$frequency.ramp(to: 660.0, duration: 1.0)
sleep(2)
osc.stop()
}
}
This probably deserves an explanation, or maybe it should be fixed to work as you have it above, but once you start automating changes, you should stick with the automation syntax and not jump out to plain setting of values. For you this means just replacing osc.frequency = 440 with osc.$frequency.ramp(to: 440.0, duration: 0.0) and I believe you will get the effect you want.
Setting a parameter (osc.frequency = 440.0) causes a tiny ramp to be used to avoid zippering (equivalent to osc.$frequency.ramp(to: 440.0, duration:epsilon)). The test code immediately applies another ramp, overriding the zippering ramp.
If you insert a sleep after your second osc.start(), you'll hear the quick zipper ramp back to 440.

Audiokit: (V5) Sequencer cannot play notes simultaneously at the same position in a track

I have used Audiokit's both AKAppleSequencer and AKSequencer for 2 years now. This is my first iteration getting used to the new V5 version of the library. For whatever reason, I cannot get more than a single note to play simultaneously.
Below is a very simple example of what I am trying to do:
public func setupSequencerForInterval(note1: MIDINoteNumber, note2: MIDINoteNumber) {
sequencer.clear()
sequencer = Sequencer(targetNode: sampler)
sequencer.tempo = 120
sequencer.loopEnabled = false
sequencer.length = 12.0
sequencer.add(noteNumber: note1, velocity: 127, channel: 1, position: 0.0, duration: 4.0, trackIndex: 0)
sequencer.add(noteNumber: note2, velocity: 127, channel: 1, position: 4.0, duration: 4.0, trackIndex: 0)
sequencer.add(noteNumber: note1, velocity: 127, channel: 1, position: 8.0, duration: 4.0, trackIndex: 0)
sequencer.add(noteNumber: note2, velocity: 127, channel: 1, position: 8.0, duration: 4.0, trackIndex: 0)
}
Here is what it sounds like
A sequence of 3 whole notes: 1st whole note on note1, 2nd whole note on note2, 3rd whole note both note1 and note2 playing together.
I have tested my sampler to make sure it was not monophonic, and it can play notes polyphonically.
Stranger yet, if I change the last line of (adding the note 2 whole note at the same position as note 1 at position 8.0) to a position of anything greater than 8.0, the effect of polyphony occurs. You can hear that here, a value of 8.01 was used for position on the last sequencer.add call
Is this intended behavior? Is Sequencer not supposed to play multiple notes at the same position? Any guidance would be greatly appreciated, thank you!
According to the AudioKit team, this is not intended behavior and is being looked into: https://github.com/AudioKit/AudioKit/issues/2409

AudioKit (still) missing Clock for sequencing Audiofiles

I am trying to playback audiofiles using with the sequencer in AudioKit framework.
AudioKit.output = sampler
AudioKit.start()
sampler.enableMIDI(midi.client,name: "sampler")
// sequencer start
let seq = AKSequencer()
seq.setLength(AKDuration(beats:Double(4)))
seq.enableLooping()
let pattern = seq.newTrack()
pattern?.setMIDIOutput(sampler.midiIn)
pattern!.add(noteNumber: 48, velocity: 127, position: AKDuration(beats:Double(1)), duration: AKDuration(beats:Double(0.2)), channel: 0)
pattern!.add(noteNumber: 48, velocity: 127, position: AKDuration(beats:Double(1)), duration: AKDuration(beats:Double(0.2)), channel: 0)
pattern!.add(noteNumber: 48, velocity: 127, position: AKDuration(beats:Double(2)), duration: AKDuration(beats:Double(0.2)), channel: 0)
pattern!.setLoopInfo(AKDuration( beats:Double(4) ), numberOfLoops: 80)
seq.play()
I got to the point where the AKMidiSampler will only play sine waves but not the right sample as described here
So as it turns out it is not possible to create sequences "on the fly" so i started to look for workarounds and found SelectorClock Its a workaround from the AudioKit Developers. Sadly this is not working anymore.. many of the class definitions and their properties changed.
Maybe I am not up to date and this is fixed already.. if not I'm sure there must be a go to solution to this issue.
Turn on the background capability to your target.
Choose audio.
Without this, you get just sine waves.
If you want to be completely independent from using AKSequencer you can try the following:
let metro = AKMetronome()
metro.tempo = 120.0
metro.frequency1 = 0
metro.frequency2 = 0
metro.callback = {
// your code e.g.: trigger a AKSamplePlayer() which should have been defined earlier in your code:
sample.play()
}
AudioKit.output = AKMixer(metro, sample)
try! AudioKit.start()
metro.start()
I haven‘t tested this piece of code since I am on my phone right now but it should work. I have this concept running on my iPhone 6s and it works very well. I also tried to replace AKMetronome() with my own class but I haven‘t figured out every single aspect of the sporth parameter yet. I basically want to get rid of initiating any metronome sound ( which is already set to zero in sporth so shouldn‘t produce any noise ) in the first place.. I‘ll let you know in case I‘ll achieve that.

Is 5.1 channel positional audio output in Sprite Kit possible?

I'm trying to play positional audio using the front and back channels in Sprite Kit, and testing on an Apple TV device.
I'm using the following code:
let musicURL = NSBundle.mainBundle().URLForResource("music", withExtension: "m4a")
let music = SKAudioNode(URL: musicURL!)
addChild(music)
music.positional = true
music.position = CGPoint(x: 0, y: 0)
let moveForward = SKAction.moveToY(1024, duration: 2)
let moveBack = SKAction.moveToY(-1024, duration: 2)
let sequence = SKAction.sequence([moveForward, moveBack])
let repeatForever = SKAction.repeatActionForever(sequence)
music.runAction(repeatForever)
What I want to accomplish is a sound that pans from the front to the back channels but Sprite Kit seems to be using just the 2 channel stereo output.
If I use moveToX instead of moveToY I get a sound panning from left to right.
I'm surely missing some initialization code to signal I want a 5.1 sound output, but I'm not sure if the SKAudioNode positional feature only works for 2 channel stereo output.
Is positional audio with more than 2 channels achievable in Sprite Kit or should I resort to AVFoundation or even OpenAL for this?
I have tried similar code with SceneKit and it seems that it also uses only 2 channels for positional audio.
A sound can't be positioned in 3D space using SceneKit. You should not use an SKAudioNode but use AVFoundation directly to play the sound.
First you have to setup the audio session to use a 5.1 channel output layout:
let session = AVAudioSession.sharedInstance()
session.setCategory(AVAudioSessionCategoryPlayback)
session.setActive(true)
session.setPreferredOutputNumberOfChannels(6)
And then wire an AVAudioEnvironmentNode setup to output the 6 output channels.
A starting point can be found in this existing answer:
https://stackoverflow.com/a/35657416/563802

AVAudioMixerNode pan or AVAudioUnitSampler stereoPan properties not working to change left/right balance of sound output for AVAudioEngine

I have the following code, which plays a single midi note, but I want to be able to adjust the balance/pan so that it only plays out of the left speaker or the right speaker or perhaps some combination. I thought changing "sampler.stereoPan" or perhaps "engine.mainMixerNode.pan" would do the trick but it seems to have no effect. Any ideas what I'm doing wrong?
engine = AVAudioEngine()
sampler = AVAudioUnitSampler()
sampler.stereoPan = -1.0 // doesn't work
//engine.mainMixerNode.pan = -1.0 // doesn't work
engine.attachNode(sampler)
engine.connect(sampler, to: engine.mainMixerNode, format: engine.mainMixerNode.outputFormatForBus(0))
var error: NSError?
engine.startAndReturnError(&error)
sampler.startNote(65, withVelocity: 64, onChannel: 1)
You should set the pan of any node after it has been connected, the pan settings are defaulted again at the engine.connect method.
According to Apple Developer Forum the range of stereopan is -100 to 100.

Resources