Skip to contents

These functions calculate the ammount of time (either in beats, or seconds) that have unfolded since the beginning of a piece, giving a sense of the timeline in which events unfold. In music21 this information is described as "offsets"---however, we prefer to reserve the words "onset" and "offset" to refer to the beginning (attack) and end (release) of rhythmic events.

If timeline() is applied to a humdrumR data class you may use the data's fields as arguments. If no field names are specified, the first selectedField is used as x.

If timestamp() is applied to a humdrumR data class you may use the data's fields as arguments. If no field names are specified, the first selectedField is used as x.

Usage

# S3 method for default
timeline(
  x,
  start = 0,
  pickup = NULL,
  ...,
  Exclusive = NULL,
  threadNA = TRUE,
  parseArgs = list(),
  groupby = list()
)

humData |> select(Token) |> timeline() 
humData |> timeline(Token)

timeline(
  x,
  start = 0,
  pickup = NULL,
  ...,
  Exclusive = NULL,
  threadNA = TRUE,
  parseArgs = list(),
  groupby = list()
)

# S3 method for default
timestamp(
  x,
  BPM = 60,
  start = 0,
  pickup = NULL,
  minutes = TRUE,
  ...,
  Exclusive = NULL,
  threadNA = TRUE,
  parseArgs = list(),
  groupby = list()
)

humData |> select(Token) |> timestamp() 
humData |> timestamp(Token)

timestamp(
  x,
  BPM = 60,
  start = 0,
  pickup = NULL,
  minutes = TRUE,
  ...,
  Exclusive = NULL,
  threadNA = TRUE,
  parseArgs = list(),
  groupby = list()
)

Arguments

x

Input rhythm information.

Must be atomic, or NULL.

Is parsed as duration information.

start

Where does timeline begin?

Defaults to 0.

Must be a single number.

pickup

Where is there a pickup (anacrusis)?

Defaults to NULL

Must be logical of same length(x), Or NULL. See "Pickups" section below.

threadNA

Should rhythm-less tokens return NA?

Defaults to TRUE.

Must be a singleton logical value: an on/off switch.

parseArgs

An optional list of arguments passed to the rhythm parser.

Defaults to an empty list().

Must be a list of named arguments to the rhythm parser.

groupby

A list of vectors to group x.

Defaults to list().

Must be a list; every element of the list must be length length(x).

To function as a by-record timeline, the groupby list music include a named Piece and Record fields. Luckily, these are automatically passed by with(in).humdrumR, so you won't need to worry about it!

BPM

The tempo.

Defaults to 60.

Must be a single number or a character string in the format "MM120" (for 120 bpm).

By default, with(in).humdrumR passes the BPM field, if present.

minutes

Should minutes be counted in output?

Defaults to TRUE.

Must be a singleton logical value: an on/off switch.

If TRUE, output seconds are converted to a character string encoding minutes, seconds, and milliseconds in the format MM.SS.ms.

Details

Music unfolds over time, and humdrum data typically represents this by placing simultaneous events in the same record, with successive events in ever higher records---progressing "top down" through the file. In some humdrum data, only this (implicit) ordering of data over time is present. The Record and DataRecord fields capture this ordering in all data parsed by humdrumR. However, many (probably most) humdrum data files contain at least some information about the relative duration of events, representing more detailed information about timing and rhythm.

timeline() parses and input vector x as durations, computes the cumulative sum of the durations, with the start argument appended to the beginning. The result is a numeric vector representing the total duration since the beginning of the vector (plus the value of start, which defaults to zero). The cumulative durations of timeline() represent musical duration units, where 1 equals a whole note. timestamp() converts these durations to seconds, either using the BPM argument/field to determine the tempo or using the default tempo of 60 beats per minute. If minutes == TRUE, the output is formatted into "minute:seconds.milliseconds" character strings.

If a groupby argument is provided, localDuration() is used to compute the minimum durations in each group before computing the cumulative sum only with unique values from each Record in the groupby. By default, with(in).humdrumR will automatically pass groupby = list(Piece = Piece, Record = Record) into calls to timeline() or timestamp(). Thus, a call like within(humData, timeline(Token)) will compute the correct timeline position for all tokens across all spines/paths/stops---all values in the same record will be the same.

Note that, timeline() and timestamp() follow the default behavior of duration() by treating grace-notes as duration 0. This means that their position on the timeline is simply inherited from the previous event on the timeline, as if they occur at the same time. If you want to use the specified duration(s) of grace notes, specify grace = TRUE. By default, any other tokens without (parsable) rhythm information are returned a NA. However, if threadNA = FALSE, rhythm-less tokens will be treated as if they have a duration of 0 as well, and thus have a (shared) position on the timeline.

Pickups

Another option is to pass the pickup argument a logical vector of the same length as the input x. Within each piece/group, any block of TRUE values at the beginning of the pickup vector indicate a pickup. The first index where the pickup logical is FALSE is used as the starting point of the timeline/timecount; All the earlier (pickup == TRUE) points will be negative numbers, measured backwards from the start index. In humdrumR, and datapoints before the first barline record (=) are labeled Bar == 0 in the Bar field. Thus, a common use for the pickup argument is within(humData, timeline(Token, pickup = Bar < 1), which makes the downbeat of the first complete bar 1 the starting point of the timeline---any notes in pickup bars are negative on the timeline.

See also

The timecount() and metcount() functions provide "higher level" musical interpretations of timeline information.

Examples

tokens <- c('4.GG', '8G', '16E', '16F#', '16G', '16D', 'q8D#', '4E')

timeline(tokens)
#> [1] 0.0000 0.3750 0.5000 0.5625 0.6250 0.6875 0.6875 0.7500
timestamp(tokens, BPM = '90')
#> [1] ":0"     ":1"     ":1.333" ":1.500" ":1.667" ":1.833" ":1.833" ":2"    

if (FALSE) {
B075 <- readHumdrum(humdrumRroot, "HumdrumData/BeethovenVariations/B075_00_0._a.krn")
within(B075, timeline(Token))
}