I have code to take a sequence of letters in a string and interpret them as notes. The code will then play the notes. The problem is that they all play at the same time. How do I play them each as a quarter note, essentially to play a note, wait for it to end, and then play the next note?
@IBAction func playButton(sender: AnyObject) {
fractalEngine.output = "adgadefe"
var notes = Array(fractalEngine.output.characters)
var counter = 0
while counter < notes.count {
var note = notes[counter]
if note == "a" {
play(58)
}
else if note == "b" {
play(59)
}
else if note == "c" {
play(60)
}
else if note == "d" {
play(61)
}
else if note == "e" {
play(62)
}
else if note == "f" {
play(63)
}
else {
play(64)
}
counter += 1
}
//self.sampler.startNote(60, withVelocity: 64, onChannel: 0)
}
func play(note: UInt8) {
sampler.startNote(note, withVelocity: 64, onChannel: 0)
}
func stop(note: UInt8) {
sampler.stopNote(note, onChannel: 0)
}
Here's the code that initiates the sampler:
func initAudio(){
engine = AVAudioEngine()
self.sampler = AVAudioUnitSampler()
engine.attachNode(self.sampler)
engine.connect(self.sampler, to: engine.outputNode, format: nil)
guard let soundbank = NSBundle.mainBundle().URLForResource("gs_instruments", withExtension: "dls") else {
print("Could not initalize soundbank.")
return
}
let melodicBank:UInt8 = UInt8(kAUSampler_DefaultMelodicBankMSB)
let gmHarpsichord:UInt8 = 6
do {
try engine.start()
try self.sampler.loadSoundBankInstrumentAtURL(soundbank, program: gmHarpsichord, bankMSB: melodicBank, bankLSB: 0)
}catch {
print("An error occurred \(error)")
return
}
/*
self.musicSequence = createMusicSequence()
createAVMIDIPlayer(self.musicSequence)
createAVMIDIPlayerFromMIDIFIle()
self.musicPlayer = createMusicPlayer(musicSequence)
*/
}
It looks like you need to delay playing each in turn. Here's one implementation (that avoids blocking the main thread).
What this does is plays each note after an escalating delay, then stops playing after note length, which is assumed to be the delay constant.