Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Sound Control

Song edited this page Aug 5, 2021 · 3 revisions

2021-08-02

by Song

Step 1 - Audio Session 활성화

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

Step 2 - Sound Station 객체 생성

각 씬에 필요한 Audio Player를 컨트롤 하는 객체 생성

Background Music

  • 여러 씬에 걸쳐 플레이되어야 한다는 특성에 따라 싱글톤 객체로 생성
  • 씬 교체 상황에 따라 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()
    }
}

Sound Effect

  • BGM과 달리 각 씬에 해당하는 효과음이 정해져 있다.
  1. 메뉴 화면
    • 광고 화면, 아이템 화면에서 각각 효과음 1개씩 필요
    • 하나의 효과음을 컨트롤하는 SingleSoundEffectStation 객체를 각 씬에서 공통적으로 사용
  2. 게임 화면
    • 게임에는 여러 효과음이 동시다발적으로 사용 됨
    • GameSoundEffectStation 객체로 필요한 모든 효과음 컨트롤

Audio Player Factory

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

Clone this wiki locally

Morty Proxy This is a proxified and sanitized view of the page, visit original site.