AVAudioPlayer - 你必须创建一个属性为它工作? (X code) [英] AVAudioPlayer - must you create a property for it to work? (Xcode)

查看:146
本文介绍了AVAudioPlayer - 你必须创建一个属性为它工作? (X code)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是code我用,现在,它不工作(没有任何反应,当我preSS调用此方法的按钮)。 previously,我有audioPlayer一个属性,它的工作(以下所有audioPlayers是self.audioPlayer明显)。问题是,当我试图两次播放声音,这将结束第声音播放。

这是因为我在做声卡和希望的声音,能够重叠也是白搭。我以为我可以只让audioPlayer一个局部变量,而不是一个属性和所有将是确定的,但现在的声音完全不工作,我想不通为什么。在所有的教程我已经找到了AVAudioPlayer,属性制作,但没有人解释为什么。如果这不能工作,做我的替代品必须做出可以重叠的声音?

   - (无效)LoadSound只有:(* NSString的)声音ofType:(* NSString的)类型withDelegate:(BOOL)代表{
NSURL * URL = [NSURL fileURLWithPath:[一个NSBundle mainBundle]
                                     pathForResource:声音
                                     ofType:TYPE]];AVAudioPlayer * audioPlayer = [[AVAudioPlayer页头] initWithContentsOfURL:URL错误:无];
如果(代表)audioPlayer.delegate =自我;
[audioPlayer prepareToPlay]。[audioPlayer播放];
}


解决方案

您需要的属性或伊娃的原因是因为它提供了有力的参考。当使用ARC任何对象没有强大的指针,它是释放公平的游戏,而事实上这就是你所看到的。

您也是正确的,一个 AVAudioPlayer 强大的指针将只允许一个音频播放器在同一时间被引用。

该解决方案,如果你选择继续使用 AVAudioPlayer 是使用某种集合对象持有强引用的所有玩家实例。你可以使用的NSMutableArray 如下所示:

修改我调整了code稍微使播放的声音方法采用的NSString soundName 参数。

  @synthesize audioPlayers = _audioPlayers;
- (NSMutableArray的*)audioPlayers {
    如果(!_audioPlayers){
        _audioPlayers = [[NSMutableArray里的alloc]初始化];
    }
    返回_audioPlayers;
}
- (无效)audioPlayerDidFinishPlaying:(AVAudioPlayer *)成功的球员:(BOOL)标志{
    [self.audioPlayers的removeObject:播放器];
}
- (无效)playSoundNamed:(* NSString的)soundName {
    NSURL * URL = [NSURL fileURLWithPath:[一个NSBundle mainBundle]
                                         pathForResource:soundName
                                         ofType:@WAV]];
    AVAudioPlayer * audioPlayer = [[AVAudioPlayer页头] initWithContentsOfURL:URL错误:无];
    如果(audioPlayer){
        [audioPlayer setDelegate:个体经营];
        [audioPlayer prepareToPlay]。
        [audioPlayer播放];
        [self.audioPlayers ADDOBJECT:audioPlayer];
    }
}

一般的 AVAudioPlayer 是矫枉过正的声音效果/音板的应用程序。为了快速声滴,你可能会发现音频工具箱框架,概述了这个问题。


  

从看系统声音类引用,好像你
  只能一次播放一个声音。


它只能播放一 SystemSoundID 在一个时间。因此,举例来说,如果你有soundOne和soundTwo。你可以玩soundOne而soundTwo播放,但你不能同时播放两种声音的多个实例。


  

什么是能够发挥,可以重叠,而声音的最佳方式
  仍在高效与code和内存的容量?


最好的意见。

如果您需要相同的声音的两个实例同时运行的话,我会说,code在这个答案贴将是code使用。由于这样的事实,同样的声音的每个重叠实例需要创建新的资源,code这样其 audioPlayerDidFinishPlaying:是更容易管理(存储器可以很容易地回收)。

如果相同的声音重叠的情况下,不是一个交易断路器那么我想只用 AudioServicesCreateSystemSoundID()来创建一个实例的每个声音更加高效。

我绝对不会尝试一个按钮,每preSS管理的创建和处置 SystemSoundID 第这会出问题着急。在这种情况下 AVAudioPlayer 是单纯只是可维护性明显的赢家。

This is the code I'm using now, and it's not working (nothing happens when I press the button that calls this method). Previously, I had a property for audioPlayer and it worked (all the audioPlayers below were self.audioPlayer obviously). The problem was that when I tried to play the sound twice, it would end the first sound playing.

This is no good because I'm making a soundboard and want sounds to be able to overlap. I thought I could just make audioPlayer a local variable instead of a property and all would be ok but now the sound doesn't work at all and I can't figure out why. In all tutorials I've found for AVAudioPlayer, a property is made but no one explains why. If this can't work, what alternatives do I have to make sounds that can overlap?

- (void)loadSound:(NSString *)sound ofType:(NSString *)type withDelegate:(BOOL)delegate {
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
                                     pathForResource:sound
                                     ofType:type]];

AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
if (delegate) audioPlayer.delegate = self;
[audioPlayer prepareToPlay];

[audioPlayer play];
}

解决方案

The reason you need a property or ivar is for the strong reference it provides. When using ARC any object without a strong pointer to it is fair game for deallocation, and in fact that is what you are seeing.

You are also correct that an AVAudioPlayer strong pointer will only allow one audio player to be referenced at a time.

The solution, if you choose to continue to use AVAudioPlayer is to use some sort of collection object to hold strong reference to all the player instances. You could use an NSMutableArray as shown here:

Edit I tweaked the code slightly so method that plays the sound takes an NSString soundName parameter.

@synthesize audioPlayers = _audioPlayers;
-(NSMutableArray *)audioPlayers{
    if (!_audioPlayers){
        _audioPlayers = [[NSMutableArray alloc] init];
    }
    return _audioPlayers;
}
-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
    [self.audioPlayers removeObject:player];
}
-(void)playSoundNamed:(NSString *)soundName{
    NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
                                         pathForResource:soundName
                                         ofType:@"wav"]];
    AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
    if (audioPlayer){
        [audioPlayer setDelegate:self];
        [audioPlayer prepareToPlay];
        [audioPlayer play];
        [self.audioPlayers addObject:audioPlayer];
    }
}

Generally an AVAudioPlayer is overkill for an sound-effect/soundboard application. For quick sound "drops" you will likely find the audio toolbox framework, as outlined in my answer to this question.

From looking at the System Sound class reference, it seems like you can only play one sound at a time.

It can only play one SystemSoundID at a time. So for example if you have soundOne and soundTwo. You can play soundOne while soundTwo is playing, but you cannot play more than one instance of either sound at a time.

What's the best way to be able to play sounds that can overlap while still being efficient with the amount of code and memory?

Best is opinion.

If you need two instances of the same sound to play at the same time, then I would say the code posted in this answer would be the code to use. Due to the fact that each overlapping instance of the same sound requires creating a new resource, code like this with its audioPlayerDidFinishPlaying: is much more manageable(the memory can easily be reclaimed).

If overlapping instances of the same sound are not a deal-breaker then I think just using AudioServicesCreateSystemSoundID() to create one instance of each sound is more efficient.

I definitely would not try to manage the creation of and disposal of SystemSoundIDs with each press of a button. That would go wrong in a hurry. In that instance AVAudioPlayer is the clear winner on just maintainability alone.

这篇关于AVAudioPlayer - 你必须创建一个属性为它工作? (X code)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