AVAudioPlayer无法播放声音

8

我已经进行过搜索,我相信我的问题是非常独特的。我知道当使用AVAudioPlayer时模拟器5.1存在Bug,但这并不是我的问题。我正在iOS 5.1设备上运行。

这是我的头文件:

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <AVFoundation/AVAudioPlayer.h>

-(IBAction)pushBell;

@end

我的实现文件如下:

#import "BellViewController.h"

@interface BellViewController ()

@end

@implementation BellViewController

-(IBAction)pushBell {

    NSString *soundPath =[[NSBundle mainBundle] pathForResource:@"bell1" ofType:@"caf"];
    NSURL *soundURL = [NSURL fileURLWithPath:soundPath];
    NSError *error;

    AVAudioPlayer *theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:&error];
    [theAudio setDelegate:self];
    [theAudio setNumberOfLoops:0];
    [theAudio play];

}

@end

我在.xib中有一个按钮,用于播放文件。
为了确保我正确引用了音频文件,我特意输入了错误的文件名,确实出现了异常。为了确保文件可以播放,我将其邮件发送给自己,在设备上进行了测试。
当我点击按钮时,听不到任何声音。没有错误提示,我不知道问题出在哪里。
更多信息: iPhone 4,iOS 5.1 Xcode 4.3.2 音频大小约为700kbps,使用afconvert从大型.wav文件转换为.caf格式。

你用调试器逐步执行了吗?你检查了NSError的内容吗? - hooleyhoop
6个回答

20

已解决。

1. 检查你的文件是否已经添加到 Build Phases 中的 "Copy Bundle Resources" 中。 Copy Bundle Resources

2. ViewController.m

#import <AVFoundation/AVAudioPlayer.h>

@interface ViewController ()
@property (nonatomic, strong) AVAudioPlayer *theAudio;
- (IBAction)pushBell;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSString *soundPath =[[NSBundle mainBundle] pathForResource:@"beep-beep" ofType:@"caf"];
    NSURL *soundURL = [NSURL fileURLWithPath:soundPath];

    NSError *error = nil;
    self.theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:&error];
}

- (IBAction)pushBell {
    [self.theAudio play];
}

3.- 在 Interface Builder 中将 IBAction 连接到您的按钮上。

完成。


1
有趣的是,作为WAV文件,无论它们是否出现在Bundle Resources中,这些文件都会播放。作为CAF文件,除非添加,否则它们不会播放。 - jowie
1
我还注意到,当您将WAV文件添加到Xcode(4.4)项目中时,它会自动选中“添加到目标”复选框。对于CAF文件,此复选框默认为关闭状态。我不知道他们为什么这样做,这经常让我感到困惑!还有其他人遇到过这种情况吗? - jowie
1
谢谢,你救了我很多麻烦。这是2016年 - 仍然没有修复! - Yimin Rong

19
这是我的问题,所以我在这里发布它,以防有人需要!信不信由你,在iOS 5.1的iPad 2上,似乎存在一个错误,即如果您将侧面开关设置为静音并且已静音,则将侧面开关设置为锁定旋转,AVAudioPlayer声音将不会播放,除非通过耳机!因此,我必须打开“设置”应用程序,将开关改回静音,然后取消静音iPad,将其切换回锁定旋转模式,然后我的应用程序才能正常工作。

谢谢Jowie,我浪费了很多时间进行调试,以确保我正确地将路径设置到AVPlayer对象。很高兴学习到操作系统也会出现bug。 - Dinakar
是的...iOS很棒,但还远非完美 ;) - jowie
谢谢!在凌晨1点,这节省了我至少几个小时的时间,让我不用再试图在iOS 5和iPad 1上解决这个问题。 - Yan
我不确定当时是否错过了,但如果您的侧边开关设置为锁定旋转,则在控制中心中可用静音功能,反之亦然。这在iOS 5.1上也可能是这种情况,但当时我没有意识到。 - jowie
我的天啊,这也困扰了我。在 iPhone 6 上。当通过其他应用程序播放声音时(我录制的视频然后立即播放)。 - escapecharacter

16

你的theAudioAVAudioPlayer在开始播放之前就被释放了(因为它是在pushBell方法内作为局部变量分配的)。

将代码更改为:

头文件:

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <AVFoundation/AVAudioPlayer.h>

@interface BellViewController:UIViewController

@property (nonatomic, strong) AVAudioPlayer *theAudio;

-(IBAction)pushBell;

@end

实现文件:

#import "BellViewController.h"

@implementation BellViewController

@synthesize theAudio = _theAudio;

- (void)viewDidLoad {

    if (!theAudio) {

        NSString *soundPath =[[NSBundle mainBundle] pathForResource:@"bell1" ofType:@"caf"];
        NSURL *soundURL = [NSURL fileURLWithPath:soundPath];
        NSError *error;

        _theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:soundURL error:&error];
        [self.theAudio setDelegate:self];
        [self.theAudio setNumberOfLoops:0];

        [self.theAudio prepareToPlay];
    }
}

-(IBAction)pushBell {

   [self.theAudio play];
}

@end
假设 BellController 是一个 UIViewController,如果它是其他类型的类,请相应地修改代码。

2
“音频无法播放”在我的编程生涯中似乎出现了很多次,每次都是不同的原因!而这一次是最近遇到的...开启ARC后,“alloc init”不足以确保对象留在内存中!谢谢 :) - jowie

4
我认为这是一个内存问题,你应该将 AVAudioPlayer *theAudio 实例化为全局类对象,并在 init 方法中进行初始化。然后只需在 -(IBAction)pushBell 方法中运行 [theAudio play]; 方法即可。
我曾回答过一个与播放系统声音相关的类似问题(实际上就是你正在尝试解决的问题),请查看我的响应,它在底部: Couldn't play system sound after switching to iOS 5 顺便说一下,考虑将铃声作为系统声音播放,AVAudioPlayer 更适合播放音乐,而不是铃声和效果声音。
希望对你有所帮助。

2

我同意hooleyhoop的观点。尝试一下

NSLog(@"%@", error.userInfo) 

查看输出内容。

另一个选择是在viewDidLoadinitWithNib中设置播放器对象,并将其存储为对象的属性。这样,您可以使用类似于[self.theAudio prepareToPlay];的东西。

为了避免每次按下按钮时加载音频,如果音频质量很高,则可以节省一些时间。然后只需在IBAction方法中调用[self.theAudio play];

抱歉,如果这个答案有点粗糙 - 在iPad上打字,所以无法正确检查。


1

由于它可能正在从URL缓冲,所以您应该给它一些时间来准备发音。

代码:

[theAudio prepareToPlay];

[self performSelector:@selector(playMusic) withObject:nil afterDelay:3.0];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接