Pergunta

I'm trying to create a program, using Qt (c++), which can record audio from my microphone using QAudioinput and QIODevice. I made a research and I came up with an example located on the this page. This example does what I need.

Now, I am trying to create an audio waveform of the recorded sound. I want to extract audio amplitudes and save them on a QList. To do that I use the following code:

//Check the number of samples in input buffer
qint64 len = m_audioInput->bytesReady();

//Limit sample size
if(len > 4096)
    len = 4096;
//Read sound samples from input device to buffer
qint64 l = m_input->read(m_buffer.data(), len);
if(l > 0)
{

    //Assign sound samples to short array
    short* resultingData = (short*)m_buffer.data();

     for ( i=0; i < len; i++ )
     {
         btlist.append( resultingData[ i ]);
     }

}

m_audioInput is QAudioinput | m_buffer is QBytearray | m_input is QIODevice | btlist is QList

I use the following QAudioFormat:

m_format.setFrequency(44100); //set frequency to 44100
m_format.setSampleRate(44100); //set sample rate to 44100
m_format.setChannels(1); //set channels to mono
m_format.setSampleSize(16); //set sample sze to 16 bit
m_format.setSampleType(QAudioFormat::SignedInt ); //signed integer sample
m_format.setByteOrder(QAudioFormat::LittleEndian); //Byte order
m_format.setCodec("audio/pcm"); //set codec as simple audio/pcm

When I print my QList, using qWarning() << btlist.at(int), I get some positive and negative numbers which represents my audio amplitudes. I used Microsoft Excel to plot the data and compare it with the actual sound waveform.

(EDIT BASED ON THE OP COMMENT) I am drawing the waveform using QPainter in Qt like this

  for(int i = 1; i < btlist.size(); i++){ 
       double x1 = (i-(i/1.25))-0.2;
       double y1 = btlist.at(i-1);
       double x2 = i-(i/1.25);
       double y2 = btlist.at(i);
       painter.drawLine(x1,y1,x2, y2); 
  }

The problem is that I also get lots of zeros (0) in my QList between the amplitude data like this, which if I draw as a waveform they are a straight line, which is not normal because it causes corruption to my waveform. My question is why is that happening? What these zeros (0) represent? Am I doing something wrong? Also, is there a better way to extract audio amplitudes from QBytearray?

Thank you.

Foi útil?

Solução

The drawline method you are using take integer values. Which means most of the time both of your x indexes will be the same. By simplifiyng your formula the x value at a given i is (i/5.0). By itself it is not an issue because the lines will be superposed, and it is a perfect way of drawing (just to make sure that's what you want to do).

The zero you see can be perfectly valid. They represent silence.

The real issue is that the range of your 16 bits PCM values is [-32767 , 32768]. I doubt that the paint device you are using cover this range. You need to normalize your y-axis. Moreover, it seems taht the qt coordinated system doesn't have negative values (edit: Nevermind the negatives, its says logical coordinates are converted).

For instance, convert your pcm values using :

  ((btlist.at(i) / MAX_AMPLITUDE + 1.0) / 2) * paintDevice.height();

Edit:

Btw, you are not using l, which is the real amount of data you read. If it is inferior to len, you will read invalid values at the end of your buffer, possibly read garbage\ read zeros\crash.

And your buffer is a byte buffer. And you iterate using a short pointer. So whether you use l or len the maximum size need to be divided by two. This is probably the cause of the ling line of zero in your picture.

 for ( i=0; i < l/2; i++ )
 {
     btlist.append( resultingData[ i ]);
 }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top