Architecture
Understanding how Rhapsodist is structured helps you navigate the codebase and extend it effectively. This document gives a high-level overview of the architecture of Rhapsodist.
Scripts Directory Structure
Scripts/
├── App/ # Application-level customization
│ ├── Manifest.js # Instrument configuration data
│ ├── Style.js # Visual styling
│ └── LookAndFeel.js # Custom drawing overrides
├── Rhapsodist/
│ ├── Core/ # Foundation modules (load first)
│ │ ├── Core.js # Entry point, engine setup
│ │ ├── Includes/ # Core supporting modules
│ │ ├── Widgets/ # Core UI components
│ │ ├── Processors/ # Core MIDI processors
│ │ └── ScriptFX/ # Scripted effect processors
│ ├── Widgets/ # General-purpose widgets
│ ├── Includes/ # Shared libraries
│ └── Processors/ # MIDI processing scripts
└── ScriptProcessors/ # HISE ScriptProcessor slots
└── expansion-name/
└── Interface.js # Main interface script entry
Core.js
Core/Core.js is the entry point for the Rhapsodist framework in your project.
Include it in your Interface.js script and click compile. This will trigger the setup functions in Rhapsodist that will create the basic user interface.
The first time you click compile you will see some error messages in the Console about missing components - don’t worry, that’s expected since the components don’t yet exist. Clear the Console and click compile a second time to complete the setup.
include("Rhapsodist/Core/Core.js");
Core Includes and Widgets
Core.js itself includes several other essential files from the Core/Includes and Core/Widgets folders. These provide features such as the header, footer, settings panel, preset browser, and tooltips, among much else.
You never need to manually include any files from the Core/Includes folder but you may want to interface with them from your own scripts, so it’s a good idea to look through them and read the core documentation.
Core Processors and ScriptFX
The Core folder also contains Processors and ScriptFX. These files are essential to most Rhapsodist expansions and need to be added to your project’s module tree. If you’re building off one of the templates then these files will already be present.
Includes, Processors, and Widgets
These three folders provide optional interface include scripts and MIDI processors that you can use in your projects.
For the most part they have been built as standalone modules, but some are designed to be able to work together.
UI and Processor Relationships
Following HISE best practices, the interface script processor is deferred by Core.js.
As such no MIDI or audio processing is handled directly by the interface script or its includes. The interface exists only to provide a point of feedback and interaction for the end user.
The actual processing is handled by separate modules, either stock HISE modules, modules you create yourself, or those provided by Rhapsodist.
This table lists some of the most common pairings:
| Widget | Paired Processors | Connection |
|---|---|---|
| ArticulationList | ArticulationGain.js | slpArticulationGain bound via processorId |
| MixerPanel | Mixer.js | Bound via processorId/parameterId |
| EnvelopePanel | AhdsrController.js, Flex AHDSR modulator | Knobs bound via processorId/parameterId; floating tile and drag broadcaster bound to flexEnvelopeId |
| EqPanel | Parametric EQ effect | floating tile Data references effectId directly |
| HarpPedalPanel | NoteTransposer.js | Writes to the sliderpack directly |
| VelocityTable | VelocityScaler.js | Table’s processorId/tableIndex properties |
| MicrotuningPanel | Microtuner.js | slpMicrotune sliderpack bound via processorId/SliderPackIndex |
The interface scripts and the modules can work independently or paired together, as described above. Because of this you can create custom interfaces for existing modules or use the existing interface to connect to a custom module.
Some scripts are more flexible than others in this regard and I suggest using the existing scripts as a starting point if you intend to create custom versions.
Component Hierarchy
The UI is structured as nested panels with specific roles:
pnlMain (root)
├── pnlHeader (fixed 50px)
│ ├── knbPatch (hidden, patch selection)
│ ├── knbArticulation (hidden, articulation)
│ ├── pnlPresetDisplay (preset browser controls)
│ ├── knbMasterPan / knbMasterVolume (header controls)
│ └── btnSettings (settings toggle)
├── pnlBody (flexible, instrument UI)
│ └── [Application-specific content]
├── pnlFooter (fixed 100px)
│ ├── fltPerformanceLabel (CPU/RAM/Voices)
│ ├── pnlLogo (company branding)
│ └── fltKeyboard (virtual keyboard)
├── pnlPresetBrowserContainer (overlay)
├── pnlSettingsContainer (overlay)
└── pnlTooltip (hover info)
App
Each project should have an App folder within its Scripts folder. App is not part of Rhapsodist but is a location for keeping files specific to each project.
Such files include custom look and feel, preset preprocessors, theming, and any other scripts that are unique to the project.
If you have scripts you want to share between projects you should consider using the Global Scripts Folder or HISE’s asset manager.
Manifest
The Scripts/App folder must contain a Manifest.js file. This is a critical script that is used throughout the framework. It provides the configuration for your expansion, patches, and articulations.
Patch and Articulation Changes
The interface shell UI contains two hidden knobs: knbPatch and knbArticulation. These keep track of the current patch and articulation respectively. They also save and restore with the user preset.
Both knobs are connected directly to two matching knobs in the ConfigurationHandler module. When a preset loads, the patch knob will fire, in turn this will trigger the ConfigurationHandler to load the configuration for the current patch from Manifest.js.
When an articulation is changed by clicking in the articulation list on the interface this will trigger a change of value for knbArticulation which will also cause the ConfigurationHandler's articulation knob to fire its callback and load the articulation’s configuration from the Manifest.
If you want to implement a custom articulation selector on the interface, it must update knbArticulation in order for the ConfigurationHandler to be able to respond to it.
When changing articulation by MIDI (key switches, CC, or bank/program change) the interface is not part of the process, as it is deferred. Here articulation switching is handled entirely by the ConfigurationHandler, which in turn will update its patch and articulation knobs.
The interface script should also respond to articulation change triggers for the purposes of updating the UI. ArticulationSwitcher.js provides onNoteOn and onController functions for this purpose that can be dropped into the appropriate MIDI callbacks.
Additionally all patch and articulation changes are broadcast on global cables (patch and articulation).
If you’re adding a feature that needs to react to a patch or articulation change, attach your own broadcaster to the shell’s knbPatch/knbArticulation (Interface script) or the patch/articulation global cable (separate module script).
Broadcasters
Internally, Rhapsodist uses HISE’s broadcaster system extensively for decoupled communication.