When writing code for sound development, is important take care about the size of each sample, the byte order for storing the samples as binary data, and if is necessary to write a header to the data, or if it's raw, header-less.
And if your goal is fill a QBuffer
you can write to it trough QDataStream
, and read it back if you will.
In my answer, I'll assume Little Endian, and instead of float, I'll use 16 bits signed integer samples, 1 channel and 8000Hz frequency.
I'm providing a simple example of tone generator, please adapt it to your needs!
Let's see the following console example:
#include <QtCore>
#include <QtMultimedia>
static QBuffer m_float_buffer;
void toneGenerator()
{
QDataStream write_stream(&m_float_buffer);
write_stream.setVersion(QDataStream::Qt_5_0); //Protocol for version 5.0
write_stream.setByteOrder(QDataStream::LittleEndian);
//Tone generator from http://www.cplusplus.com/forum/general/129827/
const unsigned int samplerate = 8000;
const unsigned short channels = 1;
const double pi = M_PI;
const qint16 amplitude = qint16(INT16_MAX * 0.5);
const unsigned short n_frequencies = 8;
const unsigned short n_seconds_each = 1;
float frequencies[n_frequencies] = {55.0, 110.0, 220.0, 440.0, 880.0, 1760.0, 3520.0, 7040.0};
const int n_samples = channels * samplerate * n_frequencies * n_seconds_each;
int index = n_samples / n_frequencies;
for (unsigned short i = 0; i < n_frequencies; i++)
{
float freq = frequencies[i];
float d = (samplerate / freq);
int c = 0;
for (int j = index * i; j < index * (i + 1); j++)
{
float deg = 360.0f / d;
write_stream << qint16(qSin((c++ * double(deg)) * pi / 180.0) * amplitude);
}
}
}
void dataPlay()
{
QAudioFormat format;
format.setCodec("audio/pcm");
format.setSampleRate(8000);
format.setChannelCount(1);
format.setSampleSize(16);
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format))
{
qDebug() << "Raw audio format not supported by backend, cannot play audio.";
return;
}
QAudioOutput audio(format);
QEventLoop loop;
QObject::connect(&audio, &QAudioOutput::stateChanged, &audio, [&](const QAudio::State state){
if (state != QAudio::ActiveState)
loop.quit();
});
audio.start(&m_float_buffer);
loop.exec();
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "Opening buffer...";
m_float_buffer.open(QBuffer::ReadWrite);
qDebug() << "\nGenerating...";
toneGenerator();
//Back to beginning, now for reading
m_float_buffer.seek(0);
qDebug() << "\nPlaying...";
dataPlay();
qDebug() << "\nQBuffer size:" << m_float_buffer.size() << "bytes";
return a.exec();
}