Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. General talk
  3. Qt 6
  4. A noteworthy Qt6 issue: QIODevice::readAll() create by QAudioSource returns an odd byte length for qint16 sample points.

A noteworthy Qt6 issue: QIODevice::readAll() create by QAudioSource returns an odd byte length for qint16 sample points.

Scheduled Pinned Locked Moved Solved Qt 6
6 Posts 3 Posters 1.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • goldenhawkingG Offline
    goldenhawkingG Offline
    goldenhawking
    wrote on last edited by goldenhawking
    #1

    When I migrated a Qt5 project to Qt6, I ran into this problem. Under Windows 10, My instances of MSYS2 Qt 6.2.0 x64 compilation are not working properly. I traced the debugging and found the problem.

    My old code presupposes that readAll must return a complete sample.

    //QAudioSource *AudioInputSound = new QAudioSource(dev, format, this);
    //QIODevice InputDev = AudioInputSound->start();
    //connect(InputDev, SIGNAL(readyRead()), SLOT(OnReadMore()));
    void Dialog::OnReadMore()
    {
        //...
         QByteArray data = InputDev->readAll();
         const short * spt = (const short * ) data.constData();
         //Audio sample point size will be 4 bytes for stereo, 2 bytes for mono.
         const int point_size = sizeof(short) * channels;
         //Problem Here it is! 
         //This Operation suppose that (data.size() % point_size ==0).
         int points = data.size()/point_size;
         //Do signal process funtions.
         deal_function(spt, point_size, points);
         //When funtion returns, data will be recycled. The lost of odd tail disrupts subsequent samples.
    }
    

    But under the new Qt6, it returns an odd number of bytes. This is an issue that I didn't think through. Currently, it is solved by a cache that preserves the tail data.

    //...
    QByteArray buffer;
    void Dialog::OnReadMore()
    {
         //We can put bytes to a buffer first.
         buffer.append(InputDev->readAll());
         const short * spt = (const short * ) buffer.constData();
         const int point_size = sizeof(short) * channels;     
         //The variable "points" now refers to the maximum number of samples that can be processed. 
         int points = buffer.size()/point_size;
         deal_function(spt, point_size, points);
         //Remove old data and KEEP the tail. 
         buffer.remove(0,points* point_size);
    }
    

    This introduces some performance issues. However, it is not a big problem for low-speed devices such as sound cards.

    This is not a BUG, but this behavior of the QAudioInput module can be troubling. Some poorly designed programs crash, just like mine. For Qt, which may be used in medical devices, special attention needs to be paid to this feature.

    I wish Qt better and better!

    Qt is the best C++ framework I've ever met.

    JonBJ 1 Reply Last reply
    0
    • goldenhawkingG goldenhawking

      When I migrated a Qt5 project to Qt6, I ran into this problem. Under Windows 10, My instances of MSYS2 Qt 6.2.0 x64 compilation are not working properly. I traced the debugging and found the problem.

      My old code presupposes that readAll must return a complete sample.

      //QAudioSource *AudioInputSound = new QAudioSource(dev, format, this);
      //QIODevice InputDev = AudioInputSound->start();
      //connect(InputDev, SIGNAL(readyRead()), SLOT(OnReadMore()));
      void Dialog::OnReadMore()
      {
          //...
           QByteArray data = InputDev->readAll();
           const short * spt = (const short * ) data.constData();
           //Audio sample point size will be 4 bytes for stereo, 2 bytes for mono.
           const int point_size = sizeof(short) * channels;
           //Problem Here it is! 
           //This Operation suppose that (data.size() % point_size ==0).
           int points = data.size()/point_size;
           //Do signal process funtions.
           deal_function(spt, point_size, points);
           //When funtion returns, data will be recycled. The lost of odd tail disrupts subsequent samples.
      }
      

      But under the new Qt6, it returns an odd number of bytes. This is an issue that I didn't think through. Currently, it is solved by a cache that preserves the tail data.

      //...
      QByteArray buffer;
      void Dialog::OnReadMore()
      {
           //We can put bytes to a buffer first.
           buffer.append(InputDev->readAll());
           const short * spt = (const short * ) buffer.constData();
           const int point_size = sizeof(short) * channels;     
           //The variable "points" now refers to the maximum number of samples that can be processed. 
           int points = buffer.size()/point_size;
           deal_function(spt, point_size, points);
           //Remove old data and KEEP the tail. 
           buffer.remove(0,points* point_size);
      }
      

      This introduces some performance issues. However, it is not a big problem for low-speed devices such as sound cards.

      This is not a BUG, but this behavior of the QAudioInput module can be troubling. Some poorly designed programs crash, just like mine. For Qt, which may be used in medical devices, special attention needs to be paid to this feature.

      I wish Qt better and better!

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @goldenhawking
      I admit I know nothing about QAudioSource, but QIODevice::readAll() has never promised to read "all the data there will be", it has only ever said it will read "whatever data is currently available to it from the device", and there may well be future calls of "readyRead()" which will see further data till all has been consumed. We frequently have to remind coders here of this when they write TCP/IP/socket code and fail to take this into account. Maybe you have been "lucky" relying on the behaviour you observed in Qt5-.

      goldenhawkingG 1 Reply Last reply
      5
      • Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #3

        As @JonB already told you - it's a stream, there is no such thing like a 'packet' in a stream. You ave to take care of a higher level protocol by your own.
        It worked by accident for you until now.

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        1 Reply Last reply
        3
        • goldenhawkingG Offline
          goldenhawkingG Offline
          goldenhawking
          wrote on last edited by
          #4

          That's it~ Programming is a rigorous job, but debugging brings joy !

          Qt is the best C++ framework I've ever met.

          1 Reply Last reply
          0
          • JonBJ JonB

            @goldenhawking
            I admit I know nothing about QAudioSource, but QIODevice::readAll() has never promised to read "all the data there will be", it has only ever said it will read "whatever data is currently available to it from the device", and there may well be future calls of "readyRead()" which will see further data till all has been consumed. We frequently have to remind coders here of this when they write TCP/IP/socket code and fail to take this into account. Maybe you have been "lucky" relying on the behaviour you observed in Qt5-.

            goldenhawkingG Offline
            goldenhawkingG Offline
            goldenhawking
            wrote on last edited by
            #5

            @JonB @Christian Ehrlicher Thanks for your suggestions! I've worked around this issue and fixed up 3 possible errors in different projects. It's lucky that error code still works in Qt5, and patches can be silently applied in-time.

            Qt is the best C++ framework I've ever met.

            JonBJ 1 Reply Last reply
            0
            • goldenhawkingG goldenhawking

              @JonB @Christian Ehrlicher Thanks for your suggestions! I've worked around this issue and fixed up 3 possible errors in different projects. It's lucky that error code still works in Qt5, and patches can be silently applied in-time.

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #6

              @goldenhawking said in A noteworthy Qt6 issue: QIODevice::readAll() create by QAudioSource returns an odd byte length for qint16 sample points.:

              It's lucky that error code still works in Qt5

              I think so, yes, you just happened to be getting away with it!

              Suppose Qt6 is actually faster than Qt5 (unlikely!). The readyRead()/readAll() could just happen to be called earlier than it used to be, so that the complete audio data had not yet been received.

              1 Reply Last reply
              1

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved