2011-11-04 106 views
52

我正在研究一个需要使用AVFoundation框架播放一些声音的iOS应用程序。在Xcode 4的工作空间结构,包含两个项目:AVAudioPlayer不播放任何声音

  • 工作区
    • 应用程序本身(主体工程)
    • 一个实用程序库

建立实用程序库后,导致在主应用程序中使用静态库作为框架。

因此,当试图通过使用下面的代码在主应用程序内播放声音时,它按预期工作。

NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; 
NSString *path = [NSString stringWithFormat:@"%@/sound.mp3", resourcePath]; 

NSURL *url = [NSURL fileURLWithPath:path]; 
NSError *error = nil; 

AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url 
                    error:&error]; 
[audioPlayer play]; 

相反,试图精确地发挥效用库中相同的声音(或任何其他)使用与上述相同的代码的时候,没有任何声音都玩过,即使错误是audioPlayer属性值是正确的(通道数量,持续时间)。

我确定AVFoundation框架在两个项目中。

而且,我的类使用AVAudioPlayerDelegate协议,实现了这两种方法:

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag; 
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error; 

这些方法都试图播放声音后调用。

如果我使用AudioToolbox框架来代替,那么它会播放声音。但我有兴趣使用AVFoundation有几个原因。

有什么想法发生了什么?我是否错过了AVFoundation?它可能与在静态库中使用AVAudioPlayer有关吗?

在此先感谢。

+0

你能告诉我们什么是错误变量输出? AVAudioPlayer * audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error]; –

+0

@Maudicus,正如我所说,播放声音后错误为零。我找到了解决方案,它与我没有提及但没有考虑的事情有关:我正在编译ARC。 ARC向音频播放器插入一个释放调用,所以在离开创建它的方法之后,释放调用被解除分配,如[在这里]解释的那样(http://stackoverflow.com/questions/7692866/avaudioplayer-stops-playing-immediately -with-arc) – msoler

+0

对不起,我复制了你的代码,它工作。错过了关于错误的陈述是零。我很高兴它解决了 –

回答

139

我找到了解决方案,它与我没有提及但没有考虑的事情有关:我正在使用自动引用计数(ARC)进行编译。

ARC向音频播放器插入释放呼叫,因此它在离开创建方法后立即释放。它与AVAudioPlayer无关,但与ARC。

为了解决这个问题,我刚创建了一个AVAudioPlayer属性来处理声音,以便它不再被ARC发布。至少,这个类在发布之前不会被释放。

有关ARC的更多信息,请参阅Automatic Reference Counting: Zeroing Weak References,详细说明为什么出现此问题。

+1

这在我以前发生过,与AVAudioPlayer没有任何关系,甚至在AVAudioPlayer出现问题时我甚至忘了这个解决方案,而这个问题莫名其妙地不能播放声音。关于ARC的好记事! –

+0

我知道这是一个古老的话题,而不是创造一个新的问题提出同样的问题,你能像我五岁那样向我解释这是什么意思?我做了一个iOS应用程序,我有一个提交按钮,当计算完成时,它会播放声音。我首先做了一个简化的版本作为一个OS X应用程序运行良好,但作为一个iOS应用程序,使用AVAudioPlayer而不是NSSound或它不起作用,50%的时间会导致应用程序崩溃。 –

+0

@JonathanWeinraub对不起,但很难说没有看到任何代码。您的崩溃和AVAudioPlayer问题可能与几个原因有关。 – msoler

16

你配置了AVAudioSession吗?

我有一个类似的问题,使用这样的固定它:

AVAudioSession *audioSession = [AVAudioSession sharedInstance]; 
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:NULL]; 

[audioSession setCategory:AVAudioSessionCategoryPlayback error:NULL]; 

希望它能帮助。

+0

我已经回答了Madicus这件事,但是我没有把它作为对我的问题的直接回答,因为我不能(可能是因为StackOverflow在第一个小时/天内不允许自动应答)。官方的答案现在在这里。 :) 不管怎么说,还是要谢谢你! – msoler

+0

将其添加到您的viewDidLoad方法中。在录制之后但在播放之前设置会话不起作用。此外,没有设置会话,它在模拟器中工作,但不在设备上。 –

33

是的,绝对; ARC也是我的代码的原因。

我介绍了一个属性:

@property (strong, nonatomic) AVAudioPlayer *audioPlayer; 

,这让一切都迎刃而解。

+0

很好的回答! –

+0

你还在做alloc initWithContentsOfUrl吗? –

24

使用这一点,肯定会工作....

AVAudioSession *session = [AVAudioSession sharedInstance]; 
[session setCategory:AVAudioSessionCategoryPlayback error:nil]; 

NSURL *url = [NSURL fileURLWithPath:@"path of the sound file :)"]; 
_player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; 
[_player setDelegate:self]; 
[_player prepareToPlay]; 
[_player play]; 
+3

'AVAudioSession'为我做了诀窍。没有它,我只能在模拟器中播放声音,而不能在设备上播放。 –

+1

谢谢你'prepareToPlay' – Alexmelyon

+0

这对我有很大的帮助! –

-1

请留一段在页面上时间,我面临同样的问题。并使用睡眠来解决它。


NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] 
              pathForResource:@"sounds-1027-are-you-kidding" 
              ofType:@"mp3"]]; 
     AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] 
             initWithContentsOfURL:url 
             error:nil]; 
     [audioPlayer play]; 
     sleep(2); 

+1

尽量避免使用'sleep','dispatch_after'是一个更好的选择。 –

+0

这段代码将使audioPlayer实例活着2秒。这使得代码依赖于音频文件的长度,并且不适用于任何音频文件。此外,它会暂停2秒的调用线程,在大多数情况下,它不会是所需的行为。 – msoler

+0

这是一个骇人但富有创意的解决方案,它有其优点和缺点。在我的情况下,我试图提醒用户注意新信息。在播放警报声音的同时,冻结应用程序中的所有活动一秒钟,实际上是获得用户注意力的好方法。所以这实际上符合我的需求。它不值得投票。 –

0

迅速解决:

import AVFoundation 

    // define your player in class 
    var player = AVAudioPlayer() 

    override func viewDidLoad() { 
    super.viewDidLoad() 
    } 
0

我有同样的问题。我曾在.h文件中加入下面一行解决它:

@property (strong, nonatomic) AVAudioPlayer *audioPlayer; 

而且在.m文件:在类范围内声明

NSError *error; 
NSString *soundFilePath = [NSString stringWithFormat:@"%@/dancepechance.mp3", 
           [[NSBundle mainBundle] resourcePath]]; 
    NSURL *url = [NSURL fileURLWithPath:soundFilePath]; 
    self.audioPlayer = [[AVAudioPlayer alloc] 
            initWithContentsOfURL:url 
            error:&error]; 
    NSLog(@"Error %@",error); 
    [self.audioPlayer prepareToPlay]; 
    [self.audioPlayer play]; 
2

即使有audioPlayer变种,它不会玩。 至少在iOS 10 iPhone 5c物理设备上。

play()结果是true所以没有错误出现。

不得不添加此(斯威夫特3,4),现在它正确播放声音。

let session = AVAudioSession.sharedInstance() 
try! session.setCategory(AVAudioSessionCategoryPlayback) 
相关问题