1#!/usr/bin/python 2 3# ---------------------------------------------------------------------------- 4# 5# Copyright (C) 2013-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 22 23import sys 24import matplotlib.pyplot as plt 25import numpy as np 26from time import sleep 27from math import hypot, log10 28from jacktools.jacksignal import JackSignal 29sys.path.append ('..') 30from utils.sinewave import * 31 32 33# ---------------- SMPTE/DIN Intermodulation measurement -------------------- 34# 35# Run jack_nonlin with arguments 0.01 0.01 0 36 37 38# SMPTE frequencies 39# 40#Flo = 60 41#Fhi = 7000 42 43# DIN frequencies 44# 45Flo = 250 46Fhi = 8000 47 48 49# Test levels (dB, level of low frequency) 50# 51Levels = [ -50, -45, -40, -35, -30, -25, -20, -15, -10, -5, 0 ] 52Mtime = 1.0 53 54 55# Create a Jacksignal object. 56# 57J = JackSignal("IMtest") 58if J.get_state() < 0: 59 print ("Failed to create JackSignal -- is the server running ?") 60 exit(1) 61 62# Get Jack info. 63# 64name, Fsamp, period = J.get_jack_info() 65 66# Create ports and connect 67# 68J.create_output (0, "out") 69J.create_input (0, "in") 70J.silence() 71J.connect_output (0, "jack_nonlin:in") 72J.connect_input (0, "jack_nonlin:out") 73 74# Length of test signals in samples. 75# 76siglen = int (Mtime * Fsamp + 0.5) 77margin = 1000 78buflen = siglen + margin 79 80# Generate test signal, will be scaled for output. 81# 82Aout = ( gen_sinewave (1.00, Flo, Fsamp, buflen) 83 + gen_sinewave (0.25, Fhi, Fsamp, buflen)).astype (np.float32) 84 85# Input buffer. 86# 87Ainp = np.zeros ((buflen,), dtype = np.float32) 88 89# Generate reference signals for selective measurement. 90# 91Mlo = gen_complex (Flo, Fsamp, siglen) 92Mhi = gen_complex (Fhi, Fsamp, siglen) 93M3a = gen_complex (Fhi - 2 * Flo, Fsamp, siglen) 94M2a = gen_complex (Fhi - 1 * Flo, Fsamp, siglen) 95M2b = gen_complex (Fhi + 1 * Flo, Fsamp, siglen) 96M3b = gen_complex (Fhi + 2 * Flo, Fsamp, siglen) 97 98 99# Run test. 100# 101N = len (Levels) 102D2 = [ 0 for i in range (N) ] 103D3 = [ 0 for i in range (N) ] 104 105for i in range (N): 106 107 # Define signal buffers and run test. 108 amp = pow (10.0, Levels [i] / 20.0) 109 J.set_output_data (0, amp * Aout) 110 J.set_input_data (0, Ainp) 111 J.process() 112 J.wait() 113 114 # Skip margin samples and measure. 115 # We are not interested in the phase here. 116 # 117 T = Ainp [margin:] 118 Llo,p = sigdetect (T, Mlo) 119 Lhi,p = sigdetect (T, Mhi) 120 L3a,p = sigdetect (T, M3a) 121 L2a,p = sigdetect (T, M2a) 122 L2b,p = sigdetect (T, M2b) 123 L3b,p = sigdetect (T, M3b) 124 125 # Print results. 126 # 127 dblo = 20 * log10 (Llo + 1e-30) 128 dbhi = 20 * log10 (Lhi + 1e-30) 129 D2 [i] = im2 = 100 * hypot (L2a, L2b) / Lhi 130 D3 [i] = im3 = 100 * hypot (L3b, L3b) / Lhi 131 print ("Level = %5.1f Al = %5.1f Ah = %5.1f im2 = %6.3f%% im3 = %6.3f%%" % (Levels [i], dblo, dbhi, im2, im3)) 132 133# Stop the Jacksignal process. 134del J 135 136# Create a nice graph to present the results. 137# 138Levels = np.array (Levels) 139fig = plt.figure (figsize=(8,5), facecolor='white') 140ax = fig.add_axes ([0.07, 0.05, 0.86, 0.90]) 141ax.set_title ("% Intermodulation distortion (DIN)") 142ax.set_xlim (-55, 5) 143ax.set_ylim (1e-3, 1e1) 144ax.set_yscale ('log') 145ax.bar (Levels - 0.9, D2, 0.8, color = 'b') 146ax.bar (Levels + 0.1, D3, 0.8, color = 'g') 147ax.text (-51, 5.0, 'IM2', size = 17, color = 'b') 148ax.text (-46, 5.0, 'IM3', size = 17, color = 'g') 149ax.grid () 150plt.show () 151 152