Créer et jouer un son rapidement


103

Donc ce que je veux faire, c'est créer et jouer un son en Swift qui jouera lorsque j'appuie sur un bouton, je sais comment le faire en Objective-C, mais est-ce que quelqu'un sait comment le faire en Swift?

Ce serait comme ça pour Objective-C:

NSURL *soundURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"mysoundname" ofType:@"wav"]];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL, &mySound);

Et puis pour y jouer je ferais:

AudioServicesPlaySystemSound(Explosion);

Est-ce que quelqu'un sait comment je pourrais faire ça?


2
La racine de cette question est de savoir comment appeler des fonctions C à partir de swift. Je suis curieux à ce sujet également.
67cherries

cette ligne peut créer l'url du son: var url :NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("mysoundname", ofType: "wav"))
Connor

@connor Merci qui fonctionne mais qu'en est-il pour AudioServicesCreateSystemSoundID
Jacob Banks

Je ne suis pas certain de ça. Je n'ai pu appeler l'api objective-c que depuis swift.
Connor

Réponses:


83

Voici un peu de code que j'ai ajouté à FlappySwift qui fonctionne:

import SpriteKit
import AVFoundation

class GameScene: SKScene {

    // Grab the path, make sure to add it to your project!
    var coinSound = NSURL(fileURLWithPath: Bundle.main.path(forResource: "coin", ofType: "wav")!)
    var audioPlayer = AVAudioPlayer()

    // Initial setup
    override func didMoveToView(view: SKView) {
        audioPlayer = AVAudioPlayer(contentsOfURL: coinSound, error: nil)
        audioPlayer.prepareToPlay()
    }

    // Trigger the sound effect when the player grabs the coin
    func didBeginContact(contact: SKPhysicsContact!) {
        audioPlayer.play()
    }

}

Il semblerait que vous puissiez simplement déclarer audioPlayer juste avant de l'utiliser, mais cela n'a pas fonctionné pour moi dans le simulateur. J'ai dû le déclarer au sommet comme vous l'avez fait.
Adam Loving

@Adam Loving, vous pouvez déclarer audioPlayer juste avant de l'utiliser, mais assurez-vous d'appeler play () dans la même fonction que vous l'avez déclaré (par opposition à la bonne réponse) De plus, je déclarerais coinSoundet audioPlayeravec letau lieu de varpuisque vous ne voulez pas modifiez ces objets ultérieurement.
fat32

3
Dans Swift 2, n'oubliez pas de l'exécuter de cette façon do { (player object) } catch _ { }ou vous obtiendrez un bug! :)
ParisNakitaKejser

1
Mais attention! Il mettra en pause la musique de fond du lecteur. Pour jouer un son court, nous devons utiliser la réponse ci
Nikita Pronchik

Downvote - ce n'est pas un son système, il utilise une API différente
William Entriken

119

Ceci est similaire à d'autres réponses, mais peut-être un peu plus "Swifty":

// Load "mysoundname.wav"
if let soundURL = Bundle.main.url(forResource: "mysoundname", withExtension: "wav") {
    var mySound: SystemSoundID = 0
    AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
    // Play
    AudioServicesPlaySystemSound(mySound);
}

Notez qu'il s'agit d'un exemple trivial reproduisant l'effet du code dans la question. Vous devrez vous assurer de le faire import AudioToolbox, et le modèle général pour ce type de code serait de charger vos sons au démarrage de votre application, de les enregistrer dans des SystemSoundIDvariables d'instance quelque part, de les utiliser dans toute votre application, puis d'appeler AudioServicesDisposeSystemSoundIDlorsque vous avez terminé avec eux.


1
Vous devez également importer AudioToolbox
Brody Robertson

Devez-vous appeler AudioServicesDisposeSystemSoundID(mySound)pour libérer de la mémoire plus tard? si vous le faites tout de suite, le son ne joue pas (se nettoie instantanément), alors je l'ai fait dispatch_afteret je l'ai nettoyé 10 secondes plus tard.
owenfi

@owenfi Le fragment de code dans ma réponse n'est que l'équivalent Swift du fragment de code dans la question. Le modèle général pour AudioServices consiste à charger vos sons lorsque votre application se déclenche, à les utiliser dans toute l'application et à les éliminer lorsque l'application se ferme, mais chaque application sera différente.
Matt Gibson

@ozgur Pourquoi utilisez-vous une version obsolète de Xcode? Nous aurons besoin de savoir ce que signifie «ne fonctionne pas», et vous ferez probablement mieux de poser une nouvelle question si vous avez des problèmes spécifiques.
Matt Gibson

