2010-03-18 1 views
3

Я пишу класс, который открывает AudioQueue и анализирует его характеристики, а затем при определенных условиях может начинать или заканчивать запись файла из уже созданного 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 для записи в виде файла в то время, когда он создан, как установить формат файлов и т. Д., Но не как сказать ему, чтобы он начинал и останавливал срединный поток. Большое спасибо за любые указатели, спасибо.

ответ

4

Вы можете приостановить/запустить аудиоклип в любое время с помощью AudioQueuePause (AudioQueueRef inAQ) и AudioQueueStart (AudioQueueRef inAQ, const AudioTimeStamp * inStartTime);

И больше возможностей. Поскольку вы пишете аудиофайл в функции обратного вызова, вы можете выбрать там, когда и какие данные должны быть сохранены.

Чтобы управлять записью данных, создайте флаг bool, например, doWrite, в вашем классе рекордера и напишите, только если он установлен в YES. Очередь начинает получать данные от начала и постоянно заполняет буферы, но вы просто вставляете эти данные в обратный вызов, пока флаг не останется. Затем в любой момент установите 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

Спасибо, Владимир, подход булевского флага для MyInputBufferHandler работал отлично. – Halle

+0

Я хотел добавить (для тех, кто читает это, кто хочет попробовать), что моя функция выше должна быть изменена, чтобы включить вызов AudioFileCreateWithURL, чтобы он имел аудиофайл для записи, когда ему говорят писать - функция StartRecord() в проекте примера кода Apple SpeakHere показывает хороший пример того, как это сделать. – Halle