Obtenga AVAudioPlayer para reproducir múltiples sonidos a la vez.

Estoy tratando de get múltiples files de sonidos para que se reproduzcan en una instancia de AVAudioPlayer; sin embargo, cuando un sonido se reproduce, el otro se detiene. No puedo reproducir más de un sonido a la vez. Aquí está mi código:

import AVFoundation class GSAudio{ static var instance: GSAudio! var soundFileNameURL: NSURL = NSURL() var soundFileName = "" var soundPlay = AVAudioPlayer() func playSound (soundFile: String){ GSAudio.instance = self soundFileName = soundFile soundFileNameURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(soundFileName, ofType: "aif", inDirectory:"Sounds")!) do{ try soundPlay = AVAudioPlayer(contentsOfURL: soundFileNameURL) } catch { print("Could not play sound file!") } soundPlay.prepareToPlay() soundPlay.play () } } 

¿Alguien puede ayudarme diciéndome cómo get más de un file de sonido para reproducir a la vez? Cualquier ayuda es muy apreciada.

Muchas gracias Kai

La razón por la que se detiene el audio es porque solo tiene configurado un AVAudioPlayer, por lo que cuando le pide a la class que reproduzca otro sonido, actualmente está reemplazando la instancia anterior por una nueva instancia de AVAudioPlayer. Lo estás sobreescribiendo básicamente.

Puede crear dos instancias de la class GSAudio y luego llamar a playSound en cada una de ellas o hacer que la class sea un administrador de audio genérico que use un dictionary de reproductores de audio.

Prefiero esta última opción, ya que permite un código más limpio y también es más eficiente. Puedes comprobar si ya has hecho un reproductor para el sonido antes, en lugar de hacer un nuevo reproductor, por ejemplo.

De todas forms, volví a hacer tu class para ti para que reproduzca múltiples sonidos a la vez. También puede reproducir el mismo sonido sobre sí mismo (no reemplaza la instancia anterior del sonido) ¡Espero que ayude!

La class es un singleton, por lo que para acceder al uso de la class:

 GSAudio.shanetworkingInstance 

por ejemplo, para reproducir un sonido que llamarías:

 GSAudio.shanetworkingInstance.playSound("AudioFileName") 

y para reproducir una serie de sonidos a la vez:

 GSAudio.shanetworkingInstance.playSounds("AudioFileName1", "AudioFileName2") 

o podría cargar los sonidos en una matriz en alguna parte y llamar a la function playSounds que acepta una matriz:

 let sounds = ["AudioFileName1", "AudioFileName2"] GSAudio.shanetworkingInstance.playSounds(sounds) 

También agregué una function de playSounds que te permite retrasar cada sonido que se está reproduciendo en una especie de formatting en cascada. Asi que:

  let soundFileNames = ["SoundFileName1", "SoundFileName2", "SoundFileName3"] GSAudio.shanetworkingInstance.playSounds(soundFileNames, withDelay: 1.0) 

jugaría sound2 un segundo después de sound1, luego sound3 jugaría un segundo después de sound2, etc.

Aquí está la class:

 class GSAudio: NSObject, AVAudioPlayerDelegate { static let shanetworkingInstance = GSAudio() private override init() {} var players = [NSURL:AVAudioPlayer]() var duplicatePlayers = [AVAudioPlayer]() func playSound (soundFileName: String){ let soundFileNameURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(soundFileName, ofType: "aif", inDirectory:"Sounds")!) if let player = players[soundFileNameURL] { //player for sound has been found if player.playing == false { //player is not in use, so use that one player.prepareToPlay() player.play() } else { // player is in use, create a new, duplicate, player and use that instead let duplicatePlayer = try! AVAudioPlayer(contentsOfURL: soundFileNameURL) //use 'try!' because we know the URL worked before. duplicatePlayer.delegate = self //assign delegate for duplicatePlayer so delegate can remove the duplicate once it's stopped playing duplicatePlayers.append(duplicatePlayer) //add duplicate to array so it doesn't get removed from memory before finishing duplicatePlayer.prepareToPlay() duplicatePlayer.play() } } else { //player has not been found, create a new player with the URL if possible do{ let player = try AVAudioPlayer(contentsOfURL: soundFileNameURL) players[soundFileNameURL] = player player.prepareToPlay() player.play() } catch { print("Could not play sound file!") } } } func playSounds(soundFileNames: [String]){ for soundFileName in soundFileNames { playSound(soundFileName) } } func playSounds(soundFileNames: String...){ for soundFileName in soundFileNames { playSound(soundFileName) } } func playSounds(soundFileNames: [String], withDelay: Double) { //withDelay is in seconds for (index, soundFileName) in soundFileNames.enumerate() { let delay = withDelay*Double(index) let _ = NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: #selector(playSoundNotification(_:)), userInfo: ["fileName":soundFileName], repeats: false) } } func playSoundNotification(notification: NSNotification) { if let soundFileName = notification.userInfo?["fileName"] as? String { playSound(soundFileName) } } func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) { duplicatePlayers.removeAtIndex(duplicatePlayers.indexOf(player)!) //Remove the duplicate player once it is done } } 

He creado una biblioteca auxiliar que simplifica la reproducción de sonidos en Swift. Crea múltiples instancias de AVAudioPlayer para permitir reproducir el mismo sonido varias veces al mismo time. Puede downloadlo desde Github o importar con Cocoapods.

Aquí está el enlace: SwiftySound

El uso es tan simple como puede ser:

 Sound.play(file: "sound.mp3")