Tone Generator Inaccuracies?

I need to create very accurate tones @ 96K

I tried to create a 830.61Hz sine wave @ 96K

To get a perfect loop I should be able to multiply 830.61 X 9600 = 7973856 (or 83.061 seconds)

Then simply set start of loop at zero and end of loop at 7973856 and it SHOULD be 100% accurate

When I generate the tone and look at what has been calculated, something is wrong

This has always worked for me with Sound Forge

Any ideas on this?



A frequency of 830.61 Hz has a period of 1/830.61 seconds.
At 96000 Hz sample rate, to convert seconds to samples, multiply seconds by 96000.
So a single cycle at 830.61 Hz would be 96000/830.61 = 115.57770795 sample periods.

68991 cycles of 830.61 Hz at 96000 Hz sample rate would be:
1 cycle period = 96000/830.61 samples
68991 cycles = (68991 * 96000)/ 830.61 = 7973821.64914942
So 7973822 samples will be very nearly perfect.

I had the first calculation, thanks

But where does 68991 come from?

What would make it perfect?

Can I do this:

83061 cycles of 830.61 Hz at 96000 Hz sample rate would be:
1 cycle period = 96000/830.61 samples
83061 cycles = (83061 * 96000)/ 830.61 = 9600000
So 96000.00 samples will be perfect

I was trying to account for the two decimal places and over complicating it

Now makes perfect sense to me



I looked for the closest number of complete cycles to your figure of 7973856 samples.

To do that:
We know that 1 cycle is: “(sample rate)/frequency” samples.
How many cycles in 7973856 samples = (number of samples)/(samples per cycle)
Which gives us:
= 68991.29721 cycles
Rounding to the closest number of cycles = 68991 cycles.

Any whole number of samples that is an exact multiple of 96000/830.61
Try 100 seconds

or 3,200,000 samples (33.333 seconds)

that’s a pretty nasty frequency, isn’t it?
The exact value (to 50 places) would be:
830.60939515989027704488357786743025088666010693809 Hz

The question is now how much accuracy one wants.
Steve’s 33.3… seconds are perfect for 830.61 Hz
For 830.609 Hz it would be:
1,000 s / GCD(96,000,000 , 830,609) = 1,000 / 1 = 1,000 seconds
and for 830.6094 Hz:
10,000 s / GCD(960,000,000 , 8,306,094) = 10,000 / 6 = 1,666.667 seconds

That’s the problem with such irrational, transcendental numbers… :wink:


Is that for G#5/Ab5 at A440?

Exactly, for equal temperament to be precise.

Here’s the Octave formula for the frequency value:


It works only with the Symbolic package installed.

I guess this is of most interest in the “Audio Processing” board so I moved it there.


Yes exactly

But really just wanted to make it possible to make accurate loops that don’t click (without having to look for them) of any audio frequency which has two decimal places in it at any given sample rate

So I could make a sine wave I could throw in an Arduino or a Pi and it would loop? to play an accurate tone at say 319.88Hz

And I can predict the zero cross point of the sample and just type in a number rather than look for it

I need a formula in an Excel sheet which says



So if an Arduino plays back WAVs at a lower sample rate of say 8KHz then I can use the Audacity tone generator to make a suitable WAV and set the loop points and it will playback without clicking (in an ideal world ;/)

Does that make sense now?


We know that for frequency F Hz, there are F complete cycles in 1 second,
an if F is a whole number, then the number of complete cycles in 1 second will be a whole number.

So what we need to do for a decimal number, is to look for a frequency that is an exact multiple of F and is itself a whole number. For a 2 digit decimal this is easy - we can just multiply by 100.
830.61 * 100 = 83061 (whole number).
So for any 2 digit decimal frequency, 100 seconds will be a whole number of cycles.
830.61 Hz has 830.61 cycles in 1 second
830.61 Hz has 83061 cycles in 100 seconds.
We know that there are an exact whole number of samples in each whole second (96000), so 100 seconds must be a whole number of samples (9600000).

For ‘some’ decimal frequencies, smaller durations may be possible. To find these, look for common factors of the number of samples and the number of cycles in 100 seconds.
In this case we have 9600000 samples in 100 seconds, and 83061 cycles in 100 seconds.
Both numbers are divisible by 3.
9600000/3 = 3200000
83061/3 = 27687
so in 320000 samples there are exactly 27687 cycles.

For the Nyquist prompt:

(let* ((freq 830.6)
       (fs 96000)
       (exponent (- (flatsize freq) (flatsize (truncate freq))))
       (multiplier (expt 10.0 (max 0.0 (1- exponent)))) 
       (fsm (truncate (* multiplier fs)))
       (freqm (truncate (* multiplier freq)))
       (divisor (gcd fsm freqm))
       (seconds (/ multiplier 1.0 divisor))
       (whole-seconds (truncate seconds))
       (cycles (/ freqm divisor))
       (samples (truncate (* seconds fs))))   
(format nil "A perfect loop for a tone at the frequency ~a Hz
can be achieved after ~a cycle(s).
This corresponds to ~a seconds,
or ~a seconds and ~a samples,
or ~a samples all in all."
        freq cycles seconds whole-seconds (* fs (- seconds whole-seconds)) samples))

Please test for different “freq” and “fs”.

For example for 440.56 Hz it gives the same answer - 5507 cycles - at 44100 Hz and 88200 Hz.

Perhaps I am not understanding what we are aiming for in a perfect loop. I thought it was a minimum length in whole seconds.


It’s the minimum length in whole samples.

Excellent thanks that’s perfect

I almost understand the logic in this code but where do I put it to run it?

I have a Mac - is there somewhere I can paste it to make it run?


In the “Nyquist Prompt” effect (see:

Tip: You can save the snippet either directly on the hard drive, or more conveniently as user preset:
Nyquist Prompt–>Manage–>Save Preset
and it can easily be revoked by Manage–>User Presets–>given name.

Alternatively, it could be made to work as a proper plugin for the “Analyze” menu.
…or generate menu with the tone with the right frequency and length (sample rate is given by the selection or the project rate).

Okay perfect thanks

Of course 100 second samples are not going to work in Arduino

even if I slow the sample rate right down?

useful to know the Math though for other applications