Sei sulla pagina 1di 4

Understanding Fourier Stuff

Save the .npy files I have sent you to the same folder you save your script files to. You will use np.load to
load the info in each file when you need to. When working with these audio files, we will not multiply
our k by 2pi, because we want to view them in Hz instead of rad/s.

Your .npy file contains an array, let’s call it 𝑦. Let 𝑛 be the number of points in array 𝑦. These correspond
to a sampling frequency (Fs), which in this case is 16384. Let t be an array with values 1 to 𝑛, divided by
the sampling frequency.

Note: It is a common naming convention to use the same letter name for a Fourier Transform of the
original and use case to distinguish between the two (lower case for time domain signal, upper case for
Fourier Transform, or frequency domain signal).

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Try generating Fourier plots for the following functions. Plot the absolute value of the Fourier transform.
What do you notice?

1. sin(𝑡)
2. sin(100𝑡)
3. sin(200𝑡)
4. sin(50𝑡) and cos(50𝑡)
5. sech(𝑡)
6. sech(10𝑡)
7. sech(20𝑡)
8. sech(100𝑡)
9. sech(20𝑡) ∗ sin(100𝑡)
10. sech(20𝑡) ∗ sin(200𝑡)
11. sech(20𝑡) ∗ sin(150𝑡)
12. sech(20𝑡) ∗ (cos(150𝑡) + sin(150𝑡))
13. sech(20 ∗ (𝑡 − 2)) ∗ cos(50𝑡)
14. sech(𝑎 ∗ (𝑡 − 𝑏)) ∗ cos(𝑤𝑡)
Look at these recorded note files in both the time and Fourier domain. What do you notice?

Open Anaconda Prompt and type in pip install simpleaudio. Then, copy and paste the following script
into Spyder.

import simpleaudio as sa
import numpy as np

# calculate note frequencies


A_freq = 440
Csh_freq = A_freq * 2 ** (4 / 12)
E_freq = A_freq * 2 ** (7 / 12)

# get timesteps for each sample, T is note duration in seconds


sample_rate = 44100
T = 0.25
t = np.linspace(0, T, T * sample_rate, False)

# generate sine wave notes


A_note = np.sin(A_freq * t * 2 * np.pi)
Csh_note = np.sin(Csh_freq * t * 2 * np.pi)
E_note = np.sin(E_freq * t * 2 * np.pi)

# concatenate notes
audio = np.hstack((A_note, Csh_note, E_note))
# normalize to 16-bit range
audio *= 32767 / np.max(np.abs(audio))
# convert to 16-bit data
audio = audio.astype(np.int16)

# start playback
play_obj = sa.play_buffer(audio, 1, 2, sample_rate)

# wait for playback to finish before exiting


play_obj.wait_done()

Alter this script so that it includes 2 plots: one where it is t vs. each note, and one where it is k vs the
absolute value of the Fourier transform of each note. Include legends so you can see what you got.
What do you notice? Zoom in. Remember that the x-axis for the Fourier transform here represents
hertz.
Ever heard a fuzzy radio signal? What if we could remove that static to make the message clearer? We
can do this with notch and low pass filters.

Notch:
Notch Filter

0.8

0.6

0.4

0.2

0
-8000 -6000 -4000 -2000 0 2000 4000 6000 8000

def notch(k,k1,a):

return 1 - (1/np.cosh(a*(k - k1)) + 1/np.cosh(a*(k + k1)))

where a is a parameter determining the width of your window, and k1 (and – k1) are the modes that
you’re actively trying to filter out.

Low Pass:
Low Pass Filter

0.8

0.6

0.4

0.2

0
-1 -0.8 -0.6 -0.4 -0.2 0 0.2 0.4 0.6 0.8 1
4
x 10

def low_pass(k,k1,a):

return 0.5*(np.tanh(a*(k+k1))-np.tanh(a*(k-k1)))
By applying these filters to our Fourier transforms, we cut out signals we do not want and leave in
signals we do want based on respective frequencies.

e.g.

y = our array

Y = fft(y)

Y_clean = filter*Y

y_clean = ifft(Y_clean)

First, try this with the previous script. Use the notch filter to remove one of the notes and play the audio
to make sure you did it right. Then, try this with the files I have sent you. They contain a message,
recorded by Dr. Farnum. Comment on what you learn.

Potrebbero piacerti anche