mkmod -- a .mod (soundtracker) compiler & utilities --------------------------------------------------- Roger Espel Llima These are 3 utilities needed to create and play with .mod files: . modexpl, to explode existing .mods into separate files, one for each sample and one for the decompiled module. . convt, to convert samples between different formats, and change information in the sample headers. . mkmod, to take a text definition of a song, as well as a number of sample files, and make the .mod. They are all written in perl, and require perl version 5. If you have perl 4 only, you really should upgrade anyway. These programs are all covered by the GNU General Public License; see the file LICENSE for copying details. * modexpl --------- modexpl understands new-type as well as old-type modules (i.e., 15 or 31 samples), and can also read 6-channel and 8-channel modules. By default, it takes the filename of a .mod as its only argument, prints some information about it, asks for a directory name in which to store the samples, prompts for each of the samples what file to store it in, and prompts for the filename of the decompiled module. The extension .aiff is added to sample filenames, and .mdf to the decompiled module. Samples are saved by default in the AIFF instrument format, which includes looping and volume information. mkmod also reads AIFF samples. To facilitate exchanges with other MOD editors, modexpl can also save the sample in a 'raw' format (i.e., just the sample itself), with or without the 30-byte header that samples have inside the .mod. However, it is much better to use AIFF files, since it conveniently holds all the information related to a given sample in a straightforward, standard format. Use: modexpl [options] file.mod recognized options: -l -- list the samples and print the info, but doesn't prompt for anything or create any files -d -- decompile only: list samples, print out info and make a .mdf without extracting the samples -old -- read the .mod as an old-format (15 samples) .mod file -new -- read the .mod as a new-format (31 samples) .mod file (modexpl auto-detects the format by default) -raw -- save the samples in raw format (no header) -hraw -- save the samples in raw format with a 30-byte header * convt ------- convt takes a sample in AIFF format or in raw format (with or without a header) and converts it to either of these 3 formats. It can also be useful to change information in a sample. The format of the input sample is detected automatically. use: convt [options] sample-file > new-sample-file recognized options: -n "name" -- set new instrument name -v volume -- set new default volume (0 to 64) -f finetune -- set new finetune (0 to 15) -l offs len -- set new loop params (offset and length in 2-byte words) -raw -- output a raw 8-bit sample (no header) -hraw -- output a raw 8-bit sample with 30-byte header -aiff -- output an AIFF sample (default) * mkmod ------- mkmod it takes a module definition file (.mdf), which references a number of sample files, and creates a playable module file (.mod). To run it: mkmod file.mdf > file.mod To create your own .mdf files, you first need to understand some of the .mod format : A .mod is made of a number of samples (up to 31, numbered from 1), each representing an instrument, and a number of sections (up to 128, numbered from 0). There are (normally) 4 channels, which means that up to 4 samples can be played simultaneously. There exist extensions to the .mod format that add 2 or 4 extra channels, and mknod can create them too. The basic unit of time in a .mod is the tick; there are normally 50 ticks per second, although the rate can be adjusted. .mod events occur every n ticks, where n is called the tempo. The default tempo is 6. Each .mod event takes the form of: for each channel, either load a new sample or not, specify a new note (frequency) or not, and do an effect or not. It is important to understand that there can be only one effect at each tempo beat on each channel, there isn't room in the encoding for more. -- layout of a .mdf source: See the the file blah.mdf for an example. The layout is mostly free-form: newlines and space are equivalent, and whitespace around {}[] is not required. Anything after a # is considered a comment, and the rest of the line is ignored. White space between different commands, notes, etc. *is* required. Anything between ""'s on the same line will be considered a single word. * The .mod format includes a 22-char long song name, which you can specify with the optional directive songname The default songname is "untitled". * To specify the number of channels (4 by default), you use a declaration like this: channels Possible values are 4, 6 and 8. * To import each of the samples, you use a number of declarations like these: sample { path/to/sample-file volume finetune loop name } The order of the sample definitions in the .mdf is not important, but you must import all the samples a section uses before defining the section. It's probably best to import all samples before defining any sections. Samples can be read in either of the 3 formats convt understands. In a sample import block, the volume, finetune and loop values are optional, and supercede the default values that come with the sample itself. Note that playing a .mod triggers each specified sample at its default volume unless it comes with a [volume] effect, so getting the right default volumes is quite important. The is necessary, and gives this sample a name by which it will be referred to inside this .mdf. This name does not appear on the resulting .mod. It must be only one word. The line is optional, and gives the name for the sample that will appear in the .mod, superceding the same information in the sample file. Put the name between ""'s if it's more than one word. To specify the order in which the sections will be played, you use the 'order' declaration: order { ... } Section names are given arbitrarily, and are (like sample names) case sensitive. The 'order' declaration must come before the definitions of any sections. Sections not appearing in the order will be compiled to check for errors, but will not be included in the .mod. To define a section you use a declaration like this: section { { } { } { } { } { } ... } For each of the channels, you can define at most 64 events. If this is too short, cut it in more sections. Channels will be padded to the longest of the 4 (or 6 or 8), and a 'go to next section' effect is added automatically for sections shorter than 64. Of the channels, the first /2 are assigned to the left stereo channel and the rest to the right. Inside a , mkmod understands a few directives: sample tells that the next notes will be triggered with that sample (given by its name1). There is no default, you need to specify a sample before entering any notes. . generates an empty event: at the next tempo beat, the previous sample continues if there was one, or the channel remains silent. Effects can be used on a '.' and affect the note that is being played. , generates an event with a sample but no note. This sets the volume to the sample's default, without interrupting the playback of the current sample, and leaving the effect slot free (typically for a volume slide). ticks tells mkmod to automatically insert empty events after each note. used for slow melodies; when an instrument is playing a melody that is 4 times slower than the fastest beat division you need to use (the tempo), it's easier to write "ticks 4" once than to follow each note with 3 .'s. Note that the 'ticks' value affects '.' and ',' too. Notes are given by their name (a through g), optionally followed by an octave number (1, 2 or 3, defaults to the same as the previous note, and 2 for the first), and optionally followed by a 's' to make them sharp, or a 'b' or 'f' to make them flat. Each note on a channel will be triggered with the same volume as the previous note (taking effects into account), unless you're using a different sample, in which case the default volume is that of the sample. You can force the sample to be specified even if it's the same, which sets the volume to the sample's default without using the effect slot. Effects are given between []'s and apply to the event that immediately follows them. If the first word inside the []'s is 'sticky', then the effect will be remembered and applied to each note on that channel until the next []. The format for an effect is: [ ] The effect name is one of: arpeggio, portamento-up, portamento-down, tone-portamento, vibrato, tone-portament-volume-slide, vibrato-volume-slide, tremolo, offset, volume-slide, far-jump, volume, next, small-jump, tempo, filter-on, filter-off, fine-portamento-up, fine-portamento-down, funk-glissando, vibrato-waveform, finetune, mark, loop, tremolo-waveform, retrig, fine-volume-slide-up, fine-volume-slide-down, cut, delay, delay-pattern, invert. with the following abbreviations: arp = arpeggio, port = portamento, dn = down, vibr = vibrato, vol = volume, sl = slide, trem = tremolo, offs = offset, wave = waveform, retr = retrig, inv = invert. Each effect takes either two arguments (between 0 and 15 each) or one (bewteen 0 and 255, or 0 and 15, depending on the effects). as a special case, the "far-jump" effect takes a section name as an argument. * List of effects: arpeggio ranges: n1 and n2 are both from 0 to 15 effect: if n1 and n2 are 0, no effect; otherwise, cycles between the notes , , where n1 and n2 are numbers of half-tones up. portamento-up range: 0 to 255 effect: slide the note pitch up by each tick. each tick, is substracted from the internal note representation, which ranges from 071 (C1) to 856 (B3). portamento-down range: 0 to 255 effect: slide the note pitch down by each tick. each tick, is added to the internal note representation, which ranges from 071 (C1) to 856 (B3). tone-portamento range: 0 to 255 effect: slide the note pitch between the previous one and the one specified in this event, at the rate of each tick. if this event doesn't specify a note but a previous tone-portamento was unfinished, it continues with the new rate (or with the same one if the new rate is 0). note: the exact effect depends on the setting of funk-glissando vibrato range: n1 and n2 are both from 0 to 15, 0 meaning "keep the previous value" effect: the pitch is modulated with a sine, square or rampdown waveform, with resulting pitches in the range [base-pitch - 2*n2 , base-pitch + 2*n2] and repeating every 64/n1 ticks. volume-slide range: n ranges from -15 to 15; 0 means no effect. effect: adds to the volume each tick. tone-portamento-volume-slide range: n ranges from -15 to 15; 0 means no effect effect: does a volume-slide without stopping a running tone-portamento vibrato-volume-slide range: n ranges from -15 to 15; 0 means no effect effect: does a volume-slide without stopping a running vibrato tremolo range: n1 and n2 are both from 0 to 15, 0 meaning "keep the previous value" effect: the volume is modulated with a sine, square or rampdown waveform, with resulting volumes in the range [current-vol - 4*n2 , current-vol + 4*n2] and repeating every 64/n1 ticks. external range: n is from 0 to 255. effect: none; can be used to synchronize with other events such as animations. offset range: n is from 0 to 255. effect: plays the sample starting with an offset of *256 bytes. far-jump effect: jumps to play the given section. volume range: n is from to 64. effect: sets the volume for the channel. next effect: ends the current section. small-jump range: n is from 0 to 63. effect: ends the current section and starts playing the next one, skipping the first tempo beats. tempo range: n is from 0 to 255. effect: if is between 1 and 31, sets ticks per tempo beat and resets the duration of the tick to 1/50 second. if is greater than 31, sets the duration of the tick to be 125/(50 * ) seconds. filter-on effect: turns on the low-pass filter (14kHz) on the Amiga. the filter is off by default. filter-off effect: turns off the low-pass filter on the Amiga. fine-portamento-up range: n is from 0 to 15. effect: slide the pitch up by on the 0th tick of the current beat. fine-portamento-down range: n is from 0 to 15. effect: slide the pitch down by on the 0th tick of the current beat. funk-glissando range: n is from 0 to 15. effect: set funk glissando if n is non-null, clear it if n is 0. while funk glissando is active, tone-portamento will round each pitch to the nearest entire note. vibrato-waveform range: n is from 0 to 7. [not checked for possible future extensions] effect: sets the vibrato waveform, from the following list: 0 sine 1 ramp down 2 square 3 random of (sine, rampdown, square) 4 sine, without retrigger 5 ramp down without retrigger 6 square without retrigger 7 random without retrigger note: without retrigger means that it will not be retriggered from the beginning at the start of each new note. finetune range: n is from -8 to 7. effect: sets the finetune for the current sample. mark effect: sets a mark for looping loop effect: loop to the previously set 'mark' times before playing on. note: loops affect all channels at the same time, but marks are kept separately for each channel, so it is possible (and messy) to interleave loops for complex looping structures. tremolo-waveform range: n is from 0 to 7. [not checked for possible future extensions] effect: sets the tremolo waveform; the values have the same meanings as with vibrato-waveform retrig range: n is from 0 to 15. effect: retriggers the same note on the th tick, the <2*n>th tick, and so on. fine-volume-slide-up range: n is from 0 to 15. effect: slide the volume up by on the 0th tick of the current beat. fine-volume-slide-down range: n is from 0 to 15. effect: slide the volume down by on the 0th tick of the current beat. cut range: n is from 0 to 15. effect: set the volume on the current note to 0 on the th tick. delay range: n is from 0 to 15. effect: delay triggering the note to the th tick. delay-pattern range: n is from 0 to 15. effect: wait for tempo beats before processing new entries. notes: effects are continued during the 'long event'; this effect affects all channels. invert range: n is from 0 to 15. effect: if x is non null, play the current sample's loop upside down (negating the sign of all sample points) at speed . It will only work if the sample's loop is not too big. The speed is based on an internal table.