Results 1 to 10 of 10

Thread: Qt Audio in Linux and Windows: different behaviour

  1. #1
    Join Date
    Mar 2008
    Posts
    51
    Thanks
    2
    Thanked 2 Times in 2 Posts
    Platforms
    Unix/X11 Windows

    Default Qt Audio in Linux and Windows: different behaviour

    I have an application (SDR type) where the software generates a nice stream of PCM audiosamples and the output is made audible using QAudio to the soundcard of the PC
    The current version runs with Qt5, and I am in the transition from Qt5 to Qt

    I have a version that runs fine under Linux, but - it is cross compiled - under Windows it does not generate sound and does not give error messages either
    It should be possible to have it run under Windows, the audioOutput example from the Qt sourcetree runs both under Linux and Windows fine

    The structure of the class, driving the output, is basic, it is a class in which an AudioSink and a IODevice are created and the incoming samples are stored in a large ringbuffer
    Part of the code that is executed on a (re)start, where newDeviceIndex is just in index is the vector ith device descriptions. the format is stored in m_settings:

    Qt Code:
    1. if (newDeviceIndex < 0)
    2. return;
    3. QAudioDevice currentDevice
    4. = outputDevices. at (newDeviceIndex);
    5. fprintf (stderr, "going for %s\n",
    6. currentDevice. description (). toLatin1 (). data ());
    7. m_audioSink = new QAudioSink (currentDevice, m_settings);
    8.  
    9. m_audioSink -> setBufferSize (8 * 32768);
    10. connect (m_audioSink, &QAudioSink::stateChanged,
    11. this, &Qt_Audio::state_changed);
    12. //
    13. // and run off
    14. theIODevice -> close ();
    15. delete theIODevice;
    16. theIODevice = new Qt_AudioDevice (mr, &tempBuffer);
    17. theIODevice -> start ();
    18. m_audioSink -> start (theIODevice);
    19.  
    20. QtAudio::Error err = m_audioSink -> error ();
    21. fprintf (stderr, "Errorcode %d\n", (int)(err));
    To copy to clipboard, switch view to plain text mode 
    And the IODevice is the most simple one one can imagine

    Qt Code:
    1. void Qt_AudioDevice::start () {
    2. if (running. load ())
    3. return;
    4. bool b = open (QIODevice::ReadOnly);
    5. fprintf (stderr, "Opening QIODevice %s\n", b ? "ok" : "error");
    6. running. store (true);
    7. }
    8.  
    9. // we always return "maxSize" bytes
    10. qint64 Qt_AudioDevice::readData (char* buffer, qint64 maxSize) {
    11. qint64 amount = 0;
    12. // "maxSize" is the requested size in bytes
    13. // "amount" is in uint8_t's
    14. amount = Buffer -> getDataFromBuffer (buffer, maxSize);
    15.  
    16. if (amount < maxSize) {
    17. for (int i = amount; i < maxSize; i ++)
    18. buffer [i] = (char)(0);
    19. }
    20.  
    21. totalBytes_l += amount;
    22. missedBytes_l += maxSize - amount;
    23. return maxSize;
    24. }
    To copy to clipboard, switch view to plain text mode 


    On a state change I print the state,
    On Linux, the message is - after opening the device "activeState"
    On windows, the message with opening is that opening was successfull and the state is "Idle"

    Format is 48000, 2 channels and floats (bit I tried Int16 as well with the same result)

    Any help would really be appreciated

    Jan
    Last edited by d_stranz; 26th December 2024 at 01:48. Reason: missing [code] tags

  2. #2
    Join Date
    Mar 2008
    Posts
    51
    Thanks
    2
    Thanked 2 Times in 2 Posts
    Platforms
    Unix/X11 Windows

    Default Re: Qt Audio in Linux and Windows: different behaviour

    I simplified the code and made it into a small example with the same behaviour,
    The "start" function now only reads
    Qt Code:
    1. const QAudioDevice &defaultDevice =
    2. QMediaDevices::defaultAudioOutput ();
    3. m_audioSink = new QAudioSink (defaultDevice, m_settings);
    4. connect (m_audioSink, &QAudioSink::stateChanged,
    5. this, &Qt_Audio::state_changed);
    6. theIODevice. start ();
    7. m_audioSink -> start (&theIODevice);
    8. QtAudio::Error err = m_audioSink -> error ();
    9. fprintf (stderr, "Errorcode %d\n", (int)(err));
    To copy to clipboard, switch view to plain text mode 
    The behaviour is the same, in the example I just generate a tone of 600 Hz, and add per 100 msec a buffer
    Under Linux the tone is OK, the status report tells the the AudioSink is active
    Under Windows no errors, state is Idle, and the read function is NOT called
    Qt Code:
    1. void Qt_AudioDevice::start () {
    2. bool b = open (QIODevice::ReadOnly);
    3. }
    4.  
    5. // we always return "maxSize" bytes
    6. qint64 Qt_AudioDevice::readData (char* buffer, qint64 maxSize) {
    7. qint64 amount = 0;
    8. static int64_t teller = 0;
    9. amount = Buffer -> getDataFromBuffer (buffer, maxSize);
    10. if (amount < maxSize) {
    11. for (int i = amount; i < maxSize; i ++)
    12. buffer [i] = (char)(0);
    13. }
    14.  
    15. return maxSize;
    16. }
    To copy to clipboard, switch view to plain text mode 

    Fot me the question is, why is the state "Idle" in Windows, when in Linux it is "Active"

    suggestions?

    best
    jan
    Last edited by d_stranz; 28th December 2024 at 00:15. Reason: missing [code] tags

  3. #3
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,289
    Thanks
    310
    Thanked 869 Times in 856 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Qt Audio in Linux and Windows: different behaviour

    I am wondering whether you need to tell Windows to give your program permission to use the audio device? Or whether you need to run your program as Administrator? I know that for things like Zoom, you must give permission for it to use the camera, microphone, and speakers.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  4. #4
    Join Date
    Mar 2008
    Posts
    51
    Thanks
    2
    Thanked 2 Times in 2 Posts
    Platforms
    Unix/X11 Windows

    Default Re: Qt Audio in Linux and Windows: different behaviour

    Rgabjs,
    But the audiooutput example from the the examples in the Qt sources works just fine.
    I merely copied the code, the difference being that they use as QIOdevice a program that generates the data by itsellf
    Anyway, thanks for the effort

  5. #5
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,289
    Thanks
    310
    Thanked 869 Times in 856 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Qt Audio in Linux and Windows: different behaviour

    Something else that comes to mind: Is the endianess (byte order) different between linux and Windows? In the audiooutput example, the bytes are internally generated so the byte order is consistent. In your case, I get the idea that you are connecting to an external SDR stream where the byte order could be different.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  6. #6
    Join Date
    Mar 2008
    Posts
    51
    Thanks
    2
    Thanked 2 Times in 2 Posts
    Platforms
    Unix/X11 Windows

    Default Re: Qt Audio in Linux and Windows: different behaviour

    That is true, but that does not explain why the Audiosink opens without error and then goes into state Idle. especially when the QIODevice reports that opening is fine, The result is that in the end no bytes are read.
    If I understand the documentation, then the Audiosink goes into state Idle if there is no input, but I ensured that a buffer is filled, and then no element of the buffer is read
    And again, using Linux, it works fine, so either the Windows version should have worked, or the Linux version works while it should not

  7. #7
    Join Date
    Mar 2008
    Posts
    51
    Thanks
    2
    Thanked 2 Times in 2 Posts
    Platforms
    Unix/X11 Windows

    Default Re: Qt Audio in Linux and Windows: different behaviour

    Quote Originally Posted by janK View Post
    That is true, but that does not explain why the Audiosink opens without error and then goes into state Idle. especially when the QIODevice reports that opening is fine, The result is that in the end no bytes are read.
    If I understand the documentation, then the Audiosink goes into state Idle if there is no input, but I ensured that a buffer is filled, and then no element of the buffer is read
    And again, using Linux, it works fine, so either the Windows version should have worked, or the Linux version works while it should not

    I think the basic quesiton is
    if the creation of a QIODevice and the creation of an QAudioSink is also without errors,
    under what conditions changes the AudioSink the state to "Idle"

    I checked again btw that while sthe "start" of the QIODevice is - according to the QIODevice = without problems, the "readData" function
    is not called at all. So, it seems that the AudioSink does not see that the readData function can be called

    Anyway, in the documentation I do not find any clue of why this behavious happens under Windows

  8. #8
    Join Date
    Mar 2008
    Posts
    51
    Thanks
    2
    Thanked 2 Times in 2 Posts
    Platforms
    Unix/X11 Windows

    Default Re: Qt Audio in Linux and Windows: different behaviour

    Implementing the (virtual) bytesAvailable function for the derives QUIDevice class did the trick. It remains a mystery why the Linux implementation apaprently does not require that and rhe windows ine does
    (Both are 6.8.1)

  9. The following user says thank you to janK for this useful post:

    d_stranz (10th January 2025)

  10. #9
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,289
    Thanks
    310
    Thanked 869 Times in 856 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Qt Audio in Linux and Windows: different behaviour

    Implementing the (virtual) bytesAvailable function for the derives QUIDevice class did the trick.
    I assume you meant QIODevice. It would be nice if you could post your code for that to help others who might experience the same problem in the future and come across this thread looking for an answer.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  11. #10
    Join Date
    Mar 2008
    Posts
    51
    Thanks
    2
    Thanked 2 Times in 2 Posts
    Platforms
    Unix/X11 Windows

    Default Re: Qt Audio in Linux and Windows: different behaviour

    Quote Originally Posted by d_stranz View Post
    I assume you meant QIODevice. It would be nice if you could post your code for that to help others who might experience the same problem in the future and come across this thread looking for an answer.
    The siruation was roughly as sketched below, a derived class from QIODevice was used and sound was output under Linux and silence was output under Windows
    Under windows, the AudioSink that was use to embed the derived QIODevice class gave state Idle under Window and Active under Linux
    The read function implemented in the derived QIOdevice class always gives the required amount of bytes back, taken from abuffer and a shortage, if appearing, filled with o bytes.
    The original version differs from the one given below by not having impmented the "bytesAvailable" function and the "sze" function.
    After implementing the bytesAvailable function itworked fine. Appparently the Windows version of AudioSink - when started- first looks at the bytesAvailable function, while the
    same class in the Linux version does not.

    The amount returned by the bytesAvailable function did not matter, as long as the (virtual) function is reimplemented and returns a value > 0 it works fine (again, given that the read function always returns the
    requested amount

    In both cases it was version 6.8.1.

    Qt Code:
    1. Qt_AudioDevice::~Qt_AudioDevice () {
    2. close ();
    3. }
    4.  
    5. void Qt_AudioDevice::start () {
    6. bool b = open (QIODevice::ReadOnly);
    7. }
    8.  
    9. // we always return "maxSize" bytes
    10. qint64 Qt_AudioDevice::readData (char* buffer, qint64 maxSize) {
    11. // "maxSize" is the requested size in bytes
    12. // "amount" is in uint8_t's
    13. amount = Buffer -> getDataFromBuffer (buffer, maxSize);
    14. if (amount < maxSize) {
    15. for (int i = amount; i < maxSize; i ++)
    16. buffer [i] = (char)(0);
    17. }
    18. }
    19.  
    20. // usused here
    21. qint64 Qt_AudioDevice::writeData (const char* data, qint64 len) {
    22. Q_UNUSED (data);
    23. Q_UNUSED (len);
    24. return 0;
    25. }
    26.  
    27.  
    28. qint64 Qt_AudioDevice::bytesAvailable () const {
    29. return 32768;
    30. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by d_stranz; 16th January 2025 at 17:42. Reason: missing [code] tags

  12. The following user says thank you to janK for this useful post:

    d_stranz (16th January 2025)

Similar Threads

  1. Left audio channel intermittently drops out (QAudioOutput, Linux)
    By QtDrivesMeCrazy in forum Qt Programming
    Replies: 0
    Last Post: 2nd March 2016, 00:09
  2. Replies: 5
    Last Post: 10th June 2014, 12:26
  3. Replies: 0
    Last Post: 8th December 2011, 13:21
  4. executing a audio player code on Embedded linux
    By sureshlohith in forum Qt for Embedded and Mobile
    Replies: 0
    Last Post: 21st April 2010, 06:17
  5. Replies: 2
    Last Post: 4th June 2009, 17:09

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.