Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/120.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 我将分贝从-120-0转换为0-120是否正确_Iphone_Ios_Xcode_Audio Recording_Decibel - Fatal编程技术网

Iphone 我将分贝从-120-0转换为0-120是否正确

Iphone 我将分贝从-120-0转换为0-120是否正确,iphone,ios,xcode,audio-recording,decibel,Iphone,Ios,Xcode,Audio Recording,Decibel,我想测量周围环境的音量,不太确定我是否做了正确的事情 我想创建一个范围为0(安静)到120(非常嘈杂)的VU仪表 我得到了峰值和平均功率,但在正常的安静环境下非常高。 一定要给我一些指示 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //creating an audio CAF fi

我想测量周围环境的音量,不太确定我是否做了正确的事情

我想创建一个范围为0(安静)到120(非常嘈杂)的VU仪表

我得到了峰值和平均功率,但在正常的安静环境下非常高。 一定要给我一些指示

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.


    //creating an audio CAF file in the temporary directory, this isn’t ideal but it’s the only way to get this class functioning (the temporary directory is erased once the app quits). Here we also specifying a sample rate of 44.1kHz (which is capable of representing 22 kHz of sound frequencies according to the Nyquist theorem), and 1 channel (we do not need stereo to measure noise).

    NSDictionary* recorderSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                      [NSNumber numberWithInt:kAudioFormatLinearPCM],AVFormatIDKey,
                                      [NSNumber numberWithInt:44100],AVSampleRateKey,
                                      [NSNumber numberWithInt:1],AVNumberOfChannelsKey,
                                      [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,
                                      [NSNumber numberWithBool:NO],AVLinearPCMIsBigEndianKey,
                                      [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,
                                      nil];
    NSError* error;

    NSURL *url = [NSURL fileURLWithPath:@"/dev/null"];
    recorder = [[AVAudioRecorder alloc] initWithURL:url settings:recorderSettings error:&error];

    //enable measuring
    //tell the recorder to start recording:
    [recorder record];

    if (recorder) {
        [recorder prepareToRecord];
        recorder.meteringEnabled = YES;
        [recorder record];
        levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.01 target: self selector: @selector(levelTimerCallback:) userInfo: nil repeats: YES];

    } else
    {
        NSLog(@"%@",[error description]);
    }        
}

- (void)levelTimerCallback:(NSTimer *)timer {
    [recorder updateMeters];

    const double ALPHA = 0.05;
    double peakPowerForChannel = pow(10, (0.05 * [recorder averagePowerForChannel:0]));
    lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;     

    NSLog(@"Average input: %f Peak input: %f Low pass results: %f", [recorder averagePowerForChannel:0], [recorder peakPowerForChannel:0], lowPassResults);

    float tavgPow =[recorder averagePowerForChannel:0] + 120.0;
    float tpPow = [recorder peakPowerForChannel:0] + 120.0;

    float avgPow = tavgPow;//(float)abs([recorder averagePowerForChannel:0]);
    float pPow = tpPow;//(float)abs([recorder peakPowerForChannel:0]);

    NSString *tempAvg = [NSString stringWithFormat:@"%0.2f",avgPow];
        NSString *temppeak = [NSString stringWithFormat:@"%0.2f",pPow];
    [avg setText:tempAvg];
        [peak setText:temppeak];
    NSLog(@"Average input: %f Peak input: %f Low pass results: %f", avgPow,pPow , lowPassResults);
}   

当您希望使用1.0作为参考(对于0db)时,将线性振幅转换为分贝的公式如下

因此,我不确定查看代码的意图,但您可能希望

float db = 20 * log10([recorder averagePowerForChannel:0]);
振幅为0时,这将从-无穷大变为振幅为1时的0db。 如果你真的需要它上升到0到120之间,你可以加上120并在0处使用max函数

因此,在上述行之后:

db += 120;
db = db < 0 ? 0 : db;


实际上,分贝的范围是从-160到0,但它可以变成正值。(-averagePowerForChannel:method)


然后最好写
db+=160而不是
db+=120。当然,你也可以设置一个偏移量来修正它。

苹果公司在他们的样本中使用一个查找表,将dB转换为水平仪上显示的线性值。这是为了节省设备电源(我猜)

我也需要这个,但没想到每隔1/10秒(我的刷新率)进行两次浮点计算会花费这么多设备电源。因此,我没有建立一个表,而是将他们的代码塑造成:

float       level;                // The linear 0.0 .. 1.0 value we need.
const float minDecibels = -80.0f; // Or use -60dB, which I measured in a silent room.
float       decibels    = [audioRecorder averagePowerForChannel:0];

