4#ifndef AUDIOGENERATIONUTILS_H
5#define AUDIOGENERATIONUTILS_H
19#include <QtMultimedia/qaudioformat.h>
20#include <QtMultimedia/qaudiobuffer.h>
21#include <QtCore/qiodevice.h>
22#include <QtCore/qmath.h>
23#include <QtCore/qtemporaryfile.h>
33class SineWaveGenerator
36 static constexpr double tau = 2 *
M_PI;
38 SineWaveGenerator(std::uint32_t phase, std::uint32_t increment)
39 : m_phase(phase), m_increment(increment)
43 SineWaveGenerator(
double frequency,
double sampleRate,
double phase = 0.0)
44 : SineWaveGenerator(phaseToFixedPoint(phase), incrementFromFrequency(frequency, sampleRate))
48 static std::uint32_t phaseToFixedPoint(
double phase)
50 constexpr double scale =
static_cast<
double>(std::numeric_limits<std::uint32_t>::max());
51 double normalizedPhase = std::fmod(phase, tau);
52 if (normalizedPhase < 0.0)
53 normalizedPhase += tau;
54 return std::uint32_t((normalizedPhase / tau) * scale);
57 static std::uint32_t incrementFromFrequency(
double frequency,
double sampleRate)
59 constexpr double scale =
static_cast<
double>(std::numeric_limits<std::uint32_t>::max());
60 return std::uint32_t((frequency / sampleRate) * scale);
63 double getSample()
const
65 constexpr double scale =
static_cast<
double>(UINT32_MAX);
66 return std::sin(tau * (
static_cast<
double>(m_phase) / scale));
71 m_phase += m_increment;
76 double result = getSample();
82 std::uint32_t m_phase;
83 std::uint32_t m_increment;
91 using iterator_category =
std::input_iterator_tag;
92 using value_type =
double;
93 using difference_type =
std::ptrdiff_t;
95 using reference =
double;
97 iterator(
std::uint32_t phase,
std::uint32_t increment) : m_generator(phase, increment) { }
99 double operator*()
const {
return m_generator.getSample(); }
101 iterator &operator++()
103 m_generator.advance();
107 bool operator!=(
std::nullptr_t)
const
113 SineWaveGenerator m_generator;
118 : m_phase(SineWaveGenerator::phaseToFixedPoint(phase)),
119 m_increment(SineWaveGenerator::incrementFromFrequency(frequency, sample_rate))
130 std::nullptr_t
end()
const {
return nullptr; }
133 std::uint32_t m_phase;
134 std::uint32_t m_increment;
137unsigned char *
writeSineSample(
unsigned char *ptr, QAudioFormat::SampleFormat sampleFormat,
141 qint32 sampleIndex = 0, qreal frequency = 500, qreal volume = 0.8);
146 std::chrono::microseconds duration,
147 qreal frequency, qreal volume = 0.8);
152 explicit SineWaveIODevice(
const QAudioFormat &format, qreal frequency = 500, qreal volume = 0.8)
155 open(QIODeviceBase::ReadOnly);
160 unsigned char *ptr =
reinterpret_cast<
unsigned char *>(data);
161 const unsigned char *
const end = ptr + len - (len % m_format.bytesPerFrame());
164 const qreal x = m_generator() * m_volume;
165 for (
int ch = 0; ch < m_format.channelCount(); ++ch)
166 ptr = writeSineSample(ptr, m_format.sampleFormat(), x);
169 return ptr -
reinterpret_cast<
unsigned char *>(data);
177 QAudioFormat m_format;
178 SineWaveGenerator m_generator;
251 int m_bufferIndex = 0;
252 QAudioFormat m_format;
253 bool m_emitEmptyBufferOnStop =
false;
254 qreal m_frequency = 500.;
255 qint32 m_sampleIndex = 0;
QByteArray createSineWaveData(const QAudioFormat &format, std::chrono::microseconds duration, qint32 sampleIndex, qreal frequency, qreal volume)
std::unique_ptr< QTemporaryFile > makeMonoPcm16WavFile(int sampleRate, std::chrono::microseconds duration, qreal frequency, qreal volume)
QT_BEGIN_NAMESPACE unsigned char * writeSineSample(unsigned char *ptr, QAudioFormat::SampleFormat sampleFormat, qreal x)
void audioBufferCreated(const QAudioBuffer &buffer)
qint64 bytesAvailable() const override
Returns the number of bytes that are available for reading.
qint64 readData(char *data, qint64 len) override
Reads up to maxSize bytes from the device into data, and returns the number of bytes read or -1 if an...
SineWaveIODevice(const QAudioFormat &format, qreal frequency=500, qreal volume=0.8)
bool isSequential() const override
Returns true if this device is sequential; otherwise returns false.
qint64 writeData(const char *, qint64) override
Writes up to maxSize bytes from data to the device.
SineWaveSignal(double frequency, double sample_rate, double phase=0.0)
std::nullptr_t end() const