2012-05-07 2 views
7

오디오 장치를 사용하여 음악 녹음 앱을 코딩하고 있는데 결과 M4A 파일이 굉장한 윙윙 거리는 소리가 아닌 다른 것을 재생하는 데 문제가 있습니다. . 나는 이걸 사용했습니다 sourcesasreferences, 나는 모든 문제를 해결하려고 노력했습니다.원격 I/O 출력을 파일로 작성 및 인코딩 - Core Audio

AUGraph에는 멀티 채널 믹서와 원격 I/O 노드가 2 개 있습니다. 믹서에는 두 개의 입력 콜백이 있습니다. 하나는 마이크에서 입력을 가져오고 하나는 오디오 파일에서 가져옵니다. 믹서 출력은 I/O 유닛의 출력 스코프의 입력 요소에 연결됩니다. 이것은 동시에 I/O를 가능하게합니다.

내가 추가 한 출력 콜백 및 두 가지 방법을 캡처하려면 :

콜백

static OSStatus recordAndSaveCallback (void *    inRefCon, 
             AudioUnitRenderActionFlags * ioActionFlags, 
             const AudioTimeStamp *  inTimeStamp, 
             UInt32      inBusNumber, 
             UInt32      inNumberFrames, 
             AudioBufferList *   ioData) 
{ 
    Mixer* THIS = (__bridge Mixer*)inRefCon; 
    AudioBufferList bufferList; 

    OSStatus status; 
    status = AudioUnitRender(THIS.ioUnit,  
          ioActionFlags, 
          inTimeStamp, 
          0, 
          inNumberFrames, 
          &bufferList); 

    SInt16 samples[inNumberFrames]; // A large enough size to not have to worry about buffer overrun 
    memset (&samples, 0, sizeof (samples)); 

    bufferList.mNumberBuffers = 1; 
    bufferList.mBuffers[0].mData = samples; 
    bufferList.mBuffers[0].mNumberChannels = 1; 
    bufferList.mBuffers[0].mDataByteSize = inNumberFrames*sizeof(SInt16); 

    OSStatus result; 
    if (*ioActionFlags == kAudioUnitRenderAction_PostRender) { 
     result = ExtAudioFileWriteAsync(THIS.extAudioFileRef, inNumberFrames, &bufferList); 
     if(result) printf("ExtAudioFileWriteAsync %ld \n", result);} 
    return noErr; 
} 

녹음 방법 :

- (void)recordFile 
{  
    OSStatus result; 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString *recordFile = [documentsDirectory stringByAppendingPathComponent: @"audio.m4a"]; 

    CFURLRef destinationURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, 
                  (__bridge CFStringRef)recordFile, 
                  kCFURLPOSIXPathStyle, 
                  false);  

    AudioStreamBasicDescription destinationFormat; 
    memset(&destinationFormat, 0, sizeof(destinationFormat)); 
    destinationFormat.mChannelsPerFrame = 1; 
    destinationFormat.mFormatID = kAudioFormatMPEG4AAC; 
    UInt32 size = sizeof(destinationFormat); 
    result = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &destinationFormat);   
    if(result) printf("AudioFormatGetProperty %ld \n", result);  


    result = ExtAudioFileCreateWithURL(destinationURL, 
             kAudioFileM4AType, 
             &destinationFormat, 
             NULL, 
             kAudioFileFlags_EraseFile, 
             &extAudioFileRef); 
    if(result) printf("ExtAudioFileCreateWithURL %ld \n", result); 


    AudioStreamBasicDescription clientFormat; 
    memset(&clientFormat, 0, sizeof(clientFormat)); 


    UInt32 clientsize = sizeof(clientFormat); 
    result = AudioUnitGetProperty(ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &clientFormat, &clientsize); 
    if(result) printf("AudioUnitGetProperty %ld \n", result); 

    UInt32 codec = kAppleHardwareAudioCodecManufacturer; 

    result = ExtAudioFileSetProperty(extAudioFileRef, 
            kExtAudioFileProperty_CodecManufacturer, 
            sizeof(codec), 
            &codec); 

    if(result) printf("ExtAudioFileSetProperty %ld \n", result); 


    result = ExtAudioFileSetProperty(extAudioFileRef,kExtAudioFileProperty_ClientDataFormat,sizeof(clientFormat), &clientFormat); 
    if(result) printf("ExtAudioFileSetProperty %ld \n", result); 


    result = ExtAudioFileWriteAsync(extAudioFileRef, 0, NULL); 
    if (result) {[self printErrorMessage: @"ExtAudioFileWriteAsync error" withStatus: result];} 

    result = AudioUnitAddRenderNotify(ioUnit, recordAndSaveCallback, (__bridge void*)self); 
    if (result) {[self printErrorMessage: @"AudioUnitAddRenderNotify" withStatus: result];}  
} 

저장 방법 :

- (void) saveFile { 
    OSStatus status = ExtAudioFileDispose(extAudioFileRef); 
    NSLog(@"OSStatus(ExtAudioFileDispose): %ld\n", status); 

} 

이 6,내가 내 콘솔에서 볼 것입니다 :

Stopping audio processing graph 
OSStatus(ExtAudioFileDispose): 0 
ExtAudioFileWriteAsync -50 
ExtAudioFileWriteAsync -50 
ExtAudioFileWriteAsync -50 

내 코드는이 작업을 입수했습니다 사람들의 그것과 매우 유사하다는 것을 나에게 보인다,하지만 분명히 나는했습니다 중대한 오류가 발생했습니다. 나는이 일로 어려움을 겪고있는 다른 사람들이있을 것이라고 확신합니다.

아무도 통찰력이 있습니까?

감사합니다.

+0

'recordAndSaveCallback'이 끝나기 전에'-saveFile' 메쏘드가 호출되고있는 것처럼 보입니다. saveFile을 호출하기 전에 AUGraph를 멈추고 있습니까? – sbooth

+0

그래프와 관련된 모든 문제를 배제하는 실험으로 wav와 같은 간단한 형식을 사용하여 시도하고 기록하는 것이 좋습니다. ASBD는 제대로 이해하기가 어려울 수 있지만, ASBD가 문제 (내 의견)라고 판단 할 수 있다면 파일 형식을 실험하는 데 집중할 수 있습니다. – dubbeat

+0

명령 행에서 macerror -50을 실행하면 다음과 같이 나타납니다. Mac OS 오류 -50 (paramErr) : 사용자 매개 변수 목록에 오류가 있습니다. – morgancodes

답변

1

나는 오랜 시간 전에 질문을 받았으며 아마도 지금까지 오류를 발견했다는 것을 알고있다. 나는 똑같은 문제가있을 수도있는 다른 사람들을 위해 대답하고있다.

내가 틀릴 수도 있지만 문제는 버퍼에 대한 범위 내 변수 선언을 수행하고 있다는 사실에서 비롯된 것 같습니다.

난 당신이 변경하는 것이 좋습니다 것입니다

SInt16 samples[inNumberFrames]; 

recordAndSaveCallback은 당신이 범위 내 선언을 할 경우, datas가 파괴되고, 버퍼 목록을 해소하기 위해 개발되었다 때문에

SInt16* samples = malloc(inNumberFrames * sizeof(SInt16)); 

로 범위가 끝나면 곧.

관련 문제