2

これは私が現在使用しているコードであり、機能していません(このメソッドを呼び出すボタンを押しても何も起こりません)。以前、私はaudioPlayerのプロパティを持っていて、それは機能しました(以下のすべてのaudioPlayerは明らかにself.audioPlayerでした)。問題は、サウンドを2回再生しようとすると、最初のサウンドの再生が終了することでした。

私はサウンドボードを作っているので、音が重なるようにしたいので、これは良くありません。私はaudioPlayerをプロパティの代わりにローカル変数にすることができ、すべてが大丈夫だと思っていましたが、今ではサウンドがまったく機能せず、理由がわかりません。AVAudioPlayerについて私が見つけたすべてのチュートリアルでは、プロパティが作成されていますが、その理由は誰も説明していません。これがうまくいかない場合、オーバーラップする可能性のあるサウンドを作成するには、どのような代替手段が必要ですか?

- (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];
}
4

2 に答える 2

8

プロパティまたはivarが必要な理由は、それが提供する強力な参照のためです。ARCを使用する場合、それへの強力なポインターのないオブジェクトは、割り当て解除のための公正なゲームであり、実際、それがあなたが見ているものです。

AVAudioPlayerまた、強力なポインターでは、一度に1つのオーディオプレーヤーしか参照できないということも正しいです。

引き続き使用する場合の解決策は、AVAudioPlayerある種のコレクションオブジェクトを使用して、すべてのプレーヤーインスタンスへの強力な参照を保持することです。ここに示すようにを使用できますNSMutableArray

編集コードを少し微調整して、サウンドを再生するメソッドがNSString soundNameパラメーターを受け取るようにしました。

@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];
    }
}

一般的に、AVAudioPlayer効果音/サウンドボードアプリケーションにとってはやり過ぎです。この質問への私の回答で概説されているように、すばやく音を「落とす」には、オーディオツールボックスフレームワークが見つかる可能性があります。

システムサウンドクラスリファレンスを見ると、一度に再生できるサウンドは1つだけのようです。

一度に1つしか再生できませんSystemSoundID。たとえば、soundOneとsoundTwoがある場合。soundTwoの再生中にsoundOneを再生できますが、一度にどちらかのサウンドの複数のインスタンスを再生することはできません。

コードとメモリの量を効率的に保ちながら、オーバーラップできるサウンドを再生できるようにするための最良の方法は何ですか?

最高は意見です。

同じサウンドの2つのインスタンスを同時に再生する必要がある場合は、この回答に記載されているコードが使用するコードになると思います。同じサウンドの重複するインスタンスごとに新しいリソースを作成する必要があるため、このようなコードaudioPlayerDidFinishPlaying:ははるかに管理しやすくなります(メモリは簡単に再利用できます)。

AudioServicesCreateSystemSoundID()同じサウンドの重複するインスタンスが問題にならない場合は、各サウンドのインスタンスを1つ作成するために使用する方が効率的だと思います。

SystemSoundIDボタンを押すたびにの作成と破棄を管理しようとは絶対にしません。それは急いでうまくいかないでしょう。その場合AVAudioPlayer、保守性だけで明らかに勝者となります。

于 2012-11-21T04:36:43.597 に答える
5

ARCを使用していると思います。オーディオプレーヤーが機能しない理由は、オブジェクトが解放され、メソッドが終了AVAudioPlayerするとその後破棄されるためです。loadSound:これは、ARCのオブジェクト管理が原因で発生しています。ARCの前は、コードは次のとおりです。

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

期待通りに音が鳴ります。ただし、オブジェクトは、メソッドが終了AVAudioPlayerした後もずっと存在します。loadSound:つまり、サウンドを再生するたびに、メモリリークが発生することになります。

プロパティについて少し

プロパティは、開発者が作成および保守する必要のあるコードの量を減らすために導入されました。プロパティの前に、開発者はインスタンス変数ごとにセッターとゲッターを手書きする必要があります。それは多くの冗長なコードです。プロパティの幸運な副作用は、オブジェクトベースのインスタンス変数のセッター/ゲッターを作成するために必要な多くのメモリ管理コードを処理することでした。これは、公開する必要のない変数であっても、多くの開発者がプロ​​パティを排他的に使用し始めたことを意味します。

ARCはすべてのメモリ管理の詳細を処理するため、プロパティは本来の目的にのみ使用し、冗長なコードの量を削減する必要があります。従来のiVarはデフォルトで強く参照されます。つまり、次のような単純な割り当て title = [NSString stringWithFormat:@"hello"]; は、基本的にコードと同じです self.title = [NSString stringWithFormat:@"hello"];

OK、質問に戻ります。

AVAudioPlayerメソッドでインスタンスを作成する場合は、loadSound:各インスタンスへの強力な参照を保持する必要があります。AVAudioPlayerそうしないと、ARCによってインスタンスが破棄されます。新しく作成したAVAudioPlayerオブジェクトをNSMutableArray配列に追加することをお勧めします。AVAudioPlayerDelegateプロトコルを採用すれば、audioPlayerDidFinishPlaying:successfully:メソッドを実装できます。配列からオブジェクトを削除して、AVAudioPlayerオブジェクトを破棄しても問題がないことをARCに通知できます。

于 2012-11-21T04:59:13.163 に答える