Raw Audio Data Playback
-
Hi All,
I have set the correct settings for my QAudioFormats according to my pc, however, after start() is executed, I don't hear anything.
-
Does raw audio data need processing before it can be played? E.g, normalising the data to the various step levels?
-
When selecting 'audio/pcm' does it mean, the default output device will be playing audio based on pcm?
-
How could I also directly implement an int array as the source to audio->start( QIOdevice* device)?
From: http://doc.qt.io/qt-5/qaudiooutput.html
void MainWindow::doThat() { QString myFile = "brilliant_terrain.raw"; sourceFile = new QFile(); sourceFile->setFileName(myFile); sourceFile->open(QIODevice::ReadWrite); if (sourceFile->error() != QFile::NoError){ qDebug()<<"Open FIle error"; } QAudioFormat format; // Set up the format, eg. format.setSampleRate(44100); format.setChannelCount(1); format.setSampleSize(32); format.setCodec("audio/pcm"); format.setByteOrder(QAudioFormat::LittleEndian); format.setSampleType(QAudioFormat::UnSignedInt); QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice()); if (!info.isFormatSupported(format)) { qWarning() << "Raw audio format not supported by backend, cannot play audio."; return; } // qDebug()<<info.supportedCodecs(); // qDebug()<<info.supportedByteOrders(); // qDebug()<<info.supportedChannelCounts(); // qDebug()<<info.supportedSampleRates(); // qDebug()<<info.supportedSampleSizes(); audio = new QAudioOutput(format, this); connect(audio, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleStateChanged(QAudio::State))); audio->start(sourceFile); qDebug()<<"Audio Start"; } void MainWindow::handleStateChanged(QAudio::State newState) { switch (newState) { case QAudio::IdleState: // Finished playing (no more data) audio->stop(); sourceFile->close(); qDebug()<<"Finished Playing"; delete audio; break; case QAudio::StoppedState: // Stopped for other reasons if (audio->error() != QAudio::NoError) { // Error handling } break; default: // ... other cases as appropriate break; } }
-
-
Hi,
-
What kind of raw data is that ? What format ? What sample rate ? What sample size ?
-
It means that you are going to feed it PCM data to play
-
You have to use the second overload and you'll have to implement handling of your data to feed the device properly.
-
-
@scottnat said in Raw Audio Data Playback:
How could I also directly implement an int array as the source to audio->start( QIOdevice* device)
You must store the data in a QByteArray first (in the correct ByteOrder, here LittleEndian as in your example), then assign that QByteArray to a buffer, e.g. as follows:
QByteArray* m_data; // --> fill m_data with your PCM data QBuffer m_buffer; //this is really a QIODevice m_buffer.setBuffer(m_data); m_buffer.open(QIODevice::ReadOnly); m_audioOutput->start(&m_buffer);
That's how I did it: I first read the complete file from disk into the QByteArray, but of course you can also directly pass the open file to the start() method.
QFile m_file; //this is also a QIODevice m_file.setFileName(fileName); m_file.open(QIODevice::ReadOnly); m_audioOutput->start(&m_file);
-
@Diracsbracket Thank you. I will give this a shot.
-
Hi, @Diracsbracket
Basically I have 1024 x uint32 values stored in audioData. Since they are uint32, each number has a size of 4 bytes.
I store that number in a QByteArray, byte by byte in little endian.
frameMax is 1024.- However, when I play the audio, there is still no sound being played. Is something wrong with the way I filled my QByteArray?
- My QAudioFormat is set to play at UnSignedInt - 32 bit resolution. So will QAudioOutput understand that my buffer is only feeding in byte by byte, and not 4 bytes?
- My application will crash after audio has stopped.
QByteArray m_data; QDataStream mydataStream(&m_data,QIODevice::WriteOnly); mydataStream.setByteOrder(QDataStream::LittleEndian); quint32 n = 0; for (int i =0; i < frameMax; i++){ n = audioData[i]; for(int j = 0; j != sizeof(n); ++j) { m_data.append((char)(n&(0xFF << (j*8)) >>(j*8))); } } QBuffer m_buffer; m_buffer.setBuffer(&m_data); m_buffer.open(QIODevice::ReadOnly); audio->start(&m_buffer);
-
@scottnat said in Raw Audio Data Playback:
n = audioData[i]; for(int j = 0; j != sizeof(n); ++j) { m_data.append((char)(n&(0xFF << (j*8)) >>(j*8))); }
You can directly use the << operator of
QDataStream
instead of the inner loop you're using, like so:mydataStream << audioData[i];
Furthermore, the documentation of
QDataStream
states that when passing aQByteArray
to it"Since QByteArray is not a QIODevice subclass, internally a QBuffer is created to wrap the byte array."
So you might just as well create your
m_buffer
first, assign yourm_data
QByteArray
to it and passm_buffer
directly tomydataStream
, to avoid the creation of the internal buffer. -
Thank you, @Diracsbracket. From what you have commented I have achieved my audio playback of raw audio data.
Although the raw audio format is 32bits, and the supported formats indicated that 32 bits was supported, in actuality for my windows OS, i think only 8 bit Unsigned Int or 16 bit Signed Int work.