Skip to content

Commit

Permalink
Documentation additions
Browse files Browse the repository at this point in the history
  • Loading branch information
ideoforms committed Oct 7, 2020
1 parent 2b63fd4 commit 4bddf6f
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 4 deletions.
43 changes: 42 additions & 1 deletion docs/events/action.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,44 @@
# Action events

Action events trigger Python functions.
Action events trigger Python functions. Set the `action` property to a function or lambda, and it will be executed at the time of the event:

```python
timeline.schedule({
"action": lambda: print("Hello world")
})
```

Observe that, when you run the above, it will print `Hello world` indefinitely, once per beat. Why is this?

Just as for [notes](note.md) and other event types, the `duration` parameter of the event template defaults to an infinitely-repeating pattern generated by `PConstant`. To limit the number of repeats that an action performs, use the `count` argument:

```python
timeline.schedule({
"action": lambda: print(round(timeline.current_time))
}, count=4)
```

## Action arguments

For more complex functions, custom named keyword arguments can be passed to the function using the `args` property

This executes an action every 4 beats to change the global key of the piece, using the [Globals](/patterns/#globals) variables:

```python
def set_key(k):
iso.Globals.set("key", iso.Key(key))

timeline.schedule({
"action": set_key,
"args": {
"k": iso.PWhite(8)
},
"duration": 4
})
timeline.schedule({
"degree": 0,
"key": iso.PGlobals("key"),
"octave": 4
})
```

4 changes: 3 additions & 1 deletion docs/events/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ Events are scheduled by passing a dict to `Timeline.schedule()`, which inspects
- Event dicts with a `control` or `program_change` key are assumed to be `control` events
- Event dicts with an `action` key is assumed to be an `action` event

The default values for unspecified parameters in an Event dict are infinite patterns generated by `PConstant`. This means that, unless a finite parameter is explicitly passed, events will continue to be generated forever.

## Event types

- [Note events](note.md) trigger discrete MIDI notes, with a duration and amplitude
- [Control events](control.md) include MIDI control change, program change and pitchwheel messages, and can apply quasi-continuous control curves
- [Action events](control.md) call arbitrary Python functions
- [Action events](action.md) call arbitrary Python functions
3 changes: 2 additions & 1 deletion docs/events/note.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,5 +141,6 @@ Many Pattern classes can operate explicitly on rests, or introduce rests.
For example:

- `PCollapse` takes an input and steps past any rests to remove gaps
- `PSkipIf` replaces notes with rests randomly given a probability
- `PSkipIf` replaces notes with rests given a conditional
- `PSkip` replaces notes with rests randomly given a probability
- `PPad` pads a sequence with rests until it reaches a specified length
8 changes: 7 additions & 1 deletion docs/patterns/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ StopIteration

Note that this means that patterns can't seek backwards in time. Their only concern is generating the next event.

By assigning patterns to properties of [events](events/index.md), you can specify sequences of values to control any aspect of the control output: pitch, velocity, duration, etc.
By assigning patterns to properties of [events](/events/), you can specify sequences of values to control any aspect of the control output: pitch, velocity, duration, etc.

Patterns can be finite, such as the example above, or infinite, in which case they will keep generating new values forever.

Expand All @@ -35,6 +35,12 @@ Patterns can also typically generate different Python types. Some Pattern classe
- `PWhite(0, 10)` generates a stream of ints between `[0 .. 9]`
- `PWhite(0.0, 10.0)` generates a stream of floats between `[0.0 .. 10.0]`
- `PChoice([ Key("C", "major"), Key("A", "minor") ])` picks one of the specified [Key](../events/note.md)s at random

## Pattern resolution

When a pattern returns a pattern, the embedded pattern will also be resolved recursively. For example:

- `PChoice([ PSequence([0, 2, 3]), PSequence([7, 5, 2 ]) ])` each step, picks one of the embedded patterns and returns its next value

## Pattern operators

Expand Down
8 changes: 8 additions & 0 deletions docs/timelines/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,14 @@ Scheduling can be quantized or delayed by passing args to the `schedule()` metho
- `quantize=N`: quantize to the next `N` beats before beginning playback. For example, `quantize=1` will quantize to the next beat. `quantize=0.25` will quantize to a quarter-beat.
- `delay=N`: delay by `N` beats before beginning playback. If `quantize` and `delay` are both specified, quantization is applied, and the event is scheduled `delay` beats after the quantization time.

To limit the number of iterations of an event, pass the `count` property:

```
timeline.schedule({
"note": iso.PSeries(0, 1) + 60
}, count=4)
```

## Clock resolution and accuracy

isobar's internal clock by default has a resolution of 480 ticks per beat (PPQN), which equates to a timing precision of 1ms at 120bpm.
Expand Down

0 comments on commit 4bddf6f

Please sign in to comment.