MOSEF – a MOdular Synthesizer Framework for Java

In order to facilitate my experiments with sound synthesis, I have developed a software framework inspired by modular synthesizers, where a synthesizer consists of many connected modules, each with a very specific function. An important feature in modular synthesis is that the output of any module may be used as input in another, yielding endless possibilities in how to setup a synthesizer.

The framework is written in Java, and the core interface of the framework is the Module which has a single method which iterates the module and returns the output:

public interface Module {

  /**
   * Iterate the state of the module and return the output
   * buffer.
   * 
   * @return The output of this module.
   */
  double[] getNextSamples();

}

All modules in MOSEF are instances of this interface, exploiting the polymorphism of object-oriented programming to allow the output of any module to be used as input for another. A module may take any number of inputs and give a single output.

A simple example of a Module is an Amplifier which takes a single input, and gains it by a fixed value.

public class Amplifier implements Module {

  private final double[] buffer;
  private final Module input;
  private final double gain;

  public Amplifier(MOSEFSettings settings, 
                   Module input, double gain) {
    this.buffer = new double[settings.getBufferSize()];
    this.input = input;
    this.gain = gain;
  }

  @Override
  public double[] getNextSamples() {
    double[] inputBuffer = input.getNextSamples();
    for (int i = 0; i < buffer.length; i++) {
      buffer[i] = gain * inputBuffer[i];
    }
    return buffer;
  }

}

However, this amplifier can easily be changed into an amplifier where the gain is controlled by another Module. In modular synthesis this is called a voltage controlled amplifier (VCA):

public class VCA implements Module {

  private final double[] buffer;
  private final Module input, gain;

  public Amplifier(MOSEFSettings settings, 
                   Module input, Module gain) {
    this.buffer = new double[settings.getBufferSize()];
    this.input = input;
    this.gain = gain;
  }

  @Override
  public double[] getNextSamples() {
    double[] inputBuffer = input.getNextSamples();
    double[] gainBuffer = gain.getNextSamples();
    for (int i = 0; i < buffer.length; i++) {
      buffer[i] = gainBuffer[i] * inputBuffer[i];
    }
    return buffer;
  }

}

Note that this a module calls the getNextSamples method on its inputs, so a more complex synthesizer will consist of many modules in a tree structure, where calling getNextSamples on the root module will call all modules the root has a input, each of which will call all modules it has as input and so on.

The framework implements a number of basic modules including

  • Mixers,
  • Oscillators and LFOs,
  • Delays,
  • Envelope generators,
  • Low pass filters,
  • Offsetters,
  • Glide/portamento modules,
  • MIDI / wav inputs,
  • Noise generators,
  • Limiters,
  • Arpeggiators and sequencers.

The basic modules are available through the MOSEF factory class, simplifying the code needed to design complex synthesizers. For example, pulse-width modulation synthesis where the width of a pulse wave is controlled by a low frequency sine wave may be created as follows. Here the variable m is an instance of the MOSEF factory class, and the width of the pulse wave varies between 0.3 ± 0.1 with frequency 15 Hz.

Module modulator = m.offset(m.sine(15.0), 0.3, 0.1);
Module oscillator = m.pulse(in, modulator);

The framework is available on GitHub as well as some examples on how to use the framework.