티스토리 뷰

Xcode(버전11.3)를 AVAudioPlayer 음악(오디오) 재생 및 녹음 앱v2을 만든다:)

아래 링크는 이전에 만든 음악 재생 및 녹음 앱이다.

 

[iOS/swift] AVAudioPlayer 음악(오디오) 재생 및 녹음 앱 만들기

Xcode(버전11.3)를 AVAudioPlayer 음악(오디오) 재생 및 녹음 앱을 만든다:) AVAudioPlayer을 이용하여 아래 기능을 구현한다. 1. 오디오 파일을 재생, 일시정지, 정지 2. 볼륨 조절 3. 녹음 - 스토리보드 화면..

moonibot.tistory.com

위 앱에 현재 상태에 따라 이미지를 보여주는 기능을 추가한다.

현재 상태는 아래와 같이 분류 했다.

1) 재생 

2) 일시정지 

3) 정지

4) 녹음중

 

 

 

사용할 이미지를 프로젝트에 추가한다.

 

 

 

- 스토리보드 화면 구성

Volume과 Record 사이에 ImageView 추가한다.

 

 

 

- 아웃렛 변수 추가하기

ImageView -> 'imgStatus'

 

 

 

전체 소스 보기

//
//  ViewController.swift
//  day191223_Audio
//
//  Created by 무니 on 2019/12/23.
//  Copyright © 2019 com.mooni. All rights reserved.
//

import UIKit
import AVFoundation

class ViewController: UIViewController, AVAudioPlayerDelegate, AVAudioRecorderDelegate {
   
    // 현재 상태 상수값
    let STATUS_PLAY = 0
    let STATUS_PASUE = 1
    let STATUS_STOP = 2
    let STATUS_RECORD = 3
    
    var audioPlayer : AVAudioPlayer! // audioPlayer : AVAudioPlayer 인스턴스 변수
    var audioFile : URL! // 재생할 오디오의 파일명 변수
    let MAX_VOLUME : Float = 10.0 // 최대 볼륨, 실수형 상수
    var progressTimer : Timer! // 타이머를 위한 변수
    
    let timePlayerSelector:Selector = #selector(ViewController.updatePlayTime)
    let timeRecordSelector:Selector = #selector(ViewController.updateRecordTime)

    @IBOutlet var pvProgressPlay: UIProgressView!
    @IBOutlet var lblCurrentTime: UILabel!
    @IBOutlet var lblEndTime: UILabel!
    @IBOutlet var btnPlay: UIButton!
    @IBOutlet var btnPause: UIButton!
    @IBOutlet var btnStop: UIButton!
    @IBOutlet var slVolume: UISlider!
    @IBOutlet var btnRecord: UIButton!
    @IBOutlet var lblRecordTime: UILabel!
    @IBOutlet var imgStatus: UIImageView!
    
