Sputnik-1 was the first artificial satellite, launched by the Soviet Union on Oct. 4 1957.
It used radio frequency to broadcast a beeping sound towards the surface of the Earth.
By the time the sound reached the earth, and due to the performance of the recording equipment at the time (analog tape recorders), the sound is noisy, but the regular beeps can be heard clearly. Although this signal carried no information, its existence itself was fascinating due to the political consequences of being able to send objects into space.
The Sputnik crisis created the perception in the United States of a threat from the Soviet Union, as the same launcher that put Sputnik in orbit could very well deliver a nuclear warhead directly to the american continent, bypassing all oceanic defences. In additon, the american government became aware of the urgency of funding for science education to catch up to the Soviet Union in math and science, which was critical to the Cold War effort. This lead to increased funding, and improved education and research in math, science and engineering.
Of course, launching a satellite also showed the possibility of space exploration. The timing of the event, at the height of the Cold War, meant a race between the Soviet Union and the USA to place a human in orbit. The first man to reach orbit was Gagarin in April 1961, followed by Shepard in May 1961. These men were called Cosmonauts in the Soviet Union and Astronauts in the USA. The race to the moon that followed was won by the Apollo 11 team, landing on Earth's satellite in July 1969.
From a more peaceful perspective, the fact that satellites can be placed into orbit (in this case, it flew for about three months before crashing) and send signals back towards the Earth demonstrated the possibility of telecommunication satellites to carry radio, television, or telephone signals across the oceans. This was revolutionary at the time, and would take another decade to become reality.
We will use the Sputnik signal to demonstrate basic time and frequency analysis routinely done in signal processing.
First, load the signal and print its sampling rate. The sampling rate is the number of samples collected per second. It is a very import information to relate the sampled signal (a vector of numbers) to its physical dimension (in seconds, or Hertz).
from scipy.io import wavfile
fs, data = wavfile.read("sputnk1b.wav")
print 'Sampling frequency Fs = %d Hz' % (fs)
Sampling frequency Fs = 11025 Hz
Plot the waveform in the time domain.
%pylab inline
figsize(9,6)
# define nice plotting function for time domain signals
def plot_time(x, fs):
'''
Plot a time domain signal
x: signal
fs: sampling frequency
'''
# each sample corresponds to 1/fs seconds interval
time_axis = arange(x.shape[0])/float(fs)
plot(time_axis, x)
xlabel("Time [s]")
ylabel("Amplitude")
xlim((0,time_axis[-1]))
# plot the sputnik signal
plot_time(data, fs)
show()
Populating the interactive namespace from numpy and matplotlib
Zoom in on one of the beeps.
subplot(2,1,1)
plot_time(data[:fs/2], fs)
title('One beep')
subplot(2,1,2)
plot_time(data[fs/8-200:fs/8],fs)
title('Zoom in the beep')
subplots_adjust(left=0.0, right=1., bottom=0., top=1., wspace=0.18, hspace=0.28)
This signal has a large positive offset (frequently called DC offset by electrical engineers). This is not desirable for frequency analysis and we subtract it to obtain a zero mean signal.
data = data - np.mean(data)
Plot the waveform in the spectral domain. Determine the frequency of the sinusoid.
# define a function that plots the spectrum of a real signal
def plot_freq(x, fs):
'''
Plot the spectrum of a signal x
x: signal
fs: sampling frequency
'''
# compute real FFT and transform to decibels
N = x.shape[0]
# The discrete Fourier transform of a real signal is symmetric
# thus we only keep half of the output of FFT.
# Here, we also directly transform the amplitude to decibels.
data_freq_db = 20.*log(abs(np.fft.fft(x)[0:N/2+1]))
# Each discrete point on the frequency axis covers Fs/N Hertz.
# This means the whole axis (positive side) runs from 0 to Fs/2 Hertz
frequency_axis = arange(N/2+1)/float(N)*fs
plot(frequency_axis, data_freq_db)
xlabel("Frequency [Hz]")
ylabel("Energy [dB]")
xlim(0,fs/2.)
ylim(0,1.1*data_freq_db.max())
# plot the spectrum of the sputnick signal
plot_freq(data, fs)
show()
Plot the short-time fourier transform (STFT) of the signal.
(We use the STFT code proposed here)
You can change the parameters frame_size
(the length of every frame to which a traditional Fourier transform is applied) and time_shift
(the distance between every two consecutive frames) to see the effects.
import scipy
def stft(x, fs, framesz, hop):
'''
Compute the Short Time Fourier Transform of a real signal x.
x: signal
fs: sampling frequency
framesz: time duration of one analysis frame
hop: time difference between two frames
'''
framesamp = int(framesz*fs)
hopsamp = int(hop*fs)
# Analysis window is used to obtain a smoother spectrogram
w = scipy.hamming(framesamp)
# Recall that we only need half of the frequencies for real signals
X = scipy.array([np.fft.fft(w*x[i:i+framesamp])[:framesamp/2+1]
for i in range(0, len(x)-framesamp, hopsamp)])
return X
frame_size = 0.05
time_shift = 0.020
X = stft(data, fs, frame_size, time_shift)
# set the axis size correctly
extent=(0,X.shape[0]*time_shift,0,fs/2.)
# plot, color intensity is proportional to signal energy in decibels
figure()
imshow(20.*log(abs(X.T)), origin='lower', aspect='auto',interpolation='nearest',extent=extent)
xlabel('Time [s]')
ylabel('Frequency [Hz]')
show()
The signal seems to be a little noisy. Let's see if we can do something about it. We will try to denoise the signal using a simple moving averaging filter. You can view the effect of the filter length by changing it.
def moving_average(x, length):
'''
Compute the moving average of x
x: signal
length: length of average
'''
y = np.zeros(len(data))
for i in range(data.shape[0]):
y[i] = np.mean(data[maximum(0, i-length+1):i+1])
return y
# you can try changing the filter length here:
filter_length = 10
y = moving_average(data, filter_length)
subplot(2,2,1)
plot_time(data, fs)
title('Original')
subplot(2,2,2)
plot_freq(data, fs)
title('Original (spectrum)')
subplot(2,2,3)
plot_time(y, fs)
title('Denoised signal')
subplot(2,2,4)
plot_freq(y, fs)
title('Denoised signal (spectrum)')
subplots_adjust(left=0.0, right=1., bottom=0., top=1., wspace=0.18, hspace=0.28)
scaled = np.int16(y/np.max(np.abs(y)) * 32767)
wavfile.write("denoised.wav",fs,scaled)
Notice how the noise floor has lowered from around 150 in the original spectrum to 100 in the denoised spectrum.