สร้างและเล่นเสียงได้อย่างรวดเร็ว


104

สิ่งที่ฉันต้องการทำคือสร้างและเล่นเสียงอย่างรวดเร็วซึ่งจะเล่นเมื่อฉันกดปุ่มฉันรู้วิธีทำใน Objective-C แต่มีใครรู้วิธีใน Swift บ้าง?

มันจะเป็นเช่นนี้สำหรับ Objective-C:

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

จากนั้นในการเล่นฉันจะทำ:

AudioServicesPlaySystemSound(Explosion);

มีใครรู้บ้างว่าฉันทำได้อย่างไร?


2
รากของคำถามนี้คือวิธีการเรียกใช้ฟังก์ชัน C จาก swift ฉันอยากรู้เกี่ยวกับเรื่องนี้ด้วย
67cherries

บรรทัดนี้สามารถสร้าง url เสียง: var url :NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("mysoundname", ofType: "wav"))
Connor

@connor ขอบคุณที่ใช้งานได้ แต่สิ่งที่เกี่ยวกับ AudioServicesCreateSystemSoundID
Jacob Banks

ฉันไม่แน่ใจเกี่ยวกับเรื่องนั้น ฉันสามารถเรียกว่า objective-c api จาก swift เท่านั้น
Connor

คำตอบ:


84

นี่คือรหัสเล็กน้อยที่ฉันได้เพิ่มลงใน FlappySwift ที่ใช้งานได้:

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

}

ดูเหมือนว่าคุณจะสามารถประกาศ audioPlayer ได้ก่อนใช้งาน แต่นั่นไม่ได้ผลสำหรับฉันในโปรแกรมจำลอง ฉันต้องประกาศที่ด้านบนเหมือนที่คุณทำ
Adam Loving

@Adam รักคุณสามารถประกาศ Audioplayer ขวาก่อนที่จะใช้ แต่ให้แน่ใจว่าคุณเรียกเล่น () ในการทำงานเดียวกับที่คุณประกาศว่ามัน (ตรงข้ามกับคำตอบที่ดี) นอกจากนี้ผมจะประกาศcoinSoundและaudioPlayerมีletแทนvarเนื่องจากคุณไม่ต้องการที่จะ เปลี่ยนวัตถุเหล่านี้ในเวลาต่อมา
fat32

3
ใน Swift 2 อย่าลืมเรียกใช้ด้วยวิธีนี้มิdo { (player object) } catch _ { }ฉะนั้นคุณจะได้รับบั๊ก! :)
ParisNakitaKejser

1
แต่ความสนใจ! มันจะหยุดเพลงพื้นหลังชั่วคราวจากเครื่องเล่น ในการเล่นเสียงสั้นเราต้องใช้คำตอบด้านล่าง
Nikita Pronchik

Downvote - นี่ไม่ใช่เสียงระบบ แต่ใช้ api อื่น
William Entriken

120

คำตอบนี้คล้ายกับคำตอบอื่น ๆ แต่อาจจะมากกว่า "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);
}

โปรดทราบว่านี่เป็นตัวอย่างเล็กน้อยที่จำลองเอฟเฟกต์ของโค้ดในคำถาม คุณจะต้องตรวจสอบให้แน่ใจว่าimport AudioToolboxรวมถึงรูปแบบทั่วไปสำหรับรหัสประเภทนี้คือการโหลดเสียงของคุณเมื่อแอปของคุณเริ่มทำงานบันทึกไว้ในSystemSoundIDตัวแปรอินสแตนซ์ที่ใดที่หนึ่งใช้ในแอปของคุณจากนั้นโทรAudioServicesDisposeSystemSoundIDเมื่อคุณดำเนินการเสร็จสิ้น กับพวกเขา.


1
คุณต้องนำเข้า AudioToolbox
Brody Robertson

คุณต้องโทรAudioServicesDisposeSystemSoundID(mySound)เพื่อเพิ่มหน่วยความจำในภายหลังหรือไม่? ถ้าคุณทำทันทีเสียงโดยทั่วไปไม่เล่น (ได้รับการทำความสะอาดทันที) ดังนั้นฉันจึงทำdispatch_afterและล้างมันใน 10 วินาทีต่อมา
owenfi

@owenfi ส่วนของรหัสในคำตอบของฉันเป็นเพียง Swift ที่เทียบเท่ากับส่วนของรหัสในคำถาม รูปแบบทั่วไปสำหรับ AudioServices คือการโหลดเสียงของคุณเมื่อแอปของคุณเริ่มทำงานใช้งานได้ตลอดทั้งแอปและกำจัดทิ้งเมื่อแอปปิด แต่แต่ละแอปจะแตกต่างกัน
Matt Gibson

@ozgur ทำไมคุณถึงใช้ Xcode เวอร์ชันที่ล้าสมัย เราจำเป็นต้องทราบว่า "ใช้งานไม่ได้" หมายถึงอะไรและคุณอาจจะดีกว่าถ้าคุณถามคำถามใหม่หากคุณมีปัญหาเฉพาะ
Matt Gibson

จริงๆแล้วนี่เป็นวิธีเดียวในการเล่นไฟล์ wav ดูเหมือนว่า AVPlayer จะไม่ทำงาน
Haitao

18

ส่วนขยาย 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)
        }
    }
}

จากนั้นimport AudioToolboxคุณสามารถโทรได้จากทุกที่ในแอป (อย่าลืม)

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

เพื่อเล่น "sound.mp3"


เมื่อฉันดำเนินการสิ่งนี้ในเกม SpriteKit มักจะมีความล่าช้าก่อนที่เสียงจะเล่น แม้ว่าจะใส่ไว้ข้างในDispatchQueue.global(qos: .userInitiated).async {}ก็ตาม
Jon Kantner

NSBundleถูกแทนที่ด้วยBundleใช้Bundle.main.url(forResource: fileName, withExtension: fileExtension)แทน
diachedelic

14

สิ่งนี้สร้างSystemSoundIDจากไฟล์ที่เรียกว่า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
}

คุณพยายามรวบรวมโค้ดหรือไม่? ฉันได้รับข้อผิดพลาด "ไม่สามารถแปลงประเภทของการขยายตัว 'Unmanaged <CFURL>!' เพื่อพิมพ์ "CFString" "จากบรรทัดนี้" ให้ soundURL = CFBundleCopyResourceURL (CFBundleGetMainBundle (), "Cha-Ching", "aiff", nil) "
bpolat

ใช่มันรวบรวมให้ฉัน ดูgithub.com/acani/Chats/blob/master/Chats/Chats/…
ma11hew28

2
นี่ควรเป็นคำตอบที่ได้รับการยอมรับเนื่องจากตัวอย่าง Obj-C ที่ให้ไว้นั้นอ้างอิงจาก AudioToolBox Framework
eharo2

@JochenBedersdorfer คุณอาจได้รับข้อผิดพลาดเนื่องจากวัตถุ Core Foundation ได้รับการจัดการหน่วยความจำโดยอัตโนมัติ
XCool

8

ด้วยคลาสและ 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)
    }
}

การใช้งาน:

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

2
ฉันชอบคำตอบนี้ เนื่องจากเป็นเสียงของระบบฉันไม่ได้รับข้อความระบบที่ AVAudioPlayer พ่นในคอนโซลสำหรับ xcode 8
TPot

โปรดช่วยฉันทำสิ่งเดียวกันเสียงเล่น แต่ระดับเสียงเบาเกินไป ไม่ได้ยิน
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) ใน Swift สมัยใหม่
แกะกล่อง

5

รหัสนี้ใช้ได้กับฉัน ใช้ Try and Catch สำหรับ 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" เป็นเสียงระบบของ OSX แต่ถ้าคุณเพียงคลิกที่ "ชื่อ" ภายใน XCode คุณจะสามารถดู (ในบานหน้าต่าง QuickHelp) ซึ่งฟังก์ชันนี้กำลังค้นหาเสียง สามารถอยู่ในโฟลเดอร์ "ไฟล์สนับสนุน" ของคุณ


4
คำถามเกี่ยวกับ iOS
rmaddy

อันที่จริง ... ไม่สามารถสร้างในเครื่องจำลองได้ ไม่มีเอกสารถึงวันที่
philippe

4

ตาม Swift 2.0 ใหม่เราควรใช้ลองจับ รหัสจะมีลักษณะดังนี้:

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

สิ่งนี้ทำงานร่วมกับ 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
กรุณาอธิบายรหัสของคุณ คำตอบแบบใช้รหัสเท่านั้นมีค่าน้อยกว่าคำอธิบาย
Vincent

@ Vincent +1 ที่จริงฉันสงสัย & ตัวดำเนินการ อาจมีการอ้างอิงระหว่างเสียงและหน่วยความจำ
elia

คุณต้องเพิ่ม AudioToolbox นำเข้าจากนั้นเพิ่มรหัสด้านบน
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

ให้เราดูแนวทางที่อัปเดตเพิ่มเติมสำหรับคำถามนี้:

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
รหัสทำงานได้ดีใน Swift 4 แต่ดูเหมือนว่าเสียงที่ปล่อยออกมาจะไม่เป็นไปตามระดับเสียงของสื่อ
David Vargas

1

โซลูชันของ Matt Gibson ใช้ได้ผลสำหรับฉันนี่คือเวอร์ชัน 3 ที่รวดเร็ว

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

1

สวิฟต์ 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])
    }
}
}

หรือ

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

ตัวอย่างรหัส 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);
    }
}

โปรดเพิ่มรายละเอียดเพิ่มเติมว่าเหตุใดรหัสนี้จึงมีประโยชน์
Berendschot

1

คุณสามารถลองสิ่งนี้ได้ใน 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

รวดเร็ว 4 และ 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()    }

}


อย่าเพิ่งโพสต์รหัส - อธิบายว่ามันทำอะไร! stackoverflow.com/help/how-to-answer
Nino Filiu

โปรดดูคำถามของโพสต์นี้ คุณสามารถหาคำตอบได้! ขอบคุณค่ะ @NinoFiliu
Gulsan Borbhuiya

0

ใช้ฟังก์ชั่นนี้เพื่อสร้างเสียงใน Swift (คุณสามารถใช้ฟังก์ชั่นนี้ในที่ที่คุณต้องการสร้างเสียง)

ขั้นแรกให้เพิ่ม SpriteKit และ 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

รหัสนี้ใช้ได้กับฉัน:

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

สำหรับ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 นี่คือวิธีที่ฉันทำ

{

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

แค่import AVFoundationเลือกเครื่องเล่นเสียง ( var audioPlayer : AVAudioPlayer!) แล้วเล่นเสียงไม่ได้หรือ ( 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] )
    }    

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.