Moselle Alpha 0.1.3 Released

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

Version 0.1.3 of Moselle IDE is now released and available for download at:

http://moselle.invisionzone.com/index.p ... a-release/

Moselle IDE is a standalone music synthesizer for Windows, that can be programmed in a special "modular synthesizer programming language" called Moselle. Hook up a MIDI keyboard to your computer, and MoselleIDE will play music out your speakers. Learn the language from 150+ example patches arranged as a textbook. 400 "standard style" keyboard patches are included as well as specific demos of Moselle's power. For more basic details, please follow the above link.

CHANGES from 0.1.2

The main change is that "packages" are now supported. Packages are similar to "libraries" in most other languages. Inside, a package looks like a patch, except it doesn't have Voice and Patch modules. It has any other modules though (or none at all), and as much math as you want. Normal Moselle patches can use these packages exactly the same as the built-in module types like Oscillator and Envelope. (And packages can in turn use other packages.)

Going forward, I'll be supplying some packages. You can write your own packages. And I hope that other users will start to share good packages around.

The initial packages in this release include:

-- Reverb
-- ReverseReverb
-- SoftLimiterRBJ
-- Leslie Rotary Speaker Simulator
-- SzaboSawOsc (similar perhaps to JP-8000 supersaw?)
-- CazanovaOsc (similar perhaps to Casio CZ synthesizers?)
-- Small80sSynth (similar perhaps to Juno-106 or Polysix?)
-- TuneJust7LimC (7-Limit Just Intonation module for C)

Example: you're writing a patch, and decide you want to use the Leslie package. You list it like any other module, and specify its input signal and slow/fast switch. (You can set slow/fast RPMs and rise/fall times too if you want.) Internally, it has a filter (for the crossover), two LFOs modulating two delay lines (for Doppler shift for the bass and treble speakers), and two Slew modules handling the change of LFO speed. However you don't need to think about all that to use it.

Its like buying ingredients for a hamburger: you can buy the beef, and the onion, and the lettuce, and the bread. Unlike the rest, the bread is itself actually made of lots of other ingredients. You can think about those ingredients if you want, but you can also treat the bread pretty much the same as the raw ingredients like lettuce. In the same way your patch can use modules (the raw ingredients) and packages (the ingredients made from other ingredients) the same way.



Other changes include:

-- multiple Delay taps can now be specified with a formula.

-- Windows XP 32-bit may now work, not sure.



Changes I plan on making in the next month or so:

-- performance speedup: three approaches. I think I will do one approach, giving just a 1.5-3x speedup for everyone, followed by multi-threading which will be a big pickup but only for people with lots of processor cores. The long range plan (summer 2014?) is still to have a compiler, which should be 20-50x faster than the current system.

-- a new language feature called "anonymous modules", whereby you can create a module only used one place just by referring to it. You could for instance write: "Frequency = 2000 + Slew( Hold( 1 sec ), .5 sec )" to create a sample-and-hold (by default sampling a random number) every second, and slewing that with a slew rate of a half-second. Up until now you'd have to make a module called [Hold], and one called [Slew] that uses Hold as its Input, then use that Slew in your Frequency formula. In short, this gives no new power but saves a lot of typing in some cases.

-- figure out why 64-bit isn't working

-- plan a merger of patches and packages. As a simple example, I'd like to make a new patch, that is simply an old patch but with reverb. Complicated example: write patches for trumpet, trombone, and saxaphone. Then, I'd like to write another patch that uses the first three packages, but actually has them play three part harmony automatically. This will probably end up combining the module types Voice, Patch, and Interface somehow, but I don't know the details yet.

Post

Swiss Frank wrote:The long range plan (summer 2014?) is still to have a compiler, which should be 20-50x faster than the current system.
Out of curiosity (since the whole programming language and compiler thing is kinda my other hobby) how does your implementation work right now? I mean, are you running some interpreter and if so, are you doing it on per-sample basis or in terms of blocks?

Post

Hi Mystran,

The language (if you haven't seen it) is basically the same as a MSFT .ini file; section headings and variable=value pairs. Each section heading is basically a module: Oscillator, Envelope, etc. All the settings on the module in question are variables that can be set. Almost without exception they have default values that do the most common thing. The values are more or less Excel formula, except instead of referring to other "cells" by row/column notation, its by module:variable notation. Almost all modules have multiple outputs. For instance, an Oscillator gives you an audio output scaled by frequency; a non-audio output good for modulation; a sync out; etc.

In addition to that, there's a lot of "syntactical sugar," making common paradigms easy to type. A few examples: the canonical module:variable pair can be shorted to just Module, if you're referring to its output variable Output. You can just use Variable, if referring to another variable in the current module, or to a variable unique across the patch (within scope, in other words not in other packages). Keywords cent semi octave and dB are supported; adding these "exponential" types is equivalent of multiplication, so writing "Frequency = Osc1:Frequency + 1 oct" in effect multiplies Osc1's frequency by two. You can scale quantities in the inclusive range 0..1 (which includes for instance MIDI controllers, the default output range of envelopes, etc.) with an [a,b] (linear) or {a,b} (exponential) notation. For instance, Frequency = ModWheel{A2,A6} would vary the frequency based on the ModWheel between 110 and 1760 Hz exponentially (assuming you're using the default tuning). Or, to apply vibrato, you might set an oscillator's Frequency = Voice:Frequency + (ModWheel * LFO)[0,40] cents.

