1

I have several speech files. In each file a vowel is annotated. I want to cut the half portion of this vowel and save it in another file. In order to do this, I am cutting the vowel in 4 parts. Then I am adding 1/4 to the starting time and then 3/4 to the starting time to get the middle portion. I came up with the following script based on other scripts I found online. However, I don't get anything in my output folder, so I am obviously doing something wrong. Any comments are welcome.

form Files
    comment Insert the directory
    sentence InputDir  ./
endform

createDirectory ("output")
Create Strings as file list... fileList 'path$'*.wav
n_of_files = Get number of strings


for file to n_of_files
    select Strings fileList
    # Gets the name of the sound file to be worked out
    file$ = Get string... 'file'
    # Reads the sound file to the Objects list
    Read from file... 'path$''file$'
    # Appends the ".TextGrid" extension to the string file$ and reads
    # the matching TextGrid
    Read from file... 'path$''file$'.TextGrid
    select all
    minus Strings fileList
    # Labelled intervals are extracted from the original sound file and are
    # then listed in the Objects list 
    Extract non-empty intervals... 'tier' yes
    # Remembers how many pieces of sound where extracted
    selected = numberOfSelected ("Sound")
    # Cleaning up the unnecessary clutter
    select Sound 'file$'
    plus TextGrid 'file$'
    Remove
    for i to selected
        select all
        #gets the duration
        dur = Get total duration
        #gets one quarter of the vowel 
        quart = dur/4
        #gets starting point of the vowel 
        start = Get starting point... tier interval
        #gets the the starting point of the second quarter of the vowel 
        cut = start +  quart
        #gets the ending point of the third quarter of the vowel
        cut2 = start + 3 * quart
    endfor

    sound_name$ = selected$ ("Sound")

        select Sound 'sound_name$'
        Edit
        editor Sound 'sound_name$'
        Select... cut cut2
        Move start of selection to nearest zero crossing
        Move end of selection to nearest zero crossing
        Cut selected sound 
        Write to WAV file... ./output/'file$'.wav
        endeditor

    select all
    minus Strings fileList
    # Cleans up unnecessary clutter
    Remove

endfor

select all
Remove
3
  • I vote to keep this question open, questions about using software specifically made for linguists are IMO on-topic. – jk - Reinstate Monica Jan 11 '18 at 10:23
  • @jknappen There is still a lot of code in the text. – new QOpenGLWidget Jan 17 '19 at 0:28
  • @zixuan No problem for me. – jk - Reinstate Monica Jan 17 '19 at 11:04
1

Your script doesn't work because it's not doing what you think it is doing. The main problem is that the for loop in lines 31-43 doesn't actually do anything. It calculates the same values every time, stores those values in some variables, and then overwrites those variables the next time.

Every time the loop runs, it is actually measuring the same Sound object, because each time you select all, and then commands like Get total duration work on the first selected appropriate object.

Then in line 45 you have the same problem: the sound_name$ variable (which you never use) will always be the same, because it is always the name of the first selected Sound object ... after selecting them all. And the initial form stores the path in the inputDir$ variable, but then you want to use one called path$ (in line 7).

Here's your corrected script (untested):

form Files
  comment Insert the directory
  sentence Path ./
endform

createDirectory ("output")
list = Create Strings as file list: "list", path$ + "*.wav"
n_of_files = Get number of strings

for file to n_of_files
  # Read sound file
  selectObject: list
  file$ = Get string: file
  sound = Read from file: path$ + file$

  # Read annotation file
  textgrid = Read from file: path$ + file$ - "wav" + "TextGrid"

  # Extract relevant intervals
  selectObject: sound, textgrid
  Extract non-empty intervals: tier, "yes"

  # Store the extracted intervals
  selected = numberOfSelected ("Sound")
  for i to selected
    piece[i] = selected("Sound", i)
  endfor

  # Sound and TextGrid no longer necessary
  removeObject: sound, textgrid

  # Loop through each extracted interval
  for i to selected
    # Query sound timing
    selectObject: piece[i]
    dur = Get total duration
    quart = dur / 4
    start = Get starting point: tier, interval
    t1 = Get nearest zero-crossing: 1, start +  quart
    t2 = Get nearest zero-crossing: 1, start + (quart * 3)

    # Extract center half
    part = Extract part: t1, t2, "rectangular", 1, "no"

    # Save to disk
    Write to WAV file: "./output/" + file$ + ".wav"

    # Clean up unnecessary objects
    removeObject: part, piece[i]
  endfor
endfor

# Remove list
removeObject: list

Some general pointers for the future:

  • Use object IDs and select the objects you want each time (instead of the select all-except-for-these-ones approach you are using).

  • Avoid using the Editor window for tasks such as these that don't require ... editing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.