9
\$\begingroup\$

I'm making my first app in Swift: a Piano app. I'd like to get your feedback especially about how I can make codes shorter. I maybe have to use arrays and loops and something, and searched by myself but couldn't get it.

view controller.swift

import UIKit
import AVFoundation

class ViewController: UIViewController {

var pianoSoundC3 = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("C3", ofType: "mp3")!)
var audioPlayerC3 = AVAudioPlayer()

var pianoSoundCS = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("C#", ofType: "mp3")!)
var audioPlayerCS = AVAudioPlayer()

var pianoSoundD = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("D", ofType: "mp3")!)
var audioPlayerD = AVAudioPlayer()

var pianoSoundDS = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("D#", ofType: "mp3")!)
var audioPlayerDS = AVAudioPlayer()

var pianoSoundE = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("E", ofType: "mp3")!)
var audioPlayerE = AVAudioPlayer()

var pianoSoundF = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("F", ofType: "mp3")!)
var audioPlayerF = AVAudioPlayer()

var pianoSoundFS = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("F#", ofType: "mp3")!)
var audioPlayerFS = AVAudioPlayer()

var pianoSoundG = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("G", ofType: "mp3")!)
var audioPlayerG = AVAudioPlayer()

var pianoSoundGS = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("G#", ofType: "mp3")!)
var audioPlayerGS = AVAudioPlayer()

var pianoSoundA = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("A", ofType: "mp3")!)
var audioPlayerA = AVAudioPlayer()

var pianoSoundAS = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("A#", ofType: "mp3")!)
var audioPlayerAS = AVAudioPlayer()

var pianoSoundB = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("B", ofType: "mp3")!)
var audioPlayerB = AVAudioPlayer()

var pianoSoundC4 = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("C4", ofType: "mp3")!)
var audioPlayerC4 = AVAudioPlayer()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    audioPlayerC3 = AVAudioPlayer(contentsOfURL: pianoSoundC3, error: nil)
    audioPlayerC3.prepareToPlay()

    audioPlayerCS = AVAudioPlayer(contentsOfURL: pianoSoundCS, error: nil)
    audioPlayerCS.prepareToPlay()

    audioPlayerD = AVAudioPlayer(contentsOfURL: pianoSoundD, error: nil)
    audioPlayerD.prepareToPlay()

    audioPlayerDS = AVAudioPlayer(contentsOfURL: pianoSoundDS, error: nil)
    audioPlayerDS.prepareToPlay()

    audioPlayerE = AVAudioPlayer(contentsOfURL: pianoSoundE, error: nil)
    audioPlayerE.prepareToPlay()

    audioPlayerF = AVAudioPlayer(contentsOfURL: pianoSoundF, error: nil)
    audioPlayerF.prepareToPlay()

    audioPlayerFS = AVAudioPlayer(contentsOfURL: pianoSoundFS, error: nil)
    audioPlayerFS.prepareToPlay()

    audioPlayerG = AVAudioPlayer(contentsOfURL: pianoSoundG, error: nil)
    audioPlayerG.prepareToPlay()

    audioPlayerGS = AVAudioPlayer(contentsOfURL: pianoSoundGS, error: nil)
    audioPlayerGS.prepareToPlay()

    audioPlayerA = AVAudioPlayer(contentsOfURL: pianoSoundA, error: nil)
    audioPlayerA.prepareToPlay()

    audioPlayerAS = AVAudioPlayer(contentsOfURL: pianoSoundAS, error: nil)
    audioPlayerAS.prepareToPlay()

    audioPlayerB = AVAudioPlayer(contentsOfURL: pianoSoundB, error: nil)
    audioPlayerB.prepareToPlay()

    audioPlayerC4 = AVAudioPlayer(contentsOfURL: pianoSoundC4, error: nil)
    audioPlayerC4.prepareToPlay()

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

@IBAction func C3(sender: UIButton) {
    audioPlayerC3.currentTime = 0
    audioPlayerC3.play()
}

@IBAction func CS(sender: UIButton) {
    audioPlayerCS.currentTime = 0
    audioPlayerCS.play()
}

@IBAction func D(sender: UIButton) {
    audioPlayerD.currentTime = 0
    audioPlayerD.play()
}

@IBAction func DS(sender: UIButton) {
    audioPlayerDS.currentTime = 0
    audioPlayerDS.play()
}

@IBAction func E(sender: UIButton) {
    audioPlayerE.currentTime = 0
    audioPlayerE.play()
}

@IBAction func F(sender: UIButton) {
    audioPlayerF.currentTime = 0
    audioPlayerF.play()
}

@IBAction func FS(sender: UIButton) {
    audioPlayerFS.currentTime = 0
    audioPlayerFS.play()
}

@IBAction func G(sender: UIButton) {
    audioPlayerG.currentTime = 0
    audioPlayerG.play()
}

@IBAction func GS(sender: UIButton) {
    audioPlayerGS.currentTime = 0
    audioPlayerGS.play()
}

@IBAction func A(sender: UIButton) {
    audioPlayerA.currentTime = 0
    audioPlayerA.play()
}

@IBAction func AS(sender: UIButton) {
    audioPlayerAS.currentTime = 0
    audioPlayerAS.play()
}

@IBAction func B(sender: UIButton) {
    audioPlayerB.currentTime = 0
    audioPlayerB.play()
}

@IBAction func C4(sender: UIButton) {
    audioPlayerC4.currentTime = 0
    audioPlayerC4.play()
}

}
\$\endgroup\$
1
  • \$\begingroup\$ It's worth nothing that if you can penetrate the documentation, Apple actually provides AUSampler, which can load a custom set of samples into a MIDI instrument. It's basically designed to do exactly what you're doing here, only it uses a preprepared bundle of samples, loads in one step, and then you can fire MIDI commands at it rather than working a whole bunch of AVAudioPlayers. \$\endgroup\$ Commented Dec 15, 2014 at 8:48

1 Answer 1

17
\$\begingroup\$

I think this should work. The key (pun intended) to making this work is to take advantage of the tag property of UIButton. In Interface Builder, set a different tag to each piano key. Start with 0 for "C3", 1 for "C#", up to 12 for "C4". Wire all of those keys to playKey.

import UIKit
import AVFoundation

class ViewController: UIViewController {

    let pianoKeys = ["C3", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", "C4"]
    var audioPlayers:[AVAudioPlayer] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        for key in pianoKeys {
            let pianoSoundURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(key, ofType: "mp3")
            let audioPlayer = AVAudioPlayer(contentsOfURL: pianoSoundURL, error: nil)
            audioPlayer.prepareToPlay()
            audioPlayers.append(audioPlayer)
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func playKey(sender: UIButton) {
        let keynum = sender.tag
        audioPlayers[keynum].currentTime = 0
        audioPlayers[keynum].play()
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ It worked! now I come to understand Arrays, for in, and .tag property. Thank you very much! \$\endgroup\$
    – Bick
    Commented Oct 6, 2014 at 4:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.