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). -
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? -
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(); }
-
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.