[Swift] AVAudioPlayer. 音楽、効果音の再生、ループ回数、音量、速度を設定する。 | はじはじアプリ体験記

AVAudioPlayer
【Swift】AVAudioPlayerの使い方。音楽や効果音を鳴らす。

  • 2016年7月12日
    Swift 2.1で検証
  • Twitterでシェア
  • Facebook
  • LINEで送る

AVAudioPlayerとは

AVAudioPlayerとは、音を鳴らすための機能である。複数の音をループ回数や音量、速度などを設定して再生できる。

AVAudioPlayerを使うにはAVFoundationフレームワークをインポートする。ちなみに、音を鳴らす機能を持ったフレームワークは他にもあるが本記事ではAVAudioPlayerのみを紹介する。

 

AVAudioPlayerを試す

実際にAVAudioPlayerを試してみよう。

以降の手順を行う前のXcodeプロジェクトをGitHubに置いたので、試してみる人はご利用下さい。
⇒「テスト用プロジェクト

事前準備ではテスト用の音楽ファイル(mp3)を2個取り込んでおいたのと、デバイス画面にボタンを2個配置しておいた。現段階ではボタンを押しても何も起きない。

事前準備

 

ViewController.swiftを以下のコードに変更する。

音の再生はとてもシンプルに実装することができ、音声ファイルのURLを引数にAVAudioインスタンスを作成し、作成したインスタンスに対してplayメソッドを呼ぶだけである。

prepareToPlayメソッドは、再生開始までの遅延を無くすために音楽データをあらかじめバッファに読み込んでおくためにある。

 

以下は実際のプレイ動画

 

 

2つの音を並列で鳴らす

複数の音を並列で鳴らす場合は、AVAudioPlayerインスタンスを音ファイルぶん作成し、各インスタンスのplayメソッドを呼び出す。

実際にやってみよう。VIViewController.swiftを以下のコードに変更する。

 

以下は実際のプレイ動画

 

スポンサーリンク

音を停止する

音を停止するにはstopメソッド、または、pauseメソッドを用いる。メソッド名から想像するのは、stopメソッドは再生位置が最初まで巻き戻り、pauseメソッドは再生位置は保存されてまた同じ位置から再生できる。といった仕様を想像する。

しかし、そのような動きにはならず、stopメソッドとpauseメソッドの両方とも、再生位置が保存されてまた同じ位置から再生される。

実際にやってみよう。ViewController.swiftを以下のコードに変更する。青ボタンでplayメソッド、赤ボタンでstopメソッドを呼び出している。

 

以下は実際のプレイ動画。stopメソッドで音を停止したあと、再びplayメソッドを呼び出すと前回停止位置から再生が始まった。pauseメソッドも同じ動きになる。

 

最初まで巻き戻したいときは、以下のコードのようにstopメソッドのあとにAVAudioPlayerインスタンスのcurrentTimeプロパティの値を0に変更する。

 

以下は実際のプレイ動画。音が最初から再生されるようになった。

 

pauseメソッドを読んだあとも同様にcurrentTimeプロパティの値を0にすることで再生位置が最初に戻る。

となると、stopメソッドもpauseメソッドもどちらを使っても変わらないことになるが、stopメソッドの場合はバッファに読みこんだ音データがクリアされ、pauseメソッドの場合はバッファに残り続けるという違いがある。

なのでstopメソッドを使う場合は、次の再生で遅延が発生させたくないならstopメソッドの直後でprepareToPlayメソッドを呼んでバッファにデータをロードしておく必要がある。

処理負荷のことを考えると、何度も再生される音の場合はpauseメソッドを使い、一度再生して終わりの場合はstopメソッドを使うのでどうだろう。

といいつつも、今回のようなサイズの小さい音データでは双方の性能的な違いは認識できなかった。

 

音が再生中かを確認する

音が再生中かを確認するにはplayingプロパティを確認する。再生中の場合はtrue、再生中ではない場合はfalseになる。

例えば、ボタンを押したときにplayingプロパティがtrue(再生中)だったら音を停止し、falseだったら音を再生する場合は以下のコードのようになる。

 

以下は実際のプレイ動画

 

 

再生速度を指定する

再生速度を変更するにはrateプロパティの値を変更する。設定できる範囲は0.5〜2.0(半分のスピード〜2倍速)

