sodalive-ios/SodaLive/Sources/Message/Voice/SoundManager.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("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()
}
}