Chapter 3 my solution for side quest

We can use second timer for bass chords but it won't be sync with first. In any case I commented second timer and added bassToneOutput to the first timer to sync it.
Code Block
func performance(owner: Assessable) {
let toneOutput = ToneOutput()
let bassToneOutput = ToneOutput()
let qPitches:[Pitch] = [.e3, .e3, .f3, .g3, .g3, .f3, .e3, .d3, .c3, .c3, .d3, .e3, .e3, .d3]
let hPitches:[Pitch] = [.d3]
let notes: [Note] = qPitches.map{Note.quarter($0)} + hPitches.map{Note.half($0)}
var pitches = [Pitch]()
for note in notes {
pitches.append(contentsOf: note.subdivide())
}
var index = 0
let interval = TimeInterval(Note.shortestSupportedNoteLength * 0.5)
Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { timer in
guard index < pitches.count else {
toneOutput.stopTones()
bassToneOutput.stopTones()
timer.invalidate()
owner.endPerformance()
return
}
toneOutput.play(tone: Tone(pitch: pitches[index].frequency, volume: 0.3))
bassToneOutput.play(tone: Tone(pitch: pitches[index].bassFrequency, volume: 0.3))
index += 1
}
// Second timer but it won’t with the first timer.
// Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { timer in
// guard index < pitches.count else {
// bassToneOutput.stopTones()
// timer.invalidate()
// owner.endPerformance()
// return
// }
//
// bassToneOutput.play(tone: Tone(pitch: pitches[index].bassFrequency, volume: 0.3))
// //index += 1
// }
owner.endPerformance()
}

Add new property to Pitch
Code Block language
public var bassFrequency: Double {
return self.rawValue/2.0
}