en fait, c'est la seule façon de lire un fichier wav. AVPlayer ne semble pas fonctionner.
Haitao

18

Extension Handy Swift:

import AudioToolbox

extension SystemSoundID {
    static func playFileNamed(fileName: String, withExtenstion fileExtension: String) {
        var sound: SystemSoundID = 0
        if let soundURL = NSBundle.mainBundle().URLForResource(fileName, withExtension: fileExtension) {
            AudioServicesCreateSystemSoundID(soundURL, &sound)
            AudioServicesPlaySystemSound(sound)
        }
    }
}

Ensuite, de n'importe où dans votre application (n'oubliez pas de le faire import AudioToolbox), vous pouvez appeler

SystemSoundID.playFileNamed("sound", withExtenstion: "mp3")

pour lire "sound.mp3"


Lorsque j'exécute cela dans un jeu SpriteKit, il y a toujours du retard avant que le son ne soit joué. Même si je l'ai mis à l'intérieur DispatchQueue.global(qos: .userInitiated).async {}.
Jon Kantner

NSBundlea été remplacé par Bundle, utilisez à la Bundle.main.url(forResource: fileName, withExtension: fileExtension)place
diachedelic

14

Cela crée un SystemSoundIDfichier à partir d'un fichier appelé Cha-Ching.aiff.

import AudioToolbox

let chaChingSound: SystemSoundID = createChaChingSound()

class CashRegisterViewController: UIViewController {
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        AudioServicesPlaySystemSound(chaChingSound)
    }
}

func createChaChingSound() -> SystemSoundID {
    var soundID: SystemSoundID = 0
    let soundURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), "Cha-Ching", "aiff", nil)
    AudioServicesCreateSystemSoundID(soundURL, &soundID)
    CFRelease(soundURL)
    return soundID
}

Avez-vous essayé de compiler le code? J'obtiens l'erreur "Impossible de convertir le type d'extression" Unmanaged <CFURL>! " pour taper 'CFString' "à partir de cette ligne" let soundURL = CFBundleCopyResourceURL (CFBundleGetMainBundle (), "Cha-Ching", "aiff", nil) "
bpolat


2
Cela devrait être la réponse acceptée, étant donné que l'exemple Obj-C fourni est basé dans le Framework AudioToolBox
eharo2

@JochenBedersdorfer, vous obtenez probablement une erreur car les objets Core Foundation sont automatiquement gérés en mémoire.
XCool

8

Avec une classe et AudioToolbox:

import AudioToolbox

class Sound {

    var soundEffect: SystemSoundID = 0
    init(name: String, type: String) {
        let path  = NSBundle.mainBundle().pathForResource(name, ofType: type)!
        let pathURL = NSURL(fileURLWithPath: path)
        AudioServicesCreateSystemSoundID(pathURL as CFURLRef, &soundEffect)
    }

    func play() {
        AudioServicesPlaySystemSound(soundEffect)
    }
}

Usage:

testSound = Sound(name: "test", type: "caf")
testSound.play()

2
J'adore cette réponse. Aussi parce que c'est le son du système, je ne reçois pas le message système que l'AVAudioPlayer jette dans la console pour xcode 8.
TPot

Aidez-moi, je fais la même chose, le son joue mais le volume est trop bas. ne peut pas entendre
veeresh kumbar

5
import AVFoundation

var audioPlayer = AVAudioPlayer()

class GameScene: SKScene {

    override func didMoveToView(view: SKView) {

        let soundURL = NSBundle.mainBundle().URLForResource("04", withExtension: "mp3")
        audioPlayer = AVAudioPlayer(contentsOfURL: soundURL, error: nil)
        audioPlayer.play()
    }
}

C'est AVAudioPlayer (contentsOf: soundURL) dans Swift moderne
boîte

5

Ce code fonctionne pour moi. Utilisez Try and Catch pour AVAudioPlayer

import UIKit
import AVFoundation
class ViewController: UIViewController {

    //Make sure that sound file is present in your Project.
    var CatSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Meow-sounds.mp3", ofType: "mp3")!)
    var audioPlayer = AVAudioPlayer()

    override func viewDidLoad() {
        super.viewDidLoad()

        do {

            audioPlayer = try AVAudioPlayer(contentsOfURL: CatSound)
            audioPlayer.prepareToPlay()

        } catch {

            print("Problem in getting File")

        }      
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func button1Action(sender: AnyObject) {

        audioPlayer.play()
    }
}

4
var mySound = NSSound(named:"Morse.aiff")
mySound.play()

"Morse.aiff" est un son système d'OSX, mais si vous cliquez simplement sur "nommé" dans XCode, vous pourrez voir (dans le volet Aide rapide) où cette fonction recherche les sons. Il peut se trouver dans votre dossier "Fichiers de support"


4
La question concerne iOS.
rmaddy

En effet ... Impossible de le faire dans le simulateur. Aucun doc disponible pour le moment
philippe

4

Selon le nouveau Swift 2.0, nous devrions utiliser do try catch. Le code ressemblerait à ceci:

var badumSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("BadumTss", ofType: "mp3"))
var audioPlayer = AVAudioPlayer()
 do {
     player = try AVAudioPlayer(contentsOfURL: badumSound)
 } catch {
     print("No sound found by URL:\(badumSound)")
 }
 player.prepareToPlay()

3

cela fonctionne avec Swift 4:

if let soundURL = Bundle.main.url(forResource: "note3", withExtension: "wav") {
                var mySound: SystemSoundID = 0
                AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
                // Play
                AudioServicesPlaySystemSound(mySound);
            }

2
Veuillez expliquer votre code. Les réponses basées uniquement sur le code ont moins de valeur que les explications.
Vincent

@Vincent +1, en fait je me demande & opérateur. Cela peut être référencé entre le son et la mémoire.
elia

vous devez ajouter l'importation AudioToolbox puis ajouter le code ci-dessus
Mohammad Aboelnasr

2
//Swift 4
import UIKit
import AVFoundation

class ViewController: UIViewController {

    var player : AVAudioPlayer?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func notePressed(_ sender: UIButton) {
        let path = Bundle.main.path(forResource: "note1", ofType: "wav")!
        let url = URL(fileURLWithPath: path)
        do {
            player = try AVAudioPlayer(contentsOf: url)
            player?.play()
        } catch {
            // error message
        }
    }
}

2

Voyons une approche plus mise à jour de cette question:

Import AudioToolbox

func noteSelector(noteNumber: String) {

    if let soundURL = Bundle.main.url(forResource: noteNumber, withExtension: "wav") {
        var mySound: SystemSoundID = 0
        AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
        AudioServicesPlaySystemSound(mySound)
}

1
Le code fonctionne bien sur Swift 4, mais apparemment le son émis ne suit pas le volume du média
David Vargas

1

La solution de Matt Gibson a fonctionné pour moi, voici la version swift 3.

if let soundURL = Bundle.main.url(forResource: "ringSound", withExtension: "aiff") {
  var mySound: SystemSoundID = 0
  AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
  AudioServicesPlaySystemSound(mySound);
}

1

Swift 4

import UIKit
import AudioToolbox

class ViewController: UIViewController{

var sounds : [SystemSoundID] = [1, 2, 3, 4, 5, 6, 7]

override func viewDidLoad() {
    super.viewDidLoad()

    for index in 0...sounds.count-1 {
        let fileName : String = "note\(sounds[index])"

        if let soundURL = Bundle.main.url(forResource: fileName, withExtension: "wav") {
            AudioServicesCreateSystemSoundID(soundURL as CFURL, &sounds[index])
        }
    }
}



@IBAction func notePressed(_ sender: UIButton) {
    switch sender.tag {
    case 1:
        AudioServicesPlaySystemSound(sounds[0])
    case 2:
        AudioServicesPlaySystemSound(sounds[1])
    case 3:
        AudioServicesPlaySystemSound(sounds[2])
    case 4:
        AudioServicesPlaySystemSound(sounds[3])
    case 5:
        AudioServicesPlaySystemSound(sounds[4])
    case 6:
        AudioServicesPlaySystemSound(sounds[5])
    default:
        AudioServicesPlaySystemSound(sounds[6])
    }
}
}

ou

import UIKit
import AVFoundation

class ViewController: UIViewController, AVAudioPlayerDelegate{

var audioPlayer : AVAudioPlayer!

override func viewDidLoad() {
    super.viewDidLoad()
}

@IBAction func notePressed(_ sender: UIButton) {

    let soundURL = Bundle.main.url(forResource: "note\(sender.tag)", withExtension: "wav")

    do {
        audioPlayer = try AVAudioPlayer(contentsOf: soundURL!)
    }
    catch {
        print(error)
    }

    audioPlayer.play()

}
}

1

travaille dans Xcode 9.2

if let soundURL = Bundle.main.url(forResource: "note1", withExtension: "wav") {
   var mySound: SystemSoundID = 0
   AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
   // Play
    AudioServicesPlaySystemSound(mySound);
 }

1

Exemple de code SWIFT :

import UIKit
import AudioToolbox

class ViewController: UIViewController {  

override func viewDidLoad() {
    super.viewDidLoad()
}

@IBAction func notePressed(_ sender: UIButton) {

    // Load "mysoundname.wav"

    if let soundURL = Bundle.main.url(forResource: "note1", withExtension: "wav") {
        var mySound: SystemSoundID = 0
        AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
    // Play

        AudioServicesPlaySystemSound(mySound);
    }
}

Veuillez ajouter plus de détails sur les raisons pour lesquelles ce code est utile.
Berendschot

1

Vous pouvez essayer ceci dans Swift 5.2:

func playSound() {
        let soundURL = Bundle.main.url(forResource: selectedSoundFileName, withExtension: "wav")
        do {
            audioPlayer = try AVAudioPlayer(contentsOf: soundURL!)
        }
        catch {
            print(error)
        }
        audioPlayer.play()
    }

1

swift 4 et iOS 12

var audioPlayer: AVAudioPlayer?

override func viewDidLoad() {
    super.viewDidLoad()



}

@IBAction func notePressed(_ sender: UIButton) {

    // noise while pressing button

    _ = Bundle.main.path(forResource: "note1", ofType: "wav")

    if Bundle.main.path(forResource: "note1", ofType: "wav") != nil {
        print("Continue processing")
    } else {
        print("Error: No file with specified name exists")
    }

    do {
        if let fileURL = Bundle.main.path(forResource: "note1", ofType: "wav") {
            audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: fileURL))
        } else {
            print("No file with specified name exists")
        }
    } catch let error {
        print("Can't play the audio file failed with an error \(error.localizedDescription)")
    }


    audioPlayer?.play()    }

}


