2010-03-18 17 views
3

我在寫一個打開AudioQueue並分析其特性的類,然後在某些條件下可以開始或結束從已經實例化的那個AudioQueue寫出一個文件。這是我的代碼(完全基於SpeakHere)打開的AudioQueue不寫任何東西出來TMP:如何開始寫出現有的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在創建文件時寫出文件,如何設置文件格式等,但不知道如何告訴它在中途啓動和停止。非常感謝任何指針,謝謝。

回答

4

您可以使用AudioQueuePause(AudioQueueRef inAQ)和AudioQueueStart(AudioQueueRef inAQ,const AudioTimeStamp * inStartTime)隨時暫停/啓動audioqueue;

而且還有更多的可能性。因爲你在回調函數中編寫audiofile,你可以選擇何時以及應該保存什麼數據。

要控制寫入數據與否,請在記錄器類中創建例如「doWrite」的布爾標誌,並且只有在設置爲YES時才寫入。隊列開始從開始接收數據並不斷填充緩衝區,但您只需將這些數據轉入回調狀態,直到標誌保持爲NO。然後在任何時候設置doWrite = YES並且下一個緩衝區將被保存到文件中。當您根據聲音本身更改錄音時(例如,只有在聲音比某個thredhold值更響時才錄製),此方法尤其有用。

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 2010-03-19 00:29:38

+0

我想添加(對於任何想讀這個的人來說)我上面的函數需要改變,以包含對AudioFileCreateWithURL的調用,以便它有一個音頻文件寫出來,當它被告知寫入時 - Apple的示例代碼項目SpeakHere中的StartRecord()函數顯示瞭如何執行此操作的一個很好的示例。 – Halle 2010-03-19 00:36:26