내 애플 오디오 재생 및 녹음 기능, 그리고 사용자가 녹음을 시작할 때 표준 오디오 재생이 음소거 스위치 뮤트 할 수 있도록 만 PlayAndRecord
에 오디오 세션의 범주를 설정하려는 등AudioSession 범주를 SoloAmbient에서 PlayAndRecord로 변경 한 후 RemoteIOUnit에서 녹화 할 수없는 이유는 무엇입니까?
I 모두가 그래도 문제가 있는데, 오디오 세션을 PlayAndRecord
으로 변경하면 AudioUnitRender
에 오디오 입력을 녹음하라는 전화가 errParam
(-50)으로 실패합니다. PlayAndRecord
카테고리를 사용하여 앱을 시작하면 올바르게 레코딩됩니다.
@implementation MyAudioSession
- (instancetype)init {
NSError *error = nil;
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategorySoloAmbient];
[session setActive:YES error:&error];
}
- (void)enableRecording {
void (^setCategory)(void) = ^{
NSError *error;
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
};
// Do I need to set the category from the main thread?
if ([NSThread isMainThread]) {
setCategory();
} else {
dispatch_sync(dispatch_get_main_queue(), ^{
setCategory();
});
}
}
@end
@interface MyRecorder {
AudioUnit ioUnit_;
AudioBufferList *tmpRecordListPtr_
@end
@implementation MyRecorder
- (instancetype)init {
// Sets up AUGraph with just a RemoteIOUnit node, recording enabled, callback, etc.
// Set up audio buffers
tmpRecordListPtr_ = malloc(sizeof(AudioBufferList) + 64 * sizeof(AudioBuffer));
}
- (OSStatus)doRecordCallback:(AudioUnitRenderActionFlags *)ioActionFlags
timeStamp:(AudioTimeStamp *)inTimeStamp
busNumber:(UInt32)busNumber
numFrames:(UInt32)numFrames
bufferOut:(AudioBufferList *)ioData {
// Set up buffers... All this works fine if I initialize the audio session to
// PlayAndRecord in -[MyAudioSession init]
OSStatus status = AudioUnitRender(ioUnit_, ioActionFlags, inTimeStamp, busNumber,
numFrames, tmpRecordListPtr_);
// This fails with errParam, but only if I start my app in SoloAmbient and then
// later change it to PlayAndRecord
}
@end
OSStatus MyRecorderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags,
AudioTimeStamp *inTimestamp, UInt32 inBusNumber,
UInt32 inNumberFrames, AudioBufferList *ioData) {
MyRecorder *recorder = (MyRecorder *)inRefCon;
return [recorder doRecordCallback:ioActionFlags
timeStamp:inTimestamp
busNumber:inBusNumber
numFrames:inNumberFrames
bufferOut:ioData];
}
iOS 7.1.2를 실행하는 iPod touch (5 세대)에서 테스트 중입니다.
다른 사람이이 문제를 겪었습니까? 내가 게시 할 수있는 수정 사항이나 추가 정보에 대한 제안 사항이 있습니까?
편집 : 언급하기 어려운 코드를 보지 않고
- (void)startRecording {
[mySession enableRecording];
[myRecorder release];
myRecorder = [[MyRecorder alloc] init];
[myRecorder start]; // starts the AUGraph
}
'-setActive :'는 오디오 세션이 활성화되어있는 동안 호출 할 수 있도록 문서화되어 있습니다.하지만 라우트 변경 알림을 발생시킵니다. 어떤 경우이든 카테고리를 변경하기 전에 내 세션을 비활성화해도 도움이되지 않습니다. 관련성이있는 코드를 게시 해 보겠습니다. 나는이 코드베이스에 꽤 익숙하다. 그래서 나는 뭔가를 놓칠지도 모른다. – Greg
오디오 세션을 재구성하는 동안 렌더링 콜백이 발생하지 않도록해야 할 필요가 있다고 생각합니다. 나는 실제로 remoteIO 유닛을 폐기하고 세션이 재구성 될 때마다 새로운 유닛을 생성한다. 그러나 콜백을 비활성화하고 기존 장치 인스턴스를 다시 구성하는 것으로 충분할 수 있습니다. – user2338215
녹음을 위해 세션을 재구성 한 후에 이미 녹음기 그래프를 폐기하고 다시 작성하고 있습니다. 레코더 객체 라이프 사이클이 질문과 어떤 관련이 있는지를 보여주는 의사 코드를 추가했습니다. – Greg