$124$ Hz sampled at $256$ Hz has "beats", but $128$ doesn't - a phenomenon of this question:
Whether these are "legitimate" beats is up to interpretation, but suppose the goal is the underlying continuous-time function and we are bandlimited, and beats are supposed to reflect amplitude - then it's not legitimate.
Question is, what interpolation do audio readers use, if any? For above example, a .wav
generated by scipy
with 256 samples yields no beats in either case, but if we use 2048 samples with frequencies scaled proportionally (and beats graphically verified), there are beats.
Above with 8 samples is just a brief bleep, despite the sampling rate specifying a 1 sec duration, so one might think they're converted directly to voltages, but... electricity is fast enough that I don't have to hear 2048 samples at all.
Extra detail
What I'm really trying to figure out is when to favor calling the left figure "beats". I'm not the only one who thinks they're beats; librosa.stft:

The culprit is imperfect analyticity. What I'm unsure of, is whether the spectrogram should show a flat line; again, I think it depends on interpretation, and I'm trying to interpret it for audio.
(As a side note, if imperfect analyticity yields "more accurate" amplitude in some sense, I wonder if it does the same for instantaneous frequency.)
Audio code
import numpy as np
from scipy.io.wavfile import write
N = 2048
t = np.linspace(0, 1, N, 0)
f0, f1 = N//2 - 4, N//2
x0 = np.cos(2*np.pi * f0 * t)
x1 = np.cos(2*np.pi * f1 * t)
A = np.iinfo(np.int16).max
x0, x1 = x0 * A, x1 * A
sr = int(1/np.diff(t)[0])
write('x0.wav', sr, x0.astype(np.int16))
write('x1.wav', sr, x1.astype(np.int16))
.wav
. And, these are exact sines, represented as diracs in DFT: note the integer frequencies andendpoint=False
. (but I suppose you mean we can tell if the beats are legitimate from frequency domain -- then agreed) $\endgroup$