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. What's the correct/efficient way of converting char* array to float array in QIODevice::writeData?
Forum Update on Monday, May 27th 2025

What's the correct/efficient way of converting char* array to float array in QIODevice::writeData?

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 2 Posters 1.4k 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 13 Jun 2020, 11:31 last edited by Thinium
    #1

    In my app I am receiving audio data from the selected QIODevice. The audio signal is 32bit values between -1 and 1.

    In my QIODevice::writeData function, I still first convert the signal into integer, as the qFromLittleEndian and qFromBigEndian only works with int types (I get values between -1624492672 and 1624492672). And then divide the value by 2^31 to convert them into float. Is there a more correct/efficient way to directly convert the received data into float, instead of first int and then float value?

    Here is a simplified version of my QIODevice::writeData function:

    MyIODevice::writeData(const char *data, qint64 len)
    {
        int channelCount = m_audioFormat.channelCount();
        int sampleSize   = m_audioFormat.sampleSize();
    
        int channelBytes = sampleSize / 8;
        int sampleBytes = channelCount * channelBytes;
    
        int numSamples = len / sampleBytes;
        const bool isLittleEndian = m_audioFormat.byteOrder() == QAudioFormat::LittleEndian;
        QVector<qint32> sampleValues(channelCount);
    
        for (int sample = 0; sample < numSamples; sample++)
        { 
               isLittleEndian ? qFromLittleEndian<qint32>(data, channelCount, sampleValues.data()) :
                                 qFromBigEndian<qint32>(data, channelCount, sampleValues.data());
               // then before using the sampleValues, sampleValue[index] will be divided by 2^31 to convert the value into a float value between -1, 1
               // ex.  sampleValues[0] / 2147483648.0f 
               // the approach only sort of works because the values are between -0.756463 and 0.756463
               // instead of -1 and 1
      
                // send the received value to the ring buffer to store
               // emit receiveSample(sampleValues); 
        }
    
        return len;
    }
    
    1 Reply Last reply
    0
    • B Offline
      B Offline
      Bonnie
      wrote on 13 Jun 2020, 14:19 last edited by Bonnie
      #2

      Are you using QAudioInput?
      If the audio format is float, there's no such big/little endian thing, you should just cast the pointer to a float*.

      const float* floatPtr = reinterpret_cast<const float*>(data);
      

      How are you planning to use the vector then? Acctually I don't think there is any need to use a vector.
      It is already a float array if you cast the pointer.

      1 Reply Last reply
      1
      • T Offline
        T Offline
        Thinium
        wrote on 13 Jun 2020, 17:32 last edited by Thinium
        #3

        @Bonnie thanks for the reply! Yes I use QAudioInput.
        When I print the audio format used for QAudioInput, it shows:
        QAudioFormat(44100Hz, 32bit, channelCount=64, sampleType=SignedInt, byteOrder=BigEndian, codec="audio/pcm"). (It's confusing as the audio signal is indeed a float value between -1, 1, but it says the sample type is SignedInt)

        Do you think it could be directly casted to float nevertheless?

        I plan to store the float array into a ring buffer (I've updated my question to show that each individual sample will be sent to the ringBuffer through a singal). There is another object that will fetch the float arrays from the ring buffer and convert them into information for drawing (x, y, red, green blue. etc). Do you think QVector is indeed not needed in this case?

        Also I just tried what you suggested

        const float* floatPtr = reinterpret_cast<const float*>(data)
        

        When I print floatPtr[0] floatPtr[1] ... the value doesn't seem to be right (when I send signal value 1, the float value is -1.86266e-38)

        B 1 Reply Last reply 13 Jun 2020, 18:17
        0
        • T Thinium
          13 Jun 2020, 17:32

          @Bonnie thanks for the reply! Yes I use QAudioInput.
          When I print the audio format used for QAudioInput, it shows:
          QAudioFormat(44100Hz, 32bit, channelCount=64, sampleType=SignedInt, byteOrder=BigEndian, codec="audio/pcm"). (It's confusing as the audio signal is indeed a float value between -1, 1, but it says the sample type is SignedInt)

          Do you think it could be directly casted to float nevertheless?

          I plan to store the float array into a ring buffer (I've updated my question to show that each individual sample will be sent to the ringBuffer through a singal). There is another object that will fetch the float arrays from the ring buffer and convert them into information for drawing (x, y, red, green blue. etc). Do you think QVector is indeed not needed in this case?

          Also I just tried what you suggested

          const float* floatPtr = reinterpret_cast<const float*>(data)
          

          When I print floatPtr[0] floatPtr[1] ... the value doesn't seem to be right (when I send signal value 1, the float value is -1.86266e-38)

          B Offline
          B Offline
          Bonnie
          wrote on 13 Jun 2020, 18:17 last edited by Bonnie
          #4

          @Thinium
          I'm guessing that you write you code referring to the audio input example?
          The casting is also in it.

          ...
          else if (m_format.sampleSize() == 32 && m_format.sampleType() == QAudioFormat::Float) {
              value = qAbs(*reinterpret_cast<const float*>(ptr) * 0x7fffffff); // assumes 0-1.0
          }
          ...
          

          So if the condition is m_format.sampleSize() == 32 && m_format.sampleType() == QAudioFormat::Float, then that's the right way.
          [EDITED]
          But as you said the format is signed int but actually it is a float, then I'm confusing, too. How would that happen?
          The only approach I would think of is, reading with qFromBigEndian<qint32>, but also casting the value to float.
          According the code in your previous post, something like

          QVector<float> destination(channelCount);
          qFromBigEndian<qint32>(data, channelCount, destination.data());
          

          If this still cannot get the correct value, then I'm out of ideas.

          About the vector / array...It seems that you are drawing some kind of spectrum chart?
          Hmm...I was assuming the calculating is also here, which would be no need to use the vector ([ADDED] if there's no big/little endian conversion).
          I didn't expect that you need to send a signal for every sample. Yes, you may need the QVector in that case.
          But I'm worrying about the performance. It may be too heavy to copy and send every sample like that.

          1 Reply Last reply
          0
          • T Offline
            T Offline
            Thinium
            wrote on 14 Jun 2020, 13:56 last edited by Thinium
            #5

            @Bonnie said in What's the correct/efficient way of converting char* array to float array in QIODevice::writeData?:

            QVector<float> destination(channelCount);
            qFromBigEndian<qint32>(data, channelCount, destination.data());

            Thanks for the suggestions! Yes, I am visualizing the received data (but not exactly audio spectrum as they could also be interpreted as other visual data, like color, etc.) I tried the above approach you suggested, and it unfortunately doesn't give the expected values. So I think I'll still need to convert the integers to floats manually.

            And you are totally right about the performance issue. That is why I am trying to optimize it. Maybe I need to consider threading, or avoid copying if possible.

            Thanks again for your help! @Bonnie!

            1 Reply Last reply
            0

            1/5

            13 Jun 2020, 11:31

            • Login

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