22unsigned char *
writeSineSample(
unsigned char *ptr, QAudioFormat::SampleFormat sampleFormat, qreal x)
24 auto writeNextFrame = [&](
auto value) {
25 *
reinterpret_cast<
decltype(value) *>(ptr) = value;
26 return ptr +
sizeof(value);
29 switch (sampleFormat) {
30 case QAudioFormat::UInt8:
31 return writeNextFrame(quint8(
std::round((1.0 + x) / 2 * 255)));
32 case QAudioFormat::Int16:
33 return writeNextFrame(qint16(
std::round(x * std::numeric_limits<qint16>::max())));
34 case QAudioFormat::Int32:
35 return writeNextFrame(qint32(
std::round(x * std::numeric_limits<qint32>::max())));
36 case QAudioFormat::Float:
37 return writeNextFrame(
float(x));
38 case QAudioFormat::Unknown:
39 case QAudioFormat::NSampleFormats:
46 qint32 sampleIndex, qreal frequency, qreal volume)
48 if (!format.isValid())
51 const qint32 length = format.bytesForDuration(duration.count());
53 QByteArray data(format.bytesForDuration(duration.count()), Qt::Uninitialized);
54 unsigned char *ptr =
reinterpret_cast<
unsigned char *>(data.data());
55 const auto end = ptr + length;
57 const double initialPhase = 2.0 *
M_PI * frequency * sampleIndex / format.sampleRate();
58 SineWaveSignal generator(frequency, format.sampleRate(), initialPhase);
59 for (
double rawSample : generator) {
62 const qreal x = rawSample * volume;
63 for (
int channel = 0; channel < format.channelCount(); ++channel)
64 ptr = writeSineSample(ptr, format.sampleFormat(), x);
73 std::chrono::microseconds duration,
74 qreal frequency, qreal volume)
77 format.setSampleFormat(QAudioFormat::Int16);
78 format.setChannelCount(1);
79 format.setSampleRate(sampleRate);
81 const QByteArray pcmData =
82 createSineWaveData(format, duration, 0, frequency, volume);
84 drwav_data_format wavFormat{};
85 wavFormat.container = drwav_container_riff;
86 wavFormat.format = DR_WAVE_FORMAT_PCM;
87 wavFormat.channels = 1;
88 wavFormat.sampleRate = drwav_uint32(sampleRate);
89 wavFormat.bitsPerSample = 16;
91 void *wavData =
nullptr;
92 size_t wavDataSize = 0;
94 if (!drwav_init_memory_write(&wav, &wavData, &wavDataSize, &wavFormat,
nullptr))
97 auto dataGuard = qScopeGuard([&] {
99 drwav_free(wavData,
nullptr);
102 const auto framesToWrite = drwav_uint64(pcmData.size() /
sizeof(qint16));
103 if (drwav_write_pcm_frames(&wav, framesToWrite, pcmData.constData()) != framesToWrite)
106 auto file = std::make_unique<QTemporaryFile>();
109 file->write(
static_cast<
const char *>(wavData), qint64(wavDataSize));