首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Praat:获得共振峰强度

Praat:获得共振峰强度
EN

Stack Overflow用户
提问于 2016-10-13 23:37:00
回答 2查看 1.3K关注 0票数 2

我有一个praat脚本,可以从wavefiles文件夹中提取共振峰信息:

代码语言:javascript
复制
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

并生成以下输出:

代码语言:javascript
复制
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
...

这对我需要的东西很有效,但是有没有办法也能得到每个共振峰的强度呢?现在我只有一个强度估计值。

EN

回答 2

Stack Overflow用户

发布于 2016-11-16 22:13:12

这是一个老问题,但我还是会回答的。

我在2002年也遇到过这种情况,当时我正在为硬件格式合成器(FS1R)创建编辑器。我使用praat进行wav->格式轨道计算,合成器期望共振峰频率和强度作为输入。

我已经为它实现了几种算法,但具有最真实结果的算法评估了光谱图中每帧的每个共振峰的强度。

这是我用来做这个的代码。请记住,我的目标是获得一个512帧的列表,最多8个频率/强度对,以及一个基本的音高。

代码语言:javascript
复制
# 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.
票数 0
EN

Stack Overflow用户

发布于 2016-11-16 22:27:01

我不确定这是否是你需要的,但根据@nikolay-shmyrev的评论,这就是你如何将来自光谱图对象的共振峰强度测量插入到你的脚本中。

我似乎已经预防了使用Praat编写脚本的痛苦……

我简化了下面的脚本,使其只适用于当前选定的Sound对象(用于测试),并简单地保留了生成的Table (以便您可以将其签出),但它应该会为您指明正确的方向。

代码语言:javascript
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40025339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档