Create QAudioBuffer from wav file



  • I need create an QAudioBuffer from a wav file. I also need to get the properties of the file, such as bits, sample frequency etc.
    This is so I can display the waveform and it's properties. I need access to individual sample values, so am assuming QAudioBuffer is my best approach.
    For reference, I'm converting an old VB app, which has the following method to do this:

    Set dsBuffer(curWave) = DS.CreateSoundBufferFromFile(CommonDialog1.FileName, dsDesc(curWave))
    

    I then need to play the buffer out of the audio output.
    I've found plenty of examples of working with realtime audio streams, but not wav files, so have got a bit stuck and would appreciate any tips!
    (This is for Windows and OSX).


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Wouldn't QMediaPlayer and the QAudioDecoder be more in line with what you want to do ?



  • Thanks! I've just had a look at those classes. They seem to be OK for getting the audio properties and playing the file, but I can't see anyway to get to the buffer data. I need that for drawing the waveform and I also need to output the sample values to a text file.
    Am I missing something with those classes?


  • Lifetime Qt Champion

    Then QAudioProbe might be of interest.



  • Yeah - I did look into that, but found this thread. It looks like it's not compatible with OSX, so I can't use it as it's essential that the software is OSX compatible.
    I feel that one of the audio libraries must have a "create buffer from file" method, much like the VB directX one above. I just can't seem to find it or any similar examples.



  • I ended up solving this by manually reading the wav file byte by byte and then initialising the QAudioBuffer from a QByteArray, read from the appropriate part of the file. Here's the code. Would be good if there was a method in the QAudioBuffer to read from file automatically.

    void MainWindow::readWAV(QString wavFile, int waveNum)
    {
        QFile m_WAVFile;
        m_WAVFile.setFileName(wavFile);
        if(m_WAVFile.exists()==false)
        {
            qDebug()<<"File doesn't exist";
            return;
        }
        m_WAVFile.open(QIODevice::ReadWrite);
    
        char strm[4];
        char s[1];
        QByteArray wav;
        quint32 conv;
    
        qDebug()<<"\nstart";
        qDebug()<<m_WAVFile.read(4);//RIFF
        // m_WAVHeader.RIFF = m_WAVFile.read(4).data();
    
        m_WAVFile.read(strm,4);//chunk size
        qDebug()<<qFromLittleEndian<quint32>((uchar*)strm);
    
        m_WAVFile.read(strm,4);//format
        qDebug()<<strm;
    
        m_WAVFile.read(strm,4);//subchunk1 id
        qDebug()<<strm;
    
        m_WAVFile.read(strm,4);//subchunk1 size
        qDebug()<<qFromLittleEndian<quint32>((uchar*)strm);
    
        m_WAVFile.read(strm,2);//audio format
        qDebug()<<qFromLittleEndian<quint32>((uchar*)strm);
    
        m_WAVFile.read(strm,2);//NumChannels
        conv = qFromLittleEndian<quint32>((uchar*)strm);
        qDebug()<<conv;
        if(conv!=1)
        {
            QMessageBox::warning(this, "Import wav file", "Wav file must be mono",QMessageBox::Ok,QMessageBox::NoButton);
            return;
        }
    
        m_WAVFile.read(strm,4);//Sample rate
        conv = qFromLittleEndian<quint32>((uchar*)strm);
        qDebug()<<conv;
        if(conv!=11025)
        {
            QMessageBox::warning(this, "Import wav file", "Use file with 11025Hz sample rate for native sample rate",QMessageBox::Ok,QMessageBox::NoButton);
        }
    
        m_WAVFile.read(strm,4);//Byte rate
        qDebug()<<qFromLittleEndian<quint32>((uchar*)strm);
    
        m_WAVFile.read(strm,2);//Block Allign
        qDebug()<<qFromLittleEndian<quint32>((uchar*)strm);
    
        m_WAVFile.read(strm,2);//BPS
        conv = qFromLittleEndian<quint32>((uchar*)strm);
        qDebug()<<conv;
        if(conv!=8)
        {
            QMessageBox::warning(this, "Import wav file", "Wav file must be unsigned 8 bit",QMessageBox::Ok,QMessageBox::NoButton);
            return;
        }
    
        m_WAVFile.read(strm,4);//subchunk2 id
        qDebug()<<strm;
    
        m_WAVFile.read(strm,4);//subchunk2 size
        qDebug()<<qFromLittleEndian<quint32>((uchar*)strm);
    
        outBuffLen[waveNum] = 0;
        while(!m_WAVFile.atEnd())
        {
            m_WAVFile.read(s,1);
            wav.append(s[0]);
        }
        m_WAVFile.close();
        dsBuffer[waveNum] = QAudioBuffer(wav,fmt);
        outBuffLen[waveNum] = dsBuffer[waveNum].sampleCount();
        qDebug()<<" Processed:";
        qDebug()<<outBuffLen[waveNum];
        wavePath[waveNum] = wavFile;
        QFileInfo fileInfo(wavFile);
        waveName[waveNum] = fileInfo.fileName();
    }
    

  • Lifetime Qt Champion

    Thanks for coming back !

    I also just re-discovered that the spectrum analyser example provides the WavFile class that you could be interested in also.



  • Ah, I hadn't spotted this library - this is a slightly nicer way to read the header of a wav file than the way I did it. I may switch to this library at some point.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.