# Timing Callbacks
This runs an animation timer and does callbacks at various intervals. This allows you to do various effects that are timed with beats or playing notes.
## Creation
To use this create an instance of it:
```javascript
var timingCallbacks = new abcjs.TimingCallbacks(visualObj, params);
```
| Parameters | Description |
| ------------- | ----------- |
| visualObj | This is the output of the `renderAbc()` call. It is the music that will be timed. |
| params | This is a object. See below for the possible properties. |
## Parameters
| Name | Default | Description |
| ------------- | ------- | ----------- |
| `qpm` | whatever is in the Q: field | Number of beats per minute. |
| `extraMeasuresAtBeginning` | 0 | Don't start the callbacks right away, but insert this number of measures first. |
| `beatCallback` | null | Called for each beat passing the beat number (starting at 0). |
| `eventCallback` | null | Called for each event (either a note, a rest, or a chord, and notes in separate voices are grouped together.) |
| `lineEndCallback` | null | Called at the end of each line. (This is useful if you want to be sure the music is scrolled into view at the right time.) See `lineEndAnticipation` for more details. |
| `lineEndAnticipation` | 0 | The number of milliseconds for the `lineEndCallback` to anticipate end of the line. That is, if you want to get the callback half a second before the end of the line, use 500. |
| `beatSubdivisions` | 1 | How many callbacks should happen for each beat. This allows finer control in the client, for instance, to handle a progress bar. |
## Callbacks
### beatCallback
This is called once for every beat in the tune. It is called one additional time when the tune is finished.
```javascript
function beatCallback(beatNumber, totalBeats, totalTime, position, debugInfo) {}
```
|Name|Description|
|---|---|
| beatNumber | Zero-based beat number. Usually this will increment sequentially and regularly, but if javascript is paused long enough (for instance, if the browser tab is changed), then there may be a number of these calls at once when it catches up. |
| totalBeats | The total number of beats (including all repeats) that will be played. |
| totalTime | The total number of milliseconds of the tune. |
| position | The interpolated position of the cursor if the beat occurs between notes. This is an object with the attributes { left: , top: , height: } This can be used to smooth out the cursor by moving it on the beat callbacks. The higher the number of `beatSubdivisions` the smoother the cursor will be. |
| debugInfo | A hash of some extra info that might be useful in figuring out why the callback was triggered. |
### eventCallback
This is called once for every "event" in time - either a note or a rest. If there are multiple notes at the same time, then it is only called once
for that group of notes.
```javascript
function eventCallback(ev) {}
```
The parameter `ev` is an object that looks like this:
```javascript
ev = {
"type": "event", // This is always "event"
"milliseconds": number, // The number of milliseconds from the beginning of the piece
"millisecondsPerMeasure": number, // The number of milliseconds per measure
"line": number, // The current "line", that is, the staff system.
"measureNumber": number, // The measure number. Resets per line, so the first measure number on a line is zero.
"top": number, // The number of pixels from the top of the svg that the note appears.
"height": number, // The height of the note, in pixels.
"left": number, // The number of pixels from the left edge of the svg.
"width": number, // The width of the note
"elements": [ ], // Array of the actual elements on the page that are represented by the note or notes.
"startCharArray": [ number ], // the character position in the original abc string
"endCharArray": [ number ], // the character position in the original abc string
"midiPitches": [ // Array of the currently playing pitches
{
"pitch": number, // The pitch number (based on the midi standard, i.e. middle C is 60)
"durationInMeasures": number, // the note value as a fraction. (that is, a quarter note is 0.025)
"volume": number, // The volume expressed as a number between 0 and 127
"instrument": number // The instrument number (based on the midi standard, i.e. acoustic_grand_piano is 0)
}
]
}
```
#### Notes:
* The `startCharArray` and `endCharArray` are arrays because there is more than one location in the abc string if there is more than one voice.
* The format of the `elements` array is subject to change in future versions.
* This is called one last time with passing in `null` at the end of the tune. On that call `eventCallback` can return the string "continue" to keep the timer from stopping. This is useful if you want to play on repeat - in theory you would probably have another call to `seek()`.
* This function can be a Promise or not.
### lineEndCallback
This will be called as the cursor is approaching the end of a line of music. This is useful if there is more than a screen's worth of music; it can be used to scroll the page at the right time.
```javascript
function lineEndCallback(info, event, details) {}
```
The parameter `info` looks like this:
```javascript
info = {
"milliseconds": number, // current milliseconds from beginning of piece
"top": number, // The number of pixels from the top of the svg to the top of the cursor
"bottom": number // The number of pixels from the top of the svg to the bottom of the cursor
}
```
The parameter `event` is the standard note event.
The parameter `details` looks like this:
```javascript
details = {
"line": number, // the current line number (zero-based)
"endTimings": array // the array of the timings for each line
}
```
The `endTimings` array elements are of the same type as the `info` parameter.
## Functions
These are the entry points that can be called on the `timingCallbacks` object.
### start(position, units)
This starts the timer that triggers the callbacks. This is called to both start and resume after calling pause. See the `setProgress` method below for explanation of the parameters with one special case:
If `position` is undefined then if the previous call was to `pause()`, then the animation continues from where it left off. If there was no pause, then the animation starts from the beginning.
### pause()
Pauses the animation. Calling `start()` afterwards will resume from where it left off.
### stop()
Stop the animation. After calling this, the next call to `start()` will start at the beginning.
### reset()
Move the timer back to the beginning, so the animation starts over. This can be called either when the animation is currently running or when it is paused.
### setProgress(position, units)
Change the position of the animation. This allows random access to any place in the tune.
If the second parameter is not present, then `units` equals "percent". The possible values are:
* `"percent"`: The percent passed in is a number between 0 and 1. This can be called either when the animation is currently running or when it is paused.
* `"seconds"`: The seconds from the beginning of the tune. If this is passed the end of the tune it is changed to the end.
* `"beats"`: The beats from the beginning of the tune. If this is passed the end of the tune it is changed to the end.
### replaceTarget(visualObj)
If the underlying music changes on the fly, this replaces the current object without having to destroy the object and start over. `visualObj` is the return value from `renderAbc`.
## Example
Paste in any ABC you want here then click "start" to see what is returned by the timing callbacks: