-
Notifications
You must be signed in to change notification settings - Fork 0
Sound Control
Song edited this page Aug 5, 2021
·
3 revisions
by Song
App Delegate 메소드를 통한 Audio Session 활성화
-
didFinishLaunchingWithOptions메소드를 통해 AudioSession 설정 - 배경음과 효과음을 한번에 플레이할 수 있도록 하기 위해 Category는 ambient로 설정
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
setAudioSession()
// 기타 코드 생략
}
private func setAudioSession() {
try? AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.ambient)
try? AVAudioSession.sharedInstance().setActive(true)
}각 씬에 필요한 Audio Player를 컨트롤 하는 객체 생성
- 여러 씬에 걸쳐 플레이되어야 한다는 특성에 따라 싱글톤 객체로 생성
- 씬 교체 상황에 따라 MusicPlayer 생성 시 메모리 부하가 생겨 게임 ready 화면 로드에서 버벅임 발생 -> 미리 생성하도록 함
struct MusicStation {
static let shared = MusicStation()
private var mainMusicPlayer = AudioPlayerFactory.create(of: Music.main, mode: .music)
private var gameMusicPlayer = AudioPlayerFactory.create(of: Music.game, mode: .music)
func play(type: Music) {
switch type {
case .main:
mainMusicPlayer?.currentTime = 0 // 음악을 맨 처음으로 되돌린다
mainMusicPlayer?.play()
gameMusicPlayer?.stop()
case .game:
gameMusicPlayer?.currentTime = 0
gameMusicPlayer?.play()
mainMusicPlayer?.stop()
}
}
func stop() {
mainMusicPlayer?.stop()
gameMusicPlayer?.stop()
}
}- BGM과 달리 각 씬에 해당하는 효과음이 정해져 있다.
- 메뉴 화면
- 광고 화면, 아이템 화면에서 각각 효과음 1개씩 필요
- 하나의 효과음을 컨트롤하는
SingleSoundEffectStation객체를 각 씬에서 공통적으로 사용
- 게임 화면
- 게임에는 여러 효과음이 동시다발적으로 사용 됨
-
GameSoundEffectStation객체로 필요한 모든 효과음 컨트롤
- Factory 메소드를 통해 AudioPlayer 생성 시의 중복 코드 개선
struct AudioPlayerFactory {
enum Mode {
case music
case effect
}
static func create(of soundType: BundlePathIncludable, mode: Mode) -> AVAudioPlayer? {
guard let bundlePath = soundType.bundlePath else { return nil }
let url = URL(fileURLWithPath: bundlePath)
let audioPlayer = try? AVAudioPlayer(contentsOf: url)
audioPlayer?.numberOfLoops = mode == .music ? .max : 0
return audioPlayer
}
}- 각 Sound Enum 타입에
BundlePathIncludable프로토콜을 적용하여 팩토리 메소드 사용
protocol BundlePathIncludable {
var bundlePath: String? { get }
}
enum MainSoundEffect: BundlePathIncludable {
case reward
case upgrade
var bundlePath: String? {
switch self {
case .reward:
return Bundle.main.path(forResource: "reward", ofType: "wav")
case .upgrade:
return Bundle.main.path(forResource: "upgrade", ofType: "wav")
}
}
}created by 우송