xcode 试图了解 AVAudioPlayer 和音频电平表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10504428/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 00:13:54  来源:igfitidea点击:

Trying to understand AVAudioPlayer and audio level metering

iphoneobjective-cxcodeipadavaudioplayer

提问by SNV7

I'm trying to understand AVAudioPlayer and audio level metering. What I have below is an object "AudioPlayer" that is playing a short audio sound. Now I want to output the power of this sound (decibels). Somehow I don't think I'm doing this right.

我正在尝试了解 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]);

The NSLog output of this is 0 -160.00 -160.00 1 -160.00 -160.00

这个 NSLog 输出是 0 -160.00 -160.00 1 -160.00 -160.00

Now according to Apple "A return value of 0 dB indicates full scale, or maximum power; a return value of -160 dB indicates minimum power" So does this mean this sound is at minimum power? I don't think this is true because the audio snippet is a fairly loud sound. I think I'm missing something here, any clarification would be appreciated.

现在根据 Apple 的说法“0 dB 的返回值表示满量程或最大功率;-160 dB 的返回值表示最小功率” 那么这是否意味着该声音处于最小功率?我不认为这是真的,因为音频片段是一个相当响亮的声音。我想我在这里遗漏了一些东西,任何澄清将不胜感激。

采纳答案by jscs

You're updating and then asking for the value of the meters almost immediately after the sound starts -- that updateMetersis 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 updateMetersinsidethe loop, right before you inspect the values.

您正在更新,然后几乎在声音开始后立即询问仪表的值——这updateMeters可能在您发送play. 因此,如果剪辑开头有任何静音,您很可能会得到正确的阅读。您应该尝试延迟检查,并且您可能还需要在检查值之前在循环updateMeters发送。

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

您也永远不会真正获得大于 0 的通道的仪表值,因为无论i循环中的值是什么,您都会传递 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]);
}

回答by Rok Jarc

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

您的代码有几个问题 - Jacques 已经指出了其中的大部分问题。

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

您必须[audioPlayer updateMeters];每次在读取值之前调用。你可能最好实例化一个NSTimer.

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

NSTimer *playerTimer;在您的班级中声明一个 iVar @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.

此外,<AVAudioPlayerDelegate>在您的课程中采用也没有什么坏处,因此您可以在玩家完成游戏后使计时器无效。

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.

你应该很高兴去。