Столкнувшись с необычным устройством мониторинга PulseAudio (то есть устройством ввода звука, которое воспроизводит звук, отправленный динамику). Я уменьшил код от моего реального проекта до простого примера на основе кода из PulseAudio docs https://freedesktop.org/software/pulseaudio/doxygen/parec-simple_8c-example.html, я добавил только ограничение по времени и чтение байтов. Он работает, например, 30 секунд и печатает количество считанных байтов. Проблема в том, что количество байтов значительно отличается, если во время прогона программы происходит что-то. Я выполнил эту программу и параллельно выполнил bash for
цикл, состоящий из aplay
с коротким tada.wav
файлом. Разница составляет 9%. Чтобы проверить его больше, я попытался запустить 4 таких цикла параллельно с примером PulseAudio, а разница еще больше - 34%. Но если вместо нескольких aplay
с коротким wav я запускаю mplayer
с длинным mp3-файлом - такой разницы нет, количество байт похоже на случай, когда звук не воспроизводится.Поведение монитора монитора Strange PulseAudio
Такое поведение вызывает отказ в обработке кода обработки звука в моем реальном проекте, поэтому, если кто-то может предложить, как его решить, я буду очень благодарен.
Аналогичный код на Windows, основанном на Qt и использующем устройство Stereo Mixer в качестве аналога монитора PulseAudio, без таких проблем работает.
Вот мой код, основанный на примере из PulseAudio документации:
#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;
}
Он может быть построен с помощью следующей команды:
g++ -o main main.cpp -lpulse -lpulse-simple -std=c++11
Пример Wav файл я взял из http://d0.waper.ru/f/462151/23/HgDwimvX37CwxWqW38eywg%2C1485353628/7d74/9/462151.wav/tada.wav
И вот результаты испытаний:
Тест 1. Нет звука в spea кег
$ time ./main
30 seconds elapsed, terminating
5323776 bytes read
real 0m30.028s
user 0m0.168s
sys 0m0.388s
Тест 2. Баш for
петля «для г в последовательности 1 22; сделать aplay tada.wav; сделано»с короткими Wav файлов в фоновом режиме. Bytes подсчитывать увеличение 5798912/5323776 = 1.089
раз.
$ time ./main
30 seconds elapsed, terminating
5798912 bytes read
real 0m30.023s
user 0m0.120s
sys 0m0.184s
Тест 3. 4 Bash for
петли с короткими файлами WAV в фоновом режиме. Bytes рассчитывать увеличение 7129088/5323776 = 1.339
раз.
$ time ./main
30 seconds elapsed, terminating
7129088 bytes read
real 0m30.019s
user 0m0.164s
sys 0m0.196s
Тест 4. mplayer
с длинным mp3 в фоновом режиме. 5288960/5323776 = 0.993
, т.е. никаких существенных байт не считать разницу.
$ time ./main
30 seconds elapsed, terminating
5288960 bytes read
real 0m30.024s
user 0m0.096s
sys 0m0.204s
Пытался выполнить набор каждого теста, усредненное количество байтов - аналогичную разницу.
PS: Конфигурация моей системы:
- ОС Ubuntu 16.04.1 amd64
- PulseAudio 1: 8.0-0ubuntu3.2
- ALSA база 1.0.25 + DFSG-0ubuntu5