Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QIODevice::writeData is not triggered when working with with 64 channels QAuioFormat

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

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 3 Posters 536 Views
  • 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 Offline
    T Offline
    Thinium
    wrote on last edited by Thinium
    #1

    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
    0
    • Christian EhrlicherC Online
      Christian EhrlicherC Online
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @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 Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      T 1 Reply Last reply
      0
      • Christian EhrlicherC Christian Ehrlicher

        @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)?

        T Offline
        T Offline
        Thinium
        wrote on last edited by
        #3

        @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
        0
        • Christian EhrlicherC Online
          Christian EhrlicherC Online
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

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

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

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

          T 1 Reply Last reply
          1
          • Christian EhrlicherC Christian Ehrlicher

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

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

            T Offline
            T Offline
            Thinium
            wrote on last edited by
            #5

            @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
            0
            • T 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 Offline
              B Offline
              Bonnie
              wrote on last edited by
              #6

              @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 EhrlicherC 2 Replies Last reply
              0
              • B Bonnie

                @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 Offline
                T Offline
                Thinium
                wrote on last edited by Thinium
                #7

                @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
                0
                • B Bonnie

                  @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.

                  Christian EhrlicherC Online
                  Christian EhrlicherC Online
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  @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 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
                  0
                  • T 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 Offline
                    B Offline
                    Bonnie
                    wrote on last edited by
                    #9

                    @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
                    0
                    • B Bonnie

                      @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 Offline
                      T Offline
                      Thinium
                      wrote on last edited by
                      #10

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

                      B 1 Reply Last reply
                      0
                      • T Thinium

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

                        B Offline
                        B Offline
                        Bonnie
                        wrote on last edited by Bonnie
                        #11

                        @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
                        3

                        • Login

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