The Music Maker Project (MMP) is a Domain-Specific Language (DSL) that allows you to quickly create basic sound effects and export them as WAV files.
The objective of this DSL is to enable software developers that have negligible/very basic knowledge of music to create basic sound effects for use in small-scale software projects (such as a simple quiz game).
MMP is implemented using a modular, event-based approach and relies on the JavaScript's native Web Audio API standard for producing and recording sounds. This is an immensively powerful, ever-evolving standard and provides plently of opportunity for future extensibility/devlopment of this project.
The DSL consists of 3 major blocks:
- Sound
- Combination
- Play
The sound block describes individual audio tracks to be used for creating your sound effect.
There are 2 types of sound blocks:
- Preset
- Clip
Preset sound blocks represent the use of an exisiting sound effect.
Sound Kick1 as Preset
Pattern: x-xx-x
Repeat: 1
UseSound: "Kick"
EndSound
You specify which sound effect you want to use in the UseSound
attribute. Currently, you can choose from Kick, Bass, OpenHats, ClosedHats & Snare.
Clip sound blocks represent the use of a sequence of musical notes.
Sound MyMelody as Clip
Pattern: x
Repeat: 2
UseSound: "C1 D2 F7"
EndSound
You specify the sequence of notes (with octaves) in the UseSound
attribute as shown in the example sound block, named 'MyMelody', above.
In both types of sound blocks, you must also specify Pattern
& Repeat
.
Pattern
is denoted by a series of 'x' and '-'.
x means that the sound specified in UseSound
should be played and '-' represents a pause of (approximately) 0.5 seconds.
Repeat
denotes how many times you wish to repeat the pattern.
This block specifies how you would like to sequence the sounds you defined earlier.
Combination Draft1
Track
Volume: 75
Components: [5*Kick1, 1*MyMelody]
EndTrack
Track
Offset: 100
Volume: 25
Components: [2*MyMelody]
EndTrack
EndCombination
The two main parts of a Combination are the Track
and Components
.
As is illustrated by the way the DSL is strucuted, all Tracks in a combination are played in parallel.
In a Track, you specify:
- Volume - loudness of the track.
- Offset - start time delay in milliseconds
and
- Components
Components
represents the sounds that a track should play.
The sounds specified in the components
section are played in sequence (one after the other) for each track.
To help you ideate/draft your sound effect, you are allowed to create multiple combination blocks in your code. However, only one of them will played/rendered upon executuion.
The Play
block is used to specify which combination block you would like to be played in the current execution.
Play Draft1
Sound Kick1 as Preset
Pattern: x-xx-x
Repeat: 1
UseSound: "Kick"
EndSound
Sound Melody1 as Clip
Pattern: x
Repeat: 2
UseSound: "C1 D2 F7"
EndSound
Combination Draft1
Track
Volume: 75
Components: [5*Kick1, 1*Melody1]
EndTrack
Track
Offset: 100
Volume: 25
Components: [2*Melody1]
EndTrack
EndCombination
Play Draft1
program : sound+ combination+ play
sound : 'Sound ' soundname 'as ' SUBTYPE pattern repeat usesound 'EndSound'
soundname : TEXT
pattern : 'Pattern:' TEXT
repeat : 'Repeat:' NUM
usesound : 'UseSound:' USESOUNDS '"'
combination : 'Components:' TEXT track+ 'EndCombination'
track : 'Track' offset? volume? components* 'EndTrack'
offset : 'Offset:' NUM
volume : 'Volume:' NUM
components : 'Components:' '[' component [','component]* ']'
component : NUM? '*' COMPONENT_NAME
play : 'Play' TEXT
TEXT : ~[[\]\r\n ]+
SUBTYPE : 'Preset' | 'Clip';
NUM : [0-9]+
USESOUNDS : ~[[\]'"]+
COMPONENT_NAME : ~[[\]\r\n,* ]+
In addition to the grammar rules above, a few logical rules are in place in order for the DSL to run properly:
-
The
pattern
must be a string consisting of any combination of only characters "x" and "-" and no other characters, where an "x" means to play a note, where as "-" means rest (don't play a note) - TEXT in each
component
must match asoundname
created by you -
If a
sound
hasSUBTYPE
"Clip",USESOUNDS
must be a single line of text, with each note following the pattern of {note}{octave} with a space between each note(e.g. "C2 G9") -
If a
sound
hasSUBTYPE
"Preset", then theUSESOUNDS
must match exactly with any one of the following sound names provided: "Kick", "Base", "Snare", "OpenHats", or "ClosedHats" - The indentation level on each line does not affect the success/failure of running the DSL.