Ramekin
Ramekin is a pre-processor for AddMusicK syntax that is in very early development.
Please keep in mind that as alpha software, I may make breaking changes at any time. After initial testing is done, I will release 1.0.0, at which point I will make a reasonable commitment to back-compatibility. That time is not yet.
For a preview of what full Ramekin tracks look like, feel free to check out the examples repo.
Installation
First, Install Ruby. Windows users can use RubyInstaller.
With Rubygems
Run:
$ gem install ramekin
Then:
# sets up everything automatically
$ ramekin setup
# OR, if you want a la carte:
$ ramekin setup --packs # downloads packs from smwc
$ ramekin setup --amk # downloads and sets up AddmusicK
$ ramekin setup --spc # downloads and sets up an SPC player
Manual Installation
- Install Ruby. Windows users can use RubyInstaller.
- Download the script.
- Install the scripts:
- For Windows users, put both
ramekinandramekin.batin%LOCALAPPDATA\Microsoft\WindowsApps\. - For MacOS and Linux users, ignore
ramekin.bat- make the script executable withchmod +xand put it somewhere on your PATH.
- For Windows users, put both
- Run
ramekin setupto set up dependencies and download sample packs. You will need about 90M of free space.
Usage
usage: ramekin [--pack NAME=PATH] [command] [flags]
(default command: compile)
ramekin --pack my_cool_pack=/path/to/my_cool_pack [...]
Specifies an additional custom sample location.
Files compiled this way should use #pack "my_cool_pack",
and sample paths relative to the deepest common path that
contains .brr files. Use with `pack --list my_cool_pack` to
see details.
ramekin compile -i filename.rmk [flags]
ramekin compile filename.rmk [flags]
ramekin filename.rmk [flags]
flags:
-h --help
display this message
-i filename.rmk
set the input file
--txt filename.txt
output amk txt to this file.
use a single dash (-) to print txt to stdout.
--spc filename.spc
attempt to invoke AddmusicK to output an SPC.
--play
play the generated SPC file. will automatically
set up an SPC player if none is detected.
--package my-cool-folder/
create a package directory suitable for submission
to SMWC, complete with packaged samples.
--wav filename.wav
--wav filename.wav:N
render N seconds of the file to WAV.
(non-windows only - windows users should use --play
and render from the SPCPlay program)
--vis filename.png
outputs AddmusicK's ARAM visualization to a specified file
ramekin pack [flags]
flags:
--update
download BRR packs from SMW Central.
--search [text]
search for BRR filenames.
--list [text]
list all samples in packs matching [text].
--list-smw
list the builtin instruments from SMW that can be used
without a pack.
ramekin setup [flags]
flags:
--amk
downloads and sets up AddMusicK and asar.
(requires cmake make to be available on mac/linux)
--packs
downloads BRR packs from SMW Central.
(equivalent to pack --update)
--spc
downloads and sets up a default SPC player.
(requires make and pkg-config to be available on mac/linux)
--all (default)
runs all of the above setup steps
--force
deletes and redownloads files instead of skipping.
Configuration
The first time ramekin runs, it will create a configuration file in ~/.ramekin/config.yml (where ~ is your home directory). Edit this file with your favourite text editor, and be sure to remove the # from the start of lines you want to take effect. If you want Ramekin to keep its files in some other place, override the RAMEKIN_HOME environment variable.
If you already know AddmusicK
A list of some ramekin preprocessor features (see spec/rmk for some examples!):
- The metadata section (before any channels) is fairly different, I recommend reading the metadata part of the guide below.
- Macros ("replacements") are implemented in a much more robust way (with tokenization), and can no longer interrupt other tokens. The generated txt will not contain any replacements.
- Loops can be given arbitrary names using any combination of letters, numbers, underscores, or dashes.
(my-cool-loop)[ ... ]is valid syntax. These are case sensitive, and are assigned numbers when compiled to AddmusicK syntax. - Adopted the transposition syntax
_+N,_-N, and_0from General MML. Compiles to$fa$02$XX. #adsr:A,D,S,RRsyntax for ADSR. Also usable on an#instrumentdeclaration, with the same syntax. A, D, and R are flipped so that higher numbers are longer times.v+Xandv-Xare volumes relative to the lastvXXXcommand. Useful for separating expression from mixing.yLXandyRXcommands for panning left and right.yCto set back to center. Way easier for me to remember.- The implementation of
&is more robust, and it compiles to a proper$ddcommand. It can also much more flexibly chain multiple bends together, using a non-breaking tie^^Xto establish where the boundaries of the bend should be, and handles quite a few idiosyncracies of$ddautomatically behind the scenes. You should be able to use&and^^for all pitch bending needs. See "Pitch Expression" below for details.elisp ; bends to c two octaves up for two 16th notes, then continues for a quarter note. ; note the ties don't affect the bend, and a special tie ^^ is used to mark the true ; start of the bend. b8 ^^ b16^16 & >>c4 - Instruments are named rather than numbered. See
doc/smw-instruments.rmkfor a list. - Switching instruments always sets that instrument's default octave, by default
o4. It does not reset transposition (you can use_0for that). - Samples are loaded directly from SMWCentral using
#packsyntax:
; references the BRR pack "Chrono Trigger" from SMW Central
#pack "Chrono Trigger"
; declares an instrument @kick with tuning parameters parsed from the BRR pack
#instrument @kick "Kick"
; parameters and default octave can be overridden
#instrument @crash "Crash Cymbal" o4 #tuning:1FBC #adsr:0,0,7,1F
In ramekin, there is no difference between instrument
#adsrsyntax and the one in the pattern data. They are both compiled to their respective syntaxes in the txt.Tempo can alternately be declared with
#bpm:128. This will be converted to the nearesttXXcommand. If the tempo is overt60(#bpm:146), the tempo and all note and event lengths will be halved automatically. This is similar to#halvetempoexcept that it is done automatically.p0,0compiles to$df."Legato tie" represented by
~, which will use$f4$01at appropriate times to cause the note transition to be played legato.#legato/togglecan be used for a raw$f4$01, and#sustain/global-togglefor$f4$02.If you ever want to see what exactly Ramekin is generating, just use
--txtand you can inspect the generated AddmusicK syntax manually!
Syntax
Ramekin syntax is very similar to AddmusicK syntax. Comments begin with ; and span to the end of the line, and most commands are either single characters, or directives marked with #.
Metadata / preamble
The top of a Ramekin file, before the first channel is declared, is the preamble. Here, various commands can be used, starting with #.
Metadata commands
These commands set important metadata headers for the SPC.
#title "My cool songle"
#game "title of the game, if any"
#author "my name"
#comment "usually something about who ported the track"
Additionally, you can specify additional #readme text to be included in the packaged song:
#readme "
Here is some very important information about running this track.
"
Finally, some general options can be set:
; causes the track not to speed up when the timer is low
#option TempoImmunity
; sets the global volume, 0-255.
; Try to aim for -21 to -19 lufs to balance well with sound effects.
w150
; sets the bpm. (todo: mention the reasonable range for this)
#bpm:130
Instrument definitions
Default Instruments
Ramekin can use the #default and #optimized native sample groups for SMW. One of these directives must be included for sound effects to work properly in the game. Using native SMW instruments is the easiest way to get started quickly.
The #default sample group is implied if nothing else is specified, but you can use #optimized if you are running low on ARAM (more on that later).
To see the full list of available native instruments, see doc/smw-instruments.rmk
Sample Packs
To get more diverse sounds on the SNES, it is often nice to use samples, either ripped from other games or converted to BRR (the SNES's native sample format).
Ramekin allows you to extremely easily use BRR packs from SMW Central's repositories. These not only contain BRR samples, but also the tuning and ADSR data to make them sound great by default.
To load a pack from SMW Central, use #pack with the pack's name on SMW Central. For example, let's say I wanted to use samples from Chrono Trigger. I can search that with:
ramekin pack --list chrono
This will show us a pack named "Chrono Trigger" along with a bunch of files with a .brr extension. To use the pack, add:
#pack "Chrono Trigger"
Then, to load, say, the sitar from the pack, we use:
#instrument @sitar "Sitar.brr"
This defines a new instrument called @sitar to point to Sitar.brr with the default settings. You can also leave off the ".brr" extension if you like. Later, you can use the command @sitar to switch to this instrument.
After the instrument declaration, you can use several commands to change the default settings, such as #adsr, #tuning and o:
#instrument @sitar #adsr:0,4,2,23 #tuning:1a2f o5
It is generally advised to stick with the default tuning. The o5 declaration sets the default octave for the instrument to octave 5 (the default is 4). Whenever this instrument is selected, Ramekin will insert a switch to the specified octave.
Echo settings
Echo settings can be set up with the #echo/... family of directives:
; select which channels have echo enabled
#echo/channels:0,1,2,3
; or
#echo/channels:all
; or
#echo/channels:none
#echo/volume:20 ; range from -80 to 7f, use negatives for surround
#echo/volume:20,30 ; set different values for left vs right echo
#echo/feedback:48 ; range from -80 to 7f, use negatives for surround
#echo/fir:1 ; 1 or 0 to enable/disable the FIR filter
; later, you can use this to toggle the echo on a channel.
#echo/toggle
Channel Commands
With your metadata all set up, it's time to add some notes!
SNES audio is organized into 8 channels, numbered 0-7. But in the context of a romhack, channels 6 and 7 are reserved for sound effects.
This is the biggest limitation of romhack music: You must generally arrange your music to fit on 6 channels. Each channel can only play one note at a time - for chords, you must use multiple channels. However, channels can switch instruments extremely quickly - so things can be interleaved if you are clever with instrument switches.
Notes
To start adding notes to a channel, use #N, where N is the channel number:
#0
; now we're in channel 0!
Next, switch to an instrument, and add some notes:
#0
@smwacousticbass
o3
c8d8e8f8
this plays 8th notes c, d, e, and f in octave 3 on the instrument @smwacousticbass.
For sharps and flats, use + and -, and for rests, use the special note r:
#0 @smwacousticbass o5
d8 e-8 f+8 g8 r2
This plays d, e-flat, f-sharp, g in 8th notes, followed by a half-note rest. To convert this to an spc, save this to a file named my-cool-song.rmk, and run
ramekin my-cool-song.rmk --spc my-cool-song.spc
This will create a file called my-cool-song.spc, which you can open with an SPC player. Notice that it loops to the beginning by default! The default behaviour of the AddMusicK/smw music system is to loop as soon as the first defined channel runs out of notes.
To set the loop point somewhere that is not the beginning, use the / command:
; will return to the / when it hits the loop point
#0 @smwacousticbass o5
d8 e-8 / f+8 g8 r2
For more complex note lengths, dots and ties are available. For example, b8. plays a b for a dotted eigth note length. This is equivalent to b8^16, which plays for an 8th note tied to a 16th note.
Because it is common to play a bunch of fast notes all the same length, the l command allows setting a default length to use when no note length is specified. So our example from before is equivalent to:
#0 @smwacousticbass o5
l8 de-f+g r2
Personally, I tend to use l16 across the whole track for consistency.
Loops and loop calls
Just as in Addmusick, there are two kinds of loops:
- Regular loops, marked with
[ ], which can optionally be tagged with a name, as in(my-cool-loop)[ ]. These can not only loop immediately but also be called at arbitrary points. - Super loops, marked with
[[ ]], which can only loop immediately, but can nest either inside or outside of regular loops.
This is best shown with an example:
#0 @smwacousticbass l16
[ defg ]4 ; plays defg four times (regular loop)
[[ abcd ]]4 ; plays abcd four times (superloop)
* ; calls the last defined regular loop, in this case plays defg
*3 ; same thing but 3 times
(blungus)[ fedc ] ; defines a loop named (blungus), also plays fedc immediately
(blungus) ; calls the loop (blungus)
(blungus)2 ; calls the loop (blungus) twice
Expression and effects
Volume Expression
Volume can be set with vXXX, where XXX is a number between 0 and 255. This command also sets the current "reference volume", which can be referenced with commands v+XX and v-XX, where XX is a number to be added or subtracted to the reference volume. This way, you can add dynamics to your drums or melody lines, while also easily being able to change the overall volume of the section.
Pitch Expression
Pitch expression can be accomplished in two ways:
pA,B,C, where A,B, and C are numbers, can be used to set vibrato - a slight pitch wiggle that starts sometime after a note is started.Aspecifies the delay - how long to wait before wiggling the pitch,Bspecifies the speed - how fast to wiggle the pitch, andCspecifies the amplitude - how much to wiggle the pitch. Turn off vibrato withp0,0.- Manual pitch bends are fairly straightforward in ramekin, using
&and^^:
; bend b8 and then hold on c for the rest of the bar
b8 & >c4.^2
; multiple bends can be safely strung together
b8 & >c8 & d2
; to hold on a note and then do further bends, use a non-breaking tie ^^.
; this will hold steady on c, and then bend for an eighth note to the e.
b8 & c8^4 ^^8 & e8
; to bend at the very end, use a zero-length note.
; this falls to g and then stops.
c4 & <g0
Panning Expression
Panning can be specified with the command yLX or yRX, where X is a number from 1-10. To reset panning to the center, use yC:
yR10 ; maximum pan right
yR2 ; tasteful pan right
yC ; pan center
yL2 ; tasteful pan left
yl10 ; maximum pan left
Legato and quantization
To play notes in sequence without re-starting the note from the beginning, you can use a "legato tie", represented by ~:
a4~b4~>c4
This works by inserting AddmusicK's "legato toggle" command at appropriate times. To insert this toggle manually, use #legato/toggle - but be careful of using this command inside loops, as it can sometimes be ignored by AddmusicK, leaving you with settings that leave the toggle in an inconsistent state. Legato ties should always be safe inside loops.
To activate "sustain" mode, where notes are rekeyed but there is far less space between notes, use #sustain/global-toggle. AddmusicK will apply this setting to all channels at once. Again, this is a toggle, so be careful of activating this more than once unintentionally.
To activate staccato for a channel, you can change the "quantization" (i.e. how long notes hold compared to their length) with qX, where X is a number 0-7. q7 results in the longest held notes, and q0 in the shortest. If you've used qXY in AddmusicK to modify GAIN before, note that Ramekin's syntax requires a comma for parsing consistency: qX,Y.
Hex
For those who want to use AddmusicK features that are not currently supported by Ramekin, Ramekin still supports manual entry of hex values with $XX. While these can be made slightly easier to use with macros, I would very much appreciate it if you could open an issue here or contact me via SMWC or Discord if you find you are using these heavily.
Macros
To make your life easier, Ramekin implements a very similar macro ("replacement") system as AddmusicK - allowing you to define all manner of custom shortcuts for maximum efficiency and tweakability. (Note that Ramekin's implementation of macros is far more robust than AddmusicK's, and will not interrupt other tokens - e.g. a macro called F will not be applied to something like $EF).
A macro looks like this:
"MY_COOL_MACRO=@smwacousticbass o3 v150"
Now whenever you type MY_COOL_MACRO in a channel, it will be as if you typed @smwacousticbass o3 v150. This can be used to define all sorts of helpers, including some dynamics helpers:
"F=v+0" ; forte
"M=v-20" ; mezzo
"P=v-40" ; piano
Or drum instrument helpers:
"K=@smwkick o4"
"S=@smwsnare o4"
"H=@smwshaker o4"
Or anything else you might find helpful.
Custom Samples
If you have your own BRR-format samples that you'd like to use, Ramekin supports loading these through custom packs, specified on the CLI. First, organize your samples into a directory, with an optional !patterns.txt or tunings.txt file, much as may be found on SMW Central's BRR repository. In the simplest case, this is just a directory with .brr files in it.
Then, when running ramekin, use:
$ ramekin --pack 'my cool pack=/path/to/my_cool_pack' [the rest of the ramekin command]
where /path/to/my_cool_pack is replaced with a relative path to your BRR files directory. Your ramekin files can then freely use #pack "my cool pack", and conjure up instruments from the pack. If no tuning file is specified, you may need to use #tuning:XXXX to specify a tuning, as the default tuning of 0000 is unlikely to be audible.
If Ramekin is having trouble finding your BRR files, try:
$ ramekin --pack 'my cool pack=/path/to/my_cool_pack' pack --list 'my cool pack'
which will display the paths it expects you to use for each BRR sample it found.
Thank you for trying out Ramekin!
If you find any bugs, please report them in the issue tracker here on Codeberg. If you have questions, design ideas, or complaints, or just want to chat, please feel free to ask anything in my discord. Cheers!