Skip to content

voices and notes

scanner-darkly edited this page Jul 13, 2020 · 4 revisions

Typically a multipass app will produce some notes. How these notes will be output exactly depends on the hardware used. With multipass there are currently two ways to do it:

  • Set CV and gate output values directly or send I2C commands to a specific device
  • Use voice allocation and note functions provided by multipass

Setting CV and gate outputs directly

To set CV and gate outputs directly use the outputs functions. The main two functions are:

void set_cv(uint8_t output, int16_t value)
void set_gate(uint8_t output, uint8_t on)

As different devices or modules will have a different number of available outputs you might want to use get_cv_input_count and get_gate_input_count functions to determine the actual number. The set functions are self guarded however, so it's safe to use set_cv and set_gate even on a non existing output.

Typically you don't even need to check how many outputs are available. Let's say your app produces 4 CVs. You can simply update them using output numbers 0..3 (output numbers are 0-based), and when running on ansible or teletype you will get all 4 CVs, but the same firmware will only use the 2 available CV outputs on white whale without any modification needed. You really only need to check the number of outputs if the app behaviour needs to change based on how many outputs are available.

For voltage value range -16383..16383 range is mapped to -10V.._10V range. Please note monome eurorack modules only use 0..10V range. For convenience, MAX_LEVEL constant is provided.

Sending I2C commands directly

Multipass currently supports Telexi, Telexo, ER-301 and Just Friends I2C commands. Each device has its own specific set of commands, so you can do things like choose a waveform on Telexo, for instance, but all of them with the exception of Telexi have functions for updating CVs and gates.

In order to use these functions you will need to set multipass to act as an I2C leader:

set_as_i2c_leader();

You can switch it between a leader and a follower at any point. For more information refer to using I2C.

Voice allocation and note functions

Instead of using device specific functions it's more convenient to use the voice allocation and note functions provided by multipass.

With this approach you work with voices instead of devices. A voice is a virtual output that can be mapped to any physical output or a I2C device's output - or even any combination of outputs. When you output a note, you send it to a voice, and multipass will translate it into appropriate hardware actions. This allows you to re-use the same code for any device by simply reconfiguring a voice.

Mapping a voice is very simple:

map_voice(uint8_t voice, uint8_t device, uint8_t output, uint8_t on)

Calling this function will map the specified device output to the specified voice. Example:

map_voice(0, VOICE_TXO_NOTE, 0, 1);

This will map voice 0 to a Telexo device, output 0. Now whenever you send a note to voice 0 multipass will translate that into appropriate TXo I2C commands.

You can map multiple devices to the same voice. The following line maps voice 0 to CV/gate outputs 3:

map_voice(0, VOICE_CV_GATE, 3, 1);

Now any note sent to voice 0 will be output on both Telexo output 0 and CV/gate outputs 3.

To send a note you can either use note_on and note_off functions or a general note function where you can specify if it's a note on or a note off:

void note(uint8_t voice, uint16_t note, uint16_t volume, uint8_t on);
void note_v(uint8_t voice, int16_t pitch, uint16_t volume, uint8_t on);
void note_on(uint8_t voice, uint16_t note, uint16_t volume);
void note_on_v(uint8_t voice, int16_t pitch, uint16_t volume);
void note_off(uint8_t voice);

There are two ways to specify pitch. Functions note and note_on use chromatic scale semitones. Functions note_v and note_on_v can be used to specify any pitch (useful for microtonal scales), where the value maps to output voltage directly (so for 1V/Oct standard one octave is 1638).

Finally, you can transpose each device output separately by using the following functions:

void set_output_transpose(uint8_t device, uint16_t output, uint16_t note);
void set_output_transpose_v(uint8_t device, uint16_t output, int16_t pitch);

With this you could easily create chords by mapping one voice to several outputs and tranposing each output appropriately.

Note on I2C devices: when using them with voice mapping you still need to enable your app to act as a leader:

set_as_i2c_leader();

To use Just Friends in synth mode you also need to set the mode:

set_jf_mode(1);

For Telexo you can use it to either produce CV/gates:

set_txo_mode(0);

or use it as a sound source:

set_txo_mode(1);

On ER-301 outputs 0-15 are mapped to SC.CV 1-16 (pitch) and SC.TR 1-16 (gates). Volume values are sent to SC.CV 17-32.