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("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()
|
|
}
|
|
}
|