Stream recording on PulseAudio starts before startStream being called
dagargo opened this issue · comments
I've noticed that when using PulseAudio as the backend, an "internal" recording buffer is filled up before startStream
is being called.
Audio playback seems to work as expected.
Other backends seem to record as expected too (tested on LINUX_PULSE and WINDOWS_WASAPI).
This happens at least since 5.2.0 and the behavior is present in the master branch too.
This minimal patch over the included test record.cpp
provides the proof. Notice the 5 s sleep.
$ git diff record.cpp
diff --git a/tests/record.cpp b/tests/record.cpp
index c5f9cb5..2587247 100644
--- a/tests/record.cpp
+++ b/tests/record.cpp
@@ -111,7 +111,7 @@ int main( int argc, char *argv[] )
// minimal command-line checking
if ( argc < 3 || argc > 6 ) usage();
- RtAudio adc;
+ RtAudio adc = RtAudio(RtAudio::LINUX_PULSE);
std::vector<unsigned int> deviceIds = adc.getDeviceIds();
if ( deviceIds.size() < 1 ) {
std::cout << "\nNo audio devices found!\n";
@@ -165,6 +165,9 @@ int main( int argc, char *argv[] )
goto cleanup;
}
+ sleep (5);
+ std::cout << "Start recording...";
+
if ( adc.startStream() ) goto cleanup;
std::cout << "\nRecording for " << time << " seconds ... writing file 'record.raw' (buffer frames = " << bufferFrames << ")." << std::endl;
When asking the included script record
for a 5 s sample, this is the result.
tests$ ./record 2 48000 5
Start recording...
Recording for 5 seconds ... writing file 'record.raw' (buffer frames = 512).
Obviously, there is a pause of 5 s before the first line is printed. Then, there is no pause between the first message and the second one and the execution ends. The callback is invoked at the moment of calling startStream
as many times as needed to provide the client the with the 5 s of recorded audio since openStream
.
Can anyone replicate this or am I missing something?
Before giving it a try, I need to be sure the error is not on my side.
I don't have easy access to a pulse audio system to test but one thing you could try is to change "buffer_attr.maxlength = -1; " on line 9524 of the latest master branch version of RtAudio.cpp to something like "buffer_attr.maxlength = 4 * bufferBytes;"
Or change it to the setting for playback on line 9539.
You were right.
The issue was in the initialization of maxlength
. As per the docs, it can be initialized to (uint32_t) -1
but that doesn't seem to work.
Setting attr_ptr
to nullptr
like in the OUTPUT
mode like doesn't work either.
Line 9545 in 13a5839
This patches fixes it. As options might be not initialized, a check is needed to use numberOfBuffers
.
$ git diff
diff --git a/RtAudio.cpp b/RtAudio.cpp
index b13f04e..5e05e03 100644
--- a/RtAudio.cpp
+++ b/RtAudio.cpp
@@ -9521,7 +9521,11 @@ bool RtApiPulse::probeDeviceOpen( unsigned int deviceId, StreamMode mode,
pa_buffer_attr buffer_attr;
case INPUT:
buffer_attr.fragsize = bufferBytes;
- buffer_attr.maxlength = -1;
+ if ( options && options->numberOfBuffers > 0 ) {
+ buffer_attr.maxlength = bufferBytes * options->numberOfBuffers;
+ } else {
+ buffer_attr.maxlength = bufferBytes;
+ }
pah->s_rec = pa_simple_new( NULL, streamName.c_str(), PA_STREAM_RECORD,
dev_input, "Record", &ss, NULL, &buffer_attr, &error );
Should I create a PR?
I just tested this. I verified the behavior you described initially. But when I made the suggested change, I found that the record.cpp test program never finishes if maxlength is set to bufferBytes. I had to make maxlength at least equal to 2 * bufferBytes to work. I am committing a change that fixes this but I will use (options->numberOfBuffers+1) if options are provided and bufferBytes * 4 otherwise. I just pushed the change to the repo.