我想我可以AVAudioPlayer
用来播放声音,但是,我需要的只是播放一个短的声音,我不需要任何循环或对音量等进行细粒度控制。
是否有捷径可寻?
其他每一个答案都会泄漏内存(除非为其中一个答案启用了 ARC)......奇怪的是,最初标记为正确的答案retainCount
无缘无故地被调用。
如果你有alloc/init
什么东西,它需要被释放(除非你使用 ARC)。
如果你打电话AudioServicesCreateSystemSoundID()
,你必须处理产生的声音。
请参阅音频 UI 声音示例。
基本上:
@interface MyClass:UI*ViewController // fixed
{
SystemSoundID mySound;
}
@implementation MyClass
- (void) viewDidLoad {
[super viewDidLoad];
AudioServicesCreateSystemSoundID(.... URL ...., &mySound);
}
- (void) playMySoundLikeRightNowReally {
AudioServicesPlaySystemSound(mySound);
}
- (void) dealloc {
AudioServicesDisposeSystemSoundID(mySound);
[super dealloc]; // only in manual retain/release, delete for ARC
}
@end
为了完整性:
添加 AudioToolbox.framework
#import <AudioToolbox/AudioToolbox.h>
对于短的声音片段(少于 30 秒),有一个 SystemSounds 库,非常好。
优点:您不需要单独管理音量设置。声音在单独的线程中播放,音频剪辑的加载和播放速度非常快。简而言之,您将此剪辑视为另一个系统声音。
缺点:您无法提供单独的音频控制设置。它与系统声音的设置有关。你不能玩超过 30 秒。您可能无法应用任何声音过滤器来增强音频效果。
肯定有更多的优点和缺点,但这些是我能想到的,从我的脑海中浮出水面。
使用这个导入:<AudioToolbox/AudioToolbox.h>
添加 AudioToolbox 框架,然后调用下面的方法,如 [self playSound],无论你想在哪里播放剪辑。
-(void) playSound {
NSString *soundPath = [[NSBundle mainBundle] pathForResource:@"changeTrack" ofType:@"aif"];
SystemSoundID soundID;
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath: soundPath], &soundID);
AudioServicesPlaySystemSound (soundID);
[soundPath release];
}
这里的其他答案使用了 Objective-C,所以我在这里提供了一个 Swift 版本。Swift 使用自动引用计数(ARC),所以我不知道这个答案有任何内存泄漏问题(正如在接受的答案中所警告的那样)。
AudioToolbox
当您不需要太多控制它们的播放方式时,您可以使用该框架播放短声音。
以下是您将如何设置它:
import UIKit
import AudioToolbox
class PlaySoundViewController: UIViewController {
var soundURL: NSURL?
var soundID: SystemSoundID = 0
@IBAction func playSoundButtonTapped(sender: AnyObject) {
let filePath = NSBundle.mainBundle().pathForResource("yourAudioFileName", ofType: "mp3")
soundURL = NSURL(fileURLWithPath: filePath!)
if let url = soundURL {
AudioServicesCreateSystemSoundID(url, &soundID)
AudioServicesPlaySystemSound(soundID)
}
}
}
笔记:
yourAudioFileName.mp3
(或.wav
等)添加到您的项目中。import AudioToolbox
通过导入AVFoundation
框架,您可以使用AVAudioPlayer
. 它适用于短音频剪辑和长歌曲。与使用 AudioToolbox 方法相比,您还可以更好地控制播放。
以下是您将如何设置它:
import UIKit
import AVFoundation
class PlaySoundViewController: UIViewController {
var mySound: AVAudioPlayer?
// a button that plays a sound
@IBAction func playSoundButtonTapped(sender: AnyObject) {
mySound?.play() // ignored if nil
}
override func viewDidLoad() {
super.viewDidLoad()
// initialize the sound
if let sound = self.setupAudioPlayerWithFile("yourAudioFileName", type: "mp3") {
self.mySound = sound
}
}
func setupAudioPlayerWithFile(file: NSString, type: NSString) -> AVAudioPlayer? {
let path = NSBundle.mainBundle().pathForResource(file as String, ofType: type as String)
let url = NSURL.fileURLWithPath(path!)
var audioPlayer: AVAudioPlayer?
do {
try audioPlayer = AVAudioPlayer(contentsOfURL: url)
} catch {
print("Player not available")
}
return audioPlayer
}
}
笔记:
import AVFoundtation
并添加yourAudioFileName.mp3
到您的项目中。最近,我用这段代码播放了简短的 mp3 音频,效果很好:-
在@implementation 下方声明
NSString *path;
NSURL *url;
//where you are about to add sound
path =[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"quotes_%d",soundTags] ofType:@"mp3"];
url = [NSURL fileURLWithPath:path];
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:NULL];
[player setVolume:1.0];
[player play];
//just add AVFoundation framework
我用这段代码在 iOS 上播放了一个简短的 aiff-sound
#import <AudioToolbox/AudioServices.h>
SystemSoundID completeSound;
NSURL *audioPath = [[NSBundle mainBundle] URLForResource:@"downloadCompleted" withExtension:@"aiff"];
AudioServicesCreateSystemSoundID((CFURLRef)audioPath, &completeSound);
AudioServicesPlaySystemSound (completeSound);
希望这可以帮助。
简单干净的 Swift 3 版本
我喜欢更多地控制我的声音,所以我使用了 AVFoundation。
import AVFoundation
class TodayViewController: UIViewController {
var clink: AVAudioPlayer?
var shatter: AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
// initialize the sound
shatter = setupAudioPlayer(withFile: "shatter", type: "wav")
clink = setupAudioPlayer(withFile: "clink", type: "wav")
}
func setupAudioPlayer(withFile file: String, type: String) -> AVAudioPlayer? {
let path = Bundle.main.path(forResource: file, ofType: type)
let url = NSURL.fileURL(withPath: path!)
return try? AVAudioPlayer(contentsOf: url)
}
func onClick() {
clink?.play()
}
}
确保将声音文件添加到项目中并导入 AVFoundation。
我的回答是比尔的回答,但我在没有 init 或 dealloc 的情况下使用它,并在播放后释放声音:
- (void)playSound:(NSURL *)url
SystemSoundID ssID = 0;
AudioServicesCreateSystemSoundID((CFURLRef)url, &ssID);
AudioServicesAddSystemSoundCompletion(ssID, NULL, NULL, (AudioServicesSystemSoundCompletionProc)MyAudioServicesSystemSoundCompletionProc, NULL);
AudioServicesPlaySystemSound(ssID);
//AudioServicesDisposeSystemSoundID(ssID);
}
void MyAudioServicesSystemSoundCompletionProc (SystemSoundID ssID, void *clientData) {
AudioServicesDisposeSystemSoundID(ssID);
}
import AudioToolbox
func playSoundEasy(note : String) {
var soundURL: NSURL?
var soundID: SystemSoundID = 0
let filePath = Bundle.main.path(forResource: note, ofType: "wav")
soundURL = NSURL(fileURLWithPath: filePath!)
if let url = soundURL {
AudioServicesCreateSystemSoundID(url, &soundID)
AudioServicesPlaySystemSound(soundID)
}
}
这是一种快速清理方法,您可以复制并在您的应用中使用:
-(BOOL) playSoundFXnamed: (NSString*) vSFXName Loop: (BOOL) vLoop
{
NSError *error;
NSBundle* bundle = [NSBundle mainBundle];
NSString* bundleDirectory = (NSString*)[bundle bundlePath];
NSURL *url = [NSURL fileURLWithPath:[bundleDirectory stringByAppendingPathComponent:vSFXName]];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
if(vLoop)
audioPlayer.numberOfLoops = -1;
else
audioPlayer.numberOfLoops = 0;
BOOL success = YES;
if (audioPlayer == nil)
{
success = NO;
}
else
{
success = [audioPlayer play];
}
return success;
}
然后使用:
[self playSoundFXnamed:@"someAudio.mp3" Loop: NO];
如果你要循环,那么你需要把你AVAudioPlayer *audioPlayer
带到你的课堂上才能停止声音。如果你只是想要一个简短的声音,你不会这样做。
使用 ARC……我从来没有对 NSError 做过任何事情,所以如果你喜欢就使用它……
很多答案令人困惑,有些正在使用AudioToolbox
框架,与框架不同AVAudioFoundation
......这就是我所做的。在.h
文件中,我将此代码放入:
@property (nonatomic, retain) AVAudioPlayer *player;
此代码声明了一个名为“player”的音频播放器。在.m
文件中,在您的@implementation
声明下,添加@synthesize player
. 这综合了该player
属性。
在您想要的任何功能中,通过添加这行代码将您的声音绑定到播放器,其中yourSound
是声音文件的名称,并且aif
是您的文件扩展名:
player = [[AVAudioPlayer alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"yourSound" withExtension:@"aif"] error:nil]
我知道 Apple 文档说要声明一个字符串和一个 NSURL,但是如果你将它组合成一行,那么你以后就不必处理它了。此外,由于这是您ViewController.m
文件中的一个属性,因此您不必继续设置该player
对象以与您的声音相关联。
其他答案还包括使用 a SystemSoundID
,但这也施加了一些限制,例如“文件不能超过 30 秒”、“它必须采用特定格式”和作品。这样,它可以一次播放多个声音(如果您正在开发音板),并且更容易创建声音。
要真正播放您的声音,请插入这一行(是的,这真的很简单):
[player play]
如果您使用 ARC,则无法手动处理播放器,因为系统会为您处理。如果您是开发新手并且使用的是最新版本的 Xcode,那么您启用了 ARC。如果由于某种奇怪的原因您不这样做,那么用于处理所使用资源的代码player
是:
[player release]
请参考简单的iOS音频播放
- (void)playSound
{
SystemSoundID soundId;
// NSURL *soundURL = [[NSBundle mainBundle] URLForResource:@"sample"
// withExtension:@"caf"];
// AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL, &soundId);
NSString *path = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"mp3"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path], &soundId);
AudioServicesAddSystemSoundCompletion(soundId,
NULL,
NULL,
systemAudioCallback,
NULL);
AudioServicesPlaySystemSound(soundId);
//AudioServicesPlayAlertSound(soundId);
}
- (void) systemAudioCallback(SystemSoundID soundId, void *clientData)
{
AudioServicesRemoveSystemSoundCompletion(soundId);
AudioServicesDisposeSystemSoundID(soundId);
}
查看 systemsound 以播放短音频文件
包括音频工具箱框架
并创建
systemsoundid 对象
NSString *soundPath = [[NSBundle mainBundle] pathForResource:file ofType:@"aiff"];
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath: soundPath], &soundID);
AudioServicesPlaySystemSound (soundID);