├── LICENSE.txt
├── README.md
├── calculation.py
├── dut_test
├── dut_test.py
└── dut_test_reality.py
├── generation.py
├── ir_imitation.py
├── lin_sweep_kaiser_window_bandlimited_script5
├── lin_sweep_kaiser_window_bandlimited_script5.py
├── lin_sweep_kaiser_window_bandlimited_script5_1.py
└── merge_scripts.py
├── lin_sweep_kaiser_window_bandlimited_script6
├── lin_sweep_kaiser_window_bandlimited_script6.py
├── lin_sweep_kaiser_window_bandlimited_script6_1.py
└── merge_scripts.py
├── lin_sweep_kaiser_window_script1
├── lin_sweep_kaiser_window_script1.py
├── lin_sweep_kaiser_window_script1_1.py
└── merge_scripts.py
├── lin_sweep_kaiser_window_script2
├── lin_sweep_kaiser_window_script2.py
├── lin_sweep_kaiser_window_script2_1.py
└── merge_scripts.py
├── lin_sweep_kaiser_window_script3
├── lin_sweep_kaiser_window_script3.py
├── lin_sweep_kaiser_window_script3_1.py
└── merge_scripts.py
├── lin_sweep_kaiser_window_script4
├── lin_sweep_kaiser_window_script4.py
├── lin_sweep_kaiser_window_script4_1.py
└── merge_scripts.py
├── log_sweep_kaiser_window_bandlimited_script5
├── log_sweep_kaiser_window_bandlimited_script5.py
├── log_sweep_kaiser_window_bandlimited_script5_1.py
└── merge_scripts.py
├── log_sweep_kaiser_window_bandlimited_script6
├── log_sweep_kaiser_window_bandlimited_script6.py
├── log_sweep_kaiser_window_bandlimited_script6_1.py
└── merge_scripts.py
├── log_sweep_kaiser_window_script1
├── __pycache__
│ ├── log_sweep_kaiser_window_script1.cpython-34.pyc
│ ├── sweep_kaiser_window.cpython-34.pyc
│ └── sweep_kaiser_window_script1.cpython-34.pyc
├── log_sweep_kaiser_window_script1.py
├── log_sweep_kaiser_window_script1_1.py
└── merge_scripts.py
├── log_sweep_kaiser_window_script2
├── log_sweep_kaiser_window_script2.py
├── log_sweep_kaiser_window_script2_1.py
└── merge_scripts.py
├── log_sweep_kaiser_window_script3
├── log_sweep_kaiser_window_script3.py
├── log_sweep_kaiser_window_script3_1.py
└── merge_scripts.py
├── log_sweep_kaiser_window_script4
├── log_sweep_kaiser_window_script4.py
├── log_sweep_kaiser_window_script4_1.py
└── merge_scripts.py
├── log_sweep_rect_window
└── log_sweep_rect_window.py
├── measurement_chain.py
├── peak_to_noise_ratio
├── peak_to_noise_ratio.py
├── pnr_depends_on_averaging_length.py
└── pnr_depends_on_excitation_length.py
├── plotting.py
├── software_sweep.ipynb
├── sweep_akf_kaiser_window
├── lin_sweep_akf_window.py
└── log_sweep_akf_window.py
└── windows.py
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Franz Plocksties
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This repository deals with the generation of a simulation environment for room impulse response measurements.
2 | It contains a measuring chain which simulates parameters occurring in reality (microphone, preamp, DAC, ...).
3 | Here, we consider only linear time-invariant systems (LTI). The user can choose between different parameters (type
4 | of excitation signals, length of signal, type of windowing, intensity and type of noise, sampling frequency, ...) which excite the fictitous "Device Under Test" (DUT). Than the tool returns impulse response, frequency response, power spectral density and signal quality by mathematical functions (FFT, deconvolution, averaging, ...). Thus, results can
5 | be validated by known analytical LTI systems. The software environment will be programmed in Python3 by using packages
6 | for scientific computing, e.g. numpy.
7 |
--------------------------------------------------------------------------------
/calculation.py:
--------------------------------------------------------------------------------
1 | """Calculation functions."""
2 | from __future__ import division
3 | import numpy as np
4 | import plotting
5 | from scipy.signal import butter, freqz
6 |
7 |
8 | def deconv_process(excitation, system_response, fs):
9 | """Deconvolution.
10 |
11 | It is a necessity to zeropadd the excitation signal
12 | to avoid zircular artifacts, if the system response is longer
13 | than the excitation signal.
14 | """
15 | NFFT = _pow2(len(excitation) + len(system_response) - 1)
16 | excitation_f = np.fft.rfft(excitation, NFFT)
17 | return np.fft.irfft(np.fft.rfft(system_response, NFFT) / excitation_f)
18 |
19 |
20 | def pnr_db(peak, noise):
21 | """Calculating Signal-to-noise ratio.
22 |
23 | Parameters
24 | ----------
25 | signal : array_like
26 | Signal vector
27 | noise : array_like
28 | Noise vector
29 |
30 | Returns
31 | -------
32 | Return SNR in dB
33 | """
34 | return 10 * np.log10(peak**2 / _mean_power(noise))
35 |
36 |
37 | def _mean_power(signal):
38 | return np.mean(np.square(signal))
39 |
40 |
41 | def peak_to_noise_ratio(ir, noise_bound_begin, fs):
42 | peak = ir[0]
43 | noise = ir[noise_bound_begin:]
44 | return pnr_db(peak, noise)
45 |
46 |
47 | def _pow2(n):
48 | i = 1
49 | while i < n:
50 | i *= 2
51 | return i
52 |
53 |
54 | def butter_bandpass_regularisation(lower_bound, higher_bound, fs, NFFT, order):
55 | wl = lower_bound / (fs / 2)
56 | wh = higher_bound / (fs / 2)
57 | b, a = butter(order, [wl, wh], btype='bandpass')
58 | butter_w, butter_h = freqz(b, a, worN=NFFT, whole=True)
59 | return butter_h
60 |
61 |
62 | def butter_bandstop(lower_bound, higher_bound, fs, NFFT, order):
63 | wl = lower_bound / (fs / 2)
64 | wh = higher_bound / (fs / 2)
65 | b, a = butter(order, [wl, wh], btype='bandstop')
66 | butter_w, butter_h = freqz(b, a, worN=NFFT, whole=True)
67 | return butter_h
68 |
69 |
70 | def butter_lowpass(fc, fs, NFFT, order):
71 | wc = fc / (fs / 2)
72 | b, a = butter(order, wc, btype='lowpass')
73 | butter_w, butter_h = freqz(b, a, worN=NFFT, whole=True)
74 | return butter_h
75 |
76 |
77 | def awgn_noise(level, size=None, seed=1):
78 | scale = 10 ** (level / 20.)
79 | np.random.seed(seed)
80 | return np.random.normal(scale=scale, size=size)
81 |
82 |
83 | def vector_distance(transfer_function_ideal, transfer_function_deconv):
84 | return np.sum(
85 | np.abs((transfer_function_ideal - transfer_function_deconv))**2)
86 |
87 |
88 | def start_time_noise_floor(ir_noise_level, ir_db_decay, system_noise):
89 | m = ir_db_decay + np.abs(ir_noise_level)
90 | return (system_noise + np.abs(ir_noise_level))/m
91 |
92 |
93 | def estimation_function(excitation, system_response, fs):
94 | NFFT = _pow2(len(excitation) + len(system_response) - 1)
95 | excitation_f = np.fft.rfft(excitation, NFFT)
96 | system_response_f = np.fft.rfft(system_response, NFFT)
97 | Rxx = np.conjugate(excitation_f)*excitation_f
98 | Ryy = np.conjugate(system_response_f)*system_response_f
99 | Rxy = excitation_f*np.conjugate(system_response_f)
100 | Ryx = system_response_f*np.conjugate(excitation_f)
101 | H1 = Ryx / Rxx
102 | H2 = Ryy / Rxy
103 | return np.fft.irfft(H1), np.fft.irfft(H2)
104 |
--------------------------------------------------------------------------------
/dut_test/dut_test.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """Software-Test with a known IR.
4 | h[k] = dirac[k] + dirac[k-1050]
5 | Please note: For Frequency Response is scaling to 2 / len(signal)
6 | before FFT invalid
7 | """
8 |
9 | import sys
10 | sys.path.append('..')
11 |
12 | import matplotlib.pyplot as plt
13 | import numpy as np
14 | import generation
15 | import plotting
16 | import calculation
17 | import measurement_chain
18 | import ir_imitation
19 |
20 |
21 | # Parameters of the measuring system
22 |
23 | fs = 44100
24 |
25 | fstart = 1
26 | fstop = 22050
27 | pad = 7
28 |
29 |
30 | # Excitation signal
31 |
32 | excitation = np.zeros(44100)
33 | excitation[0] = 1
34 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
35 |
36 |
37 | system_response = measurement_chain.convolution(ir_imitation.diracs([0, 1050]))(excitation_zeropadded)
38 |
39 | h = calculation.deconv_process(excitation,
40 | system_response, fs)[:len(excitation)]
41 |
42 |
43 | # Plot impulse response
44 |
45 | plotting.plot_time(h)
46 | plt.xlim(-500, 10000)
47 | plt.xticks([0, 1050, 2000, 4000, 6000, 8000, 10000])
48 | plt.savefig('impulse_response.png')
49 | plt.close()
50 |
51 | # Plot frequency response
52 |
53 | plotting.plot_freq(h, fs, scale='db', title=' ')
54 | plt.xscale('log')
55 | plt.xlim(1, 23000)
56 | plt.savefig('frequency_response.png')
57 | plt.close()
58 |
59 | # Plot phase response
60 |
61 | plotting.plot_freq(h, fs, mode='phase', title=' ')
62 | plt.xscale('log')
63 | plt.savefig('phase_response.png')
64 | plt.close()
65 |
--------------------------------------------------------------------------------
/dut_test/dut_test_reality.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """Software-Test with a known IR in real-life conditions.
4 | h[k] = dirac[k] + dirac[k-1050]
5 | """
6 |
7 | import sys
8 | sys.path.append('..')
9 |
10 | import matplotlib.pyplot as plt
11 | import numpy as np
12 | import generation
13 | import plotting
14 | import calculation
15 | import measurement_chain
16 | import ir_imitation
17 |
18 |
19 | fs = 44100
20 |
21 | fstart = 1
22 | fstop = 22050
23 | pad = 7
24 |
25 |
26 | # Noise in measurement chain
27 |
28 | noise_level_db = -50.
29 | noise = measurement_chain.additive_noise(noise_level_db)
30 |
31 | # FIR-Filter-System
32 |
33 | dirac_system = measurement_chain.convolution(ir_imitation. diracs([0, 1050]))
34 |
35 | # Combinate system elements
36 |
37 | system = measurement_chain.chained(dirac_system, noise)
38 |
39 |
40 | excitation = np.zeros(44100)
41 | excitation[0] = 1
42 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
43 |
44 |
45 | system_response = system(excitation_zeropadded)
46 |
47 | h = calculation.deconv_process(excitation,
48 | system_response, fs)[:len(excitation)]
49 |
50 | # Plot impulse response
51 |
52 | plotting.plot_time(h, title='')
53 | plt.xlim(-1000, fs)
54 | plt.savefig('impulse_response_reality.png')
55 | plt.close()
56 |
57 | # Plot frequency response
58 |
59 | plotting.plot_freq(h, fs, scale='db', title='')
60 | plt.xscale('log')
61 | plt.savefig('frequency_response_reality.png')
62 | plt.close()
63 |
64 | # Plot phase response
65 |
66 | plotting.plot_freq(h, fs, mode='phase', title='')
67 | plt.xscale('log')
68 | plt.savefig('phase_response_reality.png')
69 | plt.close()
70 |
--------------------------------------------------------------------------------
/generation.py:
--------------------------------------------------------------------------------
1 | """Signal Generation."""
2 |
3 | import numpy as np
4 | import calculation
5 |
6 |
7 | def lin_sweep(fstart, fstop, duration, fs):
8 | """Generation of a linear sweep signal.
9 |
10 | Parameters
11 | ----------
12 | fstart : int
13 | Start frequency in Hz
14 | fstop : int
15 | Stop frequency in Hz
16 | duration : float
17 | Total length of signal in s
18 | fs : int
19 | Sampling frequency in Hz
20 |
21 | Returns
22 | -------
23 | array_like
24 | generated signal vector
25 |
26 | Note that the stop frequency must not be greater than half the
27 | sampling frequency (Nyquist-Shannon sampling theorem).
28 |
29 | """
30 | if fstop > fs / 2:
31 | raise ValueError("fstop must not be greater than fs/2")
32 | t = np.arange(0, duration, 1 / fs)
33 | excitation = np.sin(
34 | 2 * np.pi * ((fstop - fstart) /
35 | (2 * duration) * t ** 2 + fstart * t))
36 | # excitation = excitation - np.mean(excitation) # remove direct component
37 | return excitation
38 |
39 |
40 | def log_sweep(fstart, fstop, duration, fs):
41 | """Generation of a logarithmic sweep signal.
42 |
43 | Parameters
44 | ----------
45 | fstart : int
46 | Start frequency in Hz
47 | fstop : int
48 | Stop frequency
49 | duration : float
50 | Total length of signal in s
51 | fs : int
52 | Sampling frequency in Hz
53 |
54 | Returns
55 | -------
56 | array_like
57 | Generated signal vector
58 |
59 | Note that the stop frequency must not be greater than half the
60 | sampling frequency (Nyquist-Shannon sampling theorem).
61 |
62 | """
63 | if fstop > fs / 2:
64 | raise ValueError("fstop must not be greater than fs/2")
65 | t = np.arange(0, duration, 1 / fs)
66 | excitation = np.sin(2 * np.pi * duration *
67 | fstart / np.log(fstop / fstart) *
68 | (np.exp(t / duration * np.log(fstop / fstart)) - 1))
69 | # excitation = excitation - np.mean(excitation) # remove direct component
70 | return excitation
71 |
72 |
73 | def noise(noise_level_db, duration, fs, seed=1):
74 | return calculation.awgn_noise(noise_level_db, duration * fs, seed)
75 |
76 |
77 | def zero_padding(signal, appending_time, fs):
78 | """Zeropadding a signal."""
79 | number_of_zeros = appending_time * fs
80 | return np.concatenate((signal, np.zeros(number_of_zeros)))
81 |
--------------------------------------------------------------------------------
/ir_imitation.py:
--------------------------------------------------------------------------------
1 | """ Imitate a impulse response."""
2 | import numpy as np
3 | import measurement_chain
4 | import calculation
5 |
6 |
7 | def exponential_decay(duration_seconds,
8 | db_decay,
9 | noise_level_db,
10 | fs,
11 | seed=1):
12 | """ Imitate real IR.
13 | duration_seconds : IR duration
14 | db_decay : dB / sec
15 | noise_level: dB
16 |
17 | """
18 | t = np.arange(0, duration_seconds, 1 / fs)
19 | noise = calculation.awgn_noise(noise_level_db, duration_seconds * fs, seed)
20 | decay = 10 ** ((noise_level_db + db_decay) / 20)
21 | noise_level = 10 ** (noise_level_db / 20)
22 | lifetime = -1 / (np.log(decay / noise_level))
23 | exponential_fading_noise = noise * np.exp(-t / lifetime)
24 | exponential_fading_noise[0] = 1
25 | return exponential_fading_noise
26 |
27 |
28 | def diracs(array):
29 | """Dirac-Array.
30 |
31 | """
32 | a = np.asarray(array)
33 | y = np.zeros(a.max() + 1)
34 | y[a] = 1
35 | return y
36 |
37 |
38 | def bandstop(lower_bound, higher_bound, fs, order):
39 | b, a = measurement_chain._butter_bandstop(lower_bound,
40 | higher_bound,
41 | fs, order)
42 | return b, a
43 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_bandlimited_script5/lin_sweep_kaiser_window_bandlimited_script5.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of lin. bandlimited sweep signals when using a
4 | Kaiser Window by fixing beta (=2) and fade_out (=0).
5 | fstart = 100 Hz
6 | fstop = 5000 Hz
7 | Deconvolution: Windowed
8 |
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import ir_imitation
19 | import generation
20 | import matplotlib.pyplot as plt
21 | import windows
22 | from scipy.signal import lfilter, fftconvolve
23 | import numpy as np
24 |
25 |
26 | # Parameters of the measuring system
27 |
28 | fs = 44100
29 |
30 | fstart = 100
31 | fstop = 5000
32 | duration = 1
33 | pad = 4
34 |
35 | # Generate excitation signal
36 |
37 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
38 | N = len(excitation)
39 |
40 |
41 | # Noise in measurement chain
42 |
43 | noise_level_db = -30
44 | noise = measurement_chain.additive_noise(noise_level_db)
45 |
46 | # FIR-Filter-System
47 |
48 |
49 | dirac_system = measurement_chain.convolution([1.0])
50 |
51 | # Combinate system elements
52 |
53 | system = measurement_chain.chained(dirac_system, noise)
54 |
55 | # Lists
56 | beta = 7
57 | fade_in_list = np.arange(0, 1001, 1)
58 | fade_out = 0
59 |
60 |
61 | # Spectrum of dirac for reference
62 |
63 | dirac = np.zeros(pad * fs)
64 | dirac[0] = 1
65 | dirac_f = np.fft.rfft(dirac)
66 |
67 |
68 | def get_results(fade_in):
69 | excitation_windowed = excitation * windows.window_kaiser(N,
70 | fade_in,
71 | fade_out,
72 | fs, beta)
73 | excitation_windowed_zeropadded = generation.zero_padding(
74 | excitation_windowed, pad, fs)
75 | system_response = system(excitation_windowed_zeropadded)
76 | ir = calculation.deconv_process(excitation_windowed_zeropadded,
77 | system_response,
78 | fs)
79 | return ir
80 |
81 | with open("lin_sweep_kaiser_window_bandlimited_script5.txt", "w") as f:
82 | for fade_in in fade_in_list:
83 | ir = get_results(fade_in)
84 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
85 | spectrum_distance = calculation.vector_distance(
86 | dirac_f, np.fft.rfft(ir[:pad * fs]))
87 | f.write(
88 | str(fade_in) + " " + str(pnr) +
89 | " " + str(spectrum_distance) + " \n")
90 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_bandlimited_script5/lin_sweep_kaiser_window_bandlimited_script5_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of lin. bandlimited sweep signals when using a
4 | Kaiser Window by fixing beta (=2) and fade_out (=0).
5 | fstart = 100 Hz
6 | fstop = 5000 Hz
7 | Deconvolution: Unwindowed
8 |
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import matplotlib.pyplot as plt
20 | import windows
21 | from scipy.signal import lfilter
22 | import numpy as np
23 |
24 |
25 | # Parameters of the measuring system
26 |
27 | fs = 44100
28 |
29 | fstart = 100
30 | fstop = 5000
31 | duration = 1
32 | pad = 4
33 |
34 | # Generate excitation signal
35 |
36 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
37 | N = len(excitation)
38 |
39 |
40 | # Noise in measurement chain
41 |
42 | noise_level_db = -30
43 | noise = measurement_chain.additive_noise(noise_level_db)
44 |
45 | # FIR-Filter-System
46 |
47 | dirac_system = measurement_chain.convolution([1.0])
48 |
49 | # Combinate system elements
50 |
51 | system = measurement_chain.chained(dirac_system, noise)
52 |
53 | # Spectrum of dirac for reference
54 |
55 | dirac = np.zeros(pad * fs)
56 | dirac[0] = 1
57 | dirac_f = np.fft.rfft(dirac)
58 |
59 | # Lists
60 | beta = 7
61 | fade_in_list = np.arange(0, 1001, 1)
62 | fade_out = 0
63 |
64 |
65 | def get_results(fade_in):
66 | excitation_windowed = excitation * windows.window_kaiser(N,
67 | fade_in,
68 | fade_out,
69 | fs, beta)
70 | excitation_windowed_zeropadded = generation.zero_padding(
71 | excitation_windowed, pad, fs)
72 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
73 | system_response = system(excitation_windowed_zeropadded)
74 | ir = calculation.deconv_process(excitation_zeropadded,
75 | system_response,
76 | fs)
77 | return ir
78 |
79 |
80 | with open("lin_sweep_kaiser_window_bandlimited_script5_1.txt", "w") as f:
81 | for fade_in in fade_in_list:
82 | ir = get_results(fade_in)
83 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
84 | spectrum_distance = calculation.vector_distance(
85 | dirac_f, np.fft.rfft(ir[:pad * fs]))
86 | f.write(
87 | str(fade_in) + " " + str(pnr) +
88 | " " + str(spectrum_distance) + " \n")
89 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_bandlimited_script5/merge_scripts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """ Script to merge scripts"""
3 |
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 | script5 = np.genfromtxt('lin_sweep_kaiser_window_bandlimited_script5.txt')
8 |
9 | script5_1 = np.genfromtxt('lin_sweep_kaiser_window_bandlimited_script5_1.txt')
10 |
11 | fade_in_list = script5[:, 0]
12 |
13 | # Script5
14 |
15 | pnr_list = script5[:, 1]
16 | spectrum_distance_list = script5[:, 2]
17 |
18 | # Script5_1 (unwindowed deconvolution)
19 |
20 | pnr_unwindowed_deconvolution_list = script5_1[:, 1]
21 | spectrum_distance_unwindowed_deconvolution_list = script5_1[:, 2]
22 |
23 |
24 | plt.plot(fade_in_list, pnr_list, label='Deconvolution: Excitation windowed')
25 |
26 | plt.plot(
27 | fade_in_list,
28 | pnr_unwindowed_deconvolution_list,
29 | label='Deconvolution: Excitation unwindowed')
30 | plt.grid()
31 | plt.title('Peak to noise ratio depending on Fade in')
32 | plt.xlabel('Fade in / ms')
33 | plt.ylabel('Peak to noise ratio / dB')
34 | plt.ticklabel_format(useOffset=False)
35 | plt.legend(loc='lower left')
36 | plt.xlim([-10, 1000])
37 | plt.savefig('pnr.png')
38 | plt.close()
39 |
40 |
41 | NFFT_dirac = 88201
42 | max_measurement = 5974410.59739
43 |
44 | plt.plot(fade_in_list, -10 * np.log10(1 / NFFT_dirac *
45 | np.asarray(spectrum_distance_list) / max_measurement), label='Deconvolution: Excitation windowed')
46 |
47 | plt.plot(fade_in_list,
48 | -10 * np.log10(1 / NFFT_dirac * np.asarray(spectrum_distance_unwindowed_deconvolution_list) /
49 | max_measurement), label='Deconvolution: Excitation unwindowed')
50 |
51 |
52 | plt.grid()
53 | plt.title('Spectrum Distance depending on Fade in')
54 | plt.xlabel('Fade in / ms')
55 | plt.ylabel('(Spectrum Distance / max(Spectrum Distance)) / dB')
56 | plt.ticklabel_format(useOffset=False)
57 | plt.legend(loc='lower right')
58 | plt.xlim([-10, 1000])
59 | plt.savefig('spectral_distance.png')
60 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_bandlimited_script6/lin_sweep_kaiser_window_bandlimited_script6.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of bandlimited lin. sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_in (=0).
5 | fstart = 100 Hz
6 | fstop = 5000 Hz
7 | Deconvolution: Windowed
8 |
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import matplotlib.pyplot as plt
20 | import windows
21 | from scipy.signal import lfilter, fftconvolve
22 | import numpy as np
23 |
24 |
25 | # Parameters of the measuring system
26 |
27 | fs = 44100
28 |
29 | fstart = 100
30 | fstop = 5000
31 | duration = 1
32 | pad = 4
33 |
34 | # Generate excitation signal
35 |
36 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
37 | N = len(excitation)
38 |
39 |
40 | # Noise in measurement chain
41 |
42 | noise_level_db = -30.
43 | noise = measurement_chain.additive_noise(noise_level_db)
44 |
45 | # FIR-Filter-System
46 |
47 | dirac_system = measurement_chain.convolution([1.0])
48 |
49 | # Combinate system elements
50 |
51 | system = measurement_chain.chained(dirac_system, noise)
52 |
53 | # Lists
54 | beta = 7
55 | fade_in = 0
56 | fade_out_list = np.arange(0, 1001, 1)
57 |
58 | # Spectrum of dirac for reference
59 |
60 | dirac = np.zeros(pad * fs)
61 | dirac[0] = 1
62 | dirac_f = np.fft.rfft(dirac)
63 |
64 |
65 | def get_results(fade_out):
66 | excitation_windowed = excitation * windows.window_kaiser(N,
67 | fade_in,
68 | fade_out,
69 | fs, beta)
70 | excitation_windowed_zeropadded = generation.zero_padding(
71 | excitation_windowed, pad, fs)
72 | system_response = system(excitation_windowed_zeropadded)
73 | ir = calculation.deconv_process(excitation_windowed_zeropadded,
74 | system_response,
75 | fs)
76 | return ir
77 |
78 |
79 | with open("lin_sweep_kaiser_window_bandlimited_script6.txt", "w") as f:
80 | for fade_out in fade_out_list:
81 | ir = get_results(fade_out)
82 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
83 | spectrum_distance = calculation.vector_distance(
84 | dirac_f, np.fft.rfft(ir[:pad * fs]))
85 | f.write(
86 | str(fade_out) + " " + str(pnr) +
87 | " " + str(spectrum_distance) + " \n")
88 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_bandlimited_script6/lin_sweep_kaiser_window_bandlimited_script6_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of lin. sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_in (=0).
5 | fstart = 100 Hz
6 | fstop = 5000 Hz
7 | Deconvolution: Unwindowed
8 | """
9 |
10 |
11 | import sys
12 | sys.path.append('..')
13 |
14 | import measurement_chain
15 | import plotting
16 | import calculation
17 | import generation
18 | import matplotlib.pyplot as plt
19 | import windows
20 | from scipy.signal import lfilter
21 | import numpy as np
22 |
23 |
24 | # Parameters of the measuring system
25 |
26 | fs = 44100
27 |
28 | fstart = 100
29 | fstop = 5000
30 | duration = 1
31 | pad = 4
32 |
33 | # Generate excitation signal
34 |
35 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
36 | N = len(excitation)
37 |
38 | # Noise in measurement chain
39 |
40 | noise_level_db = -30.
41 | noise = measurement_chain.additive_noise(noise_level_db)
42 |
43 | # FIR-Filter-System
44 |
45 | dirac_system = measurement_chain.convolution([1.0])
46 |
47 | # Combinate system elements
48 |
49 | system = measurement_chain.chained(dirac_system, noise)
50 |
51 | # Lists
52 | beta = 7
53 | fade_in = 0
54 | fade_out_list = np.arange(0, 1001, 1)
55 |
56 | # Spectrum of dirac for reference
57 |
58 | dirac = np.zeros(pad * fs)
59 | dirac[0] = 1
60 | dirac_f = np.fft.rfft(dirac)
61 |
62 |
63 | def get_results(fade_out):
64 | excitation_windowed = excitation * windows.window_kaiser(N,
65 | fade_in,
66 | fade_out,
67 | fs, beta)
68 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
69 | excitation_windowed_zeropadded = generation.zero_padding(
70 | excitation_windowed, pad, fs)
71 | system_response = system(excitation_windowed_zeropadded)
72 | ir = calculation.deconv_process(excitation_zeropadded,
73 | system_response,
74 | fs)
75 | return ir
76 |
77 |
78 | with open("lin_sweep_kaiser_window_bandlimited_script6_1.txt", "w") as f:
79 | for fade_out in fade_out_list:
80 | ir = get_results(fade_out)
81 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
82 | spectrum_distance = calculation.vector_distance(
83 | dirac_f, np.fft.rfft(ir[:pad * fs]))
84 | f.write(
85 | str(fade_out) + " " + str(pnr) +
86 | " " + str(spectrum_distance) + " \n")
87 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_bandlimited_script6/merge_scripts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """ Script to merge scripts"""
3 |
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 | script6 = np.genfromtxt('lin_sweep_kaiser_window_bandlimited_script6.txt')
8 |
9 | script6_1 = np.genfromtxt('lin_sweep_kaiser_window_bandlimited_script6_1.txt')
10 |
11 | fade_out_list = script6[:, 0]
12 |
13 | # Script6
14 |
15 | pnr_list = script6[:, 1]
16 | spectrum_distance_list = script6[:, 2]
17 |
18 | # Script6_1 (unwindowed deconvolution)
19 |
20 | pnr_unwindowed_deconvolution_list = script6_1[:, 1]
21 | spectrum_distance_unwindowed_deconvolution_list = script6_1[:, 2]
22 |
23 |
24 | plt.plot(fade_out_list, pnr_list, label='Deconvolution: Excitation windowed')
25 |
26 | plt.plot(
27 | fade_out_list,
28 | pnr_unwindowed_deconvolution_list,
29 | label='Deconvolution: Excitation unwindowed')
30 | plt.grid()
31 | plt.title('Peak to noise ratio depending on Fade out')
32 | plt.xlabel('Fade out / ms')
33 | plt.ylabel('Peak to noise ratio / dB')
34 | plt.ticklabel_format(useOffset=False)
35 | plt.legend(loc='upper right')
36 | plt.xlim([-10, 1000])
37 | plt.savefig('pnr.png')
38 | plt.close()
39 |
40 | NFFT_dirac = 88201
41 | max_measurement = 5974410.59739
42 |
43 | plt.plot(fade_out_list, -10 * np.log10(1 / NFFT_dirac *
44 | np.asarray(spectrum_distance_list) / max_measurement), label='Deconvolution: Excitation windowed')
45 |
46 | plt.plot(fade_out_list,
47 | -10 * np.log10(1 / NFFT_dirac * np.asarray(spectrum_distance_unwindowed_deconvolution_list) /
48 | max_measurement), label='Deconvolution: Excitation unwindowed')
49 |
50 |
51 | plt.grid()
52 | plt.title('Spectrum Distance depending on Fade in')
53 | plt.xlabel('Fade out / ms')
54 | plt.ylabel('(Spectrum Distance / max(Spectrum Distance)) / dB')
55 | plt.ticklabel_format(useOffset=False)
56 | plt.legend(loc='center right')
57 | plt.xlim([-10, 1000])
58 | plt.savefig('spectral_distance.png')
59 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_script1/lin_sweep_kaiser_window_script1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of lin sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_out (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | Deconvolution: Windowed
8 |
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import ir_imitation
19 | import generation
20 | import matplotlib.pyplot as plt
21 | import windows
22 | from scipy.signal import lfilter, fftconvolve
23 | import numpy as np
24 |
25 |
26 | # Parameters of the measuring system
27 |
28 | fs = 44100
29 |
30 | fstart = 1
31 | fstop = 22050
32 | duration = 1
33 | pad = 4
34 |
35 | # Generate excitation signal
36 |
37 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
38 | N = len(excitation)
39 |
40 |
41 | # Noise in measurement chain
42 |
43 | noise_level_db = -30
44 | noise = measurement_chain.additive_noise(noise_level_db)
45 |
46 | # FIR-Filter-System
47 |
48 |
49 | dirac_system = measurement_chain.convolution([1.0])
50 |
51 | # Combinate system elements
52 |
53 | system = measurement_chain.chained(dirac_system, noise)
54 |
55 | # Lists
56 | beta = 7
57 | fade_in_list = np.arange(0, 1001, 1)
58 | fade_out = 0
59 |
60 |
61 | # Spectrum of dirac for reference
62 |
63 | dirac = np.zeros(pad * fs)
64 | dirac[0] = 1
65 | dirac_f = np.fft.rfft(dirac)
66 |
67 |
68 | def get_results(fade_in):
69 | excitation_windowed = excitation * windows.window_kaiser(N,
70 | fade_in,
71 | fade_out,
72 | fs, beta)
73 | excitation_windowed_zeropadded = generation.zero_padding(
74 | excitation_windowed, pad, fs)
75 | system_response = system(excitation_windowed_zeropadded)
76 | ir = calculation.deconv_process(excitation_windowed_zeropadded,
77 | system_response,
78 | fs)
79 | return ir
80 |
81 |
82 | with open("lin_sweep_kaiser_window_script1.txt", "w") as f:
83 | for fade_in in fade_in_list:
84 | ir = get_results(fade_in)
85 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
86 | spectrum_distance = calculation.vector_distance(
87 | dirac_f, np.fft.rfft(ir[:pad * fs]))
88 | f.write(
89 | str(fade_in) + " " + str(pnr) +
90 | " " + str(spectrum_distance) + " \n")
91 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_script1/lin_sweep_kaiser_window_script1_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of lin sweep signals when using a
4 | Kaiser Window by fixing beta (=2) and fade_out (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | Deconvolution: Unwindowed
8 |
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import matplotlib.pyplot as plt
20 | import windows
21 | from scipy.signal import lfilter
22 | import numpy as np
23 |
24 |
25 | # Parameters of the measuring system
26 |
27 | fs = 44100
28 |
29 | fstart = 1
30 | fstop = 22050
31 | duration = 1
32 | pad = 4
33 |
34 | # Generate excitation signal
35 |
36 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
37 | N = len(excitation)
38 |
39 |
40 | # Noise in measurement chain
41 |
42 | noise_level_db = -30
43 | noise = measurement_chain.additive_noise(noise_level_db)
44 |
45 | # FIR-Filter-System
46 |
47 | dirac_system = measurement_chain.convolution([1.0])
48 |
49 | # Combinate system elements
50 |
51 | system = measurement_chain.chained(dirac_system, noise)
52 |
53 | # Spectrum of dirac for reference
54 |
55 | dirac = np.zeros(pad * fs)
56 | dirac[0] = 1
57 | dirac_f = np.fft.rfft(dirac)
58 |
59 | # Lists
60 | beta = 7
61 | fade_in_list = np.arange(0, 1001, 1)
62 | fade_out = 0
63 |
64 |
65 | def get_results(fade_in):
66 | excitation_windowed = excitation * windows.window_kaiser(N,
67 | fade_in,
68 | fade_out,
69 | fs, beta)
70 | excitation_windowed_zeropadded = generation.zero_padding(
71 | excitation_windowed, pad, fs)
72 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
73 | system_response = system(excitation_windowed_zeropadded)
74 | ir = calculation.deconv_process(excitation_zeropadded,
75 | system_response,
76 | fs)
77 | return ir
78 |
79 |
80 | with open("lin_sweep_kaiser_window_script1_1.txt", "w") as f:
81 | for fade_in in fade_in_list:
82 | ir = get_results(fade_in)
83 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
84 | spectrum_distance = calculation.vector_distance(
85 | dirac_f, np.fft.rfft(ir[:pad * fs]))
86 | f.write(
87 | str(fade_in) + " " + str(pnr) +
88 | " " + str(spectrum_distance) + " \n")
89 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_script1/merge_scripts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """ Script to merge scripts"""
3 |
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 | script1 = np.genfromtxt('lin_sweep_kaiser_window_script1.txt')
8 |
9 | script1_1 = np.genfromtxt('lin_sweep_kaiser_window_script1_1.txt')
10 |
11 | fade_in_list = script1[:, 0]
12 |
13 | # Script1
14 |
15 | pnr_list = script1[:, 1]
16 | spectrum_distance_list = script1[:, 2]
17 |
18 | # Script1_1 (unwindowed deconvolution)
19 |
20 | pnr_unwindowed_deconvolution_list = script1_1[:, 1]
21 | spectrum_distance_unwindowed_deconvolution_list = script1_1[:, 2]
22 |
23 |
24 | plt.plot(fade_in_list, pnr_list, label='Deconvolution: Excitation windowed')
25 |
26 | plt.plot(
27 | fade_in_list,
28 | pnr_unwindowed_deconvolution_list,
29 | label='Deconvolution: Excitation unwindowed')
30 | plt.grid()
31 | plt.title('Peak to noise ratio depending on Fade in')
32 | plt.xlabel('Fade in / ms')
33 | plt.ylabel('Peak to noise ratio / dB')
34 | plt.ticklabel_format(useOffset=False)
35 | plt.legend(loc='upper right')
36 | plt.xlim([-10, 1000])
37 | plt.savefig('pnr.png')
38 | plt.close()
39 |
40 | NFFT_dirac = 88201
41 | max_measurement = 6.79601317575
42 |
43 | plt.plot(fade_in_list, -10 * np.log10(1 / NFFT_dirac *
44 | np.asarray(spectrum_distance_list) / max_measurement), label='Deconvolution: Excitation windowed')
45 |
46 | plt.plot(fade_in_list,
47 | -10 * np.log10(1 / NFFT_dirac * np.asarray(spectrum_distance_unwindowed_deconvolution_list) /
48 | max_measurement), label='Deconvolution: Excitation unwindowed')
49 |
50 |
51 | plt.grid()
52 | plt.title('Spectrum Distance depending on Fade in')
53 | plt.xlabel('Fade in / ms')
54 | plt.ylabel('(Spectrum Distance / max(Spectrum Distance)) / dB')
55 | plt.ticklabel_format(useOffset=False)
56 | plt.legend(loc='upper right')
57 | plt.savefig('spectral_distance.png')
58 |
59 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_script2/lin_sweep_kaiser_window_script2.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of lin sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_in (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | Deconvolution: Windowed
8 |
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import matplotlib.pyplot as plt
20 | import windows
21 | from scipy.signal import lfilter, fftconvolve
22 | import numpy as np
23 |
24 |
25 | # Parameters of the measuring system
26 |
27 | fs = 44100
28 |
29 | fstart = 1
30 | fstop = 22050
31 | duration = 1
32 | pad = 4
33 |
34 | # Generate excitation signal
35 |
36 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
37 | N = len(excitation)
38 |
39 |
40 | # Noise in measurement chain
41 |
42 | noise_level_db = -30.
43 | noise = measurement_chain.additive_noise(noise_level_db)
44 |
45 | # FIR-Filter-System
46 |
47 | dirac_system = measurement_chain.convolution([1.0])
48 |
49 | # Combinate system elements
50 |
51 | system = measurement_chain.chained(dirac_system, noise)
52 |
53 | # Lists
54 | beta = 7
55 | fade_in = 0
56 | fade_out_list = np.arange(0, 1001, 1)
57 |
58 | # Spectrum of dirac for reference
59 |
60 | dirac = np.zeros(pad * fs)
61 | dirac[0] = 1
62 | dirac_f = np.fft.rfft(dirac)
63 |
64 |
65 | def get_results(fade_out):
66 | excitation_windowed = excitation * windows.window_kaiser(N,
67 | fade_in,
68 | fade_out,
69 | fs, beta)
70 | excitation_windowed_zeropadded = generation.zero_padding(
71 | excitation_windowed, pad, fs)
72 | system_response = system(excitation_windowed_zeropadded)
73 | ir = calculation.deconv_process(excitation_windowed_zeropadded,
74 | system_response,
75 | fs)
76 | return ir
77 |
78 |
79 | with open("lin_sweep_kaiser_window_script2.txt", "w") as f:
80 | for fade_out in fade_out_list:
81 | ir = get_results(fade_out)
82 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
83 | spectrum_distance = calculation.vector_distance(
84 | dirac_f, np.fft.rfft(ir[:pad * fs]))
85 | f.write(
86 | str(fade_out) + " " + str(pnr)
87 | + " " + str(spectrum_distance) + " \n")
88 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_script2/lin_sweep_kaiser_window_script2_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of lin sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_in (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | Deconvolution: Unwindowed
8 |
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import matplotlib.pyplot as plt
20 | import windows
21 | from scipy.signal import lfilter
22 | import numpy as np
23 |
24 |
25 | # Parameters of the measuring system
26 |
27 | fs = 44100
28 |
29 | fstart = 1
30 | fstop = 22050
31 | duration = 1
32 | pad = 4
33 |
34 | # Generate excitation signal
35 |
36 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
37 | N = len(excitation)
38 |
39 | # Noise in measurement chain
40 |
41 | noise_level_db = -30.
42 | noise = measurement_chain.additive_noise(noise_level_db)
43 |
44 | # FIR-Filter-System
45 |
46 | dirac_system = measurement_chain.convolution([1.0])
47 |
48 | # Combinate system elements
49 |
50 | system = measurement_chain.chained(dirac_system, noise)
51 |
52 | # Lists
53 | beta = 7
54 | fade_in = 0
55 | fade_out_list = np.arange(0, 1001, 1)
56 |
57 | # Spectrum of dirac for reference
58 |
59 | dirac = np.zeros(pad * fs)
60 | dirac[0] = 1
61 | dirac_f = np.fft.rfft(dirac)
62 |
63 |
64 | def get_results(fade_out):
65 | excitation_windowed = excitation * windows.window_kaiser(N,
66 | fade_in,
67 | fade_out,
68 | fs, beta)
69 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
70 | excitation_windowed_zeropadded = generation.zero_padding(
71 | excitation_windowed, pad, fs)
72 | system_response = system(excitation_windowed_zeropadded)
73 | ir = calculation.deconv_process(excitation_zeropadded,
74 | system_response,
75 | fs)
76 | return ir
77 |
78 |
79 | with open("lin_sweep_kaiser_window_script2_1.txt", "w") as f:
80 | for fade_out in fade_out_list:
81 | ir = get_results(fade_out)
82 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
83 | spectrum_distance = calculation.vector_distance(
84 | dirac_f, np.fft.rfft(ir[:pad * fs]))
85 | f.write(
86 | str(fade_out) + " " + str(pnr) +
87 | " " + str(spectrum_distance) + " \n")
88 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_script2/merge_scripts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """ Script to merge scripts"""
3 |
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 | script2 = np.genfromtxt(
8 | 'lin_sweep_kaiser_window_script2.txt')
9 |
10 | script2_1 = np.genfromtxt(
11 | 'lin_sweep_kaiser_window_script2_1.txt')
12 |
13 | fade_out_list = script2[:, 0]
14 |
15 | # Script2
16 |
17 | pnr_list = script2[:, 1]
18 | spectrum_distance_list = script2[:, 2]
19 |
20 | # Script2_1 (unwindowed deconvolution)
21 |
22 | pnr_unwindowed_deconvolution_list = script2_1[:, 1]
23 | spectrum_distance_unwindowed_deconvolution_list = script2_1[:, 2]
24 |
25 |
26 | plt.plot(fade_out_list, pnr_list, label='Deconvolution: Excitation windowed')
27 |
28 | plt.plot(
29 | fade_out_list,
30 | pnr_unwindowed_deconvolution_list,
31 | label='Deconvolution: Excitation unwindowed')
32 | plt.grid()
33 | plt.title('Peak to noise ratio depending on Fade out')
34 | plt.xlabel('Fade out / ms')
35 | plt.ylabel('Peak to noise ratio / dB')
36 | plt.ticklabel_format(useOffset=False)
37 | plt.legend(loc='upper right')
38 | plt.xlim([-10, 1000])
39 | plt.savefig('pnr.png')
40 | plt.close()
41 |
42 |
43 | NFFT_dirac = 88201
44 | max_measurement = 6.79601317575
45 |
46 | plt.plot(fade_out_list, -10 * np.log10(1 / NFFT_dirac *
47 | np.asarray(spectrum_distance_list) / max_measurement), label='Deconvolution: Excitation windowed')
48 |
49 | plt.plot(fade_out_list,
50 | -10 * np.log10(1 / NFFT_dirac * np.asarray(spectrum_distance_unwindowed_deconvolution_list) /
51 | max_measurement), label='Deconvolution: Excitation unwindowed')
52 |
53 |
54 | plt.grid()
55 | plt.title('Spectrum Distance depending on Fade in')
56 | plt.xlabel('Fade out / ms')
57 | plt.ylabel('(Spectrum Distance / max(Spectrum Distance)) / dB')
58 | plt.ticklabel_format(useOffset=False)
59 | plt.legend(loc='upper right')
60 | plt.savefig('spectral_distance.png')
61 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_script3/lin_sweep_kaiser_window_script3.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of lin. sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_out (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | FIR-Filter: Bandstop
8 | Deconvolution: Unwindowed Excitation
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import ir_imitation
20 | import matplotlib.pyplot as plt
21 | import windows
22 | from scipy.signal import lfilter
23 | import numpy as np
24 |
25 |
26 | # Parameters of the measuring system
27 |
28 | fs = 44100
29 |
30 | fstart = 1
31 | fstop = 22050
32 | duration = 1
33 | pad = 4
34 |
35 | # Generate excitation signal
36 |
37 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
38 | N = len(excitation)
39 |
40 |
41 | # Noise in measurement chain
42 |
43 | awgn = -30
44 | noise_system = measurement_chain.additive_noise(awgn)
45 |
46 | # FIR-Filter-System
47 |
48 | f_low = 5000
49 | f_high = 6000
50 | order = 2
51 |
52 | bandstop_system = measurement_chain.bandstop(f_low, f_high, fs, order)
53 |
54 |
55 | # Combinate system elements
56 |
57 | system = measurement_chain.chained(bandstop_system, noise_system)
58 |
59 | # Lists
60 | beta = 7
61 | fade_in_list = np.arange(0, 1001, 1)
62 | fade_out = 0
63 | t_noise = 0.004
64 |
65 | # Spectrum of bandstop for reference
66 |
67 | bandstop_f = calculation.butter_bandstop(f_low, f_high, fs, N * 2 + 1, order)
68 |
69 |
70 | def get_results(fade_in):
71 | excitation_windowed = excitation * windows.window_kaiser(N,
72 | fade_in,
73 | fade_out,
74 | fs, beta)
75 | excitation_windowed_zeropadded = generation.zero_padding(
76 | excitation_windowed, pad, fs)
77 | system_response = system(excitation_windowed_zeropadded)
78 | ir = calculation.deconv_process(excitation_windowed_zeropadded,
79 | system_response,
80 | fs)
81 | return ir
82 |
83 |
84 | with open("lin_sweep_kaiser_window_script3.txt", "w") as f:
85 | for fade_in in fade_in_list:
86 | ir = get_results(fade_in)
87 | pnr = calculation.pnr_db(ir[0], ir[t_noise * fs:pad * fs])
88 | spectrum_distance = calculation.vector_distance(
89 | bandstop_f, np.fft.rfft(ir[:pad * fs]))
90 | f.write(
91 | str(fade_in) + " " + str(pnr) +
92 | " " + str(spectrum_distance) + " \n")
93 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_script3/lin_sweep_kaiser_window_script3_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of lin. sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_out (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | FIR-Filter: Bandstop
8 | Deconvolution: Unwindowed Excitation
9 |
10 | """
11 |
12 |
13 | import sys
14 | sys.path.append('..')
15 |
16 | import measurement_chain
17 | import plotting
18 | import calculation
19 | import generation
20 | import ir_imitation
21 | import matplotlib.pyplot as plt
22 | import windows
23 | from scipy.signal import lfilter
24 | import numpy as np
25 |
26 |
27 | # Parameters of the measuring system
28 |
29 | fs = 44100
30 |
31 | fstart = 1
32 | fstop = 22050
33 | duration = 1
34 | pad = 4
35 |
36 | # Generate excitation signal
37 |
38 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
39 | N = len(excitation)
40 |
41 |
42 | # Noise in measurement chain
43 |
44 | awgn = -30
45 | noise_system = measurement_chain.additive_noise(awgn)
46 |
47 | # FIR-Filter-System
48 |
49 | # FIR-Filter-System
50 |
51 | f_low = 5000
52 | f_high = 6000
53 | order = 2
54 |
55 |
56 | bandstop_system = measurement_chain.bandstop(f_low, f_high, fs, order)
57 |
58 | # Combinate system elements
59 |
60 | system = measurement_chain.chained(bandstop_system, noise_system)
61 |
62 | # Lists
63 | beta = 7
64 | fade_in_list = np.arange(0, 1001, 1)
65 | fade_out = 0
66 | t_noise = 0.004
67 |
68 | # Spectrum of bandstop for reference
69 |
70 | bandstop_f = calculation.butter_bandstop(f_low, f_high, fs, N * 2 + 1, order)
71 |
72 |
73 | def get_results(fade_in):
74 | excitation_windowed = excitation * windows.window_kaiser(N,
75 | fade_in,
76 | fade_out,
77 | fs, beta)
78 | excitation_windowed_zeropadded = generation.zero_padding(
79 | excitation_windowed, pad, fs)
80 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
81 | system_response = system(excitation_windowed_zeropadded)
82 | ir = calculation.deconv_process(excitation_zeropadded,
83 | system_response,
84 | fs)
85 | return ir
86 |
87 |
88 | with open("lin_sweep_kaiser_window_script3_1.txt", "w") as f:
89 | for fade_in in fade_in_list:
90 | ir = get_results(fade_in)
91 | pnr = calculation.pnr_db(ir[0], ir[t_noise * fs:pad * fs])
92 | spectrum_distance = calculation.vector_distance(
93 | bandstop_f, np.fft.rfft(ir[:pad * fs]))
94 | f.write(
95 | str(fade_in) + " " + str(pnr) +
96 | " " + str(spectrum_distance) + " \n")
97 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_script3/merge_scripts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """ Script to merge scripts"""
3 |
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 | script3 = np.genfromtxt('lin_sweep_kaiser_window_script3.txt')
8 |
9 | script3_1 = np.genfromtxt('lin_sweep_kaiser_window_script3_1.txt')
10 |
11 | fade_in_list = script3[:, 0]
12 |
13 | # Script3
14 |
15 | pnr_list = script3[:, 1]
16 | spectrum_distance_list = script3[:, 2]
17 |
18 | # Script3_1 (unwindowed deconvolution)
19 |
20 | pnr_unwindowed_deconvolution_list = script3_1[:, 1]
21 | spectrum_distance_unwindowed_deconvolution_list = script3_1[:, 2]
22 |
23 |
24 | plt.plot(fade_in_list, pnr_list, label='Deconvolution: Excitation windowed')
25 |
26 | plt.plot(
27 | fade_in_list,
28 | pnr_unwindowed_deconvolution_list,
29 | label='Deconvolution: Excitation unwindowed')
30 | plt.grid()
31 | plt.title('Peak to noise ratio depending on Fade in')
32 | plt.xlabel('Fade in / ms')
33 | plt.ylabel('Peak to noise ratio / dB')
34 | plt.ticklabel_format(useOffset=False)
35 | plt.legend(loc='center right')
36 | plt.xlim([-10, 1000])
37 | plt.savefig('pnr.png')
38 | plt.close()
39 |
40 |
41 | NFFT_bandstop = 88201
42 | max_measurement = 7.09207671865
43 |
44 | plt.plot(fade_in_list, -10 * np.log10(1 / NFFT_bandstop *
45 | np.asarray(spectrum_distance_list) / max_measurement), label='Deconvolution: Excitation windowed')
46 |
47 | plt.plot(fade_in_list,
48 | -10 * np.log10(1 / NFFT_bandstop * np.asarray(spectrum_distance_unwindowed_deconvolution_list) /
49 | max_measurement), label='Deconvolution: Excitation unwindowed')
50 |
51 |
52 | plt.grid()
53 | plt.title('Spectrum Distance depending on Fade in')
54 | plt.xlabel('Fade in / ms')
55 | plt.ylabel('(Spectrum Distance / max(Spectrum Distance)) / dB')
56 | plt.ticklabel_format(useOffset=False)
57 | plt.legend(loc='lower left')
58 | plt.savefig('spectral_distance.png')
59 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_script4/lin_sweep_kaiser_window_script4.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of lin. sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_in (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | FIR-Filter: Bandstop
8 | Deconvolution: Unwindowed Excitation
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import ir_imitation
20 | import matplotlib.pyplot as plt
21 | import windows
22 | from scipy.signal import lfilter
23 | import numpy as np
24 |
25 |
26 | # Parameters of the measuring system
27 |
28 | fs = 44100
29 |
30 | fstart = 1
31 | fstop = 22050
32 | duration = 1
33 | pad = 4
34 |
35 | # Generate excitation signal
36 |
37 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
38 | N = len(excitation)
39 |
40 |
41 | # Noise in measurement chain
42 |
43 | awgn = -30
44 | noise_system = measurement_chain.additive_noise(awgn)
45 |
46 | # FIR-Filter-System
47 |
48 | f_low = 5000
49 | f_high = 6000
50 | order = 2
51 |
52 | bandstop_system = measurement_chain.bandstop(f_low, f_high, fs, order)
53 |
54 |
55 | # Combinate system elements
56 |
57 | system = measurement_chain.chained(bandstop_system, noise_system)
58 |
59 | # Lists
60 | beta = 7
61 | fade_in = 0
62 | fade_out_list = np.arange(0, 1001, 1)
63 | t_noise = 0.004
64 |
65 | # Spectrum of bandstop for reference
66 |
67 | bandstop_f = calculation.butter_bandstop(f_low, f_high, fs, N * 2 + 1, order)
68 |
69 |
70 | def get_results(fade_out):
71 | excitation_windowed = excitation * windows.window_kaiser(N,
72 | fade_in,
73 | fade_out,
74 | fs, beta)
75 | excitation_windowed_zeropadded = generation.zero_padding(
76 | excitation_windowed, pad, fs)
77 | system_response = system(excitation_windowed_zeropadded)
78 | ir = calculation.deconv_process(excitation_windowed_zeropadded,
79 | system_response,
80 | fs)
81 | return ir
82 |
83 |
84 | with open("lin_sweep_kaiser_window_script4.txt", "w") as f:
85 | for fade_out in fade_out_list:
86 | ir = get_results(fade_out)
87 | pnr = calculation.pnr_db(ir[0], ir[t_noise * fs:pad * fs])
88 | spectrum_distance = calculation.vector_distance(
89 | bandstop_f, np.fft.rfft(ir[:pad * fs]))
90 | f.write(
91 | str(fade_out) + " " + str(pnr) +
92 | " " + str(spectrum_distance) + " \n")
93 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_script4/lin_sweep_kaiser_window_script4_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of lin. sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_in (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | FIR-Filter: Bandstop
8 | Deconvolution: Unwindowed Excitation
9 |
10 | """
11 |
12 |
13 | import sys
14 | sys.path.append('..')
15 |
16 | import measurement_chain
17 | import plotting
18 | import calculation
19 | import generation
20 | import ir_imitation
21 | import matplotlib.pyplot as plt
22 | import windows
23 | from scipy.signal import lfilter
24 | import numpy as np
25 |
26 |
27 | # Parameters of the measuring system
28 |
29 | fs = 44100
30 |
31 | fstart = 1
32 | fstop = 22050
33 | duration = 1
34 | pad = 4
35 |
36 | # Generate excitation signal
37 |
38 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
39 | N = len(excitation)
40 |
41 |
42 | # Noise in measurement chain
43 |
44 | awgn = -30
45 | noise_system = measurement_chain.additive_noise(awgn)
46 |
47 | # FIR-Filter-System
48 |
49 | # FIR-Filter-System
50 |
51 | f_low = 5000
52 | f_high = 6000
53 | order = 2
54 |
55 | bandstop_system = measurement_chain.bandstop(f_low, f_high, fs, order)
56 |
57 | # Combinate system elements
58 |
59 | system = measurement_chain.chained(bandstop_system, noise_system)
60 |
61 | # Lists
62 | beta = 7
63 | fade_in = 0
64 | fade_out_list = np.arange(0, 1001, 1)
65 | t_noise = 0.004
66 |
67 | # Spectrum of bandstop for reference
68 |
69 | bandstop_f = calculation.butter_bandstop(f_low, f_high, fs, N * 2 + 1, order)
70 |
71 |
72 | def get_results(fade_out):
73 | excitation_windowed = excitation * windows.window_kaiser(N,
74 | fade_in,
75 | fade_out,
76 | fs, beta)
77 | excitation_windowed_zeropadded = generation.zero_padding(
78 | excitation_windowed, pad, fs)
79 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
80 | system_response = system(excitation_windowed_zeropadded)
81 | ir = calculation.deconv_process(excitation_zeropadded,
82 | system_response,
83 | fs)
84 | return ir
85 |
86 |
87 | with open("lin_sweep_kaiser_window_script4_1.txt", "w") as f:
88 | for fade_out in fade_out_list:
89 | ir = get_results(fade_out)
90 | pnr = calculation.pnr_db(ir[0], ir[t_noise * fs:pad * fs])
91 | spectrum_distance = calculation.vector_distance(
92 | bandstop_f, np.fft.rfft(ir[:pad * fs]))
93 | f.write(
94 | str(fade_out) + " " + str(pnr) +
95 | " " + str(spectrum_distance) + " \n")
96 |
--------------------------------------------------------------------------------
/lin_sweep_kaiser_window_script4/merge_scripts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """ Script to merge scripts"""
3 |
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 | script4 = np.genfromtxt('lin_sweep_kaiser_window_script4.txt')
8 |
9 | script4_1 = np.genfromtxt('lin_sweep_kaiser_window_script4_1.txt')
10 |
11 | fade_out_list = script4[:, 0]
12 |
13 | # Script4
14 |
15 | pnr_list = script4[:, 1]
16 | spectrum_distance_list = script4[:, 2]
17 |
18 | # Script4_1 (unwindowed deconvolution)
19 |
20 | pnr_unwindowed_deconvolution_list = script4_1[:, 1]
21 | spectrum_distance_unwindowed_deconvolution_list = script4_1[:, 2]
22 |
23 |
24 | plt.plot(fade_out_list, pnr_list, label='Deconvolution: Excitation windowed')
25 |
26 | plt.plot(
27 | fade_out_list,
28 | pnr_unwindowed_deconvolution_list,
29 | label='Deconvolution: Excitation unwindowed')
30 | plt.grid()
31 | plt.title('Peak to noise ratio depending on Fade out')
32 | plt.xlabel('Fade out / ms')
33 | plt.ylabel('Peak to noise ratio / dB')
34 | plt.ticklabel_format(useOffset=False)
35 | plt.legend(loc='center right')
36 | plt.xlim([-10, 1000])
37 | plt.savefig('pnr.png')
38 | plt.close()
39 |
40 | NFFT_bandstop = 88201
41 | max_measurement = 7.09207671865
42 |
43 | plt.plot(fade_out_list, -10 * np.log10(1 / NFFT_bandstop *
44 | np.asarray(spectrum_distance_list) / max_measurement), label='Deconvolution: Excitation windowed')
45 |
46 | plt.plot(fade_out_list,
47 | -10 * np.log10(1 / NFFT_bandstop * np.asarray(spectrum_distance_unwindowed_deconvolution_list) /
48 | max_measurement), label='Deconvolution: Excitation unwindowed')
49 |
50 |
51 | plt.grid()
52 | plt.title('Spectrum Distance depending on Fade in')
53 | plt.xlabel('Fade out / ms')
54 | plt.ylabel('(Spectrum Distance / max(Spectrum Distance)) / dB')
55 | plt.ticklabel_format(useOffset=False)
56 | plt.legend(loc='center right')
57 | plt.savefig('spectral_distance.png')
58 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_bandlimited_script5/log_sweep_kaiser_window_bandlimited_script5.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of log. bandlimited sweep signals when using a
4 | Kaiser Window by fixing beta (=2) and fade_out (=0).
5 | fstart = 100 Hz
6 | fstop = 5000 Hz
7 |
8 | """
9 |
10 |
11 | import sys
12 | sys.path.append('..')
13 |
14 | import measurement_chain
15 | import plotting
16 | import calculation
17 | import ir_imitation
18 | import generation
19 | import matplotlib.pyplot as plt
20 | import windows
21 | from scipy.signal import lfilter, fftconvolve
22 | import numpy as np
23 |
24 |
25 | # Parameters of the measuring system
26 |
27 | fs = 44100
28 |
29 | fstart = 100
30 | fstop = 5000
31 | duration = 1
32 | pad = 4
33 |
34 | # Generate excitation signal
35 |
36 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
37 | N = len(excitation)
38 |
39 |
40 | # Noise in measurement chain
41 |
42 | noise_level_db = -30
43 | noise = measurement_chain.additive_noise(noise_level_db)
44 |
45 | # FIR-Filter-System
46 |
47 |
48 | dirac_system = measurement_chain.convolution([1.0])
49 |
50 | # Combinate system elements
51 |
52 | system = measurement_chain.chained(dirac_system, noise)
53 |
54 | # Lists
55 | beta = 7
56 | fade_in_list = np.arange(0, 1001, 1)
57 | fade_out = 0
58 |
59 |
60 | # Spectrum of dirac for reference
61 |
62 | dirac = np.zeros(pad * fs)
63 | dirac[0] = 1
64 | dirac_f = np.fft.rfft(dirac)
65 |
66 |
67 | def get_results(fade_in):
68 | excitation_windowed = excitation * windows.window_kaiser(N,
69 | fade_in,
70 | fade_out,
71 | fs, beta)
72 | excitation_windowed_zeropadded = generation.zero_padding(
73 | excitation_windowed, pad, fs)
74 | system_response = system(excitation_windowed_zeropadded)
75 | ir = calculation.deconv_process(excitation_windowed_zeropadded,
76 | system_response,
77 | fs)
78 | return ir
79 |
80 |
81 | with open("log_sweep_kaiser_window_bandlimited_script5.txt", "w") as f:
82 | for fade_in in fade_in_list:
83 | ir = get_results(fade_in)
84 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
85 | spectrum_distance = calculation.vector_distance(
86 | dirac_f, np.fft.rfft(ir[:pad * fs]))
87 | f.write(
88 | str(fade_in) + " " + str(pnr) +
89 | " " + str(spectrum_distance) + " \n")
90 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_bandlimited_script5/log_sweep_kaiser_window_bandlimited_script5_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of log. bandlimited sweep signals when using a
4 | Kaiser Window by fixing beta (=2) and fade_out (=0).
5 | fstart = 100 Hz
6 | fstop = 5000 Hz
7 |
8 | """
9 |
10 |
11 | import sys
12 | sys.path.append('..')
13 |
14 | import measurement_chain
15 | import plotting
16 | import calculation
17 | import generation
18 | import matplotlib.pyplot as plt
19 | import windows
20 | from scipy.signal import lfilter
21 | import numpy as np
22 |
23 |
24 | # Parameters of the measuring system
25 |
26 | fs = 44100
27 |
28 | fstart = 100
29 | fstop = 5000
30 | duration = 1
31 | pad = 4
32 |
33 | # Generate excitation signal
34 |
35 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
36 | N = len(excitation)
37 |
38 |
39 | # Noise in measurement chain
40 |
41 | noise_level_db = -30
42 | noise = measurement_chain.additive_noise(noise_level_db)
43 |
44 | # FIR-Filter-System
45 |
46 | dirac_system = measurement_chain.convolution([1.0])
47 |
48 | # Combinate system elements
49 |
50 | system = measurement_chain.chained(dirac_system, noise)
51 |
52 | # Spectrum of dirac for reference
53 |
54 | dirac = np.zeros(pad * fs)
55 | dirac[0] = 1
56 | dirac_f = np.fft.rfft(dirac)
57 |
58 | # Lists
59 | beta = 7
60 | fade_in_list = np.arange(0, 1001, 1)
61 | fade_out = 0
62 |
63 |
64 | def get_results(fade_in):
65 | excitation_windowed = excitation * windows.window_kaiser(N,
66 | fade_in,
67 | fade_out,
68 | fs, beta)
69 | excitation_windowed_zeropadded = generation.zero_padding(
70 | excitation_windowed, pad, fs)
71 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
72 | system_response = system(excitation_windowed_zeropadded)
73 | ir = calculation.deconv_process(excitation_zeropadded,
74 | system_response,
75 | fs)
76 | return ir
77 |
78 |
79 | with open("log_sweep_kaiser_window_bandlimited_script5_1.txt", "w") as f:
80 | for fade_in in fade_in_list:
81 | ir = get_results(fade_in)
82 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
83 | spectrum_distance = calculation.vector_distance(
84 | dirac_f, np.fft.rfft(ir[:pad * fs]))
85 | f.write(
86 | str(fade_in) + " " + str(pnr) +
87 | " " + str(spectrum_distance) + " \n")
88 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_bandlimited_script5/merge_scripts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """ Script to merge scripts"""
3 |
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 | script5 = np.genfromtxt('log_sweep_kaiser_window_bandlimited_script5.txt')
8 |
9 | script5_1 = np.genfromtxt('log_sweep_kaiser_window_bandlimited_script5_1.txt')
10 |
11 | fade_in_list = script5[:, 0]
12 |
13 | # Script5
14 |
15 | pnr_list = script5[:, 1]
16 | spectrum_distance_list = script5[:, 2]
17 |
18 | # Script5_1 (unwindowed deconvolution)
19 |
20 | pnr_unwindowed_deconvolution_list = script5_1[:, 1]
21 | spectrum_distance_unwindowed_deconvolution_list = script5_1[:, 2]
22 |
23 |
24 | plt.plot(fade_in_list, pnr_list, label='Deconvolution: Excitation windowed')
25 |
26 | plt.plot(
27 | fade_in_list,
28 | pnr_unwindowed_deconvolution_list,
29 | label='Deconvolution: Excitation unwindowed')
30 | plt.grid()
31 | plt.title('Peak to noise ratio depending on Fade in')
32 | plt.xlabel('Fade in / ms')
33 | plt.ylabel('Peak to noise ratio / dB')
34 | plt.ticklabel_format(useOffset=False)
35 | plt.legend(loc='lower left')
36 | plt.xlim([-10, 1000])
37 | plt.savefig('pnr.png')
38 | plt.close()
39 |
40 |
41 | NFFT_dirac = 88201
42 | max_measurement = 7040966.76862
43 |
44 | plt.plot(
45 | fade_in_list,
46 | -10 * np.log10(1 / NFFT_dirac * np.abs(
47 | np.asarray(spectrum_distance_list) / max_measurement)),
48 | label='Deconvolution: Excitation windowed')
49 |
50 | plt.plot(fade_in_list,
51 | -10 * np.log10(1 / NFFT_dirac * np.abs(np.asarray(spectrum_distance_unwindowed_deconvolution_list) /
52 | max_measurement)), label='Deconvolution: Excitation unwindowed')
53 |
54 |
55 | plt.grid()
56 | plt.title('Spectrum Distance depending on Fade in')
57 | plt.xlabel('Fade in / ms')
58 | plt.ylabel('(Spectrum Distance / max(Spectrum Distance)) / dB')
59 | plt.ticklabel_format(useOffset=False)
60 | plt.legend(loc='center right')
61 | plt.xlim([-10, 1000])
62 | plt.savefig('spectrale_distance.png')
63 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_bandlimited_script6/log_sweep_kaiser_window_bandlimited_script6.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of bandlimited log. sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_in (=0).
5 | fstart = 100 Hz
6 | fstop = 5000 Hz
7 | Deconvolution: Windowed
8 |
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import matplotlib.pyplot as plt
20 | import windows
21 | from scipy.signal import lfilter, fftconvolve
22 | import numpy as np
23 |
24 |
25 | # Parameters of the measuring system
26 |
27 | fs = 44100
28 |
29 | fstart = 100
30 | fstop = 5000
31 | duration = 1
32 | pad = 4
33 |
34 | # Generate excitation signal
35 |
36 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
37 | N = len(excitation)
38 |
39 |
40 | # Noise in measurement chain
41 |
42 | noise_level_db = -30.
43 | noise = measurement_chain.additive_noise(noise_level_db)
44 |
45 | # FIR-Filter-System
46 |
47 | dirac_system = measurement_chain.convolution([1.0])
48 |
49 | # Combinate system elements
50 |
51 | system = measurement_chain.chained(dirac_system, noise)
52 |
53 | # Lists
54 | beta = 7
55 | fade_in = 0
56 | fade_out_list = np.arange(0, 1001, 1)
57 |
58 | # Spectrum of dirac for reference
59 |
60 | dirac = np.zeros(pad * fs)
61 | dirac[0] = 1
62 | dirac_f = np.fft.rfft(dirac)
63 |
64 |
65 | def get_results(fade_out):
66 | excitation_windowed = excitation * windows.window_kaiser(N,
67 | fade_in,
68 | fade_out,
69 | fs, beta)
70 | excitation_windowed_zeropadded = generation.zero_padding(
71 | excitation_windowed, pad, fs)
72 | system_response = system(excitation_windowed_zeropadded)
73 | ir = calculation.deconv_process(excitation_windowed_zeropadded,
74 | system_response,
75 | fs)
76 | return ir
77 |
78 |
79 | with open("log_sweep_kaiser_window_bandlimited_script6.txt", "w") as f:
80 | for fade_out in fade_out_list:
81 | ir = get_results(fade_out)
82 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
83 | spectrum_distance = calculation.vector_distance(
84 | dirac_f, np.fft.rfft(ir[:pad * fs]))
85 | f.write(
86 | str(fade_out) + " " + str(pnr) +
87 | " " + str(spectrum_distance) + " \n")
88 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_bandlimited_script6/log_sweep_kaiser_window_bandlimited_script6_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of log. sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_in (=0).
5 | fstart = 100 Hz
6 | fstop = 5000 Hz
7 | Deconvolution: Unwindowed
8 |
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import matplotlib.pyplot as plt
20 | import windows
21 | from scipy.signal import lfilter
22 | import numpy as np
23 |
24 |
25 | # Parameters of the measuring system
26 |
27 | fs = 44100
28 |
29 | fstart = 100
30 | fstop = 5000
31 | duration = 1
32 | pad = 4
33 |
34 | # Generate excitation signal
35 |
36 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
37 | N = len(excitation)
38 |
39 | # Noise in measurement chain
40 |
41 | noise_level_db = -30.
42 | noise = measurement_chain.additive_noise(noise_level_db)
43 |
44 | # FIR-Filter-System
45 |
46 | dirac_system = measurement_chain.convolution([1.0])
47 |
48 | # Combinate system elements
49 |
50 | system = measurement_chain.chained(dirac_system, noise)
51 |
52 | # Lists
53 | beta = 7
54 | fade_in = 0
55 | fade_out_list = np.arange(0, 1001, 1)
56 |
57 | # Spectrum of dirac for reference
58 |
59 | dirac = np.zeros(pad * fs)
60 | dirac[0] = 1
61 | dirac_f = np.fft.rfft(dirac)
62 |
63 |
64 | def get_results(fade_out):
65 | excitation_windowed = excitation * windows.window_kaiser(N,
66 | fade_in,
67 | fade_out,
68 | fs, beta)
69 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
70 | excitation_windowed_zeropadded = generation.zero_padding(
71 | excitation_windowed, pad, fs)
72 | system_response = system(excitation_windowed_zeropadded)
73 | ir = calculation.deconv_process(excitation_zeropadded,
74 | system_response,
75 | fs)
76 | return ir
77 |
78 |
79 | with open("log_sweep_kaiser_window_bandlimited_script6_1.txt", "w") as f:
80 | for fade_out in fade_out_list:
81 | ir = get_results(fade_out)
82 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
83 | spectrum_distance = calculation.vector_distance(
84 | dirac_f, np.fft.rfft(ir[:pad * fs]))
85 | f.write(
86 | str(fade_out) + " " + str(pnr) +
87 | " " + str(spectrum_distance) + " \n")
88 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_bandlimited_script6/merge_scripts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """ Script to merge scripts"""
3 |
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 | script6 = np.genfromtxt('log_sweep_kaiser_window_bandlimited_script6.txt')
8 |
9 | script6_1 = np.genfromtxt('log_sweep_kaiser_window_bandlimited_script6_1.txt')
10 |
11 | fade_out_list = script6[:, 0]
12 |
13 | # Script6
14 |
15 | pnr_list = script6[:, 1]
16 | spectrum_distance_list = script6[:, 2]
17 |
18 | # Script6_1 (unwindowed deconvolution)
19 |
20 | pnr_unwindowed_deconvolution_list = script6_1[:, 1]
21 | spectrum_distance_unwindowed_deconvolution_list = script6_1[:, 2]
22 |
23 |
24 | plt.plot(fade_out_list, pnr_list, label='Deconvolution: Excitation windowed')
25 |
26 | plt.plot(
27 | fade_out_list,
28 | pnr_unwindowed_deconvolution_list,
29 | label='Deconvolution: Excitation unwindowed')
30 | plt.grid()
31 | plt.title('Peak to noise ratio depending on Fade out')
32 | plt.xlabel('Fade out / ms')
33 | plt.ylabel('Peak to noise ratio / dB')
34 | plt.ticklabel_format(useOffset=False)
35 | plt.legend(loc='upper right')
36 | plt.xlim([-10, 1000])
37 | plt.savefig('pnr.png')
38 | plt.close()
39 |
40 |
41 | NFFT_dirac = 88201
42 | max_measurement = 7040966.76862
43 |
44 | plt.plot(
45 | fade_out_list,
46 | -10 * np.log10(1 / NFFT_dirac * np.abs(
47 | np.asarray(spectrum_distance_list) / max_measurement)),
48 | label='Deconvolution: Excitation windowed')
49 |
50 | plt.plot(fade_out_list,
51 | -10 * np.log10(1 / NFFT_dirac * np.abs(np.asarray(spectrum_distance_unwindowed_deconvolution_list) /
52 | max_measurement)), label='Deconvolution: Excitation unwindowed')
53 |
54 |
55 | plt.grid()
56 | plt.title('Spectrum Distance depending on Fade in')
57 | plt.xlabel('Fade out / ms')
58 | plt.ylabel('(Spectrum Distance / max(Spectrum Distance)) / dB')
59 | plt.ticklabel_format(useOffset=False)
60 | plt.legend(loc='center right')
61 | plt.xlim([-10, 1000])
62 | plt.savefig('spectral_distance.png')
63 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script1/__pycache__/log_sweep_kaiser_window_script1.cpython-34.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spatialaudio/sweep/003bc0efcc3c441bf6cca2749b100e33a0b3c4bb/log_sweep_kaiser_window_script1/__pycache__/log_sweep_kaiser_window_script1.cpython-34.pyc
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script1/__pycache__/sweep_kaiser_window.cpython-34.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spatialaudio/sweep/003bc0efcc3c441bf6cca2749b100e33a0b3c4bb/log_sweep_kaiser_window_script1/__pycache__/sweep_kaiser_window.cpython-34.pyc
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script1/__pycache__/sweep_kaiser_window_script1.cpython-34.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spatialaudio/sweep/003bc0efcc3c441bf6cca2749b100e33a0b3c4bb/log_sweep_kaiser_window_script1/__pycache__/sweep_kaiser_window_script1.cpython-34.pyc
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script1/log_sweep_kaiser_window_script1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of log. sweep signals when using a
4 | Kaiser Window by fixing beta (=2) and fade_out (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 |
8 | """
9 |
10 |
11 | import sys
12 | sys.path.append('..')
13 |
14 | import measurement_chain
15 | import plotting
16 | import calculation
17 | import ir_imitation
18 | import generation
19 | import matplotlib.pyplot as plt
20 | import windows
21 | from scipy.signal import lfilter, fftconvolve
22 | import numpy as np
23 |
24 |
25 | # Parameters of the measuring system
26 |
27 | fs = 44100
28 |
29 | fstart = 1
30 | fstop = 22050
31 | duration = 1
32 | pad = 4
33 |
34 | # Generate excitation signal
35 |
36 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
37 | N = len(excitation)
38 |
39 |
40 | # Noise in measurement chain
41 |
42 | noise_level_db = -30
43 | noise = measurement_chain.additive_noise(noise_level_db)
44 |
45 | # FIR-Filter-System
46 |
47 |
48 | dirac_system = measurement_chain.convolution([1.0])
49 |
50 | # Combinate system elements
51 |
52 | system = measurement_chain.chained(dirac_system, noise)
53 |
54 | # Lists
55 | beta = 7
56 | fade_in_list = np.arange(0, 1001, 1)
57 | fade_out = 0
58 |
59 |
60 | # Spectrum of dirac for reference
61 |
62 | dirac = np.zeros(pad * fs)
63 | dirac[0] = 1
64 | dirac_f = np.fft.rfft(dirac)
65 |
66 |
67 | def get_results(fade_in):
68 | excitation_windowed = excitation * windows.window_kaiser(N,
69 | fade_in,
70 | fade_out,
71 | fs, beta)
72 | excitation_windowed_zeropadded = generation.zero_padding(
73 | excitation_windowed, pad, fs)
74 | system_response = system(excitation_windowed_zeropadded)
75 | ir = calculation.deconv_process(excitation_windowed_zeropadded,
76 | system_response,
77 | fs)
78 | return ir
79 |
80 |
81 | with open("log_sweep_kaiser_window_script1.txt", "w") as f:
82 | for fade_in in fade_in_list:
83 | ir = get_results(fade_in)
84 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
85 | spectrum_distance = calculation.vector_distance(
86 | dirac_f, np.fft.rfft(ir[:pad * fs]))
87 | f.write(str(fade_in) + " " + str(pnr)
88 | + " " + str(spectrum_distance) + " \n")
89 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script1/log_sweep_kaiser_window_script1_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of log. sweep signals when using a
4 | Kaiser Window by fixing beta (=2) and fade_out (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | Unwindowed Deconvolution
8 |
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import matplotlib.pyplot as plt
20 | import windows
21 | from scipy.signal import lfilter
22 | import numpy as np
23 |
24 |
25 | # Parameters of the measuring system
26 |
27 | fs = 44100
28 |
29 | fstart = 1
30 | fstop = 22050
31 | duration = 1
32 | pad = 4
33 |
34 | # Generate excitation signal
35 |
36 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
37 | N = len(excitation)
38 |
39 |
40 | # Noise in measurement chain
41 |
42 | noise_level_db = -30
43 | noise = measurement_chain.additive_noise(noise_level_db)
44 |
45 | # FIR-Filter-System
46 |
47 | dirac_system = measurement_chain.convolution([1.0])
48 |
49 | # Combinate system elements
50 |
51 | system = measurement_chain.chained(dirac_system, noise)
52 |
53 | # Spectrum of dirac for reference
54 |
55 | dirac = np.zeros(pad * fs)
56 | dirac[0] = 1
57 | dirac_f = np.fft.rfft(dirac)
58 |
59 | # Lists
60 | beta = 7
61 | fade_in_list = np.arange(0, 1001, 1)
62 | fade_out = 0
63 |
64 |
65 | def get_results(fade_in):
66 | excitation_windowed = excitation * windows.window_kaiser(N,
67 | fade_in,
68 | fade_out,
69 | fs, beta)
70 | excitation_windowed_zeropadded = generation.zero_padding(
71 | excitation_windowed, pad, fs)
72 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
73 | system_response = system(excitation_windowed_zeropadded)
74 | ir = calculation.deconv_process(excitation_zeropadded,
75 | system_response,
76 | fs)
77 | return ir
78 |
79 |
80 | with open("log_sweep_kaiser_window_script1_1.txt", "w") as f:
81 | for fade_in in fade_in_list:
82 | ir = get_results(fade_in)
83 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
84 | spectrum_distance = calculation.vector_distance(
85 | dirac_f, np.fft.rfft(ir[: pad * fs]))
86 | f.write(str(fade_in) + " " +
87 | str(pnr) + " " + str(spectrum_distance) + " \n")
88 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script1/merge_scripts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """ Script to merge scripts"""
3 |
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 | script1 = np.genfromtxt('log_sweep_kaiser_window_script1.txt')
8 |
9 | script1_1 = np.genfromtxt('log_sweep_kaiser_window_script1_1.txt')
10 |
11 | fade_in_list = script1[:, 0]
12 |
13 | # Script1
14 |
15 | pnr_list = script1[:, 1]
16 | spectrum_distance_list = script1[:, 2]
17 |
18 | # Script1_1 (unwindowed deconvolution)
19 |
20 | pnr_unwindowed_deconvolution_list = script1_1[:, 1]
21 | spectrum_distance_unwindowed_deconvolution_list = script1_1[:, 2]
22 |
23 |
24 | plt.plot(fade_in_list, pnr_list, label='Deconvolution: Excitation windowed')
25 |
26 | plt.plot(fade_in_list, pnr_unwindowed_deconvolution_list,
27 | label='Deconvolution: Excitation unwindowed')
28 | plt.grid()
29 | plt.title('Peak to noise ratio depending on Fade in')
30 | plt.xlabel('Fade in / ms')
31 | plt.ylabel('Peak to noise ratio / dB')
32 | plt.ticklabel_format(useOffset=False)
33 | plt.legend(loc='lower left')
34 | plt.xlim([-10, 1000])
35 | plt.savefig('pnr.png')
36 | plt.close()
37 |
38 | NFFT_dirac = 88201
39 | max_measurement = 362.462253302
40 |
41 | plt.plot(fade_in_list,
42 | -10 * np.log10(1 / NFFT_dirac *
43 | np.abs(
44 | np.asarray(
45 | spectrum_distance_list) / max_measurement)),
46 | label='Deconvolution: Excitation windowed')
47 |
48 | plt.plot(fade_in_list,
49 | -10 * np.log10(
50 | 1 / NFFT_dirac * np.abs(
51 | np.asarray(spectrum_distance_unwindowed_deconvolution_list) /
52 | max_measurement)),
53 | label='Deconvolution: Excitation unwindowed')
54 |
55 |
56 | plt.grid()
57 | plt.title('Spectrum Distance depending on Fade in')
58 | plt.xlabel('Fade in / ms')
59 | plt.ylabel('(Spectrum Distance / max(Spectrum Distance)) / dB')
60 | plt.ticklabel_format(useOffset=False)
61 | plt.legend(loc='lower left')
62 | plt.xlim([-10, 1000])
63 | plt.savefig('spectral_distance.png')
64 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script2/log_sweep_kaiser_window_script2.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of log. sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_in (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 |
8 | """
9 |
10 |
11 | import sys
12 | sys.path.append('..')
13 |
14 | import measurement_chain
15 | import plotting
16 | import calculation
17 | import generation
18 | import matplotlib.pyplot as plt
19 | import windows
20 | from scipy.signal import lfilter, fftconvolve
21 | import numpy as np
22 |
23 |
24 | # Parameters of the measuring system
25 |
26 | fs = 44100
27 |
28 | fstart = 1
29 | fstop = 22050
30 | duration = 1
31 | pad = 4
32 |
33 | # Generate excitation signal
34 |
35 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
36 | N = len(excitation)
37 |
38 |
39 | # Noise in measurement chain
40 |
41 | noise_level_db = -30.
42 | noise = measurement_chain.additive_noise(noise_level_db)
43 |
44 | # FIR-Filter-System
45 |
46 | dirac_system = measurement_chain.convolution([1.0])
47 |
48 | # Combinate system elements
49 |
50 | system = measurement_chain.chained(dirac_system, noise)
51 |
52 | # Lists
53 | beta = 7
54 | fade_in = 0
55 | fade_out_list = np.arange(0, 1001, 1)
56 |
57 | # Spectrum of dirac for reference
58 |
59 | dirac = np.zeros(pad * fs)
60 | dirac[0] = 1
61 | dirac_f = np.fft.rfft(dirac)
62 |
63 |
64 | def get_results(fade_out):
65 | excitation_windowed = excitation * windows.window_kaiser(N,
66 | fade_in,
67 | fade_out,
68 | fs, beta)
69 | excitation_windowed_zeropadded = generation.zero_padding(
70 | excitation_windowed, pad, fs)
71 | system_response = system(excitation_windowed_zeropadded)
72 | ir = calculation.deconv_process(excitation_windowed_zeropadded,
73 | system_response,
74 | fs)
75 | return ir
76 |
77 |
78 | with open("log_sweep_kaiser_window_script2.txt", "w") as f:
79 | for fade_out in fade_out_list:
80 | ir = get_results(fade_out)
81 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
82 | spectrum_distance = calculation.vector_distance(
83 | dirac_f, np.fft.rfft(ir[:pad * fs]))
84 | f.write(
85 | str(fade_out) + " " + str(pnr) +
86 | " " + str(spectrum_distance) + " \n")
87 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script2/log_sweep_kaiser_window_script2_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of log. sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_in (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | Undwindowed Deconvolution
8 |
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import matplotlib.pyplot as plt
20 | import windows
21 | from scipy.signal import lfilter
22 | import numpy as np
23 |
24 |
25 | # Parameters of the measuring system
26 |
27 | fs = 44100
28 |
29 | fstart = 1
30 | fstop = 22050
31 | duration = 1
32 | pad = 4
33 |
34 | # Generate excitation signal
35 |
36 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
37 | N = len(excitation)
38 |
39 | # Noise in measurement chain
40 |
41 | noise_level_db = -30.
42 | noise = measurement_chain.additive_noise(noise_level_db)
43 |
44 | # FIR-Filter-System
45 |
46 | dirac_system = measurement_chain.convolution([1.0])
47 |
48 | # Combinate system elements
49 |
50 | system = measurement_chain.chained(dirac_system, noise)
51 |
52 | # Lists
53 | beta = 7
54 | fade_in = 0
55 | fade_out_list = np.arange(0, 1001, 1)
56 |
57 | # Spectrum of dirac for reference
58 |
59 | dirac = np.zeros(pad * fs)
60 | dirac[0] = 1
61 | dirac_f = np.fft.rfft(dirac)
62 |
63 |
64 | def get_results(fade_out):
65 | excitation_windowed = excitation * windows.window_kaiser(N,
66 | fade_in,
67 | fade_out,
68 | fs, beta)
69 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
70 | excitation_windowed_zeropadded = generation.zero_padding(
71 | excitation_windowed, pad, fs)
72 | system_response = system(excitation_windowed_zeropadded)
73 | ir = calculation.deconv_process(excitation_zeropadded,
74 | system_response,
75 | fs)
76 | return ir
77 |
78 |
79 | with open("log_sweep_kaiser_window_script2_1.txt", "w") as f:
80 | for fade_out in fade_out_list:
81 | ir = get_results(fade_out)
82 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
83 | spectrum_distance = calculation.vector_distance(
84 | dirac_f, np.fft.rfft(ir[:pad * fs]))
85 | f.write(
86 | str(fade_out) + " " + str(pnr) +
87 | " " + str(spectrum_distance) + " \n")
88 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script2/merge_scripts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """ Script to merge scripts"""
3 |
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 | script2 = np.genfromtxt(
8 | 'log_sweep_kaiser_window_script2.txt')
9 |
10 | script2_1 = np.genfromtxt(
11 | 'log_sweep_kaiser_window_script2_1.txt')
12 |
13 | fade_out_list = script2[:, 0]
14 |
15 | # Script2
16 |
17 | snr_list = script2[:, 1]
18 | spectrum_distance_list = script2[:, 2]
19 |
20 | # Script2_1 (unwindowed deconvolution)
21 |
22 | snr_unwindowed_deconvolution_list = script2_1[:, 1]
23 | spectrum_distance_unwindowed_deconvolution_list = script2_1[:, 2]
24 |
25 |
26 | plt.plot(fade_out_list, snr_list, label='Deconvolution: Excitation windowed')
27 |
28 | plt.plot(
29 | fade_out_list,
30 | snr_unwindowed_deconvolution_list,
31 | label='Deconvolution: Excitation unwindowed')
32 | plt.grid()
33 | plt.title('Peak to noise ratio depending on Fade out')
34 | plt.xlabel('Fade out / ms')
35 | plt.ylabel('Peak to noise ratio / dB')
36 | plt.ticklabel_format(useOffset=False)
37 | plt.legend(loc='upper right')
38 | plt.xlim([-10, 1000])
39 | plt.savefig('pnr.png')
40 | plt.close()
41 |
42 | NFFT_dirac = 88201
43 | max_measurement = 362.462253302
44 |
45 | plt.plot(
46 | fade_out_list,
47 | -10 * np.log10(
48 | 1 / NFFT_dirac * np.abs(
49 | np.asarray(spectrum_distance_list) / max_measurement)),
50 | label='Deconvolution: Excitation windowed')
51 |
52 | plt.plot(fade_out_list,
53 | -10 * np.log10(1 / NFFT_dirac *
54 | np.abs(np.asarray(spectrum_distance_unwindowed_deconvolution_list) /
55 | max_measurement)), label='Deconvolution: Excitation unwindowed')
56 |
57 |
58 | plt.grid()
59 | plt.title('Spectrum Distance depending on Fade in')
60 | plt.xlabel('Fade out / ms')
61 | plt.ylabel('(Spectrum Distance / max(Spectrum Distance)) / dB')
62 | plt.ticklabel_format(useOffset=False)
63 | plt.legend(loc='upper right')
64 | plt.xlim([-10, 1000])
65 | plt.savefig('spectral_distance.png')
66 | plt.close()
67 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script3/log_sweep_kaiser_window_script3.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of log. sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_out (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | FIR-Filter: Bandstop
8 | Deconvolution: Windowed Excitation
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import ir_imitation
20 | import matplotlib.pyplot as plt
21 | import windows
22 | from scipy.signal import lfilter
23 | import numpy as np
24 |
25 |
26 | # Parameters of the measuring system
27 |
28 | fs = 44100
29 |
30 | fstart = 1
31 | fstop = 22050
32 | duration = 1
33 | pad = 4
34 |
35 | # Generate excitation signal
36 |
37 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
38 | N = len(excitation)
39 |
40 |
41 | # Noise in measurement chain
42 |
43 | awgn = -30
44 | noise_system = measurement_chain.additive_noise(awgn)
45 |
46 | # FIR-Filter-System
47 |
48 | f_low = 5000
49 | f_high = 6000
50 | order = 2
51 |
52 | bandstop_system = measurement_chain.bandstop(f_low, f_high, fs, order)
53 |
54 |
55 | # Combinate system elements
56 |
57 | system = measurement_chain.chained(bandstop_system, noise_system)
58 |
59 | # Lists
60 | beta = 7
61 | fade_in_list = np.arange(0, 1001, 1)
62 | fade_out = 0
63 | t_noise = 0.004
64 |
65 | # Spectrum of bandstop for reference
66 |
67 | bandstop_f = calculation.butter_bandstop(f_low, f_high, fs, N * 2 + 1, order)
68 |
69 |
70 | def get_results(fade_in):
71 | excitation_windowed = excitation * windows.window_kaiser(N,
72 | fade_in,
73 | fade_out,
74 | fs, beta)
75 | excitation_windowed_zeropadded = generation.zero_padding(
76 | excitation_windowed, pad, fs)
77 | system_response = system(excitation_windowed_zeropadded)
78 | ir = calculation.deconv_process(excitation_windowed_zeropadded,
79 | system_response,
80 | fs)
81 | return ir
82 |
83 |
84 | with open("log_sweep_kaiser_window_script3.txt", "w") as f:
85 | for fade_in in fade_in_list:
86 | ir = get_results(fade_in)
87 | pnr = calculation.pnr_db(ir[0], ir[t_noise * fs:pad * fs])
88 | spectrum_distance = calculation.vector_distance(
89 | bandstop_f, np.fft.rfft(ir[:pad * fs]))
90 | f.write(
91 | str(fade_in) + " " + str(pnr) +
92 | " " + str(spectrum_distance) + " \n")
93 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script3/log_sweep_kaiser_window_script3_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of log. sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_out (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | FIR-Filter: Bandstop
8 | Deconvolution: Unwindowed Excitation
9 |
10 | """
11 |
12 |
13 | import sys
14 | sys.path.append('..')
15 |
16 | import measurement_chain
17 | import plotting
18 | import calculation
19 | import generation
20 | import ir_imitation
21 | import matplotlib.pyplot as plt
22 | import windows
23 | from scipy.signal import lfilter
24 | import numpy as np
25 |
26 |
27 | # Parameters of the measuring system
28 |
29 | fs = 44100
30 |
31 | fstart = 1
32 | fstop = 22050
33 | duration = 1
34 | pad = 4
35 |
36 | # Generate excitation signal
37 |
38 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
39 | N = len(excitation)
40 |
41 |
42 | # Noise in measurement chain
43 |
44 | awgn = -30
45 | noise_system = measurement_chain.additive_noise(awgn)
46 |
47 | # FIR-Filter-System
48 |
49 | # FIR-Filter-System
50 |
51 | f_low = 5000
52 | f_high = 6000
53 | order = 2
54 |
55 |
56 | bandstop_system = measurement_chain.bandstop(f_low, f_high, fs, order)
57 |
58 | # Combinate system elements
59 |
60 | system = measurement_chain.chained(bandstop_system, noise_system)
61 |
62 | # Lists
63 | beta = 7
64 | fade_in_list = np.arange(0, 1001, 1)
65 | fade_out = 0
66 | t_noise = 0.004
67 |
68 | # Spectrum of bandstop for reference
69 |
70 | bandstop_f = calculation.butter_bandstop(f_low, f_high, fs, N * 2 + 1, order)
71 |
72 |
73 | def get_results(fade_in):
74 | excitation_windowed = excitation * windows.window_kaiser(N,
75 | fade_in,
76 | fade_out,
77 | fs, beta)
78 | excitation_windowed_zeropadded = generation.zero_padding(
79 | excitation_windowed, pad, fs)
80 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
81 | system_response = system(excitation_windowed_zeropadded)
82 | ir = calculation.deconv_process(excitation_zeropadded,
83 | system_response,
84 | fs)
85 | return ir
86 |
87 |
88 | with open("log_sweep_kaiser_window_script3_1.txt", "w") as f:
89 | for fade_in in fade_in_list:
90 | ir = get_results(fade_in)
91 | pnr = calculation.pnr_db(ir[0], ir[t_noise * fs:pad * fs])
92 | spectrum_distance = calculation.vector_distance(
93 | bandstop_f, np.fft.rfft(ir[:pad * fs]))
94 | f.write(
95 | str(fade_in) + " " + str(pnr) +
96 | " " + str(spectrum_distance) + " \n")
97 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script3/merge_scripts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """ Script to merge scripts"""
3 |
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 | script3 = np.genfromtxt('log_sweep_kaiser_window_script3.txt')
8 |
9 | script3_1 = np.genfromtxt('log_sweep_kaiser_window_script3_1.txt')
10 |
11 | fade_in_list = script3[:, 0]
12 |
13 | # Script3
14 |
15 | pnr_list = script3[:, 1]
16 | spectrum_distance_list = script3[:, 2]
17 |
18 | # Script3_1 (unwindowed deconvolution)
19 |
20 | pnr_unwindowed_deconvolution_list = script3_1[:, 1]
21 | spectrum_distance_unwindowed_deconvolution_list = script3_1[:, 2]
22 |
23 |
24 | plt.plot(fade_in_list, pnr_list, label='Deconvolution: Excitation windowed')
25 |
26 | plt.plot(
27 | fade_in_list,
28 | pnr_unwindowed_deconvolution_list,
29 | label='Deconvolution: Excitation unwindowed')
30 | plt.grid()
31 | plt.title('Peak to noise ratio depending on Fade in')
32 | plt.xlabel('Fade in / ms')
33 | plt.ylabel('Peak to noise ratio / dB')
34 | plt.ticklabel_format(useOffset=False)
35 | plt.legend(loc='lower left')
36 | plt.xlim([-10, 1000])
37 | plt.savefig('pnr.png')
38 | plt.close()
39 |
40 | NFFT_bandstop = 88201
41 | max_measurement = 362.799629307
42 |
43 | plt.plot(
44 | fade_in_list,
45 | -10 * np.log10(1 / NFFT_bandstop * np.abs(
46 | np.asarray(spectrum_distance_list) / max_measurement)),
47 | label='Deconvolution: Excitation windowed')
48 |
49 | plt.plot(fade_in_list,
50 | -10 * np.log10(1 / NFFT_bandstop * np.abs(np.asarray(spectrum_distance_unwindowed_deconvolution_list) /
51 | max_measurement)), label='Deconvolution: Excitation unwindowed')
52 |
53 |
54 | plt.grid()
55 | plt.title('Spectrum Distance depending on Fade in')
56 | plt.xlabel('Fade in / ms')
57 | plt.ylabel('(Spectrum Distance / max(Spectrum Distance)) / dB')
58 | plt.ticklabel_format(useOffset=False)
59 | plt.legend(loc='upper left')
60 | plt.xlim([-10, 1000])
61 | plt.savefig('spectral_distance.png')
62 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script4/log_sweep_kaiser_window_script4.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_in (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | FIR-Filter: Bandstop
8 | Deconvolution: Windowed Excitation
9 | """
10 |
11 |
12 | import sys
13 | sys.path.append('..')
14 |
15 | import measurement_chain
16 | import plotting
17 | import calculation
18 | import generation
19 | import ir_imitation
20 | import matplotlib.pyplot as plt
21 | import windows
22 | from scipy.signal import lfilter
23 | import numpy as np
24 |
25 |
26 | # Parameters of the measuring system
27 |
28 | fs = 44100
29 |
30 | fstart = 1
31 | fstop = 22050
32 | duration = 1
33 | pad = 4
34 |
35 | # Generate excitation signal
36 |
37 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
38 | N = len(excitation)
39 |
40 |
41 | # Noise in measurement chain
42 |
43 | awgn = -30
44 | noise_system = measurement_chain.additive_noise(awgn)
45 |
46 | # FIR-Filter-System
47 |
48 | f_low = 5000
49 | f_high = 6000
50 | order = 2
51 |
52 | bandstop_system = measurement_chain.bandstop(f_low, f_high, fs, order)
53 |
54 |
55 | # Combinate system elements
56 |
57 | system = measurement_chain.chained(bandstop_system, noise_system)
58 |
59 | # Lists
60 | beta = 7
61 | fade_in = 0
62 | fade_out_list = np.arange(0, 1001, 1)
63 | t_noise = 0.004
64 |
65 | # Spectrum of bandstop for reference
66 |
67 | bandstop_f = calculation.butter_bandstop(f_low, f_high, fs, N * 2 + 1, order)
68 |
69 |
70 | def get_results(fade_out):
71 | excitation_windowed = excitation * windows.window_kaiser(N,
72 | fade_in,
73 | fade_out,
74 | fs, beta)
75 | excitation_windowed_zeropadded = generation.zero_padding(
76 | excitation_windowed, pad, fs)
77 | system_response = system(excitation_windowed_zeropadded)
78 | ir = calculation.deconv_process(excitation_windowed_zeropadded,
79 | system_response,
80 | fs)
81 | return ir
82 |
83 | with open("log_sweep_kaiser_window_script4.txt", "w") as f:
84 | for fade_out in fade_out_list:
85 | ir = get_results(fade_out)
86 | pnr = calculation.pnr_db(ir[0], ir[t_noise * fs:pad * fs])
87 | spectrum_distance = calculation.vector_distance(
88 | bandstop_f, np.fft.rfft(ir[:pad * fs]))
89 | f.write(
90 | str(fade_out) + " " + str(pnr) +
91 | " " + str(spectrum_distance) + " \n")
92 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script4/log_sweep_kaiser_window_script4_1.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of sweep signals when using a
4 | Kaiser Window by fixing beta (=7) and fade_in (=0).
5 | fstart = 1 Hz
6 | fstop = 22050 Hz
7 | FIR-Filter: Bandstop
8 | Deconvolution: Unwindowed Excitation
9 |
10 | """
11 |
12 |
13 | import sys
14 | sys.path.append('..')
15 |
16 | import measurement_chain
17 | import plotting
18 | import calculation
19 | import generation
20 | import ir_imitation
21 | import matplotlib.pyplot as plt
22 | import windows
23 | from scipy.signal import lfilter
24 | import numpy as np
25 |
26 |
27 | # Parameters of the measuring system
28 |
29 | fs = 44100
30 |
31 | fstart = 1
32 | fstop = 22050
33 | duration = 1
34 | pad = 4
35 |
36 | # Generate excitation signal
37 |
38 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
39 | N = len(excitation)
40 |
41 |
42 | # Noise in measurement chain
43 |
44 | awgn = -30
45 | noise_system = measurement_chain.additive_noise(awgn)
46 |
47 | # FIR-Filter-System
48 |
49 | # FIR-Filter-System
50 |
51 | f_low = 5000
52 | f_high = 6000
53 | order = 2
54 |
55 | bandstop_system = measurement_chain.bandstop(f_low, f_high, fs, order)
56 |
57 | # Combinate system elements
58 |
59 | system = measurement_chain.chained(bandstop_system, noise_system)
60 |
61 | # Lists
62 | beta = 7
63 | fade_in = 0
64 | fade_out_list = np.arange(0, 1001, 1)
65 | t_noise = 0.004
66 |
67 | # Spectrum of bandstop for reference
68 |
69 | bandstop_f = calculation.butter_bandstop(f_low, f_high, fs, N * 2 + 1, order)
70 |
71 |
72 | def get_results(fade_out):
73 | excitation_windowed = excitation * windows.window_kaiser(N,
74 | fade_in,
75 | fade_out,
76 | fs, beta)
77 | excitation_windowed_zeropadded = generation.zero_padding(
78 | excitation_windowed, pad, fs)
79 | excitation_zeropadded = generation.zero_padding(excitation, pad, fs)
80 | system_response = system(excitation_windowed_zeropadded)
81 | ir = calculation.deconv_process(excitation_zeropadded,
82 | system_response,
83 | fs)
84 | return ir
85 |
86 |
87 | with open("log_sweep_kaiser_window_script4_1.txt", "w") as f:
88 | for fade_out in fade_out_list:
89 | ir = get_results(fade_out)
90 | snr = calculation.pnr_db(ir[0], ir[t_noise * fs:pad * fs])
91 | spectrum_distance = calculation.vector_distance(
92 | bandstop_f, np.fft.rfft(ir[:pad * fs]))
93 | f.write(
94 | str(fade_out) + " " + str(snr) +
95 | " " + str(spectrum_distance) + " \n")
96 |
--------------------------------------------------------------------------------
/log_sweep_kaiser_window_script4/merge_scripts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | """ Script to merge scripts"""
3 |
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 |
7 | script4 = np.genfromtxt('log_sweep_kaiser_window_script4.txt')
8 |
9 | script4_1 = np.genfromtxt('log_sweep_kaiser_window_script4_1.txt')
10 |
11 | fade_out_list = script4[:, 0]
12 |
13 | # Script4
14 |
15 | pnr_list = script4[:, 1]
16 | spectrum_distance_list = script4[:, 2]
17 |
18 | # Script4_1 (unwindowed deconvolution)
19 |
20 | pnr_unwindowed_deconvolution_list = script4_1[:, 1]
21 | spectrum_distance_unwindowed_deconvolution_list = script4_1[:, 2]
22 |
23 |
24 | plt.plot(fade_out_list, pnr_list, label='Deconvolution: Excitation windowed')
25 |
26 | plt.plot(
27 | fade_out_list,
28 | pnr_unwindowed_deconvolution_list,
29 | label='Deconvolution: Excitation unwindowed')
30 | plt.grid()
31 | plt.title('Peak to noise ratio depending on Fade out')
32 | plt.xlabel('Fade out / ms')
33 | plt.ylabel('Peak to noise ratio / dB')
34 | plt.ticklabel_format(useOffset=False)
35 | plt.legend(loc='upper right')
36 | plt.xlim([-10, 1000])
37 | plt.savefig('pnr.png')
38 | plt.close()
39 |
40 | NFFT_bandstop = 88201
41 | max_measurement = 362.799629307
42 |
43 | plt.plot(
44 | fade_out_list,
45 | -10 * np.log10(1 / NFFT_bandstop * np.abs(
46 | np.asarray(spectrum_distance_list) / max_measurement)),
47 | label='Deconvolution: Excitation windowed')
48 |
49 | plt.plot(fade_out_list,
50 | -10 * np.log10(1 / NFFT_bandstop * np.abs(np.asarray(spectrum_distance_unwindowed_deconvolution_list) /
51 | max_measurement)), label='Deconvolution: Excitation unwindowed')
52 |
53 |
54 | plt.grid()
55 | plt.title('Spectrum Distance depending on Fade in')
56 | plt.xlabel('Fade out / ms')
57 | plt.ylabel('(Spectrum Distance / max(Spectrum Distance)) / dB')
58 | plt.ticklabel_format(useOffset=False)
59 | plt.legend(loc='upper right')
60 | plt.xlim([-10, 1000])
61 | plt.savefig('spectral_distance.png')
62 |
--------------------------------------------------------------------------------
/log_sweep_rect_window/log_sweep_rect_window.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of windowing of sweep signals when using a
4 | Rect Window.
5 |
6 | """
7 |
8 |
9 | import sys
10 | sys.path.append('..')
11 |
12 | import measurement_chain
13 | import plotting
14 | import calculation
15 | import generation
16 | import matplotlib.pyplot as plt
17 | import windows
18 | from scipy.signal import lfilter
19 | import numpy as np
20 |
21 |
22 | # Parameters of the measuring system
23 |
24 | fs = 44100
25 |
26 | fstart = 1
27 | fstop = 22050
28 | duration = 1
29 | pad = 4
30 |
31 | # Generate excitation signal
32 |
33 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
34 | N = len(excitation)
35 |
36 |
37 | # Noise in measurement chain
38 |
39 | noise_level_db = -20.
40 | noise = measurement_chain.additive_noise(noise_level_db)
41 |
42 | # FIR-Filter-System
43 |
44 | dirac_system = measurement_chain.convolution([1.0])
45 |
46 | # Combinate system elements
47 |
48 | system = measurement_chain.chained(dirac_system, noise)
49 |
50 |
51 | def get_results():
52 | akf = np.correlate(excitation, excitation, 'full')
53 | plotting.plot_time(akf,
54 | scale='db',
55 | title='AKF log. Sweep with Rect Window')
56 | plt.savefig('akf_log_sweep_rect.png')
57 | plt.close()
58 | excitation_zeropadded = generation.zero_padding(
59 | excitation, pad, fs)
60 | system_response = system(excitation_zeropadded)
61 | ir = calculation.deconv_process(excitation_zeropadded,
62 | system_response,
63 | fs)
64 | return calculation.snr_db(ir[0], ir[1:4 * fs]), akf.max()
65 |
66 |
67 | with open("log_sweep_rect_window.txt", "w") as f:
68 | snr, akf_max = get_results()
69 | f.write("AKF_max(dB): " +
70 | str(plotting._db_calculation(akf_max)) +
71 | " SNR(dB): " + str(snr) + " \n")
72 |
--------------------------------------------------------------------------------
/measurement_chain.py:
--------------------------------------------------------------------------------
1 | from scipy.signal import butter, lfilter, fftconvolve
2 | import numpy as np
3 | import generation
4 | import calculation
5 |
6 |
7 | def bandpass(lower_bound, higher_bound, fs, order):
8 | def inner(data):
9 | b, a = _butter_bandpass(lower_bound, higher_bound, fs, order)
10 | return lfilter(b, a, data)
11 | inner.name = "{}.-order bandpass with f_L = {} Hz, f_H = {} Hz".format(
12 | order, lower_bound, higher_bound)
13 | inner.filename = "bp{}_{}_{}".format(order, lower_bound, higher_bound)
14 | return inner
15 |
16 |
17 | def bandstop(lower_bound, higher_bound, fs, order):
18 | def inner(data):
19 | b, a = _butter_bandstop(lower_bound, higher_bound, fs, order)
20 | return lfilter(b, a, data)
21 | inner.name = "{}.-order bandstop with f_L = {} Hz, f_H = {} Hz".format(
22 | order, lower_bound, higher_bound)
23 | inner.filename = "bs{}_{}_{}".format(order, lower_bound, higher_bound)
24 | return inner
25 |
26 |
27 | def additive_noise(noise_level_db, seed=1):
28 | def inner(data):
29 | return data + calculation.awgn_noise(noise_level_db, len(data), seed)
30 | inner.name = "additive noise with {} dB noise level".format(
31 | noise_level_db)
32 | inner.filename = "{}noise".format(noise_level_db)
33 | return inner
34 |
35 |
36 | def lowpass(cutoff, fs, order):
37 | def inner(data):
38 | b, a = _butter_lowpass(cutoff, fs, order=order)
39 | return lfilter(b, a, data)
40 | inner.name = "lowpass-filter with fc = {} and {}.order".format(
41 | cutoff, order)
42 | inner.filename = "lpf_fc{}_order{} ".format(cutoff, order)
43 | return inner
44 |
45 |
46 | def highpass(cutoff, fs, order):
47 | def inner(data):
48 | b, a = _butter_highpass(cutoff, fs, order=order)
49 | return lfilter(b, a, data)
50 | inner.name = "high-filter with fc = {} and {}.order".format(
51 | cutoff, order)
52 | inner.filename = "hpf_fc{}_order{} ".format(cutoff, order)
53 | return inner
54 |
55 |
56 | def add_gain(gain_level_db):
57 | def inner(data):
58 | return 10 ** (gain_level_in_dB / 20) * data
59 | inner.name = "add {} dB to the signal".format(gain_level_db)
60 | inner.filename = "addgain{}dB".format(gain_level_db)
61 | return inner
62 |
63 |
64 | def moving_average(N):
65 | # for more information:
66 | # http://stackoverflow.com/questions/13728392/moving-average-or-running-mean
67 | def inner(data):
68 | cumsum = np.cumsum(np.insert(data, 0, 0))
69 | return (cumsum[N:] - cumsum[:-N]) / N
70 | inner.name = "moving average filter with {} samples".format(N)
71 | inner.filename = "maf{}".format(N)
72 | return inner
73 |
74 |
75 | def convolution(ir):
76 | def inner(data):
77 | return fftconvolve(data, ir)[:len(data)]
78 | inner.name = "{}".format("IR")
79 | inner.filename = "{}".format("IR")
80 | return inner
81 |
82 |
83 | # Help functions
84 |
85 |
86 | def chained(*systems):
87 | def inner(arg):
88 | for system in systems:
89 | arg = system(arg)
90 | return arg
91 | inner.name = " and ".join([x.name for x in systems])
92 | return inner
93 |
94 |
95 | def _butter_lowpass(cutoff, fs, order):
96 | wc = cutoff / (fs / 2)
97 | b, a = butter(order, wc, btype='lowpass')
98 | return b, a
99 |
100 |
101 | def _butter_highpass(cutoff, fs, order):
102 | wc = cutoff / (fs / 2)
103 | b, a = butter(order, wc, btype='highpass')
104 | return b, a
105 |
106 |
107 | def _butter_bandpass(lower_bound, higher_bound, fs, order):
108 | wl = lower_bound / (fs / 2)
109 | wh = higher_bound / (fs / 2)
110 | b, a = butter(order, [wl, wh], btype='bandpass')
111 | return b, a
112 |
113 |
114 | def _butter_bandstop(lower_bound, higher_bound, fs, order):
115 | wl = lower_bound / (fs / 2)
116 | wh = higher_bound / (fs / 2)
117 | b, a = butter(order, [wl, wh], btype='bandstop')
118 | return b, a
119 |
--------------------------------------------------------------------------------
/peak_to_noise_ratio/peak_to_noise_ratio.py:
--------------------------------------------------------------------------------
1 | import sys
2 | sys.path.append('..')
3 |
4 | import calculation
5 | import random
6 | import plotting
7 | import generation
8 | import ir_imitation
9 | import matplotlib.pyplot as plt
10 | import matplotlib.patches as mpatches
11 | import numpy as np
12 |
13 |
14 | # IR parameters
15 | fs = 44100
16 | ir_duration = 2
17 | ir_noise_level = -15
18 | ir_db_decay = -200
19 |
20 | # AWGN
21 | awgn = -50
22 |
23 | t = calculation.start_time_noise_floor(ir_noise_level, ir_db_decay, awgn)
24 |
25 | ir = ir_imitation.exponential_decay(ir_duration, ir_db_decay,
26 | ir_noise_level, fs, seed=1)
27 | ir_awgn = ir + calculation.awgn_noise(awgn, len(ir), seed=1)
28 |
29 |
30 | plotting.plot_time(ir, fs)
31 | plt.xlim([-0.02, 2])
32 | plt.savefig('ir.png')
33 | plt.close()
34 |
35 |
36 | plotting.plot_time(ir, fs, scale='db')
37 | plt.xlim([-0.02, 2])
38 | plt.savefig('ir_db.png')
39 | plt.close()
40 |
41 |
42 | plotting.plot_time(ir_awgn, fs)
43 | plt.xlim([-0.02, 2])
44 | plt.savefig('ir_awgn.png')
45 | plt.close()
46 |
47 |
48 | plotting.plot_time(ir_awgn, fs, scale='db')
49 | plt.xlim([-0.02, 2])
50 | plt.savefig('ir_awgn_db.png')
51 | plt.close()
52 |
53 |
54 | pnr = calculation.peak_to_noise_ratio(ir_awgn, t*fs, fs)
55 | print(pnr)
56 |
--------------------------------------------------------------------------------
/peak_to_noise_ratio/pnr_depends_on_averaging_length.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import sys
3 | sys.path.append('..')
4 |
5 | import calculation
6 | import random
7 | import plotting
8 | import generation
9 | import ir_imitation
10 | import matplotlib.pyplot as plt
11 | import matplotlib.patches as mpatches
12 | import numpy as np
13 |
14 |
15 | # IR parameters
16 | fs = 44100
17 | ir_duration = 2
18 | ir_noise_level = -15
19 | ir_db_decay = -200
20 |
21 | # AWGN
22 | awgn = -50
23 |
24 | t = calculation.start_time_noise_floor(ir_noise_level, ir_db_decay, awgn)
25 |
26 | acc = 0
27 | ir_array = []
28 |
29 | mean_length_list = np.arange(1, 101)
30 |
31 | for i in range(1, max(mean_length_list) + 1):
32 | ir = ir_imitation.exponential_decay(ir_duration, ir_db_decay,
33 | ir_noise_level, fs, seed=i)
34 | ir_awgn = ir + calculation.awgn_noise(awgn, len(ir), seed=i)
35 | acc += ir_awgn
36 | if i in mean_length_list:
37 | ir_array.append(acc/i)
38 |
39 | pnr_array = []
40 |
41 |
42 | for i in range(len(mean_length_list)):
43 | pnr_array.append(calculation.peak_to_noise_ratio(ir_array[i], t*fs, fs))
44 |
45 |
46 | plt.plot(mean_length_list, pnr_array)
47 | plt.ticklabel_format(useOffset=False)
48 | plt.title('SNR depends on Averaging Length')
49 | plt.xlabel('Averaging Length')
50 | plt.ylabel('PNR / dB')
51 | plt.grid(True)
52 | plt.savefig('pnr_depends_on_averaging_length.png')
53 |
--------------------------------------------------------------------------------
/peak_to_noise_ratio/pnr_depends_on_excitation_length.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """The influence of excitation length.
4 |
5 | """
6 |
7 |
8 | import sys
9 | sys.path.append('..')
10 |
11 | import measurement_chain
12 | import plotting
13 | import calculation
14 | import ir_imitation
15 | import generation
16 | import matplotlib.pyplot as plt
17 | import windows
18 | from scipy.signal import lfilter, fftconvolve
19 | import numpy as np
20 |
21 |
22 | # Parameters of the measuring system
23 |
24 | fs = 44100
25 |
26 | fstart = 1
27 | fstop = 22050
28 | duration = 1
29 | pad = 4
30 |
31 | duration_list = np.arange(1, 50, 1)
32 |
33 | # Noise in measurement chain
34 |
35 | noise_level_db = -13.5
36 | noise = measurement_chain.additive_noise(noise_level_db)
37 |
38 | # FIR-Filter-System
39 |
40 | dirac_system = measurement_chain.convolution([1.0])
41 |
42 | # Combinate system elements
43 |
44 | system = measurement_chain.chained(dirac_system, noise)
45 |
46 |
47 | def get_results(duration):
48 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
49 | excitation_zeropadded = generation.zero_padding(excitation,
50 | duration + pad, fs)
51 | system_response = system(excitation_zeropadded)
52 | ir = calculation.deconv_process(excitation_zeropadded,
53 | system_response,
54 | fs)
55 | return ir
56 |
57 | pnr_array = []
58 |
59 | with open("pnr_depends_on_excitation_length.txt", "w") as f:
60 | for duration in duration_list:
61 | ir = get_results(duration)
62 | pnr = calculation.pnr_db(ir[0], ir[1:4 * fs])
63 | pnr_array.append(pnr)
64 | f.write(
65 | str(duration) + " " + str(pnr) + " \n")
66 |
67 | plt.plot(duration_list, pnr_array)
68 | plt.ticklabel_format(useOffset=False)
69 | plt.title('PNR depends on Averaging Length')
70 | plt.xlabel('Duration Length / s')
71 | plt.ylabel('PNR / dB')
72 | plt.grid(True)
73 | xticks = [1, 10, 20, 30, 40, 50]
74 | plt.xticks(xticks)
75 | plt.xlim([1, 50])
76 | plt.savefig('pnr_depends_on_averaging_length')
77 |
--------------------------------------------------------------------------------
/plotting.py:
--------------------------------------------------------------------------------
1 | """Plot Functions."""
2 |
3 | from __future__ import division
4 | import numpy as np
5 | import matplotlib.pyplot as plt
6 | import calculation
7 |
8 |
9 | def plot_time(signal,
10 | fs=None,
11 | ax=None,
12 | scale='linear',
13 | sides='onesided',
14 | title=None,
15 | label=None,
16 | **kwargs):
17 | """Plot in Time Domain.
18 |
19 | """
20 | if ax is None:
21 | ax = plt.gca()
22 | if fs is None:
23 | fs = 1
24 | ax.set_xlabel("Samples")
25 | else:
26 | ax.set_xlabel("t / s")
27 | t = _time_vector_onesided(signal, fs)
28 | if scale == 'linear':
29 | ax.set_ylabel('Amplitude (linear)')
30 | elif scale == 'db':
31 | signal = _db_calculation(signal)
32 | ax.set_ylabel('Amplitude / dB')
33 | else:
34 | raise NameError("Invalid scale")
35 | if sides == 'onesided':
36 | ax.plot(t, signal, label=label, linewidth=2.0)
37 | elif sides == 'twosided':
38 | ax.plot(
39 | _time_vector_twosided(signal,
40 | fs),
41 | np.fft.fftshift(signal),
42 | label=label, linewidth=1.0)
43 | else:
44 | raise NameError("Invalid sides")
45 | if title is not None:
46 | ax.set_title(title)
47 | ax.grid(True)
48 | ax.ticklabel_format(useOffset=False)
49 | return ax
50 |
51 |
52 | def plot_freq(signal,
53 | fs,
54 | ax=None,
55 | scale='linear',
56 | mode='magnitude',
57 | stem=False,
58 | sides=None,
59 | title=None,
60 | **kwargs):
61 | """Plot in Frequency Domain.
62 |
63 | """
64 | result, freqs = _spectral_helper(
65 | signal, fs, scale=scale, mode=mode, **kwargs)
66 |
67 | if ax is None:
68 | ax = plt.gca()
69 |
70 | if scale == 'linear':
71 | ax.set_ylabel('Magnitude (linear)')
72 | elif scale == 'db':
73 | ax.set_ylabel('Magnitude / dB')
74 | else:
75 | raise NameError("Invalid scale")
76 | if mode == 'magnitude':
77 | if title is not None:
78 | ax.set_title(title)
79 | else:
80 | ax.set_title('Magnitude Spectrum')
81 | elif mode == 'phase':
82 | if title is not None:
83 | ax.set_title(title)
84 | else:
85 | ax.set_title('Phase Spectrum')
86 | ax.set_ylabel('Phase / rad')
87 | elif mode == 'psd':
88 | if title is not None:
89 | ax.set_title(title)
90 | else:
91 | ax.set_title('Power Density Spectrum')
92 | ax.set_ylabel('dB / Hz')
93 | else:
94 | raise NameError("Invalid mode")
95 | if stem is False:
96 | ax.plot(freqs, result, linewidth=1.4)
97 | else:
98 | ax.stem(freqs, result, linewidth=1.4)
99 | ax.set_xlabel('f / Hz')
100 | ax.grid(True)
101 | ax.ticklabel_format(useOffset=False)
102 | return ax
103 |
104 |
105 | def plot_tf(signal, fs, config='time+freq', **kwargs):
106 | """Subplot of Time and Frequency Domain.
107 |
108 | """
109 | fig, (ax1, ax2) = plt.subplots(2, 1)
110 | plt.subplots_adjust(hspace=0.6)
111 | if config == 'time+freq':
112 | plot_time(signal, fs, ax1)
113 | plot_freq(signal, fs, ax2, scale='db')
114 | ax2.set_xscale('log')
115 | elif config == 'mag+pha':
116 | plot_freq(signal, fs, ax1, scale='db')
117 | plot_freq(signal, fs, ax2, mode='phase')
118 | else:
119 | raise NameError("Invalid config")
120 |
121 |
122 | def _spectral_helper(signal, fs, scale=None, mode=None, sides=None, **kwargs):
123 |
124 | result = np.fft.rfft(signal)
125 | freqs = np.fft.rfftfreq(len(signal), 1 / fs)
126 |
127 | if mode == 'psd':
128 | result = np.abs(result) ** 2 / (len(signal) * fs)
129 | if mode is None or mode == 'magnitude':
130 | result = 2 / len(signal) * np.abs(result)
131 | if mode == 'phase':
132 | result = np.angle(result)
133 | result = np.unwrap(result)
134 | if scale == 'db' and mode != 'phase':
135 | result = _db_calculation(result)
136 | elif mode == 'psd':
137 | result = result / 2
138 | return result, freqs
139 |
140 |
141 | def _db_calculation(signal):
142 | return 20 * np.log10(np.abs(signal))
143 |
144 |
145 | def _time_vector_onesided(signal, fs):
146 | return np.arange(len(signal)) / fs
147 |
148 |
149 | def _time_vector_twosided(signal, fs):
150 | return np.linspace(-len(signal) // 2, len(signal) // 2, len(signal)) / fs
151 |
--------------------------------------------------------------------------------
/software_sweep.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Simulation of Impulse Response Measurements\n",
8 | "The software (https://github.com/franzpl/sweep) has been written in the context of my bachelor thesis with the topic \"On the influence of windowing of sweep signals for room impulse measurements\" at the University of Rostock.\n",
9 | "Impulse responses are an important tool to determine acoustic properties of a Device Under Test. The main requirement is that all desired frequencies cover the interesting frequency range with sufficient energy. Therefore, sweep signals and white noise are usally favored to excite DUT's. In this context sweep signals and LTI-Systems were used. However, the design of sweep signals in time domain causes ripple in the excitation spectrum at the start and stop frequency. It is possible to reduce ripple with the use of convenient windows. With this software, you can evaluate the effect of windowing of sweep signals on impulse responses under the influence of noise. This Ipython3 Notebook shows an examplary impulse response measurement (Sweep -> DUT -> System Response -> Impulse Response -> Quality of Impulse Response). You can also use the software for real measurements, because measurement module and simulation module are seperated strictly.
\n",
10 | "Let's start the simulation of an impulse response measurement! "
11 | ]
12 | },
13 | {
14 | "cell_type": "markdown",
15 | "metadata": {},
16 | "source": [
17 | "# Imports\n",
18 | "First, you need imports from Python and the software."
19 | ]
20 | },
21 | {
22 | "cell_type": "markdown",
23 | "metadata": {},
24 | "source": [
25 | "### Python Modules"
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": 21,
31 | "metadata": {
32 | "collapsed": false
33 | },
34 | "outputs": [],
35 | "source": [
36 | "%matplotlib inline\n",
37 | "import numpy as np\n",
38 | "import matplotlib.pyplot as plt"
39 | ]
40 | },
41 | {
42 | "cell_type": "markdown",
43 | "metadata": {},
44 | "source": [
45 | "### Software Modules"
46 | ]
47 | },
48 | {
49 | "cell_type": "code",
50 | "execution_count": 22,
51 | "metadata": {
52 | "collapsed": false
53 | },
54 | "outputs": [],
55 | "source": [
56 | "import generation\n",
57 | "import plotting\n",
58 | "import ir_imitation\n",
59 | "import calculation\n",
60 | "import windows\n",
61 | "import measurement_chain"
62 | ]
63 | },
64 | {
65 | "cell_type": "markdown",
66 | "metadata": {},
67 | "source": [
68 | "# Excitation\n",
69 | "Than, you have to design the excitation signal.\n",
70 | "## Excitation Parameters"
71 | ]
72 | },
73 | {
74 | "cell_type": "code",
75 | "execution_count": 23,
76 | "metadata": {
77 | "collapsed": false
78 | },
79 | "outputs": [],
80 | "source": [
81 | "fs = 44100\n",
82 | "fstart = 1\n",
83 | "fstop = 22050\n",
84 | "duration = 1 # seconds\n",
85 | "pad = 5 # attach 5 seconds zeros to excitation signal"
86 | ]
87 | },
88 | {
89 | "cell_type": "markdown",
90 | "metadata": {},
91 | "source": [
92 | "## Excitation Signal\n",
93 | "Generate a excitation signal with the excitation parameters above."
94 | ]
95 | },
96 | {
97 | "cell_type": "code",
98 | "execution_count": 24,
99 | "metadata": {
100 | "collapsed": false
101 | },
102 | "outputs": [],
103 | "source": [
104 | "excitation = generation.log_sweep(fstart, fstop, duration, fs)"
105 | ]
106 | },
107 | {
108 | "cell_type": "markdown",
109 | "metadata": {},
110 | "source": [
111 | "### Plot Time Domain"
112 | ]
113 | },
114 | {
115 | "cell_type": "code",
116 | "execution_count": 25,
117 | "metadata": {
118 | "collapsed": false
119 | },
120 | "outputs": [
121 | {
122 | "data": {
123 | "image/png": "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\n8lDkAAAAAElFTkSuQmCC\n",
124 | "text/plain": [
125 | ""
126 | ]
127 | },
128 | "metadata": {},
129 | "output_type": "display_data"
130 | }
131 | ],
132 | "source": [
133 | "plotting.plot_time(excitation, fs);"
134 | ]
135 | },
136 | {
137 | "cell_type": "markdown",
138 | "metadata": {},
139 | "source": [
140 | "### Plot Frequency Domain\n",
141 | "As shown in this figure, the excitation spectrum is characterized by ripple at the start and stop frequency."
142 | ]
143 | },
144 | {
145 | "cell_type": "code",
146 | "execution_count": 26,
147 | "metadata": {
148 | "collapsed": false
149 | },
150 | "outputs": [
151 | {
152 | "data": {
153 | "image/png": "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\n",
154 | "text/plain": [
155 | ""
156 | ]
157 | },
158 | "metadata": {},
159 | "output_type": "display_data"
160 | }
161 | ],
162 | "source": [
163 | "plotting.plot_freq(excitation, fs, scale='db')\n",
164 | "plt.xscale('log')\n",
165 | "plt.xlim([1, fs/2])\n",
166 | "plt.ylim([-55, -14]);"
167 | ]
168 | },
169 | {
170 | "cell_type": "markdown",
171 | "metadata": {},
172 | "source": [
173 | "## Window Parameters\n",
174 | "A window reduces the ringing artifacts. Fade in and fade out parameters of the window can help to produce a smoother spectrum. "
175 | ]
176 | },
177 | {
178 | "cell_type": "code",
179 | "execution_count": 27,
180 | "metadata": {
181 | "collapsed": false
182 | },
183 | "outputs": [],
184 | "source": [
185 | "fade_in = 50 # ms\n",
186 | "fade_out = 10 # ms\n",
187 | "beta = 7 # kaiser window"
188 | ]
189 | },
190 | {
191 | "cell_type": "markdown",
192 | "metadata": {},
193 | "source": [
194 | "## Windowed Sweep\n"
195 | ]
196 | },
197 | {
198 | "cell_type": "code",
199 | "execution_count": 28,
200 | "metadata": {
201 | "collapsed": false
202 | },
203 | "outputs": [],
204 | "source": [
205 | "window = windows.window_kaiser(len(excitation), fade_in, fade_out, fs, beta)\n",
206 | "excitation_windowed = window * excitation"
207 | ]
208 | },
209 | {
210 | "cell_type": "markdown",
211 | "metadata": {},
212 | "source": [
213 | "## Zeropadding\n",
214 | "Zeropadding makes space for the recording signal. "
215 | ]
216 | },
217 | {
218 | "cell_type": "code",
219 | "execution_count": 29,
220 | "metadata": {
221 | "collapsed": false
222 | },
223 | "outputs": [],
224 | "source": [
225 | "excitation_windowed_zeropadded = generation.zero_padding(excitation_windowed, pad, fs)"
226 | ]
227 | },
228 | {
229 | "cell_type": "markdown",
230 | "metadata": {},
231 | "source": [
232 | "### Plot Zeropadded Windowed Sweep"
233 | ]
234 | },
235 | {
236 | "cell_type": "code",
237 | "execution_count": 30,
238 | "metadata": {
239 | "collapsed": false
240 | },
241 | "outputs": [
242 | {
243 | "data": {
244 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYkAAAEPCAYAAAC3NDh4AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3X+0XHV57/H3k18EQuAYQQIhEEAoRnTxS0QoMiJSEET0\napGuuzC4al32cttV21u02gv3rtVb8d6qF7VKVX54i2JLFVGhFJXBHygaIBISoKDEJvyGEAIESEKe\n+8fe45kMs2e+58zs853v93xea82avWf2mXmelaz9zPf77B/m7oiIiHQzI3YAIiIyulQkRESkkoqE\niIhUUpEQEZFKKhIiIlJJRUJERCpFLRJmdomZPWJmK3tsc5GZ3WtmvzSzw6YyPhGR6S72SOJS4OSq\nN83srcAr3f1A4I+Az09VYCIiErlIuPuPgCd7bHI6cHm57S3AmJntMRWxiYhI/JFEP4uAtW3r64C9\nI8UiIjLtjHqRALCOdV1HRERkisyKHUAfDwCL29b3Ll/bjpmpcIiITIK7d/4Q386ojySuAc4GMLOj\ngQ3u/ki3Dd19u8fv/q5TDDqce+7xl7zfeu+jHx1fHtXH+eef/5L4c3nknJvyS/+Re34hoo4kzOxr\nwPHAbma2FjgfmA3g7he7+7Vm9lYzuw94Fjgn9LPvvXd8+YEH4KCDum83Y9TLJLBmzZrYIdQm59xA\n+aUu9/xCRC0S7n5WwDbnTvRzt22Dxx4bX1+/vnpb6znQEhGZ3hL4HT1x69cXhaJ9vUoKI4mzz14W\nO4TaLFu2LHYItVJ+acs9vxAJ7CInrn0UAemPJI49thE7hNo0Go3YIdRK+aUt9/xCTIsi8cQT1dum\nMJK46aZm7BBq02w2Y4dQK+WXttzzC5HALnLiOovEM89sv97e1E9hJCEiEkvWRWL27OL52We3f3/L\nlvHlrVunJqZBvPGNjdgh1Cb34bzyS1vu+YXIukgsWVI8dxaJzZvHl9sb3CIisr0si8SGDcXz4vJc\n7c4i8eKL3ZdH1Q9/2IwdQm1yn/NVfmnLPb8QWRaJjRuL54ULi+fOItE+etBIQkSkWpZF4umni+c9\n9yyeexWJFEYS6kmkS/mlLff8QmRZJFojiVaR6Dy6SSMJEZEwWRaJ1kgiZLophZGEehLpUn5pyz2/\nEFkWic6RROpFQkQkFgu9XOwoMzNvz2P//eH+++GOO+C1r4Udd4RNm8a3X7du/Minc8+Fz352igOe\noOeeg7lzY0chIrkxMzzx+0lMSmu6affdi+fnn9/+LGuNJEREwmRZJFrTTWNjMHNmUSDaz6xOrXGt\nnkS6lF/acs8vRHZF4oUXijOqZ8+GHXYoHq3XWzSSEBEJk11P4vHHi2mmBQuKq78uWABPPllcqmO3\n3Yrt77sPDjywWH7f++CSSyIFHkg9CRGpw7TsSbT6EbvsUjy3dq4aSYiITFx2RaLVj5g/v3juN92k\nnkRcuc/5Kr+05Z5fiOyKROdIoluRSO0CfyIisWRXJDpHEq3ppuefH98mtZGErt2ULuWXttzzC5Fd\nkWiNJEKnmzSSEBGplm2R6DXdlNpIQj2JdCm/tOWeX4jsikRV47pqukkjCRGRatkViYkeApvCSEI9\niXQpv7Tlnl+I7IrERA+B1UhCRKRadkVioofApjCSUE8iXcovbbnnFyK7IjHRQ2A1khARqZZdkeg8\nBHbOnOJ58+bxbdSTGB25z/kqv7Tlnl+IbItEa7pp9uziecuW8W00khARCZNdkeicbupXJFK4CK56\nEulSfmnLPb8Q2RWJiY4kUigSIiKxZFckJjqSSKEnceyxjdgh1Cb3OV/ll7bc8wuRXZEIGUm09yFS\nGEl873uxIxCR6SqrIrF5c3E+xKxZ4+dH5DCSuP32ZuwQapP7nK/yS1vu+YXIqki0H/5q5Q351JMQ\nEZm8LItEa6oJxotEyudJvPrVjdgh1Cb3OV/ll7bc8wuRVZHobFqDRhIiIoPIqkh0G0m0zrhOuSex\nalUzdgi1yX3OV/mlLff8QmRVJDSSEBEZrqyKRK+eRMojiaVLG7FDqE3uc77KL2255xciqyIROpJI\n7TwJjXhFJJasikTnFWAhj5HEr37VjB1CbXKf81V+acs9vxBZFYnWSGIi000pjCRERGLJqkjkOpJY\nuLARO4Ta5D7nq/zSlnt+IbIsEhpJiIgMR1ZFYjKHwKYwknj44WbsEGqT+5yv8ktb7vmFiFokzOxk\nM7vbzO41s/O6vN8ws6fM7Pby8bFen6eRhIjIcM2K9cVmNhP4LHAi8ADwCzO7xt3v6tj0Jnc/PeQz\ne40k2q/d1H4IbAojCfUk0qX80pZ7fiFijiSOAu5z9zXuvgW4Enh7l+0s9AO7Na77XZZDIwkRkWox\ni8QiYG3b+rrytXYOHGNmvzSza81saa8PzPXoJvUk0qX80pZ7fiGiTTdRFIB+bgMWu/smMzsFuBo4\nqNuGy5Yt45FHlgDw1a+Ocfzxh9JoNMoi0SynohoA3HNPs/yrRjmSGF8vjNb6+vUraDbHh76t/7ha\n17rWtT6R9WazyWWXXQbAkiVLCGEeab7FzI4GLnD3k8v1jwDb3P3CHn9zP3CEu6/veN3dnV13LfoS\nTz4JY2PFe2vXwj77wKJFsG5d8dqnPgUf+lCxvO++8JvfDD29oTr7bLj88thRiEhuzAx37zmlH3O6\naTlwoJktMbM5wJnANe0bmNkeZsU95szsKIqitv6lH1X0Fp59tlieN2/89RyObkohRhHJU7Qi4e5b\ngXOB64HVwNfd/S4z+4CZfaDc7F3ASjNbAXwaeE/V523ZUhy1NHv2eGEA9SRGXWsonCvll7bc8wsR\nsyeBu18HXNfx2sVty58DPhfyWa1RxE47bf96DleBFRGJJZszrjdtKp7bp5ogj5GEzpNIl/JLW+75\nhcimSFSNJGaVY6WqE+g0khARqZZdkegcScycWTxv3TpeENqLRHvxGFXqSaRL+aUt9/xCZFMkWtNN\nnSOJGTPAygO8WsUhtSKRQowikqdsikTVSAJeOuWUWk/izjsbsUOoTe5zvsovbbnnFyKbIlHVuIbx\nIrF1a/GskYSISJhsikRV4xpeWiTad7op7IC3bGnGDqE2uc/5Kr+05Z5fiOyKRLeRRHvzGtIbSYiI\nxNLzZDozewXwbuCNwBKKi/L9Bvgh8M/u/mjdAYaqalxD7+mmFHoSs2c3YodQm9znfJVf2nLPL0Rl\nkTCzLwMHUJwR/QXgIYp7O+xJcS+IfzKz+9z9D6ci0H4m27jWSEJEpFqv6ab/6+4Nd7/Q3W9097vd\n/S53/4G7f9zdG8BFUxRnXzmPJNSTSJfyS1vu+YWoLBLufoeZzTSzK3ptU09YExcykuhWJEREpFrP\nxrW7vwjsa2Y7TFE8kzbZxnUK1JNIl/JLW+75hQi5Cuz9wI/N7BqgnNTB3f2T9YU1cSHTTa3+g/oQ\nIiJhQg6B/RXw3XLbnYH55WOk5Dzd9MQTzdgh1Cb3OV/ll7bc8wvRdyTh7hdMQRwDm2zjWkREqvUt\nEuW5En8JLAV2LF92dz+hzsAmKueeBDRiB1Cb3Od8lV/acs8vRMh00xXA3cD+wAXAGor7U4+UnKeb\nRERiCSkSL3f3LwGb3f0mdz8HGKlRBEyscZ1ekWjGDqA2uc/5Kr+05Z5fiJCjmzaXzw+b2WnAg8DL\n6gtpcjSSEBEZvpAi8TdmNgb8OfAZYBfgz2qNahJ6jSTUkxhduc/5Kr+05Z5fiJCjm75dLm5ghPdW\nExlJ6DwJEZEwfXsSZvY7ZvZ9M1tVrr/WzD5Wf2gTs2VLcavSOXNe+p56EqMr9zlf5Ze23PMLEdK4\n/iLwV4z3JlYCZ9UW0QDmzRu/n3U79SRERCYnpEjs5O63tFbc3YEt9YU0ed2mmiCHItGIHUBtcp/z\nVX5pyz2/ECFF4jEze2VrxczeRXFviZHTrWkNOTSuRUTiCCkS5wIXAweb2YMURzZ9sNaoJqnfSEI9\nidGT+5yv8ktb7vmFCDm66VfAm81sHjDD3Z+uP6zJqRpJpD/dJCISR8i1m+YC/4niHtczzcwoWhP/\ns+bYJiy0J5HeIbCN2AHUJvc5X+WXttzzCxFyMt23KM6RuBV4vt5wBqOehIjIcIX0JBa5+5nu/gl3\n/7vWo/bIJiHfo5uasQOoTe5zvsovbbnnFyKkSNxsZq+tPZIhyLdxLSISR8h003HAOWZ2P/BC+Zq7\n+8gVjnwb143YAdQm9zlf5Ze23PMLEVIkTqk9iiHJd7pJRCSOyukmM9ulXNxY8Rg5+Taum7EDqE3u\nc77KL2255xei10jia8CpwG2Ad3l/v1oiGsDOO3d/vbMnkd4hsCIicVQWCXc/tXxeMmXRDKhfkUh3\nJNGIHUBtcp/zVX5pyz2/EJVFwswO7/WH7n7b8MMZTL5FQkQkjl6HwH4S+Lsej5FTVSTUkxhduc/5\nKr+05Z5fiF7TTY0pjGMoNJIQERmuXkc3Hd/vj83sTcMNZzChjev0ikQjdgC1yX3OV/mlLff8QvQ6\nuultZva/ge8ByynuITEDWAgcCZwI3Fg+RoJGEiIiw1U5knD3vwDeDKwG3gL8NfBRiuJwJ/Amd//L\nqQgyVL5XgW3GDqA2uc/5Kr+05Z5fiJ5nXJf3jvjH8jHy5s/v/nr6jWsRkThCLvCXBDPYddfu76kn\nMbpyn/NVfmnLPb8Q2RSJBQvGRwydqnoSM7LJXkSkHtnsJl/+8ur3qorErJDLG46EZuwAapP7nK/y\nS1vu+YXoWyTMbJ6Z/bWZfbFcP9DMThvGl5vZyWZ2t5nda2bnVWxzUfn+L83ssKrP6lUkqnoSVSMP\nEREphIwkLgU2A8eU6w8CfzPoF5vZTOCzwMnAUuAsM3tVxzZvBV7p7gcCfwR8vurzFi+u/q70RxKN\n2AHUJvc5X+WXttzzCxFSJA5w9wspCgXu/uyQvvso4D53X+PuW4Argbd3bHM6cHn5vbcAY2a2R7cP\n23//6i+qalxrJCEi0lvIb+kXzGzH1oqZHcD4HeoGsQhY27a+Dnh9wDZ7A490ftgRR1R/UdV5EumM\nJJoccUQjdhC1ePrpJvPnN2KHURvll7bc8wsRspu8APhXYG8z+ypwLLBsCN/d7R4V3VjI31199TLu\nvHMJAGNjYxx66KG/HSquWtUEYOvWYv2554r1WbMa5V83y+dRXV/BbbeNUjxa17rW01xvApeV60sI\nYe7999VmthtwdLn6M3d/POjTe3/m0cAF7n5yuf4RYFs5tdXa5gtA092vLNfvBo5390c6Pst75XHD\nDXDSSXDiicXyHnvAo4/C3nvDunWDZjI1li+PHYGI5ObIIw137/whvp1e95M4gu1/tT9I8at+HzPb\nZwj3k1gOHGhmS8rPPhM4q2Oba4BzgSvLorKhs0CEqGpcp9ST6DWdJiJSl16N69Z9I/4euAX4IvAP\n5fLnBv1id99KUQCup7g+1Nfd/S4z+4CZfaDc5lrg12Z2H3Ax8MeT+a6qQ2BT6knkKvfj0JVf2nLP\nL0Tf+0mY2TeA97v7ynL9EOB/DOPL3f064LqO1y7uWD930O+pOropnSIhIhJH356Ema1296X9Xoup\nX0/i5z+H178eXve6YnnXXWHjRli6FFavnsJABxDQOhIRmRCzAXoSbe4wsy9RXAnWgD8AfjmE+KZM\n53RTeofAiojEEXIy3TkUPYM/Bf6kXD6nzqCGLf0zrpuxA6hN7nO+yi9tuecXou9u0t2fAz5ZPpKk\nM65FRCYnpCdxf5eX3d17XAhjavXrSdxzDxx8MBx0ULE8Zw5s2QJveAP89KdTGOgA1JMQkWEbVk/i\ndW3Lc4F3AT2uuTp60j8EVkQkjr49CXd/vO2xzt0/DZw6BbENTfrTTc3YAdQm9zlf5Ze23PML0fe3\ndMeZ1zOAI4Fkdq+wfePafXzqJp0iISISR0hPosl4kdgKrAH+j7vfU2tkE9CvJ/HQQ7DXXsU1mx54\noCgaZuPXckqBehIiMmzD6km8z91/3fHB+w0U2RRrn25qv7+17nEtItJbyG7yqsDXRlb7dFN7P8J6\n1s9R0owdQG1yn/NVfmnLPb8Qva4C+yqK24qOmdk7Kc62dmAXiqOcktF+dJNGEiIi4Sp7EmZ2BnAG\n8DaKS3a3PA1c6e431x9emH49iU2bYN48mDsXHn8cdt4ZdtoJTjgBvvOdKQx0AOpJiMiwDdSTcPer\ngavN7A3unsgpZ91V9STSmW4SEYmjcsLFzM4rF//AzD7T8bhoiuIbim49ibSmm5qxA6hN7nO+yi9t\nuecXotfRTa2LaN/a5b2kJj9axcB9/KxrjSRERPoLusf1qOvXkwCYPbsoEA8+WJwzsWABNBrwjW9M\nTYyDyuCfSURGzEA9CTP7do+/c3c/fdKRRTBrVlEkNm8u1tM6BFZEJI6Qe1xXPZLSOgy2VSTUkxgN\nuc/5Kr+05Z5fiF5HNzVby2a2A3AwsA24x9031x/acLWa11u2FM/qSYiI9Bdy7aZTgS8ArUtz7A98\nwN2vrTm2YCE9id12gyeegNtvh8MOg0WL4Ljj4MorpyjIAaknISLDNqxrN30SeJO731d+6AHAteUj\nGd2mmzSSEBHpLWRWfmOrQJR+DWysKZ7atKab1JMYLbnP+Sq/tOWeX4iQkcStZnYt8E/l+ruB5eX1\nnHD3JA4iVU9CRGTiQnoSl5WLrQ2tbRl3P6eWyCYgpCex//5w//1w3XVwyilwwAFw7LHwla9MUZAD\nUk9CRIZtKD0Jd182tIgi6pxu0nkSIiL99Z2VN7P9zexTZvZNM/t2+bim39+Nmm7TTepJxJf7nK/y\nS1vu+YUI6UlcDXwJ+DbFeRKQ2LWbIPXGtYhIHCFF4nl3T+qqr92kfQhsI3YAtWk0GrFDqJXyS1vu\n+YUIKRKfMbMLgOuBF1ovuvttdQVVh7Snm0RE4gjZTb4aeD/wcRK+dlO36aZ0RhLN2AHUJvc5X+WX\nttzzCxEykng3sF+K12tql/YF/kRE4gjZTa4EXlZ3IHVLeyTRiB1AbXKf81V+acs9vxAhI4mXAXeb\n2S8Y70kkeT8J2P48CY0kRER6C9lNng+8A/hfJNyTSPvopmbsAGqT+5yv8ktb7vmFCDnjutm+bmbH\nAWcBN9UUUy10noSIyMSFTDdhZodTFIbfB+4H/qXOoOqQ9gX+GrEDqE3uc77KL2255xei1z2uf4ei\nMJwJPAb8M8UFARtTE9pwaSQhIjJxvXaTdwGHA7/n7m90988AL05NWMOnnsRoyn3OV/mlLff8QvQq\nEu8EngN+aGZfMLM3U1wmPEkaSYiITFzlbtLdr3b3M4FDgB8BfwbsbmafN7OTpirAYUn7ENhG7ABq\nk/ucr/JLW+75hei7m3T3Z9z9Cnc/DVgM3A58uPbIhizt6SYRkTgm9Fva3de7+z+4+wl1BVSXtC/w\n14wdQG1yn/NVfmnLPb8QyewmB5X2ZTlEROKYNkUi7Qv8NWIHUJvc53yVX9pyzy9EMrvJQWkkISIy\ncdOuSKgnMVpyn/NVfmnLPb8QQZflGDYzWwB8HdgXWAP8vrtv6LLdGmAjxUl8W9z9qMl+Z6tIvFBe\nx1YjCRGR/mL9lv4wcIO7HwR8n+pDah1ouPthgxQIeGlPQudJjIbc53yVX9pyzy9ErN3k6cDl5fLl\nwBk9th3K7/20L/AnIhJHrCKxh7s/Ui4/AuxRsZ0D3zOz5Wb2/kG+MO3LcjRjB1Cb3Od8lV/acs8v\nRG09CTO7AVjY5a2Ptq+4u5uZV3zMse7+kJntDtxgZne7+4+6bbhs2TKWLFkCwNjYGIceeuhvh4rN\nZpPf/AagURaJJo8+Cocc0ij/ulk+j+r6CppNtssHtK51rWt9YuvNZpPLLrsM4Lf7y37MvWr/XB8z\nu5ui1/Cwme0J3OjuB/f5m/OBZ9z9JXfFMzPvl8cnPgHnnQe77w6PPQbvfS8sXVq8loII/0wikjkz\nw917TrzHmnC5Bnhvufxe4OrODcxsJzObXy7PA04CVk72C1M+T+KogVr2IiKTF6tIfBx4i5n9O3BC\nuY6Z7WVm3y23WQj8yMxWALcA33H3f5vsF7aObmo/BHZGIj2JTZuasUOoTWsonCvll7bc8wsR5TwJ\nd18PnNjl9QeBU8vlXwOHDus7U25cpzLiEZH8JLKbHFyrSGzbVjzPnJnOzndsrBE7hNq0mmu5Un5p\nyz2/ENOmSLSmm1o0khAR6S+R3eTgZnVMrKXUuH7qqWbsEGqT+5yv8ktb7vmFmNZFIpWRhIhILNNm\nN5nySGLBgkbsEGqT+5yv8ktb7vmFmDZFQj0JEZGJS2Q3ObiURxIbNjRjh1Cb3Od8lV/acs8vxLQu\nEqmMJEREYpk2u8nO6aaUzpNQTyJdyi9tuecXYtoUic6RREo3HUqlmIlIfhLZTQ6uW5FIZef74ovN\n2CHUJvc5X+WXttzzCzFtikS36aZURhKvfnXsCERkukpkNzm4zpHErFnpjCSWLm3EDqE2uc/5Kr+0\n5Z5fiGlbJFIaSZx0UuwIRGS6SmQ3ObiUi8Ty5c3YIdQm9zlf5Ze23PMLkchucnApHwIrIhJLlHtc\nD1vIPa7vvBNe85rx9Ysugle8At7znpqDG4L/+A9YvDh2FCKSm1G+x/WUS7lxLSISy7QpEikfAvuz\nnzVjh1Cb3Od8lV/acs8vRCK7ycGlfDKdiEgs06YnsXYt7LPP+Pqll8Kuu8I731lzcEOwdi3svXfs\nKEQkN+pJtNHRTSIiEzdtikS3xnUqPYmf/rQZO4Ta5D7nq/zSlnt+IRLZTQ5OPQkRkYmbNj2Jp56C\nsbHx9auugrlz4bTTag5uCNatg0WLYkchIrlRT6KNRhIiIhM3rYuEehLx5T7nq/zSlnt+IRLZTQ4u\n5ca1iEgs06Yn4b59Ubj++mK6KYXLcD/wAOy1V+woRCQ36km0Mdv+XImUpptERGKZVrvJ9imnlBrX\n6kmkS/mlLff8Qszqv0k+OkcSIiLS27TpSUBxraaNG4vlm2+GzZshhVvYPvgg7Lln7ChEJDfqSXTo\nnG5ST0JEpLdptZvsnG5STyK+3Od8lV/acs8vxLQqEu0jCZ0nISLS37TqSeyzT3FvBoDVq2HDBjjm\nmJqDG4KHHoKFC2NHISK5UU+iQ/tIYvZsjSRERPqZVrvJ9p7EnDnp9CRuvrkZOYL65D7nq/zSlnt+\nIaZVkWgfScyZo5GEiEg/06oncdhhsGJFsfz447BmDRx5ZL2xDcPDD8Mee8SOQkRyo55Ehx13HF9O\naSSRSpwikp9ptfuZO3d8OaUisWpVM3YItcl9zlf5pS33/EIkspscjvaRxOzZ6TSuRURimVY9iTPO\ngG99q1h2h1Wr4JBDag5uCDL4JxKREaSeRIfOK7/OmRMnDhGRVEQpEmb2bjNbZWYvmtnhPbY72czu\nNrN7zey8wb93+/Uddhj0E6dGzvOiOecGyi91uecXItZIYiXwDuCHVRuY2Uzgs8DJwFLgLDN71SBf\num3b9uupjCRWtI7bzVDOuYHyS13u+YWIctMhd78bivmwHo4C7nP3NeW2VwJvB+6a7Pd2FolURhIb\nNmyIHUJtcs4NlF/qcs8vxCj3JBYBa9vW15WvTVqqRUJEJJbaioSZ3WBmK7s83hb4EUM/pud1r9t+\nPZXppjVr1sQOoTY55wbKL3W55xci6iGwZnYj8OfufluX944GLnD3k8v1jwDb3P3CLtvqIFERkUno\ndwhslJ5Eh6oAlwMHmtkS4EHgTOCsbhv2S1JERCYn1iGw7zCztcDRwHfN7Lry9b3M7LsA7r4VOBe4\nHlgNfN3dJ920FhGRicvijGsREanHKB/d1NewT7YbJWZ2iZk9YmYrY8dSBzNbbGY3lidV3mlmfxI7\npmEys7lmdouZrTCz1Wb2t7FjGjYzm2lmt5vZt2PHMmxmtsbM7ijz+3nseIbNzMbM7Cozu6v8/3l0\n5bapjiTKk+3uAU4EHgB+AZyVy5SUmR0HPAN8xd1fEzueYTOzhcBCd19hZjsDtwJn5PLvB2BmO7n7\nJjObBfwY+At3/3HsuIbFzD4EHAHMd/fTY8czTGZ2P3CEu6+PHUsdzOxy4CZ3v6T8/znP3Z/qtm3K\nI4nfnmzn7luA1sl2WXD3HwFPxo6jLu7+sLuvKJefoThJcq+4UQ2Xu28qF+cAM4FsdjhmtjfwVuBL\nVB98kros8zKzXYHj3P0SKPq/VQUC0i4SQz/ZTuIoj2A7DLglbiTDZWYzzGwF8Ahwo7uvjh3TEH0K\n+G/Atn4bJsqB75nZcjN7f+xghmw/4DEzu9TMbjOzL5rZTlUbp1wk0pwnk+2UU01XAX9ajiiy4e7b\n3P1QYG/gjWbWiBzSUJjZacCj7n47mf7aBo5198OAU4D/Uk7/5mIWcDjw9+5+OPAs8OGqjVMuEg8A\ni9vWF1OMJiQRZjYb+BfgH9396tjx1KUcyn8XSOCO6kGOAU4v5+2/BpxgZl+JHNNQuftD5fNjwDcp\nprdzsQ5Y5+6/KNevoigaXaVcJH57sp2ZzaE42e6ayDFJICuu7vhlYLW7fzp2PMNmZruZ2Vi5vCPw\nFuD2uFENh7v/lbsvdvf9gPcAP3D3s2PHNSxmtpOZzS+X5wEnUVy5Ogvu/jCw1swOKl86EVhVtf0o\nnHE9Ke6+1cxaJ9vNBL6c2ZExXwOOB15ennj439390shhDdOxwH8G7jCz1s7zI+7+rxFjGqY9gcvN\nbAbFj7H/5+7fjxxTXXKb+t0D+GZ5lepZwBXu/m9xQxq6/wpcUf7A/hVwTtWGyR4CKyIi9Ut5uklE\nRGqmIiEiIpVUJEREpJKKhIiIVFKREBGRSioSIiJSSUVCZJLMbFcz+2Cfbb5gZsdMVUwiw6YiITJ5\nLwP+uM82rwd+OgWxiNRCRUJk8j4OHFDemObCzjfN7FXAv3vHGatm9m4zW1nekOimqQpWZDJ0xrXI\nJJnZvsB3qm4KVd6UZ727X9bx+h3A77n7Q2a2i7tvrD9akcnRSEJk8vpdJvskoNu1qH5CcV2nPyTh\n66fJ9KAiIVKD8iYuY+UVN7fj7h8EPkZxeftbzWzBVMcnEkq/YkQm72lgfsV7bwJ+0O0NMzvA3X8O\n/NzMTqGkIcBfAAAAcklEQVS4KVE2tzaVvGgkITJJ7v4E8JOyCd3ZuD6F7lNNAJ8wszvMbCXwE3e/\no9ZARQagxrVIDczsVuAod38xdiwig1CREBGRSppuEhGRSioSIiJSSUVCREQqqUiIiEglFQkREamk\nIiEiIpVUJEREpNL/B1gXRQ5ceRSYAAAAAElFTkSuQmCC\n",
245 | "text/plain": [
246 | ""
247 | ]
248 | },
249 | "metadata": {},
250 | "output_type": "display_data"
251 | }
252 | ],
253 | "source": [
254 | "plotting.plot_time(excitation_windowed_zeropadded, fs);"
255 | ]
256 | },
257 | {
258 | "cell_type": "markdown",
259 | "metadata": {},
260 | "source": [
261 | "# System\n",
262 | "Now, you have to design the DUT.\n",
263 | "## FIR-Filter System\n",
264 | " For a better understanding, in this example a dirac impuls was used as filter. "
265 | ]
266 | },
267 | {
268 | "cell_type": "code",
269 | "execution_count": 31,
270 | "metadata": {
271 | "collapsed": false
272 | },
273 | "outputs": [],
274 | "source": [
275 | "dirac = measurement_chain.convolution([1])"
276 | ]
277 | },
278 | {
279 | "cell_type": "markdown",
280 | "metadata": {},
281 | "source": [
282 | "## Noise System\n",
283 | "In addition, you can define the system with additve noise. "
284 | ]
285 | },
286 | {
287 | "cell_type": "code",
288 | "execution_count": 32,
289 | "metadata": {
290 | "collapsed": false
291 | },
292 | "outputs": [],
293 | "source": [
294 | "noise_level = -30 # RMS (dB)\n",
295 | "awgn = measurement_chain.additive_noise(noise_level)"
296 | ]
297 | },
298 | {
299 | "cell_type": "markdown",
300 | "metadata": {},
301 | "source": [
302 | "## Combinate System Elements\n",
303 | "Finally, the system elements must be combined. Feel free to add more elements (lowpass, bandpass, gain, ...) to the system."
304 | ]
305 | },
306 | {
307 | "cell_type": "code",
308 | "execution_count": 33,
309 | "metadata": {
310 | "collapsed": false
311 | },
312 | "outputs": [],
313 | "source": [
314 | "system = measurement_chain.chained(dirac, awgn)"
315 | ]
316 | },
317 | {
318 | "cell_type": "markdown",
319 | "metadata": {},
320 | "source": [
321 | "# System Response\n",
322 | "To record the system response, you have to simply pass the excitation signal to the system."
323 | ]
324 | },
325 | {
326 | "cell_type": "code",
327 | "execution_count": 34,
328 | "metadata": {
329 | "collapsed": false
330 | },
331 | "outputs": [],
332 | "source": [
333 | "system_response = system(excitation_windowed_zeropadded)"
334 | ]
335 | },
336 | {
337 | "cell_type": "markdown",
338 | "metadata": {},
339 | "source": [
340 | "### Plot System Response"
341 | ]
342 | },
343 | {
344 | "cell_type": "code",
345 | "execution_count": 35,
346 | "metadata": {
347 | "collapsed": false
348 | },
349 | "outputs": [
350 | {
351 | "data": {
352 | "image/png": "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\nD8zvA+D66+GTT2DcuPy6NWvgscdCrLnXnjs3/Lz3XjjuOJg/H1atKto98+bBBRfARx9Vfg8qmT49\nvC9vvBHKS5bAfffBwQfD3Xfn67lH+2JeuRKuuircn80dFi8O783KlfD66+F9bG/p0pDbihXhPZ81\nK7xH778Py5fDhhvCbrvB00/DrrvCeuuF32Eu5vYuvhgeeKBynIsXh/d8yBD40peK34+77gox1cLq\n1TB+fCe/K9y97APYCPg+cDXwUPZxNfA9oG+l53bnA/Dw0fCSctty2wvLyXg0+7hxxeueey7k0qdP\nKE+aFMptbe4XXOA+bpz77be7n3qq+1VXub/1Vqi3yy7uy5eHurNnu3/nO2FfhftevNj9xBPz5e9/\n333yZPdf/9p9zRr3hQvdW1rcp04N248+2r21tfg9X7XK/frr3Xfe2f03vwn1PvMZ9298Y+3cdtjB\n/YQTQrlnT/ef/zy/vaUl7P+WW8K+rroq7H/mTPevfz2Ur7rK/Uc/cr/5ZvcLL1z79//hh+7Tp7sv\nXRriXLIkrJ83z/2rX3Xv29f9L38JueVed4cdQp17782vW7TI/eKL3bfdNpSnTMm/xurV7suWuX/y\nifuCBcX5lfqdXnpp/vc1aVJ4z1tb3TfeOF/nmWfyy21t7mPGuB9xxNr7ysXR1rb25zuXa+53kPsb\nuPXWfPlrX3OfM6f852+LLdyPOcb97rvd//nP4m333dfsS5e6v/tueH/PPtv9Jz8Jv/+bb3YfP959\n2rRQd8CAsL65uXgfL7/svs02xetyn81c+T//0/2hh8LrL1rkPnFiPl939//4j+LPa6W/p3/7N/f/\n+q+wvPnmHf/tlVp/zjnup5wS3jf3/N9C7u/hvvvC5/9733OfO7f8/q+8MuTRfv2yZe4rV7rPmBE+\nUzfd5P7aa+7HH+/+pz+F11y4sPg9yH0OjzvOfYMNQnzg/s477r/8ZVju2zd8zoYODX/PoQno4Pu1\nowpJeDRCI1Fq/dVXF5cLP6hxPMyql1tXH4MGuT/+ePiDqXXe3/525/Lr3Pu17o8HHywun3tu5/d1\n1FHR8jvyyOj77OhLvdJjt91q/f6V//3lHoWNeTUf/fqV33bAAfnlXXbpyuvQYSOh6yRERBpWdea4\nFhGRBqVGIhEycQdQQ5m4A6ixTNwB1Fgm7gBqLBN3ALHrsJEwsw3N7Jdmdm22vIuZHVaNFzez4WY2\n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\nEiIiUtb/ByPdt4gSnU6ZAAAAAElFTkSuQmCC\n",
353 | "text/plain": [
354 | ""
355 | ]
356 | },
357 | "metadata": {},
358 | "output_type": "display_data"
359 | }
360 | ],
361 | "source": [
362 | "plotting.plot_time(system_response,fs);\n"
363 | ]
364 | },
365 | {
366 | "cell_type": "markdown",
367 | "metadata": {},
368 | "source": [
369 | "# Impulse Response\n",
370 | "Via the FFT and IFFT, the impulse response is calculated. That's it! A Plot with linear and dB scale show you the characteristics of the IR. "
371 | ]
372 | },
373 | {
374 | "cell_type": "code",
375 | "execution_count": 36,
376 | "metadata": {
377 | "collapsed": false
378 | },
379 | "outputs": [],
380 | "source": [
381 | "ir = calculation.deconv_process(excitation_windowed_zeropadded, system_response, fs)[:len(excitation_windowed_zeropadded)]"
382 | ]
383 | },
384 | {
385 | "cell_type": "markdown",
386 | "metadata": {},
387 | "source": [
388 | "### Plot Impulse Response (linear)"
389 | ]
390 | },
391 | {
392 | "cell_type": "code",
393 | "execution_count": 37,
394 | "metadata": {
395 | "collapsed": false
396 | },
397 | "outputs": [
398 | {
399 | "data": {
400 | "image/png": "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\nhtwTMLM0uSdgZmYtuQh0AfcE8qvIuYHzKwMXATOzEnNPIEPuCZhZmtwTMDOzllwEuoB7AvlV5NzA\n+ZWBi4CZWYm5J5Ah9wTMLE3uCZiZWUsuAl3APYH8KnJu4PzKwEXAzKzE3BPIkHsCZpYm9wTMzKwl\nF4Eu4J5AfhU5N3B+ZeAiYGZWYu4JZMg9ATNLk3sCZmbWkotAF3BPIL+KlNvg4LbzFi+ucvvtsGXL\n1MczFYr0/G0vF4ECePbZrCOYuC1bYM2azm4zAo45prPbnApDQyPHa9fCunXJtAQvvrj923755fbW\nmzULdtgh+R3ecQe8+moy/4gjoFKBHXdsbzvPPDP2Mgk2b279/e95TxJD895fCc48sx7XRAwOto4L\n4Lnntv2ZeXbwwXDooW2uLCm1BzALWAY8Bpw7xjqX1pY/DBw4xjoqosWLJZD22Ue66CLpueekW2+V\nHnxQ+uxn6+tVq9IXv5is+93vJvNWrpQefzyZN/wYtnatNDSUTA8NSf390rx50qZNyfiUU6Q770yW\nP/ts8nXTpvp21q7ddrunnSbtvrv00kvS9dcn21mxov5zbrwxmX700frPHf7+d79bWrhQOvPMkdsF\n6YILknXvvjsZP/64tHlzPZcnnpDWravHePXV0m23ScuXJ7+vdeukZcukvr76Nj/3ueTrjBnb/s6H\n47rmmuTnDA0lX199VdqyJVlncFD6/e+lj32svk5z3N/5TvJcfOlLoz+33/ymdNRRyfQrr0hve1v9\ne3/6U+mcc6SNG7fd7ssv16fPP78+ffvt0po1yfTJJ9fnL1iQfL322vpzePnl2742hh8bNki//W39\neR422rqjPQYHk+e4ed7g4Mh5L7448jW4ZUt92aZN9fnXXFOfv3TpyG3cdtvYcdx9d7KNgYFk/Oyz\nye+8+W+hMbfTTpP22EN6+OFtX6ONj7vu2va5efbZ5O9w+GcPDta3/8ILydclS+rrX3tt/XmTpOef\nr/9dfe1r9d/NsFtvTZbdckvymtuyRXrmmfrfwt/+bX3bV121bcxnn52su3HjyN917b2z5ft0ao3h\niJgGLAeOAp4E7gdmS1rasM5xwFmSjouI9wPflHTYKNtSWnFmabgxbGaWjmwbwzOAFZJWStoMXAec\n2LTOR4BvA0i6F+iJiN1TjKmrPP308FQ1wyimQjXrAFJUzTqAlFWzDiBl1awDyFyaRWBPYFXDeHVt\n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\nEnMRMDMrsf8Pu+X9dCS9yzYAAAAASUVORK5CYII=\n",
401 | "text/plain": [
402 | ""
403 | ]
404 | },
405 | "metadata": {},
406 | "output_type": "display_data"
407 | }
408 | ],
409 | "source": [
410 | "plotting.plot_time(ir, fs)\n",
411 | "plt.xlim([-1, 5])\n",
412 | "plt.ylim([-0.1, 1.1]);"
413 | ]
414 | },
415 | {
416 | "cell_type": "markdown",
417 | "metadata": {},
418 | "source": [
419 | "### Plot Impulse Response (dB)"
420 | ]
421 | },
422 | {
423 | "cell_type": "code",
424 | "execution_count": 38,
425 | "metadata": {
426 | "collapsed": false
427 | },
428 | "outputs": [
429 | {
430 | "data": {
431 | "image/png": "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\nPSsAtZXCmjVw9dVxIrtbO+0U/7377rEVz9y5sPfecO+9lXn77AMf+EDrbSY9M9p000LN9IUX1v4a\n79Tjj8dnFz/6ERQKsN9+yV973nnxr/92zjqrdvqII+LKrfoss6eJZuAs4CHgRmBe6dHudWk+UKLZ\nV6+uJMOqE2nVicGf/KS7WE46Kd7O8ce7X3JJZbtPPTW+7VXH5u6+fr37l740NqHp7v63v3WfeK7f\nbhpJ7KTbfvFF97PPdl+8OJ5++OHGr92wYex2N9us9f6ee652/rRp8d8nnnC/9Vb3k092X7Om8TaS\nJFubPUZHK+u+//3xvDe9qfE2Hnmk9fabzT/++Np1Ss/32CNZORotnzGj+WsmTGhc1nXrarc3b148\nfeaZ8aOZf/mX1nGecop7oeC+dm3z2Fetal22/fZzv+eesfv53vcq626xRWk+7u2Or21XgPuBCe3W\n6+cj/5XCvLaVwrPPVj789esr86u/FLNndxfLllvWbqv0/J3vjA/aX/mK+733Jt9eJbZ57u7+wx82\nP0g9+WT7g1by/bU+OM2f73766XFF282216yJP4t5pSNGlTPOqC3PRRc1PlC8+GLjbTd7n55+Oq5s\nGi3/9a8rz7/97dbb+dWv3K+6qn0ZS59f6fnPfhaXuXr5TTeN3UYvKoVGB75G27j2Wvdbbmm+j+pK\nYenS2l56m202r+G2G1UK1RV4I+vWtY6zenvXX9/8/Vm5svH2S8vf/vbG+6nu1fWSl5Tm497m+Jqk\n+WghsH0HJx/SQ+5x881558XX8QG4+OL4lLl6nUaatflGUXx62a7XTHVCrjpRd9NNcU+Hr30N3vCG\ntkVo6KtfjW872kyvm1RKPvOZsfN23x1OPXVs80q9BQtq8yH1DjggTjpfffXYZXfdVTt92mm100uX\nxsnLp59uHUO97bePe9g0Uv29aNV0tn49HH44HDaOUUdHHz12zMSb35zstbWX424vyZVaV66Egw+G\nN72p+TrV/xdTp8b3hbjzzrHLqrnXNsnV/881+h/s5DvcajxEs//vksmT279u9erksSSpFLYHFpvZ\n9eqS2i8FLrwwHpq+005xL5fPfja+jg/Av/4r3HNPZe1mB/dmvSz23z9ORJWSmKOjMH16fInkZq+/\n/PLaZaXE8Pr18evq25IffHBsz6jq8n3ta5UkbSP1N3ZpZt68OKH+8MPxP8Hq1fFlLZodvKsrt3rN\n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\nLtbLdKmd3cgAAAAASUVORK5CYII=\n",
432 | "text/plain": [
433 | ""
434 | ]
435 | },
436 | "metadata": {},
437 | "output_type": "display_data"
438 | }
439 | ],
440 | "source": [
441 | "plotting.plot_time(ir, fs, scale='db')\n",
442 | "plt.xlim([-1, 5])\n",
443 | "plt.ylim([-60, 2]);"
444 | ]
445 | },
446 | {
447 | "cell_type": "markdown",
448 | "metadata": {},
449 | "source": [
450 | "# Impulse Response Quality\n",
451 | "The 'Peak to Noise Ratio' provides information about the quality of the IR."
452 | ]
453 | },
454 | {
455 | "cell_type": "code",
456 | "execution_count": 39,
457 | "metadata": {
458 | "collapsed": false
459 | },
460 | "outputs": [
461 | {
462 | "name": "stdout",
463 | "output_type": "stream",
464 | "text": [
465 | "44.4698202175 dB\n"
466 | ]
467 | }
468 | ],
469 | "source": [
470 | "pnr = calculation.pnr_db(ir[0], ir[fs:pad*fs])\n",
471 | "print(str(pnr), 'dB')"
472 | ]
473 | }
474 | ],
475 | "metadata": {
476 | "kernelspec": {
477 | "display_name": "Python 3",
478 | "language": "python",
479 | "name": "python3"
480 | },
481 | "language_info": {
482 | "codemirror_mode": {
483 | "name": "ipython",
484 | "version": 3
485 | },
486 | "file_extension": ".py",
487 | "mimetype": "text/x-python",
488 | "name": "python",
489 | "nbconvert_exporter": "python",
490 | "pygments_lexer": "ipython3",
491 | "version": "3.4.2"
492 | }
493 | },
494 | "nbformat": 4,
495 | "nbformat_minor": 0
496 | }
497 |
--------------------------------------------------------------------------------
/sweep_akf_kaiser_window/lin_sweep_akf_window.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """AKF of windowed lin. Sweep.
4 |
5 | """
6 |
7 |
8 | import sys
9 | sys.path.append('..')
10 |
11 | import plotting
12 | import generation
13 | import matplotlib.pyplot as plt
14 | import windows
15 | from scipy.signal import lfilter, fftconvolve
16 | import numpy as np
17 |
18 |
19 | # Parameters of the measuring system
20 |
21 | fs = 44100
22 |
23 | fstart = 1
24 | fstop = 22050
25 | duration = 1
26 |
27 |
28 | # Generate excitation signal
29 |
30 | excitation = generation.lin_sweep(fstart, fstop, duration, fs)
31 | N = len(excitation)
32 |
33 | excitation_windowed_beta2 = excitation * windows.window_kaiser(N,
34 | 500,
35 | 500,
36 | fs, beta=2)
37 | excitation_windowed_beta7 = excitation * windows.window_kaiser(N,
38 | 500,
39 | 500,
40 | fs, beta=7)
41 |
42 |
43 | # AKF
44 |
45 | akf_excitation_rect = fftconvolve(excitation, excitation[::-1])
46 | akf_excitation_kaiser_beta2 = fftconvolve(excitation_windowed_beta2,
47 | excitation_windowed_beta2[::-1])
48 | akf_excitation_kaiser_beta7 = fftconvolve(excitation_windowed_beta7,
49 | excitation_windowed_beta7[::-1])
50 |
51 |
52 | plotting.plot_time(akf_excitation_rect, scale='db', label='AKF Rect Window')
53 | plotting.plot_time(akf_excitation_kaiser_beta2, scale='db',
54 | label=r'AKF Kaiser Window $\beta=2$')
55 | plotting.plot_time(akf_excitation_kaiser_beta7, scale='db',
56 | label=r'AKF Kaiser Window $\beta=7$')
57 |
58 |
59 | plt.legend(loc='lower left')
60 | plt.savefig('lin_AKFs.png')
61 |
--------------------------------------------------------------------------------
/sweep_akf_kaiser_window/log_sweep_akf_window.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """AKF of windowed log. sweep.
4 |
5 | """
6 |
7 |
8 | import sys
9 | sys.path.append('..')
10 |
11 | import plotting
12 | import generation
13 | import matplotlib.pyplot as plt
14 | import windows
15 | from scipy.signal import lfilter, fftconvolve
16 | import numpy as np
17 |
18 |
19 | # Parameters of the measuring system
20 |
21 | fs = 44100
22 |
23 | fstart = 1
24 | fstop = 22050
25 | duration = 1
26 |
27 |
28 | # Generate excitation signal
29 |
30 | excitation = generation.log_sweep(fstart, fstop, duration, fs)
31 | N = len(excitation)
32 |
33 | excitation_windowed_beta2 = excitation * windows.window_kaiser(N,
34 | 500,
35 | 500,
36 | fs, beta=2)
37 | excitation_windowed_beta7 = excitation * windows.window_kaiser(N,
38 | 500,
39 | 500,
40 | fs, beta=7)
41 |
42 |
43 | # Windowed Sweep-Signal
44 |
45 | plotting.plot_time(excitation, fs)
46 | plt.savefig('log_excitation.png')
47 | plt.close()
48 |
49 | plotting.plot_time(excitation_windowed_beta7, fs)
50 | plt.savefig('log_excitation_windowed')
51 | plt.close()
52 |
53 | # AKF
54 |
55 | akf_excitation_rect = fftconvolve(excitation, excitation[::-1])
56 | akf_excitation_kaiser_beta2 = fftconvolve(excitation_windowed_beta2,
57 | excitation_windowed_beta2[::-1])
58 | akf_excitation_kaiser_beta7 = fftconvolve(excitation_windowed_beta7,
59 | excitation_windowed_beta7[::-1])
60 |
61 |
62 | plotting.plot_time(akf_excitation_rect, scale='db', label='AKF Rect Window')
63 | plotting.plot_time(akf_excitation_kaiser_beta2, scale='db',
64 | label=r'AKF Kaiser Window $\beta=2$')
65 | plotting.plot_time(akf_excitation_kaiser_beta7, scale='db',
66 | label=r'AKF Kaiser Window $\beta=7$')
67 |
68 |
69 | plt.legend(loc='lower left')
70 | plt.savefig('log_AKFs.png')
71 |
--------------------------------------------------------------------------------
/windows.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | def window_rectangle(N):
5 | return ones(N)
6 |
7 |
8 | def window_poisson(N, fade_in, fade_out, fs, alpha=2):
9 |
10 | L, K, n1, n2, n3 = fade_vector_linspace(N, fade_in, fade_out, fs)
11 |
12 | w1 = np.exp(-alpha * np.abs(n1) / (L / 2.))[:L / 2]
13 | w2 = np.ones(len(n2))
14 | w3 = np.exp(-alpha * np.abs(n3) / (K / 2.))[K / 2:K]
15 | return np.concatenate((w1, w2, w3))
16 |
17 |
18 | def window_kaiser(N, fade_in, fade_out, fs, beta=3):
19 |
20 | L, M, n_ones = fade_vector_arange(N, fade_in, fade_out, fs)
21 |
22 | w1 = np.kaiser(L, beta)[:L / 2]
23 | w2 = np.ones(len(n_ones))
24 | w3 = np.kaiser(M, beta)[M / 2:M]
25 | return np.concatenate((w1, w2, w3))
26 |
27 |
28 | def window_bartlett(N, fade_in, fade_out, fs):
29 |
30 | L, M, n_ones = fade_vector_arange(N, fade_in, fade_out, fs)
31 |
32 | w1 = np.bartlett(L)[:L / 2]
33 | w2 = np.ones(len(n_ones))
34 | w3 = np.bartlett(M)[M / 2: M]
35 | return np.concatenate((w1, w2, w3))
36 |
37 |
38 | def fade_vector_arange(N, fade_in, fade_out, fs):
39 |
40 | L = np.floor(fade_in / 1000 * fs)
41 | M = np.floor(fade_out / 1000 * fs)
42 | L = L * 2
43 | M = M * 2
44 |
45 | n_ones = np.arange(L / 2, N - M / 2)
46 | return L, M, n_ones
47 |
48 |
49 | def fade_vector_linspace(N, fade_in, fade_out, fs):
50 |
51 | L = np.floor(fade_in / 1000 * fs)
52 | K = np.floor(fade_out / 1000 * fs)
53 | L = L * 2
54 | K = K * 2
55 | n1 = np.linspace(-L / 2., (L) / 2., L)
56 | n2 = np.arange(L / 2, N - K / 2)
57 | n3 = np.linspace(-K / 2., (K) / 2., K)
58 | return L, K, n1, n2, n3
59 |
--------------------------------------------------------------------------------