This is an old revision of the document!
Table of Contents
x68k Music: MXDRV MML/MDX Tutorial
So, you've been enlighted with the knowledge of a little machine called the
Sharp x68000.
It was powerful, beautiful, and maybe even a tad expensive
( that didn't keep people from flocking to purchase one ).
You probably know that one of its major strong points were two sound chips called the YM2151 and the OKI MSM6258.
And as with any computer worth buying, if you're into composing music, then this computer will work for you. Especially since it's got FM audio + ADPCM. Sega Genesis? Who needs it?! It's got a system that will stomp it any day (and yes, I mean the SNES)!
But the blessed Japanese folks were the only ones who got ahold of this machine.
So, what if you wanted to, I dunno, compose music using the x68k's beautiful FM synthesis + ADPCM audio. MXDRV MML is the name of the game (not an actual game though).
The problem is that there's not a lot of documentation on it in English.
So make sure you thank me well, and maybe give me a nice pat on the back
(and send me lotsa money so I can buy some C64 peripherals,
an Amiga 500, a Sharp x68k of my own, and every other vintage computer I'd
like to get my bony hands on! Ooops! Forgot to mention the Compaq Presario 425!).
Kidding about the money part, although that doesn't mean I won't accept money .
x68k Sound Information
The Sharp x68000 has two chips for audio within the main unit. These two chips are the Yamaha YM2151 (a.k.a. OPM), and the OKI MSM6258, which are used for FM Synthesis and ADPCM sampled audio respectively.
The early models of the x68k have 8 channels of FM and 1 channel of ADPCM. Later Sharp decided to expand the ADPCM audio, and added 7 extra channels of ADPCM, dubbing the new ADPCM system the PCM8 expansion or PCM8. There is also a software called PCM8 which uses software mixing to add more ADPCM channels, but from what I've tested of it, it's a CPU cycle thief. There are other software mixing ADPCM TSR drivers, but I haven't tried them.
MXDRV allows you to use PCM8 in addition to the normal FM Synthesis and ADPCM.
Required/Optional Tools and Information Links
Here are some useful links to tools and information that you might want to see.
The following tools are required to write MXDRV MML code:
Run68k - Sharp x68k command line emulator, necessary to run x68k programs from term/cmd: https://osdn.jp/projects/sfnet_run68/ Alternatively, you can use a full x68k emulator, but I have no idea how you would handle file transfer that way. The command line emulator has access to files on your hard drive, so you can run x68k command line programs from your system'snative command line.
MDX_TOOL - x68k MXDRV tools, necessary to compile your MML->MDX: http://nfggames.com/x68000/Mirrors/x68pub/x68tools/SOUND/MXDRV/MDX_TOOL.LZH This archive contains mxc.x, the x68k MDX compiler. You will need to run it with run68k and your MML file to compile to MDX. There are other MDX compilers, but this is the one I use.
MKPDX http://x.haun.org/software/mkpdx/mkpdx.txt This tool is required to create PDX files. See the section on making a PDX for this. It's a Win32 executable, so no emulator required (unless you're using Linux or Mac).
WAV2ADP http://nfggames.com/x68000/Mirrors/x68pub/x68tools/SOUND/ADPCM/W2ADP101.LZH This tool is required to convert any .wav audio files you have lying around, that you want to convert to ADPCM for use in a PDX. See the section on making a PDX for this. GR_ALL.lzh - Battle Garegga MDX tunes: http://kmkz.jp/mtm/mag/mus/mdxdat/GR_ALL.lzh This archive contains all the MDX tunes from Battle Garegga, but I mainly linked to it because it has a PDX file if you don't want to create your own. The PDX contains some nice samples from synths and drum machines (the TR-909 and others) that Manabu Namiki didn't want, or need to program as FM instruments.
VOPM - OPM Emulation VST, necessary for making your own FM patches: http://www.geocities.jp/sam_kb/VOPM/ You can experiment with VOPM and make your own FM sounds, or rip them from other FM tunes using mdxtools or .opm files from the internet. This is important because if you don't have any FM patches, you won't be able to make music on an FM chip lol. Savihost - Standalone Virtual Instrument Host, necessary if you want to run VOPM without a DAW: http://www.hermannseib.com/english/savihost.htm mdxtools - "A bunch of tools for handling the MDX music format (music for the Sharp X68000 using the MXDRV sound driver).": https://github.com/vampirefrog/mdxtools You need these tools if you want to do things like rip FM patches from other MDX tunes or decompile MDX. I've only gotten this toolkit to compile on Linux, which shouldn't be too much of a problem for you if you don't use Linux (VM or dual boot). opm2mml - A program to convert MiOPMdrv .opm banks to MXDRV mml: https://drive.google.com/open?id=0B-5MDOTTWQK9a0hhbFNFUlBXdDQ This is a tool I coded in Java to do exactly what the description says. With it, you'll be able to convert .opm banks to MML. You can find lots of .opm banks online, and you can rip them from software/games on systems using the YM2151 or YM2612 chips. Even better, you can export VOPM preset banks to .opm, so you can use your own patches. If, for whatever reason, you need a version in C++ or C because you don't use or like Java, then I may port it to one of those languages.
To play your compiled mdx tunes:
mxv - MXDRV World Vision, an MDX player: http://gorry.haun.org/cgitest/download.pl?subject=CGI-DOWNLOAD%20mxv200b.lzh&info=readcount&file=mx.html&downfile=mxv200b.lzh The player requires the libraries X68Sound.dll and MXDRV.dll X68Sound.dll - X68k YM2151 and OKI Emulation library, necessary for mxv: http://gorry.haun.org/cgitest/download.pl?subject=CGI-DOWNLOAD%20X68Sound_020609_g20020611.lzh&info=readcount&file=mx.html&downfile=X68Sound_020609_g20020611.lzh mxdrv.dll - Mdx driver for Windows, necessary for mxv: http://gorry.haun.org/cgitest/download.pl?subject=CGI-DOWNLOAD%20mxdrv200b.lzh&info=readcount&file=mx.html&downfile=mxdrv200b.lzh Alternatively, you can use the Winamp in_mdx.dll plugin in Winamp or XMPlay, or use the native MDX player for the X68k Note that the Winamp plugin requires you to have mxdrv.dll and X68Sound.dll in the same directory as the player (Winamp or XMPlay) Putting those libraries in the same directory as the plugin will not work if you put your plugins in subdirectories
The following tools and infos are optional:
PPMCK MML Beginner's guide: http://www.nullsleep.com/treasure/mck_guide/ Notepad++ - Windows text editor made especially for coders: https://notepad-plus-plus.org/ Notepad++ will make it a lot easier to write in MML in because you can define your own language syntaxes. I might make an MXDRV MML user defined language someday, but not atm. Woolyss chipmusic > MML - MML tools and editors http://woolyss.com/chipmusic-mml.php This page has a great deal of MML editors and compilers (though none for the x68k). It MML bundles for various text editors at the bottom of the page (including Notepad++), but it was made for PPMCK mml. However, you can still use it.
General MML Information
If you don't already know what MML is or how it works, then hold your $400 studio headphones, because I'm about to explain. Well, only the basics, because a lot of general MML information is already documented in English.
MML, or Music Macro Language, is a programming language used for nothing other than composing music. Sounds a bit masochistic, but it's not as bad as you think, so keep reading.
The core of MML is rooted in traditional musical notation. So it's not like you'll be programming your music routines in assembly…bless Rob Hubbard's heart. But it also means that you'll be doing everything in textual format, unlike many other electronic composition methods.
As with any worthwhile electronic composition method, MML uses commands which allow things like portamento, ties, vibrato, and other important musical techniques.
General MML Macros and Syntax
Get ready, because I'm about to get straight to the point with this one. If some of these terms are confusing you, then you might need to learn basic music theory.
Macro arguments in brackets are optional, and the brackets are NOT part of the command, with the only exception to this being the loop macro.
! Ignore all following commands on the current channel Sort of like commenting out code, although you can use ; or /* */ for that
@# Select voice, where # = the desired voice(0 - 255) The precondition here is that the voice must already be defined, else your compiler will flip you the bird. Assuming that you're writing this on an FM channel, using this command will switch to the desired instrument denoted by num. There is a very important variation of this syntax which I will discuss later.
#TITLE title Sets the title of a tune Ex. #title mytune
& Tie macro When this macro is used between notes, it will tie to the next note. For porta- mento, you want to use the glide macro instead. This just
( ) Decrement/Increment Volume, respectively. ( ~ lowers the volume of the current channel by one ) ~ raises the volume of the current channel by one
_ Portamento to note When specified directly after a note, this command will glide to the next note. Note: the note to be glided to must not have a duration macro after it Ex. c4_e glides from c to e in a quarter note
< > Decrement/Increment octave, respectively. Where > increments the octave and < decrements it Use these instead of o when you want to change the octave up or down by a value of one.
. Dotted note macro Add half (of a note's duration) to a note's duration Ex. c4. A dotted quarter c note []# Loop macro, loops the macros inside the brackets The macros to be looped go inside the brackets and # is the number of times to loop them. Ex. [c4]3 ~ Plays c quarter note 3 times and exits the loop / Break a loop on the last iteration This macro goes inside the brackets with the rest of the macros Ex. [c4 / d4]4 ~ Plays c quarter note four times, but d quarter only 3 times
; Line comment Use this to comment on a single line
/* */ Block comment Use this to make a comment that extends multiple lines or to make single line comments look nicer
chan Specify the channel Where chan is the corresponding letter for the channel. This macro must always be at the beginning of a line in which you intend to coerce any digital farts out of your poor x68k (or emulator). Ex. A ~ This sets the current channel to channel A
D# Detune current voice Where # is the value to detune by in 1/64 semitones
k# Delay macro Where # is the number of ticks to delay by
L Set loop start Use this command in a channel when you wish to loop everything after this command
l[length] Set the default note length. Where length is the numerical value of the length in powers of two (ex. l4 sets default note length to quarter notes). When a note is specified without a length after, the note will default to this length. If this command is not set, the default length is set to 4, a.k.a. a quarter note
MPwaveform,speed,depth Set pitch LFO Where waveform is the LFO waveform (0 = sawtooth, 1 = square, 2 = triangle), speed is 1/4 of the LFO cycle in ticks, and depth is the max amplitude of the LFO. Useful for vibrato. MPON Turn pitch LFO on for current channel, only needed if you have turned the pitch LFO off (setting the LFO automatically turns it on). MPOF Turn pitch LFO off for current channel. Only needed when it is already on.
n#,length Play a note by its numerical value, with the length separated by a comma. "length" is the length of the note in eights. See the next entry for proper lengths. Ex. n21,8 Play note 21 as an eigth note
note[accidental][length] Play a note with the desired length. Where "note" is the letter of the musical note you want to play (a-g), "accidental" is the desired accidental (+ for sharp and - for flat), and "length" is the length of the note in eights. For the note lengths, you can use any standard note length: 1 - whole note 2 - half note 4 - quarter note 8 - eighth note 16 - sixteenth note 32 - thirty-second note Any length not a power of 2 or > 32 is not supported and will cause your compiler to question your sanity. When a length is not specified, the compiler will default to the default length, which is by default a quarter note unless you specified otherwise. Unless you specified the default length as something like 33, which will mean that your compiler will complain that DE fault was yours...by default. :-P Ex. c4 - play the note c as a quarter note Ex. e-8 - play the note e flat as an eighth note Ex. c - play the note c with whatever the default note length is
o# Set the octave. Where # is the desired octave (0 - 9)
q# Note cutoff (stacatto) Sets note duration (in eights) of cutoff. Range is 1 - 8 inclusive.
t# Set the tempo Where # = the number of quarter notes per second Ex. t180
v# Set the coarse volume, where # is a number between 0 and 15
MXDRV MML Macros and Syntax
The following macros are MXDRV specific:
#PCMFILE "somefile.pdx" Includes a PDX pcmfile, for pcm audio This file will need to be in the same directory as your mdx when you want to listen to your compiled code (with pcm samples) Ex. #pcmfile "GR-PCM.pdx"
@#={ AR, DR, SR, RR, SL, OL, KS, ML, DT1, DT2, AME, AR, DR, SR, RR, SL, OL, KS, ML, DT1, DT2, AME, AR, DR, SR, RR, SL, OL, KS, ML, DT1, DT2, AME, AR, DR, SR, RR, SL, OL, KS, ML, DT1, DT2, AME, CON, FL, OP } Voice Definition macro As the YM2151 is a four operator FM chip, in order to define the voices, you must define each operator, and the voice's parameters. Two things here: 1. I'm assuming you know a bit about synthesis and envelopes here, and 2. I'm not an expert on FM Synthesis :-P, but I will tell you what I know AR = Attack Rate. How quickly you want the operator to reach full amplitude. DR = Decay Rate. How quickly you want the operator to reach the sustain. SR = Sustain Rate. How quickly you want the operator to reach the release after a note off. RR = Release Rate. How quickly you want the amplitude to reach zero after a note off. SL = Sustain Level. The amplitude of the operator during sustain. OL = ? KS = Key sync ML = Phase multiplicity DT1 = Detune in Hz from base note * ML DT2 = Detune in semitones AME = Enable amplitude modulation for current operator. Setting this value to a 1 will enable the amplitude modulation for the op and 0 will disable it. CON = FM synthesis connection/algorithm, determines how the operators are routed. You would want to play with VOPM to figure these out. FL = Feedback level, setting this to higher values distorts the voice OP = ? I always see this value set to 15, so I don't know what it does Here's an example bass voice: @2={ /* AR DR SR RR SL OL KS ML DT1 DT2 AME */ 31, 14, 0, 15, 4, 13, 0, 1, 0, 0, 0, 31, 9, 0, 10, 1, 0, 0, 4, 0, 0, 0, 31, 9, 0, 10, 1, 0, 0, 1, 0, 0, 0, 31, 9, 0, 10, 1, 0, 0, 1, 0, 0, 0, /* CON FL OP */ 5, 4, 15 } It will be easier for you to rip voices from other tunes or make them in VOPM than to program them on the fly. See the resources for my program opm2mml which will automatically convert MiOPMdrv (.opm) patches to MML for you.
@t# Set the value of OPM register B, consequently setting the tempo This is different from the t command, which is what you'd want to use normally. 0 < # < 255
@v# Set fine volume (for a single channel) 0 < # < 255 This allows more precise control over the volume. For effects like fade-ins or fade outs, you can use coarse volume instead (unless you find pain pleasurable)
A-H, P-W Set channel This macro must always appear at the very beginning of a line in which you intend to sequence notes and macros. The exceptions are voice definitions, comments, and metadata definitions. Ex. A sets channel to A (FM channel 1) Ex. P Sets channel to P (PCM channel 1)
F# Change PCM frequency (pitch) Range is 0-4 inclusive, default is 4 0 = 3.9kHz 1 = 5.2kHz 2 = 7.8kHz 3 = 10.4kHz 4 = 15.6kHz This changes the frequency of the ADPCM samples being played back. Really wish that the OKI had note sample pitching instead of this, but nope, it would have to be done through software, and MXDRV doesn't have an implementation for this. (One of the things on my bucket list is to make a chiptracker for the x68k which allows pitched samples)
MAwaveform,speed,amplitude Set amplitude LFO Where waveform is the LFO waveform (0 = sawtooth, 1 = square, 2 = triangle), speed is 1/4 of the LFO cycle in ticks, and amplitude is the max amplitude of the LFO. MAON Turn amplitude LFO on for current channel, only needed if you have turned the amplitude LFO off (setting the LFO automatically turns it on). MAOF Turn amplitude LFO off for current channel. Only needed when it is already on.
MD# Set the delay from note on to LFO start(excluding OPM LFO) Where # is the delay in ticks
MH#1,#2,#3,#4,#5,#6,#7 Set OPM LFO values #1 = LFO Waveform (0 = sawtooth, 1 = square, 2 = triangle) #2 = LFRQ #3 = PMD #4 = AMD #5 = PMS #6 = AMS #7 = Key sync (0 = no sync, 1 = sync) MHON Turn OPM LFO on for current channel (setting OPM LFO automatically turns it on) MHOF Turn OPM LFO off for current channel.
p# Set (hard) panning position 0 = no output, 1 = left, 2 = right, 3 = center
@q# Note cutoff (stacatto) in ticks Set the cutoff of a note, with duration in ticks.
S# Sync send macro Continue playback on channel if it is in sync wait mode
y[reg],[val] Write OPM register reg with value val
w# Set OPM Noise frequency
W Sync wait macro Set current channel in sync wait mode, pausing playback of the channel
Short Tutorial
So, now that you know all of the macros used in MXDRV mml, you need to know how to correctly use them to make an MDX tune.
Here is a short sample MML source code:
#title "Darude - Sandstorm" ;song name? #pcmfile "SampleText.pdx" ;below is the instrument 0 definition @0={ /* AR DR SR RR SL OL KS ML DT1 DT2 AME */ 31, 14, 0, 15, 4, 13, 0, 1, 0, 0, 0, 31, 9, 0, 10, 1, 0, 0, 4, 0, 0, 0, 31, 9, 0, 10, 1, 0, 0, 1, 0, 0, 0, 31, 9, 0, 10, 1, 0, 0, 1, 0, 0, 0, /* CON FL OP */ 5, 4, 15 } A t140 v8 o4 @0 L c4 c4 e8 e8 e-4
So here, I first set the title of the song to “Darude - Sandstorm”, using the title macro. I then specified the PCM file as “SampleText.pdx”, then defined instrument 0's FM parameters. Then on channel A, I set the song tempo to 140, set the channel volume to 8 (max volume), set the octave to 4, the instrument to 0. I then set the rest of the following code to loop, and played the notes c-quarter, c-quarter, e-eigth, e-eigth, and e-flat-quarter. When compiled into MDX and played back, it should play those notes a few times in a loop before stopping.
You can put spaces between some (but not all) macros to make your MML source code cleaner and more readable. I should have told you which ones you can and cannot in the documentation.
With the documentation on all the commands, this should show you how to code your MML tune.
Compiling Your Tune
So now that I've included a short sample tune (nothing special, just random notes), now you need to know how to compile it.
If you have all the required tools, you will need the following for compilation: 1. A Sharp x68000 emulator - run68k is easy as it emulates human68k, although you could use a full Sharp x68k emulator 2. A Sharp x68k MDX compiler - mxc.x from MDX_TOOL is the one I use 3. Your MML source code (go figure) as a .mml plain text file
From the command line, to compile your .mml tune to MDX, run the following command:
run68 \directory\for\MDX_TOOL\mxc \tune\location\songname.mml
In a full Sharp x68k emulator or real x68k environment, you can run mxc.x directly:
mxc songname.mml
If your code is syntactically correct, you should have a resulting .mdx file in the directory where your source was.
Making a PDX File
To make a PDX, you first need to get some raw ADPCM files (.pcm extension).
You can either rip them from games with ADPCM chips, or convert wav files to the format with WAV2ADP (link in tools section).
To convert a wav to PCM, run the following in cmd or human68k:
wav2adp \directory\to\dubstep\somewav.wav
If you're using run68k, then just put “run68” at the beginning.
After you've got an ADPCM or two, you'll need to put all your pcm's into a PDX with mkpdx (link in tools as well). But first, you'll need to make a PDL file mapping all of the PCMs to the desired note values.
A PDL file is just a plain text file.
Example PDL:
#ex-pdx 1 @0 21=some.pcm 23=some.pcm 31=some.pcm
Here, I specify something important at the beginning: I am using ex-pdx.
Later after MXDRV was created, the PDX file format was extended so one could switch ADPCM banks for tons of PCM files in a single PDX. A single bank can have a maximum of 90 or so ADPCM binaries.
I then defined which ADPCM bank I want to define with “@0”. Then I set notes 21, 23, and 31 to “some.pcm”.
After you finish your PDL file, you'll need to make your PDX. Run the following in CMD (or just drag and drop your pdx on mkpdx): mkpdx \directory\to\mypdl.pdl
The mkpdx binary I provided is for Win32, so you don't need to use DOSBox for it.
If your PDL file is syntactically correct, then mkpdx will spit out a PDX file in the same directory as your PDL.
Now you can use your PDX in your MML tunes by defining the following at the top:
#pcmfile "mypdx.pdx"<file> To use PCM in a MML tune, use channels P-W. It's easier to use the numerical note values for PCM than it is to use letter notes. Ex. <file>P v8 n21,8 n21,8 ;plays pcm at note 21 with eighth note duration twice