Julian Storer ist kein unbeschriebenes Blatt … JUCE, Tracktion und Kopf der Software-Abteilung bei ROLI. Vielbeschäftigter Mann. Trotzdem hat er die letzten Jahre an einer neuen Programmiersprache für Audio und Sound gearbeitet, die seit dem November letzten Jahres im Beta-Stadion ist. Echt jetzt? Noch eine neue Programmiersprache für den Bereich Audio? Jepp.

Quelle: soul.dev

SOUL heißt das Wunderkind und will die Audio-Programmierlandschaft umkrempeln. Aber SOUL ist keine generelle Sprache um Audio-Applikationen oder Plugins zu bauen. Diese Sprache ist speziell entwickelt worden, um Echtzeit-DSP Code zu entwickeln und ist gleichzeitig eine API, um diesen Code in alle möglichen Anwendungen und auch Hardware einzubinden.

Momentan ist der Standard für High-End-Realtime Audio-Code immer noch C/C++. Diese Sprache ist für viele angehenden Entwickler eine Hürde, denn C oder C++ ist hart und kann für Neulinge auch gefährlich sein, denn Entwickler aus dem Bereich Audio und Sound wollen interessante DSP Algorithmen schreiben und sich nicht mit all den anderen Themen der Applikationsentwicklung herumschlagen.

Natürlich kann man spezielle Lösungen für die Audio-Programmierung nutzen, wie Csound, Supercollider, Pure Date oder Max/MSP, denn diese sind einfacher zu erlernen und helfen sicherlich beim Verständnis von Zusammenhängen im Bereich Sound und Synthese und sind auch für spezielle Lösungen geeignet. Aber wenn es darum geht schnelle Software zu schreiben und diese auch eventuell zu vertreiben, egal ob als eigenständige Applikation oder in Plugin-Form, kommt man an C++ nicht vorbei.

The Tools are either fast or easy (or neither)

Julian Storer
Quelle: youtube.com

SOUL ist genauso schnell wie C++, aber es ist lange nicht so umfangreich, sondern speziell auf DSP Algorithmen zugeschnitten. Das macht SOUL leichter zu erlernen und einfacher zu handhaben. Natürlich bekommt man auch hier nichts geschenkt. DSP Algorithmen sind schwer und sie werden es auch bleiben, aber ich muss mich nicht mehr in eine Code-Hölle wie C oder C++ begeben, um diese zu implementieren.

Wie bereits eingangs erwähnt, befindet sich SOUL seit dem November 2019 im Beats-Stadion und man kann damit schon herum experimentieren. Es gibt mittlerweile zwei Anlaufstellen, um sich mit dem Projekt auseinanderzusetzen:

SOUL-Lang Github Seiten

SOUL Web Plattform

Die GitHub Seiten enthalten ein wenig Informationen zum Projekt und eine Einführung in die Syntax der Sprache. Des Weiteren kann man sich das Kommandozeilen Tool herunterladen und Code direkt im Terminal ausführen. Ich hatte allerdings ein paar Probleme mit dem Tool.

Ein viel besserer Weg, um ein wenig mit SOUL zu experimentieren ist die Web Plattform. Hier kann man Code eingeben, kompilieren und herunterladen. Es gibt einige Beispiele und die Möglichkeit sich den Code als Graphen anzeigen zu lassen, um etwas besser zu verstehen, was passiert.

Ein Reverb Effekt auf soul.dev
Audio Graph einer einfachen 909 Drum Machine auf soul.dev

Wie sieht der Code aus?

SOUL hat von der Syntax her viel mit C++, JavaScript oder Java gemeinsam. Wenn man in einer dieser großen Sprachen schon mal programmiert hat, wird man sich schnell zurechtfinden.

Wenn man sich mit dem Kommandozeilen-Tool ein neues Instrument generiert, bekommt man automatisch einen simplen Sinuswellen Synthesizer auf’s Tablett serviert, der so aussieht:

/**
    This is an auto-generated SOUL patch template.
    This example code simply plays a trivial sinewave mono-synth, and
    it's up to you to build upon this and create a real synthesiser!
*/
graph mySynth  [[main]]
{
    input event soul::midi::Message midiIn;
    output stream float audioOut;

    let
    {
        midiParser = soul::midi::MPEParser;
        voice = SineOsc;
    }

    connection
    {
        midiIn              -> midiParser.parseMIDI;
        midiParser.eventOut -> voice.eventIn;
        voice.audioOut      -> audioOut;
    }
}

//==============================================================================
processor SineOsc
{
    input event (soul::note_events::NoteOn,
                 soul::note_events::NoteOff) eventIn;

    output stream float audioOut;

    event eventIn (soul::note_events::NoteOn e)
    {
        currentNote = e.note;
        phaseIncrement = float (twoPi * processor.period * soul::noteNumberToFrequency (e.note));
    }

    event eventIn (soul::note_events::NoteOff e)
    {
        if (e.note == currentNote)
            currentNote = 0;
    }

    float currentNote, phaseIncrement, amplitude;

    void run()
    {
        float phase;
        phaseIncrement = 0.0f;

        loop
        {
     // A very simple amplitude envelope - linear attack, exponential decay
            if (currentNote == 0)
                amplitude *= 0.999f;
            else
                amplitude = min (amplitude + 0.001f, 1.0f);

            phase = addModulo2Pi (phase, phaseIncrement);

            audioOut << amplitude * sin (phase);
            advance();
        }
    }
}

