見出し画像

【徒然iOS】気ままにUIKit106〜音楽プレーヤーを作ろう〜

概要

このマガジンは四十を過ぎたおっさんが、

を参考にStoryboardでiOSアプリを完全に趣味で楽しんでいるだけな記事を気ままに上げてます。

今回

をベースに、音楽プレーヤーを作る〜〜〜〜🕺

と、この気ままにUIKitシリーズもついに残り、3回だね👀

実は、

で既に、ビュー構築編の機能は全部、記事にし終わってるんだけどね💦

全体を見せると、前回までで

こんな感じかな💦

SwiftUIと比べたUIKitでの開発メリットなんだけど、

SwiftUIだと、

Storyboard

って概念がないから、コードを打つだけで、ビューを簡単にStruct分で追加、改修、削除が出来るのが、設計に慣れてる人だとやりやすいんだけど、

UIKitだと、こんな感じで、全体の画面とか画面遷移をStoryboardで一目で把握しやすいから、画面遷移図みたいなモノを作らなくていいって利点もあるんだよね〜〜〜

InVIsion

なんかで、モックアップを作る人には常識だし、イメージしやすいと思うけどね〜〜〜〜

*このプロジェクトだと、ビューが多すぎて、整理するとセグエが消えちゃうので、遷移図としては🤔って感じだけど 藁🤣
もちろん普通のアプリだと、こんなに画面が増えることはないから〜〜〜

前準備

念の為、

  1. バックアップ

  2. 新規クラスを追加

  3. 新規ビューを追加

をいつもどおりやってから本題へ💃

まずは、てな感じで入り口にボタンを一個増やして
メニュービューを追加したところ〜〜〜
新しいビューを追加〜〜〜
こんな感じでクラスも適用🕺

本題

AVAudioPlayerとは、

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

で、実は既に軽くやってるんだけど、この時は、スイッチボタンの説明をメインでちょろっと触れただけだったから〜〜〜〜

⒈事前準備

まずは、再生する音楽が必要なので、このプロジェクト内では、上の記事でやってるんだけど、

Assetに音源をセットする

こんな感じで既にセット済み〜〜〜

⒉新規ビューにイメージと再生用のボタンを配置

てな感じでイメージを配置して、設定〜〜〜
pin制約を全部0にして、こんな感じに〜〜〜
横並びのボタンを配置したいので、コイツを選んで〜〜〜
てな感じで配置しとく〜〜〜
次いでに一旦、背景を黒に〜〜〜
適当にAutoLayoutも設定して〜〜〜
こんな感じに〜〜〜
選んで〜〜〜
配置して〜〜〜
こんな感じで〜〜〜

⒊ボタンをアクション接続

てな感じで〜〜〜
ハイ、接続完了🕺

⒋コード組み込み

①音声ファイルのURLを引数にAVAudioインスタンスを作成

②作成したインスタンスに対してplayメソッドを呼ぶ

てことなんで、

//
//  ViewController.swift
//
import UIKit
import AVFoundation
class ViewController: UIViewController {
    var player:AVAudioPlayer!
    let url = NSBundle.mainBundle().bundleURL.URLByAppendingPathComponent("sample_sound.mp3")
    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        do {
            try player = AVAudioPlayer(contentsOfURL:url)
            //音楽をバッファに読み込んでおく
            player.prepareToPlay()
        } catch {
            print(error)
        }
    }
    //再生ボタン1押下時の呼び出しメソッド
    @IBAction func pushButton1(sender: UIButton) {
         //音楽を再生する。
         player.play()
    }
    //再生ボタン2押下時の呼び出しメソッド
    @IBAction func pushButton2(sender: UIButton) {
    }
}

を参考に〜〜〜

AVFoundationは既にインポート済みなんで〜〜〜
とまあ、普通に組み込んでも、既にコードの書き振りが変わってるので
エラーになる👀

なので、

class MusicPlayerViewController: UIViewController, AVAudioPlayerDelegate {
    var audioPlayer1:AVAudioPlayer?
    //プレイヤー1再生
    func playBtn1() {
        if let sound1 = NSDataAsset(name: "natsuyasuminotanken") {
            audioPlayer1 = try? AVAudioPlayer(data: sound1.data)
            audioPlayer1?.play()
        }
    }
    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    @IBAction func myPlayButton(_ sender: UIButton) {
        //音楽を再生する。
        playBtn1()
    }
}

てな感じに書き換えると〜〜〜

キャプチャではわからないけど、
音楽が流れる〜〜〜

ただし、このままだと、、、、
戻らない限り、曲が終わるまで音楽が流れ続けるので〜〜〜

⒌停止ボタンを追加

