Skip to content

Commit 1d70013

Browse files
committed
separate jupyter notebooks into individual scripts
1 parent fa663a6 commit 1d70013

18 files changed

Lines changed: 787 additions & 8 deletions
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# CONVERTSECSAMPLES
2+
# This script provides two examples for converting a time delay in units of
3+
# seconds to samples and milliseconds to samples.
4+
#
5+
# See also CONVERTTEMPOSAMPLES
6+
7+
import numpy as np
8+
9+
# Example 1 - Seconds to samples
10+
Fs = 48000 # arbitrary sampling rate
11+
timeSec = 1.5 # arbitrary time in units of seconds
12+
13+
# Convert to units of samples
14+
timeSamples = np.fix(timeSec * Fs) # round to nearest integer sample
15+
16+
# Example 2 - Milliseconds to samples
17+
timeMS = 330 # arbitrary time in units of milliseconds
18+
19+
# Convert to units of seconds
20+
timeSec = timeMS/1000
21+
# Convert to units of samples
22+
timeSamples = np.fix(timeSec * Fs) # round to nearest integer samples
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# CONVERTTEMPOSAMPLES
2+
# This script provides an example for calculating a delay time in units of
3+
# samples that will be synchronized with the tempo of a song in units of
4+
# beats per minutes (BPM).
5+
#
6+
# Assume a (4/4) time signature where BEAT = QUARTER NOTE
7+
#
8+
# See also CONVERTSECSAMPLES
9+
10+
import numpy as np
11+
12+
Fs = 48000
13+
14+
beatsPerMin = 90
15+
beatsPerSec = beatsPerMin/60
16+
secPerBeat = 1/beatsPerSec
17+
18+
noteDiv = 1
19+
timeSec = noteDiv * secPerBeat
20+
timeSamples = np.fix(timeSec * Fs)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# CONVOLUTIONEXAMPLE
2+
# This script demonstrates the numpy convolution function - y = np.convolve(x, h)
3+
# The example demonstrated is with a single cycle of a sine wave. When the sine
4+
# wave is convolved with the impulse response for an echo effect, the output
5+
# signal has delayed copies of the sine wave at different amplitudes at
6+
# different times.
7+
#
8+
# See also CONV
9+
10+
import soundfile
11+
import numpy as np
12+
import matplotlib.pyplot as plt
13+
14+
# Import previously saved IR
15+
[h, Fs] = soundfile.read('impResp.wav')
16+
N = len(h)
17+
18+
# Synthesize input signal
19+
f = 4
20+
t = np.arange(0, N*0.125)/Fs
21+
sinWave = np.sin(2 * np.pi * f * t)
22+
pad = np.zeros([int(N*0.875)])
23+
x = np.concatenate((sinWave, pad))
24+
25+
# Perform convolution
26+
y = np.convolve(x, h)
27+
28+
# Plot signals
29+
xAxis = np.arange(0, N)/Fs
30+
plt.subplot(3,1,1)
31+
plt.plot(xAxis, x)
32+
plt.axis([-0.1, 2, -1.1, 1.1])
33+
plt.xlabel('Time (sec.)')
34+
plt.title('Input Signal - x[n]')
35+
36+
plt.subplot(3,1,2)
37+
plt.stem(xAxis, h)
38+
plt.axis([-0.1, 2, -1.1, 1.1])
39+
plt.xlabel('Time (sec.)')
40+
plt.title('Impulse Response')
41+
42+
plt.subplot(3,1,3)
43+
plt.plot(xAxis, y[0:Fs*2])
44+
plt.axis([-0.1, 2, -1.1, 1.1])
45+
plt.xlabel('Time (sec.)')
46+
plt.title('Output Signal - y[n]')
47+
48+
plt.show()
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# ECHOFEEDBACK
2+
# This script demonstrates one example to create a feedback, tempo-synchronized
3+
# echo effect.
4+
#
5+
# See also ECHOSYNC
6+
7+
import soundfile
8+
import numpy as np
9+
import matplotlib.pyplot as plt
10+
from IPython.display import Audio
11+
12+
# Import audio file
13+
[x, Fs] = soundfile.read('sw20.wav')
14+
Ts = 1/Fs
15+
16+
# Known tempo of recording
17+
beatsPerMin = 102 # units of beats per minute
18+
19+
# Calculate beats per second
20+
beatsPerSec = beatsPerMin / 60 # 1 minute / 60 seconds
21+
22+
# Calculate # of seconds per beat
23+
secPerBeat = 1/beatsPerSec
24+
25+
# Note division
26+
# 4 = whole, 2 = half, 1 = quarter, 0.5 = 8th, 0.25 = 16th
27+
noteDiv = 0.5
28+
timeSec = noteDiv * secPerBeat
29+
30+
# Convert to units of samples
31+
d = int(np.fix(timeSec * Fs)) # round to nearest integer sample
32+
33+
a = -0.75 # amplitude of delay branch
34+
35+
# Index each element of our signal to create the output
36+
N = len(x)
37+
y = np.zeros([N, 1])
38+
39+
for n in range(N):
40+
# When the sample number is less than the time delay
41+
# Avoid indexing negative sample number
42+
if n < d + 1:
43+
# output = input
44+
y[n] = x[n]
45+
46+
# Now add in the delayed signal
47+
else:
48+
# output = input + delayed version of output
49+
# reduce relative amplitude of delay to 3/4
50+
y[n] = x[n] + (-a) * y[n-d]
51+
52+
t = np.arange(0, N) * Ts
53+
54+
plt.plot(t, x, t, y)
55+
plt.xlabel('Time (sec.)')
56+
plt.ylabel('Amplitude')
57+
plt.title('Waveform')
58+
plt.show()
59+
60+
Audio(y, rate=Fs)

