【입문】iOS 앱 개발 #3【Sound 재생하기】
소리
이번에는 게임중의 사운드를 흘리는 처리를 작성하고 싶다. SpriteKit은 간단한 사운드 제어도 제공합니다. '팩맨' 정도라면 이 범위에서 실현될 수 있을 것 같다.
사운드에는 효과음(Sound Effect)과 BGM(BackGround Music)이 있다. 이 2 종류를 실현하는 클래스를 작성한다.
Sound Manager 클래스 만들기
효과음을 재생하는 API는
playSE(.EatDot)
한다.
BGM을 재생하는 API는
playBGM(.BgmPower)
한다.
이러한 API를 가지는, 다음의 CgSoundManager 클래스를 작성한다.
CgSoundManager 클래스
/// Sound management class plays sound with SpriteKit.
class CgSoundManager {
// Kind of sound items to play back.
enum EnKindOfSound: Int {
case EatDot = 0
case EatFruit
// ・・・略・・・
case Intermission
}
// List of sound files to load.
private let table_urls: [[(resourceName: String, typeName: String, interval: Int)]] = [
[ ("16_pacman_eatdot_256ms", "wav", 256) ],
[ ("16_pacman_eatfruit_438ms", "wav", 438) ],
// ・・・略・・・
[ ("16_pacman_intermission_5200ms", "wav", 5200) ]
]
private var view: SKScene?
private var actions: [SKAction] = []
private var table_playingTime: [Int] = []
// Adjustment time for processing to play sound.
private let triggerThresholdTime: Int = 16 //ms
/// Create and initialize a sound manager object.
/// - Parameters:
/// - view: SKScene object that organizes all of the active SpriteKit content.
init(view: SKScene) {
self.view = view
table_playingTime = Array<Int>(repeating: 0, count: table_urls.count)
for t in table_urls {
appendSoundResource(resourceName: t[0].resourceName, typeName: t[0].typeName)
}
// ・・・略・・・
}
/// Append sound resources to SpriteKit.
/// - Parameters:
/// - resourceName: File name for sound resource.
/// - typeName: Type name for sound resource.
private func appendSoundResource(resourceName: String, typeName: String) {
let fileName = resourceName+"."+typeName
let sound: SKAction = SKAction.playSoundFileNamed(fileName, waitForCompletion: false)
actions.append(sound)
}
/// Play back a specified sound.
/// If the specified item is playing back, it will not be played back.
/// - Parameter number: Kind of sound items to play back.
func playSE(_ number: EnKindOfSound) {
guard soundEnabled && number.rawValue < actions.count else { return }
let _number = number.rawValue
if table_playingTime[_number] <= triggerThresholdTime {
let table = table_urls[_number]
table_playingTime[_number] = table[0].interval
view?.run(actions[_number])
}
}
enum 으로 정의된 값과, 재생하는 사운드 파일의 table_urls 테이블을 대응시켜 둔다.
클래스 초기화시에, 이러한 파일을 SKAction의 오브젝트로서 생성해 둔다.
또한 사운드 파일의 재생 시간을 값으로 관리합니다. 이것은 동일한 효과음이 복수 중첩되지 않게 하기 때문에, 어느 효과음이 재생중에 동일한 것을 재생하는 경우에는 재생하지 않게 한다.
또한 BGM을 재생할 때는 지정된 사운드 파일의 재생이 종료되었음을 알고 동일한 것을 반복 재생하기 위해 사용한다. 자동으로 시작하기 위한 트리거는, update 메소드내에서 실시한다.
사운드 파일
이번 팩맨에 사용하는 사운드 파일은 15개로, 포맷은 WAV 형식, 16bit, 모노럴, 샘플링 레이트 22050Hz로 작성했다.
8bit라고 하면, 조금 소리가 담긴 느낌이 되기 때문에, 16bit로 해 처리의 무게를 신경쓰고 샘플링 레이트를 22050Hz에 떨어뜨렸다.
재생으로 쁘띠 푸치 노이즈가 나오지 않도록, 선두는 FadeIn, 종단은 FadeOut 처리를 해 둔다.
사운드 파일의 재생 시간은 편집 툴로 확인해 둔다.
[Sound Files]
*16_pacman_eatdot_256ms.wav 11,372bytes
*16_pacman_eatfruit_438ms.wav 19,360bytes
*16_pacman_eatghost_544ms.wav 24,040bytes
*16_pacman_miss_1536ms.wav 67,788bytes
*16_pacman_extrapac_1952ms.wav 86,166bytes
*16_credit_224ms.wav 9,634bytes
*16_BGM_normal_400ms.wav 17,852bytes
*16_BGM_power_400ms.wav 17,750bytes
*16_BGM_return_528ms.wav 23,366bytes
*16_BGM_spurt1_352ms.wav 15,592bytes
*16_BGM_spurt2_320ms.wav 14,212bytes
*16_BGM_spurt3_592ms.wav 26,272bytes
*16_BGM_spurt4_512ms.wav 23,018bytes
*16_pacman_beginning_4224ms.wav 187,054bytes
*16_pacman_intermission_5200ms.wav 229,388bytes
테스트 프로그램
GitHub 에 공개하고 있는 테스트 프로그램을 실행하면, 다음과 같은 화면이 표시되어, BGM이 5초마다 전환된다. 화면을 터치하면 효과음이 재생됩니다.
Sound Manager 클래스는 SoundManager.swift 파일에 코딩되어 있습니다. 코멘트 넣어 200행 미만이 되었다.
class GameScene: SKScene {
private var sound: CgSoundManager!
override func didMove(to view: SKView) {
// Create and reset sound object.
sound = CgSoundManager(view: self)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
sound.playSE(.EatDot)
}
private let bgm: [CgSoundManager.EnKindOfSound] = [.BgmNormal, .BgmSpurt1, .BgmSpurt2, .BgmPower, .BgmReturn]
private var bgmIndex: Int = 0
private var bgmTime: Int = 0
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
// Play back BGM.
if bgmTime == 0 {
bgmTime = 16*60*5 // 5s
sound.playBGM(bgm[bgmIndex])
bgmIndex += 1
if bgmIndex >= bgm.count {
bgmIndex = 0
}
} else {
bgmTime -= 16
}
// Update sound manager.
sound.update(interval: 16 /* ms */)
}
}
CgSoundManager 클래스는 SKView 객체를 매개 변수로 사용하여 객체를 생성합니다.
SKScene 로부터 오버라이드(override) 한 touchesEnded 이벤트의 메소드로, SE 를 재생한다.
또, 마찬가지로 update 이벤트의 메소드로, 5초마다 BGM을 전환해 재생한다.
참고
효과음을 재생하는 API는
playSE(.EatDot)
한다.
BGM을 재생하는 API는
playBGM(.BgmPower)
한다.
이러한 API를 가지는, 다음의 CgSoundManager 클래스를 작성한다.
CgSoundManager 클래스
/// Sound management class plays sound with SpriteKit.
class CgSoundManager {
// Kind of sound items to play back.
enum EnKindOfSound: Int {
case EatDot = 0
case EatFruit
// ・・・略・・・
case Intermission
}
// List of sound files to load.
private let table_urls: [[(resourceName: String, typeName: String, interval: Int)]] = [
[ ("16_pacman_eatdot_256ms", "wav", 256) ],
[ ("16_pacman_eatfruit_438ms", "wav", 438) ],
// ・・・略・・・
[ ("16_pacman_intermission_5200ms", "wav", 5200) ]
]
private var view: SKScene?
private var actions: [SKAction] = []
private var table_playingTime: [Int] = []
// Adjustment time for processing to play sound.
private let triggerThresholdTime: Int = 16 //ms
/// Create and initialize a sound manager object.
/// - Parameters:
/// - view: SKScene object that organizes all of the active SpriteKit content.
init(view: SKScene) {
self.view = view
table_playingTime = Array<Int>(repeating: 0, count: table_urls.count)
for t in table_urls {
appendSoundResource(resourceName: t[0].resourceName, typeName: t[0].typeName)
}
// ・・・略・・・
}
/// Append sound resources to SpriteKit.
/// - Parameters:
/// - resourceName: File name for sound resource.
/// - typeName: Type name for sound resource.
private func appendSoundResource(resourceName: String, typeName: String) {
let fileName = resourceName+"."+typeName
let sound: SKAction = SKAction.playSoundFileNamed(fileName, waitForCompletion: false)
actions.append(sound)
}
/// Play back a specified sound.
/// If the specified item is playing back, it will not be played back.
/// - Parameter number: Kind of sound items to play back.
func playSE(_ number: EnKindOfSound) {
guard soundEnabled && number.rawValue < actions.count else { return }
let _number = number.rawValue
if table_playingTime[_number] <= triggerThresholdTime {
let table = table_urls[_number]
table_playingTime[_number] = table[0].interval
view?.run(actions[_number])
}
}
enum 으로 정의된 값과, 재생하는 사운드 파일의 table_urls 테이블을 대응시켜 둔다.
클래스 초기화시에, 이러한 파일을 SKAction의 오브젝트로서 생성해 둔다.
또한 사운드 파일의 재생 시간을 값으로 관리합니다. 이것은 동일한 효과음이 복수 중첩되지 않게 하기 때문에, 어느 효과음이 재생중에 동일한 것을 재생하는 경우에는 재생하지 않게 한다.
또한 BGM을 재생할 때는 지정된 사운드 파일의 재생이 종료되었음을 알고 동일한 것을 반복 재생하기 위해 사용한다. 자동으로 시작하기 위한 트리거는, update 메소드내에서 실시한다.
사운드 파일
이번 팩맨에 사용하는 사운드 파일은 15개로, 포맷은 WAV 형식, 16bit, 모노럴, 샘플링 레이트 22050Hz로 작성했다.
8bit라고 하면, 조금 소리가 담긴 느낌이 되기 때문에, 16bit로 해 처리의 무게를 신경쓰고 샘플링 레이트를 22050Hz에 떨어뜨렸다.
재생으로 쁘띠 푸치 노이즈가 나오지 않도록, 선두는 FadeIn, 종단은 FadeOut 처리를 해 둔다.
사운드 파일의 재생 시간은 편집 툴로 확인해 둔다.
[Sound Files]
*16_pacman_eatdot_256ms.wav 11,372bytes
*16_pacman_eatfruit_438ms.wav 19,360bytes
*16_pacman_eatghost_544ms.wav 24,040bytes
*16_pacman_miss_1536ms.wav 67,788bytes
*16_pacman_extrapac_1952ms.wav 86,166bytes
*16_credit_224ms.wav 9,634bytes
*16_BGM_normal_400ms.wav 17,852bytes
*16_BGM_power_400ms.wav 17,750bytes
*16_BGM_return_528ms.wav 23,366bytes
*16_BGM_spurt1_352ms.wav 15,592bytes
*16_BGM_spurt2_320ms.wav 14,212bytes
*16_BGM_spurt3_592ms.wav 26,272bytes
*16_BGM_spurt4_512ms.wav 23,018bytes
*16_pacman_beginning_4224ms.wav 187,054bytes
*16_pacman_intermission_5200ms.wav 229,388bytes
테스트 프로그램
GitHub 에 공개하고 있는 테스트 프로그램을 실행하면, 다음과 같은 화면이 표시되어, BGM이 5초마다 전환된다. 화면을 터치하면 효과음이 재생됩니다.
Sound Manager 클래스는 SoundManager.swift 파일에 코딩되어 있습니다. 코멘트 넣어 200행 미만이 되었다.
class GameScene: SKScene {
private var sound: CgSoundManager!
override func didMove(to view: SKView) {
// Create and reset sound object.
sound = CgSoundManager(view: self)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
sound.playSE(.EatDot)
}
private let bgm: [CgSoundManager.EnKindOfSound] = [.BgmNormal, .BgmSpurt1, .BgmSpurt2, .BgmPower, .BgmReturn]
private var bgmIndex: Int = 0
private var bgmTime: Int = 0
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
// Play back BGM.
if bgmTime == 0 {
bgmTime = 16*60*5 // 5s
sound.playBGM(bgm[bgmIndex])
bgmIndex += 1
if bgmIndex >= bgm.count {
bgmIndex = 0
}
} else {
bgmTime -= 16
}
// Update sound manager.
sound.update(interval: 16 /* ms */)
}
}
CgSoundManager 클래스는 SKView 객체를 매개 변수로 사용하여 객체를 생성합니다.
SKScene 로부터 오버라이드(override) 한 touchesEnded 이벤트의 메소드로, SE 를 재생한다.
또, 마찬가지로 update 이벤트의 메소드로, 5초마다 BGM을 전환해 재생한다.
참고
/// Sound management class plays sound with SpriteKit.
class CgSoundManager {
// Kind of sound items to play back.
enum EnKindOfSound: Int {
case EatDot = 0
case EatFruit
// ・・・略・・・
case Intermission
}
// List of sound files to load.
private let table_urls: [[(resourceName: String, typeName: String, interval: Int)]] = [
[ ("16_pacman_eatdot_256ms", "wav", 256) ],
[ ("16_pacman_eatfruit_438ms", "wav", 438) ],
// ・・・略・・・
[ ("16_pacman_intermission_5200ms", "wav", 5200) ]
]
private var view: SKScene?
private var actions: [SKAction] = []
private var table_playingTime: [Int] = []
// Adjustment time for processing to play sound.
private let triggerThresholdTime: Int = 16 //ms
/// Create and initialize a sound manager object.
/// - Parameters:
/// - view: SKScene object that organizes all of the active SpriteKit content.
init(view: SKScene) {
self.view = view
table_playingTime = Array<Int>(repeating: 0, count: table_urls.count)
for t in table_urls {
appendSoundResource(resourceName: t[0].resourceName, typeName: t[0].typeName)
}
// ・・・略・・・
}
/// Append sound resources to SpriteKit.
/// - Parameters:
/// - resourceName: File name for sound resource.
/// - typeName: Type name for sound resource.
private func appendSoundResource(resourceName: String, typeName: String) {
let fileName = resourceName+"."+typeName
let sound: SKAction = SKAction.playSoundFileNamed(fileName, waitForCompletion: false)
actions.append(sound)
}
/// Play back a specified sound.
/// If the specified item is playing back, it will not be played back.
/// - Parameter number: Kind of sound items to play back.
func playSE(_ number: EnKindOfSound) {
guard soundEnabled && number.rawValue < actions.count else { return }
let _number = number.rawValue
if table_playingTime[_number] <= triggerThresholdTime {
let table = table_urls[_number]
table_playingTime[_number] = table[0].interval
view?.run(actions[_number])
}
}
이번 팩맨에 사용하는 사운드 파일은 15개로, 포맷은 WAV 형식, 16bit, 모노럴, 샘플링 레이트 22050Hz로 작성했다.
8bit라고 하면, 조금 소리가 담긴 느낌이 되기 때문에, 16bit로 해 처리의 무게를 신경쓰고 샘플링 레이트를 22050Hz에 떨어뜨렸다.
재생으로 쁘띠 푸치 노이즈가 나오지 않도록, 선두는 FadeIn, 종단은 FadeOut 처리를 해 둔다.
사운드 파일의 재생 시간은 편집 툴로 확인해 둔다.
[Sound Files]
*16_pacman_eatdot_256ms.wav 11,372bytes
*16_pacman_eatfruit_438ms.wav 19,360bytes
*16_pacman_eatghost_544ms.wav 24,040bytes
*16_pacman_miss_1536ms.wav 67,788bytes
*16_pacman_extrapac_1952ms.wav 86,166bytes
*16_credit_224ms.wav 9,634bytes
*16_BGM_normal_400ms.wav 17,852bytes
*16_BGM_power_400ms.wav 17,750bytes
*16_BGM_return_528ms.wav 23,366bytes
*16_BGM_spurt1_352ms.wav 15,592bytes
*16_BGM_spurt2_320ms.wav 14,212bytes
*16_BGM_spurt3_592ms.wav 26,272bytes
*16_BGM_spurt4_512ms.wav 23,018bytes
*16_pacman_beginning_4224ms.wav 187,054bytes
*16_pacman_intermission_5200ms.wav 229,388bytes
테스트 프로그램
GitHub 에 공개하고 있는 테스트 프로그램을 실행하면, 다음과 같은 화면이 표시되어, BGM이 5초마다 전환된다. 화면을 터치하면 효과음이 재생됩니다.
Sound Manager 클래스는 SoundManager.swift 파일에 코딩되어 있습니다. 코멘트 넣어 200행 미만이 되었다.
class GameScene: SKScene {
private var sound: CgSoundManager!
override func didMove(to view: SKView) {
// Create and reset sound object.
sound = CgSoundManager(view: self)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
sound.playSE(.EatDot)
}
private let bgm: [CgSoundManager.EnKindOfSound] = [.BgmNormal, .BgmSpurt1, .BgmSpurt2, .BgmPower, .BgmReturn]
private var bgmIndex: Int = 0
private var bgmTime: Int = 0
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
// Play back BGM.
if bgmTime == 0 {
bgmTime = 16*60*5 // 5s
sound.playBGM(bgm[bgmIndex])
bgmIndex += 1
if bgmIndex >= bgm.count {
bgmIndex = 0
}
} else {
bgmTime -= 16
}
// Update sound manager.
sound.update(interval: 16 /* ms */)
}
}
CgSoundManager 클래스는 SKView 객체를 매개 변수로 사용하여 객체를 생성합니다.
SKScene 로부터 오버라이드(override) 한 touchesEnded 이벤트의 메소드로, SE 를 재생한다.
또, 마찬가지로 update 이벤트의 메소드로, 5초마다 BGM을 전환해 재생한다.
참고
class GameScene: SKScene {
private var sound: CgSoundManager!
override func didMove(to view: SKView) {
// Create and reset sound object.
sound = CgSoundManager(view: self)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
sound.playSE(.EatDot)
}
private let bgm: [CgSoundManager.EnKindOfSound] = [.BgmNormal, .BgmSpurt1, .BgmSpurt2, .BgmPower, .BgmReturn]
private var bgmIndex: Int = 0
private var bgmTime: Int = 0
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
// Play back BGM.
if bgmTime == 0 {
bgmTime = 16*60*5 // 5s
sound.playBGM(bgm[bgmIndex])
bgmIndex += 1
if bgmIndex >= bgm.count {
bgmIndex = 0
}
} else {
bgmTime -= 16
}
// Update sound manager.
sound.update(interval: 16 /* ms */)
}
}
다음글
【입문】iOS 앱 개발 #4【아키텍처의 설계】
Reference
이 문제에 관하여(【입문】iOS 앱 개발 #3【Sound 재생하기】), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/KIKU_CHU/items/01a45a3d4698058bd512
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(【입문】iOS 앱 개발 #3【Sound 재생하기】), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/KIKU_CHU/items/01a45a3d4698058bd512텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)