Low-distortion Audio-range Oscillator

Outrageous. That's completely out of the question for a hobbyist, and would likely scare off most small companies as well.

If you want to play, you've got to pay. This is a pretty niche piece of test equipment (which itself is niche and invariably $$)

So probably worth playing with the high performance "sound card" type systems instead.

Still very curious about how well synchronous sampling goes.
 
I can't leave well enough alone ...

My previous-best was with the synced Vic oscillator (3kHz), no window, move-to-bin-center.

What I did now was to slightly change the nominal 3kHz Vic oscillator I have to make it synchronous to the FFT to avoid the whole move to bin center processing and still not needing to use a window. I can do that now that I can sync Vic (not Vic, his oscillator ;-) to the AP digital generator.

Calculated what the nearest frequency is to 3kHz that will be synchronous when I sample at 48kHz, 32,768 FFT samples record length. Each sample has 1/48,000 = 20.83uS, and each 32,768k samples record thus takes 0.68267 seconds. Which freq closest to 3kHz will fit an integer # of cycles in this period?

204 cycles @ 2988.3Hz
205 cycles @ 3002.9Hz
206 cycles @ 3017.6Hz

... so pulling the oscillator to 3002.9Hz seemed the way to go.

This gave the attached curve, even lower than before, and still no trace of harmonics. Using the 'Sync' setting on the FFT processor means I cannot do averaging so the noise is more ragged than before, but clearly lower.
Vic where are your harmonics??

Jan

Hi Jan,

I'm a really slow reader so I hope everyone doesn't mind me jumping back a bunch of pages. But it would really help my understanding of the requirements for a synchronous FFT.

From thinking it through I've got two constraints:
- integer number of samples per wavelength
- integer number of wavelengths that fit in to a FFT in the series given by 2**n

Most of what follows is useless if those are wrong!

I think there are some rounding errors being introduced in your calcs by looking at the wavelength from the perspective of time. I think you're also out by a factor of 10 on the number of cycles captured in the 32,768 FFT. But that may not be important.



If we look at 3kHz wave sampled at 48kHz there should be exactly 16 samples per wave and 2048 waves would fit in 32768 samples. So it isn't clear why you're wanting to shift the freq from exactly 3kHz?

Further - when looking at the other related posts there is comments that the AP ADC is working at 65.536kHz so shouldn't you be working with a frequency based off that sample rate? Is that why Pavel found that artifact at 9th Harmonic? (maybe this is unrelated but it's a thought bubble)

It would be interesting if you could go back to 3kHz rather than 3002.9Hz now that you're using this off the RTX and check that you're sampling at 48kHz.

I wrote this in python to work out the frequencies of interest based on my logic earlier, so the same disclaimer applies:
Code:
fft_len = 2**22
f_samp = 48000

for n in range(2,900):
    freq = f_samp/n
    number_waves = fft_len/n
    if number_waves.is_integer():
        print(n, freq, number_waves)


4 12000.0 1048576.0
8 6000.0 524288.0
16 3000.0 262144.0
32 1500.0 131072.0
64 750.0 65536.0
128 375.0 32768.0
256 187.5 16384.0
512 93.75 8192.0
 
AX tech editor
Joined 2002
Paid Member
OK, yes I see your reasoning. I don't think the requirement is an integer number of samples within the sampling frequency, and also not required that the ADC sampling is synchronous. The only requirement to avoid spectral leaking is an integer number of periods in the FTT record, which here is 32,768 samples. The idea is that you must be able to 'glue' the last sample to the first sample with no discontinuity.

As I noted, I reasoned that 32,768 samples at 48kHz took 32,768/48,000 = 0.682666 ... seconds. I don't see how you can fit an integer number of cycles in there from a 3kHz signal.

I don't know of a closed expression to calculate the freq with an exact # of cycles so I did a guess followed by some trial & error.

Jan
 
Last edited:
OK, yes I see your reasoning. I don't think the requirement is an integer number of samples within the sampling frequency, and also not required that the ADC sampling is synchronous. The only requirement to avoid spectral leaking is an integer number of periods in the FTT record, which here is 32,768 samples. The idea is that you must be able to 'glue' the last sample to the first sample with no discontinuity.

As I noted, I reasoned that 32,768 samples at 48kHz took 32,768/48,000 = 0.682666 ... seconds. I don't see how you can fit an integer number of cycles in there from a 3kHz signal.

I don't know of a closed expression to calculate the freq with an exact # of cycles so I did a guess followed by some trial & error.

Jan

Hi Jan,

Yep I see now. It is only the second of the two constraints that I wrote.

I should have showed the result of my code for 2**15 (32768) length FFT. Rather than the 2**22 (4M) version that I had run. The cool thing is that the oscillator freqs don't change for different length FFT as long as its length is the usual 2**n values. And even cooler that it holds for the 48, 96, 192kHz series of sample rates.

Code:
fft_len = 2**15 #32768
f_samp = 48000