rateプロパティの場合だけ、なぜかenableRateプロパティの値をtrueにして調整を許可しなければならない。

 

以下は実際のプレイ動画。再生スピードが速くなった。

 

 

再生回数を指定する

再生回数を指定したい場合はnumberOfLoopsプロパティを変更する。

注意点は「2回再生する場合は1」、「3回再生する場合は2」のように実際の再生回数より1少ない数を設定することである。デフォルトは0(1回再生)。無限ループする場合は-1に設定する。

 

以下は実際のプレイ動画

 

 

音量を指定する

音量を指定するにはvolumeプロパティの値を変更する。0.0は無音、1.0(デフォルト)はAudioPlayerインスタンスの最大音量とリファレンスに記載されているが、試しに1.0よりも数字を大きくしてみたところ、1.0のときよりも大きな音になった。

 

左右のバランスを指定する

音の左右のバランスを指定するにはpanプロパティの値を変更する。-1.0は左のスピーカーのみから音が流れ、0.0(デフォルト)は左右のスピーカーの音が同じ、1.0は右のスピーカーのみから音が流れるようになる。

 

遅延再生する

playメソッドを呼び出してから指定時間経過後に音を再生する場合はplayAtTimeメソッドを利用する。しかし、検証ではこのメソッドを使っても再生が遅延する様子は認識できなかった。何かわかったら追記する(Swift 2.1、XCode 7.2)。

引数にはAVAudioPlayerインスタンスの時間(currentTime)+遅延時間を設定する。

 

再生終了を検知する

音の再生が終了したのを検知させる場合はAVAudioPlayerDelegateを利用する。

以下のコードは、音1の再生が終わったら音2を再生する例。

 

以下は実際のプレイ動画

 

Swift記事一覧へ
  • Twitterでシェア
  • Facebook
  • LINEで送る
はじはじビットコイン目指せ!最強の暗号通貨トレーダー

コメント

  1. サーフ より:

    以下のコード、何か間違っているのでしょうか。

    import UIKit
    import AVFoundation

    class ViewController: UIViewController {

    var player:AVAudioPlayer!
    var player2:AVAudioPlayer!

    //’NSBundle’ has been renamed to ‘Bundle’というエラーが以下で出ます。
    let url = NSBundle.mainBundle().bundleURL.URLByAppendingPathComponent(“sample_sound.mp3”)
    let url2 = NSBundle.mainBundle().bundleURL.URLByAppendingPathComponent(“sample_sound2.mp3”)

    override func viewDidLoad() {
    super.viewDidLoad()

    do {
    try player = AVAudioPlayer(contentsOfURL:url)
    try player2 = AVAudioPlayer(contentsOfURL:url2)

    player.prepareToPlay()
    player2.prepareToPlay()
    } catch {
    print(error)
    }
    }

    @IBAction func pushButton1(_ sender: UIButton) {
    if(player.isPlaying) {
    player.stop()
    player.currentTime = 0
    } else {
    player.play()
    }
    }

    @IBAction func pushButton2(_ sender: UIButton) {
    if(player2.isPlaying) {
    player2.stop()
    player2.currentTime = 0
    } else {
    player2.play()
    }

    //Expected declarationというエラーがでます。
    };

    原因が分かれば教えてください。

    • 管理人 より:

      クラスが閉じられてないのがエラーの原因です。
      一番最後の行の「};」を「}}」に変更して実行してみてください。

      • ご参考までに より:

        swift3 で NS〜 の名前が変更になっているようです。
        あと、bundleURL の URLByAppendingPathComponent() も
        appendingPathComponent() に変更になっていたり、
        player.playing も player.isPlaying になっていたりと色々変わっているようです。

        私の場合 XCode8.3 で試したのですが、
        元のプロジェクトを落としてきて、XCodeで開く前に
        上記サンプルを記述して XCodeで開くと自動的に変換してくれるので
        この方法で変換させてビルドさせると動作させることができました。

        • 管理人 より:

          情報ありがとうございます。
          こちらのページはSwift2.xで試している記事なのでSwift3とは確かに結構ソースは違いますね。
          XCodeの自動変換があるので、変換かけて動かせるのが嬉しいですね。

コメントを残す

お名前