[iOS][Swift]AVAudioPlayerを使う(再生速度の変更、複数のプレイヤー)

[iOS][Swift]ミュージックライブラリにアクセスして音楽を再生する(AVAudioPlayer使用) | nackpan Blog
で、AVAudioPlayerを使いました。
今回は、そこで使っていなかったAVAudioPlayerの機能のいくつかを使ってみたいと思います。
• 再生速度の変更
• 複数のプレイヤーの使用
です。

再生速度の変更

プレイヤーのrateプロパティを変更することで、再生速度を変更できます。
ただし、そのさいのプレイヤーは、enableRateプロパティをtrueにしておく必要があります。

    
    // (playerはAVAudioPlayerのインスタンス)
    // 再生レート変更可能にする
    player.enableRate = true
    // 再生速度を0.7にする
    player.rate = 0.7

複数のプレイヤーの使用

AVAudioPlayerは複数のプレイヤーを同時に再生することができます。
なので、たとえば、歌を再生すると同時に、歓声だとか、ざわめき音など環境音的なものを重ねて再生するなんてこともできます。

    
    var audioPlayer0: AVAudioPlayer?
    var audioPlayer1: AVAudioPlayer?

のように、プロパティとして、二つのプレイヤーを設置して、

    
    audioPlayer0 = try? AVAudioPlayer(contentsOfURL: url0)
    audioPlayer1 = try? AVAudioPlayer(contentsOfURL: url1)
    
    if audioPlayer0 == nil || audioPlayer1 == nil {
        // 再生できません
    
        return
    }
    
    
    // 再生開始
    if let player0 = audioPlayer0, player1 = audioPlayer1 {
        
        // 再生
        player0.play()
        player1.play()
    }

とした場合に、同時再生できます。

サンプルプロジェクト

再生速度の変更と、2曲の同時再生を行うサンプルを作りました。
ss 2015-09-20 21 28 37

「選曲」ボタンを押すと、メディアピッカーが現れるので、そこで2曲選択してください。
すると、選択した2曲を同時に再生しはじめます。
再生速度とボリュームを調整できます。

プロジェクトはGitHubにあります。
nackpan/AVAudioPlayerDemo2

関連

[iOS][Swift]ミュージックライブラリにアクセスして音楽を再生する(AVAudioPlayer使用) | nackpan Blog
[iOS][Swift]AVAudioPlayerを使う(リソースファイルを使う) | nackpan Blog
[iOS][Swift]AVAudioPlayerを使う(複数の曲をあつかう) | nackpan Blog

[iOS][Swift]ミュージックライブラリにアクセスして音楽を再生する(MPMusicPlayerController使用) | nackpan Blog

「[iOS][Swift]AVAudioPlayerを使う(再生速度の変更、複数のプレイヤー)」への5件のフィードバック

  1. 個人でアプリ制作の勉強をしていたのですが、ちょうど複数プレイヤーを一つのView Controllerで操作する部分で悩んでいたため、参考になりました。
    ありがとうございます。

  2. nackpanさま

    参考にさせていただいております。

    どうしても分からない部分があり行き詰まっております。
    現在、シンプルなヒーリング音楽再生アプリを制作しており、1つのView Controller内に2つのプレイヤーを設置し、1つは音楽、1つは環境音が鳴るようにしてあり、個別に再生、停止、
    ボリュームスライダーを設置してあります。
    Mac上のシミュレーターや実機でのテストも稼働しているのですが、再生ボタンを押した後に停止ボタンやボリュームスライダーを操作するのは問題無いのに、アプリを立ち上げた後、再生ボタンを押さない状態で、最初に停止ボタンやスライダーを操作しようとすると、アプリが強制終了してしまいます。
    その際、タッチしたのが停止ボタンなら停止ボタン、スライダーならスライダーにthread1:EXC_BAD_ACCESS(code1,address=0×38)というエラーが出ます。コードは以下の形です。
    ーーーーーーーーーー
    import UIKit
    import AVFoundation

    class ViewController2: UIViewController {

    @IBAction func play(sender: AnyObject) {

    let audioPath = NSBundle.mainBundle().pathForResource(“returna.solo”, ofType: “wav”)!

    do {

    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
    try AVAudioSession.sharedInstance().setActive(true)

    try Player1 = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: audioPath))

    Player1.play()

    } catch {

    }
    }

    @IBAction func play2(sender: AnyObject) {

    let audioPath = NSBundle.mainBundle().pathForResource(“seseragi”, ofType: “wav”)!

    do {

    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
    try AVAudioSession.sharedInstance().setActive(true)

    try Player2 = AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: audioPath))

    Player2.play()

    } catch {
    // Process error here
    }
    }

    @IBAction func pause(sender: AnyObject) {

    Player1.pause()

    }

    @IBAction func pause2(sender: AnyObject) {

    Player2.pause()
    }

    @IBAction func adjustvolume1(sender: AnyObject) {

    Player1.volume = volumeslider1.value
    }

    @IBAction func adjustvolume2(sender: AnyObject) {

    Player2.volume = volumeslider2.value
    }

    @IBOutlet weak var volumeslider1: UISlider!

    @IBOutlet weak var volumeslider2: UISlider!

    var Player1: AVAudioPlayer = AVAudioPlayer()
    var Player2: AVAudioPlayer = AVAudioPlayer()

    override func viewDidLoad() {
    super.viewDidLoad()

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

    // MARK: Volume Changed

    }

    }

    アプリ開発支援のフォーラムで質問したところ以下のような説明を頂いたのですが、全くの素人のため、具体的に自分のコードを直す場合、どのように書き込めば良いのか分かりません。
    もしお助け頂けたら大変幸いです。

    頂いた説明は以下の通りです。
    ーーーーーーーーーー
    Player1とPlayer2は、インスタンスプロパティとして宣言されて、宣言時にAVAudioPlayer()として初期化を行っていますが、AVAudioPlayerクラスは、Swiftのクラスがそなえる基本のイニシャライザーである、引数無しの初期化指定には対応していない様です。

     つまり、「var player1 = AVAudioPlayer()」として宣言しても、AVAudioPlayerクラス型オブジェクトを格納する変数が宣言されるだけで、まともな中身が伴わない状態になっています。この状態で、再生状態を変更しようとしてエラーが出ていると思われます。

     解消するには、プロパティの宣言を「var player1:AVAudioPlayer?」(?ではなくて!でも可)の様に、型だけ指定するかたちにします。そして、スライダーや停止ボタンの処理で、再生状態を変更使用とする前に「if let player = self.player1 { 変更処理 }」などとオプショナルバインディングを行えばいいでしょう(!で宣言した場合はnilチェック)。

  3. var player1:AVAudioPlayer? = nil
    と定義して、
    Player1?.pause()
    Player1?.volume = volumeslider1.value
    とすることで問題が解決しました。
    勉強不足でした。

コメントする

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください