Trying to understand AVAudioPlayer and audio level metering

北战南征 提交于 2019-12-04 08:34:48

You're updating and then asking for the value of the meters almost immediately after the sound starts -- that updateMeters is probably running a few tens of milliseconds after you send play. So if there's any silence at the beginning of the clip, you could very well be getting the correct reading. You should trying delaying your inspection, and you may also need to send updateMeters inside the loop, right before you inspect the values.

You're also never actually getting the meter values for channels > 0, because you pass 0 no matter what the value of i is in the loop. I think you meant to do this:

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

There are several issues with your code - Jacques has already pointed out most of them.

You have to call [audioPlayer updateMeters]; each time before reading the values. You'll probably be best off instantiating a NSTimer.

Declare an iVar NSTimer *playerTimer; in your class @interface.

Also it doesn't hurt to adopt <AVAudioPlayerDelegate> in your class so you'll be able to invalidate the timer after player has finished playing.

Then change your code to:

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

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

[audioPlayer play];

Add this two methods to your class:

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

And you should be good to go.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!