Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct


    Qt World Summit: Early-Bird Tickets

    Unsolved QIODevice::writeData is not triggered when working with with 64 channels QAuioFormat

    General and Desktop
    3
    11
    214
    Loading More Posts
    • 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.
    • T
      Thinium last edited by Thinium

      I want to use a custom QIODevice to process audio data received from Soundflower (64 channel). I noticed the QIODevice::writeData function is only triggered if I manually change QAudioFormat's channelCount to anything less than 16. How can I make it work with soundflower's original audioformat, which is 64 channel? Or is this a bug in the QIODevice? Here is the sample codes:

      void MyWidget::deviceChanged (const QAudioDeviceInfo &device)
      {
          if (m_audioInput)
          {
              m_audioInput->stop();
              delete m_audioInput;
          }
      
          if (m_streamReader)
          {
              m_streamReader->stop();
              delete m_streamReader;
          }
      
          QAudioFormat format = device.preferredFormat();
      
          // this line shows the original format: QAudioFormat(44100Hz, 32bit, channelCount=64, sampleType=SignedInt, byteOrder=BigEndian, codec="audio/pcm")
          qDebug() << "original format:" << format;
      
          // in order to make QIODevice::writeData(const char *data, qint64 len) being triggered, I need to manually set the channel count to anything less than 16, if the channel count is more than 15, the QIODevice:writeData won't be triggered
          format.setChannelCount(8);
          m_audioInput = new QAudioInput(device, format);
          // StreamReader is a subclass of QIODevice
          m_streamReader = new StreamReader(m_audioInput->format(), this);
          m_streamReader->start();
          m_audioInput->start(m_streamReader);
          qDebug() << m_audioInput->state();
      }
      
      // here is the function of QIODevice subclass that doesn't work as expected
      qint64 StreamReader::writeData(const char *data, qint64 len)
      {
          // this function is called only if audioFormat.channelCount is <=16
      }
      

      When the channelCount is set to 64, the AudioInput state is StoppedState, but if I hard-code the channelCount to anything <= 16, the state is IdleState

      B 1 Reply Last reply Reply Quote 0
      • Christian Ehrlicher
        Christian Ehrlicher Lifetime Qt Champion last edited by

        @Thinium said in QIODevice::writeData is not triggered when working with with 64 channels QAuioFormat:

        MyQIODevice* streamReader = new StreamReader(m_audioInput->format(), this);

        What do you expect from this line (except maybe a memleak)?

        Qt has to stay free or it will die.

        T 1 Reply Last reply Reply Quote 0
        • T
          Thinium @Christian Ehrlicher last edited by

          @Christian-Ehrlicher thanks for the reply! I just updated the question to reflect the actual code. StreamReader is a member of myWidget and it has a function that receives audio signal from the selected audio device (in my case Soundflower 64 channels)

          qint64 StreamReader::writeData(const char *data, qint64 len)
          
          1 Reply Last reply Reply Quote 0
          • Christian Ehrlicher
            Christian Ehrlicher Lifetime Qt Champion last edited by

            But why would a reader and an input would call write()?

            btw: still leaks when deviceChanged() more than once.

            Qt has to stay free or it will die.

            T 1 Reply Last reply Reply Quote 1
            • T
              Thinium @Christian Ehrlicher last edited by

              @Christian-Ehrlicher yes I am aware this would leak. I didn't add the delete codes just to show the core of the issue.

              According to the documentation, AudioInput "Writes" to the QIODevice. For more info:
              https://doc.qt.io/qt-5/qaudioinput.html#start
              Starts transferring audio data from the system's audio input to the device. The device must have been opened in the WriteOnly, Append or ReadWrite modes.

              1 Reply Last reply Reply Quote 0
              • B
                Bonnie @Thinium last edited by

                @Thinium
                Wow, I think it is hard to know bacause I don't have a 64-channel device on Windows. :(
                BTW, what's the bufferSize after start?

                @Christian-Ehrlicher
                The internal process of an audio input is that, it reads data from the audio device, then write that data to the user provided device.

                T Christian Ehrlicher 2 Replies Last reply Reply Quote 0
                • T
                  Thinium @Bonnie last edited by Thinium

                  @Bonnie thanks for the reply! It fails when you manually set the channelCount to anything more than 16 channels. You don't really need a real device to reproduce that.

                  The buffer size after start is 4096, no matter what my channel settings are. Here are the buffer size for 2channels and 64channels:

                  "Soundflower (2ch)"
                  QAudioFormat(44100Hz, 32bit, channelCount=2, sampleType=SignedInt, byteOrder=BigEndian, codec="audio/pcm")
                  IdleState
                  buffersize 4096

                  "Soundflower (64ch)"
                  QAudioFormat(44100Hz, 32bit, channelCount=64, sampleType=SignedInt, byteOrder=BigEndian, codec="audio/pcm")
                  StoppedState
                  buffersize 4096

                  As you can see, when AudioFormat is set to 64ch, the QAudioInput is in stopped state. Which I don't understand why.

                  B 1 Reply Last reply Reply Quote 0
                  • Christian Ehrlicher
                    Christian Ehrlicher Lifetime Qt Champion @Bonnie last edited by

                    @Bonnie said in QIODevice::writeData is not triggered when working with with 64 channels QAuioFormat:

                    then write that data to the user provided device.

                    So at least the class name is wrong (it's a StreamWriter, not StreamReader).

                    Qt has to stay free or it will die.

                    1 Reply Last reply Reply Quote 0
                    • B
                      Bonnie @Thinium last edited by

                      @Thinium Seems there's an open error. You can check the m_audioInput->error() result.
                      Does device.isFormatSupported(m_audioInput->format()) returns true in 64ch mode?

                      T 1 Reply Last reply Reply Quote 0
                      • T
                        Thinium @Bonnie last edited by

                        @Bonnie indeed the format is not supported! That's surely why the audioInput can't be started.

                        B 1 Reply Last reply Reply Quote 0
                        • B
                          Bonnie @Thinium last edited by Bonnie

                          @Thinium I found this in the source code (coreaudiodeviceinfo.mm)

                          QList<int> CoreAudioDeviceInfo::supportedChannelCounts()
                              {
                                  static QList<int> supportedChannels;
                              
                                  if (supportedChannels.isEmpty()) {
                                      // If the number of channels is not supported by an audio device, Core Audio will
                                      // automatically convert the audio data.
                                      for (int i = 1; i <= 16; ++i)
                                          supportedChannels.append(i);
                                  }
                              
                                  return supportedChannels;
                              }
                          

                          So Qt will only allow 1~16 channels.

                          1 Reply Last reply Reply Quote 3
                          • First post
                            Last post