Files
SodaLive
Preview Content
Resources
Sources
Agora
App
Common
Content
Debug
Dialog
Explorer
Extensions
Follow
Font
IAP
ImagePicker
Keyboard
Live
Main
Message
SelectRecipient
Text
Voice
Write
GetVoiceMessageResponse.swift
SoundManager.swift
VoiceMessageItemView.swift
VoiceMessageView.swift
VoiceMessageViewModel.swift
KeepMessageRequest.swift
MessageApi.swift
MessageFilterTab.swift
MessageFilterTabView.swift
MessageRepository.swift
MessageView.swift
MessageViewModel.swift
SendMessageRequest.swift
MyPage
NavigationBar
Onboarding
Report
Settings
Shape
Splash
User
Utils
ContentView.swift
SodaLive.entitlements
SodaLive.xcworkspace
generated
.gitignore
Podfile
Podfile.lock
SodaLive-dev.entitlements
model-SodaLive-dev.json
model-SodaLive.json
sodalive-ios/SodaLive/Sources/Message/Voice/SoundManager.swift

165 lines
4.7 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)?
func prepareRecording() {
isLoading = true
let audioSession = AVAudioSession.sharedInstance()
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 {
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 {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(.playback, mode: .default)
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()
}
}