1. Communicating in OSC with score

Hello, and welcome to the first score tutorial.
In this tutorial we will see how to communicate with a simple PureData patch.

Presentation

When you first open score, you will be greeted by the following blank score.

score

At the left is the Device Explorer, which will show the parameters of the software or hardware that you wish to control.
In the center, the actual Score is present, and at the right, an element Inspector is shown. It is currently empty because no element is selected.
At the top, the transport section allows to start playing and stop the score, and we can zoom the main score view.
Multiple options and buttons are present in the top menu; we will leave them for now.

Creation of a PureData patch

First install PureData if you have not, and add the "mrpeach" extension in "Help > Find Externals".
This patch will listen for OSC messages on the port 9001 and print them on the console :

Minimal PureData patch
Minimal PureData patch

Connecting to the PureData patch from score

Then, we will add a corresponding device to score.
At the bottom of the Device Explorer, there is a blue Plus sign.
Click on it and select "Add device". Alternatively, you can right-click
on the background of the Device Explorer.

A new window will open, with multiple fields.
If the Protocol field isn't "OSC", select "OSC".

Then, set the device listening port to the Pd patch's port, here 9001 :

Creating an OSC device
Creating an OSC device

 

Any name can be given instead of OSCDevice; this is useful if you want to connect
to more than one patch.

Then press OK.
A new line appears in the Device Explorer :

OSC device created
OSC device created

This line represents a Device, it is an abstraction over a remote software or a remote hardware
controllable via OSC or any other protocol that score supports.

To communicate with it, we have to add an address to this device.
Right-click on the created Device, and select : "Add child".
Any name can be given. The allowed characters are integers, letters, dots and parentheses, e.g. "Fr.ui.t(36)".
For this example we choose the name "aValue".
In the "Value Type" field, put "Int".
This means that this address on the remote device expects to receive integer values (1, 2, 3, -5, 8192).
The other fields can be left as they are :

Creating an integer value
Creating an integer value

Upon validation, the tree can now be unfold and has a new node :

The integer value created
The integer value created

Testing

To test the behaviour, you can write numeric values in the "Value" column - for instance 42 -
They are sent to the PureData patch when pressing "Enter".

The PureData console should then display : "/aValue 42"

2. Scoring parameters with score

Hello, and welcome to the second score tutorial.

In this tutorial, we will see how to write a simple score for a PureData patch.
First, re-open the score and PureData patch of the precedent tutorial.
Ensure that nothing is selected in the Device Explorer.

We will try to have a basic organization of the evolution of a parameter in time.

For this, we will use the Score screen, the central screen in score.

Creating time.

There are multiple interactions possible with the score screen.
Generally speaking, elements are created in "Create" mode (key shortcut : c), and modified
in "Select and Move" mode (key shortcut : s).

When in "Create" mode, you can click anywhere in the screen.
The result will look like this :

Congratulations, you've just created your first Time Interval !

In score terminology, a Time Interval, represented as a horizontal blue line, represents a span of time; here it is lasting around 5 seconds as shown in the marker on top.

You can press play on the Transport bar or just press the spacebar to start playing :

Now, we want to actually send some data to our PureData patch.

To achieve this, score has the notion of State.
A State is a data container.
It will store OSC messages in the time-line, and when it is played, the message will be sent over the network.
To add a message, select the created address in the Device Explorer, and drag it to the little blue ball at the end of the created Interval.

The State's ball becomes bigger when hovering over it while dragging data to help targeting it.
When a state contains data, it becomes bigger and white.

Now, when pressing play again, look at the PureData console : the message will be sent.
Onwards!

Sequencing.

In this part, we will start to learn the basic interactions available to write
expressive interactive scores.
We will see how to sequence elements, and alter already-written data.

First switch to Create mode ('c') and keep "Shift" pressed.
Then, click on the State where the OSC message has been put, and move your mouse around : another Time Interval, following the first, will be created. You can revert the current action by pressing Escape at any time.

