Rudimentary DFT implementation

def dft1(f):
    f = np.asarray(f)
    N = f.shape[0]
    W = np.exp(-2 * np.pi * 1.0j / N)
    F = np.zeros(f.shape, dtype=complex)
    for k in range(N):
        F[k] = 0.0
        Wk = W**k
        for j in range(N):
            F[k] += f[j] * (Wk**j)
    return F
f = data_piano[:2000]
F = dft1(f)
N = len(f)
dx = 1. / sampling_rate
freq = 1.0 / (N * dx) * np.arange(N)
plt.plot(freq[:100], F.real[:100])
F_numpy = np.fft.fft(f)
frequency_numpy = np.fft.fftfreq(N, dx)
print(np.allclose(F, F_numpy))
plt.plot(frequency_numpy[:100], F_numpy[:100].real)

Our algorithm dft1 as well as fft from NumPy give us the same result: