Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Get sound wave from QAudioInput



  • Hello,
    I want to get a sound wave from QAudioInput like here:
    Description
    This is a python code from here.
    This code works bu I want to do that with c++.

    Here is my code to do that (only for test purpose, I will clean and optimise it later):
    code to get audio output

        auto io = this->audio->start();
    
        connect(io,&QIODevice::readyRead,[this,io]{
    
            QByteArray buff = io->readAll();
            int buffLenght = buff.length();
            if (buffLenght>0){
                this->processAudioFrame(buff.constData(),buffLenght);
            }
        });
    

    code to convert audio QByteArray to list of numbers:

    void Window::processAudioFrame(QByteArray data, int lenght){
        if(lenght > 0)
        {
             short* result = (short *)data.data();
                    for (int  i=0; i < lenght/2; i++ )
                    {
                        ui->soundView->pushSoundLevel(result[i]/32768.0);
                    }
        }
    }
    

    and here in my custom widget the pushSoundLevel and repaintEvent methods:

    void SoundWidget::pushSoundLevel(double level){
        buffer.push_back(level);
        buffer.pop_front();
        this->update();
    }
    
    
    void SoundWidget::paintEvent(QPaintEvent *event){
        QPainter p(this);
        QPolygonF soundWave;
    
        for (int x = 0; x<this->buffer.size(); x++){
            soundWave<<QPointF(x,(buffer.at(x)*0.2*this->height())+this->height()/2);
        }
    
        QRectF boundingRect = soundWave.boundingRect();
        QTransform t;
        t.scale(this->width()/boundingRect.width(),1);
    
        p.setTransform(t);
        p.drawPolyline(soundWave);
    }
    

    My QAudioInput's parameters are that:

        format.setSampleRate(11025);
        format.setChannelCount(1);
        format.setSampleSize(16);
        format.setSampleType(QAudioFormat::SignedInt);
        format.setByteOrder(QAudioFormat::LittleEndian);
        format.setCodec("audio/pcm");
    

    And I have this result:
    Description

    I think that my problem come from the QByteArray conversion but I don't know why.

    I am on Arch linux with Qt 5.15.2.

    Thanks for your help.


  • Lifetime Qt Champion

    @Robotechnic said in Get sound wave from QAudioInput:

    for (int i=0; i < lenght/2; i++ )

    I would say it should be

    for (int  i=0; i < lenght; i+=2 )
    


  • Ok thanks @jsulm but, unfortunatly, this solution doesn't work as espected


  • Lifetime Qt Champion

    @Robotechnic Just realised: result is already short*, so i+=2 is indeed wrong.



  • I think my problem come from the range of the for loop because, when I play static note on a flute I got this graph:
    Description
    And as you can see around garbage of random values, I have good wave
    If someone know how to fix that thanks in advance
    I have also removed

        QRectF boundingRect = soundWave.boundingRect();
        QTransform t;
        t.scale(this->width()/boundingRect.width(),1);
        p.setTransform(t);
    

    because this create some problems



  • I fixed my problem:

    with a qDebug of lenght I have:

    data.length() lenght
    136 2730
    740 1364
    1326 1366
    414 1364
    208 1366
    458 1364

    As you can see they are not the same so, with this code, my problem is fixed:

    void Window::processAudioFrame(QByteArray data){
        const short* result = (short *)data.constData();
    
    
        for (int  i=0; i < data.length()/2; i ++ ){
            ui->soundView->pushSoundLevel(result[i]);
        }
    
    }