You can generate a signal with frequency f
with sin(2*pi*f*t)
where t
is time. Yet, when I sweep the frequency from 0 to 10KHz, my signal reaches 20kHz.
Here is the instantaneous FFT:
And the code you can use to reproduce:
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
duration = 10 # Duration of the audio in seconds
sample_rate = 44100 # Sample rate in Hz
t = np.linspace(0, duration, int(sample_rate * duration))
# Generate sine wave with increasing frequency
frequency_start = 10 # Start frequency in Hz
frequency_end = 10000 # End frequency in Hz
sine_wave = np.sin(2 * np.pi * np.linspace(frequency_start, frequency_end, len(t)) * t)
# Compute STFT
window_size = 1024
hop_length = 256
frequencies, times, Z = signal.stft(
sine_wave,
fs=sample_rate,
nperseg=window_size,
noverlap=window_size-hop_length
)
# Plot spectrogram
plt.figure(figsize=(10, 6))
plt.pcolormesh(times, frequencies, 20 * np.log10(np.abs(Z)), shading='gouraud')
plt.colorbar(label='Amplitude (dB)')
plt.ylabel('Frequency (Hz)')
plt.xlabel('Time (s)')
plt.title('STFT Spectrogram')
plt.show()
I generated a wav file from the signal generated and played it over speakers. It's indeed going till 20 kHz.
Why does this happen? What's the correct way to generate a frequency sweep? How does scipy.signal.chirp produce the correct result?