SPECTRE - Music editor

   


Song format

The song is built up from an array of arrays (of arrays...). This is the song structure:

[
  <speed>,          // Song speed (s / tick)
  <pattern-length>, // Pattern length (ticks per pattern)
  <song-length>,    // Song length (number of sequence steps)

  // Samples.
  [
    [<sample-0-definition>],
    [<sample-1-definition>],
    ...
  ],

  // Instruments.
  [
    [<instrument-0-definition>],
    [<instrument-1-definition>],
    ...
  ],

  // Node graph.
  [
    [<node-1-definition>],
    [<node-2-definition>],
    ...
  ],

  // Channels.
  [
    [<channel-0-definition>],
    [<channel-1-definition>],
    ...
  ],

  // Patterns.
  [
    [<pattern-1-definition>],
    [<pattern-2-definition>],
    ...
  ]
]

Sample definition

There are two different sample classes:

0: Oscillator / Percussion

[
  0,                 // type = Oscillator (0)
  <wave-amplitude>,  // Wave amplitude (0 = none, 1 = 100%)
  <modulation>,      // Frequency modulation (0 = none, >0 more modulation)
  <noise-amplitude>, // Noise amplitude (0 = none, 1 = 100%)
  <decay>,           // Decay (0 = no decay, >0 more decay)
  <duration>         // Duration (s)
]

1: FFT-based periodic wave

[
  1,                // type = FFT (1)
  <width>,          // Width of the fundamental (Hz, typically 1..10)
  <harmonic-decay>, // Decay of harmonics (typically 1..10)
  <formants>        // Formant ("voice") modulation (0 = none, 1 = 100%)
]

Example sample definitions

// Oscillator-based:
[0, 1.2, 1, 0.01, 6, 0.17]  // Tom
[0, 10, 0.1, 7, 6, 0.1]     // Snare drum
[0, 0, 0, 1, 4, 0.1]        // Hihat (route through a highpass filter)

// FFT-based:
[1, 2, 2.1, 0]              // String-like looping wave
[1, 6, 1.2, 1]              // Voice/choir-like looping wave

Instrument definition

An instrument references a sample, and can be either one-shot (useful for percussion), or looping with an envelope (useful for leads, pads, etc).

One-shot

[
  <sample>          // The sample that this instrument should use
]

Looping with envelope

[
  <sample>,         // The sample that this instrument should use
  <attack>,         // Attack duration (s)
  <sustain>,        // Sustain duration (s)
  <release>         // Release duration (s)
]

Node graph definition

The effect node graph is fairly modular. Each node in the graph has one output that can be connected to another node, and each node can have any number of inputs, making it possible for an effect node to process several channels.

Node numbering

Nodes are identified by their index in the node definition array. Note: The first array item has index one (1), since index zero (0) is reserved for the audio output node of the audio context.

Automation

Effect node parameters that can be automated can eiter be given as a scalar number (i.e. a constant value for the entire song), or as a pattern sequence (i.e. an array of pattern numbers), where the indicated patterns hold the parameter value for different points in time.

Values are linearly interpolated between the defined (non-zero) pattern values.

Parameters that can be automated are indicated with a *.

Common node definition

[
  <node-type>,         // The node type:
                       //   0: Convolver (useful for reverb)
                       //   1: Dynamic compressor
                       //   2: Filter
                       //   3: Echo (delay)
                       //   4: Distortion
  <destination-node>,  // The destination node number
  <wet*>,              // Wet mix (0 = none, 1 = 100%)
  <dry*>,              // Dry mix (0 = none, 1 = 100%)
  (type-specific parameters)
]

0: Convolver

[
  (common parameters)
  <sample>       // The sample to use for convolution
]

For instance, to create a 1 second long reverb, you can use the following:

  // Samples
  [
    [0, 0, 0, 1, 5, 1], // Sample #0: 1 s of decaying noise
    ...
  ],

  ...

  // Effect nodes
  [
    ...
    [0, 0, 0.7, 1, 0],  // Convolver, destination = 0,
                        // 70% wet, 100% dry, use sample #0
    ...
  ],

  ...

1: Compressor

The dynamic compressor takes no parameters.

2: Filter

[
  (common parameters)
  <filter-type>,  // Filter type:
                  //   0: lowpass
                  //   1: highpass
                  //   2: bandpass
  <frequency*>,   // Cutoff / center frequency (Hz)
  <Q*>            // Q / resonance
]

3: Echo

[
  (common parameters)
  <delay-time*>, // Delay time (song ticks)
  <feedback*>    // Feedback (0 = none, 1 = 100%)
]

4: Distortion

[
  (common parameters)
  <distortion>  // Distortion parameter:
                //   0 = Maximum distortion (square shape)
                //   1 = No distortion (linear)
                //   >1 = "Inverted" distortion
]

Channel definition

[
  <destination-node>,    // The destination node number
  <instrument>,          // The instrument number to use
  <volume>,              // Channel volume (0 = silence, 1 = 100%)
  [<pattern-sequence>],  // Pattern sequence for the 1st voice (REQUIRED)
  [<pattern-sequence>],  // Pattern sequence for the 2nd voice (OPTIONAL)
  [<pattern-sequence>],  // Pattern sequence for the 3rd voice (OPTIONAL)
  ...
]

A pattern sequence lists the pattern numbers in the order that they should be played in this channel. Use zero (0) or nothing to mark a sequence slot as empty.

Multiple pattern sequences can be defined for each channel. They will be played in parallel, making it possible to play chords for instance.

Pattern definition

A pattern lists the notes or automation values in the order that they should be played. Use zero (0) or nothing to mark a sequence slot as empty.

Note patterns

Notes are given as decimal numbers, with 36 being C4 (261.63 Hz), and each integer increment represents a semitone (12 semitones makes an octave). The table below lists a few notes:

Note #NameFrequency [Hz]
12C265.41
24C3130.82
36C4261.63
48C5523.26

Automation patterns

Automation values are given in the unit that is expected by the parameter that is being automated. For instance, to set the filter cutoff parameter to 1000 Hz, specify 1000 in the pattern.