AVAudioRecorder AveragePowerForChannel 始终返回 -120.0

发布于 2024-10-18 03:55:40 字数 2165 浏览 7 评论 0原文

我正在尝试使用 AVAudioRecorder 的averagePowerForChannel 方法来监视iPad/iPhone 应用程序麦克风上的输入电平。我有一个回调,它会循环轮询平均水平 - 在 iPhone 上它工作正常并返回合理的水平,但由于某种原因在 iPad 上它总是返回 -120.0。

这是我的一些设置代码:

- (void) setupMic {
if (micInput) {
    [micInput release];
    micInput = nil;
}
NSURL *newURL = [[NSURL alloc] initFileURLWithPath:@"/dev/null"];

NSMutableDictionary *recordSettings = [[NSMutableDictionary alloc] init];

[recordSettings setObject:[NSNumber numberWithInt:kAudioFormatAppleLossless] forKey: AVFormatIDKey];
[recordSettings setObject:[NSNumber numberWithFloat:22050.0] forKey: AVSampleRateKey];
//  [recordSettings setObject:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
[recordSettings setObject:[NSNumber numberWithInt:12800] forKey:AVEncoderBitRateKey];
[recordSettings setObject:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[recordSettings setObject:[NSNumber numberWithInt: AVAudioQualityLow] forKey: AVEncoderAudioQualityKey];

micInput = [[AVAudioRecorder alloc] initWithURL:newURL settings:recordSettings error:nil];
//  [micInput setMeteringEnabled:YES];

[newURL release];
[recordSettings removeAllObjects];
[recordSettings release];
}

以及我的开始记录方法:

- (void) startRecording {
NSLog(@"startRecording!");
[micInput pause];
[micInput prepareToRecord];
micInput.meteringEnabled = YES;
[micInput record];
[micInput updateMeters];
levelTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:0.0] interval:0.03 target:self selector:@selector(levelTimerCallback:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:levelTimer forMode:NSDefaultRunLoopMode];
}

以及一些 levelTimer 回调:

- (void)levelTimerCallback:(NSTimer *)timer {
[micInput updateMeters];
double avgPowerForChannel = pow(10, (0.05 * [micInput averagePowerForChannel:0]));
[micSprite receiveInput:avgPowerForChannel];

NSLog(@"Avg. Power: %f", [micInput averagePowerForChannel:0]);

 ...

}

在 iPhone 上,NSLog 语句将返回合理的值,而 iPad 将始终返回 -120.0。

注意:我在 cocos2d 应用程序中使用它。由于某种原因,如果我在 iPad 上重新启动当前场景,麦克风电平将返回正确的值。

有人有什么建议吗?我在这里严重不知所措。 谢谢!

I'm trying to use AVAudioRecorder's averagePowerForChannel method to monitor input levels on the microphone for an iPad/iPhone app. I have a callback which polls the average level in a loop — on the iPhone it works fine and returns sensible levels, but for some reason on the iPad it always returns -120.0.

Here's some of my setup code:

- (void) setupMic {
if (micInput) {
    [micInput release];
    micInput = nil;
}
NSURL *newURL = [[NSURL alloc] initFileURLWithPath:@"/dev/null"];

NSMutableDictionary *recordSettings = [[NSMutableDictionary alloc] init];

[recordSettings setObject:[NSNumber numberWithInt:kAudioFormatAppleLossless] forKey: AVFormatIDKey];
[recordSettings setObject:[NSNumber numberWithFloat:22050.0] forKey: AVSampleRateKey];
//  [recordSettings setObject:[NSNumber numberWithInt:2] forKey:AVNumberOfChannelsKey];
[recordSettings setObject:[NSNumber numberWithInt:12800] forKey:AVEncoderBitRateKey];
[recordSettings setObject:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey];
[recordSettings setObject:[NSNumber numberWithInt: AVAudioQualityLow] forKey: AVEncoderAudioQualityKey];

micInput = [[AVAudioRecorder alloc] initWithURL:newURL settings:recordSettings error:nil];
//  [micInput setMeteringEnabled:YES];

[newURL release];
[recordSettings removeAllObjects];
[recordSettings release];
}

As well as my start recording method:

- (void) startRecording {
NSLog(@"startRecording!");
[micInput pause];
[micInput prepareToRecord];
micInput.meteringEnabled = YES;
[micInput record];
[micInput updateMeters];
levelTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:0.0] interval:0.03 target:self selector:@selector(levelTimerCallback:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:levelTimer forMode:NSDefaultRunLoopMode];
}

and a bit of the levelTimer callback:

- (void)levelTimerCallback:(NSTimer *)timer {
[micInput updateMeters];
double avgPowerForChannel = pow(10, (0.05 * [micInput averagePowerForChannel:0]));
[micSprite receiveInput:avgPowerForChannel];

NSLog(@"Avg. Power: %f", [micInput averagePowerForChannel:0]);

 ...

}

Where on the iPhone, the NSLog statement will return sensible values, and the iPad will always return -120.0.

Note: I'm using this inside of a cocos2d application. For some reason, if I restart the current scene on the iPad, the mic levels will return correct values.

Anyone have any suggestions? I'm seriously at a loss here.
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

萌辣 2024-10-25 03:55:40

我有同样的问题。我发现将类别设置为 AVAudioSessionCategoryPlayAndRecord 可以解决此问题:

NSError *error;
[[AVAudioSession sharedInstance] 
    setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];

if (error) {
    NSLog(@"Error setting category: %@", [error description]);
}

I had the same issue. I found setting the category to AVAudioSessionCategoryPlayAndRecord fixes it:

NSError *error;
[[AVAudioSession sharedInstance] 
    setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];

if (error) {
    NSLog(@"Error setting category: %@", [error description]);
}
ゝ偶尔ゞ 2024-10-25 03:55:40

您需要初始化 AVAudioSession (应该从 didMoveToview 方法完成,这可能是问题的原因)

let session = AVAudioSession.sharedInstance()
    try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
    try session.overrideOutputAudioPort(AVAudioSessionPortOverride.speaker)
    try session.setActive(true)
try recorder = AVAudioRecorder(url: getDocumentsDirectory(), settings: settings)

并启动录音机

func start() {
    recorder?.record()
    recorder?.updateMeters()
}

调用来获取分贝。

let decibels = recorder.averagePower(forChannel: 0)

并通过从 -120(最小值)到 0 某些咖啡馆的噪音水平示例是 -20

这是更详细的示例 http://www.mikitamanko.com/blog/2017/04/15/swift-how-to-get-decibels/ 注意:也使用更新方法。

You need to init the AVAudioSession (it should be done from didMoveToview method, it might be a reason of the problem)

let session = AVAudioSession.sharedInstance()
    try session.setCategory(AVAudioSessionCategoryPlayAndRecord)
    try session.overrideOutputAudioPort(AVAudioSessionPortOverride.speaker)
    try session.setActive(true)
try recorder = AVAudioRecorder(url: getDocumentsDirectory(), settings: settings)

and start recorder

func start() {
    recorder?.record()
    recorder?.updateMeters()
}

And get the decibels by calling

let decibels = recorder.averagePower(forChannel: 0)

from -120 (min value) up to 0. Noice level of some cafe for example is -20

here's the more detailed example http://www.mikitamanko.com/blog/2017/04/15/swift-how-to-get-decibels/ Note: use the update method as well.

鹤舞 2024-10-25 03:55:40

是的,我也这么做了。只有一个共享的 AVAudioSession。设置其类别会影响所有录音机和播放器,因此,例如,在应用程序的一个区域中将类别设置为 AVAudioSessionCategoryPlay 会禁用其他区域中的录音机。

Yes, I did too. There is only one shared AVAudioSession. Setting its category affects all recorders and players, so setting the category to AVAudioSessionCategoryPlay in one area of the app for example disables recorders in other areas.

一瞬间的火花 2024-10-25 03:55:40

另一个可能的原因很简单,请确保您正在调用[录音机记录];

该行被意外删除,我们花了一段时间才意识到这是仪表上返回 -120 值的原因。

华泰

Another possible cause of this is really simple, be sure you're calling [recorder record];

That line was accidentally deleted and it took us a while to recognize that as the cause of the -120 values being returned on the meter.

HTH

宁愿没拥抱 2024-10-25 03:55:40

1) 确保您有权限:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    if([[AVAudioSession sharedInstance] respondsToSelector:@selector(requestRecordPermission:)])
    {
        [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
            NSLog(@"permission : %d", granted);
            if(granted)[self setupMic];// record ...
        }];
    }
}

2) 确保您的路径是合法的(/dev/null ok??):

NSString* dir=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSArray *pathComponents = [NSArray arrayWithObjects:dir,fileName,nil];
recordedAudioURL = [NSURL fileURLWithPathComponents:pathComponents];

3) 激活audioSession

 [audioSession setActive:YES error:&error];

4) 检查所有错误和返回值,包括

BOOL ok=[micInput prepareToRecord];
ok=ok &&[micInput record];

1) Make sure you have the permission:

if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
    if([[AVAudioSession sharedInstance] respondsToSelector:@selector(requestRecordPermission:)])
    {
        [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) {
            NSLog(@"permission : %d", granted);
            if(granted)[self setupMic];// record ...
        }];
    }
}

2) Make sure your path is legitimate (/dev/null ok??):

NSString* dir=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSArray *pathComponents = [NSArray arrayWithObjects:dir,fileName,nil];
recordedAudioURL = [NSURL fileURLWithPathComponents:pathComponents];

3) activate audioSession

 [audioSession setActive:YES error:&error];

4) Check all errors and return values, including

BOOL ok=[micInput prepareToRecord];
ok=ok &&[micInput record];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文