7

AVAudioPlayerとオーディオレベルメータリングを理解しようとしています。以下にあるのは、短いオーディオサウンドを再生しているオブジェクト「AudioPlayer」です。この音(デシベル)のパワーを出力したいと思います。どういうわけか私はこれを正しくやっているとは思わない。

        audioPlayer.meteringEnabled = YES;
        [audioPlayer play];
        int channels = audioPlayer.numberOfChannels;
        [audioPlayer updateMeters];
        for (int i=0; i<channels; i++) {
            //Log the peak and average power
            NSLog(@"%d %0.2f %0.2f", i, [audioPlayer peakPowerForChannel:0],[audioPlayer averagePowerForChannel:0]);

このNSLog出力は0-160.00-160.00 1-160.00-160.00です。

Appleによれば、「0 dBの戻り値はフルスケール、つまり最大電力を示します。-160dBの戻り値は最小電力を示します」では、これはこのサウンドが最小電力であることを意味しますか?オーディオスニペットはかなり大きな音なので、これは真実ではないと思います。私はここで何かが欠けていると思います、どんな説明でもいただければ幸いです。

4

2 に答える 2

11

コードにはいくつかの問題があります-Jacquesはすでにそれらのほとんどを指摘しています。

[audioPlayer updateMeters];値を読み取る前に、毎回呼び出す必要があります。をインスタンス化するのがおそらく最善でしょうNSTimer

NSTimer *playerTimer;クラスでiVarを宣言します@interface

また、クラスで採用しても問題はない<AVAudioPlayerDelegate>ので、プレーヤーがプレイを終了した後にタイマーを無効にすることができます。

次に、コードを次のように変更します。

audioPlayer.meteringEnabled = YES;
audioPlayer.delegate = self;

if (!playerTimer)
{
    playerTimer = [NSTimer scheduledTimerWithTimeInterval:0.001
                  target:self selector:@selector(monitorAudioPlayer)
                userInfo:nil
                 repeats:YES];
}

[audioPlayer play];

次の2つのメソッドをクラスに追加します。

-(void) monitorAudioPlayer
{   
    [audioPlayer updateMeters];
    
    for (int i=0; i<audioPlayer.numberOfChannels; i++)
    {
        //Log the peak and average power
         NSLog(@"%d %0.2f %0.2f", i, [audioPlayer peakPowerForChannel:i],[audioPlayer averagePowerForChannel:i]);
    }
}

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{   
    NSLog (@"audioPlayerDidFinishPlaying:");
    [playerTimer invalidate];
    playerTimer = nil;
}

そして、あなたは行ってもいいはずです。

于 2012-05-14T12:09:19.317 に答える
4

サウンドが開始された直後にメーターの値を更新して要求しています。updateMetersこれは、送信してから数十ミリ秒後に実行されている可能性がありますplay。したがって、クリップの先頭に沈黙がある場合は、正しい読み値を取得している可能性があります。検査を遅らせる必要があります。また、値を検査する直前に、ループupdateMeters 内に送信する必要がある場合もあります。

iまた、ループ内の値に関係なく0を渡すため、チャネル>0のメーター値を実際に取得することはありません。私はあなたがこれをするつもりだったと思います:

for (int currChan = 0; currChan < channels; currChan++) {
    //Log the peak and average power
    NSLog(@"%d %0.2f %0.2f", currChan, [audioPlayer peakPowerForChannel:currChan], [audioPlayer averagePowerForChannel:currChan]);
}
于 2012-05-08T18:47:40.953 に答える