Qt Forum

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

    [SOLVED] QAudioInput returns more data than expected

    General and Desktop
    2
    7
    3038
    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.
    • M
      maxsivkov last edited by

      Hello!

      Having some problems with QAudioInput:
      I'm trying to record sound using QAudioInput (settings are 8000 Hz/16bit/1channel
      everything works fine except one thing: QAudiInput returns more bytes than expected:
      by "expected" I mean that I should read about 16Kbytes/sec or 16 bytes in one millisecond interval.
      Look at the following output (one line is generated each 10 seconds and shows how much bytes read from QAudioInput

              @<bytes received>     <time elapsed>
                        vvvvvv     vvvvvv
      

      Total Received 166400 in 10141
      Total Received 164480 in 10140
      Total Received 163200 in 10142
      Total Received 164480 in 10136
      Total Received 163840 in 10151
      Total Received 163200 in 10129
      Total Received 163840 in 10143
      Total Received 163840 in 10137
      Total Received 163840 in 10152
      Total Received 163840 in 10141
      @
      If we take in account timer inaccuracy (times between each line are measured with QTime::elapsed() call, running under Win7 X86 OS)
      which is +-16mills, we got min and max value for elapsed column (min:10113 and max:10168) what gives us min and max values in bytes: (min:161808 max:162688).
      so, if I am right, there shouldn't be any value in <bytes received> column that larger than 162688 bytes, but as you may see all of them are larger! 163840-162688=1152 bytes more than expected and gives about 72 mills more.
      so in a minute it will give about 0.5 seconds more data than expected!
      Am I missed something???

      1 Reply Last reply Reply Quote 0
      • JKSH
        JKSH Moderators last edited by

        Interesting! Could you share your code for measuring your bytes received and time elapsed?

        I have a feeling that processing delay is affecting your measurements. After all, your results show a ~140ms delay in "time elapsed" (Ideally, they should all be 10000). Is your program (or OS) doing anything else during your measurements? What's the delay between emitting a signal and calling its slot? What's the delay between measuring "time elapsed" and measuring "bytes received"? What are your hardware specs?

        Another experiment you could try is to pass 10000 into QAudioInput::setNotifyInterval(), and then connect QAudioInput::notify() to a slot that calls QTime::elapsed(), to see how much real time it takes for QAudioInput to produce 10s worth of data. If you're right, then "time elapsed" will be less than 10000 always.

        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

        1 Reply Last reply Reply Quote 0
        • M
          maxsivkov last edited by

          JKSH, thanks for reply!

          [quote author="JKSH" date="1343403995"]Interesting! Could you share your code for measuring your bytes received and time elapsed?
          [/quote]

          I am using my own implementation of QIODevice, this class just implements circular buffer and could be used for both QAudioInput and QAudioOutput, so my QAudioInput works in "pull" mode.
          As I mentioned, by OS is Windows7 x86, CPU Intel(R) Core(TM)2 Quad CPU Q6600 at 2.40GHz, 4Gb RAM
          I understand that the system could do something in the middle but it shouldn't affect on a <bytes received> column grow for two subqequent lines.

          Anyway, here is my code to measure time:

          @qint64 MemoryDevice::writeData(const char *data, qint64 len)
          {
          QMutexLocker l(&lock);

          static struct _time_t
          {
              int total_received;
              QTime time;
              _time_t() : total_received(0) { time.start(); }
          } timer;
          timer.total_received+=len;
          int elapsed = timer.time.elapsed();
          if (elapsed > 10000)
          {
              qDebug() << ">>>>> Total Received  " << timer.total_received << " in " << elapsed;
              timer.total_received = 0;
              timer.time.restart();
          }
          
          qint64 result = len;
          while (len) { holder.append(*data++); len--;}
          return result;
          

          }@
          the above is writeData() virtual function reimplemented in my own class.
          "holder" implements circular buffer, but it doesn't matter in this case.

          PS:
          I'm facing this problem because my app should transfer audio data over network and remote side should be able to play this stream.
          after getting all things done I put sender and receiver to work for about half an hour, and guess what, the delay between recorded sound on a sender and played on a receiver was about 10 seconds!

          1 Reply Last reply Reply Quote 0
          • M
            maxsivkov last edited by

            I disabled all timers and threads in my application, and did another test with aggregation results.

            Now the writeData function looks like:
            @qint64 MemoryDevice::writeData(const char *data, qint64 len)
            {
            QMutexLocker l(&lock);

            static struct _time_t
            {
                int total_received_interval, total_received, time_passed;
                QTime time;
                _time_t() : total_received_interval(0), total_received(0), time_passed(0) { time.start(); }
            } timer;
            
            int elapsed = timer.time.elapsed();
            timer.total_received_interval+=len;
            if (elapsed > 10000)
            {
                timer.total_received+=timer.total_received_interval;
                timer.time_passed+=elapsed;
            
                qDebug() << "!!!!! MemoryDevice::WriteStream Total Received/interval  " << timer.total_received_interval<< " in " << elapsed
                            << "total bytes "<< timer.total_received << " in " << timer.time_passed
                               << "diff " << timer.total_received - (timer.time_passed*16);
                timer.total_received_interval = 0;
                timer.time.restart();
            }
            
            qint64 result = len;
            return result;
            

            }@

            the output is the following:
            @
            Received/interval 160640 in 10001 total bytes 160640 in 10001 diff 624
            Received/interval 161280 in 10005 total bytes 321920 in 20006 diff 1824
            Received/interval 160640 in 10021 total bytes 482560 in 30027 diff 2128
            Received/interval 160640 in 10036 total bytes 643200 in 40063 diff 2192
            Received/interval 160640 in 10004 total bytes 803840 in 50067 diff 2768
            Received/interval 160640 in 10029 total bytes 964480 in 60096 diff 2944
            Received/interval 160000 in 10006 total bytes 1124480 in 70102 diff 2848
            Received/interval 160640 in 10035 total bytes 1285120 in 80137 diff 2928
            Received/interval 160640 in 10030 total bytes 1445760 in 90167 diff 3088
            Received/interval 160640 in 10041 total bytes 1606400 in 100208 diff 3072
            Received/interval 160640 in 10031 total bytes 1767040 in 110239 diff 3216
            Received/interval 160640 in 10022 total bytes 1927680 in 120261 diff 3504
            Received/interval 160640 in 10039 total bytes 2088320 in 130300 diff 3520
            Received/interval 161280 in 10036 total bytes 2249600 in 140336 diff 4224
            Received/interval 161280 in 10033 total bytes 2410880 in 150369 diff 4976
            Received/interval 160640 in 10029 total bytes 2571520 in 160398 diff 5152
            Received/interval 160000 in 10005 total bytes 2731520 in 170403 diff 5072
            Received/interval 160640 in 10037 total bytes 2892160 in 180440 diff 5120
            Received/interval 160640 in 10034 total bytes 3052800 in 190474 diff 5216
            Received/interval 160640 in 10041 total bytes 3213440 in 200515 diff 5200
            Received/interval 160640 in 10032 total bytes 3374080 in 210547 diff 5328
            Received/interval 160640 in 10023 total bytes 3534720 in 220570 diff 5600
            Received/interval 160000 in 10006 total bytes 3694720 in 230576 diff 5504
            Received/interval 160640 in 10028 total bytes 3855360 in 240604 diff 5696
            Received/interval 160640 in 10014 total bytes 4016000 in 250618 diff 6112
            Received/interval 160640 in 10032 total bytes 4176640 in 260650 diff 6240
            Received/interval 160640 in 10027 total bytes 4337280 in 270677 diff 6448
            Received/interval 160640 in 10014 total bytes 4497920 in 280691 diff 6864
            Received/interval 160640 in 10039 total bytes 4658560 in 290730 diff 6880
            Received/interval 160640 in 10035 total bytes 4819200 in 300765 diff 6960
            Received/interval 160640 in 10035 total bytes 4979840 in 310800 diff 7040
            Received/interval 160000 in 10007 total bytes 5139840 in 320807 diff 6928
            Received/interval 160640 in 10034 total bytes 5300480 in 330841 diff 7024
            Received/interval 160640 in 10009 total bytes 5461120 in 340850 diff 7520
            @

            I removed "!!!!! MemoryDevice::WriteStream " from each line for better reading.
            So, there are 34 lines, gives us 340 seconds = ~5,6 mins, and the difference is 7520/16=470 milliseconds!

            1 Reply Last reply Reply Quote 0
            • JKSH
              JKSH Moderators last edited by

              Mutex locking/unlocking is very slow... which could explain why your app lags over time, and could mean that your elapsed() measurements are out of sync with the data arrival times. Also, keep in mind that because QTime::elapsed() is inaccurate, the error in "timer.time_passed" grows every time you evaluate "timer.time_passed+=elapsed".

              What happens if you get rid of the QMutexLock?

              Anyway, here is my own bare-bones test device:

              @class TimingDevice : public QIODevice
              {
              Q_OBJECT

              qint64 total_received;
              QElapsedTimer timer;
              
              qint64 readData(char *data, qint64 maxlen) {return 0;}
              qint64 writeData(const char *data, qint64 len)
              {
                  if (timer.isValid()) {
              
                      qint64 elapsed = timer.elapsed();
                      total_received += len;
              
                      if (elapsed >= 10000) {
                          qDebug() << total_received << "bytes in" << elapsed << "msecs";
                          total_received = 0;
                          timer.restart();
                      }
                  } else {
                      timer.start();
                  }
                  return len;
              }
              

              public:
              TimingDevice(QObject *parent = 0) : QIODevice(parent)
              {
              total_received = 0;
              timer.invalidate();
              }
              };@

              I'm running Windows7 ×86, CPU Intel® Core™2 Quad CPU Q6600 at 2.40GHz, 4Gb RAM and got:
              @160000 bytes in 10000 msecs
              160640 bytes in 10038 msecs
              160640 bytes in 10039 msecs
              160000 bytes in 10000 msecs
              160640 bytes in 10039 msecs
              160000 bytes in 10000 msecs
              160640 bytes in 10039 msecs
              160000 bytes in 10000 msecs
              160640 bytes in 10039 msecs
              160640 bytes in 10039 msecs
              160000 bytes in 10000 msecs
              160640 bytes in 10039 msecs
              160000 bytes in 10000 msecs
              160640 bytes in 10039 msecs
              160000 bytes in 10000 msecs
              @

              So the device gets either 160640 bytes in 10040 msecs, or 160000 bytes in 10000 msecs, as expected.

              Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

              1 Reply Last reply Reply Quote 0
              • M
                maxsivkov last edited by

                JKSH,

                After disabling timers, threads, and using more accurate win32 "GetSystemTimeAsFileTime":http://msdn.microsoft.com/en-us/library/windows/desktop/ms724397(v=vs.85).aspx call that could return values up to 100 nanosec resolution (actually not less than 1 millisec) I got almost the same result as you did.

                So the thread might be closed.
                Thank you for your time and support!

                1 Reply Last reply Reply Quote 0
                • JKSH
                  JKSH Moderators last edited by

                  You're welcome, maxsivkov :) Good luck with your project!

                  Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

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