Ne vous contentez pas de publier du code - expliquez ce qu'il fait! stackoverflow.com/help/how-to-answer
Nino Filiu

veuillez vous référer à la question de ce post. Vous pouvez trouver votre réponse! merci @NinoFiliu
Gulsan Borbhuiya

0

Utilisez cette fonction pour produire du son dans Swift (vous pouvez utiliser cette fonction là où vous souhaitez produire du son.)

Ajoutez d'abord SpriteKit et AVFoundation Framework.

import SpriteKit
import AVFoundation
 func playEffectSound(filename: String){
   runAction(SKAction.playSoundFileNamed("\(filename)", waitForCompletion: false))
 }// use this function to play sound

playEffectSound("Sound File Name With Extension")
// Example :- playEffectSound("BS_SpiderWeb_CollectEgg_SFX.mp3")

0

Ce code fonctionne pour moi:

class ViewController: UIViewController {

    var audioFilePathURL : NSURL!
    var soundSystemServicesId : SystemSoundID = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        audioFilePathURL = NSBundle.mainBundle().URLForResource("MetalBell", withExtension: "wav")

        AudioServicesCreateSystemSoundID( audioFilePathURL, &soundSystemServicesId)


    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.


    }


    @IBAction func PlayAlertSound(sender: UIButton) {

         AudioServicesPlayAlertSound(soundSystemServicesId)
    }
}

0

Pour Swift 3 :

extension SystemSoundID {
    static func playFileNamed(_ fileName: String, withExtenstion fileExtension: String) {
        var sound: SystemSoundID = 0
        if let soundURL = Bundle.main.url(forResource: fileName, withExtension: fileExtension) {
            AudioServicesCreateSystemSoundID(soundURL as CFURL, &sound)
            AudioServicesPlaySystemSound(sound)
        }
    }
}

0

Swift 3 voici comment je le fais.

{

import UIKit
import AVFoundation

        let url = Bundle.main.url(forResource: "yoursoundname", withExtension: "wav")!
        do {

            player = try AVAudioPlayer(contentsOf: url); guard let player = player else { return }

            player.prepareToPlay()
            player.play()
        } catch let error as Error {
            print(error)

        }
    }

0

Ne pourriez-vous pas simplement import AVFoundationsélectionner le lecteur audio ( var audioPlayer : AVAudioPlayer!) et lire le son? ( let soundURL = Bundle.main.url(forResource: "sound", withExtension: "wav")


0
import UIKit
import AudioToolbox

class ViewController: UIViewController {

    let toneSound : Array =  ["note1","note2","note3","note4","note5","note6"]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

    }

    func playSound(theTone : String) {
        if let soundURL = Bundle.main.url(forResource: theTone, withExtension: "wav") {
            var mySound: SystemSoundID = 0
            do {
                AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
                // Play
                AudioServicesPlaySystemSound(mySound);
            }
            catch {
               print(error)
            }
        }
    }

    @IBAction func anypressed(_ sender: UIButton) {
        playSound(theTone: toneSound[sender.tag-1] )
    }    

}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.