0

私はキーボードのようなアプリを持っていて、新しい AVAudioPlayer をそれぞれ NSMutableArray に追加して、サウンドをオーバーレイできるようにしています。私の問題は、そのデリゲート関数です

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag

短い間隔でキーストロークがある場合は起動されません。たとえば、0.5秒以上の間隔でストロークすると、すべて正常に動作します。理由はありますか?彼のサウンド再生が終了したら、メモリを解放して配列からオブジェクトを削除したいと考えています。

アップデート

.h

@interface .. <AVAudioPlayerDelegate>
{
    NSMutableArray *soundObjects;
}

@property (nonatomic,strong) AVAudioPlayer *audioPlayer;

.m

-(void)playSound {

    //
    //  play sound
    //

    _audioPlayer = [self loadWav:_soundID];
    _audioPlayer.delegate = self;

    [soundObjects addObject:_audioPlayer];
    AVAudioPlayer *temp = [soundObjects objectAtIndex:soundIndex];
    soundIndex = [soundObjects count];
    [temp play];
}

-(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
#ifdef DEBUG_SOUND
        NSLog(@"FLAG");
        soundIndex--;
        [soundObjects removeObjectAtIndex:soundIndex];
#endif
}

- (AVAudioPlayer *)loadWav:(NSString *)filename {
    NSURL * url = [[NSBundle mainBundle] URLForResource:filename withExtension:@"mp3"];
    NSError * error;

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

    if (!player) {
#ifdef DEBUG_MODE
        NSLog(@"Error loading %@: %@", url, error.localizedDescription);
#endif
    } else {
        [player prepareToPlay];
    }
    return player;
}
4

2 に答える 2

0

バックグラウンド プロセスで再生を起動してみてください。これは私の最初のことですが、詳細を知ることなく、あなたがどのように音を演奏しているかについて推測することしかできません. メイン スレッドでサウンドを再生している場合、メイン スレッド上にあるキーボードは、サウンドがバッファリングされ、同じスレッドで再生するために起動されている間、応答しなくなります。メディアを扱うときは、通常、競合状態の可能性を排除するために、メイン スレッドからロードして再生する必要があります。曲や映画の画像をロードする場合、UI が応答しなくなるため、通常はメイン スレッド上に置くべきではありません。

于 2012-11-20T03:28:11.937 に答える
0

簡単な例として、開発者向けドキュメントに NSQueue の例がいくつかあります。私は、自分の作業を使用してまとめた Obj C レシピ本からの適応を使用します。

//This method detatches the instruction from the main thread
-(void)keyStrokeSelector:(NSString*)objectSound{


       [NSThread detachNewThreadSelector:@selector(keyStroke:objectSound)
                                toTarget:self
                              withObject:nil];


 }

//this selector will acctually execute the task
-(void)keyStroke:(NSString *)objectSound
{
   @autoreleasepool {
      //code to play the sound
   }
}

これが役立つことを願っています。上記のコードに関するいくつかの注意事項: 個々のスレッドごとに autoreleasepool を使用する必要があります。そうしないと、参照カウント (MRC または ARC) が機能しません。これは、autoreleasepool 内でのみ機能するためです。メインスレッドから離れたスレッドで発生するコードをコーディングする必要があります。他のものと同様に、単純に実行され、完了するまで実行されます。子スレッドに無限ループがある場合、アプリのテスト中には気付かないかもしれませんが、バックグラウンド スレッドの現在の最大時間を正しく覚えていれば、OS は 10 分後にアプリを強制終了します。さらに重要なことは、スレッド固有の @autoreleasepool を作成しないと、オブジェクトが解放されず、新しいスレッド内に新しいオブジェクトを作成しなくてもメモリ フットプリントを消費することです。

これがお役に立てば幸いです。あなたのプログラムで頑張ってください

于 2012-11-21T03:24:34.270 に答える