Wie gesagt, hatte ich zum Zeitpunkt des Schreibens dieser Zeilen ein paar Probleme mit dem Kommandozeilen Host für SOUL Patches. Natürlich gibt es noch eine andere Möglichkeit außer Web-Plattform und Kommandozeile. Tracktion Waveform Free, die aktuelle freie DAW von Tracktion kann selbstverständlich SOUL Patches laden und ausführen (selbstverständlich auch die Pro Version)!

Soulpatch in Tracktion Waveform 11

Und ein SOUL Patch verhält sich nicht wie ein VST- oder AU-Plugin. Das Patch wird natürlich auch kompiliert, aber in Echtzeit. SOUL benutzt einen JIT Compiler für die Code-Übersetzung und das hat den Vorteil, dass man auch in Echtzeit den Code eines Patches ändern kann. Die Änderungen sieht man sofort in der DAW bzw. im Terminal-Host. Das macht Tracktion Waveform zu einer perfekten Entwicklungsumgebung!

Waveform hat aber noch einen Vorteil, was SOUL angeht, allerdings nur die Pro Version. Mit Waveform kann man sein eigenes GUI für Plugins in Form von Faceplates generieren und das funktioniert auch mit SOUL Patches. Diese GUI wird dann mithilfe einer XML Datei im Ordner des Patches gesichert und jedesmal mit dem Plugin in Waveform geladen.

Reverb Beispiel in Waveform…

Ansonsten besteht die Möglichkeit mithilfe von JavaScript eine GUI zu programmieren. Hierzu konnte ich bisher aber noch keine weiteren Informationen finden.

Was genau ist ein SOUL Patch?

Ein SOUL Patch besteht aus einer SOUL-Quellcode Datei, einer Patch-Datei im JSON Fomat, die als Manifest des Patches alle Informationen und Links zu zusätzlichen Dateien und Resourcen sammelt und den Assets (Codefiles oder Media-Dateien). Keines der Dateien eines Patches ist ausführbar. Ein SOUL Patch benötigt einen Host.

Ein SOUL Patch kann im Grunde wie ein Plugin behandelt werden. Es behandelt Audio I/Os und externe GUIs genauso wie VST- oder AU-Plugins. Allerdings beinhaltet es keinen nativen Code und der DSP Code und der GUI Code sind in verschiedenen Sprachen geschrieben. Patches sind JIT-kompiliert und können während der Ausführung im Code-Editor bearbeitet werden. Dies funktioniert bei VST- oder AU-Plugins in der Regel nicht (mal abgesehen von Blue Cat’s Plug’n’Script)

Beispiel einer JSON .soulpatch Manifest Datei:

{
  "soulPatchV1": {
    "ID":               "com.mycompany.sounds.awesome_synth_sound_34",
    "version":          "1.0",
    "name":             "Awesome Synth Sound 34",
    "description":      "This is an awesome sound",
    "category":         "synth",
    "manufacturer":     "The Cool Synth Company Inc",
    "icon":             "AwesomeSoundIcon.svg",
    "website":          "https://mycoolsynthcompany.com",
    "isInstrument":     true,

    "source":           [ "AwesomeSound34.soul", "SomeSharedLibraryCode.soul" ],

    "externals": { 
      "SampleSet::kickdrum": "sounds/kick1.ogg",
      "SampleSet::hihat":    "sounds/hihat.flac",
      "SampleSet::bass":     "sounds/bass.wav",
      "SampleSet::crash":    "sounds/crash22.wav"
    },

    "view":             [ "AwesomeGUI.js", "AwesomeGUI.faceplate" ]
  }
}

Im Grunde stellt ein SOUL Patch in meinen Augen damit eine bessere Variante eines herkömmlichen VST-Effekts oder VST-Instruments dar. weil es von vornherein auf allen Plattformen funktioniert. Die Frage ist nur, ob DAW-Entwickler auf den Zug aufspringen und eine SOUL Unterstützung einbauen. Wünschenswert wäre es ja. Aber man könnte den SOUL-Code auch in C++ exportieren (Das Terminal Tool bietet diese Option) und mithilfe von C++ und JUCE ein Plugin daraus machen, was einfacher gesagt ist als es klingt.

Diese Frage der Möglichkeit seinen Code in ein VST-Plugin zu exportieren, haben auch schon einige Programmierer im JUCE Forum gestellt und Jules‘ Antwort darauf war:

If you just want to write and play with some soul code, you can do that in Tracktion, or using the soul command-line tools, or on soul.dev, and you don’t need C++ for that.

But if you want to build a real plugin as an actual product and distribute it, then the tool you need for that (the soul -> full juce project generator) isn’t quite finished yet. When that’s done (probably within a couple of months) then it’ll spit out a whole juce project that you can compile into a native VST… but it’s still a C++ project, and you’ll still need enough C++ know-how to at least understand how to use a C++ build chain, how to run, debug it. And you’re probably going to want to write a GUI for it, and that’s going to take grown-up C++ knowledge, much more than writing some DSP code.

In the long-term when SOUL is established and enough hosts can load it, then it’ll get a lot easier and you’ll be able to release pure soul + javascript GUI patches without needing to go near a native compiler, but that’s a way off right now!

Jules Storer

Julian Storer und sein Team haben auf jeden Fall noch große Ziele mit SOUL und ich würde mich freuen, wenn das Projekt noch wirklich groß wird, denn ich finde den Ansatz und die daraus resultierenden Möglichkeiten wirklich spannend. Ich bin gespannt, wie sich das Projekt noch entwickelt.

Wer sich das alles nochmal auf der Zunge zergehen lassen möchte, dem empfehle ich die recht ausführliche Masterclass auf dem Audio Programmer YouTube Channel aus dem November letzten Jahres: