All Downloads are FREE. Search and download functionalities are using the official Maven repository.

marytts.tools.voiceimport.script.praat Maven / Gradle / Ivy

The newest version!
##
# Copyright 2006-2010 DFKI GmbH.
# All Rights Reserved.  Use is subject to license terms.
#
# This file is part of MARY TTS.
#
# MARY TTS is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see .
#
##

# use Praat form to provide ARGV (NOTE: these must be explicitly given during call to Praat!)
form Provide arguments
  sentence basenameList ../basenames.lst
  sentence wavDir ../wav
  sentence pmDir ../pm
  real minPitch 75
  real maxPitch 600
endform

# Get basename array (taking into account that some have a header line):
Read Strings from raw text file... 'basenameList$'
numLines = Get number of strings
numBasenames = 0
for l to numLines
  line$ = Get string... l
  if !startsWith(line$, "FROM:")
    numBasenames += 1
    basenames_'numBasenames'$ = line$
  endif
endfor
Remove

# iterate over all basenames:
lastpercent$ = ""
for b to numBasenames
  basename$ = basenames_'b'$
  wavFile$ = "'wavDir$'/'basename$'.wav"
  pitchFile$ = "'pmDir$'/'basename$'.Pitch"
  pointpFile$ = "'pmDir$'/'basename$'.PointProcess"

  # provide current progress as text file "percent":
  percent = floor(b / numBasenames * 100)
  percent$ = "'percent'"
  if percent$ != lastpercent$
    percent$ > percent
    lastpercent$ = percent$
  endif

  call process

endfor
filedelete percent

# BEGIN process procedure
procedure process
wav = Read from file... 'wavFile$'

# Remove DC offset, if present:
Subtract mean

# First, low-pass filter the speech signal to make it more robust against noise
# (i.e., mixed noise+periodicity regions treated more likely as periodic)
sound = Filter (pass Hann band)... 0 1000 100

# check for available Pitch file:
if fileReadable(pitchFile$)
  pitch = Read from file... 'pitchFile$'
else
  # determine pitch curve:
  noprogress To Pitch... 0 minPitch maxPitch
  pitch = selected()
endif

# Get some debug info: 
min_f0 = Get minimum... 0 0 Hertz Parabolic
max_f0 = Get maximum... 0 0 Hertz Parabolic

# And convert to pitch marks:
plus sound
noprogress To PointProcess (cc)
pp = selected()

# convert pitch contour and pitch marks to PitchTier for easier access:
plus pitch
pt = To PitchTier

# Fill in 100 Hz pseudo-pitchmarks in unvoiced regions:
fill_f0 = 100 ; define constant

# get v/uv intervals:
select pp
# TODO tweak parameters?
tg = To TextGrid (vuv)... 0.02 0.01
# sanity check: are there even any unvoiced intervals?
ni = Get number of intervals... 1
if ni == 1
  i$ = Get label of interval... 1 1
  if i$ == "V"
    select pp
    goto writepp
  endif
endif
it = Extract tier... 1
uv = Down to TableOfReal... U

# iterate over uv intervals (two passes to avoid concurrent modification):
select pp
for row to Object_'uv'.nrow
  # get the fill start time:
  uv_start = Object_'uv'[row,"Start"]
  prev_pm_idx = Get low index... uv_start
  is_first_pm = prev_pm_idx == 0
  if is_first_pm
    fill_start = uv_start
  else
    prev_pm_time = Get time from index... prev_pm_idx
    prev_f0 = Object_'pt'[prev_pm_idx]
    fill_start = prev_pm_time + 1 / fill_f0
  endif

  # get the fill end time:
  uv_end = Object_'uv'[row,"End"]
  next_pm_idx = Get high index... uv_end
  is_last_pm = next_pm_idx > Object_'pt'.nx
  if is_last_pm
    fill_end = uv_end
  else
    next_pm_time = Get time from index... next_pm_idx
    next_f0 = Object_'pt'[next_pm_idx]
    fill_end = next_pm_time - 1 / fill_f0
  endif

  # adjust fill start and end times so that fill pitchmarks are centered in fill region:  
  fill_length = fill_end - fill_start
  fill_pm_remainder = fill_length mod (1 / fill_f0)
  if is_first_pm
    fill_start += fill_pm_remainder
  elsif is_last_pm
    fill_end -= fill_pm_remainder
  else
    fill_start += fill_pm_remainder / 2
    fill_end -= fill_pm_remainder / 2
  endif

  # store values
  fill_start_'row' = fill_start
  fill_end_'row' = fill_end
endfor

# do the fill:
for row to Object_'uv'.nrow
  time = fill_start_'row'
  while time <= fill_end_'row' + 1e-14 ; try to gracefully handle floating-point noise
    Add point... time
    time += 1 / fill_f0
  endwhile
endfor

label writepp
Write to short text file... 'pointpFile$'
printline 'basename$'   f0 range: 'min_f0:0' - 'max_f0:0' Hz ('percent$'%)

# cleanup:
plus wav
plus sound
plus pitch
plus pt
plus pp
plus tg
nocheck plus it
nocheck plus uv
Remove

endproc
# END process procedure




© 2015 - 2025 Weber Informatics LLC | Privacy Policy