I wrote a program in c++ to generate a .wav file for an 800Hz sine wave (1 channel, 8-bit, 16000Hz sampling, 32000 samples so 2 seconds long), but when I play it or examine its spectrogram in Audacity, it has overtones.
I think the problem is with the algorithm converting the sine wave to PCM; I'm not sure where to put 'zero' displacement, at 127, or 127.5, or 128 etc.
char data[32000];
for (int j = 0; j < 32000; ++j)
{
data[j] = (char) (round(127 + 60 * (sin(2.0 * 3.14159265358979323846264338327950 * j / 20.0))));
}
and the file produced is this: output.wav
If necessary, here's the cpp file: wavwriter.cpp
Thanks!
EDIT 2: I have changed the char to an uint8_t
uint8_t data[32000];
for (int j = 0; j < 32000; ++j)
{
data[j] = round(127 + 60 * (sin(2.0 * 3.14159265358979323846264338327950 * j / 20.0)));
}
outfile.write((char *)&data[0], sizeof data);
outfile.close();
return true;
to avoid undefined behaviour. The same problem still applies.
You've added rounding noise and deterministic quantization noise. Your sinewave repeats in an exact integer number of samples; thus the rounding error (or difference between the float value and the UInt_8 value of your sinewave) repeats exactly periodically, which produces audible harmonics.
You can reduce this noise by using dithering and noise filtered rounding when converting your floating point sinewave into UInt_8 values.
Dithering (or adding fractional random values to every sample before rounding) removes the deterministic noise. The resulting noise will be whiter instead of made out of overtones.
Noise filtering doesn't just throw away the fractional portion from rounding, but integrates this fractional remainder with an IIR filter to move the quantization noise to where it might be less audible and less likely to create a DC offset.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With