iOSプログラミング with Swift 2


2016.07.01: created by

Swiftで複数の音声を同時に再生する(AVAudioplayer を使う)

AVFoundation の AVAudioPlayer を使って、複数の音声を同時に再生する例です。

  1. Xcode を起動して "Create a new Xcode project" で "Single View Application" として新しいプロジェクトを開きます。 ここではプロジェクト名を SwiftAudioPlay としています。



  2. プロジェクトの最初に表示される画面は、ウィンドウの左側に表示されている "Show the project navigator" アイコンをクリックしても表示されます。 "General" -> "Linked Frameworks and Libraries" ->"+"ボタン を押して Add で AVFoundation.framework を追加します。









  3. プロジェクトに音声ファイルを追加します。プロジェクト名で右クリックして "Add Files to プロジェクト名"を選択します。 ファイルを追加する画面では Options を選択してCopy items if needed にチェックを入れてから Addボタンをクリックして ファイルを追加します。
  4. この例では素材フリーのサイトからダンロードした次の5種類のmp3形式のファイルを追加しました。










  5. Main.storyboard 上の ViewController に Button を5個配置し、表示をそれぞれ "Sound1", "Sound2", "Sound3", "Sound4", "Sound5" に変えておきます。



  6. Button をそれぞれ ViewController.swift 中の関数とconnect します。
  7. UIViewオブジェクト 表示 connect 名前
    Button Sound1 Action (Touch Up Inside) tapSound1()関数
    Button Sound2 Action (Touch Up Inside) tapSound2()関数
    Button Sound3 Action (Touch Up Inside) tapSound3()関数
    Button Sound4 Action (Touch Up Inside) tapSound4()関数
    Button Sound5 Action (Touch Up Inside) tapSound5()関数



  8. ViewController.swift を変更します。
  9. ViewController.swiftに追加するコード(赤字部分)
    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController {
        
        var players:[AVAudioPlayer]!
        let audioFiles = ["download4817","download4801","download4763","download4691","download4685" ]
    
        @IBAction func tapSound1(sender: AnyObject) {
            play(0)
        }
        @IBAction func tapSound2(sender: AnyObject) {
            play(1)
       }
        @IBAction func tapSound3(sender: AnyObject) {
            play(2)
        }
        @IBAction func tapSound4(sender: AnyObject) {
            play(3)
        }
        @IBAction func tapSound5(sender: AnyObject) {
            play(4)
        }
        
        func play(n:Int) {
            if n < players.count {
                players[n].play()
            }
        }
        
        func setup() {
            players = []
            for fname in audioFiles {
                let path = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(fname, ofType: "mp3")!)
                do {
                    let player = try AVAudioPlayer(contentsOfURL:path)
                    players.append(player)
                } catch let error as NSError {
                    print("error has occurred: \(error)")
                }
            }
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
            setup()
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    
    }
    
  10. 実行します。ボタンをタップすると音声が流れます。同時に複数の音声が再生できます。



  11. サンプルのプロジェクトはこちら。(Xcode 7.3.1版)
  12. xcodeでswift3に自動変換したプロジェクトはこちら。(Xcode 8.3.3版)

改良

上の例では、説明を簡単にするために余分な機能は実装していませんでした。 以下のような改善が考えられることでしょう。

この改善案を実装した例を示します。

  1. Main.storyboard上で ViewController 中に UISliderオブジェクトを5個配置し、 それぞれを ViewController.swift 中の volumeX というOutlet変数にconnectし、 さらに volumeSX ()という関数に Action (Value Changed) で connect する(Xは上から順に数字の1, 2, 3, 4, 5とする)。
  2. UIViewオブジェクト 配置(どのボタンの右か) connect プロパティ名または関数名
    Slider Sound1 Outlet volume1変数
    Action (Value Changed) volumeS1()関数
    Slider Sound2 Outlet volume2変数
    Action (Value Changed) volumeS2()関数
    Slider Sound3 Outlet volume3変数
    Action (Value Changed) volumeS3()関数
    Slider Sound4 Outlet volume4変数
    Action (Value Changed) volumeS4()関数
    Slider Sound5 Outlet volume5変数
    Action (Value Changed) volumeS5()関数






  3. ViewController.swift を変更します。
  4. ViewController.swiftに追加するコード(マゼンダ色の字部分)
    import UIKit
    import AVFoundation
    
    class ViewController: UIViewController {
        
        var players:[AVAudioPlayer]!
        let audioFiles = ["download4817","download4801","download4763","download4691","download4685" ]
    
        @IBAction func tapSound1(sender: AnyObject) {
            play(0)
        }
        @IBAction func tapSound2(sender: AnyObject) {
            play(1)
       }
        @IBAction func tapSound3(sender: AnyObject) {
            play(2)
        }
        @IBAction func tapSound4(sender: AnyObject) {
            play(3)
        }
        @IBAction func tapSound5(sender: AnyObject) {
            play(4)
        }
        
        @IBOutlet weak var slider1: UISlider!
        @IBOutlet weak var slider2: UISlider!
        @IBOutlet weak var slider3: UISlider!
        @IBOutlet weak var slider4: UISlider!
        @IBOutlet weak var slider5: UISlider!
        @IBAction func volumeS1(sender: AnyObject) {
            setVolume(0,slider1.value)
        }
        @IBAction func volumeS2(sender: AnyObject) {
            setVolume(1,slider2.value)
        }
        @IBAction func volumeS3(sender: AnyObject) {
            setVolume(2,slider3.value)
        }
        @IBAction func volumeS4(sender: AnyObject) {
            setVolume(3,slider4.value)
        }
        @IBAction func volumeS5(sender: AnyObject) {
            setVolume(4,slider5.value)
        }
        
        func play(n:Int) {
            if n < players.count {
                if players[n].playing {
                    players[n].stop()
                    players[n].currentTime = 0.0
                }
                players[n].play()
            }
        }
        
        func setVolume(n:Int, _ value:Float) {
            if n < players.count {
                players[n].volume = value
            }
        }
        
        func setup() {
            players = []
            for fname in audioFiles {
                let path = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(fname, ofType: "mp3")!)
                do {
                    let player = try AVAudioPlayer(contentsOfURL:path)
                    players.append(player)
                } catch let error as NSError {
                    print("error has occurred: \(error)")
                }
            }
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
            setup()
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
    
    }
    
  5. サンプルのプロジェクトはこちら。(Xcode 7.3.1版)


http://karel.tsuda.ac.jp