Ch. 11 - Echo Effects/echoSync.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# ECHOSYNC
2+
# This script demonstrates one example to create a feedforward,
3+
# tempo-synchronized echo effect.
4+
#
5+
# See also CONVERTTEMPOSAMPLES
6+
7+
import soundfile
8+
import numpy as np
9+
import matplotlib.pyplot as plt
10+
from IPython.display import Audio
11+
12+
# Import our audio file
13+
[x, Fs] = soundfile.read('sw20.wav')
14+
Ts = 1/Fs
15+
16+
# Known tempo of recording
17+
beatsPerMin = 102 # units of beats/minute
18+
19+
# Calculate beats fore second
20+
beatsPerSec = beatsPerMin / 60 # 1 minute/60 seconds
21+
22+
# Calculate # of seconds per beat
23+
secPerBeat = 1/beatsPerSec
24+
25+
# Note division
26+
# 4 = whole, 2 = half, 1 = quarter, 0.5 = 8th, 0.25 = 16th
27+
noteDiv = 0.5
28+
# Calculate delay time in seconds
29+
timeSec = noteDiv * secPerBeat
30+
31+
# Convert to units of samples
32+
d = int(np.fix(timeSec * Fs)) # round to nearest integer sample
33+
34+
b = 0.75 # amplitude of delay branch
35+
36+
# Total number of samples
37+
N = len(x)
38+
y = np.zeros([N, 1])
39+
40+
# Index each element of our signal to create the output
41+
for n in range(N):
42+
# When the sample number is less than the time delay
43+
# Avoid indexing a negative number
44+
if n < d + 1:
45+
# output = input
46+
y[n] = x[n]
47+
48+
# Now add in the delayed signal
49+
else:
50+
# output = input + delayed version of input
51+
# reduce relative amplitude of delay to 3/4
52+
echo = n - d
53+
y[n] = x[n] + b * x[echo]
54+
55+
t = np.arange(0, N) * Ts
56+
57+
plt.plot(t, x, t, y)
58+
plt.axis([0, 1, -1.1, 1.1])
59+
plt.xlabel('Time (sec.)')
60+
plt.ylabel('Amplitude')
61+
plt.title('Waveform')
62+
plt.show()
63+
64+
Audio(y, rate=Fs)

Ch. 11 - Echo Effects/impFIR.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# IMPFIR
2+
# This script demonstrates one example to measure the impulse response of an
3+
# FIR system.
4+
#
5+
# See also IMPIIR
6+
7+
import numpy as np
8+
import matplotlib.pyplot as plt
9+
import soundfile
10+
11+
Fs = 48000
12+
N = Fs * 2
13+
# Synthesize the impulse signal
14+
imp = np.zeros([N,1])
15+
imp[1] = 1 # Change the first sample = 1
16+
17+
d1 = int(0.5 * Fs) # 1/2 second delay
18+
b1 = 0.7 # Gain of first delay line
19+
20+
d2 = int(1.5 * Fs) # 3/2 second delay
21+
b2 = 0.5 # Gain of second delay line
22+
23+
# Zero-pad the beginning of the signal for indexing based on the maximum
24+
# delay time
25+
pad = np.zeros([d2, 1])
26+
impPad = np.concatenate((pad, imp))
27+
28+
out = np.zeros([N, 1])
29+
30+
# Index each element of our signal to create the output
31+
for n in range(N):
32+
index = n + d2
33+
out[n] = impPad[index] + b1 * impPad[index - d1] + b2 * impPad[index - d2]
34+
35+
t = np.arange(0, N) / Fs
36+
plt.subplot(1,2,1)
37+
plt.stem(t, imp) # Plot the impulse response
38+
plt.axis([-0.1, 2, -0.1, 1.1])
39+
plt.xlabel('Time (sec.)')
40+
plt.title('Input Impulse')
41+
plt.show()
42+
43+
plt.subplot(1,2,2)
44+
plt.stem(t, out) # Plot the impulse response
45+
plt.axis([-0.1, 2, -0.1, 1.1])
46+
plt.xlabel('Time (sec.)')
47+
plt.title('Output Impulse Response')
48+
plt.show()
49+
50+
soundfile.write('impResp.wav', out, Fs)

Ch. 11 - Echo Effects/impIIR.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# IMPIIR
2+
# This script demonstrates one example to approximate the impulse response
3+
# of an IIR system.
4+
#
5+
# See also IMPFIR
6+
7+
import numpy as np
8+
import matplotlib.pyplot as plt
9+
import soundfile
10+
11+
Fs = 48000
12+
Ts = 1/Fs
13+
N = Fs * 2 # Number of samples
14+
# Synthesize impulse signal
15+
imp = np.zeros([N, 1])
16+
imp[1] = 1 # Change the first sample = 1
17+
18+
out = np.zeros([N * 5, 1])
19+
20+
d1 = int(0.5 * Fs) # 1/2 second delay
21+
a1 = -0.7 # Gain of feedback delay line
22+
23+
# Index each element of our signal to create the output
24+
for n in range(d1):
25+
out[n] = imp[n] # Initially there is no delay
26+
27+
for n in np.arange(d1+1, Fs*2): # Then there is signal + delay
28+
out[n] = imp[n] + a1 * out[n - d1]
29+
30+
for n in np.arange(Fs*2+1, Fs*10): # Finally, there is only delay
31+
out[n] = a1 * out[n - d1] # After input finished
32+
33+
34+
t = np.arange(0, N) / Fs
35+
plt.subplot(1,2,1)
36+
plt.stem(t, imp) # Plot the impulse response
37+
plt.axis([-0.1, 2, -0.1, 1.1])
38+
plt.xlabel('Time (sec.)')
39+
plt.title('Input Impulse')
40+
plt.show()
41+
42+
t = np.arange(0, Fs * 10) * Ts
43+
plt.subplot(1,2,2)
44+
plt.stem(t, out) # Plot the impulse response
45+
plt.axis([-0.1, 10, -1.1, 1.1])
46+
plt.xlabel('Time (sec.)')
47+
plt.title('Output Impulse Response')
48+
plt.show()
49+
50+
# soundfile.write('impResp.wav', imp, Fs)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# REVERBCONV
2+
# This script demonstrates the process to create a stereo convolution reverb
3+
# by using a two-channel impulse response. This impulse response is based
4+
# on a measurement of a recording studio in Nashville, TN.
5+
6+
import soundfile
7+
import numpy as np
8+
import matplotlib.pyplot as plt
9+
from IPython.display import Audio
10+
11+
# Import sound file and IR measurement
12+
[x, Fs] = soundfile.read('AcGtr.wav') # Mono signal
13+
[h,_] = soundfile.read('reverbIR.wav') # Stereo IR
14+
15+
# Visualize one channel of the impulse response
16+
plt.plot(h[:, 0])
17+
plt.plot(h[:, 1])
18+
plt.show()
19+
20+
# Perform convolution
21+
yLeft = np.convolve(x, h[:,0])
22+
yRight = np.convolve(x, h[:,1])
23+
24+
y = [yLeft, yRight]
25+
26+
Audio(y, rate=Fs)

Ch. 17 - Amplitude Envelope Effects/Amplitude Envelope Effects.ipynb

Lines changed: 8 additions & 8 deletions
Large diffs are not rendered by default.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# ADSR
2+
# This function can be used to apply an ADSR envelope on to an input signal.
3+
#
4+
# Input Variables
5+
# attackTime: length of attack ramp in milliseconds
6+
# decayTime: length of decay ramp in milliseconds
7+
# sustainAmplitude: linear amplitude of sustain segment
8+
# releaseTime: length of release ramp in ms
9+
10+
import numpy as np
11+
12+
def adsr(x, Fs, attackTime, decayTime, sustainAmplitude, releaseTime):
13+
# Convert time inputs to seconds
14+
attackTimeSec = attackTime/1000
15+
decayTimeSec = decayTime/1000
16+
releaseTimeSec = releaseTime/1000
17+
18+
# Convert seconds to samples and determine sustain time
19+
a = int(np.round(attackTimeSec * Fs)) # Round each to an integer
20+
d = int(np.round(decayTimeSec * Fs)) # number of samples.
21+
r = int(np.round(releaseTimeSec * Fs))
22+
s = len(x) - (a + d + r) # determine length of sustain
23+
24+
# Create linearly spaced fades for A, D, and R. Create hold for S.
25+
aFade = np.linspace(0, 1, a)
26+
dFade = np.linspace(1, sustainAmplitude, d)
27+
sFade = sustainAmplitude * np.ones(s)
28+
rFade = np.linspace(sustainAmplitude, 0, r)
29+
30+
# Concatenates total ADSR envelope
31+
env = np.append(aFade, dFade)
32+
env = np.append(env, sFade)
33+
env = np.append(env, rFade)
34+
35+
# Applies ADSR shaping to x
36+
y = x * env
37+
38+
return y

0 commit comments

Comments
 (0)