Как начать запись существующего AudioQueue в ответ на событие? - PullRequest
3 голосов
/ 19 марта 2010

Я пишу класс, который открывает AudioQueue и анализирует его характеристики, а затем при определенных условиях может начинать или заканчивать запись файла из этого AudioQueue, который уже создан. Это мой код (полностью основанный на SpeakHere), который открывает AudioQueue, ничего не записывая в tmp:

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

1 Ответ

4 голосов
/ 19 марта 2010

Вы можете приостановить / запустить аудио-очередь в любое время с помощью 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));
    }
}
...