Banshee10000
Banshee10000

Reputation: 76

Qt C++ Creating a square audio tone wave. Play and saving it

Good day experts I need guidance. I have a situation that is two part. Firstly, I need to generate a square wave audio tone for a specific time specified using Qt C++ and I'm completely lost on even where to start.

Secondly I also need to export the audio to a .wav or mp3. I read somewhere that I'll need to write WAV headers to the file before I can export the data. My second question is how to export the audio in the QBuffer to a wav file.

I have found the following project on Git. However this generates a sine wave only and not a square wave. https://github.com/picaschaf/Soundgenerator

Looking at the function in this project

void QxtSoundGenerator::appendSound(qreal amplitude, float frequency, int msecs)
{

msecs = (msecs < 50) ? 50 : msecs;

qreal singleWaveTime = 1.0 / frequency;

qreal samplesPerWave = qCeil(format->sampleRate() * singleWaveTime);

quint32 waveCount = qCeil(msecs / (singleWaveTime * 1000.0));

quint32 sampleSize = static_cast<quint32>(format->sampleSize() / 8.0);

QByteArray data(waveCount * samplesPerWave * sampleSize * format->channelCount(), '\0');

unsigned char* dataPointer = reinterpret_cast<unsigned char*>(data.data());

for (quint32 currentWave = 0; currentWave < waveCount; currentWave++)
{
    for (int currentSample = 0; currentSample < samplesPerWave; currentSample++)
    {
        double nextRadStep = (currentSample / static_cast<double>(samplesPerWave)) * (2 * M_PI);

        quint16 sampleValue = static_cast<quint16>((qSin(nextRadStep) + 1.0) * 16383.0);

        for (int channel = 0; channel < format->channelCount(); channel++)
        {
            qToLittleEndian(sampleValue, dataPointer);
            dataPointer += sampleSize;
        }
    }
}

soundBuffer->append(data);
}

In the project you can append different frequencies then play them one after the other which is perfect. It just needs to be a Square wave.

Can someone please advice me as I'm not very good at math in this regard, or help me understand this block of code or show me how to go about creating a square wave in this fashion in Qt C++. Any help would be greatly appreciated.

Upvotes: 0

Views: 1188

Answers (1)

Ehz
Ehz

Reputation: 2067

Like eyllanesc mentioned, you can take the sine wave generator and use the min value when below zero, and the max value when above zero. However one thing to note is that this will produce a naive square wave. This will have artifacts because you have value changes that are above the Nyquist limit. To get a better sound you should be looking to create a band-limited square wave. A band-limited square wave is produced by adding up sine wave harmonics that are below Nyquist.

Further reading:

Nyquist: https://en.wikipedia.org/wiki/Nyquist_rate

Band limited Square waves: https://www.nayuki.io/page/band-limited-square-waves

Upvotes: 1

Related Questions