2014-11-18 51 views
0

SpriteKit을 사용하지 않고 iOS에서 게임을 만들려고합니다. 나는 사운드 효과가 적시에 재생되도록 노력하고 있습니다. 나는 온라인에서 찾은 다음과 같은 코드를 사용했고 배경 음악은 훌륭하게 연주했다. 그러나 "playSoundEffect"메서드를 사용하면 처음에는 정상적으로 재생되지만 뒤쳐지기 시작하여 동기화되지 않습니다. 매번 AVAudioPlayer를 초기화하기 때문에 이런 현상이 발생합니다. 배경 음악을 재생하는 동안 적시에 사운드 효과를 재생하는 방법에 대해 누구나 좋은 생각이 있습니까? 감사!iOS, swift : 지연없이 백그라운드 음악 및 사운드 효과를 재생합니다.

import AVFoundation 

public class SKTAudio: NSObject, AVAudioPlayerDelegate { 
public var backgroundMusicPlayer: AVAudioPlayer? 
public var soundEffectPlayer: AVAudioPlayer? 

private var mainLoopFileName:String! { 

    let randomSong = Int(arc4random_uniform(3)) 

    switch randomSong { 
    //case 0: return "Test.mp3" 
    //case 1: return "Test2.mp3" 
    case 0: return "SneakySnitch.mp3" 
    case 1: return "FasterDoesIt.mp3" 
    case 2: return "MonkeysSpinningMonkeys.mp3" 
    default: 
     break 
    } 

    return "SneakySnitch.mp3" 
} 

public class func sharedInstance() -> SKTAudio { 
    return SKTAudioInstance 
} 

public func playBackgroundMusic() { 
    let filename = mainLoopFileName 
    let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil) 
    if (url == nil) { 
     println("Could not find file: \(filename)") 
     return 
    } 

    var error: NSError? = nil 
    backgroundMusicPlayer = AVAudioPlayer(contentsOfURL: url, error: &error) 
    if let player = backgroundMusicPlayer { 
     player.numberOfLoops = 0 
     player.delegate = self 
     player.prepareToPlay() 
     player.play() 
    } else { 
     println("Could not create audio player: \(error!)") 
    } 
} 

public func pauseBackgroundMusic() { 
    if let player = backgroundMusicPlayer { 
     if player.playing { 
      player.pause() 
     } 
    } 
} 

public func resumeBackgroundMusic() { 
    if let player = backgroundMusicPlayer { 
     if !player.playing { 
      player.play() 
     } 
    } 
} 

public func playSoundEffect(filename: String) { 
    let url = NSBundle.mainBundle().URLForResource(filename, withExtension: nil) 
    if (url == nil) { 
     println("Could not find file: \(filename)") 
     return 
    } 

    var error: NSError? = nil 
    soundEffectPlayer = AVAudioPlayer(contentsOfURL: url, error: &error) 
    if let player = soundEffectPlayer { 
     player.numberOfLoops = 0 
     player.prepareToPlay() 
     player.play() 
    } else { 
     println("Could not create audio player: \(error!)") 
    } 
} 

// MARK: AVAudioPlayerDelegate 
public func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool) { 
    println("finished playing \(flag)") 

    delay(5.0, { 
     self.playBackgroundMusic() 
    }) 
} 

public func audioPlayerDecodeErrorDidOccur(player: AVAudioPlayer!, error: NSError!) { 
    println("\(error.localizedDescription)") 
} 

} 

답변

0

사운드 파일을 재생하는 데 AVPlayer를 사용할 수 있습니다. 한 명의 플레이어를 유지하고 새로운 사운드를 재생해야 할 때 AVPlayerItem을 새 항목으로 변경하십시오. 매번 플레이어를 다시 만드는 것보다 빠를 수도 있습니다.

AVAudioPlayer/AVPlayer은 가장 간단한 옵션이지만 오디오 파일을 재생할 때 가장 짧은 지연이나 완벽한 동기화를 제공하지 않습니다. 보다 정확한 사운드 재생을 위해서는 Core Audio 내의 Audio Queues 또는 Audio Units를 조사해야합니다.

0

첫 번째 사운드 효과가 끝나기 전에 두 번째 사운드 효과를 재생하는 것이 문제입니다. 새 AVAudioPlayersoundEffectPlayer 변수로 설정하면 첫 번째 참조가 강제로 재생되지 않습니다.

당신은 당신이 사용할 수있는 사운드의 볼륨 제어의 가용성 잃어버린 마음을하지 않는 경우, 당신은 당신이 배열로 만들고 각 사운드를 추가하는 경우 그렇지 않으면 AVAudioPlayer을 사용할 수 있습니다

var mySound: SystemSoundID = 0 
AudioServicesCreateSystemSoundID(url, &mySound) 
// Play 
AudioServicesPlaySystemSound(mySound) 

유지 참조. 그런 다음 AVAudioPlayer 대리자를 구현하여 사운드가 완료되면 삭제할 수 있습니다.

func playSound(){ 
    let path : NSString? = NSBundle.mainBundle().pathForResource("sound", ofType: "wav")! 
    let url = NSURL(fileURLWithPath: path!) 

    var error : NSError? 
    let sound = AVAudioPlayer(contentsOfURL: url, error: &error) 
    sound.delegate = self 
    sound.volume = 0.5 

    self.soundsEffectsArray.addObject(sound) 
    sound.prepareToPlay() 
    sound.play() 
} 

func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool) { 
    self.soundsEffectsArray.removeObject(player) 
}