Repository files navigation

BannerMusicEngine

LicenseC#.NETJoin DiscordStatus

MusicEngine

Scriptable C# music engine for realtime playback, instruments, and VST3 hosting. It can also record mics and music, render audio, and cover a full DAW-like workflow if you know what you're doing.

What makes MusicEngine different?

MusicEngine is a C# scripting language for music. It supports VSTs, sequencers, and patterns without forcing you into any workflow. You keep full control over time and timing. Everything is a tool, nothing is forced, and there are no hidden mathematical clamps. Almost anything can be turned into a variable and be modulated.

Pattern Example (Script)

varsynth=CreateSynth();varpattern=CreatePattern(synth);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Note(60,2.0,1.0,110,slideTo:67,slideTimeMs:500);pattern.NoteMs(72,1500,250,110);// Note(...) auto-uses ms when duration > 8.0 or beat > 32.0 (still supports beats)pattern.Note(72,1500,250,110);varseq1=pattern.Note(60,0.0,0.25,100).Siquenz("0010101001101110");seq1.Loop=true;pattern.Play();

MIDI Routing Example (Script)

varsynth=CreateSynth();midi.device(0).to(synth);midi.device(0).cc(1).to(value =>synth.SetParameter("cutoff",value));midi.device(0).pitchbend().to(value =>synth.PitchBend(value*2f-1f));

More MIDI details: Docs/Midi.md

Device/channel/route toggles:

varsynth=CreateSynth();varmidi1=midi.Device(0);// device handlevarroute1=midi.Device(0).to(synth);// device -> synth routemidi1.Active(false);// disable device inputmidi1.Active(true);// enable device inputmidi.Device(0).Channel(1).Active(false);// disable channel 2 on device 0route1.Active(false);// disable only this route

Modular Effects Example (Script)

varfx=CreateEffect().ReverbPreset("Hall").BitCrushPreset("Lofi").NoisePreset("Light").FilterPreset("Low");varch1=Audio.CreateChannel(1);ch1.Effect(fx);

Preset factory:

varch2=Audio.CreateChannel(2);ch2.Effect(Effect.Reverb);ch2.Effect(Effect.Drive);

Preset names:

varfx2=CreateEffect().ReverbPreset("Hall").DelayPreset("Echo").DrivePreset("Warm");Audio.CreateChannel(3).Effect(fx2);

Preset with overrides:

varfx3=CreateEffect().ReverbPreset("Hall", r =>r.Mix=0.4f).DelayPreset("Echo", d =>d.TimeMs=500f).FilterPreset("Low", f =>f.CutoffHz=800f);Audio.CreateChannel(4).Effect(fx3);

Standalone preset (for modulation):

varreverbFx3=ReverbPreset("Hall", r =>r.Mix=0.4f);varmix=Mod.Var(reverbFx3,"Mix");mix.Lfo(0.2f,0.6f,rateHz:0.5f);

Modular Oscillators (Hybrid Synth)

varsynth=CreateSynth();varosc3=synth.Oscillator();osc3.Waveform=WaveType.Sine;osc3.Level=0.2f;osc3.Pan=-0.2f;varosc4=synth.Oscillator();osc4.Waveform=WaveType.Sine;osc4.Level=0.2f;osc4.Pan=0.2f;osc4.ModToFilter=0.2f;

Wavetable Oscillators

varsynth=CreateSynth();// Built-in tablessynth.Osc1Wavetable=Wavetable.Saw(2048);synth.Osc2Wavetable=Wavetable.WhiteNoise(2048);// Custom file (first channel)varwt=Wavetable.FromFile("my_wave.wav",maxSamples:2048);varosc=synth.Oscillator();osc.Wavetable=wt;osc.Enabled=true;

VST3 Example (Script)

varvital=CreateVst("Vital");vital.SetParameterNormalized("Cutoff",0.5f);midi.device(0).to(vital);midi.device(0).pitchbend().to(value =>vital.PitchBend(value*2f-1f));varpattern=CreatePattern(vital);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Play();

Note: VST UI embedding is Windows-only for now. Linux runs VST audio + parameters without the editor window.

VST State Save/Load

varvital=CreateVst("Vital");vital.State();// on /S or exit, writes base64 into the ()

Notes:

  • The inline State() call is updated on refresh or exit, so you can copy/share the script.
  • States are stored per script under .musicengine/states/<script>/<name>.state.
  • Missing VSTs warn and stay silent instead of crashing.

Manual overrides still work:

vital.LoadState("States.vital.state");vital.SaveState("States.vital.state");

Virtual Output (Discord / Virtual Mic)

To send audio into Discord as a microphone, you need a virtual audio device (e.g. VB-CABLE or VoiceMeeter). MusicEngine can route the master or a channel to any Windows output device.

Audio.Output.List();// list render devicesAudio.Master.VirtualOut("CABLE Input");// route master to virtual micvarch1=Audio.CreateChannel(1);ch1.VirtualOut("CABLE Input");// route channel to virtual mic

Notes:

  • Without a virtual audio device installed, Windows has no "virtual mic" target.
  • In Discord, set Input Device to the virtual cable.

Audio Input (Mics / Line-In)

Note: audio input is Windows-only right now.

Audio.Input.List();// list capture devicesvarmic=CreateMic(0);// or CreateInput(0)varch1=Audio.CreateChannel(1);ch1.Route(mic);ch1.Gain(0.7);

Fluent Instrument Setup

CreateGeneralMidi().Pan(0.2f).Channel(0).Name("GM_AcousticGrandPiano");CreateSynth().Volume(0.7f).Pan(-0.2f);CreateVst("Vital").Volume(0.9f).Pan(0.1f);CreateMic(0).Gain(0.8f).Mute(false);

Variable Modulation

varpan=Mod.Pan(piano,0f);pan.Random(-0.5f,0.5f,everyMs:400);varvol=Mod.Volume(synth,0.7f);vol.Lfo(0.2f,0.9f,rateHz:0.5f);// Any propertyvarcutoff=Mod.Var(synth,"Cutoff");cutoff.Random(0.2f,0.9f,everyMs:300);

General Instruments Example (Script)

varpiano=CreateGeneralMidi();piano.Program=GeneralMidiProgram.AcousticGrandPiano;piano.Volume=0.8f;piano.Pan=0f;piano.Reverb=0.2f;piano.Channel=0;midi.device(0).to(piano);midi.device(0).pitchbend().to(value =>piano.PitchBend(value*2f-1f));varpattern=CreatePattern(piano);pattern.LoopLength=4.0;pattern.Note(60,0.0,1.0,100);pattern.Note(67,1.0,1.0,100);pattern.Note(72,2.0,2.0,100);pattern.Play();

Features (Current)

  • Low-latency MIDI routing and controller mapping.
  • Scriptable pattern sequencer with loop length and per-note velocity.
  • Built-in polyphonic synth with oscillators, ADSR, filter, LFO, and effects.
  • General MIDI output wrapper for system MIDI devices.
  • VST3 hosting with parameter control and editor support.
  • Channel routing with per-channel effects and master processing.
  • Recording taps for master and per-channel audio.

Planned Features

  • Lighting and show control: DMX512, Art-Net, sACN (E1.31), MIDI Show Control.
  • MIDI and timing: MIDI 1.0, MIDI 2.0, MTC, SMPTE/LTC sync, OSC control, MIDI screen/LED feedback with live data.
  • Audio routing: Windows ASIO/WaveOut plus virtual outputs, Linux PortAudio (default device).
  • Game engine integration: Unity/Unreal hooks, custom engine integration, realtime music logic control.
  • Modular control: CV rack-style modularity via code for every variable and setting.
  • DSP and hardware: planned DSP control surface and library to drive custom sound cards for full flexibility.

Notes

  • The project uses NAudio for audio/MIDI and provides its own instrument wrappers.
  • VST3 scanning can be configured via MUSICENGINE_VST3_PATHS (path-separator separated).
  • Extra free instruments, kits, and tools live in the companion library:
  • MusicEngine.Library

MusicEngine.Library (Optional Content)

MusicEngine.Library is a separate, community-driven repository of free instruments, kits, and utilities. It is optional: the engine runs without it. When present, you can load instruments with:

varspeech=LibraryApi("MusicEngine.Instruments.SpeechInstrument");

Use cases:

  • Sample-based kits (drums, one-shots, multisamples).
  • Procedural instruments (speech, drones, generators).
  • Utility helpers to build instruments from local folders.

Missing library instruments are skipped and stay silent (no crash), similar to missing VSTs.

Install

  • Install .NET SDK 10.0 (or newer).
  • Windows: install Visual Studio 2022 with Desktop development with C++ (for the native VST3 host).
  • Linux: install cmake, build-essential, and the PortAudio dev package (e.g. portaudio19-dev).
  • Rider works fine, but MSBuild from Visual Studio Build Tools is still required for the Windows native layer.

Settings reference: Docs/Settings.md

Linux Notes

  • Output uses PortAudio (default device).
  • VST UI embedding is not supported yet.
  • Audio input/recording are not supported yet.
  • Sample loading currently supports WAV (PCM/float) only.

Script Location

The engine scans the default project folder:

Test Project/

Any .cs or .csx file can be a main script if it calls File.Main(); or File(Main, "Name");. To use a different project folder, set MUSICENGINE_PROJECT_DIR (or pass --project-dir <path>). The engine looks for Test Project/ first and then the legacy Scripts/ folder inside that project directory.

Build

