我有一个praat脚本,从wavefiles文件夹中提取共振峰信息:
clearinfo
min_f0 = 75
max_f0 = 350
directory$ = "./soundfiles/"
outputDir$ = "./test/"
strings = Create Strings as file list: "list", directory$ + "/*.WAV"
numberOfFiles = Get number of strings
for ifile to numberOfFiles
select Strings list
filename$ = Get string... ifile
Read from file... 'directory$''filename$'
soundname$ = selected$ ("Sound", 1)
outputFileName$ = outputDir$ + soundname$ + ".f0123"
appendInfoLine: outputFileName$
select Sound 'soundname$'
formant = To Formant (burg): 0, 4, 5000, 0.025, 50
formantStep = Get time step
selectObject: formant
table = Down to Table: "no", "yes", 6, "yes", 3, "yes", 3, "yes"
numberOfRows = Get number of rows
select Sound 'soundname$'
pitch = To Pitch: 0, min_f0, max_f0
selectObject: table
Append column: "Pitch"
for step to numberOfRows
selectObject: table
t = Get value: step, "time(s)"
selectObject: pitch
pitchValue = Get value at time: t, "Hertz", "Nearest"
selectObject: table
Set numeric value: step, "Pitch", pitchValue
endfor
#export to csv
selectObject: table
Save as comma-separated file: outputFileName$
removeObject(table)
select all
minus Strings list
Remove
endfor
select all
Remove
exit
它会生成以下输出:
time(s),intensity,nformants,F1(Hz),B1(Hz),F2(Hz),B2(Hz),F3(Hz),B3(Hz),F4(Hz),B4(Hz),Pitch
0.025370,0.000007,3,213.115,14.053,2385.911,791.475,3622.099,677.605,--undefined--,--undefined--,--undefined--
0.031620,0.000007,3,208.843,15.034,2487.710,687.736,3818.027,645.184,--undefined--,--undefined--,197.5315925472943
...
这对我需要的东西很有用,但是有没有办法让每个共振峰的强度都增加?现在我只有一个强度估计值。
答案 0 :(得分:0)
这是一个老问题,但我仍然会回应。
2002年,当我为硬件格式合成器(FS1R)创建编辑器时,我也遇到了这种情况。我使用praat进行wav->格式轨道计算,合成器期望共振峰频率和强度作为输入。
我为它实现了几种算法,但是具有最逼真结果的算法评估了每个帧中每个共振峰的强度。
这是我用过的代码。 请记住,我的目标是获得512帧的列表,其中包含最多8个频率/强度对和一个基本音高。
# Add to dynamic menu... Sound 1 "" 0 "" 0 "Sine-wave speech" Resample... 1 yourdisk:Praat:scripts:SWS
form Add Sounds
word wavePath e:\samples\wav\root\
word waveFile DOUG.wav
word OutPath e:\samples\wav\root\
integer minFP 75
integer maxFP 500
integer maxFF 5000
integer Amp_low_pass_freq 50
integer Formant_low_pass_freq 20
endform
echo Wave to FSeq - FORMANT EXTRACTION
echo -------------------------------------------------------
# LOAD WAVEFILE
echo loading 'wavePath$''waveFile$'
Read from file... 'wavePath$''waveFile$'
if numberOfSelected ("Sound") <> 1
pause Select one Sound then Continue
endif
snd$ = selected$("Sound", 1)
snd = selected("Sound", 1)
sampleRate = Get sample rate
numSamples = Get number of samples
dur = Get duration
zzz = 512/509*512
timeStep = dur/zzz
echo samplerate : 'sampleRate' herz
echo number of samples : 'numSamples'
echo duration : 'dur' seconds
echo timestep : 'timeStep' seconds
echo
# GET FUNDAMENTAL PITCH
echo getting fundamental pitch
# this was the old method, used until FSeqEdit 1.21:
# To Pitch... 'timeStep' 'minFP' 'maxFP'
# Interpolate
# this algorithm seems to work better
To Pitch (ac)... 'timeStep' 'minFP' 15 no 1e-06 0.1 0.01 1 1 'maxFP'
Kill octave jumps
Interpolate
select Pitch 'snd$'
Write to short text file... 'outPath$'pitch.txt
select Pitch 'snd$'
Remove
# GET VOICED/UNVOICED INFORMATION
echo getting voiced/unvoiced information
select Pitch 'snd$'
To PointProcess
select PointProcess 'snd$'
To TextGrid (vuv)... 0.02 'timeStep'
select TextGrid 'snd$'
Write to short text file... 'outPath$'vuv.txt
#create wide-band spectrogram for finding formant amplitudes
# to spectorgam analwidth maxfreq timestep freqstep windowshape
echo to spectogram
select 'snd'
To Spectrogram... 0.003 'maxFF' 0.001 40 Gaussian
select 'snd'
echo finding formants
To Formant (burg)... 'timeStep' 8 'maxFF' 0.025 50
Rename... untrack
Track... 6 'maxFP' 'maxFP'*3 'maxFP'*5 'maxFP'*7 'maxFP'*9 1 0.1 1
Rename... 'snd$'
select Formant untrack
Remove
select 'snd'
#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 6
# make a matrix from Fi
select Formant 'snd$'
echo extracting formant 'i'
To Matrix... 'i'
Rename... f'i'
#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
if Formant_low_pass_freq <> 0
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
if Amp_low_pass_freq <> 0
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'
endif
Extract part... 0 'dur' Rectangular 1 yes
To Intensity... 'minFP' 0
Write to short text file... 'outPath$'amp'i'.txt
select Matrix f'i'
Remove
endfor
#===========================
#end of the main formant loop
select Formant 'snd$'
Write to short text file... 'outPath$'formant.txt
#tidy-up
select Spectrogram 'snd$'
plus Formant 'snd$'
plus Pitch 'snd$'
plus PointProcess 'snd$'
plus TextGrid 'snd$'
Remove
echo
echo -------------------------------------------------------
echo done.
答案 1 :(得分:0)
我不确定这是否是您所需要的,但根据@ nikolay-shmyrev的评论,您可以将Spectrogram对象的共振峰强度测量值插入到脚本中。
我似乎接受了使用Praat编写脚本的痛苦......
我简化了下面的脚本,使其仅适用于当前选定的Sound对象(用于测试),并且只保留生成的Table(因此您可以将其检出),但它应该指向正确的方向。 / p>
form Script...
positive Minimum_F0 75
positive Maximum_F0 350
positive Formants 4
endform
sound = selected("Sound")
pitch = To Pitch: 0, minimum_F0, maximum_F0
# You need this for the intensity
selectObject: sound
spectrogram = To Spectrogram: 0.005, 5000, 0.002, 20, "Gaussian"
selectObject: sound
formant = To Formant (burg): 0, formants, 5000, 0.025, 50
table = Down to Table: "no", "yes", 6, "yes", 3, "yes", 3, "yes"
Append column: "Pitch"
# Insert columns for each formant intensity
# (labeled here as "I#", where # is the formant index)
for f to formants
index = Get column index: "F" + string$(f) + "(Hz)"
Insert column: index + 1, "I" + string$(f)
endfor
for row to Object_'table'.nrow
selectObject: table
time = Object_'table'[row, "time(s)"]
# Get the intensity of each formant
for f to formants
frequency = Object_'table'[row, "F" + string$(f) + "(Hz)"]
selectObject: spectrogram
if frequency != undefined
intensity = Get power at: time, frequency
else
intensity = undefined
endif
selectObject: table
Set string value: row, "I" + string$(f), fixed$(intensity, 3)
endfor
selectObject: pitch
pitchValue = Get value at time: time, "Hertz", "Nearest"
selectObject: table
Set string value: row, "Pitch", fixed$(pitchValue, 3)
endfor
removeObject: spectrogram, formant, pitch