# SWS makes =<3-formant sine-wave speech out of the selected Sound object # modified to have consistent new-style syntax 1/9/00 - cjd # modified optionally to low-pass filter the formant tracks 4/6/01 - cjd # modified to vary tracking parameters with talkerID 12/6/01 - cjd # modified to include Add_dynamic - 27/2/03 cjd #a Formant object may be pre-prepared and used instead of the default (which is prepared directly from the selected sound) # if a pre-prepared Formant object is used, the amplitudes for the sine waves are taken from its frequencies on the spectrogram derived from the selected sound. # Formant objects can be edited using Inspect # the pre-prepared Formant object must have the same name as the selected Sound #Add to dynamic menu... Sound 1 "" 0 "" 0 "Sine-wave speech" Resample... 1 yourdisk:Praat:scripts:SWS form Sine-wave speech choice TalkerID: 1 button Male button Female button Child comment Which formants to synthesise? boolean Formant_1 1 boolean Formant_2 1 boolean Formant_3 1 comment Do you want them added together? boolean Add_them 1 comment Use a pre-prepared Formant object with comment same name as the selected Sound? boolean Formant_object 0 comment Amplitude tracks are normally LP filtered comment at 50 Hz to remove pitch modulations integer Amp_low_pass_freq_(Hz) 50 comment Low pass filtering of the formant tracks comment removes warble, but can degrade rapid consonants. comment Do you want to LP filter the formant tracks? boolean Low_pass 1 comment Choose the highest frequency that doesn't give warble. integer Formant_low_pass_freq_(Hz) 20 boolean Remove_intermediate_files 1 endform if numberOfSelected ("Sound") <> 1 pause Select one Sound then Continue endif snd$ = selected$("Sound", 1) snd = selected("Sound", 1) # upper formant limit depends on talker if talkerID = 1 upperf = 5000; male elsif talkerID = 2 upperf = 5500; female else upperf = 8000; child endif #create wide-band spectrogram for finding formant amplitudes To Spectrogram... 0.003 'upperf' 0.001 40 Gaussian # if no pre-prepared Formant object has been identified then make it, if formant_object = 0 select 'snd' To Formant (burg)... 0.01 5 'upperf' 0.025 50 Rename... untrack if talkerID = 1 basef = 500; male elsif talkerID = 2 basef = 550; female else basef = 800; child endif Track... 3 'basef' 'basef'*3 'basef'*5 'basef'*7 'basef'*9 1 0.1 1 Rename... 'snd$' select Formant untrack Remove endif # plot a spectrogram if asked for if formant_object = 0 Erase all Viewport... 0 9 0 4.5 select Spectrogram 'snd$' Paint... 0 0 0 'basef'*7 100 yes 50 6 0 no select Formant 'snd$' Red Speckle... 0 0 'basef'*7 30 yes Draw tracks... 0 0 'basef'*7 yes endif select 'snd' dur = Get duration sf = Get sample rate #start of main formant loop #=========================== #for each chosen formant turn formant tracks into #a Matrix then a Sound object for optional low-pass filtering #NB this Sound object is the formant TRACK #then back into a Matrix object for sound synthesis for i from 1 to 3 if formant_'i' # make a matrix from Fi select Formant 'snd$' To Matrix... 'i' Rename... f'i' if low_pass #low-pass filter the formant track and tidy-up the names #filtering needs a Sound object, so cast as Sound, filter and then back to Matrix To Sound (slice)... 1 Filter (pass Hann band)... 0 'formant_low_pass_freq' 'formant_low_pass_freq' Down to Matrix select Matrix f'i' Remove select Matrix f'i'_band Rename... f'i' select Sound f'i' plus Sound f'i'_band Remove endif #set up amplitude contour array (sample only at 1kHz) for i'th formant #make it a Sound object so that it can be smoothed by filtering Create Sound... amp'i' 0 'dur' 1000 sqrt(Spectrogram_'snd$'(x,Matrix_f'i'(x))) #smooth out pitch amplitude modulation by low-pass filtering Filter (pass Hann band)... 0 'amp_low_pass_freq' 'amp_low_pass_freq' select Sound amp'i' Remove select Sound amp'i'_band Rename... amp'i' # To make a sine-wave at Fi (NB you can't just use sin(2pi*fm*t) - since fm is only the instantaneous, not the historic frequency) # create a waveform with the phase-change associated with sinewave of frequency Fi Create Sound... sin'i' 0 'dur' 'sf' Matrix_f'i'(x)/'sf' # integrate phase-change to get actual local value Formula... if (self + self[col-1]) >1 then (self + self[col-1])-1 else self + self[col-1] fi # turn phase into sine value, with amplitude corresponding to formant freq in spectrogram Formula... 0.75*sin(2*pi*self)*Sound_amp'i'(x) if remove_intermediate_files #tidy-up select Sound amp'i' plus Matrix f'i' Remove endif endif endfor