Top and Tail

This chapter details a method of setting the start and end times of Audio cues by audio level threshold detection. It uses an OSC query and a script. It works in QLab 4 and in QLab 5.

Here it is in action:

Each of the selected cues is played from the beginning. When audio is detected above a threshold, the start time of the cue is set to this point, with the option to apply a short pad time to ensure the start of the audio is not clipped.

To ensure that the cue is played at a useful level for the detector, the main level and the level cue output 1 of the cue are temporarily set to 0 db.

To find the end of the cue is slightly more difficult. Short lengths of the audio, 0.2 seconds in duration, are played starting with the final 0.2 seconds of the cue. If no audio is detected during that time, the starting point is set 0.2 seconds earlier and another 0.2s is played. This process is repeated until audio above a threshold is detected. The end time of the cue is set to this point, with the option to pad the end time to ensure the end of the audio is not clipped.

This process is best done with the Times & Loops tab of the inspector open. The script pauses briefly after each edit to allow the user to visually confirm that the start or end marker has been placed correctly.

How It Works

“DETECT” is a Network cue with a long duration, set to repeat at 30 fps. It sends this OSC message:

/cue/RMS/postWait #/cue/selected/liveAverageLevel/1 0 100#

The portion of the message bounded by hashmarks is an OSC query; when the message is sent, the query is replaced by the value that the query returns.

This message sets the post-wait time of a Memo cue numbered “RMS” to the measured audio level of cue output 1 of the selected cue. The scaling of the measurement is set by the two arguments in the OSC query; in this case, a number between 0 and 100. The post-wait of the Memo cue is just used as a convenient place to store this variable for the script to use.

Here’s the script:

--This script requires a network cue  numbered "DETECT" sending the following OSC message at 30 fps for a duration of 10 s to port 53000 on localhost
-- /cue/RMS/postWait #/cue/selected/liveAverageLevel/1 0 100#
--This script requires a memo cue numbered "RMS" to store the current sound level

set threshold to 0.005 --detect threshold value between 0 and 100
set endThreshold to 0.005
set theStartPad to 0.2
set theEndPad to 0.5
set confirmTime to 0.5 --time to show each edit on screen before moving on 
-----------

display dialog "Set the Start Times of selected audio cues to start of audio" & return & return & "CAUTION: This plays each cue AT FULL LEVEL until the start of the audio" & return & return & " The first 1/10 second of each cue will be audible AND MIGHT BE VERY LOUD!"
try
  tell application id "com.figure53.QLab.5" to tell front workspace
    set theselected to (selected as list)
    repeat with eachCue in theselected
      set mainLevel to (getLevel eachCue row 0 column 0)
      set ch1Level to (getLevel eachCue row 0 column 1)
      setLevel eachCue row 0 column 0 db 0
      setLevel eachCue row 1 column 0 db 0
      set the selected to eachCue
      set the start time of eachCue to 0
      set the end time of eachCue to 99999
      set the post wait of cue "RMS" to 0
      delay 0.1
      start cue "DETECT"
      delay 0.1
      start eachCue
      delay 0.1
      repeat until post wait of cue "RMS" > threshold
        delay 0.01
      end repeat
      pause eachCue
      set the start time of eachCue to the (action elapsed of eachCue) - theStartPad
      stop eachCue
      
      delay confirmTime
      set theIndex to (end time of eachCue) - 0.2 - the (start time of eachCue)
      set x to 999999
      set post wait of cue "RMS" to 0
      repeat until post wait of cue "RMS" > endThreshold
        set theIndex to (theIndex) - 0.2
        delay 0.1
        load (eachCue) time theIndex
        delay 0.1
        start eachCue
        delay 0.2
        set x to theIndex
        pause eachCue
        delay 0.2
      end repeat
      stop eachCue
      set the end time of eachCue to x + (start time of eachCue) + theEndPad
      stop cue "DETECT"
      delay confirmTime
      
      
      setLevel eachCue row 0 column 0 db mainLevel
      setLevel eachCue row 1 column 0 db ch1Level
    end repeat
  end tell
on error
  display dialog "Something Went Wrong!" & return & "Are selected cues all audio?"
end try

At the top of the script are some variables that can be set by the user:

threshold is the audio level that will be used to set the provisional start time of the cue.

endThreshold is the audio level that will be used to set the provisional end time of the cue.

theStartPad is the amount of time that will be subtracted from the provisional start time when setting the start time of the cue.

theEndPad is the amount of time that will be added to the provisional end time when setting the end time of the cue.

confirmTime is the length of time the script will pause to display each edit before moving on to the next.

The script begins by displaying a dialog telling the user exactly what is about to happen, in order to give an opportunity for the operation to be cancelled. It also warns that the audio levels will be set to full and that this might result in loud sound output.

The script repeats for each of the selected cues.

First, it stores the current levels of the main output and cue output 1. It then sets these outputs to 0dB.

It then sets the selection to just the cue currently being edited.

The start time is set to zero, and the end time is set to the duration of the target audio file. The post-wait time of cue “RMS” is zeroed.

Cue “DETECT” is started just before the Audio cue, so it doesn’t miss any audio if the cue is already tightly edited.

Another repeat loop starts, which continues idling until the post-wait of cue “RMS”, i.e. the currently measured audio level, exceeds the threshold set.

The script then sets the start time to the time the threshold was exceeded minus the start pad time.

Another repeat loop then starts which sequentially plays 0.2 second bursts of the Audio cue starting with the end 0.2 seconds, and moving earlier in the cue until the measured audio exceeds the end threshold setting. Because the script is doing a lot at this point it can have difficulty accurately keeping track of the current elapsed time of the Audio cue. To get round this a variable x is set to the time each repeat is started from.

When the audio exceeds the end threshold setting, the end time is set to the time the threshold was exceeded plus the end pad time.

The levels of the main output and cue output 1 are then restored to their original values.

The script repeats until all the start and end times are set.

Goldberg Variations by J.S. Bach, public domain. The Open Goldberg Variations is a project by pianist Kimiko Ishizaka, and MuseScore.com, to create a public domain recording and score of J.S. Bach’s masterpiece, Die Goldberg Variationen (BWV 988).

Chapter image adapted by Mic Pool from a public domain photograph