Pickup Wizard

Version 1.0
Copyright 2022, Helmut Keller

Contents

Reset GNU Octave or MATLAB completely

clear all
close all
clc

Add function directories to search path

addpath('Functions','-end')
addpath('GUI Callback Functions','-end')

Get directory of persistent parameters

global persParamsDir
persParamsDir = strcat(pwd(),'/Persistent Parameters/');
if (~isfolder(persParamsDir))
    mkdir(persParamsDir)
end

Constants

global fs
fs = 48000;     % sample rate of the audio devices / Hz
global nbits
nbits = 24;     % bit depth of the audio devices
global channels
channels = 2;   % number of input channels of the audio device
global f1
f1 = 16;        % start frequency of log-sine sweep / Hz
global f2
f2 = 22000;     % stop frequency of log-sine sweep / Hz
global ts
ts= 3.00;       % sweep time / s
global tp
tp = 1;         % pause time /s
global tf
tf = 0.025;     % fade in and fade out time /s
global tp1
tp1 = 1;        % pause time before the sweeps
global tp2
tp2 = 1;        % pause time after the sweeps
fa = 20;                  % lowest frequency / Hz
fb = 20000;               % highest frequency Hz
global npd
npd = 120;                % nummber of points per decade
ef = 0:1/npd:log10(fb/fa);
global f
f = fa*10.^(ef);          % frequency / Hz, vector for transfer functions

sn=strcat(persParamsDir,'-.mat');
save('-mat',sn, 'f');     % save f for extrenal usage
global relmin
relmin = 1/10000; % lower parameter limit relativ to start value

Load persistent parameters

global audioInputName       % name of selected audio input device
global audioOutputName      % name of selected audio output device

sn=strcat(persParamsDir,'audioDevice.mat');
if exist(sn, 'file') == 2
    load(sn);
else
    audioInputName ='no input';
    audioOutputName ='no output';
    save('-mat',sn,'audioInputName','audioOutputName');
end
global Ls                   % level of sweep signal / dBFS
global ns                   % number of sweeps
global plf                  % powerline frequency / Hz
global isHumSuppression     % do hum suppression if true
global Rs                   % sense resistance of adaptor / Ohm
global isCrosstalkComp      % do crosstalk compenstion if true

sn=strcat(persParamsDir,'basicParams.mat');
if exist(sn, 'file') == 2
    load(sn,'-mat');
else
    Ls = -1;
    ns = 1;
    plf = 50;
    isHumSuppression = true;
    Rs = 1e6;
    isCrosstalkComp = true;
    save('-mat',sn, 'Ls', 'ns','plf', 'isHumSuppression', 'Rs', 'isCrosstalkComp');
end
global Hcal                 % transfer function from input 1 to 2

sn = strcat(persParamsDir,'Hcal.mat');
if exist(sn, 'file') == 2
    load(sn);
else
    Hcal=ones(1,length(f));
    save('-mat',sn, 'Hcal');
end
global Hcross               % crosstalk from input 1 to 2

sn = strcat(persParamsDir,'Hcross.mat');
if exist(sn, 'file') == 2
    load(sn);
else
    Hcross=ones(1,length(f));
    save('-mat',sn, 'Hcross');
end
global Cs                   % capacity parallel to Rs / F
global Ci                   % capacity of audio input / F
global Ri                   % resistance of audio input / Ohm
global Cdc                  % capacity of audio input DC blocker / F
global rmseZcal             % RMS error of Zcal appoximation

sn = strcat(persParamsDir,'zcalParams.mat');
if exist(sn, 'file') == 2
    load(sn);
else
    Cs = 1e-12;
    Ci = 100e-12;
    Ri = 1e6;
    Cdc = 1e-6;
    rmseZcal = 0.1;
    save('-mat',sn, 'Cs', 'Ci', 'Ri', 'Cdc', 'rmseZcal');
end
global Rv                   % resistance of volume potiomneter  / Ohm
global Rt                   % resistance of tone potiomneter  / Ohm
global Ct                   % tone capacity / F
global isGitLoad            % no  guitar load if true

sn = strcat(persParamsDir,'gitParams.mat');
if exist(sn, 'file') == 2
    load(sn);
else
    Rv = 500e3;
    Rt = 500e3;
    Ct = 22e-9;
    isGitLoad = true;
    save('-mat',sn, 'Rv', 'Rt' , 'Ct', 'isGitLoad');
end
global puDataDir            % selected directory of pickup impedance file
global puzFname             % selected filename of pickup impedance file