if (decibels < minDecibels)
{
    level = 0.0f;
}
else if (decibels >= 0.0f)
{
    level = 1.0f;
}
else
{
    float   root            = 2.0f;
    float   minAmp          = powf(10.0f, 0.05f * minDecibels);
    float   inverseAmpRange = 1.0f / (1.0f - minAmp);
    float   amp             = powf(10.0f, 0.05f * decibels);
    float   adjAmp          = (amp - minAmp) * inverseAmpRange;

    level = powf(adjAmp, 1.0f / root);
}
float-level;//线性0.0。。1.0我们需要的价值。
常量浮点minDecibels=-80.0f;//或者使用-60dB,这是我在一个安静的房间里测得的。
浮点分贝=[录音机平均声道功率:0];
if(分贝<分钟分贝)
{
水平=0.0f;
}
否则,如果(分贝>=0.0f)
{
水平=1.0f;
}
其他的
{
浮动根=2.0f;
浮点数=功率(10.0f,0.05f*minDecibels);
浮点数=1.0f/(1.0f-最小值);
浮动放大器=功率(10.0f,0.05f*分贝);
浮点数adjAmp=(amp-minAmp)*逆整数;
电平=功率(adjAmp,1.0f/根);
}
我使用的是
AVAudioRecorder
,因此您可以看到使用
averagePowerForChannel:
获取dB,但是您可以在那里填充自己的dB值

苹果的例子使用了
double
计算,我不理解这一点,因为对于音频测光
float
来说,准确度已经足够了,而且成本更低

不用说,您现在可以将此计算的
级别
缩放到您的0。。120范围,具有简单的
级别*120.0f


当我们在
2.0f
处修复
root
时,可以通过将
powf(adjAmp,1.0f/root)
替换为
sqrtf(adjAmp)
来加速上述代码;但这是一件小事,一个非常好的编译器也许能帮我们做到这一点。我几乎可以肯定,
inverseAmpRange
将在编译时计算一次。

只需设置最大值和最小值。就像你得到的范围是0-120。如果您希望范围为0-60。只需将值除以一半即可得到半范围,依此类推。

我建立了一个回归模型,以转换从
NSRecorder
生成的wav数据与来自
NSRecorder.averagePowerForChannel
的分贝数据之间的映射关系

NSRecorder.averagePowerForChannel
(dB)=-80+6log2(
wav\u RMS


其中,
wav_RMS
是短时间内,即0.1秒内,wav数据的均方根值。

Hi Michael,谢谢您的回复。我相信averagePowerForChannel是-x中的分贝值,我想把它转换成0-120value@Desmond:好的,最后一步我建议将PeakPower ForChannel更改为直接使用分贝值。您稍后将添加120。您还需要使用max(0,db)来确保它不小于零,就像我使用'db=db<0'时所做的那样?0:db;'谢谢Michael,但是在一个安静的房间里分贝非常高……我下载了一个10分贝的应用程序来检查它的分贝差异是巨大的。应用程序显示大约40分贝,我的显示70分贝。我的主要目标是检查用户是否发出噪音。如果它超过阈值,将触发某些事件。这可能是因为db是引用的。另一个应用程序可能使用的引用小于1.0,而您使用的是1.0。在转换为DB之前,您需要找到一个新的参考,并将振幅除以参考(这是在您尚未向我们展示的代码中完成的)。针落的声压级变化经常被用作参考——你需要知道这在你的振幅中意味着什么。如果您信任另一个应用程序,您可以猜测和检查,直到dbs对齐。
double peakPowerForChannel = pow(10, (0.05 * [recorder averagePowerForChannel:0]));
double peakPowerForChannel = [recorder averagePowerForChannel:0];
float       level;                // The linear 0.0 .. 1.0 value we need.
const float minDecibels = -80.0f; // Or use -60dB, which I measured in a silent room.
float       decibels    = [audioRecorder averagePowerForChannel:0];

if (decibels < minDecibels)
{
    level = 0.0f;
}
else if (decibels >= 0.0f)
{
    level = 1.0f;
}
else
{
    float   root            = 2.0f;
    float   minAmp          = powf(10.0f, 0.05f * minDecibels);
    float   inverseAmpRange = 1.0f / (1.0f - minAmp);
    float   amp             = powf(10.0f, 0.05f * decibels);
    float   adjAmp          = (amp - minAmp) * inverseAmpRange;

    level = powf(adjAmp, 1.0f / root);
}