更新
我开始明白了这一点。 AVAudioRecorder会话被激活,我得到麦克风水平读数几秒钟。然后异步视频代码完成,摄像机视图显示,我停止获取读数。好像视频正在杀死音频会话。
奇怪的是,该代码适用于iOS 7,并且无法在iOS 6上运行。任何想法如何解决这个问题。这是对iOS 6的限制吗?
我通过麦克风获得声级,当我在设置录音机对象的代码上放置断点时,我只能得到它们。如果我在那个时间没有暂停的情况下运行几秒钟就无法获得等级。这段代码在viewDidLoad中,我可以将断点放在前3行中的一行:
_recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
[_recorder prepareToRecord];
_recorder.meteringEnabled = YES;
_levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.03 target: self selector: @selector(levelTimerCallback) userInfo: nil repeats: YES];
我在levelTimerCallback方法中得到了我的关卡。
此代码进入viewDidAppear:
NSError *error;
if (_recorder) {
[_recorder record];
} else
NSLog(@"Error: %@", [error description]);
编辑:
levelTimerCallback代码:
[_recorder updateMeters];
const double ALPHA = 0.05;
double peakPowerForChannel = pow(10, (0.05 * [_recorder peakPowerForChannel:0]));
_lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * _lowPassResults;
NSLog(@"Average input: %f Peak input: %f", [_recorder averagePowerForChannel:0], [_recorder peakPowerForChannel:0]);
异步代码在记录器代码上方运行:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[[self captureManager] session] startRunning];
});
相机代码:
if ([self captureManager] == nil) {
AVCamCaptureManager *manager = [[AVCamCaptureManager alloc] init];
[self setCaptureManager:manager];
[[self captureManager] setDelegate:self];
if ([[self captureManager] setupSession]) {
// Create video preview layer and add it to the UI
AVCaptureVideoPreviewLayer *newCaptureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:[[self captureManager] session]];
UIView *view = [self videoPreviewView];
CALayer *viewLayer = [view layer];
[viewLayer setMasksToBounds:YES];
CGRect bounds = [view bounds];
[newCaptureVideoPreviewLayer setFrame:bounds];
if ([[newCaptureVideoPreviewLayer connection] isVideoOrientationSupported]) {
[[newCaptureVideoPreviewLayer connection] setVideoOrientation:AVCaptureVideoOrientationPortrait];
}
[newCaptureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[viewLayer insertSublayer:newCaptureVideoPreviewLayer below:[[viewLayer sublayers] objectAtIndex:0]];
[self setCaptureVideoPreviewLayer:newCaptureVideoPreviewLayer];
// Start the session. This is done asychronously since -startRunning doesn't return until the session is running.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[[self captureManager] session] startRunning];
});
[self addObserver:self forKeyPath:@"captureManager.videoInput.device.focusMode" options:NSKeyValueObservingOptionNew context:AVCamFocusModeObserverContext];
// Add a single tap gesture to focus on the point tapped, then lock focus
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapToAutoFocus:)];
[singleTap setDelegate:self];
[singleTap setNumberOfTapsRequired:1];
[view addGestureRecognizer:singleTap];
// Add a double tap gesture to reset the focus mode to continuous auto focus
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapToContinouslyAutoFocus:)];
[doubleTap setDelegate:self];
[doubleTap setNumberOfTapsRequired:2];
[singleTap requireGestureRecognizerToFail:doubleTap];
[view addGestureRecognizer:doubleTap];
}
}
NSURL *url = [NSURL fileURLWithPath:@"/dev/null"];
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey,
nil];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setActive: YES error: nil];
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryRecord error: nil];
NSError *error;
_recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
答案 0 :(得分:1)
我认为您应该在_levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.03 target: self selector: @selector(levelTimerCallback) userInfo: nil repeats: YES];
结束时致电viewDidAppear
,并将其取消并在viewDidDisappear
中使其无效。当viewDidLoad
中有其他代码时,从viewDidAppear
开始计时器没有意义。您可能还想使用主线程而不是[[[self captureManager] session] startRunning];
的后台线程进行检查。