Now to your question: the formulas are parsed into trees in memory. An optimization phase runs, with about 50 rules, which can usually get speedups of 20%. (Premultiplies constants, eliminates arithmetic identities, etc.) Then, currently, these trees are queried for their values. However, it should be extremely straightforward to, instead of executing them, just output C code that would do the execution, compile that, and dynamic-link it back into the executable. Somewhat more difficult would be to output machine language. I've been recommended to check out a package for this purpose that seems to be kind of a compiler turned into a library. That would avoid the distraction of requiring the patch-development machine from having the free Visual Studio or Cygnus GCC package.

One thread is evaluating all voices, a default of several hundred samples at a time. (I've lost track of the lowest acceptable number on my machine, but might have been 128 samples at 44.1kHz.) A second thread handles MIDI events, and can create new voices in the middle of that 128 samples so delay isn't always so bad, but it certainly can be awful.

There's lots of room for improvement in the performance, which is borderline unusable, but this is currently meant to be a testbed for evaluating whether the language itself is any good. Personally I've been VERY surprised at how much I can do with it: Casio CZ emulation only took a couple hours to get working. However, I'd like to hear a lot more criticism of the language, and potentially redesign it once or twice, before taking the big step of converting it to a compiler.

Post

Swiss Frank wrote: However, it should be extremely straightforward to, instead of executing them, just output C code that would do the execution, compile that, and dynamic-link it back into the executable. Somewhat more difficult would be to output machine language. I've been recommended to check out a package for this purpose that seems to be kind of a compiler turned into a library. That would avoid the distraction of requiring the patch-development machine from having the free Visual Studio or Cygnus GCC package.
There are a bunch of compilers turned into libraries, from the tiny C compiler (with libtcc that has a really simple API so might be a nice temporary solution; compiles C code, no idea about the output code quality) to production quality LLVM (the IR is a bit lower level, but roughly as easy to target as C; the downside is that LLVM itself is a bit large). There are others, but those at least might be worth checking out.

Then there's a bunch of assembler tuned into a library, in case you want to target native but avoid the trouble of encoding instructions and resolving labels. Downside is that you then need to do any optimizations yourself (some stuff is easy, some stuff will drive you crazy; personally I find that fun, but YMMV).

Post

Thx Mystran. What are the reasons that any of these would be easier/better to use than simply outputting C++ into a temp file, compiling into a .so/DLL, then opening with libld or LoadLibrary() (which I've been doing at the day gig since 1994)?

To answer my own question, they'd mean my user didn't have to bother downloading a free compiler. To me that's not a big win. They'd mean my software worked not only on PC/Win/Linux but also iPads, smart phones, embedded devices. Hmmm, not the development direction I had in mind as you can't program Moselle without literally typing all day. No-one would do that on an iPad. And yet if you have something with a real keyboard (eg, laptop, computer) it can compile libraries that could be downloaded into the final environment.

EG maybe the end game is to have a rackmount box with MIDI in, DACs out, and a good DSP or GPU inside doing the match. I wouldn't bother making the rackmount box edit-capable. Standalone it'd be merely patch-recall for live performance. And so it could be recalling not the textual patches but pre-compiled libraries, so to speak.

Post

BTW here's my best example of Moselle's "power".

It is a package (libary) using several oscillators to make a sound reminiscent of a Casio CZ, and a little patch based on that library.

http://moselle.invisionzone.com/index.p ... le-module/

Post

Swiss Frank wrote:Thx Mystran. What are the reasons that any of these would be easier/better to use than simply outputting C++ into a temp file, compiling into a .so/DLL, then opening with libld or LoadLibrary() (which I've been doing at the day gig since 1994)?
Less overhead mostly. No need to touch the disk, no need to start a separate process, possibly no need to express code as text at all either. Any of that might or might not matter; it's mostly a matter of the level of interactivity you're after.

[edit: also I wouldn't underestimate the support trouble for actually making sure that the user has successfully managed to install said "free compiler" properly, and that your software is using the right compiler when there are multiple available, possibly without the user knowing]

Post

A few-hundred lines of C/C++ that doesn't include headers compiles in 1/10 sec or something. Really its the headers that kill you: even "hello world" might end up reading 100 different files, as "stdio.h" includes 6 other files, which each include 6 other files, etc... So I don't worry about the overhead.

Outputting the C/C++ is actually trivial for a 25-year C++ veteran. Learning one of these (I assume) fairly complicated libraries is much harder.

Installing a compiler: meh, just tell people "get the free download" and "allow install into default location." I think I'd spend maybe an hour or two supporting such issues, as opposed man-weeks or man-months to learn the library. Which in any case can and will change and I'll have to maintain compatability with that.

Note I'm not against the compiler library--it sounds slick. But I just can't picture how its API could be any simpler than just using the fprintf() I've had memorized since the 80s.

Post

Swiss Frank wrote:A few-hundred lines of C/C++ that doesn't include headers compiles in 1/10 sec or something. Really its the headers that kill you: even "hello world" might end up reading 100 different files, as "stdio.h" includes 6 other files, which each include 6 other files, etc... So I don't worry about the overhead.
[...]
Note I'm not against the compiler library--it sounds slick. But I just can't picture how its API could be any simpler than just using the fprintf() I've had memorized since the 80s.
Yeah, well either method works [and I've used the fprintf+compile+dlopen in the past as well], just sharing experiences. My main point still is that adding a compiler doesn't have to be hard. :)

Post

Do you know off-hand a link to any such toolkit's "hello world?" It could be the canonical "hello world\n" program, or it could be something that creates a function that just does some math?

Post Reply

Return to “DSP and Plugin Development”