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!
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]);
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With