Home > OS >  Convert QAudioBuffer to QByteArray : loss of information?
Convert QAudioBuffer to QByteArray : loss of information?

Time:12-24

I have a WAV file that I decode with the QAudioDecoder. As a result I have a QAudioBuffer object. I want to store the data stored in QAudioBuffer in a QByteArray for my QIODevice derived class. I want to use this data in the ReadData method of my derived class for audio output. I now have 2 questions:

  • How to get a QByteArray from a QAuddioBuffer? I used the following code, but unfortunately this is not correct. The data in QAudioBuffer is coded to 2Bytes, but each element in a QByteArray is coded to 1Byte (right?). Don't we have a loss of information there? To test if QByteArray contains the original data from the WAV file, I save it to a TXT file.
  • is this approach appropriate? I actually want to apply some operations on the data stored in QAudioBuffer (e.g. filters) and listen to the result in real time.

Thanks in advance.

Here is the code

QAudioFormat *format_decoder;
format_decoder = new QAudioFormat;
format_decoder->setSampleRate(44100);
format_decoder->setChannelCount(1);
format_decoder->setSampleFormat(QAudioFormat::Int16);

QAudioDecoder decoder;
decoder.setSource(filenameSource);
decoder.setAudioFormat(*format_decoder);
decoder.start();

QObject::connect(&decoder, &QAudioDecoder::bufferReady, this, &MainWindow::slot_bufReady);

and the slot

void MainWindow::slot_bufReady(){

QAudioBuffer buffer = m_audioDecoder->read();
QByteArray buffer_ByteArray(buffer.constData<char>(), buffer.byteCount());

QFile file(filenameTest1);
if(!file.open(QIODevice::WriteOnly|QIODevice::Append)) {
        qDebug() << "ERRO ";  }

QTextStream strem(&file);
for(auto const dat: buffer_ByteArray)  {
        strem<< qreal(dat)/128.0<< "\r\n";
    }
file.cloe();

CodePudding user response:

This looks suspicious:

for(auto const dat: buffer_ByteArray)  {
        strem<< qreal(dat)/128.0<< "\r\n";
    }

Your audio format is 16-bit mono. Reading it byte by byte is a non-starter. Read it sample by sample. That is, read two bytes at a time and convert. More likely this:

int16_t* data = (int16_t*)(buffer.data());
int samples = buffer.sampleCount();
for (int i = 0; i < samples; i  )
{
    strem << data[i] << "\r\n";
}

The above will save your samples into a text file. You could plot it with Excel. But as others have said, that's not as useful as saving in as binary. You could prepend a WAV file header such that it can be played and analyzed with other tools.

Update

If your intent is to transcode from 16-bit to 8-bit, this is how you would likely do it:

 int16_t* data = (int16_t*)(buffer.data());
 QByteArray buffer_ByteArray(buffer.sampleCount(), '\0');
 for (size_t i = 0; i < samples; i  ) {
     buffer_ByteArray[i] = (char)(data[i] / 256); // 16-bit to 8-bit
 }

Note: some audio platforms use unsigned integers for 8-bit audio. That is the zero amplitude sample is 0x80. This is the case for 8-bit WAV files. If that's in play, then change this line:

buffer_ByteArray[i] = (char)(data[i] / 256); // 16-bit to 8-bit

To this:

char c = (char)(data[i] / 256); // 16-bit to 8-bit signed
const unsigned char mask = 0x80;
buffer_ByteArray[i] = (char)(mask ^ c);
  • Related