在 macOS 上播放声音

Posted

技术标签:

【中文标题】在 macOS 上播放声音【英文标题】:Playing a sound on macOS 【发布时间】:2016-12-10 13:07:31 【问题描述】:

我喜欢在我的应用中播放声音。我找到了很多示例,也可以在 Swift 3 上编译和运行它们。但它们始终适用于 ios。在我的应用程序中实现此代码时,AVAudioSession 保持未定义。我需要做什么? OSX 有什么不同吗?

import AVFoundation
...
    var audioPlayer = AVAudioPlayer()
    func PlaySound( ) 
        let alertSound = URL(fileURLWithPath: Bundle.main.path(forResource: "Sound", ofType: "mp3")!)
        do 
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
         catch _ 
        
        do 
            try AVAudioSession.sharedInstance().setActive(true)
         catch _ 
        
        do 
            audioPlayer = try AVAudioPlayer(contentsOf: alertSound)
         catch _
        
        audioPlayer.prepareToPlay()
        audioPlayer.play()
    

【问题讨论】:

【参考方案1】:

Swift 3 / 4 / 4.2 / 5 - 最简单的解决方案:

NSSound(named: "customSound")?.play()

【讨论】:

本话题与NSSound无关。 @ElTomato 不是吗? The NSSound class provides a simple interface for loading and playing audio filesdeveloper.apple.com/reference/appkit/nssound 阅读原文。发布此主题的人指的是 AVAudioSession,而不是 NSSound。 主题作者并没有要求只坚持 AV* 类。所以,NS* 类的答案也是有效的。 我可以用你的方法改变音量、音高和速度等因素吗?【参考方案2】:

我将以下函数与 Swift 3 和一个 Cocoa 项目结合使用。

import AVFoundation

func playSound(file:String, ext:String) -> Void 
    let url = Bundle.main.url(forResource: file, withExtension: ext)!
    do 
        let player = try AVAudioPlayer(contentsOf: url)
        player.prepareToPlay()
        player.play()
     catch let error 
        print(error.localizedDescription)
    

// 用法 //

playSound(file: "sound", ext: "caf") // where the file name is sound.caf.

确保在您选择 Xcode 项目中的音频文件时,目标成员资格复选框已打开。

【讨论】:

对我来说也是:“使用未解析的标识符”。我已经导入了AVFoundation【参考方案3】:

El Tomato 答案的修改版本, 这是我经常用于声音的 swift 4.2 类:

用法:

    /// EXAMPLE 1
    //calling this will create a "bop.m4a" player in memory, and, play it immediately
    MakeSound.shared.playSound("bop.m4a")
    //calling it a second time has a lot less overhead because the player is already in memory
    MakeSound.shared.playSound("bop.m4a")

    ///EXAMPLE 2
    //simply calls the above many times
    MakeSound.shared.playSound(["bop.m4a", "beep.m4a", "bong.m4a"])

    // EXAMPLE 3
    //registers a shorthand, for quick calling
    MakeSound.shared.registerSound(fileName: "bop", fileExtension: "m4a", shortHand: "b")
    //plays using the shorthand, mostly handy because you define the actual file once,
    //and can change the one line of code without having to change every reference
    MakeSound.shared.playSound("b")

和班级:

class MakeSound 
private var players = [String : AVAudioPlayer]()
static var shared = MakeSound()

func playSound(fileName: String, fileExtension: String) 
    if registerSound(fileName: fileName, fileExtension: fileExtension, shortHand: fileName+"."+fileExtension) 
        playSound(fileName+"."+fileExtension)
    


//thought about naming this "playsoundS", but i like it with the same name, makes it easier to type
func playSound(_ shortHands : [String])
    for sh in shortHands
        playSound(sh)
    


///playSound("shorthand") OR playSound("mySound.mp3")
func playSound(_ shortHand : String) 
    if let player = players[shortHand]  
        player.prepareToPlay()
        player.play()
     else 
        if shortHand.contains(".") 
            //going to assume that coder will not send "." as a filepath
            //also going to assume that coder will not send "xyz." as filepath
            var comp = shortHand.components(separatedBy: ".")
            let ext = comp.last!
            comp.removeLast()
            if registerSound(fileName: comp.joined(separator: "."), fileExtension: ext, shortHand: shortHand) 
                playSound(shortHand)
            
         else 
            print("Sound request sent to makesound, no such shorthand, not a valid filename either.")
        
    


///registers a sound with makeSound, and returns a bool based on the success
@discardableResult func registerSound(fileName : String, fileExtension: String, shortHand: String) -> Bool 
    guard let url = Bundle.main.url(forResource: fileName, withExtension: fileExtension) else 
        print("Unable to register sound: \(shortHand). Filepath not valid.")
        return false
    
    do 
        let player = try AVAudioPlayer(contentsOf: url)
        players[shortHand] = player
     catch let error 
        print("Audioplayer \"\(shortHand)\" unable to initialize:\n" + error.localizedDescription)
        return false
    
    return true



现在我承认NSSound 是迄今为止最简单和最直接的方法,但是,我们中的一些人更喜欢AVFoundation,因为我们有更多的控制权。 (讽刺的是,这种控制在我的课堂上被删除了)

【讨论】:

以上是关于在 macOS 上播放声音的主要内容,如果未能解决你的问题,请参考以下文章

多次播放声音的问题

在 MacOS 中网络推送没有声音

在 C、MacOS 中播放哔声

iPhone:如何在 iPod 声音上播放声音?

无法使用 JavaScript 在 iPhone 上播放声音,但可以在 Android 上播放

如何在本地通知上播放不同的声音文件