Here's another little experiment in Swift with the amazing AudioKit libraries I posted about recently. In this one, I've created a very rough simulation of pendulum waves and added a mandolin sound to each pendulum that plays as it reaches the apex of its swing.
My code only really consists of two classes, my ViewController and a Pendulum class.
The Pendulum instances do all the hard work. Its init() method accepts arguments for the pendulum period, the pendulum length and the frequency of the note it should play. In reality, the period is a function of the length but I decided to cheat for this demo.
Once a Pendulum instance is added to the display list, it invokes its swing() method. Here I use UIView.animateWithDuration() to complete one period by rotating the pendulum through an arc. When the animation completes, it invokes the same swing() method, but with the angle of the rotation reversed. Because the animation uses a CurveEaseInOut, the end result is a passable looking pendulum animation:
func swing(value: Bool)
{
transform = CGAffineTransformMakeRotation(direction*angle)
direction = -direction
UIView.animateWithDuration(pendulumDuration, delay: 0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { self.transform = CGAffineTransformMakeRotation(self.direction*self.angle) }, completion: swing)
mandolin.stop()
mandolin.play()
}
Of course, each swing also plays the pendulum's Mandolin instance which looks like this:
class Mandolin: AKInstrument
{
init(noteFrequency: Double)
{
super.init()
let frequency = AKInstrumentProperty(value: Float(noteFrequency), minimum: 0, maximum: 1000)
let amplitude = AKInstrumentProperty(value: 0.04, minimum: 0, maximum: 0.25)
addProperty(frequency)
addProperty(amplitude)
let fmOscillator = AKMandolin()
fmOscillator.frequency = frequency
fmOscillator.amplitude = amplitude
connect(fmOscillator)
connect(AKAudioOutput(audioSource: fmOscillator))
}
}
All the view controller does is create a handful of Pendulum instances based on an array of note frequencies:
var pendula = [Pendulum]()
let notes = [261.6,277.2,293.7,311.1,329.6,349.2,370.0,392.0,415.3,440.0,466.2,493.9]
overridefunc viewDidLoad()
{
super.viewDidLoad()
view.backgroundColor = UIColor.lightGrayColor()
for (idx: Int, noteFrequency: Double) inenumerate(notes)
{
let i = idx + 5
let pendulumDuration = (15 / Float(i))
let pendulumLength = (21 - i) * 25
let pendulum = Pendulum(pendulumDuration: pendulumDuration , pendulumLength: pendulumLength, noteFrequency: noteFrequency)
pendula.append(pendulum)
view.addSubview(pendulum)
}
AKOrchestra.start()
}
Easy!
The project, which I've named PendulaTone lives in my GitHub repository here.