I have an audio application that produces an arbitrary length signal by repeatedly looping over a single-period waveform. In pseudo-code:
// Build a single period of a waveform at the given frequency
samples_per_waveform = int(sampling_rate / frequency)
waveform = make_sin_waveform(samples_per_waveform)
...
// Repeat the single period waveform to produce a continuous signal
count = int(duration * sampling_frequency / samples_per_waveform)
repeat `count` times:
write(waveform)
Since the number of samples per waveform is obviously an integer, I think this is subject to rounding error:
As an example, when rounding to the nearest integer, at a 5kHz sampling rate, a single-period waveform for a 300Hz signal would require 17 samples--and thus leads to an actual frequency of 294Hz. I understand the higher will be the sampling rate, the lower will be the rounding error. However, it will still exist.
Is there a way to fix that, or is this approach doomed from the start?
EDIT: As a possible workaround, I envision to keep track of the rounding error in the output loop, and duplicating one sample when the error exceeds a sample duration. I don't know if this is clear enough, but it is somewhat similar in my mind to what the Bresenham line drawing algorithm is doing.