Skip to content

Commit d73e85b

Browse files
committed
Chapter 17 added
1 parent 9ba82b2 commit d73e85b

26 files changed

Lines changed: 1131 additions & 209 deletions

.DS_Store

0 Bytes
Binary file not shown.

Additional Scripts/testing.py

Lines changed: 0 additions & 209 deletions
This file was deleted.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# APF
2+
# This function creates an all-pass filter by processing an individual
3+
# input sample and updating a delay buffer used in a loop to index each
4+
# sample in a signal.
5+
#
6+
# Input Variables
7+
# n: current sample number of the input signal
8+
# delay: samples of delay
9+
# gain: feedback gain (linear scale)
10+
# amp: amplitude of LFO modulation
11+
# rate: frequency of LFO modulation
12+
13+
import numpy as np
14+
15+
def apf(x, buffer, Fs, n, delay, gain, amp, rate):
16+
# Calculate time in seconds for the current sample
17+
t = n/Fs
18+
fracDelay = amp * np.sin(2 * np.pi * rate * t)
19+
intDelay = int(np.floor(fracDelay))
20+
frac = fracDelay - intDelay
21+
22+
# Determine indexes for circular buffer
23+
M = len(buffer)
24+
indexC = int(np.mod(n, M)) # Current index
25+
indexD = int(np.mod((n-delay+intDelay), M)) # Delay index
26+
indexF = int(np.mod((n-delay+intDelay+1), M)) # Fractional index
27+
28+
# Temp variable for output of delay buffer
29+
w = (1 - frac) * buffer[indexD] + frac * buffer[indexF]
30+
31+
# Temp variable used for the node after the input sum
32+
v = x + (-gain * w)
33+
34+
# Summation at output
35+
out = (gain * v) + w
36+
37+
# Store the current input to delay buffer
38+
buffer[indexC] = v
39+
40+
return out, buffer
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# APFEXAMPLE
2+
# This script uses an all-pass filter function applied to an acoustic
3+
# guitar recording.
4+
#
5+
# See also APF
6+
7+
import numpy as np
8+
import soundfile
9+
from apf import apf
10+
from IPython.display import Audio
11+
12+
x, Fs = soundfile.read('AcGtr.wav')
13+
14+
maxDelay = int(np.ceil(0.05 * Fs)) # maximum delay of 50ms
15+
buffer = np.zeros(maxDelay)
16+
17+
d = np.ceil(0.042 * Fs) # 42ms of delay
18+
g = 0.9
19+
20+
rate = 0.9 # Hz (frequency of LFO)
21+
amp = 6 # Range of +/- 6 samples for delay
22+
23+
# Initialize output signal
24+
N = len(x)
25+
out = np.zeros(N)
26+
27+
for n in range(N):
28+
# Use apf function
29+
out[n], buffer = apf(x[n], buffer, Fs, n, d, g, amp, rate)
30+
31+
Audio(out, rate=Fs)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# CROSSOVERFEEDBACK
2+
# This script implements two comb filters with crossover feedback.
3+
#
4+
# See also MODDELAY
5+
6+
import numpy as np
7+
import matplotlib.pyplot as plt
8+
from modDelay import modDelay
9+
from IPython.display import Audio
10+
11+
Fs = 48000
12+
x = np.append(1, np.zeros(int(Fs*0.5))) # Add zero-padding for reverb tail
13+
14+
# Max delay of 70ms
15+
maxDelay = int(np.ceil(0.07 * Fs))
16+
# Initialize all buffers
17+
buffer1 = np.zeros(maxDelay)
18+
buffer2 = np.zeros(maxDelay)
19+
20+
# Early reflections tapped delay line
21+
bufferER = np.zeros(maxDelay)
22+
23+
# Delay and gain parameters
24+
d1 = np.fix(0.0297 * Fs)
25+
g11 = -0.75
26+
g12 = -0.75
27+
d2 = np.fix(0.0419 * Fs)
28+
g21 = -0.75
29+
g22 = -0.75
30+
31+
# LFO parameters
32+
rate1 = 0.6
33+
amp1 = 3
34+
rate2 = 0.71
35+
amp2 = 3
36+
37+
# Initialize output signal
38+
N = len(x)
39+
out = np.zeros(N)
40+
41+
fb1 = 0
42+
fb2 = 0 # feedback holding variables
43+
44+
for n in range(N):
45+
# Combine input with feedback for respective delay lines
46+
xDL1 = x[n] + fb1
47+
xDL2 = x[n] + fb2
48+
49+
50+
# Two parallel delay lines
51+
outDL1, buffer1 = modDelay(xDL1, buffer1, Fs, n, d1, amp1, rate1)
52+
outDL2, buffer2 = modDelay(xDL2, buffer2, Fs, n, d2, amp2, rate2)
53+
54+
# Combine parallel paths
55+
out[n] = 0.5 * (outDL1 + outDL2)
56+
57+
# Calculate feedback (including crossover)
58+
fb1 = 0.5 * (g11 * outDL1 + g21 * outDL2)
59+
fb2 = 0.5 * (g12 * outDL2 + g22 * outDL2)
60+
61+
plt.plot(out)
62+
plt.show()
63+
64+
Audio(out, rate=Fs)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# EARLYREFLECTIONS
2+
# This function creates a tapped delay line to be used for the early
3+
# reflections of a reverb algorithm. THe delays and gains of the taps
4+
# are included in this function and were based on an IR measurement from a
5+
# recording studio in Nashville, TN.
6+
#
7+
# Also see MOORERREVERB
8+
9+
import numpy as np
10+
11+
def earlyReflections(x, buffer, Fs, n):
12+
13+
# Delay times converted from milliseconds
14+
delayTimes = [np.fix(0*Fs), np.fix(0.01277*Fs), np.fix(0.01283*Fs), np.fix(0.01293*Fs), np.fix(0.01333*Fs),
15+
np.fix(0.01566*Fs), np.fix(0.02404*Fs), np.fix(0.02679*Fs), np.fix(0.02731*Fs), np.fix(0.02737*Fs), np.fix(0.02914*Fs),
16+
np.fix(0.02920*Fs), np.fix(0.02981*Fs), np.fix(0.03389*Fs), np.fix(0.04518*Fs), np.fix(0.04522*Fs), np.fix(0.04527*Fs),
17+
np.fix(0.05452*Fs), np.fix(0.06958*Fs)]
18+
19+
numDelays = len(delayTimes)
20+
for delay in range(numDelays):
21+
delayTimes[delay] = int(delayTimes[delay])
22+
23+
# There must be a 'gain' for each of the 'delayTimes'
24+
gains = [1, 0.1526, -0.4097, 0.2984, 0.1553, 0.1442,
25+
-0.3124, -0.4176, -0.9391, 0.6926, -0.5787, 0.5782,
26+
0.4206, 0.3958, 0.3450, -0.5361, 0.417, 0.1948, 0.1548]
27+
28+
# Determine indexes for circular buffer
29+
M = len(buffer)
30+
indexC = np.mod(n, M) # current index
31+
buffer[indexC] = x
32+
33+
out = 0 # initialize the output to be used in loop
34+
35+
# Loop through all the taps
36+
for tap in range(len(delayTimes)):
37+
# Find the circular buffer index for the current tap
38+
indexTDL = np.mod(n-delayTimes[tap], M)
39+
40+
# 'Tap' the delay line and add current tap with output
41+
out = out + gains[tap] * buffer[indexTDL]
42+
43+
return out, buffer

0 commit comments

Comments
 (0)