9
votes

Enregistrement continu dans Portudio (à partir de micro ou de sortie)

J'essaie de créer une application de la musique Visualizer à Portaudo, j'ai fait des recherches de base et j'ai trouvé quelques exemples sur la manière d'enregistrer à partir d'un micro à un fichier (temporaire). Mais il n'y avait aucun exemple si les données ne sont pas utilisées du temps d'exécution pendant l'enregistrement.

Alors, comment puis-je démarrer un audio-flux continu où je peux attraper les données du "cadre" actuel?

Ceci C'est comme ça que j'ai essayé de le faire: xxx

mais il donne la sortie suivante: xxx


2 commentaires

Sur quelle plate-forme travaillez-vous?


Je travaille sur Debian Linux (64 bits)


4 Réponses :


5
votes

update em>:

Quel est le but de ce code? p>

static void* data;
/* ... */
static int recordCallback(const void* inputBuffer, void* outputBuffer, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void* userData){
    testData* data = (testData*)userData;
    /* ... */
}


6 commentaires

Merci de pointer ces erreurs, j'ai essayé de les réparer le mieux que je pouvais, mais l'erreur reste toujours; Je ne pense pas que cela ait quelque chose à voir avec la répartition de la mémoire, car maintenant (voir la question mise à jour), je reçois toujours l'erreur de flux actif : impossible de lire à partir d'un flux de rappel Erreur. Donc, il se casse sur l'appel Pa_GetstreamReadAnter , mais j'ai un microphone utilisable connecté à mon ordinateur. J'aimerais également que l'alternative d'utiliser le son mon propre ordinateur envoie en tant que sortie.


Je n'avais pas le temps de vérifier votre réponse, mais depuis que le temps pour les points est presque terminé, je vous l'accorderai; Je vais vérifier plus tard ce jour!


Eh bien, faites-moi savoir comment cela fonctionne ... Je n'aime pas beaucoup Alsa, mais je suis toujours heureux d'apprendre. Je vais vous aider à comprendre ce qui ne va pas ...


Ah j'ai finalement eu une demi-heure à regarder, ça va à la boucle quand je suppose cette déclaration; Mais je n'ai aucune idée de comment obtenir les données, lorsque j'ajouterai fprintf (stardr, "flux:% s \ n", données-> enregistrements d'enregistrement); à la fonction RecordCallback i obtenez : H� $ � # une fois, et quand je l'ajoutez à la boucle tandis que cela reste vide!


@THOMASVERSTEEG Y a-t-il des preuves pour suggérer que Data-> enregistrements d'enregistrement pointe sur une chaîne (c'est-à-dire qu'il est garanti d'être '\ 0' terminé)? Sinon, alors % s n'est peut-être pas le spécificateur de format correct. Peut-être que ces données pourraient contenir des octets non imprimables, vous voudrez peut-être le jeter comme hexagonal: FPRINTF (STDRERR, "Stream:"); pour (x = 0; x trafrindex; x ++) {fprintf ("% x", données de caractères (sans signification )-> enregistrées [x]); } puchar ('\ n');


J'ai essayé d'ajouter votre morceau de code sur divers endroits de mon code source mais tout ce que je reçois est un flux vide: ; Et quand je l'ajoute dans la boucle tandis que Pa_sleep () Je reçois un flux complet de flux: et il quitte le code 139 (Segfault).



0
votes

Vous avez fermé le flux err = pa_closetream (flux); dans la première itération. Dans la deuxième itération, la chaîne était déjà fermée. Essayez l'opération err = pa_closetream (flux); après toutes les itérations.


1 commentaires

Lorsque je retire la ligne, vous avez souligné, je ne reçois toujours pas les données.



2
votes

Pour interagir avec le flux de données en temps réel, vous aurez besoin d'un mécanisme qui dort (occupé attend des fenêtres) pour la période de trame (taux d'échantillonnage / échantillons par image) ou utilise une primitive de synchronisation de fil pour déclencher votre fil Int Main Code> qu'il y a de l'audio prêt à être traité. Cela vous donnera accès à chaque image de données que Portudio fournit lors de son rappel (appelé à partir du fil de Portudio). Voici comment le concept fonctionne à l'aide de Boost :: Condition code> et Boost :: Mutex code>.

//CAUTION THIS SNIPPET IS ONLY INTENDED TO DEMONSTRATE HOW ONE MIGHT
//SYNCHRONIZE WITH THE PORTAUDIO THREAD

#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>

#include "portaudio.h"

boost::condition waitForAudio;
boost::mutex waitForAudioMutex;
boost::mutex audioBufferMutex;
bool trigger = false;

std::deque<char> audioBuffer;

static int recordCallback(const void* inputBuffer, void* outputBuffer, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void* userData){

    const char* buffer_ptr = (const char*)inputBuffer;

    //Lock mutex to block user thread from modifying data buffer
    audioBufferMutex.lock();

    //Copy data to user buffer
    for(i = 0; i < frameCount; ++i) {
       audioBuffer.push_back(buffer_ptr + i);
    }

    //Unlock mutex, allow user to manipulate buffer
    audioBufferMutex.unlock();

    //Signal user thread to process audio
    waitForAudioMutex.lock();
    trigger= true;
    waitForAudio.notify_one();
    waitForAudioMutex.unlock();

    return finished;
}

int main(){
        Pa_Initialize();
        //OPEN AND START PORTAUDIO STREAM
        while(true){ //Catch signal (Ctrl+C) or some other mechanism to interrupt this loop
            boost::xtime duration;
            boost::xtime_get(&duration, boost::TIME_UTC);
            boost::interprocess::scoped_lock<boost::mutex> lock(waitForAudioMutex);
            if(!trigger) {
                if(!waitForAudio.timed_wait(lock, duration)) {
                    //Condition timed out -- assume audio stream failed
                    break;
                }
            }
            trigger= false;

            audioBufferMutex.lock();
            //VISUALIZE AUDIO HERE
            //JUST MAKE SURE TO FINISH BEFORE PORTAUDIO MAKES ANOTHER CALLBACK
            audioBufferMutex.unlock();
        }
        //STOP AND CLOSE PORTAUDIO STEAM
        Pa_Terminate();
        return 0;
    }


2 commentaires

@Ashishk Quel est ton doute?


HI @Trukvl Demandez votre suggestion sur cette option s'il vous plaît ( Stackoverflow.com/Questtions/44645466/... )



-1
votes

J'ai résolu de cette façon:

    PaStreamParameters  inputParameters ,outputParameters;
    PaStream*           stream;
    PaError             err;  
    paTestData          data;
    int                 i;
    int                 totalFrames;
    int                 numSamples;
    int                 numBytes;

    err                     = paNoError;
    inputParameters.device  = 4;

    data.maxFrameIndex      = totalFrames = NUM_SECONDS * SAMPLE_RATE;
    data.frameIndex         = 0;
    numSamples              = totalFrames * NUM_CHANNELS;
    numBytes                = numSamples * sizeof(SAMPLE);
    data.recordedSamples    = (SAMPLE *) malloc( numBytes );

    std::ofstream arch;
    arch.open("signal.csv");

    err = Pa_Initialize();
    inputParameters.channelCount = 1;                    
    inputParameters.sampleFormat = PA_SAMPLE_TYPE;
    inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
    inputParameters.hostApiSpecificStreamInfo = NULL;

    int contador = 0;
    bool strec = true;
    while (strec)
    {
        err = Pa_OpenStream(
              &stream,
              &inputParameters,
              NULL,                  
              SAMPLE_RATE,
              FRAMES_PER_BUFFER,
              paClipOff,      
              recordCallback,
              &data );

        err = Pa_StartStream( stream );

        printf("\n===Grabando.... ===\n"); fflush(stdout);
        Pa_Sleep(3000);
        while( ( err = Pa_IsStreamActive(stream) ) == 1 )
        {

        }

        err = Pa_CloseStream( stream );

        for( i=0; i<numSamples; i++ )

        {

            val = data.recordedSamples[i];

            arch << val << std::endl;
            std::cout << std::endl << "valor  : " << val;
        }

        data.frameIndex = 0;
        contador++;
        if (contador >= 100) //if you delete this condition continuously recorded this audio
        {
            strec = false;
            arch.close();
        }
    }


0 commentaires