てな感じで追加して
    //プレイヤー1停止
    func stopBtn1() {
        audioPlayer1?.stop()
        //最初まで巻き戻し
        audioPlayer1?.currentTime = 0
    }

を追加して〜〜〜

停止ボタンをアクション接続〜〜〜

で、停止も出来るし、再生し直しもできる〜〜〜🕺
次いでに、一時停止ボタンも欲しいので〜〜〜〜

⒍一時停止ボタンを追加(このままだと何の意味があるのか、、、)

ボタンを追加して〜〜〜
アクション接続〜〜〜〜
    //プレイヤー1一時停止
    func pauseBtn1() {
        audioPlayer1?.pause()
    }

を追加して

てな感じで〜〜〜

で、一時停止して見たんだけど、、、最初から再生になる👀
サイト記事を見ても、

stopメソッドの場合はバッファに読みこんだ音データがクリアされ、pauseメソッドの場合はバッファに残り続けるという違いがある。

だけで、どうやら

を参照すると、

セグメントで条件分岐しないとできない様子💦

一応、ここまでで、あんまり違いはない気もするんだけど、、、

    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        //音楽をバッファに読み込んでおく
        audioPlayer1?.prepareToPlay()
    }

に変更して

prepareToPlayメソッドを呼んでバッファにデータをロードしとく〜〜〜

⒎2倍速ボタンを追加

設定できる範囲は0.5〜2.0

らしい。

てな感じでボタンを追加して〜〜〜
アクション接続〜〜〜!
    //プレイヤー1倍速再生
    func x2PlayBtn1() {
        if let sound1 = NSDataAsset(name: "natsuyasuminotanken") {
            audioPlayer1 = try? AVAudioPlayer(data: sound1.data)
            //rateの変更を許可する。
            audioPlayer1?.enableRate = true
            //2倍速にする。
            audioPlayer1?.rate = 2.0
            audioPlayer1?.play()
        }
    }

を追加して〜〜〜

てな感じで。早くなりました👀

ここはステッパーなんかを使うと、さらに面白くできそうだね🕺

⒏無限ループボタンを追加

ループボタンを追加して、アクション接続〜〜〜
    //プレイヤー1無限再生
    func loopPlayBtn1() {
        if let sound1 = NSDataAsset(name: "natsuyasuminotanken") {
            audioPlayer1 = try? AVAudioPlayer(data: sound1.data)
            //無限ループ
            audioPlayer1?.numberOfLoops = -1
            audioPlayer1?.play()
        }
    }

をコードに追加〜〜〜

無限ループもできた〜〜〜〜🕺

後は、付属機能みたいなもんなので〜〜〜上にうっすら〜〜〜

⒐音量を指定ボタンを追加

てな感じでボタンを配置して、
アクション接続して〜〜
半減できた〜〜〜

10.左右のバランスを指定ボタンを追加

  • -1.0:左のスピーカーのみ

  • 0.0:左右のスピーカーの音が同じ

  • 1.0:右のスピーカーのみ

てな感じで上の左右に耳マークを追加して、アクション接続
    //プレイヤー1左のみで再生
    func leftEarPlayBtn1() {
        if let sound1 = NSDataAsset(name: "natsuyasuminotanken") {
            audioPlayer1 = try? AVAudioPlayer(data: sound1.data)
            //左のみ
            audioPlayer1?.pan = -1.0
            audioPlayer1?.play()
        }
    }
    //プレイヤー1右のみで再生
    func rightEarEarPlayBtn1() {
        if let sound1 = NSDataAsset(name: "natsuyasuminotanken") {
            audioPlayer1 = try? AVAudioPlayer(data: sound1.data)
            //右のみ
            audioPlayer1?.pan = 1.0
            audioPlayer1?.play()
        }
    }

を追加して〜〜〜

できた〜〜〜

11.(参考までに)2曲同時再生ボタンを追加

まずはコイツを追記して〜〜〜
コイツも追記〜〜〜
コイツも追加〜〜〜
同時再生用のボタンを追加して、アクション接続〜〜〜🕺
コイツも追記しておいて〜〜〜
てな感じで両方、同時に止められるようにしとく〜〜〜
同時になり始めて〜〜停止ボタンを押したら止まった〜〜〜

今回のコード(まとめ)