Likewise, you can drop messages to the State at the end of the second Time Interval.

For now, the first and the second Intervals are sharing a same State :

This means that the ending of the first is the beginning of the second : these three times are, in the score model, shared and equivalent to a single "Logical" time.

Intervals following themselves in a sequence like this are a bit similar to the notion of Track in traditional sequencers like Cubase, Pro Tools, etc.

We will now see how to have interesting data to send remotely in our sequences.

Automating.

Automations are a core concept of score. They allow to interpolate between two values during the execution of a Time Interval.

We will create our first automation.
First, change the value of the OSC address as shown in the previous tutorial.
The value should be different that the one that was dragged earlier.
Then, drop the new value in the second State in the Sequence.

We now have a interval whose first State contains the message OSCdevice:/aValue 34, and last state contains the message OSCdevice:/aValue 64. The address notation in score is of the form device:/osc/address [values...]. This way multiple Devices can have addresses with the same pattern and be differentiated, e.g. PureData:/volume and MaxMSP:/volume.

Finally, click on the Time Interval between these two states, and, on the top toolbar, press "Interpolate States".

An automation has been created for the value between these two states.

Upon pressing play, when the time cursor will be on the second interval, the PureData patch will start receiving interpolated values according to this curve.

 

3. First elements of interactivity

Hello,

In this third tutorial about score, we will start exploring the interactive possibilities available to the score author.

There are two main ways to have temporal interactivity :

  • Conditions
  • Interactive triggering

A condition means that a part of the score will only happen if some condition is true.
For instance, such a condition could be :

an:/osc/address == 100

Triggers are a more complex version of conditions.
They are a way of saying : "WHEN something happens, THEN do something".
The format of the expressions is the same.

Creation of a condition

First, create two Time Intervals following each other, like we saw before :
cst

Now, select the middle blue dot (a State).

 

Now, hit the C button on the top

this will create (actually, enable) a condition for this event.

By default, the condition is true.
This means that there is no condition, execution will just go on.

One can choose what kind of condition (<=, !=, >, etc.) he wants by clicking on the selector in the condition's inspector.

The fields are as follows :

  • (Optional) First one is to select a boolean operator when there are multiple expressions : "a:/b == 1 and c:/d == 2".
  • Second one is to put an OSC address
  • Third one is to put a comparator or action
  • Fourth one is to put a value or another address to compare with

For instance, given this tree :

One can input this condition :

Upon pressing validation (by clicking outside or pressing Enter / Return), the score becomes as follows :

If the value of OSCdevice:/my_node is unchanged, at 0, upon pressing play, the second interval is not executed :

The state also won't run as shown by its red color : it only happens if the condition is true.

Else, if the value is changed to something >= 12, everything will play.


The condition is checked exactly when execution reaches its point.

Branching

An interesting capacity of score is conditional branching.
It is a pattern in which you can write : "IF A happens THEN do X, ELSE IF B happens THEN do Y, ELSE IF C happen THEN do nothing..."

The Events allow for branching.
Click on the middle State, go into creation mode, and drag your mouse a bit : a new interval will be created :

branch0

As you can guess, the condition will apply on both following time intervals, which will either both happen in parallel, or both not happen at all.
It is possible to do branching even without condition : it will just run the parts of the score in parallel, like tracks in an audio sequencer.

To allow conditional branching, we have to split the event.
For this, you'll have to create a new Event - this is easily achieved by alt-dragging from the little + widget that appears when selecting a state.
branch1

As you can see, there is a thin dark line : this line is called a sync, and is what allows synchronization.
Now, what happens is that the condition (materialized by the yellow C) only matters for the topmost interval. The bottom one will execute regardless during execution.
Then, the same procedure than before can be applied in order to have multiple different synchronized conditions.

 

4. Interactive triggering with score

Hello, and welcome to this fourth tutorial about score.

In this tutorial, we will study how to write interactive triggers in score.
It is directly following the previous tutorial which was about interactive conditions.

