0. Outline of the Course¶
Here's the official course description:
Introduction to signal processing for advanced undergraduates or graduate students in the biological, physical, social, engineering and computer sciences. Representation and processing of continuous-time and discrete-time signals and images using phasors, Fourier series, sampling, FIR filters, discrete-time Fourier transform, Z transform, and IIR filters. Machine problems include processing of music, speech, photographic image, bioelectric, and biomedical image data. Course Information: 4 undergraduate hours. 4 graduate hours. Credit is not given towards graduation for both ECE 310 and ECE 401. Prerequisite: MATH 220.
If you're an ECE student, please note the second-to-last sentence.
Here are some other links to help you get started:
- The web page for this course is https://courses.engr.illinois.edu/ece401. There, you can find a list of lectures, and information about grading, assignments, and exams.
- The textbook is Signal Processing First by McClellan, Schafer and Yoder.
- All machine problems in this course will use python. Instructions for each machine problem, and some lectures (like this one), will use Jupyter notebooks. If you don't have a lot of previous python experience, I strongly recommend that you install Anaconda, because it includes pre-installed versions of many of the packages we will use in this course, including Jupyter, numpy, pyplot and IPython.
- If you want to run all of the code in this lecture, you'll also need to install librosa. You can do that by running the following code block, which uses the exclamation point (!) to run a system command that installs librosa:
!pip install librosa
Requirement already satisfied: librosa in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (0.10.2.post1) Requirement already satisfied: joblib>=0.14 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (1.2.0) Requirement already satisfied: pooch>=1.1 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (1.6.0) Requirement already satisfied: numba>=0.51.0 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (0.57.0) Requirement already satisfied: scikit-learn>=0.20.0 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (1.2.2) Requirement already satisfied: numpy!=1.22.0,!=1.22.1,!=1.22.2,>=1.20.3 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (1.24.4) Requirement already satisfied: soxr>=0.3.2 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (0.3.5) Requirement already satisfied: scipy>=1.2.0 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (1.10.1) Requirement already satisfied: soundfile>=0.12.1 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (0.12.1) Requirement already satisfied: decorator>=4.3.0 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (5.1.1) Requirement already satisfied: typing-extensions>=4.1.1 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (4.11.0) Requirement already satisfied: lazy-loader>=0.1 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (0.2) Requirement already satisfied: msgpack>=1.0 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (1.0.5) Requirement already satisfied: audioread>=2.1.9 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from librosa) (3.0.0) Requirement already satisfied: llvmlite<0.41,>=0.40.0dev0 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from numba>=0.51.0->librosa) (0.40.0) Requirement already satisfied: packaging>=20.0 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from pooch>=1.1->librosa) (23.2) Requirement already satisfied: requests>=2.19.0 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from pooch>=1.1->librosa) (2.32.2) Requirement already satisfied: appdirs>=1.3.0 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from pooch>=1.1->librosa) (1.4.4) Requirement already satisfied: threadpoolctl>=2.0.0 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from scikit-learn>=0.20.0->librosa) (3.1.0) Requirement already satisfied: cffi>=1.0 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from soundfile>=0.12.1->librosa) (1.16.0) Requirement already satisfied: pycparser in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from cffi>=1.0->soundfile>=0.12.1->librosa) (2.21) Requirement already satisfied: idna<4,>=2.5 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from requests>=2.19.0->pooch>=1.1->librosa) (3.7) Requirement already satisfied: certifi>=2017.4.17 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from requests>=2.19.0->pooch>=1.1->librosa) (2024.6.2) Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from requests>=2.19.0->pooch>=1.1->librosa) (2.2.2) Requirement already satisfied: charset-normalizer<4,>=2 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from requests>=2.19.0->pooch>=1.1->librosa) (2.0.4)
Great! Now let's try creating some signals. Roughly speaking, there are three fundamental types of signals, from which all other signals are constructed: buzz, click, and hiss.
- A periodic audio signal might sound like a buzz, or if it's more pleasant, a tone. A periodic image signal is called stripes. Electrocardiogram signals and weather patterns are approximately periodic.
- A short-duration audio signal is called an impulse, and sounds like a click. A short-duration image signal is called a dot or point.
- An unpredictably random audio, electric, or image signal is called a stochastic process and sounds like noise.
1. Periodic Signals (Tones)¶
First, let's create a pure tone, at the frequency of middle C on the piano.
import numpy as np
sr = 8000 # sampling rate, [samples/second]
t = np.arange(sr)/sr # labels for the time axis, in units of seconds
middle_C = 255 # middle C on the piano is about 255 Hz
tone = np.sin(2*np.pi*middle_C*t) # a tone at middle C
Let's view the waveform.
%matplotlib inline
import matplotlib.pyplot as plt
plt.figure(figsize=(14, 5))
plt.plot(t[:500],tone[:500])
plt.xlabel('Time (seconds)')
plt.title('255Hz Pure Tone')
Text(0.5, 1.0, '255Hz Pure Tone')
Let's view the spectrogram, using librosa.
import librosa, librosa.display
TONE = librosa.stft(tone)
TONEdb = librosa.amplitude_to_db(abs(TONE))
plt.figure(figsize=(14, 5))
librosa.display.specshow(TONEdb, sr=sr, x_axis='time', y_axis='hz')
<matplotlib.collections.QuadMesh at 0x1298e7970>
Now let's play the tone, using Ipython.display.audio.
import IPython.display as ipd
ipd.Audio(tone, rate=sr)
Now I want to write the waveform to a file, so I can open it using Praat or any other interface. For this I use soundfile: https://pysoundfile.readthedocs.io/en/latest/. First, we install soundfile in case you don't already have it:
!pip install soundfile
Requirement already satisfied: soundfile in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (0.12.1) Requirement already satisfied: cffi>=1.0 in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from soundfile) (1.16.0) Requirement already satisfied: pycparser in /Users/jhasegaw/anaconda3/lib/python3.10/site-packages (from cffi>=1.0->soundfile) (2.21)
... then, use soundfile to save the waveform as an wav file.
import soundfile as sf
sf.write('tone_255.wav', tone, sr)
2. Impulses (Clicks)¶
Next, let me create a click. A click is mostly zeros, with just one high-amplitude sample in the middle.
click = np.zeros(8000)
click[4000] = 1000 # arbitrary high-amplitude sample
plt.figure(figsize=(14, 5))
plt.plot(t,click)
plt.xlabel('Time (seconds)')
plt.title('Click at 0.5 seconds, with amplitude of 1000')
Text(0.5, 1.0, 'Click at 0.5 seconds, with amplitude of 1000')
CLICK = librosa.stft(click, hop_length=80, win_length=240) # 30ms window length, with a 10ms hop between windows
CLICKdb = librosa.amplitude_to_db(abs(CLICK))
plt.figure(figsize=(14, 5))
librosa.display.specshow(CLICKdb, sr=sr, x_axis='time', y_axis='hz')
<matplotlib.collections.QuadMesh at 0x1299deda0>
ipd.Audio(click, rate=sr)
sf.write('click.wav', click, sr)
3. Stochastic Processes (Noise)¶
Finally, the third main type of signal: noise. We'll use the function np.random.randn, which generates 8000 independent samples of a zero-mean, unit-variance Gaussian random variable.
noise = np.random.randn(8000)
plt.figure(figsize=(14, 5))
plt.plot(t[:500],noise[:500])
plt.xlabel('Time (seconds)')
plt.title('Gaussian Noise, Mean=0.0, Variance=1.0')
Text(0.5, 1.0, 'Gaussian Noise, Mean=0.0, Variance=1.0')
plt.figure(figsize=(14, 5))
NOISE = librosa.stft(noise, hop_length=80, win_length=240)
librosa.display.specshow(librosa.amplitude_to_db(abs(NOISE)), sr=sr, x_axis='time', y_axis='hz')
<matplotlib.collections.QuadMesh at 0x129acdea0>
ipd.Audio(noise, rate=sr)
sf.write('noise.wav', noise, sr)
4. Quiz¶
Go to the course webpage, click on "Lectures", then click on today's date. That link will take you to the Prairielearn page for this course, to today's quiz.
In every lecture this semester, there will be a short quiz for you to try. Each quiz can be taken as many times as you like; only your highest score will count. You will be permitted to try the quiz any time during the lecture, or any time during the 23 hours following the end of lecture, without penalty; if you submit the quiz more than 23 hours after the end of lecture, you will suffer a small penalty of 5 percent.
5. Next Steps¶
That's all for today!
If you want to learn more about signal processing, you might find it useful to try some of the available audio and video editing tools, for example:
- Interactive tools that combine audio clips into a larger artistic work include IMovie and Garage Band
- Open-source command-line tools for converting between different audio file formats or sampling rates include sox and ffmpeg
- Open-source audio editing tools include Audacity
- Open-source audio annotation tools include ELAN and Praat.
See you next time!