Szybkie tworzenie i odtwarzanie dźwięku

104

Chcę więc stworzyć i odtworzyć dźwięk w języku Swift, który będzie odtwarzany po naciśnięciu przycisku. Wiem, jak to zrobić w Objective-C, ale czy ktoś wie, jak to zrobić w Swift?

Tak wyglądałoby w przypadku Objective-C:

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

A potem, żeby to zagrać, zrobiłbym:

AudioServicesPlaySystemSound(Explosion);

Czy ktoś wie, jak mogłem to zrobić?

Jacob Banks
źródło
2
Źródłem tego pytania jest wywoływanie funkcji C z poziomu swift. To też mnie ciekawi.
67cherries
ta linia może utworzyć adres URL dźwięku: var url :NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("mysoundname", ofType: "wav"))
Connor,
@connor Dzięki, że działa, ale co z AudioServicesCreateSystemSoundID
Jacob Banks,
Nie jestem co do tego pewien. Byłem w stanie wywołać api obiektywne-c tylko ze swift.
Connor

Odpowiedzi:

84

Oto fragment kodu, który dodałem do FlappySwift, który działa:

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
źródło
Wydawałoby się, że możesz po prostu zadeklarować audioPlayer tuż przed jego użyciem, ale to nie zadziałało dla mnie w symulatorze. Musiałem to zadeklarować u góry, tak jak ty.
Adam Loving
@Adam Kochanie możesz zadeklarować audioPlayer tuż przed jego użyciem, ale upewnij się, że wywołujesz funkcję play () w tej samej funkcji, w której ją zadeklarowałeś (w przeciwieństwie do dobrej odpowiedzi) Ponadto zadeklarowałbym coinSoundi audioPlayerz letzamiast, varponieważ nie chcesz zmienić te obiekty w późniejszym czasie.
fat32
3
W Swift 2 pamiętaj, aby uruchomić go w ten sposób, do { (player object) } catch _ { }albo pojawi się błąd! :)
ParisNakitaKejser
1
Ale uwaga! Wstrzyma muzykę w tle z odtwarzacza. Aby zagrać krótki dźwięk, musimy użyć odpowiedzi poniżej
Nikita Pronchik
Głos przeciw - to nie jest dźwięk systemowy, używa innego interfejsu API
William Entriken
119

Jest to podobne do innych odpowiedzi, ale być może trochę bardziej „szybkie”:

// 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);
}

Zauważ, że jest to trywialny przykład odtwarzający efekt kodu w pytaniu. Musisz się upewnić import AudioToolbox, a ogólny wzorzec dla tego rodzaju kodu polegałby na ładowaniu dźwięków podczas uruchamiania aplikacji, zapisywaniu ich SystemSoundIDgdzieś w zmiennych instancji, używaniu ich w całej aplikacji, a następnie wywołaniu, AudioServicesDisposeSystemSoundIDgdy skończysz z nimi.

Matt Gibson
źródło
1
Musisz także zaimportować AudioToolbox
Brody Robertson
Czy musisz AudioServicesDisposeSystemSoundID(mySound)później zadzwonić, aby zwolnić pamięć? jeśli zrobisz to od razu, dźwięk w zasadzie nie jest odtwarzany (jest natychmiast czyszczony), więc zrobiłem dispatch_afteri wyczyściłem go 10 sekund później.
owenfi
@owenfi Fragment kodu w mojej odpowiedzi to po prostu Swiftowy odpowiednik fragmentu kodu w pytaniu. Ogólnym wzorcem dla usług AudioServices jest ładowanie dźwięków po uruchomieniu aplikacji, używanie ich w całej aplikacji i usuwanie ich po zamknięciu aplikacji, ale każda aplikacja będzie inna.
Matt Gibson,
@ozgur Dlaczego używasz nieaktualnej wersji Xcode? Będziemy musieli wiedzieć, co oznacza „nie działa” i prawdopodobnie lepiej będzie, jeśli zadasz nowe pytanie, jeśli masz konkretne problemy.
Matt Gibson,
właściwie jest to jedyny sposób na odtworzenie pliku wav. Wygląda na to, że AVPlayer nie działa.
Haitao
18

Poręczne rozszerzenie 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)
        }
    }
}

Następnie import AudioToolboxmożesz dzwonić z dowolnego miejsca w aplikacji (pamiętaj o tym )

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

aby odtworzyć „sound.mp3”

Aleix Pinardell
źródło
Kiedy wykonuję to w grze SpriteKit, zawsze występuje opóźnienie przed odtworzeniem dźwięku. Nawet jeśli wsadzę to do środka DispatchQueue.global(qos: .userInitiated).async {}.
Jon Kantner
NSBundlezostał zastąpiony przez Bundle, użyj Bundle.main.url(forResource: fileName, withExtension: fileExtension)zamiast tego
diachedelic
14

Tworzy to SystemSoundIDz pliku o nazwie 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
źródło
Czy próbowałeś skompilować kod? Otrzymuję błąd „Nie można przekonwertować typu wymuszenia„ Niezarządzany <CFURL>! ” aby wpisać „CFString” „z tego wiersza” let soundURL = CFBundleCopyResourceURL (CFBundleGetMainBundle (), „Cha-Ching”, „aiff”, nil) ”
bpolat
Tak, kompiluje się dla mnie. Zobacz github.com/acani/Chats/blob/master/Chats/Chats/…
ma11hew28
2
To powinna być akceptowana odpowiedź, biorąc pod uwagę, że podany przykład Obj-C jest oparty na programie AudioToolBox Framework
eharo2
@JochenBedersdorfer, prawdopodobnie otrzymujesz błąd z powodu automatycznego zarządzania pamięcią obiektami Core Foundation.
XCool
8

Z klasą i 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)
    }
}

Stosowanie:

testSound = Sound(name: "test", type: "caf")
testSound.play()
karimhossenbux
źródło
2
Uwielbiam tę odpowiedź. Również dlatego, że jest to dźwięk systemowy, nie otrzymuję komunikatu systemowego, który AVAudioPlayer rzuca w konsoli dla xcode 8.
TPot
proszę o pomoc, robię to samo, dźwięk jest odtwarzany, ale głośność jest zbyt niska. nie słychać
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.
źródło
To AVAudioPlayer (contentOf: soundURL) w nowoczesnym Swift
pudełku
5

Ten kod działa dla mnie. Użyj Try and Catch dla 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
źródło
4
var mySound = NSSound(named:"Morse.aiff")
mySound.play()

„Morse.aiff” to dźwięk systemowy OSX, ale jeśli po prostu klikniesz „named” w XCode, będziesz mógł zobaczyć (w panelu QuickHelp), gdzie ta funkcja wyszukuje dźwięki. Może znajdować się w folderze „Pliki pomocnicze”

philippe
źródło
4
Pytanie dotyczy iOS.
rmaddy
Rzeczywiście ... Nie mogłem tego zrobić w symulatorze. Jak dotąd brak dokumentu
philippe
4

Zgodnie z nowym Swiftem 2.0 powinniśmy używać do try catch. Kod wyglądałby tak:

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
źródło
3

to działa ze 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
źródło
2
Proszę, wyjaśnij swój kod. Odpowiedzi zawierające tylko kod są mniej wartościowe niż wyjaśnienia.
Vincent
@Vincent +1, właściwie się zastanawiam i operator. Może to odnosić się do dźwięku i pamięci.
elia
musisz dodać import AudioToolbox, a następnie dodać powyższy kod
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
źródło
2

Zobaczmy bardziej aktualne podejście do tego pytania:

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
źródło
1
Kod działa dobrze na Swift 4, ale najwyraźniej emitowany dźwięk nie podąża za głośnością mediów
David Vargas
1

Rozwiązanie Matta Gibsona zadziałało dla mnie, oto wersja 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
źródło
1

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

lub

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

}
}

źródło
1

pracuje w 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
źródło
1

Przykład szybkiego kodu :

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);
    }
}
Paweł
źródło
Dodaj więcej szczegółów na temat tego, dlaczego ten kod jest pomocny.
Berendschot,
1

Możesz spróbować tego w 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
źródło
1

swift 4 i 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
źródło
Nie tylko wysyłaj kod - wyjaśnij, do czego służy! stackoverflow.com/help/how-to-answer
Nino Filiu
proszę odnieść się do pytania tego postu. Możesz znaleźć swoją odpowiedź! dziękuję @NinoFiliu
Gulsan Borbhuiya
0

Użyj tej funkcji, aby uzyskać dźwięk w języku Swift (możesz użyć tej funkcji, jeśli chcesz uzyskać dźwięk).

Najpierw dodaj SpriteKit i 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
źródło
0

Ten kod działa dla mnie:

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
źródło
0

Dla 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 何 一 非
źródło
0

Swift 3 Oto jak to zrobić.

{

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)

        }
    }

źródło
0

Nie mógłbyś po prostu import AVFoundationwybrać odtwarzacza audio ( var audioPlayer : AVAudioPlayer!) i odtworzyć dźwięk? ( let soundURL = Bundle.main.url(forResource: "sound", withExtension: "wav")

BoeingLikesToDab
źródło
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
źródło