Используя сценарии Praat, как я могу разделить wav-файл по тишине, а затем объединить речевые клипы в более мелкие wav-файлы?

Я работаю над сценарием Praat, чтобы:

1- открыть wav файл

2- разделить wav файл на основе тишины

3- объединить интервалы на основе продолжительности, чтобы новые файлы сегментов wav были ‹ = 15 секунд каждый

4- записать новые сегменты wav в отдельные файлы wav

Я добился некоторого прогресса в том, чтобы заставить этот скрипт работать, но у меня есть две основные проблемы:

1- после того, как я объединил сегменты для создания первого 15-секундного клипа, мой вывод останавливается, поэтому в выводе отсутствует часть wav-файла.

2- клипы соединяются в обратном порядке

Вот мой сценарий на данный момент. Пожалуйста помоги! Я новичок в написании сценариев в Praat, и я полностью озадачен.

Read from file... Desktop/englishTest.wav
name$ = selected$("Sound", 1)
outputDir$ = "Desktop/praat_output/"
To TextGrid (silences)... 100 0 -25 0.3 0.1 silent sounding
plus Sound 'name$'
Extract intervals where... 1 no "is equal to" sounding

n = numberOfSelected("Sound")

for i to n
    soundObject'i'=selected("Sound", i)
endfor

topSound = soundObject1
select topSound
durTop = Get total duration

i = 2
for i to n
    select soundObject'i'
    dur = Get total duration
    if durTop + dur <= 15
        select topSound
        plus soundObject'i'
        topSound = Concatenate
        select topSound
        durTop = Get total duration
    else
        select topSound
        Save as WAV file... 'outputDir$''name$'_'i'.wav
        topSound = soundObject'i'
        durTop = dur
    endif
endfor

person user3746644    schedule 24.02.2016    source источник
comment
Что произойдет, если некоторые из ваших интервалов зондирования превышают 15 секунд?   -  person jja    schedule 25.02.2016
comment
@jja Если интервалы звучания превышают 15 секунд, я бы хотел, чтобы они были сохранены в отдельный файл wav.   -  person user3746644    schedule 25.02.2016


Ответы (1)


Давайте пройдемся по вашему сценарию по частям:

i = 2
for i to n

Здесь первая строка не будет иметь никакого эффекта, потому что цикл for инициализирует свою управляющую переменную значением 1 по умолчанию. Вместо этого вы должны написать for i from 2 to n.

select topSound
plus soundObject'i'
topSound = Concatenate

Вот почему ваши звуки объединяются в неправильном порядке. В Praat Concatenate объединяет звуки в том порядке, в котором они появляются в списке объектов. К сожалению, нет простых способов перемещать объекты в списке объектов. Но решить эту проблему можно копированием объектов, так как вновь созданные объекты всегда появляются внизу списка.

selectObject: soundObject[i]           ; Select the sound
tmp = Copy: selected$("Sound")         ; Copy (= move to bottom)
removeObject: soundObject[i]           ; Remove the original
soundObject[i] = tmp                   ; Update the object ID
selectObject: topSound, soundObject[i] ; Select the new objects
topSound = Concatenate                 ; Concatenate in the right order

С этими двумя изменениями ваш скрипт почти готов. Оставшаяся проблема заключается в том, что, поскольку вы сохраняете свои файлы, когда они превышают максимальную продолжительность, последняя часть (которая, как и оставшаяся часть, вероятно, будет короче) никогда не сохраняется. Вам нужно не забыть сохранить эту часть отдельно после окончания цикла.

Я сделал некоторые другие небольшие изменения, такие как добавление формы, преобразование ваших переменных в более правильные массивы и обновление синтаксиса в целом (selectObject вместо select), но я попытался аннотировать их, когда они неясны. Собрав все это вместе, вы получите что-то вроде этого

form Reticulate splines...
    sentence Sound_path  Desktop/englishTest.wav
    sentence Output_path Desktop/praat_output/
endform

sound = Read from file: sound_path$
sound$ = selected$("Sound")
silences = To TextGrid (silences):
  ... 100, 0, -25, 0.3, 0.1, "silent", "sounding"

selectObject: sound, silences
Extract intervals where:
    ... 1, "no", "is equal to", "sounding"
n = numberOfSelected("Sound")

for i to n
    soundObject[i] = selected("Sound", i)
endfor

topSound = soundObject[1]
selectObject: topSound
durTop = Get total duration

# new is a counter for the new objects we'll be making
new = 0
# Start for loop from second position
for i from 2 to n
    selectObject: soundObject[i]
    dur = Get total duration
    if durTop + dur <= 15
        # Rearrange objects in object list
        tmp = soundObject[i]
        selectObject: soundObject[i]
        soundObject[i] = Copy: selected$("Sound")
        removeObject: tmp
        previous = topSound
        selectObject: topSound, soundObject[i]
        topSound = Concatenate
        durTop = Get total duration

        # Remember to remove unwanted objects!
        removeObject: previous, soundObject[i]
    else
        # Save an array of new indices
        new += 1
        final[new] = topSound
        topSound = soundObject[i]
        durTop = dur
    endif
endfor
# Remember to add the last sound
new += 1
final[new] = topSound

# Clean up unwanted objects
removeObject: silences

# Loop through the array to rename them
nocheck selectObject: undefined
for i to new
    selectObject: final[i]
    Rename: sound$ + "_" + string$(i)

    ## You can save the objects automatically here
    ## but this is not the best design in my opinion
    # Save as WAV file: output_path$ + selected$("Sound")
endfor

# Select the newly extracted parts
nocheck selectObject: undefined
for i to new
    plusObject: final[i]
endfor

Это можно было бы дополнительно улучшить, например, заполнив нулями числа в ваших именах файлов, но это выходит за рамки. :)

Обновление: вот один из вариантов улучшения с немного другим алгоритмом и нарушением разбивайте более длинные куски на фрагменты, размер которых не превышает указанного вами максимума.

person jja    schedule 26.02.2016