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?

Jacob Banks
la source
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()
    }

}
Bauerpauer
la source
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.

Matt Gibson
la source
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"

Aleix Pinardell
la source
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
}
ma11hew28
la source
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
Oui, ça compile pour moi. Voir github.com/acani/Chats/blob/master/Chats/Chats/…
ma11hew28
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()
Karimhossenbux
la source
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()
    }
}
Michael N
la source
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()
    }
}
Sachin Dobariya
la source
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"

Philippe
la source
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()
Roman Safin
la source
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);
            }
Mohammad Aboelnasr
la source
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
        }
    }
}
Soma Sharma
la source
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)
}
Adam Eberbach
la source
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);
}
Pavle Mijatovic
la source
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()

}
}

la source
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);
 }
Ray Sawyer
la source
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);
    }
}
Pawel
la source
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()
    }
Xab Ion
la source
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()    }

}

Gulsan Borbhuiya
la source
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")
Rex
la source
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)
    }
}
Jeeva
la source
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)
        }
    }
}
He Yifei 何 一 非
la source
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)

        }
    }

la source
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")

Boeing aimeToDab
la source
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] )
    }    

}
IslamNazir
la source