From b2ef37ad8c96635ba276a99762a0b533400ddd74 Mon Sep 17 00:00:00 2001 From: Henry Nomeland Date: Thu, 22 Feb 2024 10:39:42 -0600 Subject: [PATCH 01/11] testing --- .gitignore | 4 ++++ wave_viewer.m | 7 ++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 454c7ff..b5dd851 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ # matlab autosave files *.asv *.m~ +# other files being used in testing +audioGUI.m +*.mat +*/* diff --git a/wave_viewer.m b/wave_viewer.m index dec0bff..2165e7c 100644 --- a/wave_viewer.m +++ b/wave_viewer.m @@ -124,7 +124,7 @@ %% set up GUI % create new figure -hf = figure('Name',p.plot_params.name,'Units','normalized','Position',p.plot_params.figpos); +hf = figure('Name',p.plot_params.name,'Units','normalized','Position',p.plot_params.figpos); set(hf,'DeleteFcn',@delete_func); p.guidata = guihandles(hf); @@ -390,10 +390,6 @@ function edit_events(hObject,eventdata) % callback for h_button_edit_events end end - - - - % clear events button clearEventsButtonPos = [padL+buttonWidth*1/2 horiz_orig buttonWidth*1/2 buttonHeight]; hbutton.clear_events = uicontrol(p.guidata.buttonPanel,'Style','pushbutton',... @@ -669,6 +665,7 @@ function toggle_formants(hObject,eventdata) % callback for hbutton.toggle_forman end set(gram_ax,'UserData',axinfo); end + % calc button calcButtonPos = [padL horiz_orig buttonWidth buttonHeight]; hbutton.calc = uicontrol(p.guidata.buttonPanel,'Style','pushbutton',... From 32260d63c668069077947c07d54d06fd33476ebd Mon Sep 17 00:00:00 2001 From: Henry Nomeland Date: Thu, 21 Mar 2024 09:34:33 -0500 Subject: [PATCH 02/11] small updates --- get_formant_tracks.m | 203 ++++--------------------------------------- 1 file changed, 15 insertions(+), 188 deletions(-) diff --git a/get_formant_tracks.m b/get_formant_tracks.m index 8fab430..43d90b1 100644 --- a/get_formant_tracks.m +++ b/get_formant_tracks.m @@ -1,8 +1,5 @@ function [ftrack_out,ftrack_mstaxis,ftrack_lpc_coeffs] = get_formant_tracks(y,fs,faxis,ms_framespec,nlpc_coeffs,yes_preemph,nformants,ftrack_method,yes_verbose) -frames_per_dot = 10; -dots_per_line = 50; - if nargin < 2 || isempty(fs), fs = 11025; end if nargin < 3 || isempty(faxis), faxis = linspace(0,fs/2,1025); end if nargin < 4 || isempty(ms_framespec), ms_framespec = 'narrowband'; end @@ -15,9 +12,6 @@ params.fs = fs; params.nlpc = nlpc_coeffs; switch ftrack_method - case 'colea', ftrack_func = @colea_ftrack_func; params.nformants_max = 3; params.yes_trackperframe = 1; - case 'mine', ftrack_func = @my_ftrack_func; params.nformants_max = 3; params.yes_trackperframe = 1; - case 'mine2', ftrack_func = @my_ftrack_func2; params.nformants_max = 4; params.yes_trackperframe = 1; case 'praat', ftrack_func = @praat_ftrack_func; params.nformants_max = 5; params.yes_trackperframe = 0; otherwise, error('formant tracking method(%s) unrecognized',ftrack_method); end @@ -26,41 +20,18 @@ params.nformants = nformants; params.faxis = faxis; -starting_formants = [500 1500 2500 3500]; - -[nsamps,yes_y_is_rowvec] = get_len_yvec(y); +[nsamps,~] = get_len_yvec(y); [ms_awin,ms_astep,nsamps_frame,nsamps_astep] = get_ms_framespec(ms_framespec,fs); -win = hann(nsamps_frame)/sum(hann(nsamps_frame)); -if ~yes_y_is_rowvec, win = win'; end y = my_preemph(y,yes_preemph); nframes = floor((nsamps - nsamps_frame)/nsamps_astep); -ftrack = zeros(nformants,nframes); -ftrack_mstaxis = zeros(1,nframes); -lpc_coeffs = zeros((nlpc_coeffs+1),nframes); -if params.yes_trackperframe % if tracker operates on a frame-by-frame basis within Matlab - for iframe = 1:nframes - yframe = y((iframe-1)*nsamps_astep + (1:nsamps_frame)); - ftrack_mstaxis(iframe) = 1000*mean((iframe-1)*nsamps_astep + (1:nsamps_frame))/fs; - ywinframe = win .* yframe; - if iframe > 1, params.Fprev = ftrack(:,iframe-1); else params.Fprev = starting_formants; end - output = ftrack_func(ywinframe,params); - ftrack(:,iframe) = output{1}; - lpc_coeffs(:,iframe) = output{2}; - if yes_verbose - if ~rem(iframe,frames_per_dot), fprintf('.'); end - if ~rem(iframe,frames_per_dot*dots_per_line), fprintf('%d\n',iframe); end - end - end -else % if we want to pass entire utterance to external tracker - params.window_size = ms_awin/1000; - params.step_size = ms_astep/1000; - params.nframes = nframes; - output = ftrack_func(y,params); - ftrack = output{1}; - lpc_coeffs = output{2}; - ftrack_mstaxis = output{3}; -end +params.window_size = ms_awin/1000; +params.step_size = ms_astep/1000; +params.nframes = nframes; +output = ftrack_func(y,params); +ftrack = output{1}; +lpc_coeffs = output{2}; +ftrack_mstaxis = output{3}; % ftrack_out(1:nformants,1:nframes) = ftrack(1:nformants,1:nframes); ftrack_out(1:nformants,:) = ftrack(1:nformants,:); %removing nframes allows for praat tracking @@ -69,64 +40,6 @@ end if nargout >= 3, ftrack_lpc_coeffs = lpc_coeffs; end - -% must have colea on matlab path to use this function -function output = colea_ftrack_func(ywinframe,params) - -fs = params.fs; -nlpc_coeffs = params.nlpc; -nformants = params.nformants; - -lpc_coeffs = lpc(ywinframe,nlpc_coeffs); -[frmnt(1),frmnt(2),frmnt(3)] = frmnts(lpc_coeffs,fs); -formant(1:nformants) = frmnt(1:nformants); - -output{1} = formant; -output{2} = lpc_coeffs; - -function output = my_ftrack_func(ywinframe,params) - -fs = params.fs; -nlpc_coeffs = params.nlpc; -nformants = params.nformants; - -lpc_coeffs = lpc(ywinframe,nlpc_coeffs); -[frmnt(1),frmnt(2),frmnt(3)] = my_frmnts(lpc_coeffs,fs); - -formant(1:nformants) = frmnt(1:nformants); - -output{1} = formant; -output{2} = lpc_coeffs; - - -function output = my_ftrack_func2(ywinframe,params) - -fs = params.fs; -faxis = params.faxis; -nlpc_coeffs = params.nlpc; -nformants = params.nformants; -Fprev = params.Fprev; - -lpc_coeffs = lpc(ywinframe,nlpc_coeffs); -lpc_magspec = get_lpc_magspec(lpc_coeffs,faxis,fs); -[lpc_magspec_peaks,nlpc_magspec_peaks] = peakfind(lpc_magspec); -for iformant = 1:nformants - if iformant < nlpc_magspec_peaks - formant(iformant) = faxis(lpc_magspec_peaks(iformant)); - elseif iformant == nlpc_magspec_peaks - formant(iformant) = faxis(lpc_magspec_peaks(iformant)); - if abs(Fprev(iformant)-formant(iformant)) > 75 - formant(iformant) = Fprev(iformant); - end - else - formant(iformant) = Fprev(iformant); - end -end - -output{1} = formant; -output{2} = lpc_coeffs; - - function output = praat_ftrack_func(y,params) % execute Praat script using params %must be in git repo folder to run praat function, so save current location and go there @@ -136,8 +49,6 @@ cd(praat_path) fs = params.fs; -faxis = params.faxis; -nlpc_coeffs = params.nlpc; nformants = params.nformants; %%% Praat wrapper code here @@ -158,10 +69,10 @@ error('Something went wrong in Praat analysis') end -% clean up praat output text file to eliminate uniterpretable characters +% clean up praat output text file to eliminate uninterpretable characters A = regexp( fileread('temp_wav_formants.txt'), '\n', 'split'); headers = strsplit(A{1},'\t'); -if length(headers) == 1 %for some reason Praat sometimes uses a space to separate headers +if length(headers) == 1 % for some reason Praat sometimes uses a space to separate headers headers = strsplit(A{1},' '); end for i = 1:length(headers) @@ -180,7 +91,7 @@ % load formant tracks from file written by Praat and put in 'formant' output formant_vals = readtable('temp_wav_formants.txt','Delimiter','\t'); -%find number of formant values returbned by praat +%find number of formant values returned by praat for nf = 1:nformants form=['F' num2str(nf)]; formant(nf,:) = formant_vals.(form)'; @@ -189,96 +100,12 @@ %find times of formants msaxis = formant_vals.time'; -% load LPC values from file written by Praat and put in 'lpc_coeffs' output -% lpc_coeffs = dlmread('temp_wav_lpc.txt','\t'); -lpc_coeffs = []; -% clean up by deleting files that were created and return to previous -% directory -delete temp_wav.wav temp_wav_formants.txt %temp_wav_lpc.txt +% clean up by deleting files and return to previous directory +delete temp_wav.wav temp_wav_formants.txt cd(curr_dir) +% establish outputs +lpc_coeffs = []; output{1} = formant; output{2} = lpc_coeffs; output{3} = msaxis * 1000; %covert from s to ms - - -% my version of the colea frmnts function, -% orinally copyright (c) 1998 by Philipos C. Loizou -function [F1,F2, F3]=my_frmnts(lpc_coeffs,fs) - -global F1prev F2prev F3prev - -min_formant_freq = 90; -max_formant_freq = 4000; -max_formant_bw = 500; -defaultF1 = 300; defaultF2 = 1200; defaultF3 = 3000; - -max_allowable_F1dev = 150; -max_allowable_F2dev = 150; -min_initial_formant_sep = 80; -min_formant_sep = 50; - -const = fs/(2*pi); -rts = roots(lpc_coeffs); -k = 1; -for i=1:length(lpc_coeffs)-1 - re = real(rts(i)); im = imag(rts(i)); - the_formant_cand = const*atan2(im,re); %--formant frequencies - formant_bw = -0.5*const*log(abs(rts(i)));%--formant bandwidth - if (the_formant_cand < max_formant_freq) & ... - (the_formant_cand > min_formant_freq) & ... - (formant_bw < max_formant_bw) - unsort_candidate_formant(k) = the_formant_cand; - bandw(k) = formant_bw; - k = k + 1; - end -end -candidate_formant = sort(unsort_candidate_formant); -ncand_formants = length(candidate_formant); - -if isempty(F1prev) %++++++++++++++++ the first frame ++++++++++++++++++ - if 2 > ncand_formants - F1 = defaultF1; F2 = defaultF2; F3 = defaultF3; - elseif abs(candidate_formant(1)-candidate_formant(2)) < min_initial_formant_sep - F1 = candidate_formant(2); F2 = candidate_formant(3); - if 3 > ncand_formants, F3 = candidate_formant(4); else F3 = defaultF3; end - elseif 4 == ncand_formants - F1 = candidate_formant(2); F2 = candidate_formant(3); - F3 = candidate_formant(4); - else - F1 = candidate_formant(1); F2 = candidate_formant(2); - if 3 > ncand_formants, F3 = defaultF3; else F3 = candidate_formant(3); end - end -else %++++++++++++++++ all frames after the first ++++++++++++++++++ - %----Impose some formant continuity constraints ------------------- - in1 = find(abs(F1prev-candidate_formant) < max_allowable_F1dev); - in2 = find(abs(F2prev-candidate_formant) < max_allowable_F2dev); - if length(in1) > 1, i1 = in1(2); else i1 = in1; end - if length(in2) > 1, i2 = in2(2); else i2 = in2; end - - switch (10*(~isempty(i1)) + (~isempty(i2))) - case 11 - if i1 == i2 - if 1 > ncand_formants, F1 = F1prev; else F1 = candidate_formant(1); end - if 2 > ncand_formants, F2 = F2prev; else F2 = candidate_formant(2); end - if 3 > ncand_formants, F3 = F3prev; else F3 = candidate_formant(3); end - else - F1 = candidate_formant(i1); F2 = candidate_formant(i2); - if i2 + 1 > ncand_formants, F3 = F3prev; else F3 = candidate_formant(i2 + 1); end - end - case 10 - F1 = candidate_formant(i1); - if i1 + 1 > ncand_formants, F2 = F2prev; else F2 = candidate_formant(i1 + 1); end - if i1 + 2 > ncand_formants, F3 = F3prev; else F3 = candidate_formant(i1 + 2); end - otherwise - F1 = candidate_formant(1); - if 2 > ncand_formants, F2 = F2prev; else F2 = candidate_formant(2); end - if 3 > ncand_formants, F3 = F3prev; else F3 = candidate_formant(3); end - end -end - -% --last check .. -------- -if abs(F2-F3) < min_formant_sep, F2 = F2prev; F3 = F3prev; end -if abs(F2-F1) < min_formant_sep, F2 = F2prev; F3 = F3prev; end - -F1prev = F1; F2prev = F2; F3prev = F3; From 002bbc25887fa9efe8d39ae42fa6ce12a4deb5db Mon Sep 17 00:00:00 2001 From: Henry Nomeland Date: Tue, 2 Apr 2024 10:40:54 -0500 Subject: [PATCH 03/11] fast track testing --- .gitignore | 1 + ...mant_tracks.praat => get_fast_tracks.praat | 26 ++-- get_formant_tracks.m | 138 +++++++++--------- 3 files changed, 86 insertions(+), 79 deletions(-) rename get_formant_tracks.praat => get_fast_tracks.praat (50%) diff --git a/.gitignore b/.gitignore index b5dd851..9e85ac2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ audioGUI.m *.mat */* +temp_wav.wav diff --git a/get_formant_tracks.praat b/get_fast_tracks.praat similarity index 50% rename from get_formant_tracks.praat rename to get_fast_tracks.praat index 01d2d66..20d4cd8 100644 --- a/get_formant_tracks.praat +++ b/get_fast_tracks.praat @@ -1,19 +1,22 @@ -# get_formants.praat -# BEN PARRELL 18 DEC 2017 +# get_fast_tracks.praat by Henry Nomeland, 21 Mar 2024 +# adapted from get_formants.praat by Ben Parrell, 18 Dec 2017 # -# Measure formants for whole .wav file -# For use with wave_viewer +# measures formants for a .wav file utilizing tools and utils of FastTrack +# FastTrack code available here: https://github.com/santiagobarreda/FastTrack/ +# for use with wave_viewer + +include utils/trackAutoselectProcedure.praat #Inputs form Measure formant values for segments in a textgrid sentence directory_name: /Users/Ben/Documents/MATLAB/wave_viewer - sentence file_name: temp_wav + sentence file_name: temp_wav + positive minimum_formant 0 positive maximum_formant 5500 - positive number_of_formants 5 - positive window_size 0.025 - positive time_step 0.005 - positive preemphasis 50 - positive fs 11025 + positive number_steps 100 + positive num_coefs 10 + positive num_formants 3 + sentence tracking_method: burg endform #open the sound and select it @@ -22,7 +25,8 @@ Read from file... 'directory_name$'/'wav_name$' soundID1$ = selected$("Sound") #extract formants -To Formant (burg)... 'time_step' 'number_of_formants' 'maximum_formant' 'window_size' 'preemphasis' +@trackAutoselectProcedure: soundID1$, directory_name$, minimum_formant, maximum_formant, number_steps, num_coefs, num_formants, tracking_method$, 0, soundID1$, 0, 5500, 2, 0, 0 +selectObject: soundID1$ formant = selected ("Formant") #write formants diff --git a/get_formant_tracks.m b/get_formant_tracks.m index 43d90b1..feb2496 100644 --- a/get_formant_tracks.m +++ b/get_formant_tracks.m @@ -6,7 +6,7 @@ if nargin < 5 || isempty(nlpc_coeffs), nlpc_coeffs=14; end if nargin < 6 || isempty(yes_preemph), yes_preemph = 1; end if nargin < 7 || isempty(nformants), nformants = 0; end -if nargin < 8 || isempty(ftrack_method), ftrack_method = 'mine'; end +if nargin < 8 || isempty(ftrack_method), ftrack_method = 'praat'; end if nargin < 9 || isempty(yes_verbose), yes_verbose = 0; end params.fs = fs; @@ -41,71 +41,73 @@ if nargout >= 3, ftrack_lpc_coeffs = lpc_coeffs; end function output = praat_ftrack_func(y,params) -% execute Praat script using params -%must be in git repo folder to run praat function, so save current location and go there -curr_dir = pwd; -temp_str = which('get_formant_tracks.praat'); -praat_path = fileparts(temp_str); -cd(praat_path) - -fs = params.fs; -nformants = params.nformants; - -%%% Praat wrapper code here -% write y to file (this will be deleted later, it is just written to the -% current directory) -audiowrite('temp_wav.wav',y,fs) - -% set praat params that are not changeable -max_formant = 5500; -preemphasis = 50; - -if ismac - status = system(['"/Applications/Praat.app/Contents/MacOS/Praat" --run get_formant_tracks.praat "' pwd '" "temp_wav" ' num2str(max_formant) ' ' num2str(params.nlpc/2) ' ' num2str(params.window_size) ' ' num2str(params.step_size) ' ' num2str(preemphasis) ' ' num2str(params.fs)]); -else - status = system(['"C:\Users\Public\Desktop\Praat.exe" --run get_formant_tracks.praat "' pwd '" "temp_wav" ' num2str(max_formant) ' ' num2str(params.nlpc/2) ' ' num2str(params.window_size) ' ' num2str(params.step_size) ' ' num2str(preemphasis) ' ' num2str(params.fs)]); -end -if status ~= 0 - error('Something went wrong in Praat analysis') -end - -% clean up praat output text file to eliminate uninterpretable characters -A = regexp( fileread('temp_wav_formants.txt'), '\n', 'split'); -headers = strsplit(A{1},'\t'); -if length(headers) == 1 % for some reason Praat sometimes uses a space to separate headers - headers = strsplit(A{1},' '); -end -for i = 1:length(headers) - curTxt = headers{i}; - startUnits = strfind(curTxt,'('); - if ~isempty(startUnits) - curTxt = curTxt(1:startUnits-1); - headers{i} = curTxt; +%%% function which executes Praat script using params + %must be in git repo folder to run praat function, so save current location and go there + curr_dir = pwd; + temp_str = which('get_fast_tracks.praat'); + praat_path = fileparts(temp_str); + cd(praat_path) + + fs = params.fs; + nformants = params.nformants; + + %%% Praat wrapper code here + % write y to file (this will be deleted later, it is just written to the + % current directory) + audiowrite('temp_wav.wav',y,fs) + + % set praat params that are not changeable + max_formant = 5500; + preemphasis = 50; + + if ismac + status = system(['"/Applications/Praat.app/Contents/MacOS/Praat" --run get_fast_tracks.praat "' pwd '" "temp_wav" ' num2str(max_formant) ' ' num2str(params.nlpc/2) ' ' num2str(params.window_size) ' ' num2str(params.step_size) ' ' num2str(preemphasis) ' ' num2str(params.fs)]); + else + status = system(['"C:\Users\Public\Desktop\Praat.exe" --run get_fast_tracks.praat "' pwd '" "temp_wav" ' num2str(max_formant) ' ' num2str(params.nlpc/2) ' ' num2str(params.window_size) ' ' num2str(params.step_size) ' ' num2str(preemphasis) ' ' num2str(params.fs)]); end -end -A{1} = strjoin(headers,'\t'); -fid = fopen('temp_wav_formants.txt','w'); -fprintf(fid, '%s\n', A{:}); -fclose(fid); - -% load formant tracks from file written by Praat and put in 'formant' output -formant_vals = readtable('temp_wav_formants.txt','Delimiter','\t'); - -%find number of formant values returned by praat -for nf = 1:nformants - form=['F' num2str(nf)]; - formant(nf,:) = formant_vals.(form)'; -end - -%find times of formants -msaxis = formant_vals.time'; - -% clean up by deleting files and return to previous directory -delete temp_wav.wav temp_wav_formants.txt -cd(curr_dir) - -% establish outputs -lpc_coeffs = []; -output{1} = formant; -output{2} = lpc_coeffs; -output{3} = msaxis * 1000; %covert from s to ms + if status ~= 0 + error('Something went wrong in Praat analysis') + end + + % clean up praat output text file to eliminate uninterpretable characters + A = regexp( fileread('temp_wav_formants.txt'), '\n', 'split'); + headers = strsplit(A{1},'\t'); + if length(headers) == 1 % for some reason Praat sometimes uses a space to separate headers + headers = strsplit(A{1},' '); + end + for i = 1:length(headers) + curTxt = headers{i}; + startUnits = strfind(curTxt,'('); + if ~isempty(startUnits) + curTxt = curTxt(1:startUnits-1); + headers{i} = curTxt; + end + end + A{1} = strjoin(headers,'\t'); + fid = fopen('temp_wav_formants.txt','w'); + fprintf(fid, '%s\n', A{:}); + fclose(fid); + + % load formant tracks from file written by Praat and put in 'formant' output + formant_vals = readtable('temp_wav_formants.txt','Delimiter','\t'); + + %find number of formant values returned by praat + for nf = 1:nformants + form=['F' num2str(nf)]; % finds the particular formant number + formant(nf,:) = formant_vals.(form)'; % updates row in formant + end + + %find times of formants + msaxis = formant_vals.time'; + + % clean up by deleting files and return to previous directory + delete temp_wav.wav + % delete temp_wav_formants.txt + cd(curr_dir) + + % establish outputs + lpc_coeffs = []; + output{1} = formant; + output{2} = lpc_coeffs; + output{3} = msaxis * 1000; %covert from s to ms +%%% end of praat function From 60e4bd77f9caa107d610423d103a88cdb964891d Mon Sep 17 00:00:00 2001 From: Henry Nomeland Date: Thu, 4 Apr 2024 10:28:22 -0500 Subject: [PATCH 04/11] added autocontinue --- get_formant_tracks.m | 6 +++--- wave_viewer.m | 14 +++++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/get_formant_tracks.m b/get_formant_tracks.m index feb2496..476c2f2 100644 --- a/get_formant_tracks.m +++ b/get_formant_tracks.m @@ -44,7 +44,7 @@ %%% function which executes Praat script using params %must be in git repo folder to run praat function, so save current location and go there curr_dir = pwd; - temp_str = which('get_fast_tracks.praat'); + temp_str = which('get_formant_tracks.praat'); praat_path = fileparts(temp_str); cd(praat_path) @@ -61,9 +61,9 @@ preemphasis = 50; if ismac - status = system(['"/Applications/Praat.app/Contents/MacOS/Praat" --run get_fast_tracks.praat "' pwd '" "temp_wav" ' num2str(max_formant) ' ' num2str(params.nlpc/2) ' ' num2str(params.window_size) ' ' num2str(params.step_size) ' ' num2str(preemphasis) ' ' num2str(params.fs)]); + status = system(['"/Applications/Praat.app/Contents/MacOS/Praat" --run get_formant_tracks.praat "' pwd '" "temp_wav" ' num2str(max_formant) ' ' num2str(params.nlpc/2) ' ' num2str(params.window_size) ' ' num2str(params.step_size) ' ' num2str(preemphasis) ' ' num2str(params.fs)]); else - status = system(['"C:\Users\Public\Desktop\Praat.exe" --run get_fast_tracks.praat "' pwd '" "temp_wav" ' num2str(max_formant) ' ' num2str(params.nlpc/2) ' ' num2str(params.window_size) ' ' num2str(params.step_size) ' ' num2str(preemphasis) ' ' num2str(params.fs)]); + status = system(['"C:\Users\Public\Desktop\Praat.exe" --run get_formant_tracks.praat "' pwd '" "temp_wav" ' num2str(max_formant) ' ' num2str(params.nlpc/2) ' ' num2str(params.window_size) ' ' num2str(params.step_size) ' ' num2str(preemphasis) ' ' num2str(params.fs)]); end if status ~= 0 error('Something went wrong in Praat analysis') diff --git a/wave_viewer.m b/wave_viewer.m index 2165e7c..b3821de 100644 --- a/wave_viewer.m +++ b/wave_viewer.m @@ -846,7 +846,15 @@ function fig_resize_func(src,event) set(hf,'KeyPressFcn',@key_press_func); set(hf,'ResizeFcn',@fig_resize_func); if yes_profile, profile off; end -if yes_start_blocking, uiwait(hf); end +if yes_start_blocking && p.sigproc_params.autocont ~= 1, uiwait(hf); end + +%%% CODE FOR AUTOCONTINUE +if p.sigproc_params.autocont + if p.sigproc_params.autocont == 1 + contprogram([],[]); + end +end + end %% @@ -2308,8 +2316,8 @@ function set_viewer_axlims(hax,t_min,t_max,dat4minmax,yax_fact2use) 'ptrack_voicing_thresh', 0.45, ... 'ptrack_octave_cost', 0.01, ... 'ptrack_octave_jump_cost', 0.35, ... - 'ptrack_voiced_unvoiced_cost', 0.14); - + 'ptrack_voiced_unvoiced_cost', 0.14, ... + 'autocont', 0); end %% get figure params (used to be global vars) From 1ea75571fa4229c506c0ced6e8932efa2eff7d63 Mon Sep 17 00:00:00 2001 From: Henry Nomeland Date: Thu, 18 Apr 2024 10:44:56 -0500 Subject: [PATCH 05/11] fast track implementation --- get_fast_tracks.praat | 31 ++++++++++++++++++------------- get_formant_tracks.m | 6 +++--- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/get_fast_tracks.praat b/get_fast_tracks.praat index 20d4cd8..1cf91c9 100644 --- a/get_fast_tracks.praat +++ b/get_fast_tracks.praat @@ -5,28 +5,33 @@ # FastTrack code available here: https://github.com/santiagobarreda/FastTrack/ # for use with wave_viewer -include utils/trackAutoselectProcedure.praat - #Inputs form Measure formant values for segments in a textgrid - sentence directory_name: /Users/Ben/Documents/MATLAB/wave_viewer + sentence dir: /Users/Ben/Documents/MATLAB/wave_viewer sentence file_name: temp_wav - positive minimum_formant 0 - positive maximum_formant 5500 - positive number_steps 100 - positive num_coefs 10 - positive num_formants 3 - sentence tracking_method: burg endform -#open the sound and select it +include utils/trackAutoselectProcedure.praat +@getSettings + +formants = 3 +time_step = 0.002 +method$ = burg +steps = 20 +coefficients = 5 +out_formant = 2 +fastTrackMinimumDuration = 0.030000000000001 +lowestAnalysisFrequency = 0 +highestAnalysisFrequency 5500 + wav_name$ = file_name$ + ".wav" Read from file... 'directory_name$'/'wav_name$' soundID1$ = selected$("Sound") +select Sound 'soundID1$' + +if windowDuration >= fastTrackMinimumDuration + @trackAutoselect: selected(), dir$, lowestAnalysisFrequency, highestAnalysisFrequency, steps, coefficients, formants, method$, 0, selected(), 0, 4000, 2, 2, 0 -#extract formants -@trackAutoselectProcedure: soundID1$, directory_name$, minimum_formant, maximum_formant, number_steps, num_coefs, num_formants, tracking_method$, 0, soundID1$, 0, 5500, 2, 0, 0 -selectObject: soundID1$ formant = selected ("Formant") #write formants diff --git a/get_formant_tracks.m b/get_formant_tracks.m index 476c2f2..16f3f36 100644 --- a/get_formant_tracks.m +++ b/get_formant_tracks.m @@ -44,7 +44,7 @@ %%% function which executes Praat script using params %must be in git repo folder to run praat function, so save current location and go there curr_dir = pwd; - temp_str = which('get_formant_tracks.praat'); + temp_str = which('get_fast_tracks.praat'); praat_path = fileparts(temp_str); cd(praat_path) @@ -61,9 +61,9 @@ preemphasis = 50; if ismac - status = system(['"/Applications/Praat.app/Contents/MacOS/Praat" --run get_formant_tracks.praat "' pwd '" "temp_wav" ' num2str(max_formant) ' ' num2str(params.nlpc/2) ' ' num2str(params.window_size) ' ' num2str(params.step_size) ' ' num2str(preemphasis) ' ' num2str(params.fs)]); + status = system(['"/Applications/Praat.app/Contents/MacOS/Praat" --run get_fast_tracks.praat "' pwd]); else - status = system(['"C:\Users\Public\Desktop\Praat.exe" --run get_formant_tracks.praat "' pwd '" "temp_wav" ' num2str(max_formant) ' ' num2str(params.nlpc/2) ' ' num2str(params.window_size) ' ' num2str(params.step_size) ' ' num2str(preemphasis) ' ' num2str(params.fs)]); + status = system(['"C:\Users\Public\Desktop\Praat.exe" --run get_fast_tracks.praat "' pwd]); end if status ~= 0 error('Something went wrong in Praat analysis') From ff4955a3fc2dda4db292454935b7c54c3d024029 Mon Sep 17 00:00:00 2001 From: Henry Nomeland Date: Thu, 25 Apr 2024 12:16:30 -0500 Subject: [PATCH 06/11] fast track implementation --- get_fast_tracks.praat | 11 +++++------ get_formant_tracks.m | 16 ++++++++-------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/get_fast_tracks.praat b/get_fast_tracks.praat index 1cf91c9..dbafe25 100644 --- a/get_fast_tracks.praat +++ b/get_fast_tracks.praat @@ -16,28 +16,27 @@ include utils/trackAutoselectProcedure.praat formants = 3 time_step = 0.002 -method$ = burg steps = 20 coefficients = 5 out_formant = 2 fastTrackMinimumDuration = 0.030000000000001 lowestAnalysisFrequency = 0 -highestAnalysisFrequency 5500 +highestAnalysisFrequency = 5500 +method$ = "burg" wav_name$ = file_name$ + ".wav" -Read from file... 'directory_name$'/'wav_name$' +Read from file... 'dir$'/'wav_name$' soundID1$ = selected$("Sound") select Sound 'soundID1$' -if windowDuration >= fastTrackMinimumDuration - @trackAutoselect: selected(), dir$, lowestAnalysisFrequency, highestAnalysisFrequency, steps, coefficients, formants, method$, 0, selected(), 0, 4000, 2, 2, 0 +@trackAutoselect: selected(), dir$, lowestAnalysisFrequency, highestAnalysisFrequency, steps, coefficients, formants, method$, 0, selected(), 0, 4000, 2, 0, 0 formant = selected ("Formant") #write formants formant_name$ = file_name$ + "_formants.txt" Down to Table... yes yes 6 no 3 yes 3 no -Save as tab-separated file... 'directory_name$'/'formant_name$' +Save as tab-separated file... 'dir$'/'formant_name$' #extract LPC parameters #selectObject: formant diff --git a/get_formant_tracks.m b/get_formant_tracks.m index 16f3f36..11f4bbc 100644 --- a/get_formant_tracks.m +++ b/get_formant_tracks.m @@ -41,7 +41,7 @@ if nargout >= 3, ftrack_lpc_coeffs = lpc_coeffs; end function output = praat_ftrack_func(y,params) -%%% function which executes Praat script using params +%%% function which executes Fast Track script using params %must be in git repo folder to run praat function, so save current location and go there curr_dir = pwd; temp_str = which('get_fast_tracks.praat'); @@ -49,21 +49,21 @@ cd(praat_path) fs = params.fs; + faxis = params.faxis; + nlpc_coeffs = params.nlpc; nformants = params.nformants; - + %%% Praat wrapper code here % write y to file (this will be deleted later, it is just written to the % current directory) audiowrite('temp_wav.wav',y,fs) - - % set praat params that are not changeable max_formant = 5500; preemphasis = 50; if ismac - status = system(['"/Applications/Praat.app/Contents/MacOS/Praat" --run get_fast_tracks.praat "' pwd]); + status = system(['"/Applications/Praat.app/Contents/MacOS/Praat" --run get_fast_tracks.praat "' pwd '" "temp_wav"']); else - status = system(['"C:\Users\Public\Desktop\Praat.exe" --run get_fast_tracks.praat "' pwd]); + status = system(['"C:\Users\nomeland\Documents\Praat.exe" --run get_fast_tracks.praat "' pwd '" "temp_wav"']); end if status ~= 0 error('Something went wrong in Praat analysis') @@ -102,7 +102,7 @@ % clean up by deleting files and return to previous directory delete temp_wav.wav - % delete temp_wav_formants.txt + delete temp_wav_formants.txt cd(curr_dir) % establish outputs @@ -110,4 +110,4 @@ output{1} = formant; output{2} = lpc_coeffs; output{3} = msaxis * 1000; %covert from s to ms -%%% end of praat function +%%% end of Fast Track function From ef9ac6656f28796a99246a1a7127a4012b3b8070 Mon Sep 17 00:00:00 2001 From: Henry Nomeland Date: Fri, 26 Apr 2024 09:38:40 -0500 Subject: [PATCH 07/11] details --- get_fast_tracks.praat | 12 ++++++------ get_formant_tracks.m | 4 ---- get_formant_tracks.praat | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 get_formant_tracks.praat diff --git a/get_fast_tracks.praat b/get_fast_tracks.praat index dbafe25..7d2b1c0 100644 --- a/get_fast_tracks.praat +++ b/get_fast_tracks.praat @@ -15,15 +15,15 @@ include utils/trackAutoselectProcedure.praat @getSettings formants = 3 -time_step = 0.002 -steps = 20 -coefficients = 5 +time_step = 0.01 +steps = 10 +coefficients = 2 out_formant = 2 fastTrackMinimumDuration = 0.030000000000001 -lowestAnalysisFrequency = 0 -highestAnalysisFrequency = 5500 +lowestAnalysisFrequency = 2400 +highestAnalysisFrequency = 3200 -method$ = "burg" +method$ = "robust" wav_name$ = file_name$ + ".wav" Read from file... 'dir$'/'wav_name$' soundID1$ = selected$("Sound") diff --git a/get_formant_tracks.m b/get_formant_tracks.m index 11f4bbc..d08c6c4 100644 --- a/get_formant_tracks.m +++ b/get_formant_tracks.m @@ -49,16 +49,12 @@ cd(praat_path) fs = params.fs; - faxis = params.faxis; - nlpc_coeffs = params.nlpc; nformants = params.nformants; %%% Praat wrapper code here % write y to file (this will be deleted later, it is just written to the % current directory) audiowrite('temp_wav.wav',y,fs) - max_formant = 5500; - preemphasis = 50; if ismac status = system(['"/Applications/Praat.app/Contents/MacOS/Praat" --run get_fast_tracks.praat "' pwd '" "temp_wav"']); diff --git a/get_formant_tracks.praat b/get_formant_tracks.praat new file mode 100644 index 0000000..66b86d5 --- /dev/null +++ b/get_formant_tracks.praat @@ -0,0 +1,40 @@ +# get_formants.praat +# BEN PARRELL 18 DEC 2017 +# +# Measure formants for whole .wav file +# For use with wave_viewer + +#Inputs +form Measure formant values for segments in a textgrid + sentence directory_name: /Users/Ben/Documents/MATLAB/wave_viewer + sentence file_name: temp_wav + positive maximum_formant 5500 + positive number_of_formants 5 + positive window_size 0.025 + positive time_step 0.005 + positive preemphasis 50 + positive fs 11025 +endform + +#open the sound and select it +wav_name$ = file_name$ + ".wav" +Read from file... 'directory_name$'/'wav_name$' +soundID1$ = selected$("Sound") + +#extract formants +To Formant (burg)... 'time_step' 'number_of_formants' 'maximum_formant' 'window_size' 'preemphasis' +formant = selected ("Formant") + +#write formants +formant_name$ = file_name$ + "_formants.txt" +Down to Table... yes yes 6 no 3 yes 3 no +Save as tab-separated file... 'directory_name$'/'formant_name$' + +#extract LPC parameters +#selectObject: formant +#To LPC... fs +#Down to Matrix (lpc) + +#save LPC parameters +#lpc_name$ = file_name$ + "_lpc.txt" +#Save as headerless spreadsheet file... 'directory_name$'/'lpc_name$' From 20402f7b81c7cd62a71cf44157276239990cb93d Mon Sep 17 00:00:00 2001 From: Henry Nomeland Date: Fri, 26 Apr 2024 09:57:06 -0500 Subject: [PATCH 08/11] formant tracking updates --- get_formant_tracks.m | 261 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 252 insertions(+), 9 deletions(-) diff --git a/get_formant_tracks.m b/get_formant_tracks.m index d08c6c4..cdca2f1 100644 --- a/get_formant_tracks.m +++ b/get_formant_tracks.m @@ -1,18 +1,25 @@ function [ftrack_out,ftrack_mstaxis,ftrack_lpc_coeffs] = get_formant_tracks(y,fs,faxis,ms_framespec,nlpc_coeffs,yes_preemph,nformants,ftrack_method,yes_verbose) +frames_per_dot = 10; +dots_per_line = 50; + if nargin < 2 || isempty(fs), fs = 11025; end if nargin < 3 || isempty(faxis), faxis = linspace(0,fs/2,1025); end if nargin < 4 || isempty(ms_framespec), ms_framespec = 'narrowband'; end if nargin < 5 || isempty(nlpc_coeffs), nlpc_coeffs=14; end if nargin < 6 || isempty(yes_preemph), yes_preemph = 1; end if nargin < 7 || isempty(nformants), nformants = 0; end -if nargin < 8 || isempty(ftrack_method), ftrack_method = 'praat'; end +if nargin < 8 || isempty(ftrack_method), ftrack_method = 'mine'; end if nargin < 9 || isempty(yes_verbose), yes_verbose = 0; end params.fs = fs; params.nlpc = nlpc_coeffs; switch ftrack_method + case 'colea', ftrack_func = @colea_ftrack_func; params.nformants_max = 3; params.yes_trackperframe = 1; + case 'mine', ftrack_func = @my_ftrack_func; params.nformants_max = 3; params.yes_trackperframe = 1; + case 'mine2', ftrack_func = @my_ftrack_func2; params.nformants_max = 4; params.yes_trackperframe = 1; case 'praat', ftrack_func = @praat_ftrack_func; params.nformants_max = 5; params.yes_trackperframe = 0; + case 'fasttrack', ftrack_func = @fasttrack_ftrack_func; params.nformants_max = 5; params.yes_trackperframe = 0; otherwise, error('formant tracking method(%s) unrecognized',ftrack_method); end if ~nformants, nformants = params.nformants_max; end @@ -20,18 +27,41 @@ params.nformants = nformants; params.faxis = faxis; -[nsamps,~] = get_len_yvec(y); +starting_formants = [500 1500 2500 3500]; + +[nsamps,yes_y_is_rowvec] = get_len_yvec(y); [ms_awin,ms_astep,nsamps_frame,nsamps_astep] = get_ms_framespec(ms_framespec,fs); +win = hann(nsamps_frame)/sum(hann(nsamps_frame)); +if ~yes_y_is_rowvec, win = win'; end y = my_preemph(y,yes_preemph); nframes = floor((nsamps - nsamps_frame)/nsamps_astep); +ftrack = zeros(nformants,nframes); +ftrack_mstaxis = zeros(1,nframes); +lpc_coeffs = zeros((nlpc_coeffs+1),nframes); -params.window_size = ms_awin/1000; -params.step_size = ms_astep/1000; -params.nframes = nframes; -output = ftrack_func(y,params); -ftrack = output{1}; -lpc_coeffs = output{2}; -ftrack_mstaxis = output{3}; +if params.yes_trackperframe % if tracker operates on a frame-by-frame basis within Matlab + for iframe = 1:nframes + yframe = y((iframe-1)*nsamps_astep + (1:nsamps_frame)); + ftrack_mstaxis(iframe) = 1000*mean((iframe-1)*nsamps_astep + (1:nsamps_frame))/fs; + ywinframe = win .* yframe; + if iframe > 1, params.Fprev = ftrack(:,iframe-1); else params.Fprev = starting_formants; end + output = ftrack_func(ywinframe,params); + ftrack(:,iframe) = output{1}; + lpc_coeffs(:,iframe) = output{2}; + if yes_verbose + if ~rem(iframe,frames_per_dot), fprintf('.'); end + if ~rem(iframe,frames_per_dot*dots_per_line), fprintf('%d\n',iframe); end + end + end +else % if we want to pass entire utterance to external tracker + params.window_size = ms_awin/1000; + params.step_size = ms_astep/1000; + params.nframes = nframes; + output = ftrack_func(y,params); + ftrack = output{1}; + lpc_coeffs = output{2}; + ftrack_mstaxis = output{3}; +end % ftrack_out(1:nformants,1:nframes) = ftrack(1:nformants,1:nframes); ftrack_out(1:nformants,:) = ftrack(1:nformants,:); %removing nframes allows for praat tracking @@ -40,8 +70,140 @@ end if nargout >= 3, ftrack_lpc_coeffs = lpc_coeffs; end + +% must have colea on matlab path to use this function +function output = colea_ftrack_func(ywinframe,params) + +fs = params.fs; +nlpc_coeffs = params.nlpc; +nformants = params.nformants; + +lpc_coeffs = lpc(ywinframe,nlpc_coeffs); +[frmnt(1),frmnt(2),frmnt(3)] = frmnts(lpc_coeffs,fs); +formant(1:nformants) = frmnt(1:nformants); + +output{1} = formant; +output{2} = lpc_coeffs; + +function output = my_ftrack_func(ywinframe,params) + +fs = params.fs; +nlpc_coeffs = params.nlpc; +nformants = params.nformants; + +lpc_coeffs = lpc(ywinframe,nlpc_coeffs); +[frmnt(1),frmnt(2),frmnt(3)] = my_frmnts(lpc_coeffs,fs); + +formant(1:nformants) = frmnt(1:nformants); + +output{1} = formant; +output{2} = lpc_coeffs; + + +function output = my_ftrack_func2(ywinframe,params) + +fs = params.fs; +faxis = params.faxis; +nlpc_coeffs = params.nlpc; +nformants = params.nformants; +Fprev = params.Fprev; + +lpc_coeffs = lpc(ywinframe,nlpc_coeffs); +lpc_magspec = get_lpc_magspec(lpc_coeffs,faxis,fs); +[lpc_magspec_peaks,nlpc_magspec_peaks] = peakfind(lpc_magspec); +for iformant = 1:nformants + if iformant < nlpc_magspec_peaks + formant(iformant) = faxis(lpc_magspec_peaks(iformant)); + elseif iformant == nlpc_magspec_peaks + formant(iformant) = faxis(lpc_magspec_peaks(iformant)); + if abs(Fprev(iformant)-formant(iformant)) > 75 + formant(iformant) = Fprev(iformant); + end + else + formant(iformant) = Fprev(iformant); + end +end + +output{1} = formant; +output{2} = lpc_coeffs; + + function output = praat_ftrack_func(y,params) +% execute Praat script using params +%must be in git repo folder to run praat function, so save current location and go there +curr_dir = pwd; +temp_str = which('get_formant_tracks.praat'); +praat_path = fileparts(temp_str); +cd(praat_path) + +fs = params.fs; +faxis = params.faxis; +nlpc_coeffs = params.nlpc; +nformants = params.nformants; + +%%% Praat wrapper code here +% write y to file (this will be deleted later, it is just written to the +% current directory) +audiowrite('temp_wav.wav',y,fs) + +% set praat params that are not changeable +max_formant = 5500; +preemphasis = 50; + +if ismac + status = system(['"/Applications/Praat.app/Contents/MacOS/Praat" --run get_formant_tracks.praat "' pwd '" "temp_wav" ' num2str(max_formant) ' ' num2str(params.nlpc/2) ' ' num2str(params.window_size) ' ' num2str(params.step_size) ' ' num2str(preemphasis) ' ' num2str(params.fs)]); +else + status = system(['"C:\Users\Public\Desktop\Praat.exe" --run get_formant_tracks.praat "' pwd '" "temp_wav" ' num2str(max_formant) ' ' num2str(params.nlpc/2) ' ' num2str(params.window_size) ' ' num2str(params.step_size) ' ' num2str(preemphasis) ' ' num2str(params.fs)]); +end +if status ~= 0 + error('Something went wrong in Praat analysis') +end + +% clean up praat output text file to eliminate uniterpretable characters +A = regexp( fileread('temp_wav_formants.txt'), '\n', 'split'); +headers = strsplit(A{1},'\t'); +if length(headers) == 1 %for some reason Praat sometimes uses a space to separate headers + headers = strsplit(A{1},' '); +end +for i = 1:length(headers) + curTxt = headers{i}; + startUnits = strfind(curTxt,'('); + if ~isempty(startUnits) + curTxt = curTxt(1:startUnits-1); + headers{i} = curTxt; + end +end +A{1} = strjoin(headers,'\t'); +fid = fopen('temp_wav_formants.txt','w'); +fprintf(fid, '%s\n', A{:}); +fclose(fid); + +% load formant tracks from file written by Praat and put in 'formant' output +formant_vals = readtable('temp_wav_formants.txt','Delimiter','\t'); + +%find number of formant values returbned by praat +for nf = 1:nformants + form=['F' num2str(nf)]; + formant(nf,:) = formant_vals.(form)'; +end + +%find times of formants +msaxis = formant_vals.time'; + +% load LPC values from file written by Praat and put in 'lpc_coeffs' output +% lpc_coeffs = dlmread('temp_wav_lpc.txt','\t'); +lpc_coeffs = []; +% clean up by deleting files that were created and return to previous +% directory +delete temp_wav.wav temp_wav_formants.txt %temp_wav_lpc.txt +cd(curr_dir) + +output{1} = formant; +output{2} = lpc_coeffs; +output{3} = msaxis * 1000; %covert from s to ms + %%% function which executes Fast Track script using params +function output = fasttrack_ftrack_func(y,params) %must be in git repo folder to run praat function, so save current location and go there curr_dir = pwd; temp_str = which('get_fast_tracks.praat'); @@ -107,3 +269,84 @@ output{2} = lpc_coeffs; output{3} = msaxis * 1000; %covert from s to ms %%% end of Fast Track function + +% my version of the colea frmnts function, +% orinally copyright (c) 1998 by Philipos C. Loizou +function [F1,F2, F3]=my_frmnts(lpc_coeffs,fs) + +global F1prev F2prev F3prev + +min_formant_freq = 90; +max_formant_freq = 4000; +max_formant_bw = 500; +defaultF1 = 300; defaultF2 = 1200; defaultF3 = 3000; + +max_allowable_F1dev = 150; +max_allowable_F2dev = 150; +min_initial_formant_sep = 80; +min_formant_sep = 50; + +const = fs/(2*pi); +rts = roots(lpc_coeffs); +k = 1; +for i=1:length(lpc_coeffs)-1 + re = real(rts(i)); im = imag(rts(i)); + the_formant_cand = const*atan2(im,re); %--formant frequencies + formant_bw = -0.5*const*log(abs(rts(i)));%--formant bandwidth + if (the_formant_cand < max_formant_freq) & ... + (the_formant_cand > min_formant_freq) & ... + (formant_bw < max_formant_bw) + unsort_candidate_formant(k) = the_formant_cand; + bandw(k) = formant_bw; + k = k + 1; + end +end +candidate_formant = sort(unsort_candidate_formant); +ncand_formants = length(candidate_formant); + +if isempty(F1prev) %++++++++++++++++ the first frame ++++++++++++++++++ + if 2 > ncand_formants + F1 = defaultF1; F2 = defaultF2; F3 = defaultF3; + elseif abs(candidate_formant(1)-candidate_formant(2)) < min_initial_formant_sep + F1 = candidate_formant(2); F2 = candidate_formant(3); + if 3 > ncand_formants, F3 = candidate_formant(4); else F3 = defaultF3; end + elseif 4 == ncand_formants + F1 = candidate_formant(2); F2 = candidate_formant(3); + F3 = candidate_formant(4); + else + F1 = candidate_formant(1); F2 = candidate_formant(2); + if 3 > ncand_formants, F3 = defaultF3; else F3 = candidate_formant(3); end + end +else %++++++++++++++++ all frames after the first ++++++++++++++++++ + %----Impose some formant continuity constraints ------------------- + in1 = find(abs(F1prev-candidate_formant) < max_allowable_F1dev); + in2 = find(abs(F2prev-candidate_formant) < max_allowable_F2dev); + if length(in1) > 1, i1 = in1(2); else i1 = in1; end + if length(in2) > 1, i2 = in2(2); else i2 = in2; end + + switch (10*(~isempty(i1)) + (~isempty(i2))) + case 11 + if i1 == i2 + if 1 > ncand_formants, F1 = F1prev; else F1 = candidate_formant(1); end + if 2 > ncand_formants, F2 = F2prev; else F2 = candidate_formant(2); end + if 3 > ncand_formants, F3 = F3prev; else F3 = candidate_formant(3); end + else + F1 = candidate_formant(i1); F2 = candidate_formant(i2); + if i2 + 1 > ncand_formants, F3 = F3prev; else F3 = candidate_formant(i2 + 1); end + end + case 10 + F1 = candidate_formant(i1); + if i1 + 1 > ncand_formants, F2 = F2prev; else F2 = candidate_formant(i1 + 1); end + if i1 + 2 > ncand_formants, F3 = F3prev; else F3 = candidate_formant(i1 + 2); end + otherwise + F1 = candidate_formant(1); + if 2 > ncand_formants, F2 = F2prev; else F2 = candidate_formant(2); end + if 3 > ncand_formants, F3 = F3prev; else F3 = candidate_formant(3); end + end +end + +% --last check .. -------- +if abs(F2-F3) < min_formant_sep, F2 = F2prev; F3 = F3prev; end +if abs(F2-F1) < min_formant_sep, F2 = F2prev; F3 = F3prev; end + +F1prev = F1; F2prev = F2; F3prev = F3; From b9b757994cc5d46d7670d5e4c5c6c2f551a37eb7 Mon Sep 17 00:00:00 2001 From: Henry Nomeland Date: Fri, 26 Apr 2024 10:05:22 -0500 Subject: [PATCH 09/11] removed autocont --- wave_viewer.m | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/wave_viewer.m b/wave_viewer.m index b3821de..ad5f5c0 100644 --- a/wave_viewer.m +++ b/wave_viewer.m @@ -846,15 +846,7 @@ function fig_resize_func(src,event) set(hf,'KeyPressFcn',@key_press_func); set(hf,'ResizeFcn',@fig_resize_func); if yes_profile, profile off; end -if yes_start_blocking && p.sigproc_params.autocont ~= 1, uiwait(hf); end - -%%% CODE FOR AUTOCONTINUE -if p.sigproc_params.autocont - if p.sigproc_params.autocont == 1 - contprogram([],[]); - end -end - +if yes_start_blocking, uiwait(hf); end end %% @@ -2316,8 +2308,7 @@ function set_viewer_axlims(hax,t_min,t_max,dat4minmax,yax_fact2use) 'ptrack_voicing_thresh', 0.45, ... 'ptrack_octave_cost', 0.01, ... 'ptrack_octave_jump_cost', 0.35, ... - 'ptrack_voiced_unvoiced_cost', 0.14, ... - 'autocont', 0); + 'ptrack_voiced_unvoiced_cost', 0.14); end %% get figure params (used to be global vars) From 387c78b4c1de12572d5ad3257e2ab2a4c4ab3047 Mon Sep 17 00:00:00 2001 From: Henry Nomeland Date: Tue, 30 Apr 2024 09:50:28 -0500 Subject: [PATCH 10/11] fixed windows path --- get_fast_tracks.praat | 14 +++++++------- get_formant_tracks.m | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/get_fast_tracks.praat b/get_fast_tracks.praat index 7d2b1c0..04ff565 100644 --- a/get_fast_tracks.praat +++ b/get_fast_tracks.praat @@ -1,4 +1,4 @@ -# get_fast_tracks.praat by Henry Nomeland, 21 Mar 2024 + # get_fast_tracks.praat by Henry Nomeland, 21 Mar 2024 # adapted from get_formants.praat by Ben Parrell, 18 Dec 2017 # # measures formants for a .wav file utilizing tools and utils of FastTrack @@ -15,15 +15,15 @@ include utils/trackAutoselectProcedure.praat @getSettings formants = 3 -time_step = 0.01 -steps = 10 -coefficients = 2 +time_step = 0.002 +steps = 30 +coefficients = 3 out_formant = 2 fastTrackMinimumDuration = 0.030000000000001 -lowestAnalysisFrequency = 2400 -highestAnalysisFrequency = 3200 +lowestAnalysisFrequency = 4800 +highestAnalysisFrequency = 5500 -method$ = "robust" +method$ = "burg" wav_name$ = file_name$ + ".wav" Read from file... 'dir$'/'wav_name$' soundID1$ = selected$("Sound") diff --git a/get_formant_tracks.m b/get_formant_tracks.m index cdca2f1..eefec15 100644 --- a/get_formant_tracks.m +++ b/get_formant_tracks.m @@ -18,7 +18,7 @@ case 'colea', ftrack_func = @colea_ftrack_func; params.nformants_max = 3; params.yes_trackperframe = 1; case 'mine', ftrack_func = @my_ftrack_func; params.nformants_max = 3; params.yes_trackperframe = 1; case 'mine2', ftrack_func = @my_ftrack_func2; params.nformants_max = 4; params.yes_trackperframe = 1; - case 'praat', ftrack_func = @praat_ftrack_func; params.nformants_max = 5; params.yes_trackperframe = 0; + case 'praat', ftrack_func = @fasttrack_ftrack_func; params.nformants_max = 5; params.yes_trackperframe = 0; case 'fasttrack', ftrack_func = @fasttrack_ftrack_func; params.nformants_max = 5; params.yes_trackperframe = 0; otherwise, error('formant tracking method(%s) unrecognized',ftrack_method); end @@ -221,7 +221,7 @@ if ismac status = system(['"/Applications/Praat.app/Contents/MacOS/Praat" --run get_fast_tracks.praat "' pwd '" "temp_wav"']); else - status = system(['"C:\Users\nomeland\Documents\Praat.exe" --run get_fast_tracks.praat "' pwd '" "temp_wav"']); + status = system(['"C:\Users\Public\Desktop\Praat.exe" --run get_fast_tracks.praat "' pwd '" "temp_wav"']); end if status ~= 0 error('Something went wrong in Praat analysis') From d7b4196941e210753b1d3bb05089411f69895de7 Mon Sep 17 00:00:00 2001 From: Henry Nomeland Date: Wed, 1 May 2024 12:24:41 -0500 Subject: [PATCH 11/11] tiny updates --- get_fast_tracks.praat | 3 +-- get_formant_tracks.m | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/get_fast_tracks.praat b/get_fast_tracks.praat index 04ff565..0e2c0b7 100644 --- a/get_fast_tracks.praat +++ b/get_fast_tracks.praat @@ -19,7 +19,6 @@ time_step = 0.002 steps = 30 coefficients = 3 out_formant = 2 -fastTrackMinimumDuration = 0.030000000000001 lowestAnalysisFrequency = 4800 highestAnalysisFrequency = 5500 @@ -45,4 +44,4 @@ Save as tab-separated file... 'dir$'/'formant_name$' #save LPC parameters #lpc_name$ = file_name$ + "_lpc.txt" -#Save as headerless spreadsheet file... 'directory_name$'/'lpc_name$' +#Save as headerless spreadsheet file... 'dir$'/'lpc_name$' diff --git a/get_formant_tracks.m b/get_formant_tracks.m index eefec15..54c5748 100644 --- a/get_formant_tracks.m +++ b/get_formant_tracks.m @@ -18,7 +18,7 @@ case 'colea', ftrack_func = @colea_ftrack_func; params.nformants_max = 3; params.yes_trackperframe = 1; case 'mine', ftrack_func = @my_ftrack_func; params.nformants_max = 3; params.yes_trackperframe = 1; case 'mine2', ftrack_func = @my_ftrack_func2; params.nformants_max = 4; params.yes_trackperframe = 1; - case 'praat', ftrack_func = @fasttrack_ftrack_func; params.nformants_max = 5; params.yes_trackperframe = 0; + case 'praat', ftrack_func = @praat_ftrack_func; params.nformants_max = 5; params.yes_trackperframe = 0; case 'fasttrack', ftrack_func = @fasttrack_ftrack_func; params.nformants_max = 5; params.yes_trackperframe = 0; otherwise, error('formant tracking method(%s) unrecognized',ftrack_method); end