Install
Note: If you get an error message the first time you run something you may have to clone the ThinkDSP library. To do this go to "Runtime->reset all runtimes", then press the run button in the "Install" section to clone the dependency into your runtime.
!git clone https://github.com/AllenDowney/ThinkDSP.git
# This file shows how to generate a sine wave using the ThinkDSP library.
import sys
sys.path.insert(0, 'ThinkDSP/code/')
import thinkdsp
import matplotlib.pyplot as pyplot
import IPython
# Generate wave
sin = thinkdsp.SinSignal(freq=400, amp=0.5) # Where freq is the frequency and amp is the amplitude of the sine wave
wave = sin.make_wave(duration=2, start=0, framerate=44100) # Turn the sin wave into an audio wave
# Plot wave
period = sin.period
segment = wave.segment(start=0, duration=period*3)
segment.plot()
pyplot.show()
# Play wave
wave.play()
IPython.display.Audio('sound.wav') # This is required on Google Colab due to compatibility issues
Challenges:
Can you change it to a higher pitch? What about a lower pitch?
Can you increase the lenth of the sound?
Consider this:> What do you think will happen if multiple sin waves are played at the same time?
import sys
sys.path.insert(0, 'ThinkDSP/code/')
import thinkdsp
import matplotlib.pyplot as pyplot
import IPython
# Generate wave
sin1 = thinkdsp.SinSignal(freq=400, amp=0.5)
sin2 = thinkdsp.SinSignal(freq=800, amp=0.3)
mix = sin1 + sin2 # Notice here how 2 waves can be added together
wave = mix.make_wave(duration=2, start=0, framerate=44100)
# Plot wave
period = mix.period
segment = wave.segment(start=0, duration=period*3)
segment.plot()
pyplot.show()
# Play wave
wave.play()
IPython.display.Audio('sound.wav')
Challenge:
Can you add 3 waves together, what about 4, or 5?
Consider this:> Do you think there is a better way to graph this data?
import sys
sys.path.insert(0, 'ThinkDSP/code/')
import thinkdsp
import matplotlib.pyplot as pyplot
import IPython
# Generate wave
sin1 = thinkdsp.SinSignal(freq=400, amp=0.5)
sin2 = thinkdsp.SinSignal(freq=800, amp=0.3)
mix = sin1 + sin2 # Notice here how 2 waves can be added together
wave = mix.make_wave(duration=2, start=0, framerate=44100)
# Plot spectrum of wave
spectrum = wave.make_spectrum()
spectrum.plot()
pyplot.show()
# Play wave
wave.play()
IPython.display.Audio('sound.wav')
Challenge:
Can you increase the higher frequencies to have a higher amplitude?
What happens when you add more waves to the mix?
Consider this:> What do you think a frequency domain plot of a song would look like
!git clone https://github.com/Tyler-Hilbert/AudioProcessingInPythonWorkshop.git
import sys
sys.path.insert(0, 'ThinkDSP/code/')
import thinkdsp
import matplotlib.pyplot as pyplot
import IPython
# Read in audio file
# FIXME - will this work for non wav files
wave = thinkdsp.read_wave('AudioProcessingInPythonWorkshop/test.wav')
# Grab first 10 seconds of audio (you can ignore me)
clipLength = 10 # in seconds
index = 0
while (index < wave.ts.size and wave.ts[index] < clipLength):
index += 1
# Remove extras
wave.ts = wave.ts[:index]
wave.ys = wave.ys[:index]
# Plot spectrum of audio file
spectrum = wave.make_spectrum()
spectrum.plot()
pyplot.show()
# Play audio file
wave.play()
IPython.display.Audio('sound.wav')
Filtering
Now we will apply a filter to the sound. A low pass filter will remove high frequencies while a high pass filter will remove low frequencies. Think of a low pass filter as increasing bass and a high pass filter as increasing treble.
This piece of code will apply a low pass filter. Listen to how it sounds different, then compare how the frequencies changed from the last graph.
import sys
sys.path.insert(0, 'ThinkDSP/code/')
import thinkdsp
import matplotlib.pyplot as pyplot
import IPython
# Read in audio file
wave = thinkdsp.read_wave('AudioProcessingInPythonWorkshop/test.wav')
# Grab first 10 seconds of audio (you can ignore me)
clipLength = 10 # in seconds
index = 0
while (index < wave.ts.size and wave.ts[index] < clipLength):
index += 1
# Remove extras
wave.ts = wave.ts[:index]
wave.ys = wave.ys[:index]
# Filter
spectrum = wave.make_spectrum()
spectrum.low_pass(cutoff = 500, factor = .1)
#spectrum.high_pass(cutoff = 1500, factor = .1) # FIXME - Change back to low pass filter
filteredWave = spectrum.make_wave()
# Plot spectrum of audio file
spectrum = filteredWave.make_spectrum()
spectrum.plot()
pyplot.show()
# Play filtered audio file
filteredWave.play()
IPython.display.Audio('sound.wav')
Challenge:
Try to decrease of increase the amount of "bass" Try to change the change of frequencies that are filtered out Change the low pass filter to a high pass filter (by switching the comments) and see how it changes
Consider this:> Why do you think the high pass filter sounds poorly?
I am assuming you have tried the high pass filter and noticed how bad it sounds, and the volume decreasing. We will now fix this by adding the filtered sound back into the original sound.
import sys
sys.path.insert(0, 'ThinkDSP/code/')
import thinkdsp
import matplotlib.pyplot as pyplot
import IPython
# Read in audio file
wave = thinkdsp.read_wave('AudioProcessingInPythonWorkshop/test.wav')
# Grab first 10 seconds of audio (you can ignore me)
clipLength = 10 # in seconds
index = 0
while (index < wave.ts.size and wave.ts[index] < clipLength):
index += 1
# Remove extras
wave.ts = wave.ts[:index]
wave.ys = wave.ys[:index]
# Filter
spectrum = wave.make_spectrum()
spectrum.high_pass(cutoff = 1500, factor = .1) # FIXME - Change back to low pass filter
filteredWave = spectrum.make_wave()
# Add filtered wave to original wave
filteredWave.ys *= 10 # Increase the filtered wave's power so the treble effect is more noticable
combinedWave = filteredWave + wave
# Plot spectrum of audio file
spectrum = wave.make_spectrum()
spectrum.plot()
pyplot.show()
# Play filtered audio file
combinedWave.play()
IPython.display.Audio('sound.wav')
Try it with a different song by replacing the loaded wave from the previous examples (you'll need to run the "Extract wav from mp3" code to get the rock.wav file first):
wave = thinkdsp.read_wave('AudioProcessingInPythonWorkshop/rock.wav') # Paste this into the previous examples
import subprocess
subprocess.call(['ffmpeg', '-i', 'AudioProcessingInPythonWorkshop/rock.mp3',
'AudioProcessingInPythonWorkshop/rock.wav'])
view file system
import subprocess
p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE)
print(str(p.communicate()[0], 'utf-8'))