在 macOS 上播放声音
Playing a sound on macOS
我喜欢在我的应用程序中播放声音。我找到了很多例子,也可以在 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()
}
我将以下函数与 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 项目中的音频文件 select 时,请确保目标成员复选框处于选中状态。
Swift 3 / 4 / 4.2 / 5 - 最简单的解决方案:
NSSound(named: "customSound")?.play()
El Tomato 答案的修改版本,
这是我经常用于声音的 swift 4.2 class:
用法:
/// 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:
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
,因为我们有更多的控制权。 (具有讽刺意味的是,在我的 class 中删除了这种控制)
我喜欢在我的应用程序中播放声音。我找到了很多例子,也可以在 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()
}
我将以下函数与 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 项目中的音频文件 select 时,请确保目标成员复选框处于选中状态。
Swift 3 / 4 / 4.2 / 5 - 最简单的解决方案:
NSSound(named: "customSound")?.play()
El Tomato 答案的修改版本, 这是我经常用于声音的 swift 4.2 class:
用法:
/// 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:
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
,因为我们有更多的控制权。 (具有讽刺意味的是,在我的 class 中删除了这种控制)