class MusicPlayerViewController: UIViewController, AVAudioPlayerDelegate {
    var audioPlayer1:AVAudioPlayer?
    //2曲目
    var audioPlayer2:AVAudioPlayer?
    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        //音楽をバッファに読み込んでおく
        audioPlayer1?.prepareToPlay()
        audioPlayer2?.prepareToPlay()
    }
    //プレイヤー1再生
    func playBtn1() {
        if let sound1 = NSDataAsset(name: "natsuyasuminotanken") {
            audioPlayer1 = try? AVAudioPlayer(data: sound1.data)
            audioPlayer1?.play()
        }
    }
    //プレイヤー2再生
    func playBtn2() {
        if let sound2 = NSDataAsset(name: "yume") {
            audioPlayer2 = try? AVAudioPlayer(data: sound2.data)
            audioPlayer2?.play()
        }
    }
    //プレイヤー1停止
    func stopBtn1() {
        audioPlayer1?.stop()
        //最初まで巻き戻し
        audioPlayer1?.currentTime = 0
    }
    //プレイヤー2停止
    func stopBtn2() {
        audioPlayer2?.stop()
        //最初まで巻き戻し
        audioPlayer2?.currentTime = 0
    }
    //プレイヤー1一時停止
    func pauseBtn1() {
        audioPlayer1?.pause()
    }
    //プレイヤー1倍速再生
    func x2PlayBtn1() {
        if let sound1 = NSDataAsset(name: "natsuyasuminotanken") {
            audioPlayer1 = try? AVAudioPlayer(data: sound1.data)
            //rateの変更を許可する。
            audioPlayer1?.enableRate = true
            //2倍速にする。
            audioPlayer1?.rate = 2.0
            audioPlayer1?.play()
        }
    }
    //プレイヤー1無限再生
    func loopPlayBtn1() {
        if let sound1 = NSDataAsset(name: "natsuyasuminotanken") {
            audioPlayer1 = try? AVAudioPlayer(data: sound1.data)
            //無限ループ
            audioPlayer1?.numberOfLoops = -1
            audioPlayer1?.play()
        }
    }
    //プレイヤー1音半分で再生
    func soundHalfPlayBtn1() {
        if let sound1 = NSDataAsset(name: "natsuyasuminotanken") {
            audioPlayer1 = try? AVAudioPlayer(data: sound1.data)
            //音半分
            audioPlayer1?.volume = 0.5
            audioPlayer1?.play()
        }
    }
    //プレイヤー1左のみで再生
    func leftEarPlayBtn1() {
        if let sound1 = NSDataAsset(name: "natsuyasuminotanken") {
            audioPlayer1 = try? AVAudioPlayer(data: sound1.data)
            //左のみ
            audioPlayer1?.pan = -1.0
            audioPlayer1?.play()
        }
    }
    //プレイヤー1右のみで再生
    func rightEarEarPlayBtn1() {
        if let sound1 = NSDataAsset(name: "natsuyasuminotanken") {
            audioPlayer1 = try? AVAudioPlayer(data: sound1.data)
            //右のみ
            audioPlayer1?.pan = 1.0
            audioPlayer1?.play()
        }
    }
    @IBAction func myPlayButton(_ sender: UIButton) {
        //音楽を再生する。
        playBtn1()
    }
    @IBAction func myStopButton(_ sender: UIButton) {
        //音楽を停止する。
        stopBtn1()
        stopBtn2()
    }
    @IBAction func myPauseButton(_ sender: UIButton) {
        pauseBtn1()
    }
    @IBAction func myX2Button(_ sender: UIButton) {
        x2PlayBtn1()
    }
    @IBAction func myLoopButton(_ sender: UIButton) {
        loopPlayBtn1()
    }
    @IBAction func mySoundHalfButton(_ sender: UIButton) {
        soundHalfPlayBtn1()
    }
    @IBAction func leftEarButton(_ sender: UIButton) {
        leftEarPlayBtn1()
    }
    @IBAction func rightEarButton(_ sender: UIButton) {
        rightEarEarPlayBtn1()
    }
    @IBAction func myTwinPalyButton(_ sender: UIButton) {
        playBtn1()
        playBtn2()
    }
}

ブラッシュアップ

とまあ、後は、いつもどおり🌐ボタンを追加して〜〜〜

記事公開後、

ハイ、ひらけた💃
実機も問題無し🕺

と思ったら、、、実機だとなんかレイアウトが崩れてるので〜〜〜

一回全部のAutoLayoutを外して
VerticalStackViewにはめ込み直して、制約を付け加えて、、
てな感じで問題なしを確認ずみ〜〜〜

Apple公式

さてと次回は、

をレッツゴする🕺

今回、

サイト記事のコードでは既に動かなくなっていた箇所が多かったので、
以前の記事でやってた方法で紹介して、果てしなく長くなって、小見出しだけでも11とかになったので、

音が再生中かと再生検知、遅延再生

については一旦、割愛してる〜〜〜
他の記事を書き上げて、余裕が出来たら作り直すか追記するかも💦
おかわり予定、、、

ま、音を再生する基本機能については、充分網羅はしてるつもりなんで、
そこんトコ、よろしく🕺

この記事が気に入ったらサポートをしてみませんか?