Triggers are a way to specify interactivity : we can say
"WHEN A happens, THEN perform B".

Let's start with the following simple score.

Select the last State (the blue dot).

Hit the T button on the top:

A yellow T with an downward-pointing arrow should appear. This means that this state will be triggered interactively from now on.

The dashes signifies that "something" can happen.
Then, when clicking on the interval, in its inspector, more options appear, as showcased here :

The trigger, as mentioned before, has an expression. This expression is evaluated constantly whenever the score as reached the point where the trigger may be triggered (i.e. it has reached the beginning of the dashed part of the interval preceding the trigger).

When the execution reaches the max bound(s) of the intervals prior to the trigger, it will be automatically triggered.
When the expression is false, and the intervals prior to the trigger have no maximum bound, then the trigger will always be waiting to be triggered but
will never automatically trigger.

The expression editor of the trigger, as saw previously with the conditions, allows the following options :

  • The traditional operators "<, >, ==, <=, >=". In this case, the trigger is run as soon as an expression becomes true. If the expression is true beforehand, it will be triggered directly at the min boundary.
  • True : the trigger will always be true. This is the default case, also in operation if there is no expression. It means that it will be triggered as soon as the min boundary is reached during execution.
  • False : the trigger will always be false. This is useful to have infinite loops, for instance in order to build interactive installations that should always be running.
  • Pulse : the trigger will run as soon as a message is received on this address, without doing any conditional work.

Finally, during execution, one can trigger something by hand by clicking on the icon in the score view.

5. Recording external parameters with score

score allows recording the evolution of external parameters in time.

In this tutorial, we will see :

  • How to set-up a PureData patch that will send data to score.
  • The various modes of recording.
  • How to select and record parameters.

 

1. Setup of a PureData patch

This part is done with Pd, but also works with any OSC, OSCquery or Minuit-compliant device.
Here is an example patch that will send data to score :

patch-record
By default, this will send the "/aParameter N" OSC message to score whenever the slider moves,
with N being a number between 0 and 127.

2. Setup of score

First, create a device.
The score listening port shall be equal to the port connected to in PureData.

record-device

Then, as seen in the first tutorial, add a child node named "aParameter", to match the remote OSC device.
Either Int or Float types can be used.

Now, select the "aParameter" node in the Device Explorer :
select

3. Recording automations

Right-click anywhere in the main score, & in the context menu, select "Process > Record Automations from here".

A vertical bar appears : it is a box that awaits an event to start recording.
waitrecord

As soon as a message is received, the recording will start.

Only Float and Int parameters can be recorded this way.
So, as soon as the slider is moved in the PureData patch, a curve will appear in the box.

To stop the recording, press Stop or enter.
Here is a video of the full procedure :

By default, score simplifies the curve. The simplification settings can be changed :

There are 4 settings :

  • Simplification ratio : how many points will be removed.
  • Simplify : if there is any simplification.
  • Ramp to new value : instead of recording the addresses as parameters (i.e. even
    when a message is not received, record the current value), only record the
    incoming messages, and ramp between them.
    This means that if the message '0' is sent at the beginning, and five seconds after the message '1' is sent,
    there will be a ramp from 0 to 1, (triangular wave) while in the default mode, the curve will stay at 0 until five seconds and
    switch to 1 without continuity (square wave).
  • Play while recording : this will try to play the scenario at the moment where the recording happens.

4. Recording messages

The other option in the context menu, "Record messages from here", does record all the incoming messages
exactly as they enter score. Keep in mind that they will be played back at the update rate of score
which may not fit exactly with the rate at which messages were sent; this will cause jitter.

This option, however, cannot create a curve from the messages (what would be a curve of strings or impulses ?).
The recorded messages are visible in the inspector.

5. Recording multiple parameters

If multiple parameters are selected in the Device Explorer, they will all be recorded together.
If a parameter has children, they will also be recorded, recursively.