    var audioRecoder : AVAudioRecorder!
    var isRecordMode = false // '녹음 모드'를 나타내는 변수. 기본값은 false('재생 모드')
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        selectAudioFile()
        if !isRecordMode { // 재생 모드일 때(녹음 모드가 아니라면)
            initplay()
            btnRecord.isEnabled = false
            lblRecordTime.isEnabled = false
        } else { // 녹음 모드일 때
            initRecord()
        }
    }
    
    // 재생 모드와 녹음 모드에 따라 다른 파일을 선택함
    func selectAudioFile(){
        if !isRecordMode { // 재생 모드일 때
             audioFile = Bundle.main.url(forResource: "Touch", withExtension: "mp3")
        } else { // 녹음 모드일 때
            let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            audioFile = documentDirectory.appendingPathComponent("recordFile.m4a")
        }
    }
    
    // 녹음 모드의 초기화
    func initRecord(){
        let recordSettings = [AVFormatIDKey : NSNumber(value: kAudioFormatAppleLossless as UInt32),
                              AVEncoderAudioQualityKey : AVAudioQuality.max.rawValue,
                              AVEncoderBitRateKey : 320000,
                              AVNumberOfChannelsKey : 2,
                              AVSampleRateKey : 44100.0 ] as [String : Any]
        do {
            audioRecoder = try AVAudioRecorder(url: audioFile, settings: recordSettings)
        } catch let error as NSError {
            print("Error-initRecord : \(error)")
        }
        audioRecoder.delegate = self
        audioRecoder.isMeteringEnabled =  true
        audioRecoder.prepareToRecord()
        
        slVolume.value = 1.0
        audioPlayer.volume = slVolume.value
        lblEndTime.text = convertNSTimeInterval12String(0)
        lblCurrentTime.text = convertNSTimeInterval12String(0)
        setPlayButtons(false, pause: false, stop: false)
        
        let session = AVAudioSession.sharedInstance()
        do {
            try session.setCategory(AVAudioSession.Category.playAndRecord)
        } catch let error as NSError {
            print(" Error-setCategory : \(error)")
        }
        do {
            try session.setActive(true)
        } catch let error as NSError {
            print(" Error-setActive : \(error)")
        }
    }
    
    // 재생 모드의 초기화
    func initplay(){
        do {
            audioPlayer = try AVAudioPlayer(contentsOf: audioFile)
        } catch let error as NSError {
            print("Error-initPlay : \(error)")
        }
        slVolume.maximumValue = MAX_VOLUME // 슬라이더(slVolume) 최대 볼륨 10.0으로 초기화
        slVolume.value = 1.0 // 슬라이더(slVolume) 볼륨 1.0으로 초기화
        pvProgressPlay.progress = 0 // 프로그레스 뷰(pvProgressPlay)의 진행 0으로 초기화
        
        audioPlayer.delegate = self // audioPlayer의 델리게이트는 self
        audioPlayer.prepareToPlay() // prepareToPlay() 실행
        audioPlayer.volume = slVolume.value // audioaplayer 볼륨을 슬라이더(slVolume) 값 1.0으로 초기화
        lblEndTime.text = convertNSTimeInterval12String(audioPlayer.duration)
        lblCurrentTime.text = convertNSTimeInterval12String(0)
        setPlayButtons(true, pause: false, stop: false)
    }
    
    // '재생', '일시 정지', '정지' 버튼을 활성화 또는 비활성화하는 함수
    func setPlayButtons(_ play: Bool, pause: Bool, stop: Bool){
        btnPlay.isEnabled = play
        btnPause.isEnabled = pause
        btnStop.isEnabled = stop
    }
    
    // 00:00 형태의 문자열로 변환함
    func convertNSTimeInterval12String(_ time:TimeInterval) -> String {
        let min = Int(time/60)
        let sec = Int(time.truncatingRemainder(dividingBy: 60))
        let strTime = String(format: "%02d:%02d", min, sec)
        return strTime
    }

    // '재생' 버튼을 클릭하였을 때
    @IBAction func btnPlayAudio(_ sender: UIButton) {
        audioPlayer.play()
        setPlayButtons(false, pause: true, stop: true)
        progressTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: timePlayerSelector, userInfo: nil, repeats: true)
        changeStatus(status: STATUS_PLAY)
    }
    
    // 0.1초마다 호출되며 재생 시간을 표시함
    @objc func updatePlayTime(){
        lblCurrentTime.text = convertNSTimeInterval12String(audioPlayer.currentTime) // 재생 시간인 audioPlayer.currentTime을 lblCurrentTime에 나타냄
        pvProgressPlay.progress = Float(audioPlayer.currentTime/audioPlayer.duration) // 프로그레스(Progress View)인 pvProgressPlay의 진행 상황에 audioPlayer.currentTime을 audioPlayer.duration으로 나눈 값으로 표시
    }
    
    // '일시 정지' 버튼을 클릭하였을 때
    @IBAction func btnPauseAudio(_ sender: UIButton) {
        audioPlayer.pause()
        setPlayButtons(true, pause: false, stop: true)
        changeStatus(status: STATUS_PASUE)
    }
    
    // '정지' 버튼을 클릭하였을 때
    @IBAction func btnStopAudio(_ sender: UIButton) {
        audioPlayer.stop()
        audioPlayer.currentTime = 0
        lblCurrentTime.text = convertNSTimeInterval12String(0)
        setPlayButtons(true, pause: false, stop: false)
        progressTimer.invalidate() // 타이머 무효화
        changeStatus(status: STATUS_STOP)
    }
    
    // 볼륨 슬라이더 값을 audioplayer.volume에 대임함
    @IBAction func slChangeVolume(_ sender: UISlider) {
        audioPlayer.volume = slVolume.value
    }
    
    // 재생이 종료되었을 때 호출함
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        progressTimer.invalidate() // 타이머 무효화
        setPlayButtons(true, pause: false, stop: false)
    }
    
    // 스위치를 ON/Off하여 녹음모드 인지 재생 모드인지를 결정함
    @IBAction func swRecordMode(_ sender: UISwitch) {
        if sender.isOn { // 녹음 모드일 때
            audioPlayer.stop()
            audioPlayer.currentTime = 0
            lblRecordTime!.text = convertNSTimeInterval12String(0)
            isRecordMode = true
            btnRecord.isEnabled = true
            lblRecordTime.isEnabled = true
        } else { // 재생 모드일 때
            isRecordMode = false
            btnRecord.isEnabled = false
            lblRecordTime.isEnabled = false
            lblRecordTime.text = convertNSTimeInterval12String(0)
        }
        selectAudioFile() // 모드에 따라 오디오 파일을 선택함
        
        // 모드에 따라 재생 초기화 또는 녹음 초기화를 수행함
        if !isRecordMode { // 녹음 모드가 아닐 때, 즉 재생 모드일 때
            initplay()
        } else { // 녹음 모드일 때
            initRecord()
        }
    }
    
    @IBAction func btnRecord(_ sender: UIButton) {
        if sender.titleLabel?.text == "Record" { // 버튼이 'Record'일 때 녹음을 중지함
            audioRecoder.record()
            sender.setTitle("Stop", for: UIControl.State())
            progressTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: timeRecordSelector, userInfo: nil, repeats: true)
            
            changeStatus(status: STATUS_RECORD)
        } else { // 버튼이 'Stop'일 때 녹음을 위한 초기화를 수행함
            audioRecoder.stop()
            progressTimer.invalidate() // 녹음이 중지되면 무효화
            sender.setTitle("Record", for: UIControl.State())
            btnPlay.isEnabled = true
            initplay()
            
            changeStatus(status: STATUS_STOP)
        }
    }
    
    // 0.1초마다 호출되며 녹음 시간을 표시함
    @objc func updateRecordTime(){
        lblRecordTime.text = convertNSTimeInterval12String(audioRecoder.currentTime)
    }
    
    // 재생, 일시정지, 정지, 녹음 상태에 따라 이미지를 표시함
    func changeStatus(status: Int) {
        switch status {
            case STATUS_PLAY: // 재생 상태일 때
                imgStatus.image = UIImage(named: "play.png")
            case STATUS_PASUE: // 일시정지 상태일 때
                imgStatus.image = UIImage(named: "pause.png")
            case STATUS_STOP: // 정지 상태일 때
                imgStatus.image = UIImage(named: "stop.png")
            case STATUS_RECORD: // 녹음 상태일 때
                imgStatus.image = UIImage(named: "record.png")
        default:
            print("Error")
        }
    }
    
}

 

 

 

시뮬레이터 결과 화면

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함