Reputation: 1513
I have two tiers within a textgrid and I'd like to combine them into one tier. Each tier is a different speaker. The intervals within each tier don't overlap. Is this possible? I've seen a lot of Praat scripts that will merge or concatenate but nothing to combine them. I've trying to use the Python tgt module to do this but it's been a slow go. I've been digging for a while so any suggestions on how to attack this problem are greatly appreciated! Thanks.
Upvotes: 3
Views: 1158
Reputation: 2098
Some time ago I wrote a script that was used to find non-overlapping intervals, also in tiers with different speakers. Although the task is different, the TextGrid that script creates to work on can be used for what you want.
The logic of that script is in a procedure that can be included into whatever script you are using (or canibalised into it, if you're into that sort of thing).
If you include that procedure (either physically copying it or include
ing it), you can do
old = selected("TextGrid")
@toNonOverlappingTiers()
new = selected("TextGrid")
After that, the new
TextGrid will have a single tier will all the intervals from the other tiers "flattened out". Each interval in this new tier with a non-zero label will represent a chunk of the old
TextGrid contained in labeled intervals in at most one tier. Unlabeled intervals were not contained in any labeled intervals in old
. The remaining labels tell you the tier number of the only labeled interval that contained them.
So after running the example above, you can do
# Loop through intervals in the new TextGrid
selectObject: new
for i to do("Get number of intervals...", 1)
label$ = Get label of interval: 1, i
# Since your original TextGrid had no overlapping intervals
# you only want labeled intervals (there will be no zeros)
if label$ != ""
# Get the midpoint, to match to intervals in a different
# tier in the original TextGrid
tier = number(label$)
start = Get start point: 1, i
end = Get end point: 1, i
midpoint = ((end - start) / 2) + start
# Get the original label
selectObject: old
j = Get interval at time: tier, midpoint
original$ = Get label of interval: tier, j
# Apply the original label to the new TextGrid
selectObject: new
Set interval text: 1, i, original$
endif
endfor
For archival purposes:
# This procedure is a part of the tgutils plugin
# Please see http://cpran.net/plugins/tgutils for more details
procedure toNonOverlappingIntervals ()
# Original TextGrid
.tg = selected("TextGrid")
.tiers = Get number of tiers
.start = Get start time
.end = Get end time
# Overlap TextGrid
.id = Create TextGrid: .start, .end, "overlap", ""
# Populate overlap tier with "flattened" intervals from all tiers
for .tier to .tiers
selectObject: .tg
.intervals = Get number of intervals: .tier
for .interval to .intervals-1
selectObject: .tg
.end = Get end point: .tier, .interval
# We use nocheck because there might already be a boundary there
selectObject: .id
nocheck Insert boundary: 1, .end
endfor
endfor
# Cycle through the flattened intervals to check how many spoken intervals
# align with each. A segment in the overlap tier will be considered to have no
# overlap if and only if there is one tier with a speech labeled interval which
# coincides with it.
selectObject: .id
.flat_intervals = Get number of intervals: 1
for .interval to .flat_intervals
.start = Get start point: 1, .interval
.end = Get end point: 1, .interval
.midpoint = (.end - .start) / 2 + .start
# Count how many speakers are speaking over that flattened interval
.speakers = 0
for .tier to .tiers
selectObject: .tg
.interval_number = Get interval at time: .tier, .midpoint
.label$ = Get label of interval: .tier, .interval_number
if .label$ != ""
# Increment the number of speakers for each labeled coinciding interval
# on any tier. We also save the tier number of the (last) speaker, so we
# know where to look for measurements later.
.speakers += 1
.speaker_tier = .tier
endif
endfor
# Label the overlap intervals. Blank intervals are matched by no speakers in
# any tier. Intervals labeled "0" are matched by more than one speaker, in
# more than one tier. The rest contain the tier number of the single speaker
# speaking at that time.
selectObject: .id
if .speakers = 1
Set interval text: 1, .interval, string$(.speaker_tier)
elif .speakers > 1
Set interval text: 1, .interval, "0"
else
Set interval text: 1, .interval, ""
endif
endfor
endproc
Upvotes: 1