├── 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": "iVBORw0KGgoAAAANSUhEUgAAAY0AAAEPCAYAAAC+35gCAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJztnXu8XUWV538r9+YJCSGEBJIAAYwRmsFEMA10q1tBQHn4\naBXpZiTatIoyYzu2bWu34synndZpR3vQbmDEBx9xtH0goKAMD7cygELAhEeIPEMSEkJICEnIg9yb\nNX/Uqbvr7LsftV+ndp27vp/P+ezae9fZZ3G4qd9Za9WqImaGIAiCINgwzrUBgiAIgj+IaAiCIAjW\niGgIgiAI1ohoCIIgCNaIaAiCIAjWiGgIgiAI1jgVDSL6FhFtJKIHM/pcRkSPEdEKIlrcS/sEQRCE\nblx7Gt8GcGbaTSJ6K4BXMPMCAB8EcHmvDBMEQRBG41Q0mPkOAC9kdDkXwNWdvr8DMJ2IZvfCNkEQ\nBGE0rj2NPOYCWGucrwMwz5EtgiAIY562iwYAUOxc1j0RBEFwxKBrA3J4BsBhxvm8zrUuiEiERBAE\noQTMHP9hnknbPY0bALwPAIjoJABbmXljUkdmbtXrM59hAIwZMxj336+ubdzIOPpodf3Tn27mcy+9\n9NJannP44cpOgPHRj5Z/zvBw9JyFC4v1/8hHkvssXx71ufPO7nt33BHd++u/jr6LCy6IrutrCxd2\nX7v55u7zt741Ot+9O2qvWRO1L788auv/t+18XdoCG9ryku8iehXH9ZTb7wO4C8BCIlpLRB8gog8R\n0YcAgJlvAvAkET0O4EoAH3ForjX33w986UsAEfCTnwCLOxOFZ80Cvvtd1f7qV4G1a9OfUZbVq1dX\nfsa2bcCaNdH5o4+Wf9amTVF769b8/tu3R+1du5L7vPRS1H4hNo1i9+6o/dRTq0falPBbamAg25bx\n46O2uRj0yy8n90/6jPaw2rUBLWK1awO8xml4ipnPt+hzSS9sqQtm4OKLgeFh4GMfA4Kg+/7JJwPv\nehfw4x8Dl10G/PM/OzEzk5Ur1XHyZDVwP/ZY+WetXx+1N29W30/W4GqKwLZtyX1M0di5s/ueOaAP\nDUVtmwF9376ozdwtGuY98zPM58ouA8JYoO3hKe+44QbgnnuA2bOBf/zH5D6f/KQ6futb6b+my7J0\n6dLKz3j6aXU89VQ1KK5Z0z0AF+G556L20FC6EGiKiobpWQDAnj1R+8wzl460x1n8pe/dG7WHhro9\nEVM0zM8wMfu0j6WuDWgRS10b4DUiGjWybx/wuc+p9mc+A+y/f3K/JUuAE08EtmwBrr++XhuCuGtT\ngmc6Uw2OPBKYOVP9d5mDfxHiA//mzdn9X3wxuW2yY0fUzhKN444LRtpJohH3PkwPYu/e7veYXoQp\noOb14eFke9tB4NqAFhG4NsBrRDRq5MYbgQceAObNAz74wey+f/EX6vijH9VrQxiGlZ+hRWPuXODQ\nQ1X72WfLPcvMUQD5eQ1TBOKhJ42tp3HvveFIOyk8lSUaQ0Pd99M8DdM7abdohK4NaBGhawO8RkSj\nRi67TB0//nFg0qTsvu96lzredFP3L+c2sG6dOs6bF4nGhg3lnhX3NMwBPwlTBOKCkPSMeHgvbUC3\nyT3E35v2HtMuf0RDEOpBRKMmVq4Ebr0VmDIF+MAH8vvPmwecdJIagG67rT476gxPmZ5GWdGIexp5\nAmkjGubgHu9jegsLFwYjbTOklJZ7yApP2Xga7c5pBK4NaBGBawO8RkSjJr72NXW88EJg+nS795xx\nhjreemszNpXFFI1DDlHtsuGpuKeRJxqm55A2ScAUgKzwlCkCSbOqyoan4uKikdlTwlhARKMGXnoJ\nuOYa1b6kwAThN79ZHW+5pT5b6shp6KT3IYcABx2k2lu2lHtWUdGw8TRM0cgKT61YEY6006bipj03\nKzxlhqHMdrtFI3RtQIsIXRvgNSIaNXDttWowPPlk4Nhj7d+3ZAkwdSrwhz80U+hXht27VQJ6/Hg1\n+2vGDHU9XkRniw5Pae+rDtEwB2rzlz7QLRpxEYi/Px5OMs+Hh9M9DfO5/oiGINSDiEYNXH21Ol54\nYbH3jR8PvP71qn3HHfXYUjWnoafEHnSQGjS1aFT1NObMUcciojE8nOwVpIkB0C0aRx4ZjLSTPI24\naJgCsG9fuqfhp2gErg1oEYFrA7xGRKMia9cCt98OTJwInHde8feffLI6/va39dpVFlM0AODAA9Wx\nrGhoT0Mn1IvkNJLOAXtPIy2nod8fH+TjnkZaItxP0RCEehDRqMh3v6sGi7e9zT4BbqJF4+6767Gn\nak4jLhp1had0Qr3IlNukcyDb0zDF4dFHw8TraZ6GeR73NNJEI63Qr32Erg1oEaFrA7xGRKMCzNEC\nhEVDU5rXvlb9ol2+vP4lRcpQt6eh/5tmzlTHIuGppHMg29NIS1InDfTxuoos0UgLT8XXqxKEfkdE\nowIPPQSsWqUGxNNPL/eMqVOB445TA9F991W3qc6cBlDd09CiocUnbd0mTVwkkoQ0y9MwheDww4PE\n62MzER64NqBFBK4N8BoRjQroJUDe8Q5gsMJ6wUuWqGMdolGVuGhMnqzyNbt3l/OEtAho8UmbEaWJ\nf0bSMuRZnkZ84E+6rgf9rJzGvn12a0/5E54ShHoQ0ajAj3+sju9+d7XnLFqkjitWVHsOUH9Ogyjy\nEsp4G3FPI0804vfjogDYexqPPx6OtNM8BZMyOQ1/wlOhawNaROjaAK8R0SjJww8DjzyifkFXXbnj\n1a9WxzpEoypx0QBUCA0YvSSIDVo09CSBoqKR52nEBSDNu0jLdZj0d3hKEOpBRKMk2st4xzu6N+sp\nw/HHq+PDD5fft0JTd04DiEQjby+MOMPDUWX1tGnqWl6Iq05PY+7cYKSd52kwj/Y04veT3l/1/1fv\nCFwb0CIC1wZ4jYhGSXQ+Q69WW4Vp09TeFXv2qOpwl+hZUjoHAZT3NLQATJ6sXua1NHSiXP/KTxIN\n25xGWhgpqU5jeDhbNGw8jXYvWCgI9SCiUYJHHlFewYEHqt3t6qCuEFXVnIb2Jg44ILpWVjS0VzFp\nUrRUfJ5oaBGYMkUdk8JTtp7G00+HI+2kQT8uElkhLJuK8HaLRujagBYRujbAa0Q0SvCTn6jj295W\nPTSl0aLxwAP1PK8sWjR0OMlslxWNyZOLi8Z++3Wfm5Sp00jKg8S9j7iIpC1SmCYagjAWENEowQ03\nqOM731nfM/VCh6tWVXtO1ZyG3mK1Tk+jSHgq7mlUyWkcckgw0k4KT9UtGu1OhAeuDWgRgWsDvEZE\noyAbNgD33qt+OdcVmgKAV71KHauKRhWYI09DC4XZLpoI1wJRJjylPY0qdRppOQ0bTyPpPKmdlQcR\nhH5ERKMgN96ojqedFv0aroMFC1Ty94knkn9d21Ilp7FjhxKO/fbrLlasw9PQopE3e6pOT2PdujDx\nelpOI+vcJuzVbk8jdG1AiwhdG+A1IhoF+dnP1PGcc+p97uTJwBFHqAHtySfrfbYtSfkMoF7R2L07\ne3AtmgjPqtPIqwgvG55KC1W1WzQEoR5ENAqwa1e0y97ZZ9f//DpCVFVyGkn5DKCeRPjgIDAwoAbj\nrNqGOhPhM2cGI+2kMFKR8FTe9N349fYRuDagRQSuDfAaEY0C3H67GghPOCHaVKhOFi5UR1d5jTxP\no0pOwzxm5TWqhqeK5CHyPI2i4SlBGAuIaBSgqdCURnsaVQr8quQ00jyNOsJT5rGIaBRNhJv3NmwI\nR9p5nkaSSPSXaISuDWgRoWsDvEZEwxJm4Oc/V+2mRKPtnkZV0SjiaWSFp7LqJGxmNul2fPDPEhGb\n8JQgjAVENCz5/e+BZ54B5s4FFi9u5jMWLFDHJ54o/4w6chp1iUY8PDVxYvf1JLRnkRWeyvqlb55P\nnx6MtG3qNOKCY5MI90c0AtcGtIjAtQFeI6JhiQ5NnX129+qndTJnDjBhAvDcc/k73DVB0hIiQPSr\nf+fOYs+LexoTJqhj2pRiZrs6jSxPo8gaUXXUafgjGoJQDyIaljSdzwDUpj9HHqnaTz1V7hl15DTi\nnob+1V+XaKTt3qcHYKLIK8nzNLKm3D7/fDjSLprTyApP+SkaoWsDWkTo2gCvEdGwYP16tave5MnA\nm97U7GcddZQ6lhWNKqR5Glo0Xnqp2PPMBQuBSDSSvAcgEogJE7L7xmsjbMJIRafcyuwpQUhGRMMC\nnQA/7bToV3NTaNEoW+BXJaeRlgg3w1NFCtjMpdEBe9EYPz5aCDLP04ifm+2pU4PMPnnhqDQx8jMR\nHrg2oEUErg3wGhENC3oRmtJUFY0qpE25HT9eFefpTZVs0eKgQ011iYbtbn1pM57iSW79DPE0BCEf\nEY0cdu4Ebr1VtZuoAo+jcxplRaNKTiPN0wDKhah07kKLRRHRyOobH6jT8g1btoQj7SxBAJJ37pOc\nRr8SujbAa0Q0crj9dhVmOfFE4NBDm/+8NnoaQLkZVHrALyMaZT2NtAUE495I0s58MntKEPIR0cih\nl6EpoHv2VJm1jJrIaQDlZlBVCU/pVXaTBmXbnMaUKQGA5GT52BONwLUBLSJwbYDXiGhk0Isq8DjT\npgEzZyrv5tlne/OZGl28Z+6lodGeRpXwlBaPIqKRtLhh/FpW7gIYnb+wCU/FhUYqwgVBIaKRwf33\nq+m28+YBixb17nO1t7F6dfH3Vt1PAwD233/0vSqeRpnwVJZo6IFai1DaL/9t28JR14D08FQ8tNVf\nnkbo2oAWEbo2wGtENDLoRRV4Eocdpo5r1/buM5kj0dBehUmZRHgd4aksTyNPNJLqMfR53jXb2VNZ\ny7wLQj8iopFBr/MZmiqiUTan8fLLajA0C+tMyiTCq8yeqkM0Jk0KAIwWCJucRtzTyFuSpP0Erg1o\nEYFrA7xGRCOFZ55R4akpU5qvAo9z+OHquGZN7z4zKzQFtDs8lZfTKOtp9NeChYJQDyIaKZh7getl\nMHpFFU+jbE4jKzQFtCc8xRwN1Pp5aYP4Sy+Fo64B9olwmx36/BGN0LUBLSJ0bYDXiGik4Co0BbjJ\naeR5Gr0OTw0MqHZcNPSATZQ8LbfXOQ1/wlOCUA8iGgmYVeBnndX7z68Sniqb09AeRNvDU/p8cDC5\njzmgT5gQAGg2p+GPpxG4NqBFBK4N8BoRjQR6XQUeZ/ZsNSBu2pS9YVGd2HoaTYan9PUs0dCD9OBg\n5I3khY5sp9zK2lOCkI+IRgK6oK8Xa00lMTCgdggEgHXrir236ZyG69lT+nxgIFk0zPbu3SEAu/BU\nXnGf/+Gp0LUBLSJ0bYDXOBUNIjqTiFYR0WNE9KmE+wERvUhEv++8/qFpm1xUgSfR6xlUbZ09lbZk\niBmeyvMCmsxpiKchjDUGXX0wEQ0A+DqA0wA8A+BeIrqBmR+Jdf01M5/bK7v0XuBz5jS3F7gNZZPh\nTeU0ehGeMjdhKuJppOUbBgeDUdf0eRXR8HP2VODagBYRuDbAa1x6GksAPM7Mq5l5L4AfAHhbQr8e\n1mJ3h6Z6WQUep9czqJrwNNLCU2nbvdqEp7JyGvGQUtHZU1nLiPifCBeEenApGnMBmEPius41EwZw\nChGtIKKbiOjYpo1yOdXWpGx4qi05DeZuEQCaz2nEhWDPnjDxuu1+GjY5DX8IXRvQIkLXBniNs/AU\nlCDkcT+Aw5h5JxG9BcB1AF6Z1HHp0qWYP38+AGD69OlYtGjRSKhGD6R55698ZYBly4Dx48POoFXs\n/XWev/CC+vxnnunN561cqT5v//2T769ape7v3m33PCUAAcaPB37zG3VfT4Fdvz5EGI5+/9696nzj\nxhDLlqn3Dw11P18N2CGGhqLw07JlIZiBU05R53pQ0IP+XXeFnevq/lNPhbj77ugcCLFiBbBvX3T+\n5JPd508/HfXXRYPm+9t/vrxl9rg8X94ye3p5HgL4Tud8PkrBzE5eAE4C8Evj/NMAPpXznqcAzEi4\nznXwjW+oAMfZZ9fyuErce6+yZfHi3nzeRz+qPu9rX0u+f+ed6v5JJ9k9b9s21X+//aJrP/+5uvaW\ntyS/58tfVvc//nHmtWtVe+7c7j6PP66uH3kk82mnqfbNN6t7O3fqAJV6TZqkrj/6aPf1T36SedWq\n7mvXXst8/PHR+ec+x/zqV0fnH/5w1J4zp/u98pKXvy8wc7Gx22V4ahmABUQ0n4gmADgPwA1mByKa\nTaQyC0S0BAAx85amDDJXtXWNrg9Zv743n5cXntJLqdjWjcRnTpntKuGprJyGDi/p61UqwpntEuGC\nMNZwJhrMPATgEgA3A1gJ4N+Z+REi+hARfajT7V0AHiSi5QD+BcB7m7Jn167e7gWex+zZKhH/3HPF\nlt+umtNIS4RPnqyOu3bZPS8+cwqoP6cRn3KrjzqHMjQUAmh2yq0/hK4NaBGhawO8xmVOA8z8CwC/\niF270mj/K4B/7YUtv/qVSvIuXhwV1rlkcBCYNQvYuFG9mrYpTzS0p2ErGvGZU0A9O/cleRq6jyka\nu3dHg37ZBQuZo/O02VOCMNaQivAObQpNaebMUcciIaqydRq2nkaT4Sk9MJedPRX3NIBglBjofmPP\n0whcG9AiAtcGeI2IBtTgcP31qv32t7u1xaSMaJRFF+2l5TTqDE+l1WnkLUYY75OV09A1NjahqKRr\nWTkNP0VDEOpBRAPAPfcAGzao2giXVeBxdDJ8wwb79zSV0yiaCE8KT2kPQIeh4tiIhh6wzZxGPDw1\nbpwWlHBU0R5QPafhZyI8dG1AiwhdG+A1IhoAfvpTdXz7291WgcfppaeRJxoTJqjvZu9eu1/aSeGp\nIqJhehFJuYUkT8MUlHHjomu2xX3xinDJaQjCaMa8aDB3i0abKONpNJXTICrmbSSFp7RnYCMaRN0D\nv8YUhizRUPeCRIGQnMZYJ3BtgNeMedF45BHgsceAgw4CXvc619Z00ytPgzk/pwEUy2tkhafSphCb\nomEezf5JIayknIYpOGXCU1KnIQjJjHnR0F7GOedEg1BbKCMaZXIau3apQXLSpOjXexJFpt1WDU+Z\nx6TQUNaU23hOo446DdMGP0UjdG1AiwhdG+A1Y140rrtOHdsWmgLKhafKkBea0hSZdpsUnqpDNGym\n3Jqehq1oJNVp+LkEuiA0S+ZvayKaBeDdAF4PtboVA3gawG8A/IiZn2vawCZZuxZYtkyt4Hr66a6t\nGY1ZFb53r1l/kE6ZnEZR0aganioqGkn5hKTw1GjRCBLzF7Y5jbREuJ8Erg1oEYFrA7wmVTSI6JsA\njoaq2L4CwAaovS0OhdoL44dE9DgzX9QLQ5tA12aceWY0ILaJeFX4vHnNfI5NPgMolwgvIhr6elFP\nQ18zcxrm+lN15zQEYSyTFZ76X8wcMPOXmPlXzLyKmR9h5tuZ+YvMHAC4rEd2NkJbZ02Z6LyGbYiq\nTE6jCU8ja/ZUfBqtpmxOI+5pjBunPY3Qespt3LPImj3lJ6FrA1pE6NoAr0kVDWZ+gIgGiOh7WX2a\nMat5tmwBfv1rNfC0aemQOL1Y7dZWNIp4GknhKaLsabd15jRMT0NyGoJQH5mJcGYeBnAEEU3M6ucj\n11+vBoIgAA480LU16cyerY7PWWaP2pLTSApPAdkhKnPtKaC8pxHPadjuER73NMxz/0UjcG1Aiwhc\nG+A1NpNMnwLw/4joBgB6s09m5q80Z1bz/PCH6vie97i1Iw8tGhs3NvcZRXMaVUQjbXkQ81pZTyMt\np5G3H3hSP/E0BCEZmym3TwC4sdN3fwBTOy9v2bxZ7Z0xMAC8852urcmmqGj0IqdRdsotYOdpuMpp\n2FaE+0no2oAWEbo2wGtyPQ1m/nwP7Ogp112nBqLTTwdmznRtTTazZqmjbXiqDL2acgtUF42kTZji\nxX3xOg3zuhaRsZcIF4R6yBWNTq3G3wI4FoCemMrM/KYmDWsSX0JTQHFPo0pOo+kpt0BvPI20tafG\nj4+WFSmaCJc6jX4icG2A19iEp74HYBWAowB8HsBqqP29veT554HbblODTpun2mp6mdNoesotUK+n\nkZXTSFrlVn/22EyEC0I92IjGQcx8FYCXmfnXzPx+AN56GT/9qRoATjtNLVLYdtqU06g65RboXU4j\naT8N/byk3fz6PxEeujagRYSuDfAam9lTenPOZ4nobADrAbR4kmo2PoWmACVs48YBL7ygfr3HB+E6\naNuU2zrXnjK9Cv28sZkIF4R6sPE0vkBE0wF8AsDfALgKwMcbtaohNm0Cbr9dDVw+hKYANfgdfLBq\nb9qU378XOY02hKfK5jSA9OI+MxzVf55G4NqAFhG4NsBrbGZP/azT3ArPv+1rr1UDwZlntrugL87s\n2dH6U3Pn1v/8ojmNNoSnyuQ0zGVMii5Y6L9oCEI95HoaRLSQiG4jooc758cT0T80b1r9fK+zIMp5\n57m1oyhF8hpVchp5nkYd4akixX1aFEyBsfE0zDoNM6eR5WnERaH/PI3QtQEtInRtgNfYhKe+AeAz\niHIbDwI4vzGLGmL1auCOO9Qy6G0v6IvT9AyqJhLhZcJTaavcpi2NXnTtqSzRyJtN5f+UW0GoBxvR\nmMLMv9MnzMwAUha3bi/ay3j72/MHx7ZRZP2pMjkN22VEXBX3maJRLBEeWCfCk9anyjr3j8C1AS0i\ncG2A19iIxiYieoU+IaJ3Qe2t4Q3MwDXXqPYFF7i1pQy6KrwpT6NX+2kAzU65zdtPI0s04p5E/4mG\nINSDjWhcAuBKAK8iovVQM6cubtSqmrnvPmDVKjX4vvnNrq0pTtM5jbYV92WtcmvjaaStPZUVnup/\n0QhdG9AiQtcGeI3N7KknAJxKRPsBGMfM25s3q160l3H++dFA5BNN5jSYm1nlto7wVHxnPqBaTiNr\n9lRcFPJERBDGKjZrT00C8GdQe4QPEBFBpTb+W8O21cLQEPD976u2j6EpoNmcxq5dSjgmTowG2jRc\nFfdVzWmUmT2VJyL+Ebg2oEUErg3wGpvf3ddD1WjcB8Aimt0ubrlFDbYLFwInnODamnI0mdOw9TKA\nyNPQXkQWvVgaPX4/qU4jydMoIxpJ29MKwljERjTmMvMZjVvSEFdfrY4XXKC2G/URLRqbNqnBLMsj\nCMOwkLdRRDSaLO5j7vYUgGo5jWjtqaCWnIb/hJBf2JoQ8l2UxyYRfhcRHd+4JQ2webNaoJAIuPBC\n19aUZ/x4YMYMNdBt3lzvs22T4ECzO/eZgqHFvfp2r/ZrT8Xt8T8cJQjNYCMarwNwHxE9SkQPdl4P\nNG1YHVxzjRq8zjgDOOww19ZUw3YzpqI5DdtqcKDZKbfx0BSQnAi3zWmYa0/ZTLntv9lScQLXBrSI\nwLUBXmMTnnpL41Y0ADNw1VWqfdFFbm2pg4MPVtOGn3++3ucWCU9pAdi7Nz9MVjSnkSQaRSvCy+yn\noXfz67/EtyA0Q6qnQUTTOs1tKa9Wc++9wEMPqcH2nHNcW1Md25Vui9ZpFBENIvtkeB2eRj05jew6\njSRhSjr3n9C1AS0idG2A12R5Gt8HcBaA+wEkzR05shGLakJ7Ge97XzN7UPSaIsujF6FITgNQyfDd\nu9VrypTkPvqXO9Fob6SqaJTJaWSFpwYHlQD2fyJcEOohVTSY+azOcX7PrKmJHTui2oy//Eu3ttTF\nzJnqmBeeKprTKOJpAHbJcC0IEyaMnrHmIqeR5WnEn6HpP9EIXBvQIgLXBnhNqmgQ0Wuy3sjM99dv\nTj388IdKOE45BTjmGNfW1EPTnkZR0chKhqeFpoB00YivcGu2bTdhKlOnkRaekpyGICSTFZ76CpLD\nUpo31mxLLTAD//Zvqt0PCXBNkZxGEW+jyOwpoDnRKJoIt197KsgNT5mfH/+c/iGE/MLWhJDvojxZ\n4amgh3bUxj33qAUKZ8wA3vte19bUhw5PufY0bAr8skRDD9JVE+FV9tNI283PpP9EQxDqIWv21Bvy\n3kxErfM2vv51dbzoomiA6we0p9FUTsM2EW6T07DxNNKK6fR9oI5EePd+Glmzp/q/uC9wbUCLCFwb\n4DVZ4alziOifAdwKYBnUHhrjABwC4EQApwH4VefVCjZuVPkMIuBirxZvz6ffcxp1JMLL7KcxdhLh\nglAPqZ4GM/8NgFMBrATwZgCfBfD3UGLxEIA3MvPf9sJIW666Sg1Y55wDzJ/v2pp6MWdPZS2e12Sd\nBtCenIbtHuF5y4iMnUR46NqAFhG6NsBrMivCO3tnXNN5tZqhIeCKK1T7kkvc2tIEkyapENKOHcC2\nbcABB9TzXB8S4WmeRvx+mT3Cx04iXBDqwWbtKS+4/npg3Tq1BPqpp7q2phlsQlRN12lUTYT3trgv\nf4/wsZMID1wb0CIC1wZ4Td+Ixpe/rI6XXBLN0e83mshruEqEN7GMSF5OI23tKfMZmv4TDUGoh74Z\nXn/7WzXN9v3vd21Jc9hUhfdTTqPsdq9F9giXnMZYJHRtgNfkigYR7UdEnyWib3TOFxDR2XV8OBGd\nSUSriOgxIvpUSp/LOvdXENHirOd99KP2g5+PNOlptFE0qmz3mrVHuOQ0BKE8Np7GtwG8DOCUzvl6\nAF+o+sFENADg6wDOBHAsgPOJ6JhYn7cCeAUzLwDwQQCXpz1v0qT+TICb+JbTMGsuNFWL+8rkNKQi\nHJA4vkng2gCvsRGNo5n5S1DCAWZ+qabPXgLgcWZezcx7AfwAwNtifc4FcHXnc38HYDoRzU562IUX\nRhsV9Su2ixYWoezsqaaK+5rIaciChYJQHzaisYeIRmqriehoADm7KVgxF8Ba43xd51pen3lJD/vE\nJ2qwqOXYeBpFchr79gE7d6p22jLncXzOaej+5n7kaTmN/iN0bUCLCF0b4DU2O/d9HsAvAcwjov8D\n4E8ALK3hs7MWQzSJLa6d/L4vfGEp5ncq+qZPn45FixaNhGr0QOr7+cEHq/NVq0KEYfXnvfa16nzC\nhBB33GH3fiUaIZ54AtBufrz/Aw+EneeOvq9EI+zsdR7dX7FCnQ8ORv0HB9X9556L/nuVgIS45x7g\n9NPV/T171P3hYXX+2GMh1q8HACUY69er5w0MBCACmEOsWaM+T2/WpMJ00X1F0Dn2w/nyltnj8nx5\ny+zp5XluA3ZtAAAe4UlEQVQI4Dud8/koBTPnvgDMBHB25zXT5j0WzzwJwC+N808D+FSszxUA3muc\nrwIwO+FZPBa46y5mgHnJknqet3Gjet7Mmfbv+eY31Xve//70Ppdfrvp88IOj7y1bpu4tXtx9/Xvf\nU9ff+97o2i23qGunnhpdmz1bXduwgXn7dtWeMkXdu+ACdX711cyf+5xqX3op8/nnq/Y11zAPDqr2\nBz6gjmedpY5z56qjvi8veY2NF5i52NidtWDhCUT0ms6+GodDJcA3ADg8b68NS5YBWEBE84loAoDz\nANwQ63MDgPd17DkJwFZm3ljDZ3tJ3bOniibBAT/rNJL22Yh/nplEFwQhnazw1P8EwAAmAzgBwAOd\n68dDDfgnV/lgZh4ioksA3AxgAMA3mfkRIvpQ5/6VzHwTEb2ViB4H8BKAPq7CyMc2p2E7g6poEhxo\nzzIi9jmNYEQ0ouujP88Uo/4khMwa0oSQ76I8uftpENG1AP6KmR/snB8H4L/W8eHM/AsAv4hduzJ2\n3ucTae2ZNk0Nujt2qEFbD+BlKVoNDjQvGuY03axEeJE6jdFiMhZFQxDqwWb21Ku0YAAAMz8EoE82\nUfULovxpt0XqNKqEp1wX9w0ORgLA3C0OaWtPmeGp+Pay/R+eClwb0CIC1wZ4jY1oPEBEVxFRQERv\n7FSGr2jaMCGZOvMaZUTD9c595lRZom5vI2+PcPE0BKE6NqLxfqg9NT4G4D932mM6t+CSvG1fi9Rp\nuEyE11HcZx7Nyu9x4zAylTYenoqHvOIhrv4VjdC1AS0idG2A1+TWaTDzLgBf6bwEx9hu+2pD2xPh\n8QF+377OJEFEHkOSaJieRpoHEheJpM8XBGE0uf9EiOiphMvMzEc1YI+QQ154qkxOo02J8CxPwxzo\niaK2vjc6ER5Yh6fiVeP9R+DagBYRuDbAa2x+V73WaE8C8C4ABzVjjpCH7zmNKonw+NIfQH5OIx62\nShON+PMEQUgmN6fBzM8br3XM/C8AzuqBbUICebOnfMlp7N0bhZoAO08jKVltk9OwmT0Vf17/Ebo2\noEWErg3wGpvw1AnAyHpP4wCcCFWMJzigzpyGiym3ekAfHlYiEE+M24Sn0jyNvJyGeBqCUB2b8JSu\nDAeAIQCrAbynKYOEbPJmTzVdpzFxojq+/LIajJO21s0SDUAJxfCw+rWfJRrxJLWtpxHPaWTNnho7\nohG4NqBFBK4N8Bob0fgAMz9pXiCiIxuyR8ihzj019OypIolwIiUce/ao1+TJo/vYiMbu3d15jTo8\njbSchngaglAfNnUaP7a8JvSAvPBU0zkNID8ZrsUgSzTMfmY7KxFeZ04jTTT6d8pt6NqAFhG6NsBr\nUv+JdLZePRZqt7x3Qu1rwQCmQc2iEhxwUGfe2ubN6eEhW8qKhpkMP/DA0fdtPA2gfk+jTE4j7lmI\npyEI2WT9rloI4BwAB3SOmu0A/qpJo4R0xo8Hpk8Htm5Vrxkzuu83ndMA8pPhTYlGHTmNsRueClwb\n0CIC1wZ4TdYqt9cBuI6ITmbmu3tok5DDzJlKMDZtGi0aRWijaGStcls1p2GufiuehiCUI2sTpk91\nmn9ORF+LvS7rkX1CAlnJ8CI5jTKJcCA/p1GXp2Eub86c7WkMDeXnNMa2pxG6NqBFhK4N8Jqs8NTK\nzvG+hHuccE3oEXVVhdeR00jCVjR0PyB5ENer2OrQU17VeFpOo0h4KklEzKXZBWGskxWe+lnn+J2e\nWSNYkeVp+JDT0NfzPA19rgUjaSXaImtP2cyeSgpX9YdoBK4NaBGBawO8Jmv21M8y3sfMfG4D9ggW\n1FEVvm9f5Ckk1Vpk0atEONAdfsoKYdVVEZ50bnpEgjDWydsjPA0JTzkkqyrcdo/wnTvVccqU4tN2\neyka5gwq20R4d04jSAxP2a491T85jhDyC1sTQr6L8mSFp0LdJqKJAF4FYB+APzCz/PZySB1V4WWT\n4EDkmVTNaRQRDTOnYROeqmv2VP+IhiDUg82ChWcBuAKAXkrkKCL6EDPf1KhlQipZiXDbnMb27eo4\ndWrxz2+rp1FlP4348+Kf7z+BawNaRODaAK+x+SfxFQBvZObHAYCIjgZwU+clOMC1p+FKNKp6GqZo\nxJ+fdi6ehiB0YxPN3qYFo8OTALY1ZI9gQVYi3LZOoylPQw/S5oqyccomwsvlNJKn3GrGjqcRujag\nRYSuDfAam38S9xHRTQB+2Dl/N4BlnfWowMzXNmWckEze8ug21JHTSBKNPC8DcOdpmNfjz9fE74un\nIQjd2IjGJADPAXhD53xT55pej0pEo8dMm6YG3h071MA9yVg+spc5jaREeBHRMKeyps1mSireK5rT\nyPI04qKg+/TfnuGBawNaRODaAK/JFQ1mXtoDO4QCEClvY8MGFaKaN6/4M5rKadiIRtHiPn2/ztlT\n8edriPpVNAShHnJzGkR0FBF9lYh+SkQ/67xu6IVxQjppyXDXOY0mw1NFchpKNNLXnoo/XxPvIzmN\nfiR0bYDX2PyTuA7AVQB+BlWnAUhxn3Oqrj/V1pyGucotkFwRbr+MSPraU5o80RBPQxC6sRGN3cws\nq9q2jDRPw6ecRtHivixPI742lRr409eeir9fQ6Reaff9JXBtQIsIXBvgNTai8TUi+jyAmwHs0ReZ\n+f6mjBLyqbr+lMucRp2zp9JWuTWXVZfwlCDUh02dxh9B7dT3Raj1qPRLcEjatNuxmtMYGlJ7bgDd\nOY2i4SmdCI8/339C1wa0iNC1AV5j8zvq3QCOlPWm2kXVqnBfPA3bnIZ+1rhx0T4cAEaFp/JmT4mn\nIQjZ2HgaDwI4sGlDhGKkJcJ7kdNwVdyX5WmYohEdg1KehuQ0+p3AtQFeY/M76kAAq4joXkQ5DdlP\nwzFt8DTqLO6rusqtfpY+T/M0qs6eMms4BGEsYiMalyZckym3jklLhNvup+FjTiNrE6a4aEQ5jSAz\nEZ5WER7/fLO/n6IRQn5ha0LId1Eem4rw0DwnotcBOB/ArxuySbCg6vpTPlaEZ4Wn0jyN4eEoQR5P\ncid9Xl4ifGCg225BGGtYpfmI6DVQQvEeAE8B+EmTRgn5HHSQOj7/vBoUdRy+aE6j7uK+PZ0AZrxI\nz6SJRHiypxGMSpAX9TT6Z1OmwLUBLSJwbYDXZO0RvhBKKM6DWqTwRwCImYPemCZkMXGiWrhw2zZg\n61bgwIJTFbSnUXdxnxaNiRPT3x8XDebuGguTqp5GPEGeJBJE3d5IViLcX9EQhHrImj31CIDXADiD\nmV/PzF8DMNwbswQbkpLhNnUaL7+sXgMD2YN7GlnhqTKiYXoQ5oANlE+E65yG/ozu6xFxz8Imp2H2\n9YfQtQEtInRtgNdk/dm/E8AuAL8hoiuI6FQAlNFf6DFl158yvYz4IG2DFoQ9e6Jf6BotGuZy7XHi\noqGPSSGtqp6GFpruqbgReaKR5WmI1yGMRVJFg5mvY+bzABwH4A4AHwdwMBFdTkSn98pAIZ0kT6PI\nzKky+QxADao6mb1nT/e9Mp6GrWhUzWmYR/O/xbwWz3v0j6cRuDagRQSuDfCa3D97Zt7BzN9j5rMB\nHAbg9wD+rnHLhFzKrj9VJZ+h0cnweF6jSngqqfradrtXLRrx3EXV8JR4GoLQTaHfSsy8hZn/NzO/\nqSmDBHuSpt3a5DSqehpAel6jiGjogd7G0yib0zDXozKPmiRPIysRbt7zy9MIXRvQIkLXBniNV3/2\nQjdlq8Lr8DTqEI06chq6nZbT0GTNnrJNhMteG4IgouE1SYnwXuQ0gGqiES/uK5rTsK8ID0b1S/I0\n4t5DmjDE+/olGoFrA1pE4NoArxHR8BiXnkZagV/dnkZScV+R2VOasolw8znxe36FpwShHuTP3mOS\nEuG9zmnUkQhvztMIR/WLD/RJQpDmTfjtaYSuDWgRoWsDvMbJbgFENAPAvwM4AsBqAO9h5q0J/VYD\n2AZVVLiXmZf00MzWU3b9qSqLFWp6ndMwE+G99DTMz4onycXTEMYirv7s/w7ALcz8SgC3IX0KLwMI\nmHmxCMZoytZpvPiiOh5wQPnPThMNfd5EcV+R2VNqcA9G+pUt7uufRHjg2oAWEbg2wGtcica5AK7u\ntK8G8PaMvlKFnsL06Wrg2rZtdJFdFtu2qeO0aeU/uy2zp9LqNNJyE3mzp7JyGn6HpwShHlyJxmxm\n3thpbwQwO6UfA7iViJYR0V/1xjR/IIq8jc2b1dEmp1GHp1FncV8difB4EZ8iHGnVsYyI3/uHh64N\naBGhawO8prGcBhHdAuCQhFt/b54wMxNR2qZOf8LMG4joYAC3ENEqZr4jqePSpUsxf/58AMD06dOx\naNGikVCNHkj78fzgg4GNG0PcdBNw0UV273/iCXV+wAHlP/+FFwAgwO7d3feVaIRYuRI4/fTk9y9b\nps5ffrn7fPz40f2VQIR46ilgeFjdX7UqRBiq+2rgDrF1q7JnYCB6/7hxesOksGNXEEuQByACXn45\nOh83DtixIzrXz1fPCzqeRnSuiPq393x5y+xxeb68Zfb08jwE8J3O+XyUgpl7/gKwCsAhnfahAFZZ\nvOdSAJ9IucdjlSBgBphvvdX+PW94g3rPbbeV/9yLL1bP+PrXu68vWaKu3313+nuffVb1mTlTnd94\nozo/44zRfb/6VXXvYx9jPvdc1b7uuuj+t7+trh1xhDq+/vXRvcmT1TWA+VWvUtc++9noGpG6dvjh\n0bV/+ifmE0+Mzi+9NGpPn858zDHR+cKFUVte8vLzBWYuNn67Ck/dAODCTvtCANfFOxDRFCKa2mnv\nB+B0AA/2zEJPKFOr0WQivExxnw471TnlFkiuqbC5lpXT8Dc8JQj14Eo0vgjgzUT0KIA3dc5BRHOI\n6MZOn0MA3EFEywH8DsDPmfn/OrG2xcSrwnud0+hlIrzI7CkAMHcqTqrT0EltM7mdV9znbyI8dG1A\niwhdG+A1Tuo0mHkLgNMSrq8HcFan/SSART02zTvKeBp1zp5qSyJcf258kNckrT1l42lkTbmVOg1h\nLCJ/9p4T9zTy6jSY3YenTNFgti/uK7IJk7IxGGkXCU/ZVoT7JRqBawNaRODaAK/x6s9eGE1RT2PX\nLvWLfeLEclu9avJEI6u4z/zFPjxcbRmRtFVu9edoksJTSaKRVREeF40yux4Kgu+IaHhOXDTychp1\nhKaAajkNoNvbqGPtKY054A8NhaOuFxWNrES4X6IRujagRYSuDfAaEQ3PKbpPeB2hKaBaTgOwFw3b\nnEbSeRlPY2BAPA1ByEJEw3PinkZeTkN7GnWJhulp7NuXLQAm5u59dcyeSjqfMiUYaZdNhPePpxG4\nNqBFBK4N8BoRDc8xRYM5v7/2NKqGp5JEw/Qy8gbUouGpvFVuk87L1mmYtmetcuuXaAhCPYhoeM6k\nSWpfjL17lReRl9OoOzyVJhp5mAV+dSxYmHQeLQ/STHjKr9lToWsDWkTo2gCv8erPXkimSF6jrvBU\n0oKFRUQjydMYTKgaKpoIz6vTSAovjY3wlCDUg4hGH2CGqPJyGr0KT+VhikbWMiJVEuFTpwYj7bLL\niPSPpxG4NqBFBK4N8Bqv/uyFZIrUarQlPNXUlNsys6fixXxZxX3iaQhjHRGNPsAMT/WqTiNLNLIK\n+zRVEuG2s6d27QpH2nUsI+J3Ijx0bUCLCF0b4DUiGn1AEU9D7YMBHHhgtc9MKu7TbZeeRtraULaJ\n8Kycht+iIQj1IKLRB5ieRl5OY8sWdZwxo9pnJhX36faUKfnvLyMaRWdP6U2mgPSZUknXskTD3/BU\n4NqAFhG4NsBrRDT6AO1pPPdcfl/tadQlGqanoUVDeyFZ2Bb31VURbisaeSvZiqchjHVENPqAQzqb\n6m7cmJ/TqMvT0CGo3bujosIyotFkcd9LL4Wjrhct7ouLhr+eRujagBYRujbAa0Q0+oBDD1XHDRvy\n+2rRqJrTGBjo9haAYqJRprgva5Vb0y5NXp2GTXgqy9Pwa8qtINSD/Nn3AaZo9CqnAYwu8Nu5s/t6\nFtpT2bOnubWnZswIRl1Peu/YCE8Frg1oEYFrA7xGRKMPmDVLDWCbNkUDaxK7dqlw0oQJdsnqPOJ5\njSKehq1omJss6TBYWqI6fl53TiM+e0o8DWEsIn/2fcDgoJpBxQz89Kdhaj8zCV7Hr+QqomG+N6so\nUHsaus/gYPY+3eb5tm3hSLuuRLjNopDtJHRtQIsIXRvgNSIafYIOUenwUxJ15TM0aaJh48WYnkZR\n0TCJi0Z82Y94v6IV4f4mvgWhGUQ0+gQtGnPnBql96sxnAKML/Mp6GjqRrpPjJloE9GcUEY2ZM4NR\n16t4Gsw+exqBawNaRODaAK8R0egT9LTbrBlUdYtGvMCvbE6jF55GHaIB+CwaglAPIhp9gvY07ror\nTO3TlGhU8TTyRCMrZ5F0borGCy+Eo/rlzZ7KmnIbD0/5Fa4KXRvQIkLXBniNiEafoEVj8+b0PnWt\nO6WJi0aZKbe2iXBNPIQVFw1zBlZZTyNrhpTpaYjXIYxFRDT6BB2eGhgIUvs0lQgvE54yPQ2d06hD\nNMz+s2YFo64XXbCwfxLhgWsDWkTg2gCvEdHoE2yqwvXOfrNm1fOZ++2nji+9pI5lchqmp5GVCNfE\nazmyRMMmFJV0TXIagpCOiEafoEXjqafC1D56QcO6RGPqVHXcvl0dm8hpxAftIuGpzZvDkbYkwkPX\nBrSI0LUBXiOi0Sfo8NSWLekD28aN6ti0aBSt08gKTwHd3kOR8JSNVxG/licaefgdwhKEfEQ0+oT9\n9lO78Q0NBakFfm3yNGwT4UC3EMTDU/GlPcy+hxwSjLpuE7KyTYT7ReDagBYRuDbAa0Q0+ojDDlPH\ntWuT77dJNMwketLqtSZZnkb8vikqpkBkhafiIlFlyq14GkK/I6LRRxx+OACEWLNm9L2dO4EdO9Sg\nesAB9XxeXDT0cf/989+rvQq9Z/nEiekDrikEWYsaAt0CsmlTOKpPldlTgM+eRujagBYRujbAa0Q0\n+gglGsDTT4++Z86cquvXsBaNHTu6j/p6FtrTMEUjDfNekqeRJhpJ7bGbCBeEehDR6COOOAIAgkRP\nQ4emZs+u7/NMT4M5Eg09FTeLJE8jDS0wQDHROOKIYFSfqlNu82ivqASuDWgRgWsDvEZEo4/QnkaW\naNSVzwCiMNT27So3sW+fymek5SZMynoaeeGptFBWHRXhRG0WBUHoDSIafURWTuPZZ9WxTtEwPY0i\n+QwgEoIXX1THJA8i3jetX5qn8eyz4ajrSbOn4hs32XoafglI6NqAFhG6NsBrRDT6CBWeSvY0nnlG\nHefOre/zTNEoks8AIk9jeFgdbcNTRRLhNlu7Jr2nSk7DLyERhOKIaPQRc+YA48YF2LAhKpjT6Gm4\nelpuHdThaWiyCgKLeBqmqCxYEIy0s8JT8UUO+zMRHrg2oEUErg3wGhGNPmJwUHkSzMC6dd339Pm8\nefV9XpKnYSsapvcAZItG2US4bU4j3s+2TmPfvnSbBaFfEdHoM6ZPDwEATz7Zfb0JT2PyZDWo7tkT\nLbteNDylsfU0ksJTadNs16wJR9pZs6fiopEmPOPG+bw0eujagBYRujbAa0Q0+gwtCn/4Q/f1JjwN\nokgk1q9XxyKehjmAVwlPmQKUV6eRJAjxa0keCjA6VCWehjAWEdHoM4IgANAtGtu3q1lKkyYBBx1U\n7+fpvTl0QaGtp2EKDmAfnkpKmKfdP/bYYKStvYokryUuEmmiMTDgs6cRuDagRQSuDfAaEY0+Y+FC\ndTRFY/VqdTz88PrXRpo5Ux0ffVQdi2wla3olWQWB5kCftK6VKRppM620h5LktdiKRrxOQzwNYSwi\notFnbN0aAugWDT2gv/KV9X9eXDSKeDJlPI2kfqaQmH2feCIcaWuxMMNbSZ5GXnjKDFH55WmErg1o\nEaFrA7xGRKPPmDNHDXRr1kSrzjYpGlokqnoatjmNPE/D7GsO+Pp6UngqnvuIF/uZbX9FQxDqQUSj\nzzjttAALFqgB7aGH1LXHHlPHJj0NvSdG055GkmiYQmC2jz8+GGlrDyPJ08gSBhO/RSNwbUCLCFwb\n4DUiGn3IiSeq4733quPKlerYpKehKeJpmKKRlUA3hSBJXNKqwE2B0M9IqruI53myRMPsm5TTkP00\nhH7HiWgQ0buJ6GEiGiai12T0O5OIVhHRY0T0qV7a6CthGGLJEtW+915g715gxQp1vmhR/Z+nPQ1N\nEU/DDE/pWVhJmEnyJE8jbaBetSocaSfNutKegs3mSoASCfNekqcR3362PYSuDWgRoWsDvMaVp/Eg\ngHcA+E1aByIaAPB1AGcCOBbA+UR0TG/M85fly5ePiMbddwMPP6y2VH3FK7IH5rIcemj3eZE6ENO7\nyLLN9F5s9h/XPP308pF2kmikzX5KE429e/M9jaJLqfeO5fldxgzyXVTByZ84M69i5kdzui0B8Dgz\nr2bmvQB+AOBtzVvnN1u3bsWiRWp3vj/8AbjySnX95JOb+bxXvCJqF60DMff2yBIN815SP71dbJw9\ne7aOtJNEQwuAXjRRk5arGBryWTS25ncZM8h3UYXW/okDmAvA3O16XeeakMOECcDZZ6v2FVeo41ln\nNfNZRx0VtefNKxbTN72SrM2hTE8jKWeyd2/y+0yvZNq00fd1ziO+uGPa8+KJ8Pj7AN+S44JQnMZE\ng4huIaIHE17nWD5C/vmVYHWnku/DH46uzZoFnGP7rRdkypRo6ZLjjiv23vnzo7beQCqJgw+O2kn7\ngfzpnya/b/Pm1SPtpES7FqD4M6dP7z7XeYo5c4DFi6Prpv2aI49MtsU9q10b0CJWuzbAa4gd/jQi\nol8B+AQz359w7yQAn2fmMzvnnwawj5m/lNBXBEYQBKEEzFxozp/FxpyNk2bwMgALiGg+gPUAzgNw\nflLHov/RgiAIQjlcTbl9BxGtBXASgBuJ6Bed63OI6EYAYOYhAJcAuBnASgD/zsyPuLBXEARBUDgN\nTwmCIAh+0ebZU13YFPoR0WWd+yuIaHFSn34g77sgor/ofAcPENGdRHS8Czt7gW0BKBG9loiGiOid\nvbSvl1j+GwmI6PdE9BARhT02sWdY/BuZSUS/JKLlne9iqQMzG4eIvkVEG4nowYw+xcZNZm79C8AA\ngMcBzAcwHqo655hYn7cCuKnT/mMAv3Vtt8Pv4mQAB3TaZ47l78LodzuAnwP4M9d2O/y7mA7gYQDz\nOuczXdvt8Lv4PIB/0t8DgM0ABl3b3sB38ToAiwE8mHK/8Ljpi6dhU+h3LoCrAYCZfwdgOhFlzP73\nltzvgpnvZuYXO6e/A1Djfn2twrYA9D8B+DGATb00rsfYfBd/DuAnzLwOAJj5+R7b2CtsvosNAHT1\nzjQAm1nlUfsKZr4DwAsZXQqPm76Ihk2hX1KffhwsixY9/iWAmxq1yB253wURzYUaMC7vXOrXJJ7N\n38UCADOI6FdEtIyI/mPPrOstNt/FNwD8ERGtB7ACwMd6ZFvbKDxutmHKrQ22/9DjU2/7cYCw/m8i\nojcC+ACAP2nOHKfYfBf/AuDvmJmJiJA+xdt3bL6L8QBeA+BUAFMA3E1Ev2Xmxxq1rPfYfBefAbCc\nmQMiOhrALUT0ambe3rBtbaTQuOmLaDwD4DDj/DAoRczqM69zrd+w+S7QSX5/A8CZzJzlnvqMzXdx\nAoAfKL3ATABvIaK9zHxDb0zsGTbfxVoAzzPzLgC7iOg3AF4NoN9Ew+a7OAXAFwCAmZ8goqcALISq\nDxtLFB43fQlPjRT6EdEEqEK/+D/6GwC8DxipJt/KzBt7a2ZPyP0uiOhwANcCuICZH3dgY6/I/S6Y\n+ShmPpKZj4TKa1zch4IB2P0buR7AnxLRABFNgUp8ruyxnb3A5rtYBeA0AOjE8BcCeLKnVraDwuOm\nF54GMw8RkS70GwDwTWZ+hIg+1Ll/JTPfRERvJaLHAbwE4P0OTW4Mm+8CwOcAHAjg8s4v7L3MvMSV\nzU1h+V2MCSz/jawiol8CeADAPgDfYOa+Ew3Lv4v/DuDbRLQC6sfz3zLzFmdGNwQRfR/AGwDM7BRU\nXwoVpiw9bkpxnyAIgmCNL+EpQRAEoQWIaAiCIAjWiGgIgiAI1ohoCIIgCNaIaAiCIAjWiGgIgiAI\n1ohoCEJJiOgAIro4p88VRHRKr2wShKYR0RCE8hwI4CM5ff4YwN09sEUQeoKIhiCU54sAju5savSl\n+E0iOgbAoxyroCWidxPRg50NgH7dK2MFoQ6kIlwQSkJERwD4OTP/h5T7/wXAFmb+Tuz6AwDOYOYN\nRDSNmbc1b60g1IN4GoJQnrxl1k8H8MuE63cCuJqILoIn678JgkZEQxAaoLOK7HRmfjZ+j5kvBvAP\nUEtS30dEM3ptnyCURX7lCEJ5tgOYmnLvjVD7ko+CiI5m5nsA3ENEb4Haw6DvVlgV+hPxNAShJMy8\nGcCdnaR2PBH+FiSHpgDgfxDRA0T0IIA7mfmBRg0VhBqRRLggNAAR3QdgCTMPu7ZFEOpEREMQBEGw\nRsJTgiAIgjUiGoIgCII1IhqCIAiCNSIagiAIgjUiGoIgCII1IhqCIAiCNSIagiAIgjX/H52Q9Dr1\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": "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\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": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAEKCAYAAAD9xUlFAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xm4HFWd//H3lyWyymV+6G8kiUYMiNFhLuCw+RttECKg\nwIOIqONycVQkioo6KIoCjwPiQMARHIVRjI4GRFAUlCWYFCAgDpgbAiGSoAEDYYdIWLJ+f39U77eX\n6ttdfaorn9fz9HO7lq76nu6+dbrO95wqc3dEREQANgkdgIiIZIcqBRERKVOlICIiZaoURESkTJWC\niIiUqVIQEZGyzUIHMB5mpn60IiLj4O7WavnAnim4e24fp556avAYVD6Vb2MsX57L5p7st3QmKwUz\nO9jMFpvZEjP7Quh4+m3ZsmWhQ0iVyjfY8ly+PJctqcxVCma2KXABcDAwDXivmb0ubFQiIhuHzFUK\nwF7AUndf5u5rgUuBIwLH1FcjIyOhQ0iVyjfY8ly+PJctKUvaztQvZvYu4G3u/tHi9PuBvd39hKp1\nPGtx98qaNeAOm28Om2SxyhaRgWVm+AAmmvN5tE/o0ENhiy0i5s4NHUl6oigKHUKqVL7BleeyJZXF\nLqkPAZOrpicDy+tXGhkZYcqUKQAMDQ0xPDxMoVAAKh/soE7DKAsWwIEHZiOeXk+Pjo5mKh6VT+XL\n63QURcyaNQugfLxsJ4vNR5sBfwLeCjwM/AF4r7vfW7VObpuPDjwQfvtbmDMnfi4i0itJmo8yd6bg\n7uvM7JPAdcCmwPerKwQREUlPFnMKuPs17v5ad5/q7l8PHU//RaEDSFXp9DavVL7BleeyJZXJSkFE\nRMLIXE4hCeUUREQ6N6hdUkVEJBBVCpkUhQ4gVXlvt1X5Bleey5aUKgURESlTTiFjlFMQkbQopyAi\nIh1RpZBJUegAUpX3dluVb3DluWxJqVIQEZEy5RQyRjkFEUmLcgoiItIRVQqZFIUOIFV5b7dV+QZX\nnsuWlCoFEREpU04hY5RTEJG0KKcgIiIdUaWQSVHoAFKV93ZblW9w5blsSalSEBGRMuUUMkY5BRFJ\ni3IKIiLSEVUKmRSFDiBVeW+3VfkGV57LlpQqBRERKVNOIWOUUxCRtCinICIiHVGlkElR6ABSlfd2\nW5VvcOW5bEmpUhARkTLlFDJGOQURSYtyCiIi0pEglYKZHW1m95jZejPbo27ZyWa2xMwWm9n0EPGF\nF4UOIFV5b7dV+QZXnsuW1GaB9rsQOBK4sHqmmU0DjgGmAROBG8xsF3ff0P8QRUQ2PkHOFNx9sbvf\n12DREcAl7r7W3ZcBS4G9+hpcJhRCB5CqQqEQOoRUqXyDK89lSyprOYUdgeVV08uJzxhERKQPUqsU\nzGyOmS1s8Disw03ls5tRS1HoAFKV93ZblW9w5blsSaWWU3D3g8bxsoeAyVXTk4rzxhgZGWHKlCkA\nDA0NMTw8XD71K32wgzoNoyxYAAcemI14ej09OjqaqXhUPpUvr9NRFDFr1iyA8vGynaDjFMxsHvB5\nd7+zOD0NmE2cR5gI3ABMrR+UoHEKIiKdy+w4BTM70sz+CuwD/NrMrgFw90XAZcAi4BpgRm6P/iIi\nGRSq99Ev3H2yu2/p7n/v7odULTvT3ae6+67ufl2I+MKLQgeQqtLpbV6pfIMrz2VLKmu9j0REJCBd\n+yhjlFMQkbRkNqcgIiLZpEohk6LQAaQq7+22Kt/gynPZklKlICIiZcopZIxyCiKSFuUURESkI6oU\nMikKHUCq8t5uq/INrjyXLSlVCiIiUqacQsYopyAiaVFOQUREOqJKIZOi0AGkKu/ttirf4Mpz2ZJS\npSAiImXKKWSMcgoikhblFEREpCOqFDIpCh1AqvLebqvyDa48ly0pVQoiIlKmnELGKKcgImlRTkFE\nRDqiSiGTotABpCrv7bYq3+DKc9mSUqUgIiJlyilkjHIKIpIW5RRERKQjqhQyKQodQKry3m6r8g2u\nPJctKVUKIiJSppxCxiinICJpUU5BREQ6EqRSMLOzzexeM1tgZj83s+2qlp1sZkvMbLGZTQ8RX3hR\n6ABSlfd2W5VvcOW5bEm1rBTMbDMzs+LzV5rZ0Wa2ew/2ez3wenf/R+A+4OTiPqYBxwDTgIOB/zIz\nnc2IiPRJ0wOumX0UeAx4oPj8BuAo4FIz+2I3O3X3Oe6+oTh5OzCp+PwI4BJ3X+vuy4ClwF7d7Gsw\nFUIHkKpCoRA6hFSpfIMrz2VLarMWy04EXgO8FLgXeKW7P2FmWwF3AGf1KIYPA5cUn+8I/L5q2XJg\nYo/2IyIibbRqmlnt7k+7+wPAEnd/AsDdnwdWt9uwmc0xs4UNHodVrfNlYI27z26xqXx2M2opCh1A\nqvLebqvyDa48ly2pVmcKW5rZHoABLyk+pzi9ZbsNu/tBrZab2QhwKPDWqtkPAZOrpicV540xMjLC\nlClTABgaGmJ4eLh86lf6YAd1GkZZsAAOPDAb8fR6enR0NFPxqHwqX16noyhi1qxZAOXjZTtNxymY\nWUTlV7pR94vd3fdPtIfG2z4YmAm8pXQGUpw/DZhNnEeYSJzHmFo/KEHjFEREOpdknELTMwV3L/Q8\noorzgQnAnGLnptvcfYa7LzKzy4BFwDpgRm6P/iIiGdSq99FRZvbOZo9uduruO7v7q9x99+JjRtWy\nM919qrvv6u7XdbOfwRWFDiBVpdPbvFL5Bleey5ZUq5zCYcRNRi8H9gPmFufvD9wK/Dzd0EREpN/a\nXvvIzOYAH3T3FcXpVwA/dPdgo42VUxAR6Vyvrn00GXikavpR4JXdBCYiItmUpFK4AbjOzEbM7Fjg\nN8CcdMPa2EWhA0hV3tttVb7BleeyJdUqpwCAu3+ymFj+5+KsC939F+mGJSIiIeh+ChmjnIKIpEX3\nUxARkY6oUsikKHQAqcp7u63KN7jyXLakWg1eu8jMjjSzbfsZkIiIhNPq2kf7AIcABwBrgeuAa919\nQf/Ca0w5BRGRznV77aPfE9/b4FQz2wGYDnzOzHYD5gPXuPtlvQxYRETCSpRTcPcn3H22u38Q2B34\nNrBzqpFt1KLQAaQq7+22Kt/gynPZkmo7TqFesd3mjuJDRERyROMUMkY5BRFJi8YpiIhIR9pWCma2\ntZl9xcz+uzi9s5m9I/3QNmZR6ABSlfd2W5VvcOW5bEklOVP4AbCG+J4KAA8DZ6QWkYiIBJPkfgp3\nuvueZjbf3Xcvzlvg7v/Ylwgbx6ScgohIh3qVU1htZltWbfQ1wOpugxMRkexJUimcBlwLTDKz2cS3\n5fxCmkFJFDqAVOW93VblG1x5LltSSe6ncL2Z/RHYpzjrU+7+RLphiYhICK2ufbQnUL/QSvPc/Y/p\nhtaccgoiIp3r6tpHwEziCmBLYE/gruL83YhHM+/biyBFRCQ7muYU3L3g7vsTd0Hdw933dPc9ia99\n9HC/Atw4RaEDSFXe221VvsGV57IllSTRvKu7LyxNuPvdwOvSC0lEREJJMk7hUmAV8GPinML7gG3c\n/b3ph9c0JuUUREQ61G1OoeRY4Hjg08Xpm4DvdBmbiIhkUNvmI3d/wd3Pdfcji4/z3P3FbnZqZl8z\nswVmNmpmvzWzyVXLTjazJWa22Mymd7OfwRWFDiBVeW+3VfkGV57LllTbMwUz+0uD2e7uO3Wx3/9w\n968Ut38CcCrwETObBhwDTAMmAjeY2S7uvqGLfYmISEJJmo/+qer5FsC7gP/TzU7d/dmqyW2A0mC4\nI4BL3H0tsMzMlgJ7Ed8WdCNSCB1AqgqFQugQUqXyDa48ly2pJCOa60cvf7M4wvkr3ezYzM4APgC8\nQHzgB9iR2gpgOfEZg4iI9EGS+ynsaWZ7FB9vNLOPA5smeN0cM1vY4HEYgLt/2d1fSXxp7m+22FQ+\nuxm1FIUOIFV5b7dV+QZXnsuWVJLmo9LIZoB1wDLg3e1e5O4HJYxhNvCb4vOHgMlVyyYV540xMjLC\nlClTABgaGmJ4eLh86lf6YAd1GkZZsAAOPDAb8fR6enR0NFPxqHwqX16noyhi1qxZAOXjZTtJxins\n5O5/rpv3andvlIBOtlOznd19SfH5CcBe7v6BYqJ5NnFz0kTgBmBq/aAEjVMQEelcr8YpXA7s0WDe\nnuMNDPi6mb0WWA/cTzwOAndfZGaXAYuIz0pm5PboLyKSQU1zCmb2OjM7Chgys3ea2VHFvyPEvZDG\nzd3f5e7/4O7D7n6Uuz9WtexMd5/q7ru6+3Xd7GdwRaEDSFXp9DavVL7BleeyJdXqTOG1wGHAdsW/\nJc8CH00zKBERCSNJTmFfd7+tT/EkopyCiEjnusopmNkX3P0bwPvM7H11i93dP9WLIEVEJDtajVNY\nVPx7Z5OHpCYKHUCq8t5um/fynXFGxH/+Z+go0pH3zy6JpmcK7n5V8e+svkUjIpmxdi2sXg3bbFM7\n/5RT4r+HHAK77NL/uCRdrZqPrmrxOnf3w1OIRwBd+2iw5aV8U6bAww/Dc8/BVltVLykA8MwzAYJK\nWV4+u260u0dzM/nM8opI2cPFm+7+5S/w+teHjUX6p9U9mqPSA7gNeBp4ErjV3W/sU3wbqSh0AKnK\ne7tt3spXqhwqor7u/5lnoF+dDfP22Y1HkgvivR1YCnwLuAC438wOTTswkW6tXw+LF/fvgJJXv/hF\n4/n9eF+vvBK23x42SXI3eWlq1SooXgKprSRv9bnA/u7+Fnd/C3GD4nnjDU6SKIQOIFX9arcdGYHX\nvQ6+972+7K4sb+3Sh475CVjo276PPLJvuwLy99mVzJgBxx6bbN0klcLf3H1p1fSfgb+NIy6Rvvrx\nj+O/39Edxbuyww7w/PNj51vLIVC9MWlS82U//zm57Rrba7/6VfJ1k1QKd5rZb8xspHjdo6uBO4rX\nQXrn+EKU1qLQAaSqWbvtqlXpNEls6PPNXHvdLv3UU/DNb8Ljj/d0s4ntuy9svXXcRTUW9W3fY89S\nKo46Cj7zGVi2rHf7y2tOoZMKPEmlsAXwGPCW4uPx4rzDqL0mkmTEihXxZTIGyZIlsO226TQXDHpO\n4f3vhxNPrLw3v/wlLF3a+jXNPPtsXMmMR32llORAc/75cMYZzZe3+2yS7KPTrrHPPQfHHw833dR8\nnblz4YtfjPNSedDR/4C7D9wjDjuf3vpWd3CfM2f824i/Au7XXNO7uNJ22mmVuHultL1ttundNvvh\nc59z//jHK9OlcoD79dd39z6VXvv888nXLT0eesh9xYrK9P/+b/JtPP302GW33+7+kpe4X3RR89cf\nd1zz8pbmz5zZOoYNG2qnk3zXSsv/539ab3tQvPSlpTLh3ub4mqT30U5mdp6Z/cLMrio+Omihkn56\n5JHK8690dRftsZ55Btat6+02+2HVqnS2+0Tx7uW9fk9mzoTvfrdx3B/7WOPXrFoFZ58NDzyQbB/j\naSVxh1e9qjLdSZNEpemp4vjj4xHTzcqU1J/+1HzZv/0b7Lxz7Xu5YkXr7VX/qq5f93e/gx/+sPMY\n++HLX4ZPNbkiXSdnCkmaj64E/gKcTzygrfSQ1ESJ1vrTn+C++2rnveIVled33NG7iFasiLsG7r57\n99uqb7edOROuuKL77fbTKafAy14GH/oQbL45XHRRZVmv2qW33Rauv752XrP280MPhZNOikchJ9Hq\nQNrKmjVQ+n52Uik0yus81PBGu7G1a+MDWZJ9bNZiCO4558D998dJ6ZJW3Vtnzox4+csr0/UH03/+\n57hX26JFBHfzzfGPh5Izz4yb61auHLtuJ3m1JJXCi+7+LXef65UBbRq8Fpg77LorvPa1zdd5xzt6\nt78bi5/43XePfxsXXRT/kz/4YGXe/ffD5z8PCxd2F1+/ldrJf/Sj+O9xx6Wzn7e9Ldl6N9/c2XZP\nPDHut1462xmPbnsfPfpo4/nLl8OECbDbbsm284lPtF8n6UHxpJNq35Nmv7Cbxd7KjTfCbT28CcGb\n3xyfbd1++9j9nH12bey9PlM438xOM7N9zWyP0iP5LqRzhbZrJPmSH310d1GsWxd/4Rqd+o9H6cD5\noQ8VyvP+1qJz8xln9K7LYRTBX//am221k7Sv+2OPwYUXNu7u2Y116xq/r+efXzt97LGdXdDu978v\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 | --------------------------------------------------------------------------------