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. Generating a sound wave according to a signal
Forum Updated to NodeBB v4.3 + New Features

Generating a sound wave according to a signal

Scheduled Pinned Locked Moved General and Desktop
4 Posts 2 Posters 2.5k 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.
  • J Offline
    J Offline
    jproberge
    wrote on last edited by
    #1

    Dear Qt users,

    I have a sensor measuring vibrations at a rate of 1000Hz. I would like to be able to reproduce those vibrations on the audio output of my computer with Qt, in real time (also at 1000Hz). Over the last few weeks, I have been struggling with this and found no solution so far.

    For example, what I would like to achieve is to be able to specify, at each millisecond, the amplitude of the audio signal that has to be sent to the audio output. The audio output (e.g. speakers) would then react also at each millisecond.

    I have tried to do that with QtMultimedia and QAudioOutput, using the pulse-code modulation codec (pcm), but so far I have not been able to succeed.

    Anyone has an idea of what I could do to solve this?

    1 Reply Last reply
    0
    • JKSHJ Offline
      JKSHJ Offline
      JKSH
      Moderators
      wrote on last edited by
      #2

      Hi, and welcome to the Qt Dev Net!

      QAudioOutput with PCM is the correct class for your use case. Please post your code so that we can pinpoint the issue.

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

      1 Reply Last reply
      0
      • J Offline
        J Offline
        jproberge
        wrote on last edited by
        #3

        Hello JKSH!

        Thank you for your quick reply, it is much appreciated.

        Ok, so you said QAudioOutput with the PCM codec is the right way to attack this problem. Just to be sure I was clear in my previous message, let me explain another time... I have a sensor generating data at each millisecond. As soon as one data comes in, I want to generate an amplitude at my audio output. I want to repeat this cycle each and every time a new data comes in (at each millisecond).

        Ok, so here's what I have at the moment:

        In my header:
        @
        ...
        public:
        uint16_t *audio_outputBuffer;
        uint16_t *tempAudioBuffer;
        QAudioOutput *audio_outputStream;
        QIODevice *audio_outputDevice;
        QAudioFormat format;
        public slots:
        void GeneratePulseCodeModulationSignal(double DynData);
        @

        In the class' Constructor:
        @
        CommunicationHandler::CommunicationHandler(VisualizationForm *visualiationWindow, MainWindow *mainwnd)
        {
        ...
        // Set up the format
        format.setSampleRate(1000);
        format.setChannelCount(1);
        format.setSampleSize(16);
        format.setCodec("audio/pcm");
        format.setSampleType(QAudioFormat::SignedInt);
        format.setByteOrder(QAudioFormat::LittleEndian);
        audio_outputBuffer = (uint16_t *) malloc((1000) * 4);
        // Create audio output stream, set up signals
        audio_outputStream = new QAudioOutput(format);
        ...
        }
        @

        Finally, the method:

        @
        void CommunicationHandler::GeneratePulseCodeModulationSignal(double DynData)
        {
        qDebug() << "This is DynData we just have received: " << DynData;
        tempAudioBuffer = audio_outputBuffer;

            *tempAudioBuffer = ((uint16_t) (DynData) & 0xFFFF);
        
        
        audio_outputDevice = audio_outputStream->start();
        qDebug() <&lt; audio_outputStream-&gt;periodSize();
        
        if(audio_outputDevice->isOpen() && audio_outputStream->state() != QAudio::StoppedState) {
            bytesOfAudioWrittenToDevice = audio_outputDevice->write((char *) audio_outputBuffer,1);
        }
        

        }
        @

        So, this code doesn't work first of all because QAudioFormat won't allow a sample rate of 1000 (1 millisecond period). And even if it was accepting that rate, I'm not even sure the concept is correct...

        Do you see any way to achieve this?

        1 Reply Last reply
        0
        • JKSHJ Offline
          JKSHJ Offline
          JKSH
          Moderators
          wrote on last edited by
          #4

          Hi jproberge,

          [quote author="jproberge" date="1407959424"]I have a sensor generating data at each millisecond. As soon as one data comes in, I want to generate an amplitude at my audio output. I want to repeat this cycle each and every time a new data comes in (at each millisecond).[/quote]Your audio driver won't read one sample at a time. Instead, it reads a chunk of a few thousand samples at a time, and then it will interpolate your data to create electric signals.

          As a result, you will also have a bit of latency.

          [quote author="jproberge" date="1407959424"]So, this code doesn't work first of all because QAudioFormat won't allow a sample rate of 1000 (1 millisecond period).[/quote]Sound cards don't support a sample rate of 1000 Hz. The minimum standard sample rate (for audio) is 8000 Hz.

          You can do is set your QAudioFormat to accept 8000 Hz, and then interpolate your data. (Every time you receive 1 sample, write 8 samples to audio_outputDevice)

          Anyway, what is the maximum frequency of your vibrations? If you sample at 1000 Hz, the maximum frequency that you can measure is 500 Hz.

          [quote author="jproberge" date="1407959424"]
          Finally, the method:

          @
          void CommunicationHandler::GeneratePulseCodeModulationSignal(double DynData)
          {
          tempAudioBuffer = audio_outputBuffer;

          *tempAudioBuffer = ((uint16_t) (DynData) & 0xFFFF);
          
          ...
          
          bytesOfAudioWrittenToDevice = audio_outputDevice->write((char *) audio_outputBuffer,1);
          

          }
          @
          [/quote]Why do you write to audio_outputBuffer and then copy the data into audio_outputDevice? Just get rid of audio_outputBuffer and write directly into audio_outputDevice.

          [quote author="jproberge" date="1407959424"]
          @
          void CommunicationHandler::GeneratePulseCodeModulationSignal(double DynData)
          {
          ...
          audio_outputDevice = audio_outputStream->start();
          ...
          }
          @
          [/quote]Don't start() the output every time you receive data!

          Call start() once. Then, acquire and write your data many times. Then, call stop() when you have finished.

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

          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