Creazione e riproduzione di un suono in modo rapido


103

Quindi quello che voglio fare è creare e riprodurre un suono in Swift che verrà riprodotto quando premo un pulsante, so come farlo in Objective-C, ma qualcuno lo sa in Swift?

Sarebbe così per Objective-C:

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

E poi per suonarlo farei:

AudioServicesPlaySystemSound(Explosion);

Qualcuno sa come potrei farlo?


2
La radice di questa domanda è come chiamare le funzioni C da swift. Sono curioso anche di questo.
67cherries

questa linea può creare l'URL del suono: var url :NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("mysoundname", ofType: "wav"))
Connor

@connor Grazie che funziona, ma per quanto riguarda AudioServicesCreateSystemSoundID
Jacob Banks

Non ne sono sicuro. Sono stato in grado di chiamare l'API Objective-C solo da Swift.
Connor

Risposte:


83

Ecco un po 'di codice che ho aggiunto a FlappySwift che funziona:

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()
    }

}

Sembrerebbe che potresti semplicemente dichiarare audioPlayer subito prima di usarlo, ma non ha funzionato per me nel simulatore. Ho dovuto dichiararlo in alto proprio come hai fatto tu.
Adam Loving

@Adam Loving puoi dichiarare audioPlayer subito prima di usarlo, ma assicurati di invocare play () nella stessa funzione in cui lo hai dichiarato (al contrario della buona risposta) Inoltre, dichiarerei coinSounde audioPlayercon letinvece di vardal momento che non vuoi modificare questi oggetti in un secondo momento.
fat32

3
In Swift 2 ricordati di eseguirlo in questo modo do { (player object) } catch _ { }o riceverai un bug! :)
ParisNakitaKejser

1
Ma attenzione! Metterà in pausa la musica di sottofondo dal lettore. Per riprodurre un breve suono dobbiamo usare la risposta di seguito
Nikita Pronchik

Downvote - questo non è un suono di sistema, utilizza un'API diversa
William Entriken,

119

È simile ad alcune altre risposte, ma forse un po 'più "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);
}

Nota che questo è un banale esempio che riproduce l'effetto del codice nella domanda. Dovrai assicurarti di farlo import AudioToolbox, inoltre lo schema generale per questo tipo di codice sarebbe caricare i tuoi suoni all'avvio della tua app, salvarli in SystemSoundIDvariabili di istanza da qualche parte, usarli in tutta l'app, quindi chiamare AudioServicesDisposeSystemSoundIDquando hai finito con loro.


1
Devi anche importare AudioToolbox
Brody Robertson

Hai bisogno di chiamare AudioServicesDisposeSystemSoundID(mySound)per liberare la memoria più tardi? se lo fai subito, il suono praticamente non viene riprodotto (viene ripulito all'istante), quindi l'ho fatto dispatch_aftere l' ho ripulito 10 secondi dopo.
owenfi

@owenfi Il frammento di codice nella mia risposta è solo l'equivalente Swift del frammento di codice nella domanda. Lo schema generale per AudioServices consiste nel caricare i suoni quando l'app si avvia, usarli in tutta l'app e smaltirli quando l'app si chiude, ma ogni app sarà diversa.
Matt Gibson

@ozgur Perché stai usando una versione obsoleta di Xcode? Avremo bisogno di sapere cosa significa "non funziona" e probabilmente farai meglio a fare una nuova domanda se hai problemi specifici.
Matt Gibson

in realtà questo è l'unico modo per riprodurre file wav. AVPlayer non sembra funzionare.
Haitao

18

Pratica estensione 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)
        }
    }
}

Quindi, da qualsiasi punto della tua app (ricordati di import AudioToolbox), puoi chiamare

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

per riprodurre "sound.mp3"


Quando lo eseguo in un gioco SpriteKit, c'è sempre un ritardo prima che il suono venga riprodotto. Anche se lo metto dentro DispatchQueue.global(qos: .userInitiated).async {}.
Jon Kantner

NSBundleè stato sostituito da Bundle, usa Bundle.main.url(forResource: fileName, withExtension: fileExtension)invece
diachedelico

14

Questo crea un SystemSoundIDda un file chiamato 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
}

Hai provato a compilare il codice? Ricevo l'errore "Impossibile convertire il tipo di estrazione" Unmanaged <CFURL>! " per digitare "CFString" "da questa riga" lascia soundURL = CFBundleCopyResourceURL (CFBundleGetMainBundle (), "Cha-Ching", "aiff", nil) "
bpolat


2
Questa dovrebbe essere la risposta accettata, dato che l'esempio Obj-C fornito è basato su AudioToolBox Framework
eharo2

@JochenBedersdorfer, probabilmente stai ricevendo un errore a causa della gestione automatica della memoria degli oggetti Core Foundation.
XCool

8

Con una classe e 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)
    }
}

Uso:

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

2
Amo questa risposta. Anche perché è il suono di sistema, non ricevo il messaggio di sistema che AVAudioPlayer lancia nella console per xcode 8.
TPot

per favore aiuto sto facendo la stessa cosa, il suono viene riprodotto ma il volume è troppo basso. non può sentire
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()
    }
}

È AVAudioPlayer (contentsOf: soundURL) in Modern Swift
boxed

5

Questo codice funziona per me. Usa Try and Catch per 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" è un suono di sistema di OSX, ma se fai clic su "named" all'interno di XCode, sarai in grado di vedere (nel riquadro QuickHelp) dove questa funzione sta cercando i suoni. Può essere nella cartella "File di supporto"


4
La domanda riguarda iOS.
rmaddy

In effetti ... Non sono riuscito a farlo nel simulatore. Nessun documento disponibile fino ad oggi
philippe

4

Secondo il nuovo Swift 2.0 dovremmo usare do try catch. Il codice sarebbe simile a questo:

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

funziona con 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
Per favore, spiega il tuo codice. Le risposte di solo codice sono meno preziose delle spiegazioni.
Vincent,

@ Vincent +1, in realtà mi chiedo e operatore. Questo potrebbe essere referenziato tra suono e memoria.
elia

devi aggiungere import AudioToolbox quindi aggiungere il codice sopra
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

Vediamo un approccio più aggiornato a questa domanda:

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
Il codice funziona bene su Swift 4, ma a quanto pare il suono emesso non segue il volume dei media
David Vargas

1

La soluzione di Matt Gibson ha funzionato per me, ecco la versione 3 rapida.

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])
    }
}
}

o

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

lavora in 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

Esempio di codice 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);
    }
}

Si prega di aggiungere ulteriori dettagli sul motivo per cui questo codice è utile.
Berendschot

1

Puoi provare questo in 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 e 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()    }

}


Non limitarti a inserire il codice: spiega cosa fa! stackoverflow.com/help/how-to-answer
Nino Filiu

si prega di fare riferimento alla domanda di questo post. Puoi trovare la tua risposta! grazie @NinoFiliu
Gulsan Borbhuiya

0

Usa questa funzione per creare suoni in Swift (puoi usare questa funzione dove desideri creare suoni).

Per prima cosa aggiungi SpriteKit e 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

Questo codice funziona per me:

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

Per 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 ecco come lo faccio.

{

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

Non potresti semplicemente import AVFoundationselezionare il lettore audio ( var audioPlayer : AVAudioPlayer!) e riprodurre il suono? ( 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] )
    }    

}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.