for n in range(2,900):
    freq = f_samp/n
    number_waves = fft_len/n
    if number_waves.is_integer():
        print(n, freq, number_waves)

2 24000.0 16384.0
4 12000.0 8192.0
8 6000.0 4096.0
16 3000.0 2048.0
32 1500.0 1024.0
64 750.0 512.0
128 375.0 256.0
256 187.5 128.0
512 93.75 64.0


2048 is the number of cycles of 3kHz you'll get in 32768 samples.

2048/3000 = 32,768/48,000


Chris
 
AX tech editor
Joined 2002
Paid Member
Going back over it, a frequency of 3002.9 also has an integer number of periods in a 32768 record (2500; I erroneously used 250).

I can sync the Viktor to 3002.9Hz but not to 3kHz (that's too far to pull it).
So I assume that with 3002.9Hz I would not need a window, but with the RTX that doesn't seem to be the case, a window still gives better results. Hmmm.

Jan
 
Going back over it, a frequency of 3002.9 also has an integer number of periods in a 32768 record (2500; I erroneously used 250).

The wav was recorded at 65,536Hz samplerate. I think the smallest number of samples to reach exact period boundary of 3,002.9Hz signal at that samplerate is exactly 1,966,080.

total samples / samples_per_period = 1966080 samples / ((1/3002.9Hz)/(1/65536Hz)) = 90,087 periods.

For 48kHz samplerate exactly 480,000 samples contain exactly 30,029 periods of the 3,002.9Hz signal.

480000 samples / ((1/3002.9Hz)/(1/48000Hz)) = 30,029 periods


That is why I duplicated the received wav at multiples of 1,966,080 samples for 65kHz and of 480,000 samples for 48kHz.

The boundary at 4M FFT is not exactly at the boundary of period for either of the samplerates. For 65kHz rate 15 averages of the 4M FFT would be required:

2^22 × 15 ÷1966080 = 32 complete blocks


For 48kHz that would take 1875 averages - quite a long calculation :)


2^22 × 1875 ÷480000 = 16,384 complete blocks

Nevertheless since there are hundreds of thousands of periods in 4M FFT block for both samplerates, the windowing error is IMO negligible.

2^22÷ ((1÷3002,9)÷(1÷65536)) = 192,185.6 periods

2^22÷ ((1÷3002,9)÷(1÷48000)) = 262,397.4 periods
 
Can you also say that with those extremely long FFT records, that windowing gets less and less important?

Jan

That would be true in general, the Fourier transform of a large "box" uniform window function gets closer and closer to an impulse (very narrow sinc function). It all depends on how large.

I still have a question on your large file, looked at in power of 2 chunks the phase rotates slowly on the 3002.9Hz fundamental (and harmonics). This makes vector averaging on the noise not work.
 
The wav was recorded at 65,536Hz samplerate. I think the smallest number of samples to reach exact period boundary of 3,002.9Hz signal at that samplerate is exactly 1,966,080.

total samples / samples_per_period = 1966080 samples / ((1/3002.9Hz)/(1/65536Hz)) = 90,087 periods.

Don't you just need exact 0.1 Hz bins?

1,966,080/655360 = 3

655360 samples are 30,029 periods.

Just noticed 30029 is prime so that's it.
 
Last edited:
I still have a question on your large file, looked at in power of 2 chunks the phase rotates slowly on the 3002.9Hz fundamental (and harmonics).

I do not understand, please can you explain? If the chunk does not contain exact periods of fundamental, of course the next chunk will have the fundamental phase rotated. But the harmonics phase should be calculated against zero phase of the fundamental, it is easy to rotate the FFT'd phases to time when fundamental was at zero phase and I think REW does it. I am almost sure it does, otherwise the harmonics phase values would wildly fluctuate every FFT run. The phase values would make no sense if they were not related to the fundamental at zero phase. Plus the distortions box does not list fundamental phase for the given FFT run, IMO it is always shifted to zero.

IMO the averaging in the RTA chart works on amplitudes only (the magnitude of complex FFT results).
 
Last edited:
Don't you just need exact 0.1 Hz bins?

1,966,080/655360 = 3

655360 samples are 30,029 periods.

Just noticed 30029 is prime so that's it.

You are right, the smallest chunk with whole number of periods is 3 times smaller - your prime, my wrong calculation (yours is much more logical that the hard force I used, wrongly assuming octave/matlab min() function will find the first occurence from beginning of array).

Since I took a multiple of my x3 chunk to create the longer wav for averaged 4M FFT, the result is still aligned with your chunk and the periods :)
 
I do not understand, please can you explain?
IMO the averaging in the RTA chart works on amplitudes only (the real part of FFT results).

You mean the magnitude. Not sure why the phase of the harmonics would matter in this case, I've seen nothing discussed here about the phase of the harmonics only the magnitudes.

I mentioned that I wanted to try vector averaging which requires perfect phase sync to the input. You need a tool that gives the user access to both the real and imaginary part of the FFT separately.