Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
6.8.0
-
As seen in Calibre 7.20 TTS, Ubuntu 22.04, X11 and reproduced with PySide
Description
This is a reproduction of a problem seen using Calibre 7.20 TTS on Ubuntu 22.04.
When a QAudioSink is initialised with a large buffer, it does not play the audio it reads from a custom QIODevice if the QIODevice initially starts empty.
The attached PySide script incrementally generates sound data and signals the QAudioSink when there is more to read. It has command line parameters to start with/without an initially empty QIODevice and set the buffer size.
We see a different pattern of calls on the custom QIODevice when it works and when it does not.
a) When it fails, the QAudioSink only calls QIODevice.atEnd once and does not transition from Active to Idle after each sound clip has been read.
b) We also see inconsistent calls to QIODevice.readData between the different cases. If using the default buffer size, QIODevice.readData never gets called with a zero length (which the docs say is to allow for cleanup activity)
There are three main cases of interest:
1. bug reproduction - start empty but with large buffer -> no sound
python audio_test.py --start_empty 2097152
starting with buffer_size=2097152, start_empty=True
config: start QIODevice without data
config: Use QAudioSink buffer size 2097152
QIODevice.isSequential
QIODevice.bytesAvailable 0
QAudioSink.state = ActiveState
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.atEnd True
– generate data --
QIODevice.readData -returned 16384 bytes maxlen=16384
QIODevice.readData -returned 10076 bytes maxlen=16384
QIODevice.readData - Zero length requested
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.atEnd True
– generate data --
QIODevice.readData -returned 16384 bytes maxlen=16384
QIODevice.readData -returned 10076 bytes maxlen=16384
QIODevice.readData - Zero length requested
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.atEnd True
– generate data --
QIODevice.readData -returned 16384 bytes maxlen=16384
QIODevice.readData -returned 10076 bytes maxlen=16384
QIODevice.readData - Zero length requested
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.atEnd True
2. workaround - use a large buffer but ensure data is ready before QAudioSink.start -> makes sound
python audio_test.py 2097152
starting with buffer_size=2097152, start_empty=False
config: start QIODevice with data ready
config: Use QAudioSink buffer size 2097152
QIODevice.isSequential
QIODevice.bytesAvailable 26460
QAudioSink.state = ActiveState
QIODevice.readData -returned 16384 bytes maxlen=16384
QIODevice.readData -returned 10076 bytes maxlen=16384
QIODevice.readData - Zero length requested
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.atEnd True
QIODevice.atEnd True
QAudioSink.state = IdleState
– generate data --
QIODevice.readData -returned 16384 bytes maxlen=16384
QAudioSink.state = ActiveState
QIODevice.readData -returned 10076 bytes maxlen=16384
QIODevice.readData - Zero length requested
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.atEnd True
QIODevice.atEnd True
QAudioSink.state = IdleState
– generate data --
QIODevice.readData -returned 16384 bytes maxlen=16384
QAudioSink.state = ActiveState
QIODevice.readData -returned 10076 bytes maxlen=16384
QIODevice.readData - Zero length requested
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.atEnd True
QIODevice.atEnd True
QAudioSink.state = IdleState
3. workaround - start empty but don't set a buffer size and just use default -> makes sound
python audio_test.py --start_empty 0
starting with buffer_size=0, start_empty=True
config: start QIODevice without data
config: Use default QAudioSink buffer size 8820
QIODevice.isSequential
QIODevice.bytesAvailable 0
QAudioSink.state = ActiveState
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.atEnd True
– generate data --
QIODevice.readData -returned 16384 bytes maxlen=16384
QIODevice.readData -returned 10076 bytes maxlen=16384
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.atEnd True
QIODevice.atEnd True
QAudioSink.state = IdleState
– generate data --
QIODevice.readData -returned 16384 bytes maxlen=16384
QAudioSink.state = ActiveState
QIODevice.readData -returned 10076 bytes maxlen=16384
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.atEnd True
QIODevice.atEnd True
QAudioSink.state = IdleState
– generate data --
QIODevice.readData -returned 16384 bytes maxlen=16384
QAudioSink.state = ActiveState
QIODevice.readData -returned 10076 bytes maxlen=16384
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.readData -returned 0 bytes maxlen=16384
QIODevice.atEnd True
QIODevice.atEnd True
QAudioSink.state = IdleState