sn = strcat(persParamsDir,'puDirFname.mat');
if exist(sn, 'file') == 2
    load(sn);
else
    puDataDir = strcat(pwd(),'/Pickup Data/');
    if ~isfolder(puDataDir)
        mkdir(puDataDir)
    end
    puzFname='';
    save('-mat',sn,'puDataDir', 'puzFname');
end
global sR0                  % R0 start value / Ohm
global isR0Variable         % R0 is variable if true
global sC0                  % C0 start value / F
global sLs                  % L start values / H for three subcoils
global sRs                  % R start values / Ohm for three subcoils

sn = strcat(persParamsDir,'approxStartValues.mat');
if exist(sn, 'file') == 2
    load(sn);
else
    sR0  = 10e3;
    isR0Variable = true;
    sC0 = 100e-12;
    sLs = [2 0.5 0.0];
    sRs = [500 10 0.0 ]*1000;
    save('-mat',sn, 'sR0', 'isR0Variable', 'sC0', 'sLs', 'sRs')
end
global Rls                  % load resitances/ Ohm
global Cls                  % load capacities /F

sn = strcat(persParamsDir,'loadParams.mat');
if exist(sn, 'file') == 2
    load(sn);
else
    Rls = [200 200 200]*1000;
    Cls = [400 700 1000]*1e-12;
    save('-mat',sn, 'Rls', 'Cls');
end

Initialize programm

global td    % short additional pause for optimal hum reduction with ns > 1
if plf >55
    td = 494/fs;
else
    td = 593/fs;
end

global y
y = testsignal;    % ns log-sine sweeps
sppi = get(0,'screenpixelsperinch');
global sfontsize
sfontsize = round(10*sppi/96); % fontzize for GUI size corrections

Generate the GUI

% Main Window

global hdt
hdt = [];  % handle to PU data table, delete it before plotting

fm = figure('units', 'normalized' ...
    ,'position',[ 0.15, 0.15, 0.7, 0.7] ...
    ,'units', 'normalized' ...
    ,'color',[1 1 1] ...
    ,'numbertitle','off' ...
    ,'name','Pickup Wizard' ...
    ,'menubar','none' ...
    ,'DeleteFcn',@(h,e) cancelMeasurement ...
    );

logo=imread('Gitec Logo.png');
image(logo);
axis image
axis off

% Settings Menu

m1=uimenu(fm,'label','Settings');

global m11
m11 =uimenu(m1,'label','Audio input device','callback', 'cb_m11');
global m12
m12 =uimenu(m1,'label','Audio output device','callback', 'cb_m12');
global m13
m13 = uimenu(m1,'label','Basic parameters','callback', 'cb_m13');

% Calibration menu

m2=uimenu(fm,'label','Calibration');

global m21
m21 =uimenu(m2,'label','Calibrate transfer function','callback','cb_m21');
global m22
m22 =uimenu(m2,'label','Calibrate crosstalk','callback', 'cb_m22');

global m23
m23 =uimenu(m2,'label','Calibrate impedance','callback', 'cb_m23');

% Tools Menu

m3=uimenu(fm,'label','Tools');

global m31
m31 =uimenu(m3,'label','FFT Analyzer','callback', 'cb_m31');
global m32
m32 =uimenu(m3,'label','Calculate R0 and Rv','callback', 'cb_m32');

% Measurement menu

m4=uimenu(fm,'label','Measurement');

global m41
m41 =uimenu(m4,'label','Guitar load','callback', 'cb_m41');
global m42
m42 =uimenu(m4,'label','Measure impedance','callback', 'cb_m42');
global m43
m43 =uimenu(m4,'label','Approximation start values','callback', 'cb_m43');
global m44
m44 =uimenu(m4,'label','Approximate impedance','callback', 'cb_m44');

% Diplay menu

m5=uimenu(fm,'label','Display ');

global m51
m51 =uimenu(m5,'label','Display Z','callback', 'cb_m51');
global m52
m52 =uimenu(m5,'label','Display Z and Za','callback', 'cb_m52');
global m53
m53 =uimenu(m5,'label','Frequency response loads','callback', 'cb_m53');
global m54
m54 =uimenu(m5,'label','Display frequency response','callback','cb_m54');
global m55
m55 =uimenu(m5,'label','Display pickup data table','callback', 'cb_m55');

% Help menu

m6=uimenu(fm,'label','Help');

global m61
m61 =uimenu(m6,'label','About','callback', 'cb_m61');