Created
June 28, 2020 07:49
-
-
Save mhanlon/eeb55ae8f5660f0169df0c568b4773c3 to your computer and use it in GitHub Desktop.
Swan's Quest, Chapter 4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This code is for the Advice from the Lizard main.swift file | |
// It uses the playInstrument function to play an A4 with an electric guitar. | |
func performance(owner: Assessable) { | |
// TODO: Play an instrument using the calls the Lizard told you about | |
playInstrument(.electricGuitar, note: MIDINotes.a4) | |
// Let the Lizard know when you're done | |
owner.endPerformance() | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Touch "Run My Code" to continue your quest... | |
// The Lizard has decoded the sheet music, in case you need it: | |
let bassNotes: [MIDINotes] = [ | |
.g3, .rest, .g2, .rest, | |
.c3, .g3, .c4, .rest, | |
.b4, .rest, .as4, .rest, | |
.f2, .rest, .f3, .e3, | |
.d3, .rest, .g2, .rest, | |
.c4, .rest, .rest, .rest, | |
.a3, .rest, .fs3, .rest, | |
.f3, .d3, .c4, .a3 | |
] | |
let trebleNotes: [MIDINotes] = [ | |
.rest, .b3, .c4, .d4, | |
.e4, .rest, .rest, .d4, | |
.e4, .a4, .g4, .e4, | |
.d4, .c4, .a3, .rest, | |
.rest, .c4, .e4, .f4, | |
.g4, .rest, .rest, .a4, | |
.g4, .e4, .c4, .e4, | |
.d4, .rest, .rest, .rest | |
] | |
func performance(owner: Assessable) { | |
let numberOfBeats = 32 // two bars of 4/4 | |
let duration = 16.0 // seconds | |
var bass = Track(instrument: .bassGuitar, length: numberOfBeats) | |
var piano = Track(instrument: .piano, length: numberOfBeats) | |
bass.notes = bassNotes | |
piano.notes = trebleNotes | |
let tracks = [bass, piano] | |
let interval = duration / Double(numberOfBeats) | |
var index = 0 | |
Timer.scheduledTimer(withTimeInterval: interval, repeats: true, block: { timer in | |
for track in tracks { | |
playInstrument(track.instrument, note: track.note(for: index)) | |
} | |
if index + 1 < numberOfBeats { | |
index = index + 1 | |
} | |
else { | |
index = 0 | |
// Don't forget to call endPerformance() after you played through the song once. | |
owner.endPerformance() | |
} | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Sequencer.swift | |
// | |
// Copyright © 2020 Apple Inc. All rights reserved. | |
// | |
public protocol MIDINoteProtocol { | |
/// note as an 8-bit MIDI code | |
var midiCode: UInt8 { get } | |
} | |
public protocol TrackProtocol { | |
associatedtype NoteType : MIDINoteProtocol | |
/// The kind of instrument that the track sequences | |
var instrument: Instrument.Kind { get } | |
/// Number of beats contained in the sequence | |
var length: Int { get } | |
/// MIDI code for the sequence frame | |
func note(for frame: Int) -> NoteType | |
} | |
// The Wizard has provided a MIDI Notes implementation for you. | |
public enum MIDINotes : UInt8, MIDINoteProtocol { | |
case rest = 0 | |
case c1 = 24 | |
case cs1 = 25 | |
case d1 = 26 | |
case ds1 = 27 | |
case e1 = 28 | |
case f1 = 29 | |
case fs1 = 30 | |
case g1 = 31 | |
case gs1 = 32 | |
case a1 = 33 | |
case as1 = 34 | |
case b1 = 35 | |
case c2 = 36 | |
case cs2 = 37 | |
case d2 = 38 | |
case ds2 = 39 | |
case e2 = 40 | |
case f2 = 41 | |
case fs2 = 42 | |
case g2 = 43 | |
case gs2 = 44 | |
case a2 = 45 | |
case as2 = 46 | |
case b2 = 47 | |
case c3 = 48 | |
case cs3 = 49 | |
case d3 = 50 | |
case ds3 = 51 | |
case e3 = 52 | |
case f3 = 53 | |
case fs3 = 54 | |
case g3 = 55 | |
case gs3 = 56 | |
case a3 = 57 | |
case as3 = 58 | |
case b3 = 59 | |
case c4 = 60 | |
case cs4 = 61 | |
case d4 = 62 | |
case ds4 = 63 | |
case e4 = 64 | |
case f4 = 65 | |
case fs4 = 66 | |
case g4 = 67 | |
case gs4 = 68 | |
case a4 = 69 | |
case as4 = 70 | |
case b4 = 71 | |
case c5 = 72 | |
case cs5 = 73 | |
case d5 = 74 | |
case ds5 = 75 | |
case e5 = 76 | |
case f5 = 77 | |
case fs5 = 78 | |
case g5 = 79 | |
case gs5 = 80 | |
case a5 = 81 | |
case as5 = 82 | |
case b5 = 83 | |
/// note as an 8-bit MIDI code | |
public var midiCode: UInt8 { | |
return self.rawValue | |
} | |
} | |
// This is the big addition, the definition of a Track struct. | |
public struct Track : TrackProtocol { | |
public var instrument: Instrument.Kind | |
public var length: Int | |
public var notes: [MIDINotes]? = nil | |
public init(instrument: Instrument.Kind, length: Int) { | |
self.instrument = instrument | |
self.length = length | |
} | |
public func note(for frame: Int) -> MIDINotes { | |
guard let n = notes, frame < n.count else { | |
return .rest | |
} | |
return n[frame] | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment