1#!/usr/bin/python
2
3# ----------------------------------------------------------------------------
4#
5#  Copyright (C) 2008-2020 Fons Adriaensen <fons@linuxaudio.org>
6#
7#  This program is free software; you can redistribute it and/or modify
8#  it under the terms of the GNU General Public License as published by
9#  the Free Software Foundation; either version 3 of the License, or
10#  (at your option) any later version.
11#
12#  This program is distributed in the hope that it will be useful,
13#  but WITHOUT ANY WARRANTY; without even the implied warranty of
14#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15#  GNU General Public License for more details.
16#
17#  You should have received a copy of the GNU General Public License
18#  along with this program.  If not, see <http:#www.gnu.org/licenses/>.
19#
20# ----------------------------------------------------------------------------
21
22import sys
23import numpy as np
24import matplotlib.pyplot as plt
25from scipy.signal import convolve # much faster than numpy.convolve
26from jacktools.jacksignal import JackSignal
27sys.path.append ('..')
28from utils.logsweep import genlogsweep
29
30
31# ------- Frequency response using log sweep, deconvolution and fft ---------
32#
33# Make sure jnoisemeter is running, using
34# input 1, and select the A, C or ITU filter.
35
36
37# Create a JackSignal object and connect.
38#
39J = JackSignal("JackSignal")
40if J.get_state() < 0:
41    print ("Failed to create JackSignal -- is Jack running ?")
42    exit(1)
43J.create_output (0, "out")
44J.create_input (0, "in")
45J.silence()
46J.connect_output (0, "jnoisemeter:in_1")
47J.connect_input (0, "jnoisemeter:out")
48
49# Get Jack info.
50#
51name, fsamp, period = J.get_jack_info ()
52
53# Sweep parameters.
54#
55amp = 0.1
56fmin = 20
57fmax = 22.0e3
58tfade1 = 0.50
59tsweep = 5.00
60tfade2 = 0.01
61implen = 15000
62
63# Generate sweep.
64#
65Afwd, Ainv, p = genlogsweep (amp, fmin, fmax, fsamp, tfade1, tsweep, tfade2)
66
67# Create input buffer.
68#
69k = implen + Afwd.shape [0] - 1
70Ainp = np.zeros ([k,], dtype = np.float32)
71
72# Connect buffer to ports.
73#
74J.set_output_data (0, Afwd)
75J.set_input_data (0, Ainp, nskip = period)
76
77# Run the test
78#
79print ("Measuring....")
80J.process()
81J.wait()
82del J
83
84# Process and store result
85#
86print ("Convolving....")
87Imp = convolve (Ainp, Ainv, mode = 'valid')
88Lfft = 0x4000
89Nbin = Lfft // 2 + 1
90Spec = np.fft.rfft (Imp, Lfft)
91
92# Display impulse and magnitude response.
93#
94print ("Display...")
95Freq = np.linspace (0, fsamp / 2, Nbin)
96
97fig = plt.figure (figsize=(8,6), facecolor='white')
98k = Afwd.shape [0]
99ax1 = fig.add_axes ([0.07, 0.04, 0.90, 0.44])
100ax1.set_ylim (-1.5, 1.5)
101ax1.plot (Imp [0:100], color='b', lw=1)
102ax1.grid ()
103
104ax2 = fig.add_axes ([0.07, 0.53, 0.90, 0.44])
105ax2.set_xlim (20, 20e3)
106ax2.set_ylim (-60, 15)
107ax2.set_xscale ('log')
108ax2.plot (Freq, 20 * np.log10 (np.abs (Spec) + 1e-10), color='b', lw=1)
109ax2.grid ()
110plt.show()
111