2010-03-18 3 views
3

AudioQueue를 열고 특성을 분석하는 클래스를 작성하고 있으며 특정 조건에서 이미 인스턴스화 된 해당 AudioQueue에서 파일을 작성하거나 종료 할 수 있습니다. 이 TMP 밖으로 아무것도 작성하지 않고도 AudioQueue를 엽니 다 (전체 SpeakHere 기준) 내 코드입니다 :이벤트에 대한 응답으로 기존 AudioQueue 작성을 시작하는 방법은 무엇입니까?

void AQRecorder::StartListen() { 
int i, bufferByteSize; 
UInt32 size; 

try {  

    SetupAudioFormat(kAudioFormatLinearPCM); 

    XThrowIfError(AudioQueueNewInput(&mRecordFormat, 
        MyInputBufferHandler, 
        this, 
        NULL, NULL, 
        0, &mQueue), "AudioQueueNewInput failed"); 

    mRecordPacket = 0; 

    size = sizeof(mRecordFormat); 
    XThrowIfError(AudioQueueGetProperty(mQueue, kAudioQueueProperty_StreamDescription, 
      &mRecordFormat, &size), "couldn't get queue's format"); 

    bufferByteSize = ComputeRecordBufferSize(&mRecordFormat, kBufferDurationSeconds); 
    for (i = 0; i < kNumberRecordBuffers; ++i) { 
     XThrowIfError(AudioQueueAllocateBuffer(mQueue, bufferByteSize, &mBuffers[i]), 
         "AudioQueueAllocateBuffer failed"); 
     XThrowIfError(AudioQueueEnqueueBuffer(mQueue, mBuffers[i], 0, NULL), 
         "AudioQueueEnqueueBuffer failed"); 
    } 

    mIsRunning = true; 
    XThrowIfError(AudioQueueStart(mQueue, NULL), "AudioQueueStart failed"); 
} 
catch (CAXException &e) { 
    char buf[256]; 
    fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf)); 
} 
catch (...) { 
    fprintf(stderr, "An unknown error occurred\n"); 
} 
} 

그러나 나는 지금까지에서이 큐 "를 알려주는 기능을 작성하는 방법에 약간 불분명 해요 정지 신호,이 대기열을 파일로 tmp에 쓰기 시작 ". AudioQueue가 생성 된 시점의 파일, 파일 형식을 설정하는 방법 등으로 AudioQueue에 알려주는 방법을 이해합니다.하지만 중간 스트림을 시작하고 중지하는 방법을 알려주는 방법은 아닙니다. 어떤 포인터에 감사하고 감사합니다.

답변

4

AudioQueuePause (AudioQueueRef inAQ) 및 AudioQueueStart (AudioQueueRef inAQ, const AudioTimeStamp * inStartTime)를 사용하여 언제든지 오디오 대기열을 일시 중지/시작할 수 있습니다.

그리고 더 많은 가능성이 있습니다. 콜백 함수에 오디오 파일을 작성하기 때문에 언제 저장할 것인지, 저장할 데이터를 선택할 수 있습니다.

쓰기 데이터를 제어하려면 레코더 클래스에 "doWrite"와 같은 bool 플래그를 만들고 YES로 설정된 경우에만 쓰기하십시오. 큐는 처음부터 데이터를 받기 시작하고 지속적으로 버퍼를 채우지 만 플래그가 NO가 될 때까지이 데이터를 콜백에 저장합니다. 그런 다음 doWrite = YES로 설정하면 다음 버퍼가 파일로 저장됩니다. 이 방법은 사운드 자체를 기반으로 녹음을 변경할 때 특히 유용합니다 (예 : 소리가 일부 음원 값보다 큰 경우에만 녹음).

void AQRecorder::MyInputBufferHandler( void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp * inStartTime, UInt32 inNumPackets, const AudioStreamPacketDescription* inPacketDesc) 
{ 
    AQRecorder *aqr = (AQRecorder *)inUserData; 
    try { 
     if (inNumPackets > 0) { 

        if (aqr.doWrite){ 
          // write packets to file 
          XThrowIfError(AudioFileWritePackets(aqr->mRecordFile, FALSE, inBuffer->mAudioDataByteSize, inPacketDesc, aqr->mRecordPacket, &inNumPackets, inBuffer->mAudioData), "AudioFileWritePackets failed"); 
          aqr->mRecordPacket += inNumPackets; 
        } 
     } 

     // if we're not stopping, re-enqueue the buffe so that it gets filled again 
     if (aqr->IsRunning()) 
      XThrowIfError(AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL), "AudioQueueEnqueueBuffer failed"); 
    } catch (CAXException e) { 
     char buf[256]; 
     fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf)); 
    } 
} 
+0

감사합니다. Vladimir, MyInputBufferHandler에 대한 부울 플래그 접근 방식이 완벽하게 작동했습니다. – Halle

+0

필자는 AudioFileCreateWithURL에 대한 호출을 포함하도록 위의 함수를 변경하여 쓰기를 요청할 때 쓸 오디오 파일을 포함해야한다고 (이를 사용하고자하는 사람은 누구나 읽을 수 있습니다) Apple의 샘플 코드 프로젝트 인 SpeakHere의 StartRecord() 함수는이를 수행하는 좋은 예를 보여줍니다. – Halle