Extended MML - MMLX

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Extended MML - MMLX
by on (#88906)
I'm new here, but I wanted to share a little project I've been working on for the last few weeks. It is called MMLX which stands for MML Extended.

I only recently started getting into chiptune composing. Since I'm a programmer MML feels more natural to me than using a tracker, but in some ways it is limiting, and there is not a whole lot of easy to find examples/documentation.

I decided to try writing my own language to make some things easier to do using MML.

Essentially MMLX is a superset of MML. It offers a bunch of features that MML on its own does not support including:

- Defining instruments
- Portamento
- ADSR Envelopes
- Using variables
- Transposing

You can check out the project at:
https://github.com/ccampbell/mmlx

Getting started guide:
https://github.com/ccampbell/mmlx/wiki/Getting-Started

Documentation:
https://github.com/ccampbell/mmlx/wiki/Documentation

I should point out that I have only tested it using Python 2.6 on Mac OS 10.6 and only using the default 5 NES voices A-E. I believe it should run on Linux as well. I don't have a windows machine to test on so if anyone is interested feel free to fork the project on GitHub and add Windows support.

I also have included a TextMate/Sublime Text 2 bundle with syntax highlighting that looks like this:
http://f.cl.ly/items/3B2B2R12303j0E283E3b/mmlx.html

I also hope that someone else might find this useful.

I look forward to hearing feedback.

Please report bugs and feature requests on GitHub:
https://github.com/ccampbell/mmlx/issues

Craig

by on (#88920)
Sounds great !

I agree MML feels more natural than using a tracker. What I hate so much about trackers is that you have to remember all sort of key combinations to do every single thing, and you have to remember all effects code. Quite annoying if you ask me.
Re: Extended MML - MMLX
by on (#88929)
I like it. Here are my suggestions:
  • Non-layout mode for instrument definitions (like how Haskell supports layout and non-layout modes)
  • Allow blocks of commands defined in a variable to take parameters
  • Include arithmetic macros
  • Feature for custom temperament (instead of being limited to 12-TET, you could have Bohlen-Pierce, etc)
  • In PPMCK, I have seen some of the assembly code is not well optimized; you could replace a subroutine call followed by return from current subroutine, with just a unconditional jump. I have fixed it in my computer, but it is probably a good idea to correct MMLX too

by on (#88933)
The worst unoptimised thing in PPMCK is how it stores sequence data !

For example [c c d d]4 would be stored as : ccddccddccddccdd instead of being effectively stored like you type it which would save a lot of bytes !

But this is the fault of the compiler/replay engine, not the language.

by on (#88938)
Bregalad wrote:
The worst unoptimised thing in PPMCK is how it stores sequence data !

For example [c c d d]4 would be stored as : ccddccddccddccdd instead of being effectively stored like you type it which would save a lot of bytes !

But this is the fault of the compiler/replay engine, not the language.


The [ ~ ] command is a kind of unrolled loop. If you want it to really repeat <num> times without unrolling, use |: ~ :|.
But it's a fact that PPMCK store its data rather unoptimised; every command occupy a byte. At least, it has one advantage, it's easier to extend its capability (it's simpler that, say, a rather compressed one)

EDIT: Disabled a smiley.

by on (#88944)
Bregalad wrote:
But this is the fault of the compiler/replay engine, not the language.
I was refering to the codes built in to the replay engine (where call followed by return is used where jump could be used instead; this is a kind of tail calls optimization), although your points are something too.

by on (#88949)
Actually PPMCK does support transposing with the "K" command. K<num> transposes <num> semitones.

I did something like this awhile ago in vb.net that basically reads in a NSF file, separates the channels and makes each note/command an object, so it's possible to do whatever you want. The first thing I did was portamento, and it works well enough but I am lazy and never finished it.

by on (#88976)
RushJet1 wrote:
Actually PPMCK does support transposing with the "K" command. K<num> transposes <num> semitones.


Thanks, I totally did not realize this. I guess I can take out that feature :)

by on (#88977)
~J-@D!~ wrote:
Bregalad wrote:
The worst unoptimised thing in PPMCK is how it stores sequence data !

For example [c c d d]4 would be stored as : ccddccddccddccdd instead of being effectively stored like you type it which would save a lot of bytes !

But this is the fault of the compiler/replay engine, not the language.


The [ ~ ] command is a kind of unrolled loop. If you want it to really repeat <num> times without unrolling, use |: ~ :|.
But it's a fact that PPMCK store its data rather unoptimised; every command occupy a byte. At least, it has one advantage, it's easier to extend its capability (it's simpler that, say, a rather compressed one)

EDIT: Disabled a smiley.


This is a good point. It seems to me that the [] notation allows for nested loops where the |: :| does not. I could add an optimization so that if you write a loop such as [c c d d]4 and it is not nested it rewrites it as |: c c d d :|4 when it generates the MML.

by on (#88985)
I never knew about the |: :¦ notation. It seems absent from the tutorials/docs I've used, although this symbol looks very like music sheet repeat symbol. I'll have to give it a try.

I think I know why [] does allow nested repeats and not |: :|
I assumes |: :| stores the location in ROM of the sequence data where |: is located, and when they met the :| it decrease a counter and go back to |:
Of course if you place two |: before one :|, the second will override the first, and this won't work as supposed.

On the other side it would have been possible to reserve memory for a repeat location stack, so you can repeat repeats, as many times as the stack allows it. But it'll quickly take a lot of memory if you have to do it for all channels.
I remember Secret of Mana's sound engine did something like that (I've fully disassembled it).

by on (#88986)
Quote:
On the other side it would have been possible to reserve memory for a repeat location stack, so you can repeat repeats, as many times as the stack allows it. But it'll quickly take a lot of memory if you have to do it for all channels.


XPMCK does that, but it only allows up to two levels.
Re: Extended MML - MMLX
by on (#88988)
zzo38 wrote:
Feature for custom temperament (instead of being limited to 12-TET, you could have Bohlen-Pierce, etc)

I quite like this idea. Ideally, you should be able to make your own scales by assigning custom frequencies to note letters. In the case of scales with more than 12 notes per octave, perhaps you could use extra flats/sharps (ex: c c+ c++), similar to microtonal sheet music. Also, you should be able to switch scales during a song.

It would also be nice to be able to use ties when defining note length with the "l" command. (ex: l4^7)

by on (#89027)
mic_ wrote:
Quote:
On the other side it would have been possible to reserve memory for a repeat location stack, so you can repeat repeats, as many times as the stack allows it. But it'll quickly take a lot of memory if you have to do it for all channels.


XPMCK does that, but it only allows up to two levels.


I noticed this too when I played with XPMCK and've been dieing for it in PPMCK ever since.

I've felt discouraged to ask this for some time feeling it to be a dumb question, but I must ask; as I like to double up channel voices together, knowing it's rather inefficient, is it possible in nes standards to point one channel to the playback data of another channel, have both play simultaneously and perhaps save some space?

by on (#89028)
Quote:
is it possible in nes standards to point one channel to the playback data of another channel, have both play simultaneously and perhaps save some space?

The way I solved that was to implement what I call patterns (kind of like subroutines).

by on (#89061)
haven't checked xpmck in a while, very happy to see updates=)