Skip to content

Creating a new instrument

Warning

This page was written for a previous version of the app. The codebase has changed significantly since then, and this page may be out of date. Please refer to the source code for the most up-to-date information.

The following describes the process of creating a new instrument.

  1. Create assets for the instrument, including 3D model and texture.
  2. Export these assets in a way that the code can manipulate.
  3. Create a Kotlin class for the instrument.
  4. Write logic to drive animation procedurally from MIDI data.

Creating assets

First, create assets for the instrument. This includes the 3D model and texture.

3D Model

It might be necessary to export the 3D model in pieces for separate animation of individual components in the code. For example, the keys of the piano are separate from the body of the piano, so that the code animates they keys independently of the body.

Make sure each part exports with a transform of (0, 0, 0) and rotation of (0, 0, 0) so that the initial transformations don't offset transformations applied in code.

Free software such as Blender can be used to create the 3D model.

Export the 3D model as an Autodesk Filmbox—FBX—file.

Texture

Export the texture as a PNG file. The texture should be a single image that has all the textures for the instrument. It should ideally be a power of two in both dimensions—for example, 1024×1024, or 2048×2048.

Free software such as GIMP can be used to create the texture.

Loading assets

Place assets in the src/main/resources/Assets directory.

Creating a Kotlin class

Depending on the instrument, a relevant class likely already exists—use this class as the superclass. If not, create a new class that extends Instrument.

The following is the hierarchy of abstract classes for instruments. This promotes code re-usability.

This diagram shows properties and methods in those classes.

Procedural animation

The best way to create a new instrument is to reference an existing one. However, there are some components that are common to many instruments:

  • BellStretcher – Animates the bell of an instrument by stretching it based on the elapsed time of the NotePeriod.
  • EventCollector – On each frame, it collects MIDI events that have elapsed since the last frame.
  • FingeringManager – Handles the lookup of fingerings for an instrument.
  • NotePeriodCollector – On each frame, it collects NotePeriods whose start time has elapsed.
  • PercussionInstrument.recoilDrum(...) – Animates a drum recoiling.
  • PitchBendModulationController – Handles the calculation of pitch bend and modulation effects.
  • Striker – Provides common logic for objects that animate with a striking motion, such as drum sticks or mallets.
  • VibratingStringAnimator – Animates vibrating strings, as seen on the guitar, violin, and others.

The jMonkeyEngine documentation is a good place to start for learning how to animate objects in jMonkeyEngine.

Registering the instrument

Register the instrument in the buildInstrument function, located in the InstrumentAssignment class. Use existing instruments as a reference.