Topics

Harmonic peak and valley-picking script

kyoon@...
 

Thanks to those who responded to my earlier messages, I'm in the
middle of refining my script on harmonic peak and valley-picking from
a spectrum object. When I test-ran the script, however, I don't seem
to be getting the correct peak and valley intensity values. The
intensity values I get from the spectrum edit view are not the same
as those I get from the script below. Maybe my script gets intensity
values from wrong bins.

So I'm asking for help from experienced script users. Here's my not-
so-efficient script for your examination... It's a segment from a
longer script, so it will not run by itself. I'm just wondering if
there's anything wrong in the peak and valley-picking segment.

#A script segment summing harmonic peak intensities and
#valley intensities and subtracting the latter from the
#former, given a spectrum object

#Harmonic peak-picking starts here
#make a spectrum object at vowel_onset time
To Spectrum (slice)... 'vowel_onset'
spectrumID = selected ("Spectrum", -1)
To Formant (peaks)... 1000
formant_peakID = selected ("Formant (peaks)", -1)
num_fmts = Get number of formants... 1
#initialize sum of peak intensity values to zero before the loop
sum_peak = 0
for i from 1 to num_fmts
peak_freq = Get value at time... 'i' 0.5 Hertz Linear
select 'spectrumID'
bin_num = Get bin from frequency... 'peak_freq'
energy_Pa = Get real value in bin... 'bin_num'
energy_dB = 20 * log10(energy_Pa * 50000)
sum_peak = sum_peak + energy_dB
select 'formant_peakID'
endfor
#when you're done with peak-picking from a formant (peaks) object
#remove the formant object.
Remove
select 'spectrumID'
Remove
fileappend 'output_file$' 'sum_peak:4' 'tab$'

#Harmonic valley-picking starts here

To Spectrum (slice)... 'vowel_onset'
spectrumID = selected ("Spectrum", -1)
#make a copy of the spectrum object for inverting
Copy... copy_of_spectrum
spectrumID_copy = selected ("Spectrum", -1)
#The following is what I think Paul suggested earlier... if there's
#any mistake, it's all mine.
#make every bin real-values
select 'spectrumID_copy'
Formula... if row=1 then sqrt(self^2+self[2,col]^2) else 0 fi
#invert the spectrum
Formula... 1/(1+self)
To Formant (peaks)... 1000
#formant peaks are actually harmonic valleys
#since the peaks were inverted
formant_valleyID = selected ("Formant (peaks)", -1)
num_fmts = Get number of formants... 1
sum_valley = 0
for i from 1 to num_fmts
valley_freq = Get value at time... 'i' 0.5 Hertz Linear
#after you get the valley frequency, go to the original
#spectrum for intensity value
select 'spectrumID'
bin_num = Get bin from frequency... 'valley_freq'
energy_Pa = Get real value in bin... 'bin_num'
energy_dB = 20 * log10(energy_Pa * 50000)
sum_valley = sum_valley + energy_dB
select 'formant_valleyID'
endfor
Remove
subtracted = sum_peak - sum_valley
select 'spectrumID'
Remove
select 'spectrumID_copy'
Remove
fileappend 'output_file$' 'sum_valley:4' 'tab$'
#END_OF_SCRIPT_SEGMENT

I guess there are some mistakes in the above script. I'd very much
appreciate your comments.

Kyuchul Yoon
Department of Linguistics
The Ohio State University
http://ling.ohio-state.edu/~kyoon/