Managed build (C#):

  • Open the solution in Rider or Visual Studio and build the MusicEngine project.

Native VST3 host (C++):

  • First-time setup (pull the Steinberg SDK into external/vst3sdk):
    • git clone https://github.com/steinbergmedia/vst3sdk.git external/vst3sdk
    • git -C external/vst3sdk submodule update --init --recursive

Windows build (MSBuild):

  • Rider: open MusicEngine.CppLayer/native/MusicEngine.CppLayer.Native.vcxproj and build x64 Debug/Release.
  • Visual Studio: open the same .vcxproj, select x64 + Debug/Release, then Build.
  • Command line (PowerShell):
    • & "C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" "MusicEngine.CppLayer\native\MusicEngine.CppLayer.Native.vcxproj" /p:Configuration=Release /p:Platform=x64

Linux build (CMake):

  • cmake -S MusicEngine.CppLayer/native -B MusicEngine.CppLayer/native/build -DCMAKE_BUILD_TYPE=Release
  • cmake --build MusicEngine.CppLayer/native/build --config Release

The native build copies MusicEngine.CppLayer.Native.dll or libMusicEngine.CppLayer.Native.so into MusicEngine\ automatically (and C# build copies it to the output).

Troubleshooting native build:

  • Error: Cannot open include file: public.sdk/source/vst/hosting/module.h
    • The SDK submodules are missing or empty. Run:
      • git -C external/vst3sdk submodule update --init --recursive
      • If the submodules are present but empty, reset them:
        • git -C external/vst3sdk/public.sdk reset --hard
        • git -C external/vst3sdk/base reset --hard
        • git -C external/vst3sdk/pluginterfaces reset --hard

Mentions

Links

Copyright 2026 watermann429 and contributers.

About

Music Engine is a modular, open-source live-coding music engine written in C#. It combines code, MIDI, patterns, and real-time audio to enable flexible music production, live performance, and interactive audio programming.

Topics

Resources

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

BannerMusicEngine

LicenseC#.NETJoin DiscordStatus

MusicEngine

Scriptable C# music engine for realtime playback, instruments, and VST3 hosting. It can also record mics and music, render audio, and cover a full DAW-like workflow if you know what you're doing.

What makes MusicEngine different?

MusicEngine is a C# scripting language for music. It supports VSTs, sequencers, and patterns without forcing you into any workflow. You keep full control over time and timing. Everything is a tool, nothing is forced, and there are no hidden mathematical clamps. Almost anything can be turned into a variable and be modulated.

Pattern Example (Script)

varsynth=CreateSynth();varpattern=CreatePattern(synth);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Note(60,2.0,1.0,110,slideTo:67,slideTimeMs:500);pattern.NoteMs(72,1500,250,110);// Note(...) auto-uses ms when duration > 8.0 or beat > 32.0 (still supports beats)pattern.Note(72,1500,250,110);varseq1=pattern.Note(60,0.0,0.25,100).Siquenz("0010101001101110");seq1.Loop=true;pattern.Play();

MIDI Routing Example (Script)

varsynth=CreateSynth();midi.device(0).to(synth);midi.device(0).cc(1).to(value =>synth.SetParameter("cutoff",value));midi.device(0).pitchbend().to(value =>synth.PitchBend(value*2f-1f));

More MIDI details: Docs/Midi.md

Device/channel/route toggles:

varsynth=CreateSynth();varmidi1=midi.Device(0);// device handlevarroute1=midi.Device(0).to(synth);// device -> synth routemidi1.Active(false);// disable device inputmidi1.Active(true);// enable device inputmidi.Device(0).Channel(1).Active(false);// disable channel 2 on device 0route1.Active(false);// disable only this route

Modular Effects Example (Script)

varfx=CreateEffect().ReverbPreset("Hall").BitCrushPreset("Lofi").NoisePreset("Light").FilterPreset("Low");varch1=Audio.CreateChannel(1);ch1.Effect(fx);

Preset factory:

varch2=Audio.CreateChannel(2);ch2.Effect(Effect.Reverb);ch2.Effect(Effect.Drive);

Preset names:

varfx2=CreateEffect().ReverbPreset("Hall").DelayPreset("Echo").DrivePreset("Warm");Audio.CreateChannel(3).Effect(fx2);

Preset with overrides:

varfx3=CreateEffect().ReverbPreset("Hall", r =>r.Mix=0.4f).DelayPreset("Echo", d =>d.TimeMs=500f).FilterPreset("Low", f =>f.CutoffHz=800f);Audio.CreateChannel(4).Effect(fx3);

Standalone preset (for modulation):

varreverbFx3=ReverbPreset("Hall", r =>r.Mix=0.4f);varmix=Mod.Var(reverbFx3,"Mix");mix.Lfo(0.2f,0.6f,rateHz:0.5f);

Modular Oscillators (Hybrid Synth)

varsynth=CreateSynth();varosc3=synth.Oscillator();osc3.Waveform=WaveType.Sine;osc3.Level=0.2f;osc3.Pan=-0.2f;varosc4=synth.Oscillator();osc4.Waveform=WaveType.Sine;osc4.Level=0.2f;osc4.Pan=0.2f;osc4.ModToFilter=0.2f;

Wavetable Oscillators

varsynth=CreateSynth();// Built-in tablessynth.Osc1Wavetable=Wavetable.Saw(2048);synth.Osc2Wavetable=Wavetable.WhiteNoise(2048);// Custom file (first channel)varwt=Wavetable.FromFile("my_wave.wav",maxSamples:2048);varosc=synth.Oscillator();osc.Wavetable=wt;osc.Enabled=true;

VST3 Example (Script)

varvital=CreateVst("Vital");vital.SetParameterNormalized("Cutoff",0.5f);midi.device(0).to(vital);midi.device(0).pitchbend().to(value =>vital.PitchBend(value*2f-1f));varpattern=CreatePattern(vital);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Play();

Note: VST UI embedding is Windows-only for now. Linux runs VST audio + parameters without the editor window.

VST State Save/Load

varvital=CreateVst("Vital");vital.State();// on /S or exit, writes base64 into the ()

Notes:

  • The inline State() call is updated on refresh or exit, so you can copy/share the script.
  • States are stored per script under .musicengine/states/<script>/<name>.state.
  • Missing VSTs warn and stay silent instead of crashing.

Manual overrides still work:

vital.LoadState("States.vital.state");vital.SaveState("States.vital.state");

Virtual Output (Discord / Virtual Mic)

To send audio into Discord as a microphone, you need a virtual audio device (e.g. VB-CABLE or VoiceMeeter). MusicEngine can route the master or a channel to any Windows output device.

Audio.Output.List();// list render devicesAudio.Master.VirtualOut("CABLE Input");// route master to virtual micvarch1=Audio.CreateChannel(1);ch1.VirtualOut("CABLE Input");// route channel to virtual mic

Notes:

  • Without a virtual audio device installed, Windows has no "virtual mic" target.
  • In Discord, set Input Device to the virtual cable.

Audio Input (Mics / Line-In)

Note: audio input is Windows-only right now.

Audio.Input.List();// list capture devicesvarmic=CreateMic(0);// or CreateInput(0)varch1=Audio.CreateChannel(1);ch1.Route(mic);ch1.Gain(0.7);

Fluent Instrument Setup

CreateGeneralMidi().Pan(0.2f).Channel(0).Name("GM_AcousticGrandPiano");CreateSynth().Volume(0.7f).Pan(-0.2f);CreateVst("Vital").Volume(0.9f).Pan(0.1f);CreateMic(0).Gain(0.8f).Mute(false);

Variable Modulation

varpan=Mod.Pan(piano,0f);pan.Random(-0.5f,0.5f,everyMs:400);varvol=Mod.Volume(synth,0.7f);vol.Lfo(0.2f,0.9f,rateHz:0.5f);// Any propertyvarcutoff=Mod.Var(synth,"Cutoff");cutoff.Random(0.2f,0.9f,everyMs:300);

General Instruments Example (Script)

varpiano=CreateGeneralMidi();piano.Program=GeneralMidiProgram.AcousticGrandPiano;piano.Volume=0.8f;piano.Pan=0f;piano.Reverb=0.2f;piano.Channel=0;midi.device(0).to(piano);midi.device(0).pitchbend().to(value =>piano.PitchBend(value*2f-1f));varpattern=CreatePattern(piano);pattern.LoopLength=4.0;pattern.Note(60,0.0,1.0,100);pattern.Note(67,1.0,1.0,100);pattern.Note(72,2.0,2.0,100);pattern.Play();

Features (Current)

  • Low-latency MIDI routing and controller mapping.
  • Scriptable pattern sequencer with loop length and per-note velocity.
  • Built-in polyphonic synth with oscillators, ADSR, filter, LFO, and effects.
  • General MIDI output wrapper for system MIDI devices.
  • VST3 hosting with parameter control and editor support.
  • Channel routing with per-channel effects and master processing.
  • Recording taps for master and per-channel audio.

Planned Features

  • Lighting and show control: DMX512, Art-Net, sACN (E1.31), MIDI Show Control.
  • MIDI and timing: MIDI 1.0, MIDI 2.0, MTC, SMPTE/LTC sync, OSC control, MIDI screen/LED feedback with live data.
  • Audio routing: Windows ASIO/WaveOut plus virtual outputs, Linux PortAudio (default device).
  • Game engine integration: Unity/Unreal hooks, custom engine integration, realtime music logic control.
  • Modular control: CV rack-style modularity via code for every variable and setting.
  • DSP and hardware: planned DSP control surface and library to drive custom sound cards for full flexibility.

Notes

  • The project uses NAudio for audio/MIDI and provides its own instrument wrappers.
  • VST3 scanning can be configured via MUSICENGINE_VST3_PATHS (path-separator separated).
  • Extra free instruments, kits, and tools live in the companion library:
  • MusicEngine.Library

MusicEngine.Library (Optional Content)

MusicEngine.Library is a separate, community-driven repository of free instruments, kits, and utilities. It is optional: the engine runs without it. When present, you can load instruments with:

varspeech=LibraryApi("MusicEngine.Instruments.SpeechInstrument");

Use cases:

  • Sample-based kits (drums, one-shots, multisamples).
  • Procedural instruments (speech, drones, generators).
  • Utility helpers to build instruments from local folders.

Missing library instruments are skipped and stay silent (no crash), similar to missing VSTs.

Install

  • Install .NET SDK 10.0 (or newer).
  • Windows: install Visual Studio 2022 with Desktop development with C++ (for the native VST3 host).
  • Linux: install cmake, build-essential, and the PortAudio dev package (e.g. portaudio19-dev).
  • Rider works fine, but MSBuild from Visual Studio Build Tools is still required for the Windows native layer.

Settings reference: Docs/Settings.md

Linux Notes

  • Output uses PortAudio (default device).
  • VST UI embedding is not supported yet.
  • Audio input/recording are not supported yet.
  • Sample loading currently supports WAV (PCM/float) only.

Script Location

The engine scans the default project folder:

Test Project/

Any .cs or .csx file can be a main script if it calls File.Main(); or File(Main, "Name");. To use a different project folder, set MUSICENGINE_PROJECT_DIR (or pass --project-dir <path>). The engine looks for Test Project/ first and then the legacy Scripts/ folder inside that project directory.

Build

Managed build (C#):

  • Open the solution in Rider or Visual Studio and build the MusicEngine project.

Native VST3 host (C++):

  • First-time setup (pull the Steinberg SDK into external/vst3sdk):
    • git clone https://github.com/steinbergmedia/vst3sdk.git external/vst3sdk
    • git -C external/vst3sdk submodule update --init --recursive

Windows build (MSBuild):

  • Rider: open MusicEngine.CppLayer/native/MusicEngine.CppLayer.Native.vcxproj and build x64 Debug/Release.
  • Visual Studio: open the same .vcxproj, select x64 + Debug/Release, then Build.
  • Command line (PowerShell):
    • & "C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" "MusicEngine.CppLayer\native\MusicEngine.CppLayer.Native.vcxproj" /p:Configuration=Release /p:Platform=x64

Linux build (CMake):

  • cmake -S MusicEngine.CppLayer/native -B MusicEngine.CppLayer/native/build -DCMAKE_BUILD_TYPE=Release
  • cmake --build MusicEngine.CppLayer/native/build --config Release

The native build copies MusicEngine.CppLayer.Native.dll or libMusicEngine.CppLayer.Native.so into MusicEngine\ automatically (and C# build copies it to the output).

Troubleshooting native build:

  • Error: Cannot open include file: public.sdk/source/vst/hosting/module.h
    • The SDK submodules are missing or empty. Run:
      • git -C external/vst3sdk submodule update --init --recursive
      • If the submodules are present but empty, reset them:
        • git -C external/vst3sdk/public.sdk reset --hard
        • git -C external/vst3sdk/base reset --hard
        • git -C external/vst3sdk/pluginterfaces reset --hard

Mentions

Links

Copyright 2026 watermann429 and contributers.

About

Music Engine is a modular, open-source live-coding music engine written in C#. It combines code, MIDI, patterns, and real-time audio to enable flexible music production, live performance, and interactive audio programming.

Topics

Resources

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

BannerMusicEngine

LicenseC#.NETJoin DiscordStatus

MusicEngine

Scriptable C# music engine for realtime playback, instruments, and VST3 hosting. It can also record mics and music, render audio, and cover a full DAW-like workflow if you know what you're doing.

What makes MusicEngine different?

MusicEngine is a C# scripting language for music. It supports VSTs, sequencers, and patterns without forcing you into any workflow. You keep full control over time and timing. Everything is a tool, nothing is forced, and there are no hidden mathematical clamps. Almost anything can be turned into a variable and be modulated.

Pattern Example (Script)

varsynth=CreateSynth();varpattern=CreatePattern(synth);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Note(60,2.0,1.0,110,slideTo:67,slideTimeMs:500);pattern.NoteMs(72,1500,250,110);// Note(...) auto-uses ms when duration > 8.0 or beat > 32.0 (still supports beats)pattern.Note(72,1500,250,110);varseq1=pattern.Note(60,0.0,0.25,100).Siquenz("0010101001101110");seq1.Loop=true;pattern.Play();

MIDI Routing Example (Script)

varsynth=CreateSynth();midi.device(0).to(synth);midi.device(0).cc(1).to(value =>synth.SetParameter("cutoff",value));midi.device(0).pitchbend().to(value =>synth.PitchBend(value*2f-1f));

More MIDI details: Docs/Midi.md

Device/channel/route toggles:

varsynth=CreateSynth();varmidi1=midi.Device(0);// device handlevarroute1=midi.Device(0).to(synth);// device -> synth routemidi1.Active(false);// disable device inputmidi1.Active(true);// enable device inputmidi.Device(0).Channel(1).Active(false);// disable channel 2 on device 0route1.Active(false);// disable only this route

Modular Effects Example (Script)

varfx=CreateEffect().ReverbPreset("Hall").BitCrushPreset("Lofi").NoisePreset("Light").FilterPreset("Low");varch1=Audio.CreateChannel(1);ch1.Effect(fx);

Preset factory:

varch2=Audio.CreateChannel(2);ch2.Effect(Effect.Reverb);ch2.Effect(Effect.Drive);

Preset names:

varfx2=CreateEffect().ReverbPreset("Hall").DelayPreset("Echo").DrivePreset("Warm");Audio.CreateChannel(3).Effect(fx2);

Preset with overrides:

varfx3=CreateEffect().ReverbPreset("Hall", r =>r.Mix=0.4f).DelayPreset("Echo", d =>d.TimeMs=500f).FilterPreset("Low", f =>f.CutoffHz=800f);Audio.CreateChannel(4).Effect(fx3);

Standalone preset (for modulation):

varreverbFx3=ReverbPreset("Hall", r =>r.Mix=0.4f);varmix=Mod.Var(reverbFx3,"Mix");mix.Lfo(0.2f,0.6f,rateHz:0.5f);

Modular Oscillators (Hybrid Synth)

varsynth=CreateSynth();varosc3=synth.Oscillator();osc3.Waveform=WaveType.Sine;osc3.Level=0.2f;osc3.Pan=-0.2f;varosc4=synth.Oscillator();osc4.Waveform=WaveType.Sine;osc4.Level=0.2f;osc4.Pan=0.2f;osc4.ModToFilter=0.2f;

Wavetable Oscillators

varsynth=CreateSynth();// Built-in tablessynth.Osc1Wavetable=Wavetable.Saw(2048);synth.Osc2Wavetable=Wavetable.WhiteNoise(2048);// Custom file (first channel)varwt=Wavetable.FromFile("my_wave.wav",maxSamples:2048);varosc=synth.Oscillator();osc.Wavetable=wt;osc.Enabled=true;

VST3 Example (Script)

varvital=CreateVst("Vital");vital.SetParameterNormalized("Cutoff",0.5f);midi.device(0).to(vital);midi.device(0).pitchbend().to(value =>vital.PitchBend(value*2f-1f));varpattern=CreatePattern(vital);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Play();

Note: VST UI embedding is Windows-only for now. Linux runs VST audio + parameters without the editor window.

VST State Save/Load

varvital=CreateVst("Vital");vital.State();// on /S or exit, writes base64 into the ()

Notes:

  • The inline State() call is updated on refresh or exit, so you can copy/share the script.
  • States are stored per script under .musicengine/states/<script>/<name>.state.
  • Missing VSTs warn and stay silent instead of crashing.

Manual overrides still work:

vital.LoadState("States.vital.state");vital.SaveState("States.vital.state");

Virtual Output (Discord / Virtual Mic)

To send audio into Discord as a microphone, you need a virtual audio device (e.g. VB-CABLE or VoiceMeeter). MusicEngine can route the master or a channel to any Windows output device.

Audio.Output.List();// list render devicesAudio.Master.VirtualOut("CABLE Input");// route master to virtual micvarch1=Audio.CreateChannel(1);ch1.VirtualOut("CABLE Input");// route channel to virtual mic

Notes:

  • Without a virtual audio device installed, Windows has no "virtual mic" target.
  • In Discord, set Input Device to the virtual cable.

Audio Input (Mics / Line-In)

Note: audio input is Windows-only right now.

Audio.Input.List();// list capture devicesvarmic=CreateMic(0);// or CreateInput(0)varch1=Audio.CreateChannel(1);ch1.Route(mic);ch1.Gain(0.7);

Fluent Instrument Setup

CreateGeneralMidi().Pan(0.2f).Channel(0).Name("GM_AcousticGrandPiano");CreateSynth().Volume(0.7f).Pan(-0.2f);CreateVst("Vital").Volume(0.9f).Pan(0.1f);CreateMic(0).Gain(0.8f).Mute(false);

Variable Modulation

varpan=Mod.Pan(piano,0f);pan.Random(-0.5f,0.5f,everyMs:400);varvol=Mod.Volume(synth,0.7f);vol.Lfo(0.2f,0.9f,rateHz:0.5f);// Any propertyvarcutoff=Mod.Var(synth,"Cutoff");cutoff.Random(0.2f,0.9f,everyMs:300);

General Instruments Example (Script)

varpiano=CreateGeneralMidi();piano.Program=GeneralMidiProgram.AcousticGrandPiano;piano.Volume=0.8f;piano.Pan=0f;piano.Reverb=0.2f;piano.Channel=0;midi.device(0).to(piano);midi.device(0).pitchbend().to(value =>piano.PitchBend(value*2f-1f));varpattern=CreatePattern(piano);pattern.LoopLength=4.0;pattern.Note(60,0.0,1.0,100);pattern.Note(67,1.0,1.0,100);pattern.Note(72,2.0,2.0,100);pattern.Play();

Features (Current)

  • Low-latency MIDI routing and controller mapping.
  • Scriptable pattern sequencer with loop length and per-note velocity.
  • Built-in polyphonic synth with oscillators, ADSR, filter, LFO, and effects.
  • General MIDI output wrapper for system MIDI devices.
  • VST3 hosting with parameter control and editor support.
  • Channel routing with per-channel effects and master processing.
  • Recording taps for master and per-channel audio.

Planned Features

  • Lighting and show control: DMX512, Art-Net, sACN (E1.31), MIDI Show Control.
  • MIDI and timing: MIDI 1.0, MIDI 2.0, MTC, SMPTE/LTC sync, OSC control, MIDI screen/LED feedback with live data.
  • Audio routing: Windows ASIO/WaveOut plus virtual outputs, Linux PortAudio (default device).
  • Game engine integration: Unity/Unreal hooks, custom engine integration, realtime music logic control.
  • Modular control: CV rack-style modularity via code for every variable and setting.
  • DSP and hardware: planned DSP control surface and library to drive custom sound cards for full flexibility.

Notes

  • The project uses NAudio for audio/MIDI and provides its own instrument wrappers.
  • VST3 scanning can be configured via MUSICENGINE_VST3_PATHS (path-separator separated).
  • Extra free instruments, kits, and tools live in the companion library:
  • MusicEngine.Library

MusicEngine.Library (Optional Content)

MusicEngine.Library is a separate, community-driven repository of free instruments, kits, and utilities. It is optional: the engine runs without it. When present, you can load instruments with:

varspeech=LibraryApi("MusicEngine.Instruments.SpeechInstrument");

Use cases:

  • Sample-based kits (drums, one-shots, multisamples).
  • Procedural instruments (speech, drones, generators).
  • Utility helpers to build instruments from local folders.

Missing library instruments are skipped and stay silent (no crash), similar to missing VSTs.

Install

  • Install .NET SDK 10.0 (or newer).
  • Windows: install Visual Studio 2022 with Desktop development with C++ (for the native VST3 host).
  • Linux: install cmake, build-essential, and the PortAudio dev package (e.g. portaudio19-dev).
  • Rider works fine, but MSBuild from Visual Studio Build Tools is still required for the Windows native layer.

Settings reference: Docs/Settings.md

Linux Notes

  • Output uses PortAudio (default device).
  • VST UI embedding is not supported yet.
  • Audio input/recording are not supported yet.
  • Sample loading currently supports WAV (PCM/float) only.

Script Location

The engine scans the default project folder:

Test Project/

Any .cs or .csx file can be a main script if it calls File.Main(); or File(Main, "Name");. To use a different project folder, set MUSICENGINE_PROJECT_DIR (or pass --project-dir <path>). The engine looks for Test Project/ first and then the legacy Scripts/ folder inside that project directory.

Build

Managed build (C#):

  • Open the solution in Rider or Visual Studio and build the MusicEngine project.

Native VST3 host (C++):

  • First-time setup (pull the Steinberg SDK into external/vst3sdk):
    • git clone https://github.com/steinbergmedia/vst3sdk.git external/vst3sdk
    • git -C external/vst3sdk submodule update --init --recursive

Windows build (MSBuild):

  • Rider: open MusicEngine.CppLayer/native/MusicEngine.CppLayer.Native.vcxproj and build x64 Debug/Release.
  • Visual Studio: open the same .vcxproj, select x64 + Debug/Release, then Build.
  • Command line (PowerShell):
    • & "C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" "MusicEngine.CppLayer\native\MusicEngine.CppLayer.Native.vcxproj" /p:Configuration=Release /p:Platform=x64

Linux build (CMake):

  • cmake -S MusicEngine.CppLayer/native -B MusicEngine.CppLayer/native/build -DCMAKE_BUILD_TYPE=Release
  • cmake --build MusicEngine.CppLayer/native/build --config Release

The native build copies MusicEngine.CppLayer.Native.dll or libMusicEngine.CppLayer.Native.so into MusicEngine\ automatically (and C# build copies it to the output).

Troubleshooting native build:

  • Error: Cannot open include file: public.sdk/source/vst/hosting/module.h
    • The SDK submodules are missing or empty. Run:
      • git -C external/vst3sdk submodule update --init --recursive
      • If the submodules are present but empty, reset them:
        • git -C external/vst3sdk/public.sdk reset --hard
        • git -C external/vst3sdk/base reset --hard
        • git -C external/vst3sdk/pluginterfaces reset --hard

Mentions

Links

Copyright 2026 watermann429 and contributers.

About

Music Engine is a modular, open-source live-coding music engine written in C#. It combines code, MIDI, patterns, and real-time audio to enable flexible music production, live performance, and interactive audio programming.

Topics

Resources

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

BannerMusicEngine

LicenseC#.NETJoin DiscordStatus

MusicEngine

Scriptable C# music engine for realtime playback, instruments, and VST3 hosting. It can also record mics and music, render audio, and cover a full DAW-like workflow if you know what you're doing.

What makes MusicEngine different?

MusicEngine is a C# scripting language for music. It supports VSTs, sequencers, and patterns without forcing you into any workflow. You keep full control over time and timing. Everything is a tool, nothing is forced, and there are no hidden mathematical clamps. Almost anything can be turned into a variable and be modulated.

Pattern Example (Script)

varsynth=CreateSynth();varpattern=CreatePattern(synth);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Note(60,2.0,1.0,110,slideTo:67,slideTimeMs:500);pattern.NoteMs(72,1500,250,110);// Note(...) auto-uses ms when duration > 8.0 or beat > 32.0 (still supports beats)pattern.Note(72,1500,250,110);varseq1=pattern.Note(60,0.0,0.25,100).Siquenz("0010101001101110");seq1.Loop=true;pattern.Play();

MIDI Routing Example (Script)

varsynth=CreateSynth();midi.device(0).to(synth);midi.device(0).cc(1).to(value =>synth.SetParameter("cutoff",value));midi.device(0).pitchbend().to(value =>synth.PitchBend(value*2f-1f));

More MIDI details: Docs/Midi.md

Device/channel/route toggles:

varsynth=CreateSynth();varmidi1=midi.Device(0);// device handlevarroute1=midi.Device(0).to(synth);// device -> synth routemidi1.Active(false);// disable device inputmidi1.Active(true);// enable device inputmidi.Device(0).Channel(1).Active(false);// disable channel 2 on device 0route1.Active(false);// disable only this route

Modular Effects Example (Script)

varfx=CreateEffect().ReverbPreset("Hall").BitCrushPreset("Lofi").NoisePreset("Light").FilterPreset("Low");varch1=Audio.CreateChannel(1);ch1.Effect(fx);

Preset factory:

varch2=Audio.CreateChannel(2);ch2.Effect(Effect.Reverb);ch2.Effect(Effect.Drive);

Preset names:

varfx2=CreateEffect().ReverbPreset("Hall").DelayPreset("Echo").DrivePreset("Warm");Audio.CreateChannel(3).Effect(fx2);

Preset with overrides:

varfx3=CreateEffect().ReverbPreset("Hall", r =>r.Mix=0.4f).DelayPreset("Echo", d =>d.TimeMs=500f).FilterPreset("Low", f =>f.CutoffHz=800f);Audio.CreateChannel(4).Effect(fx3);

Standalone preset (for modulation):

varreverbFx3=ReverbPreset("Hall", r =>r.Mix=0.4f);varmix=Mod.Var(reverbFx3,"Mix");mix.Lfo(0.2f,0.6f,rateHz:0.5f);

Modular Oscillators (Hybrid Synth)

varsynth=CreateSynth();varosc3=synth.Oscillator();osc3.Waveform=WaveType.Sine;osc3.Level=0.2f;osc3.Pan=-0.2f;varosc4=synth.Oscillator();osc4.Waveform=WaveType.Sine;osc4.Level=0.2f;osc4.Pan=0.2f;osc4.ModToFilter=0.2f;

Wavetable Oscillators

varsynth=CreateSynth();// Built-in tablessynth.Osc1Wavetable=Wavetable.Saw(2048);synth.Osc2Wavetable=Wavetable.WhiteNoise(2048);// Custom file (first channel)varwt=Wavetable.FromFile("my_wave.wav",maxSamples:2048);varosc=synth.Oscillator();osc.Wavetable=wt;osc.Enabled=true;

VST3 Example (Script)

varvital=CreateVst("Vital");vital.SetParameterNormalized("Cutoff",0.5f);midi.device(0).to(vital);midi.device(0).pitchbend().to(value =>vital.PitchBend(value*2f-1f));varpattern=CreatePattern(vital);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Play();

Note: VST UI embedding is Windows-only for now. Linux runs VST audio + parameters without the editor window.

VST State Save/Load

varvital=CreateVst("Vital");vital.State();// on /S or exit, writes base64 into the ()

Notes:

  • The inline State() call is updated on refresh or exit, so you can copy/share the script.
  • States are stored per script under .musicengine/states/<script>/<name>.state.
  • Missing VSTs warn and stay silent instead of crashing.

Manual overrides still work:

vital.LoadState("States.vital.state");vital.SaveState("States.vital.state");

Virtual Output (Discord / Virtual Mic)

To send audio into Discord as a microphone, you need a virtual audio device (e.g. VB-CABLE or VoiceMeeter). MusicEngine can route the master or a channel to any Windows output device.

Audio.Output.List();// list render devicesAudio.Master.VirtualOut("CABLE Input");// route master to virtual micvarch1=Audio.CreateChannel(1);ch1.VirtualOut("CABLE Input");// route channel to virtual mic

Notes:

  • Without a virtual audio device installed, Windows has no "virtual mic" target.
  • In Discord, set Input Device to the virtual cable.

Audio Input (Mics / Line-In)

Note: audio input is Windows-only right now.

Audio.Input.List();// list capture devicesvarmic=CreateMic(0);// or CreateInput(0)varch1=Audio.CreateChannel(1);ch1.Route(mic);ch1.Gain(0.7);

Fluent Instrument Setup

CreateGeneralMidi().Pan(0.2f).Channel(0).Name("GM_AcousticGrandPiano");CreateSynth().Volume(0.7f).Pan(-0.2f);CreateVst("Vital").Volume(0.9f).Pan(0.1f);CreateMic(0).Gain(0.8f).Mute(false);

Variable Modulation

varpan=Mod.Pan(piano,0f);pan.Random(-0.5f,0.5f,everyMs:400);varvol=Mod.Volume(synth,0.7f);vol.Lfo(0.2f,0.9f,rateHz:0.5f);// Any propertyvarcutoff=Mod.Var(synth,"Cutoff");cutoff.Random(0.2f,0.9f,everyMs:300);

General Instruments Example (Script)

varpiano=CreateGeneralMidi();piano.Program=GeneralMidiProgram.AcousticGrandPiano;piano.Volume=0.8f;piano.Pan=0f;piano.Reverb=0.2f;piano.Channel=0;midi.device(0).to(piano);midi.device(0).pitchbend().to(value =>piano.PitchBend(value*2f-1f));varpattern=CreatePattern(piano);pattern.LoopLength=4.0;pattern.Note(60,0.0,1.0,100);pattern.Note(67,1.0,1.0,100);pattern.Note(72,2.0,2.0,100);pattern.Play();

Features (Current)

  • Low-latency MIDI routing and controller mapping.
  • Scriptable pattern sequencer with loop length and per-note velocity.
  • Built-in polyphonic synth with oscillators, ADSR, filter, LFO, and effects.
  • General MIDI output wrapper for system MIDI devices.
  • VST3 hosting with parameter control and editor support.
  • Channel routing with per-channel effects and master processing.
  • Recording taps for master and per-channel audio.

Planned Features

  • Lighting and show control: DMX512, Art-Net, sACN (E1.31), MIDI Show Control.
  • MIDI and timing: MIDI 1.0, MIDI 2.0, MTC, SMPTE/LTC sync, OSC control, MIDI screen/LED feedback with live data.
  • Audio routing: Windows ASIO/WaveOut plus virtual outputs, Linux PortAudio (default device).
  • Game engine integration: Unity/Unreal hooks, custom engine integration, realtime music logic control.
  • Modular control: CV rack-style modularity via code for every variable and setting.
  • DSP and hardware: planned DSP control surface and library to drive custom sound cards for full flexibility.

Notes

  • The project uses NAudio for audio/MIDI and provides its own instrument wrappers.
  • VST3 scanning can be configured via MUSICENGINE_VST3_PATHS (path-separator separated).
  • Extra free instruments, kits, and tools live in the companion library:
  • MusicEngine.Library

MusicEngine.Library (Optional Content)

MusicEngine.Library is a separate, community-driven repository of free instruments, kits, and utilities. It is optional: the engine runs without it. When present, you can load instruments with:

varspeech=LibraryApi("MusicEngine.Instruments.SpeechInstrument");

Use cases:

  • Sample-based kits (drums, one-shots, multisamples).
  • Procedural instruments (speech, drones, generators).
  • Utility helpers to build instruments from local folders.

Missing library instruments are skipped and stay silent (no crash), similar to missing VSTs.

Install

  • Install .NET SDK 10.0 (or newer).
  • Windows: install Visual Studio 2022 with Desktop development with C++ (for the native VST3 host).
  • Linux: install cmake, build-essential, and the PortAudio dev package (e.g. portaudio19-dev).
  • Rider works fine, but MSBuild from Visual Studio Build Tools is still required for the Windows native layer.

Settings reference: Docs/Settings.md

Linux Notes

  • Output uses PortAudio (default device).
  • VST UI embedding is not supported yet.
  • Audio input/recording are not supported yet.
  • Sample loading currently supports WAV (PCM/float) only.

Script Location

The engine scans the default project folder:

Test Project/

Any .cs or .csx file can be a main script if it calls File.Main(); or File(Main, "Name");. To use a different project folder, set MUSICENGINE_PROJECT_DIR (or pass --project-dir <path>). The engine looks for Test Project/ first and then the legacy Scripts/ folder inside that project directory.

Build

Managed build (C#):

  • Open the solution in Rider or Visual Studio and build the MusicEngine project.

Native VST3 host (C++):

  • First-time setup (pull the Steinberg SDK into external/vst3sdk):
    • git clone https://github.com/steinbergmedia/vst3sdk.git external/vst3sdk
    • git -C external/vst3sdk submodule update --init --recursive

Windows build (MSBuild):

  • Rider: open MusicEngine.CppLayer/native/MusicEngine.CppLayer.Native.vcxproj and build x64 Debug/Release.
  • Visual Studio: open the same .vcxproj, select x64 + Debug/Release, then Build.
  • Command line (PowerShell):
    • & "C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" "MusicEngine.CppLayer\native\MusicEngine.CppLayer.Native.vcxproj" /p:Configuration=Release /p:Platform=x64

Linux build (CMake):

  • cmake -S MusicEngine.CppLayer/native -B MusicEngine.CppLayer/native/build -DCMAKE_BUILD_TYPE=Release
  • cmake --build MusicEngine.CppLayer/native/build --config Release

The native build copies MusicEngine.CppLayer.Native.dll or libMusicEngine.CppLayer.Native.so into MusicEngine\ automatically (and C# build copies it to the output).

Troubleshooting native build:

  • Error: Cannot open include file: public.sdk/source/vst/hosting/module.h
    • The SDK submodules are missing or empty. Run:
      • git -C external/vst3sdk submodule update --init --recursive
      • If the submodules are present but empty, reset them:
        • git -C external/vst3sdk/public.sdk reset --hard
        • git -C external/vst3sdk/base reset --hard
        • git -C external/vst3sdk/pluginterfaces reset --hard

Mentions

Links

Copyright 2026 watermann429 and contributers.

About

Music Engine is a modular, open-source live-coding music engine written in C#. It combines code, MIDI, patterns, and real-time audio to enable flexible music production, live performance, and interactive audio programming.

Topics

Resources

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

BannerMusicEngine

LicenseC#.NETJoin DiscordStatus

MusicEngine

Scriptable C# music engine for realtime playback, instruments, and VST3 hosting. It can also record mics and music, render audio, and cover a full DAW-like workflow if you know what you're doing.

What makes MusicEngine different?

MusicEngine is a C# scripting language for music. It supports VSTs, sequencers, and patterns without forcing you into any workflow. You keep full control over time and timing. Everything is a tool, nothing is forced, and there are no hidden mathematical clamps. Almost anything can be turned into a variable and be modulated.

Pattern Example (Script)

varsynth=CreateSynth();varpattern=CreatePattern(synth);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Note(60,2.0,1.0,110,slideTo:67,slideTimeMs:500);pattern.NoteMs(72,1500,250,110);// Note(...) auto-uses ms when duration > 8.0 or beat > 32.0 (still supports beats)pattern.Note(72,1500,250,110);varseq1=pattern.Note(60,0.0,0.25,100).Siquenz("0010101001101110");seq1.Loop=true;pattern.Play();

MIDI Routing Example (Script)

varsynth=CreateSynth();midi.device(0).to(synth);midi.device(0).cc(1).to(value =>synth.SetParameter("cutoff",value));midi.device(0).pitchbend().to(value =>synth.PitchBend(value*2f-1f));

More MIDI details: Docs/Midi.md

Device/channel/route toggles:

varsynth=CreateSynth();varmidi1=midi.Device(0);// device handlevarroute1=midi.Device(0).to(synth);// device -> synth routemidi1.Active(false);// disable device inputmidi1.Active(true);// enable device inputmidi.Device(0).Channel(1).Active(false);// disable channel 2 on device 0route1.Active(false);// disable only this route

Modular Effects Example (Script)

varfx=CreateEffect().ReverbPreset("Hall").BitCrushPreset("Lofi").NoisePreset("Light").FilterPreset("Low");varch1=Audio.CreateChannel(1);ch1.Effect(fx);

Preset factory:

varch2=Audio.CreateChannel(2);ch2.Effect(Effect.Reverb);ch2.Effect(Effect.Drive);

Preset names:

varfx2=CreateEffect().ReverbPreset("Hall").DelayPreset("Echo").DrivePreset("Warm");Audio.CreateChannel(3).Effect(fx2);

Preset with overrides:

varfx3=CreateEffect().ReverbPreset("Hall", r =>r.Mix=0.4f).DelayPreset("Echo", d =>d.TimeMs=500f).FilterPreset("Low", f =>f.CutoffHz=800f);Audio.CreateChannel(4).Effect(fx3);

Standalone preset (for modulation):

varreverbFx3=ReverbPreset("Hall", r =>r.Mix=0.4f);varmix=Mod.Var(reverbFx3,"Mix");mix.Lfo(0.2f,0.6f,rateHz:0.5f);

Modular Oscillators (Hybrid Synth)

varsynth=CreateSynth();varosc3=synth.Oscillator();osc3.Waveform=WaveType.Sine;osc3.Level=0.2f;osc3.Pan=-0.2f;varosc4=synth.Oscillator();osc4.Waveform=WaveType.Sine;osc4.Level=0.2f;osc4.Pan=0.2f;osc4.ModToFilter=0.2f;

Wavetable Oscillators

varsynth=CreateSynth();// Built-in tablessynth.Osc1Wavetable=Wavetable.Saw(2048);synth.Osc2Wavetable=Wavetable.WhiteNoise(2048);// Custom file (first channel)varwt=Wavetable.FromFile("my_wave.wav",maxSamples:2048);varosc=synth.Oscillator();osc.Wavetable=wt;osc.Enabled=true;

VST3 Example (Script)

varvital=CreateVst("Vital");vital.SetParameterNormalized("Cutoff",0.5f);midi.device(0).to(vital);midi.device(0).pitchbend().to(value =>vital.PitchBend(value*2f-1f));varpattern=CreatePattern(vital);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Play();

Note: VST UI embedding is Windows-only for now. Linux runs VST audio + parameters without the editor window.

VST State Save/Load

varvital=CreateVst("Vital");vital.State();// on /S or exit, writes base64 into the ()

Notes:

  • The inline State() call is updated on refresh or exit, so you can copy/share the script.
  • States are stored per script under .musicengine/states/<script>/<name>.state.
  • Missing VSTs warn and stay silent instead of crashing.

Manual overrides still work:

vital.LoadState("States.vital.state");vital.SaveState("States.vital.state");

Virtual Output (Discord / Virtual Mic)

To send audio into Discord as a microphone, you need a virtual audio device (e.g. VB-CABLE or VoiceMeeter). MusicEngine can route the master or a channel to any Windows output device.

Audio.Output.List();// list render devicesAudio.Master.VirtualOut("CABLE Input");// route master to virtual micvarch1=Audio.CreateChannel(1);ch1.VirtualOut("CABLE Input");// route channel to virtual mic

Notes:

  • Without a virtual audio device installed, Windows has no "virtual mic" target.
  • In Discord, set Input Device to the virtual cable.

Audio Input (Mics / Line-In)

Note: audio input is Windows-only right now.

Audio.Input.List();// list capture devicesvarmic=CreateMic(0);// or CreateInput(0)varch1=Audio.CreateChannel(1);ch1.Route(mic);ch1.Gain(0.7);

Fluent Instrument Setup

CreateGeneralMidi().Pan(0.2f).Channel(0).Name("GM_AcousticGrandPiano");CreateSynth().Volume(0.7f).Pan(-0.2f);CreateVst("Vital").Volume(0.9f).Pan(0.1f);CreateMic(0).Gain(0.8f).Mute(false);

Variable Modulation

varpan=Mod.Pan(piano,0f);pan.Random(-0.5f,0.5f,everyMs:400);varvol=Mod.Volume(synth,0.7f);vol.Lfo(0.2f,0.9f,rateHz:0.5f);// Any propertyvarcutoff=Mod.Var(synth,"Cutoff");cutoff.Random(0.2f,0.9f,everyMs:300);

General Instruments Example (Script)

varpiano=CreateGeneralMidi();piano.Program=GeneralMidiProgram.AcousticGrandPiano;piano.Volume=0.8f;piano.Pan=0f;piano.Reverb=0.2f;piano.Channel=0;midi.device(0).to(piano);midi.device(0).pitchbend().to(value =>piano.PitchBend(value*2f-1f));varpattern=CreatePattern(piano);pattern.LoopLength=4.0;pattern.Note(60,0.0,1.0,100);pattern.Note(67,1.0,1.0,100);pattern.Note(72,2.0,2.0,100);pattern.Play();

Features (Current)

  • Low-latency MIDI routing and controller mapping.
  • Scriptable pattern sequencer with loop length and per-note velocity.
  • Built-in polyphonic synth with oscillators, ADSR, filter, LFO, and effects.
  • General MIDI output wrapper for system MIDI devices.
  • VST3 hosting with parameter control and editor support.
  • Channel routing with per-channel effects and master processing.
  • Recording taps for master and per-channel audio.

Planned Features

  • Lighting and show control: DMX512, Art-Net, sACN (E1.31), MIDI Show Control.
  • MIDI and timing: MIDI 1.0, MIDI 2.0, MTC, SMPTE/LTC sync, OSC control, MIDI screen/LED feedback with live data.
  • Audio routing: Windows ASIO/WaveOut plus virtual outputs, Linux PortAudio (default device).
  • Game engine integration: Unity/Unreal hooks, custom engine integration, realtime music logic control.
  • Modular control: CV rack-style modularity via code for every variable and setting.
  • DSP and hardware: planned DSP control surface and library to drive custom sound cards for full flexibility.

Notes

  • The project uses NAudio for audio/MIDI and provides its own instrument wrappers.
  • VST3 scanning can be configured via MUSICENGINE_VST3_PATHS (path-separator separated).
  • Extra free instruments, kits, and tools live in the companion library:
  • MusicEngine.Library

MusicEngine.Library (Optional Content)

MusicEngine.Library is a separate, community-driven repository of free instruments, kits, and utilities. It is optional: the engine runs without it. When present, you can load instruments with:

varspeech=LibraryApi("MusicEngine.Instruments.SpeechInstrument");

Use cases:

  • Sample-based kits (drums, one-shots, multisamples).
  • Procedural instruments (speech, drones, generators).
  • Utility helpers to build instruments from local folders.

Missing library instruments are skipped and stay silent (no crash), similar to missing VSTs.

Install

  • Install .NET SDK 10.0 (or newer).
  • Windows: install Visual Studio 2022 with Desktop development with C++ (for the native VST3 host).
  • Linux: install cmake, build-essential, and the PortAudio dev package (e.g. portaudio19-dev).
  • Rider works fine, but MSBuild from Visual Studio Build Tools is still required for the Windows native layer.

Settings reference: Docs/Settings.md

Linux Notes

  • Output uses PortAudio (default device).
  • VST UI embedding is not supported yet.
  • Audio input/recording are not supported yet.
  • Sample loading currently supports WAV (PCM/float) only.

Script Location

The engine scans the default project folder:

Test Project/

Any .cs or .csx file can be a main script if it calls File.Main(); or File(Main, "Name");. To use a different project folder, set MUSICENGINE_PROJECT_DIR (or pass --project-dir <path>). The engine looks for Test Project/ first and then the legacy Scripts/ folder inside that project directory.

Build

Managed build (C#):

  • Open the solution in Rider or Visual Studio and build the MusicEngine project.

Native VST3 host (C++):

  • First-time setup (pull the Steinberg SDK into external/vst3sdk):
    • git clone https://github.com/steinbergmedia/vst3sdk.git external/vst3sdk
    • git -C external/vst3sdk submodule update --init --recursive

Windows build (MSBuild):

  • Rider: open MusicEngine.CppLayer/native/MusicEngine.CppLayer.Native.vcxproj and build x64 Debug/Release.
  • Visual Studio: open the same .vcxproj, select x64 + Debug/Release, then Build.
  • Command line (PowerShell):
    • & "C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" "MusicEngine.CppLayer\native\MusicEngine.CppLayer.Native.vcxproj" /p:Configuration=Release /p:Platform=x64

Linux build (CMake):

  • cmake -S MusicEngine.CppLayer/native -B MusicEngine.CppLayer/native/build -DCMAKE_BUILD_TYPE=Release
  • cmake --build MusicEngine.CppLayer/native/build --config Release

The native build copies MusicEngine.CppLayer.Native.dll or libMusicEngine.CppLayer.Native.so into MusicEngine\ automatically (and C# build copies it to the output).

Troubleshooting native build:

  • Error: Cannot open include file: public.sdk/source/vst/hosting/module.h
    • The SDK submodules are missing or empty. Run:
      • git -C external/vst3sdk submodule update --init --recursive
      • If the submodules are present but empty, reset them:
        • git -C external/vst3sdk/public.sdk reset --hard
        • git -C external/vst3sdk/base reset --hard
        • git -C external/vst3sdk/pluginterfaces reset --hard

Mentions

Links

Copyright 2026 watermann429 and contributers.

About

Music Engine is a modular, open-source live-coding music engine written in C#. It combines code, MIDI, patterns, and real-time audio to enable flexible music production, live performance, and interactive audio programming.

Topics

Resources

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

BannerMusicEngine

LicenseC#.NETJoin DiscordStatus

MusicEngine

Scriptable C# music engine for realtime playback, instruments, and VST3 hosting. It can also record mics and music, render audio, and cover a full DAW-like workflow if you know what you're doing.

What makes MusicEngine different?

MusicEngine is a C# scripting language for music. It supports VSTs, sequencers, and patterns without forcing you into any workflow. You keep full control over time and timing. Everything is a tool, nothing is forced, and there are no hidden mathematical clamps. Almost anything can be turned into a variable and be modulated.

Pattern Example (Script)

varsynth=CreateSynth();varpattern=CreatePattern(synth);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Note(60,2.0,1.0,110,slideTo:67,slideTimeMs:500);pattern.NoteMs(72,1500,250,110);// Note(...) auto-uses ms when duration > 8.0 or beat > 32.0 (still supports beats)pattern.Note(72,1500,250,110);varseq1=pattern.Note(60,0.0,0.25,100).Siquenz("0010101001101110");seq1.Loop=true;pattern.Play();

MIDI Routing Example (Script)

varsynth=CreateSynth();midi.device(0).to(synth);midi.device(0).cc(1).to(value =>synth.SetParameter("cutoff",value));midi.device(0).pitchbend().to(value =>synth.PitchBend(value*2f-1f));

More MIDI details: Docs/Midi.md

Device/channel/route toggles:

varsynth=CreateSynth();varmidi1=midi.Device(0);// device handlevarroute1=midi.Device(0).to(synth);// device -> synth routemidi1.Active(false);// disable device inputmidi1.Active(true);// enable device inputmidi.Device(0).Channel(1).Active(false);// disable channel 2 on device 0route1.Active(false);// disable only this route

Modular Effects Example (Script)

varfx=CreateEffect().ReverbPreset("Hall").BitCrushPreset("Lofi").NoisePreset("Light").FilterPreset("Low");varch1=Audio.CreateChannel(1);ch1.Effect(fx);

Preset factory:

varch2=Audio.CreateChannel(2);ch2.Effect(Effect.Reverb);ch2.Effect(Effect.Drive);

Preset names:

varfx2=CreateEffect().ReverbPreset("Hall").DelayPreset("Echo").DrivePreset("Warm");Audio.CreateChannel(3).Effect(fx2);

Preset with overrides:

varfx3=CreateEffect().ReverbPreset("Hall", r =>r.Mix=0.4f).DelayPreset("Echo", d =>d.TimeMs=500f).FilterPreset("Low", f =>f.CutoffHz=800f);Audio.CreateChannel(4).Effect(fx3);

Standalone preset (for modulation):

varreverbFx3=ReverbPreset("Hall", r =>r.Mix=0.4f);varmix=Mod.Var(reverbFx3,"Mix");mix.Lfo(0.2f,0.6f,rateHz:0.5f);

Modular Oscillators (Hybrid Synth)

varsynth=CreateSynth();varosc3=synth.Oscillator();osc3.Waveform=WaveType.Sine;osc3.Level=0.2f;osc3.Pan=-0.2f;varosc4=synth.Oscillator();osc4.Waveform=WaveType.Sine;osc4.Level=0.2f;osc4.Pan=0.2f;osc4.ModToFilter=0.2f;

Wavetable Oscillators

varsynth=CreateSynth();// Built-in tablessynth.Osc1Wavetable=Wavetable.Saw(2048);synth.Osc2Wavetable=Wavetable.WhiteNoise(2048);// Custom file (first channel)varwt=Wavetable.FromFile("my_wave.wav",maxSamples:2048);varosc=synth.Oscillator();osc.Wavetable=wt;osc.Enabled=true;

VST3 Example (Script)

varvital=CreateVst("Vital");vital.SetParameterNormalized("Cutoff",0.5f);midi.device(0).to(vital);midi.device(0).pitchbend().to(value =>vital.PitchBend(value*2f-1f));varpattern=CreatePattern(vital);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Play();

Note: VST UI embedding is Windows-only for now. Linux runs VST audio + parameters without the editor window.

VST State Save/Load

varvital=CreateVst("Vital");vital.State();// on /S or exit, writes base64 into the ()

Notes:

  • The inline State() call is updated on refresh or exit, so you can copy/share the script.
  • States are stored per script under .musicengine/states/<script>/<name>.state.
  • Missing VSTs warn and stay silent instead of crashing.

Manual overrides still work:

vital.LoadState("States.vital.state");vital.SaveState("States.vital.state");

Virtual Output (Discord / Virtual Mic)

To send audio into Discord as a microphone, you need a virtual audio device (e.g. VB-CABLE or VoiceMeeter). MusicEngine can route the master or a channel to any Windows output device.

Audio.Output.List();// list render devicesAudio.Master.VirtualOut("CABLE Input");// route master to virtual micvarch1=Audio.CreateChannel(1);ch1.VirtualOut("CABLE Input");// route channel to virtual mic

Notes:

  • Without a virtual audio device installed, Windows has no "virtual mic" target.
  • In Discord, set Input Device to the virtual cable.

Audio Input (Mics / Line-In)

Note: audio input is Windows-only right now.

Audio.Input.List();// list capture devicesvarmic=CreateMic(0);// or CreateInput(0)varch1=Audio.CreateChannel(1);ch1.Route(mic);ch1.Gain(0.7);

Fluent Instrument Setup

CreateGeneralMidi().Pan(0.2f).Channel(0).Name("GM_AcousticGrandPiano");CreateSynth().Volume(0.7f).Pan(-0.2f);CreateVst("Vital").Volume(0.9f).Pan(0.1f);CreateMic(0).Gain(0.8f).Mute(false);

Variable Modulation

varpan=Mod.Pan(piano,0f);pan.Random(-0.5f,0.5f,everyMs:400);varvol=Mod.Volume(synth,0.7f);vol.Lfo(0.2f,0.9f,rateHz:0.5f);// Any propertyvarcutoff=Mod.Var(synth,"Cutoff");cutoff.Random(0.2f,0.9f,everyMs:300);

General Instruments Example (Script)

varpiano=CreateGeneralMidi();piano.Program=GeneralMidiProgram.AcousticGrandPiano;piano.Volume=0.8f;piano.Pan=0f;piano.Reverb=0.2f;piano.Channel=0;midi.device(0).to(piano);midi.device(0).pitchbend().to(value =>piano.PitchBend(value*2f-1f));varpattern=CreatePattern(piano);pattern.LoopLength=4.0;pattern.Note(60,0.0,1.0,100);pattern.Note(67,1.0,1.0,100);pattern.Note(72,2.0,2.0,100);pattern.Play();

Features (Current)

  • Low-latency MIDI routing and controller mapping.
  • Scriptable pattern sequencer with loop length and per-note velocity.
  • Built-in polyphonic synth with oscillators, ADSR, filter, LFO, and effects.
  • General MIDI output wrapper for system MIDI devices.
  • VST3 hosting with parameter control and editor support.
  • Channel routing with per-channel effects and master processing.
  • Recording taps for master and per-channel audio.

Planned Features

  • Lighting and show control: DMX512, Art-Net, sACN (E1.31), MIDI Show Control.
  • MIDI and timing: MIDI 1.0, MIDI 2.0, MTC, SMPTE/LTC sync, OSC control, MIDI screen/LED feedback with live data.
  • Audio routing: Windows ASIO/WaveOut plus virtual outputs, Linux PortAudio (default device).
  • Game engine integration: Unity/Unreal hooks, custom engine integration, realtime music logic control.
  • Modular control: CV rack-style modularity via code for every variable and setting.
  • DSP and hardware: planned DSP control surface and library to drive custom sound cards for full flexibility.

Notes

  • The project uses NAudio for audio/MIDI and provides its own instrument wrappers.
  • VST3 scanning can be configured via MUSICENGINE_VST3_PATHS (path-separator separated).
  • Extra free instruments, kits, and tools live in the companion library:
  • MusicEngine.Library

MusicEngine.Library (Optional Content)

MusicEngine.Library is a separate, community-driven repository of free instruments, kits, and utilities. It is optional: the engine runs without it. When present, you can load instruments with:

varspeech=LibraryApi("MusicEngine.Instruments.SpeechInstrument");

Use cases:

  • Sample-based kits (drums, one-shots, multisamples).
  • Procedural instruments (speech, drones, generators).
  • Utility helpers to build instruments from local folders.

Missing library instruments are skipped and stay silent (no crash), similar to missing VSTs.

Install

  • Install .NET SDK 10.0 (or newer).
  • Windows: install Visual Studio 2022 with Desktop development with C++ (for the native VST3 host).
  • Linux: install cmake, build-essential, and the PortAudio dev package (e.g. portaudio19-dev).
  • Rider works fine, but MSBuild from Visual Studio Build Tools is still required for the Windows native layer.

Settings reference: Docs/Settings.md

Linux Notes

  • Output uses PortAudio (default device).
  • VST UI embedding is not supported yet.
  • Audio input/recording are not supported yet.
  • Sample loading currently supports WAV (PCM/float) only.

Script Location

The engine scans the default project folder:

Test Project/

Any .cs or .csx file can be a main script if it calls File.Main(); or File(Main, "Name");. To use a different project folder, set MUSICENGINE_PROJECT_DIR (or pass --project-dir <path>). The engine looks for Test Project/ first and then the legacy Scripts/ folder inside that project directory.

Build

Managed build (C#):

  • Open the solution in Rider or Visual Studio and build the MusicEngine project.

Native VST3 host (C++):

  • First-time setup (pull the Steinberg SDK into external/vst3sdk):
    • git clone https://github.com/steinbergmedia/vst3sdk.git external/vst3sdk
    • git -C external/vst3sdk submodule update --init --recursive

Windows build (MSBuild):

  • Rider: open MusicEngine.CppLayer/native/MusicEngine.CppLayer.Native.vcxproj and build x64 Debug/Release.
  • Visual Studio: open the same .vcxproj, select x64 + Debug/Release, then Build.
  • Command line (PowerShell):
    • & "C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" "MusicEngine.CppLayer\native\MusicEngine.CppLayer.Native.vcxproj" /p:Configuration=Release /p:Platform=x64

Linux build (CMake):

  • cmake -S MusicEngine.CppLayer/native -B MusicEngine.CppLayer/native/build -DCMAKE_BUILD_TYPE=Release
  • cmake --build MusicEngine.CppLayer/native/build --config Release

The native build copies MusicEngine.CppLayer.Native.dll or libMusicEngine.CppLayer.Native.so into MusicEngine\ automatically (and C# build copies it to the output).

Troubleshooting native build:

  • Error: Cannot open include file: public.sdk/source/vst/hosting/module.h
    • The SDK submodules are missing or empty. Run:
      • git -C external/vst3sdk submodule update --init --recursive
      • If the submodules are present but empty, reset them:
        • git -C external/vst3sdk/public.sdk reset --hard
        • git -C external/vst3sdk/base reset --hard
        • git -C external/vst3sdk/pluginterfaces reset --hard

Mentions

Links

Copyright 2026 watermann429 and contributers.

About

Music Engine is a modular, open-source live-coding music engine written in C#. It combines code, MIDI, patterns, and real-time audio to enable flexible music production, live performance, and interactive audio programming.

Topics

Resources

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

BannerMusicEngine

LicenseC#.NETJoin DiscordStatus

MusicEngine

Scriptable C# music engine for realtime playback, instruments, and VST3 hosting. It can also record mics and music, render audio, and cover a full DAW-like workflow if you know what you're doing.

What makes MusicEngine different?

MusicEngine is a C# scripting language for music. It supports VSTs, sequencers, and patterns without forcing you into any workflow. You keep full control over time and timing. Everything is a tool, nothing is forced, and there are no hidden mathematical clamps. Almost anything can be turned into a variable and be modulated.

Pattern Example (Script)

varsynth=CreateSynth();varpattern=CreatePattern(synth);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Note(60,2.0,1.0,110,slideTo:67,slideTimeMs:500);pattern.NoteMs(72,1500,250,110);// Note(...) auto-uses ms when duration > 8.0 or beat > 32.0 (still supports beats)pattern.Note(72,1500,250,110);varseq1=pattern.Note(60,0.0,0.25,100).Siquenz("0010101001101110");seq1.Loop=true;pattern.Play();

MIDI Routing Example (Script)

varsynth=CreateSynth();midi.device(0).to(synth);midi.device(0).cc(1).to(value =>synth.SetParameter("cutoff",value));midi.device(0).pitchbend().to(value =>synth.PitchBend(value*2f-1f));

More MIDI details: Docs/Midi.md

Device/channel/route toggles:

varsynth=CreateSynth();varmidi1=midi.Device(0);// device handlevarroute1=midi.Device(0).to(synth);// device -> synth routemidi1.Active(false);// disable device inputmidi1.Active(true);// enable device inputmidi.Device(0).Channel(1).Active(false);// disable channel 2 on device 0route1.Active(false);// disable only this route

Modular Effects Example (Script)

varfx=CreateEffect().ReverbPreset("Hall").BitCrushPreset("Lofi").NoisePreset("Light").FilterPreset("Low");varch1=Audio.CreateChannel(1);ch1.Effect(fx);

Preset factory:

varch2=Audio.CreateChannel(2);ch2.Effect(Effect.Reverb);ch2.Effect(Effect.Drive);

Preset names:

varfx2=CreateEffect().ReverbPreset("Hall").DelayPreset("Echo").DrivePreset("Warm");Audio.CreateChannel(3).Effect(fx2);

Preset with overrides:

varfx3=CreateEffect().ReverbPreset("Hall", r =>r.Mix=0.4f).DelayPreset("Echo", d =>d.TimeMs=500f).FilterPreset("Low", f =>f.CutoffHz=800f);Audio.CreateChannel(4).Effect(fx3);

Standalone preset (for modulation):

varreverbFx3=ReverbPreset("Hall", r =>r.Mix=0.4f);varmix=Mod.Var(reverbFx3,"Mix");mix.Lfo(0.2f,0.6f,rateHz:0.5f);

Modular Oscillators (Hybrid Synth)

varsynth=CreateSynth();varosc3=synth.Oscillator();osc3.Waveform=WaveType.Sine;osc3.Level=0.2f;osc3.Pan=-0.2f;varosc4=synth.Oscillator();osc4.Waveform=WaveType.Sine;osc4.Level=0.2f;osc4.Pan=0.2f;osc4.ModToFilter=0.2f;

Wavetable Oscillators

varsynth=CreateSynth();// Built-in tablessynth.Osc1Wavetable=Wavetable.Saw(2048);synth.Osc2Wavetable=Wavetable.WhiteNoise(2048);// Custom file (first channel)varwt=Wavetable.FromFile("my_wave.wav",maxSamples:2048);varosc=synth.Oscillator();osc.Wavetable=wt;osc.Enabled=true;

VST3 Example (Script)

varvital=CreateVst("Vital");vital.SetParameterNormalized("Cutoff",0.5f);midi.device(0).to(vital);midi.device(0).pitchbend().to(value =>vital.PitchBend(value*2f-1f));varpattern=CreatePattern(vital);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Play();

Note: VST UI embedding is Windows-only for now. Linux runs VST audio + parameters without the editor window.

VST State Save/Load

varvital=CreateVst("Vital");vital.State();// on /S or exit, writes base64 into the ()

Notes:

  • The inline State() call is updated on refresh or exit, so you can copy/share the script.
  • States are stored per script under .musicengine/states/<script>/<name>.state.
  • Missing VSTs warn and stay silent instead of crashing.

Manual overrides still work:

vital.LoadState("States.vital.state");vital.SaveState("States.vital.state");

Virtual Output (Discord / Virtual Mic)

To send audio into Discord as a microphone, you need a virtual audio device (e.g. VB-CABLE or VoiceMeeter). MusicEngine can route the master or a channel to any Windows output device.

Audio.Output.List();// list render devicesAudio.Master.VirtualOut("CABLE Input");// route master to virtual micvarch1=Audio.CreateChannel(1);ch1.VirtualOut("CABLE Input");// route channel to virtual mic

Notes:

  • Without a virtual audio device installed, Windows has no "virtual mic" target.
  • In Discord, set Input Device to the virtual cable.

Audio Input (Mics / Line-In)

Note: audio input is Windows-only right now.

Audio.Input.List();// list capture devicesvarmic=CreateMic(0);// or CreateInput(0)varch1=Audio.CreateChannel(1);ch1.Route(mic);ch1.Gain(0.7);

Fluent Instrument Setup

CreateGeneralMidi().Pan(0.2f).Channel(0).Name("GM_AcousticGrandPiano");CreateSynth().Volume(0.7f).Pan(-0.2f);CreateVst("Vital").Volume(0.9f).Pan(0.1f);CreateMic(0).Gain(0.8f).Mute(false);

Variable Modulation

varpan=Mod.Pan(piano,0f);pan.Random(-0.5f,0.5f,everyMs:400);varvol=Mod.Volume(synth,0.7f);vol.Lfo(0.2f,0.9f,rateHz:0.5f);// Any propertyvarcutoff=Mod.Var(synth,"Cutoff");cutoff.Random(0.2f,0.9f,everyMs:300);

General Instruments Example (Script)

varpiano=CreateGeneralMidi();piano.Program=GeneralMidiProgram.AcousticGrandPiano;piano.Volume=0.8f;piano.Pan=0f;piano.Reverb=0.2f;piano.Channel=0;midi.device(0).to(piano);midi.device(0).pitchbend().to(value =>piano.PitchBend(value*2f-1f));varpattern=CreatePattern(piano);pattern.LoopLength=4.0;pattern.Note(60,0.0,1.0,100);pattern.Note(67,1.0,1.0,100);pattern.Note(72,2.0,2.0,100);pattern.Play();

Features (Current)

  • Low-latency MIDI routing and controller mapping.
  • Scriptable pattern sequencer with loop length and per-note velocity.
  • Built-in polyphonic synth with oscillators, ADSR, filter, LFO, and effects.
  • General MIDI output wrapper for system MIDI devices.
  • VST3 hosting with parameter control and editor support.
  • Channel routing with per-channel effects and master processing.
  • Recording taps for master and per-channel audio.

Planned Features

  • Lighting and show control: DMX512, Art-Net, sACN (E1.31), MIDI Show Control.
  • MIDI and timing: MIDI 1.0, MIDI 2.0, MTC, SMPTE/LTC sync, OSC control, MIDI screen/LED feedback with live data.
  • Audio routing: Windows ASIO/WaveOut plus virtual outputs, Linux PortAudio (default device).
  • Game engine integration: Unity/Unreal hooks, custom engine integration, realtime music logic control.
  • Modular control: CV rack-style modularity via code for every variable and setting.
  • DSP and hardware: planned DSP control surface and library to drive custom sound cards for full flexibility.

Notes

  • The project uses NAudio for audio/MIDI and provides its own instrument wrappers.
  • VST3 scanning can be configured via MUSICENGINE_VST3_PATHS (path-separator separated).
  • Extra free instruments, kits, and tools live in the companion library:
  • MusicEngine.Library

MusicEngine.Library (Optional Content)

MusicEngine.Library is a separate, community-driven repository of free instruments, kits, and utilities. It is optional: the engine runs without it. When present, you can load instruments with:

varspeech=LibraryApi("MusicEngine.Instruments.SpeechInstrument");

Use cases:

  • Sample-based kits (drums, one-shots, multisamples).
  • Procedural instruments (speech, drones, generators).
  • Utility helpers to build instruments from local folders.

Missing library instruments are skipped and stay silent (no crash), similar to missing VSTs.

Install

  • Install .NET SDK 10.0 (or newer).
  • Windows: install Visual Studio 2022 with Desktop development with C++ (for the native VST3 host).
  • Linux: install cmake, build-essential, and the PortAudio dev package (e.g. portaudio19-dev).
  • Rider works fine, but MSBuild from Visual Studio Build Tools is still required for the Windows native layer.

Settings reference: Docs/Settings.md

Linux Notes

  • Output uses PortAudio (default device).
  • VST UI embedding is not supported yet.
  • Audio input/recording are not supported yet.
  • Sample loading currently supports WAV (PCM/float) only.

Script Location

The engine scans the default project folder:

Test Project/

Any .cs or .csx file can be a main script if it calls File.Main(); or File(Main, "Name");. To use a different project folder, set MUSICENGINE_PROJECT_DIR (or pass --project-dir <path>). The engine looks for Test Project/ first and then the legacy Scripts/ folder inside that project directory.

Build

Managed build (C#):

  • Open the solution in Rider or Visual Studio and build the MusicEngine project.

Native VST3 host (C++):

  • First-time setup (pull the Steinberg SDK into external/vst3sdk):
    • git clone https://github.com/steinbergmedia/vst3sdk.git external/vst3sdk
    • git -C external/vst3sdk submodule update --init --recursive

Windows build (MSBuild):

  • Rider: open MusicEngine.CppLayer/native/MusicEngine.CppLayer.Native.vcxproj and build x64 Debug/Release.
  • Visual Studio: open the same .vcxproj, select x64 + Debug/Release, then Build.
  • Command line (PowerShell):
    • & "C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" "MusicEngine.CppLayer\native\MusicEngine.CppLayer.Native.vcxproj" /p:Configuration=Release /p:Platform=x64

Linux build (CMake):

  • cmake -S MusicEngine.CppLayer/native -B MusicEngine.CppLayer/native/build -DCMAKE_BUILD_TYPE=Release
  • cmake --build MusicEngine.CppLayer/native/build --config Release

The native build copies MusicEngine.CppLayer.Native.dll or libMusicEngine.CppLayer.Native.so into MusicEngine\ automatically (and C# build copies it to the output).

Troubleshooting native build:

  • Error: Cannot open include file: public.sdk/source/vst/hosting/module.h
    • The SDK submodules are missing or empty. Run:
      • git -C external/vst3sdk submodule update --init --recursive
      • If the submodules are present but empty, reset them:
        • git -C external/vst3sdk/public.sdk reset --hard
        • git -C external/vst3sdk/base reset --hard
        • git -C external/vst3sdk/pluginterfaces reset --hard

Mentions

Links

Copyright 2026 watermann429 and contributers.

About

Music Engine is a modular, open-source live-coding music engine written in C#. It combines code, MIDI, patterns, and real-time audio to enable flexible music production, live performance, and interactive audio programming.

Topics

Resources

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

BannerMusicEngine

LicenseC#.NETJoin DiscordStatus

MusicEngine

Scriptable C# music engine for realtime playback, instruments, and VST3 hosting. It can also record mics and music, render audio, and cover a full DAW-like workflow if you know what you're doing.

What makes MusicEngine different?

MusicEngine is a C# scripting language for music. It supports VSTs, sequencers, and patterns without forcing you into any workflow. You keep full control over time and timing. Everything is a tool, nothing is forced, and there are no hidden mathematical clamps. Almost anything can be turned into a variable and be modulated.

Pattern Example (Script)

varsynth=CreateSynth();varpattern=CreatePattern(synth);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Note(60,2.0,1.0,110,slideTo:67,slideTimeMs:500);pattern.NoteMs(72,1500,250,110);// Note(...) auto-uses ms when duration > 8.0 or beat > 32.0 (still supports beats)pattern.Note(72,1500,250,110);varseq1=pattern.Note(60,0.0,0.25,100).Siquenz("0010101001101110");seq1.Loop=true;pattern.Play();

MIDI Routing Example (Script)

varsynth=CreateSynth();midi.device(0).to(synth);midi.device(0).cc(1).to(value =>synth.SetParameter("cutoff",value));midi.device(0).pitchbend().to(value =>synth.PitchBend(value*2f-1f));

More MIDI details: Docs/Midi.md

Device/channel/route toggles:

varsynth=CreateSynth();varmidi1=midi.Device(0);// device handlevarroute1=midi.Device(0).to(synth);// device -> synth routemidi1.Active(false);// disable device inputmidi1.Active(true);// enable device inputmidi.Device(0).Channel(1).Active(false);// disable channel 2 on device 0route1.Active(false);// disable only this route

Modular Effects Example (Script)

varfx=CreateEffect().ReverbPreset("Hall").BitCrushPreset("Lofi").NoisePreset("Light").FilterPreset("Low");varch1=Audio.CreateChannel(1);ch1.Effect(fx);

Preset factory:

varch2=Audio.CreateChannel(2);ch2.Effect(Effect.Reverb);ch2.Effect(Effect.Drive);

Preset names:

varfx2=CreateEffect().ReverbPreset("Hall").DelayPreset("Echo").DrivePreset("Warm");Audio.CreateChannel(3).Effect(fx2);

Preset with overrides:

varfx3=CreateEffect().ReverbPreset("Hall", r =>r.Mix=0.4f).DelayPreset("Echo", d =>d.TimeMs=500f).FilterPreset("Low", f =>f.CutoffHz=800f);Audio.CreateChannel(4).Effect(fx3);

Standalone preset (for modulation):

varreverbFx3=ReverbPreset("Hall", r =>r.Mix=0.4f);varmix=Mod.Var(reverbFx3,"Mix");mix.Lfo(0.2f,0.6f,rateHz:0.5f);

Modular Oscillators (Hybrid Synth)

varsynth=CreateSynth();varosc3=synth.Oscillator();osc3.Waveform=WaveType.Sine;osc3.Level=0.2f;osc3.Pan=-0.2f;varosc4=synth.Oscillator();osc4.Waveform=WaveType.Sine;osc4.Level=0.2f;osc4.Pan=0.2f;osc4.ModToFilter=0.2f;

Wavetable Oscillators

varsynth=CreateSynth();// Built-in tablessynth.Osc1Wavetable=Wavetable.Saw(2048);synth.Osc2Wavetable=Wavetable.WhiteNoise(2048);// Custom file (first channel)varwt=Wavetable.FromFile("my_wave.wav",maxSamples:2048);varosc=synth.Oscillator();osc.Wavetable=wt;osc.Enabled=true;

VST3 Example (Script)

varvital=CreateVst("Vital");vital.SetParameterNormalized("Cutoff",0.5f);midi.device(0).to(vital);midi.device(0).pitchbend().to(value =>vital.PitchBend(value*2f-1f));varpattern=CreatePattern(vital);pattern.LoopLength=4.0;pattern.Note(60,0.0,0.5,110);pattern.Note(64,0.5,0.5,110);pattern.Note(67,1.0,1.0,110);pattern.Play();

Note: VST UI embedding is Windows-only for now. Linux runs VST audio + parameters without the editor window.

VST State Save/Load

varvital=CreateVst("Vital");vital.State();// on /S or exit, writes base64 into the ()

Notes:

  • The inline State() call is updated on refresh or exit, so you can copy/share the script.
  • States are stored per script under .musicengine/states/<script>/<name>.state.
  • Missing VSTs warn and stay silent instead of crashing.

Manual overrides still work:

vital.LoadState("States.vital.state");vital.SaveState("States.vital.state");

Virtual Output (Discord / Virtual Mic)

To send audio into Discord as a microphone, you need a virtual audio device (e.g. VB-CABLE or VoiceMeeter). MusicEngine can route the master or a channel to any Windows output device.

Audio.Output.List();// list render devicesAudio.Master.VirtualOut("CABLE Input");// route master to virtual micvarch1=Audio.CreateChannel(1);ch1.VirtualOut("CABLE Input");// route channel to virtual mic

Notes:

  • Without a virtual audio device installed, Windows has no "virtual mic" target.
  • In Discord, set Input Device to the virtual cable.

Audio Input (Mics / Line-In)

Note: audio input is Windows-only right now.

Audio.Input.List();// list capture devicesvarmic=CreateMic(0);// or CreateInput(0)varch1=Audio.CreateChannel(1);ch1.Route(mic);ch1.Gain(0.7);

Fluent Instrument Setup

CreateGeneralMidi().Pan(0.2f).Channel(0).Name("GM_AcousticGrandPiano");CreateSynth().Volume(0.7f).Pan(-0.2f);CreateVst("Vital").Volume(0.9f).Pan(0.1f);CreateMic(0).Gain(0.8f).Mute(false);

Variable Modulation

varpan=Mod.Pan(piano,0f);pan.Random(-0.5f,0.5f,everyMs:400);varvol=Mod.Volume(synth,0.7f);vol.Lfo(0.2f,0.9f,rateHz:0.5f);// Any propertyvarcutoff=Mod.Var(synth,"Cutoff");cutoff.Random(0.2f,0.9f,everyMs:300);

General Instruments Example (Script)

varpiano=CreateGeneralMidi();piano.Program=GeneralMidiProgram.AcousticGrandPiano;piano.Volume=0.8f;piano.Pan=0f;piano.Reverb=0.2f;piano.Channel=0;midi.device(0).to(piano);midi.device(0).pitchbend().to(value =>piano.PitchBend(value*2f-1f));varpattern=CreatePattern(piano);pattern.LoopLength=4.0;pattern.Note(60,0.0,1.0,100);pattern.Note(67,1.0,1.0,100);pattern.Note(72,2.0,2.0,100);pattern.Play();

Features (Current)

  • Low-latency MIDI routing and controller mapping.
  • Scriptable pattern sequencer with loop length and per-note velocity.
  • Built-in polyphonic synth with oscillators, ADSR, filter, LFO, and effects.
  • General MIDI output wrapper for system MIDI devices.
  • VST3 hosting with parameter control and editor support.
  • Channel routing with per-channel effects and master processing.
  • Recording taps for master and per-channel audio.

Planned Features

  • Lighting and show control: DMX512, Art-Net, sACN (E1.31), MIDI Show Control.
  • MIDI and timing: MIDI 1.0, MIDI 2.0, MTC, SMPTE/LTC sync, OSC control, MIDI screen/LED feedback with live data.
  • Audio routing: Windows ASIO/WaveOut plus virtual outputs, Linux PortAudio (default device).
  • Game engine integration: Unity/Unreal hooks, custom engine integration, realtime music logic control.
  • Modular control: CV rack-style modularity via code for every variable and setting.
  • DSP and hardware: planned DSP control surface and library to drive custom sound cards for full flexibility.

Notes

  • The project uses NAudio for audio/MIDI and provides its own instrument wrappers.
  • VST3 scanning can be configured via MUSICENGINE_VST3_PATHS (path-separator separated).
  • Extra free instruments, kits, and tools live in the companion library:
  • MusicEngine.Library

MusicEngine.Library (Optional Content)

MusicEngine.Library is a separate, community-driven repository of free instruments, kits, and utilities. It is optional: the engine runs without it. When present, you can load instruments with:

varspeech=LibraryApi("MusicEngine.Instruments.SpeechInstrument");

Use cases:

  • Sample-based kits (drums, one-shots, multisamples).
  • Procedural instruments (speech, drones, generators).
  • Utility helpers to build instruments from local folders.

Missing library instruments are skipped and stay silent (no crash), similar to missing VSTs.

Install

  • Install .NET SDK 10.0 (or newer).
  • Windows: install Visual Studio 2022 with Desktop development with C++ (for the native VST3 host).
  • Linux: install cmake, build-essential, and the PortAudio dev package (e.g. portaudio19-dev).
  • Rider works fine, but MSBuild from Visual Studio Build Tools is still required for the Windows native layer.

Settings reference: Docs/Settings.md

Linux Notes

  • Output uses PortAudio (default device).
  • VST UI embedding is not supported yet.
  • Audio input/recording are not supported yet.
  • Sample loading currently supports WAV (PCM/float) only.

Script Location

The engine scans the default project folder:

Test Project/

Any .cs or .csx file can be a main script if it calls File.Main(); or File(Main, "Name");. To use a different project folder, set MUSICENGINE_PROJECT_DIR (or pass --project-dir <path>). The engine looks for Test Project/ first and then the legacy Scripts/ folder inside that project directory.

Build

Managed build (C#):

  • Open the solution in Rider or Visual Studio and build the MusicEngine project.

Native VST3 host (C++):

  • First-time setup (pull the Steinberg SDK into external/vst3sdk):
    • git clone https://github.com/steinbergmedia/vst3sdk.git external/vst3sdk
    • git -C external/vst3sdk submodule update --init --recursive

Windows build (MSBuild):

  • Rider: open MusicEngine.CppLayer/native/MusicEngine.CppLayer.Native.vcxproj and build x64 Debug/Release.
  • Visual Studio: open the same .vcxproj, select x64 + Debug/Release, then Build.
  • Command line (PowerShell):
    • & "C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe" "MusicEngine.CppLayer\native\MusicEngine.CppLayer.Native.vcxproj" /p:Configuration=Release /p:Platform=x64

Linux build (CMake):

  • cmake -S MusicEngine.CppLayer/native -B MusicEngine.CppLayer/native/build -DCMAKE_BUILD_TYPE=Release
  • cmake --build MusicEngine.CppLayer/native/build --config Release

The native build copies MusicEngine.CppLayer.Native.dll or libMusicEngine.CppLayer.Native.so into MusicEngine\ automatically (and C# build copies it to the output).

Troubleshooting native build:

  • Error: Cannot open include file: public.sdk/source/vst/hosting/module.h
    • The SDK submodules are missing or empty. Run:
      • git -C external/vst3sdk submodule update --init --recursive
      • If the submodules are present but empty, reset them:
        • git -C external/vst3sdk/public.sdk reset --hard
        • git -C external/vst3sdk/base reset --hard
        • git -C external/vst3sdk/pluginterfaces reset --hard

Mentions

Links

Copyright 2026 watermann429 and contributers.

About

Music Engine is a modular, open-source live-coding music engine written in C#. It combines code, MIDI, patterns, and real-time audio to enable flexible music production, live performance, and interactive audio programming.

Topics

Resources

Contributing

Stars

5 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages