2017-01-25 4 views
0

konfrontiert seltsam PulseAudio Monitor Gerät (d. H. Audio-Eingabegerät, das Ton an den Lautsprecher gesendet) Verhalten. Ich habe den Code von meinem realen Projekt auf ein einfaches Beispiel basierend auf Code von PulseAudio Docs https://freedesktop.org/software/pulseaudio/doxygen/parec-simple_8c-example.html reduziert, ich habe nur Zeitlimit hinzugefügt und Bytes zählen. Es funktioniert zum Beispiel 30 Sekunden und druckt gelesene Bytes. Problem ist, dass die Anzahl der Bytes sehr unterschiedlich ist, wenn während des Programmlaufs etwas gespielt wird. Ich habe dieses Programm ausgeführt und parallel ausgeführt Bash for Schleife bestehend aus aplay mit kurzen tada.wav Datei. Der Unterschied beträgt 9%. Um es mehr zu testen, habe ich versucht, 4 solcher Schleifen parallel zu PulseAudio zu betreiben, und der Unterschied ist sogar noch größer - 34%. Aber wenn anstelle von mehreren aplay mit kurzen wav ich mplayer mit langen mp3-Datei laufen - gibt es keinen solchen Unterschied, Bytes Anzahl ist ähnlich zu Fall, wenn kein Ton gespielt wird.Strange PulseAudio Monitor Gerät Verhalten

Ein solches Verhalten verursacht einen Fehler in der Soundverarbeitung in meinem realen Projekt. Wenn also jemand vorschlagen könnte, wie ich es lösen könnte - ich bin sehr dankbar.

Ähnliche Code auf Windows, Qt basiert und mit Stereo-Mixer-Gerät als Analog von PulseAudio-Monitor funktioniert ohne solche Probleme.

Hier ist mein Code auf Beispiel von Pulseaudio-Dokumentation basiert:

#ifdef HAVE_CONFIG_H 
#include <config.h> 
#endif 

#include <iostream> 
#include <chrono> 

#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 
#include <errno.h> 

#include <pulse/simple.h> 
#include <pulse/error.h> 

#define BUFSIZE 1024 

using namespace std; 
using namespace std::chrono; 

int main(int argc, char *argv[]) 
{ 
    int duration = 30000; 
    int64_t readBytesCounter = 0; 
    milliseconds msStart = duration_cast<milliseconds>(system_clock::now().time_since_epoch()); 

    /* The sample type to use */ 
    static const pa_sample_spec ss = { 
     .format = PA_SAMPLE_S16LE, 
     .rate = 44100, 
     .channels = 2 
    }; 
    pa_simple *s = NULL; 
    int ret = 1; 
    int error; 
    /* Create the recording stream */ 
    if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, "alsa_output.pci-0000_00_1b.0.analog-stereo.monitor", "record", &ss, NULL, NULL, &error))) { 
     fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); 
     goto finish; 
    } 
    for (;;) { 
     uint8_t buf[BUFSIZE]; 
     /* Record some data ... */ 
     if (pa_simple_read(s, buf, sizeof(buf), &error) < 0) { 
      fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error)); 
      goto finish; 
     } 
     readBytesCounter += BUFSIZE; 

     milliseconds msCurrent = duration_cast<milliseconds>(system_clock::now().time_since_epoch()); 
     int elapsed = msCurrent.count() - msStart.count(); 
     if (elapsed > duration) 
     { 
      cerr << int(elapsed/1000) << " seconds elapsed, terminating" << endl; 
      cerr << readBytesCounter << " bytes read" << endl; 
      goto finish; 
     } 
    } 
    ret = 0; 
finish: 
    if (s) 
     pa_simple_free(s); 
    return ret; 
} 

Es ist mit folgendem Befehl gebaut werden kann:

g++ -o main main.cpp -lpulse -lpulse-simple -std=c++11 

Beispiel WAV-Datei i

von http://d0.waper.ru/f/462151/23/HgDwimvX37CwxWqW38eywg%2C1485353628/7d74/9/462151.wav/tada.wav genommen habe Und hier sind Testergebnisse:

Test 1. Kein Ton in spea Ker

$ time ./main 
30 seconds elapsed, terminating 
5323776 bytes read 

real 0m30.028s 
user 0m0.168s 
sys  0m0.388s 

Test 2. Bash for loop „für i in Seq.-1 22; tu asplay tada.wav; kurzen WAV-Dateien im Hintergrund getan“mit. Bytes zählt Anstieg ist 5798912/5323776 = 1.089 Zeiten.

$ time ./main 
30 seconds elapsed, terminating 
5798912 bytes read 

real 0m30.023s 
user 0m0.120s 
sys  0m0.184s 

Test 3 4 Bash for Schleifen mit kurzen WAV-Dateien im Hintergrund. Bytes zählt Anstieg ist 7129088/5323776 = 1.339 Zeiten.

$ time ./main 
30 seconds elapsed, terminating 
7129088 bytes read 

real 0m30.019s 
user 0m0.164s 
sys  0m0.196s 

-Test 4. mplayer mit langen mp3 im Hintergrund. 5288960/5323776 = 0.993, dh es wird kein signifikantes Bytes Unterschied zählen.

$ time ./main 
30 seconds elapsed, terminating 
5288960 bytes read 

real 0m30.024s 
user 0m0.096s 
sys  0m0.204s 

Versucht, einen Satz von jedem Test auszuführen, durchschnittliche Anzahl der Bytes - ähnliche Differenz.

PS: Konfiguration meines Systems:

  • OS Ubuntu 16.04.1 amd64
  • Pulseaudio 1: 8.0-0ubuntu3.2
  • alsa-base 1.0.25 + dfsg-0ubuntu5

Antwort

1

Hier ist die Antwort von Tanu Kaskinen von PulseAudio Mailingliste https://lists.freedesktop.org/archives/pulseaudio-discuss/2017-January/027412.html.Keine vollständige Antwort, aber eine kleine Erklärung und Abhilfe:

Sie wahrscheinlich einen bekannten Bug schlagen wir mit rewind haben in Monitor Quellen Handhabung („bekannten“ bedeutet in diesem Fall, dass die Symptome sind bekannt, aber nicht die genaue Ursache). Wenn ein Stream beginnt, auf die überwachte Senke abzuspielen, schreibt die Senke den Inhalt ihres Wiedergabepuffers um (dies wird als "Rückspulen" bezeichnet), was zu einem Störimpuls in der Quelle des Monitors führt Stream, nach Ihren Experimenten zu urteilen). Ich hoffe, das eines Tages zu beheben, aber es sieht nicht so aus, als hätte ich in naher Zukunft Zeit dafür. Wenn Sie die Zeit und Motivation haben, den Fehler zu untersuchen und zu beheben, wäre das genial.

Um dieses Problem zu umgehen, können Sie die Größe des Fehlers wahrscheinlich reduzieren, indem Sie die Größe des Wiedergabepuffers verringern. Um dies zu tun, übergeben tsched_buffer_size = X Modul-udev-detect in /etc/pulse/default.pa (X ersetzen mit dem Puffergröße in Bytes).“