2010-03-18 1 views
3

J'écris une classe qui ouvre une AudioQueue et analyse ses caractéristiques, puis, sous certaines conditions, peut commencer ou terminer l'écriture d'un fichier de cette AudioQueue qui est déjà instancié. Ceci est mon code (entièrement basé sur SpeakHere) qui ouvre la AudioQueue sans écrire quoi que ce soit à tmp:Comment commencer à écrire une AudioQueue existante en réponse à un événement?

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"); 
} 
} 

Mais je suis un peu clair sur la façon d'écrire une fonction qui racontera cette file d'attente « d'ici le signal d'arrêt, commencez à écrire cette file d'attente à tmp en tant que fichier ". Je comprends comment dire à un AudioQueue d'écrire en tant que fichier au moment où il est créé, comment définir le format des fichiers, etc., mais pas comment lui dire de démarrer et d'arrêter le flux intermédiaire. Beaucoup reconnaissant de tout pointeur, merci.

Répondre

4

Vous pouvez suspendre/démarrer la file audio à tout moment avec AudioQueuePause (AudioQueueRef inAQ) et AudioQueueStart (AudioQueueRef inAQ, const AudioTimeStamp * inStartTime);

Et il y a plus de possibilités. Parce que vous écrivez audiofile dans la fonction de rappel, vous pouvez choisir quand et quelles données doivent être sauvegardées.

Pour contrôler les données d'écriture ou non, créez un indicateur bool par exemple "doWrite" dans votre classe d'enregistreur et n'écrivez que s'il est défini sur YES. La file d'attente commence à recevoir des données depuis le début et remplit continuellement les tampons, mais vous n'avez besoin que de ces données dans le rappel jusqu'à ce que le drapeau reste NON. Puis, à tout moment, définissez doWrite = YES et le tampon suivant sera sauvegardé dans le fichier. Cette approche est particulièrement utile lorsque vous modifiez l'enregistrement en fonction du son lui-même (par exemple, enregistrez uniquement si le son est plus fort qu'une certaine valeur de 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

Merci Vladimir, l'approche du drapeau booléen pour MyInputBufferHandler a parfaitement fonctionné. – Halle

+0

Je voulais ajouter (pour quiconque lit ceci qui veut l'essayer) que ma fonction ci-dessus devrait être changée pour inclure un appel à AudioFileCreateWithURL de sorte qu'il ait un fichier audio à écrire quand on lui dit d'écrire - la fonction StartRecord() dans le projet de code exemple SpeakHere d'Apple montre un bon exemple de la façon de procéder. – Halle

Questions connexes