170 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
//
 | 
						|
//  SoundManager.swift
 | 
						|
//  SodaLive
 | 
						|
//
 | 
						|
//  Created by klaus on 2023/08/10.
 | 
						|
//
 | 
						|
 | 
						|
import Foundation
 | 
						|
import AVKit
 | 
						|
 | 
						|
class SoundManager: NSObject, ObservableObject {
 | 
						|
    @Published var errorMessage = ""
 | 
						|
    @Published var isShowPopup = false
 | 
						|
    @Published var isLoading = false
 | 
						|
    @Published var onClose = false
 | 
						|
    
 | 
						|
    @Published var isPlaying = false
 | 
						|
    @Published var isRecording = false
 | 
						|
    @Published var duration: TimeInterval = 0
 | 
						|
    
 | 
						|
    var player: AVAudioPlayer!
 | 
						|
    var audioRecorder: AVAudioRecorder!
 | 
						|
    
 | 
						|
    var startTimer: (() -> Void)?
 | 
						|
    var stopTimer: (() -> Void)?
 | 
						|
    
 | 
						|
    let audioSession = AVAudioSession.sharedInstance()
 | 
						|
    
 | 
						|
    func prepareRecording() {
 | 
						|
        isLoading = true
 | 
						|
        
 | 
						|
        do {
 | 
						|
            try audioSession.setCategory(.playAndRecord, mode: .default)
 | 
						|
            try audioSession.setActive(true)
 | 
						|
            
 | 
						|
            audioSession.requestRecordPermission() { [weak self] allowed in
 | 
						|
                DispatchQueue.main.async {
 | 
						|
                    if !allowed {
 | 
						|
                        self?.errorMessage = "권한을 허용하지 않으시면 음성메시지 서비스를 이용하실 수 없습니다."
 | 
						|
                        self?.isShowPopup = true
 | 
						|
                        self?.onClose = true
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        } catch {
 | 
						|
            errorMessage = "오류가 발생했습니다. 다시 시도해 주세요."
 | 
						|
            isShowPopup = true
 | 
						|
            onClose = true
 | 
						|
        }
 | 
						|
        
 | 
						|
        isLoading = false
 | 
						|
    }
 | 
						|
    
 | 
						|
    func startRecording() {
 | 
						|
        let settings = [
 | 
						|
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
 | 
						|
            AVSampleRateKey: 12000,
 | 
						|
            AVNumberOfChannelsKey: 1,
 | 
						|
            AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
 | 
						|
        ]
 | 
						|
        
 | 
						|
        do {
 | 
						|
            try audioSession.setCategory(.playAndRecord, mode: .default)
 | 
						|
            try audioSession.setActive(true)
 | 
						|
            
 | 
						|
            audioRecorder = try AVAudioRecorder(url: getAudioFileURL(), settings: settings)
 | 
						|
            audioRecorder.record()
 | 
						|
            
 | 
						|
            if let startTimer = startTimer {
 | 
						|
                startTimer()
 | 
						|
            }
 | 
						|
            isRecording = true
 | 
						|
        } catch {
 | 
						|
            errorMessage = "오류가 발생했습니다. 다시 시도해 주세요."
 | 
						|
            isShowPopup = true
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    func stopRecording() {
 | 
						|
        audioRecorder.stop()
 | 
						|
        audioRecorder = nil
 | 
						|
        isRecording = false
 | 
						|
        
 | 
						|
        if let stopTimer = stopTimer {
 | 
						|
            stopTimer()
 | 
						|
        }
 | 
						|
        
 | 
						|
        prepareForPlay()
 | 
						|
    }
 | 
						|
    
 | 
						|
    func getRecorderCurrentTime() -> TimeInterval {
 | 
						|
        return audioRecorder.currentTime
 | 
						|
    }
 | 
						|
    
 | 
						|
    func prepareForPlay(_ url: URL? = nil) {
 | 
						|
        isLoading = true
 | 
						|
        
 | 
						|
        DispatchQueue.main.async {
 | 
						|
            do {
 | 
						|
                try self.audioSession.setCategory(.playAndRecord, mode: .default)
 | 
						|
                try self.audioSession.setActive(true)
 | 
						|
                
 | 
						|
                if let url = url {
 | 
						|
                    self.player = try AVAudioPlayer(data: Data(contentsOf: url))
 | 
						|
                } else {
 | 
						|
                    self.player = try AVAudioPlayer(contentsOf: self.getAudioFileURL())
 | 
						|
                }
 | 
						|
                
 | 
						|
                self.player?.volume = 1
 | 
						|
                self.player?.delegate = self
 | 
						|
                self.player?.prepareToPlay()
 | 
						|
                
 | 
						|
                self.duration = self.player.duration
 | 
						|
            } catch {
 | 
						|
                self.errorMessage = "오류가 발생했습니다. 다시 시도해 주세요."
 | 
						|
                self.isShowPopup = true
 | 
						|
            }
 | 
						|
            
 | 
						|
            self.isLoading = false
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    func playAudio() {
 | 
						|
        player?.play()
 | 
						|
        
 | 
						|
        isPlaying = player.isPlaying
 | 
						|
        if let startTimer = startTimer {
 | 
						|
            startTimer()
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    func stopAudio() {
 | 
						|
        player.stop()
 | 
						|
        player.currentTime = 0
 | 
						|
        isPlaying = player.isPlaying
 | 
						|
        if let stopTimer = stopTimer {
 | 
						|
            stopTimer()
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    func getPlayerCurrentTime() -> TimeInterval {
 | 
						|
        return player.currentTime
 | 
						|
    }
 | 
						|
    
 | 
						|
    func deleteAudioFile() {
 | 
						|
        do {
 | 
						|
            try FileManager.default.removeItem(at: getAudioFileURL())
 | 
						|
            duration = 0
 | 
						|
        } catch {
 | 
						|
            errorMessage = "오류가 발생했습니다. 다시 시도해 주세요."
 | 
						|
            isShowPopup = true
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    func getAudioFileURL() -> URL {
 | 
						|
        return getDocumentsDirectory().appendingPathComponent("voiceon_now_voice_recording.m4a")
 | 
						|
    }
 | 
						|
    
 | 
						|
    private func getDocumentsDirectory() -> URL {
 | 
						|
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
 | 
						|
        return paths[0]
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
extension SoundManager: AVAudioPlayerDelegate {
 | 
						|
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
 | 
						|
        stopAudio()
 | 
						|
    }
 | 
						|
}
 |