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. Send raw data to QAudioOutput.
Forum Updated to NodeBB v4.3 + New Features

Send raw data to QAudioOutput.

Scheduled Pinned Locked Moved General and Desktop
21 Posts 4 Posters 15.7k 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.
  • A Offline
    A Offline
    Anticross
    wrote on last edited by
    #2

    I replace AudioBuffer By new variable <code>QIODevice * m_dev;</code> And do the following declarations
    @
    m_dev = m_output->start();
    @
    and replace
    @m_buf->writeData((const char *)data,dataSize);@
    by
    @m_dev->write((const char *)data,dataSize);@
    And now I get a beautiful noise in output but not that music which I put there. An this noise is interrupt periodically. But it finishes when data transmit finishes. Maybe something wrong with format?

    As a source I am using wav file 44100 Hz 16 bit stereo, which i transmit over network an receive data by portions and write it actually here:
    @m_buf->writeData((const char *)data,dataSize);@
    So if I use a file to receive this data, and after receiving I open it, it's contains the music that I transmitt.

    Edit: fixed code formatting and merged two posts; Andre

    1 Reply Last reply
    0
    • A Offline
      A Offline
      Anticross
      wrote on last edited by
      #3

      Now I'm using my buffer such as QIODevice @m_buf = (AudioBuffer *)m_output->start();@ and get the same. I change the file that I transmit to another one, and notice that I can hear music, but it's very distorted, and interrupts as I wrote previously. But one more notice that the high freq sounds with low volume hears better than others.

      1 Reply Last reply
      0
      • A Offline
        A Offline
        Anticross
        wrote on last edited by
        #4

        It seems like data sending through RTP is converted to BigEndian format before reaching client. But I find no BigEndian support of playback, so maybe I need to do some fast conversation. Question: How to do that ?

        1 Reply Last reply
        0
        • T Offline
          T Offline
          tobias.hunger
          wrote on last edited by
          #5

          RTP defines all values to be transmitted in big-endian, so no surprise there;-)

          http://developer.qt.nokia.com/doc/qt-4.8/qtendian.html to the rescue.

          1 Reply Last reply
          0
          • A Offline
            A Offline
            Anticross
            wrote on last edited by
            #6

            OK, thanks. Another question: I have @unsigned char const* data@ with size @unsigned dataSize@ , qFromBigEndian needs to chose type (qInt16,qInt32,qInt64), and returns value of it's type, but how can I put this data back into unsigned char const* array with size of dataSize ?

            1 Reply Last reply
            0
            • A Offline
              A Offline
              Anticross
              wrote on last edited by
              #7

              This does not helped:
              @
              char * dt = new char[dataSize];
              itoa(qFromBigEndian<qint16>(data),dt,2);
              m_buf->writeData((const char*)dt,dataSize);
              delete dt;
              @

              1 Reply Last reply
              0
              • A Offline
                A Offline
                Anticross
                wrote on last edited by
                #8

                Edited to :
                @qint16 val = qFromBigEndian<qint16>(data);
                uchar* dt = new uchar[dataSize];
                qToLittleEndian<qint16>(val,dt);
                m_buf->writeData((const char*)dt,dataSize);
                delete dt;@
                But the quality of audio is worse then without conversation.

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  Anticross
                  wrote on last edited by
                  #9

                  I write function:
                  @bool SpeakerSink::toLittleEndian( const char * src, int size, int nBits)
                  {
                  if(src == NULL)
                  return false;

                  for (int i = 0; i < size; i+=nBits) {
                      qint16 val = qFromBigEndian<qint16>((const uchar*)(src+i));
                      qMemCopy((void*)(src+i),&val,nBits);
                  }
                  
                  return true;
                  

                  }@
                  It solve task of converting from big-endian to little-endian and in headphones I get the same result(I mean sound is recognizable but bad quality) as if my server will transmit data without conversation to big-endian. But sound still distorted and interrupts.

                  1 Reply Last reply
                  0
                  • A Offline
                    A Offline
                    Anticross
                    wrote on last edited by
                    #10

                    I open VLC player and receive this stream normally, then I look at codec details and see some PCM S16BE(twos). So what is it and can I transform data to play normal PCM on QAudioOutput ? So is it 16-bit Big-endian pcm or something else? What means S ?

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      Anticross
                      wrote on last edited by
                      #11

                      I record output of my sound card when receiving stream with sine of 1000 Hz. After opening it in Sound Forge I see pauses in this sine with delays from 5 ms to 25 ms but sine has the same shape(I mean no distortions).

                      1 Reply Last reply
                      0
                      • T Offline
                        T Offline
                        tobias.hunger
                        wrote on last edited by
                        #12

                        Sorry, no idea what kind of data you send around your network;-)

                        Why do you have nBits in the toLittleEndian method shown above? Anything but nBits == 2 breaks the method, doesn't it? The name is rather confusing, too... shouldn't it at least be nBytes?

                        1 Reply Last reply
                        0
                        • A Offline
                          A Offline
                          Anticross
                          wrote on last edited by
                          #13

                          You're right the name must be at least nBytes :) Maybe QAudioOutput reads the buffer faster than it writes by receiving data from network, and I just need to wait some time before playing.

                          1 Reply Last reply
                          0
                          • A Offline
                            A Offline
                            Anticross
                            wrote on last edited by
                            #14

                            I rewrite my audio buffer class. Now it looks like this:
                            @#ifndef AUDIOBUFFER_H
                            #define AUDIOBUFFER_H

                            #include <QAudioFormat>
                            #include <QIODevice>
                            #include <QMutex>
                            #include <QDebug>

                            class AudioBuffer : public QIODevice
                            {
                            Q_OBJECT

                            public:
                            //----------------------------------------------------------------------------------------------------------------------------------
                            AudioBuffer(/const QAudioFormat &format,/ QObject parent = NULL, int bufSize = 1400) : QIODevice(parent)
                            {
                            m_bufSize = bufSize
                            4;

                                m_buffer1 = new const char[m_bufSize];
                                m_buffer2 = new const char[m_bufSize];
                            
                                m_rightOffset = 0;
                                m_leftOffset  = 0;
                                m_cursor      = 0;
                            
                                qMemSet((void *)m_buffer1,0,m_bufSize);
                            
                            }
                            

                            //----------------------------------------------------------------------------------------------------------------------------------
                            ~AudioBuffer()
                            {
                            delete m_buffer1;
                            delete m_buffer2;
                            }
                            //----------------------------------------------------------------------------------------------------------------------------------
                            void start()
                            {
                            if(!isOpen())
                            open(QIODevice::ReadWrite);
                            }
                            //----------------------------------------------------------------------------------------------------------------------------------
                            void stop()
                            {
                            close();
                            }
                            //----------------------------------------------------------------------------------------------------------------------------------
                            qint64 readData(char * data, qint64 len)
                            {
                            int free2end = m_bufSize-m_cursor;

                                if(len <= free2end){
                                    qMemCopy(data,m_buffer1+m_cursor,len);
                            
                                    m_rightOffset += len;
                                    m_cursor += len;
                            
                                    return len;
                                }
                                else
                                {
                                    qMemCopy(data,m_buffer1+m_cursor,free2end);
                            
                                    m_cursor = 0;
                            
                                    qMemCopy(data+free2end,m_buffer1,len-free2end);
                            
                                    m_rightOffset = len-free2end;
                                    m_leftOffset = 0;
                                    m_cursor += m_rightOffset;
                            
                                    return len;
                                }
                            
                                return 0;
                            }
                            

                            //----------------------------------------------------------------------------------------------------------------------------------
                            qint64 writeData(const char *data, qint64 len)
                            {
                            int free2end = m_bufSize-m_rightOffset;

                                if(len <= free2end) // if we don't reach end of buffer
                                {
                                    qMemCopy((void*)(m_buffer1+m_rightOffset),data,len);
                                    m_rightOffset += len;
                            
                                    qDebug() << m_buffer1;
                            
                                    return len;
                                }
                                else if(len <= (m_leftOffset+free2end))
                                {
                                    qMemCopy((void*)(m_buffer1+m_rightOffset),data,free2end); //write to end
                                    m_leftOffset = len-free2end; // need to write more from source and set new left offset
                                    qMemCopy((void*)m_buffer1,data+free2end,m_leftOffset); //write lefted part 
                                    m_rightOffset = m_leftOffset; // set new right offset value
                                    m_leftOffset  = 0; // set new left offset value
                            
                                    qDebug() << m_buffer1;
                            
                                    return len;
                                }
                                else
                                {
                                    qMemCopy((void*)(m_buffer1+m_rightOffset),data,free2end); //write to end
                                    m_rightOffset += len-free2end; // need to write more from source
                            
                                    len -= free2end;
                            
                                    qMemCopy((void*)m_buffer1,data+free2end,m_leftOffset); //write lefted part 
                                    m_rightOffset = 0; // set new right offset value
                            
                                    len -= m_leftOffset;
                            
                                    m_leftOffset = 0;
                            
                                    qDebug() << m_buffer1;
                            
                                    return len;
                                }
                            
                                return 0;
                            }
                            

                            //----------------------------------------------------------------------------------------------------------------------------------
                            private:
                            const char * m_buffer1;
                            const char * m_buffer2;
                            int m_rightOffset;
                            int m_leftOffset;
                            int m_cursor;
                            int m_bufSize;
                            };

                            #endif//AUDIOBUFFER_H@
                            And now I'm using it like this:
                            @m_output->start(m_buf);@
                            and it enters write data functions, but doesn't reads data. So question: How QAudioOutput asks for the data to play from QIODevice ? Is it call readData function or not ? And one more question: Is it possible to play rtsp stream using Phonon ?

                            1 Reply Last reply
                            0
                            • A Offline
                              A Offline
                              Anticross
                              wrote on last edited by
                              #15

                              One more question whats the main difference between push and pull mode of playing ?

                              1 Reply Last reply
                              0
                              • A Offline
                                A Offline
                                Anticross
                                wrote on last edited by
                                #16

                                Interesting thing: when I play 22050 Hz 16 bit 2 channels audio stream - it plays normally without interruptions, but when playing 44100 Hz 16 bit stereo - not. If I open same stream(44 kHz) in VLC player or any other it plays normally without interruptions.

                                1 Reply Last reply
                                0
                                • B Offline
                                  B Offline
                                  billconan
                                  wrote on last edited by
                                  #17

                                  this is an interesting thread. a QAudioOuput from a buffer example should be added to the document.

                                  too bad the document only has an example of playing a file.

                                  1 Reply Last reply
                                  0
                                  • B Offline
                                    B Offline
                                    billconan
                                    wrote on last edited by
                                    #18

                                    has this issue been resolved yet? I also need to achieve the same thing?

                                    1 Reply Last reply
                                    0
                                    • B Offline
                                      B Offline
                                      billconan
                                      wrote on last edited by
                                      #19

                                      has this issue been resolved yet? I also need to achieve the same thing?

                                      1 Reply Last reply
                                      0
                                      • L Offline
                                        L Offline
                                        lynic
                                        wrote on last edited by
                                        #20

                                        I had a similar problem using a ringbuffer as a QIODevice backend for which I spent a whole day. The solution was to override the following method:

                                        @bool isSequential() const
                                        {
                                        return true;
                                        }@

                                        1 Reply Last reply
                                        0
                                        • L Offline
                                          L Offline
                                          lynic
                                          wrote on last edited by
                                          #21

                                          I had a similar problem using a ringbuffer as a QIODevice backend for which I spent a whole day. The solution was to override the following method:

                                          @bool isSequential() const
                                          {
                                          return true;
                                          }@

                                          1 Reply Last reply
                                          0

                                          • Login

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