forked from laurentVeliscek/SelectorClock
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSelectorMidiInstrument.swift
124 lines (90 loc) · 2.79 KB
/
SelectorMidiInstrument.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//
// SelectorMidiInstrument.swift
//
//
// Created by Laurent Veliscek on 17/05/2016.
// Copyright © 2016 Laurent Veliscek. All rights reserved.
//
import Foundation
import AudioKit
/******************************************************************************************
SelectorMidiInstrument is a dummy midiInstrument that will trig passed functions each time
it receive Midi noteOn message.
It can be easily tweaked to trig different functions from different NoteOn Messages.
*******************************************************************************************/
class SelectorMidiInstrument: AKMIDIInstrument{
// MARK: Private Properties
private var _clients:Array<Void -> Void> = []
private var _clickOsc = AKFMSynth(voiceCount: 2)
private var _clickPlayed = false
private var _tickNumber = 0
// MARK: Public Properties
var tickNumber: Int{
get {
return _tickNumber
}
}
// default value is true
// when set to false, a click note is produced
var silent = true
// Midi Pitch of the click note (should be from 10 to 110)
var clickPitch = 60
// Volume of the click note
var clickVolume: Double {
get{
return _clickOsc.volume
}
set {
if newValue < 0 {
_clickOsc.volume = 0
}
else{
_clickOsc.volume = newValue
}
}
}
func reset(){
_tickNumber = 0
}
init() {
super.init(instrument: _clickOsc)
_clickOsc.attackDuration = 0.001
_clickOsc.decayDuration = 0.01
_clickOsc.sustainLevel = 0.001
_clickOsc.releaseDuration=0.01
_clickOsc.volume = 0.1
print ("SelectorMidiInstrument initialized")
}
// add a function to be triggered each time a NoteOn is received
func addClient(f: Void -> Void){
_clients.append(f)
print ("client added !")
}
// will trig any functions attached using addClient method
private func trigClients()
{
for c in _clients
{
c()
}
_tickNumber += 1
}
// Will trig in response to any noteOn Message
override internal func startNote(note: Int, withVelocity velocity: Int, onChannel channel: Int) {
trigClients()
if _clickOsc.volume > 0.0 && silent == false
{
if _clickPlayed
{
_clickOsc.stopNote(clickPitch)
}
else{
_clickPlayed = true
}
_clickOsc.playNote(clickPitch, velocity: 100)
}
}
override internal func stopNote(note: Int, onChannel channel: Int) {
// Does nothing, this instrument is not supposed to respond to NoteOff messages
}
}