-
Notifications
You must be signed in to change notification settings - Fork 0
How to Use
Firstly, you would create a JSON structure which encodes all the information required. This JSON object can have the following properties:
-
title
: Title of the music, stored as a string. -
composer
: Composer of the music, stored as a string. -
arranger
: Arranger of the music, stored as a string. -
transcriber
: Transcriber of the music, stored as a string. -
tuning
: A hashtable relating note numbers to their frequency. -
defaultNoteConstructor
: By default,PlayableNote
, but supports any object constructor with thePlayableTone
prototype. -
noteMapping
: An object used as a hashtable to store mappings from characters to note numbers. Iftuning
is omitted, note numberi
corresponds to a note with frequency27.5*Math.pow(2, i/12)
, otherwise the hashtable provided is used to convert note numbers to frequencies. -
volume
: Optional object to use in volume changes in the music.-
characters
: An object with 2 properties,loud
andsoft
. -
mapping
: An object with numerical properties. This maps integers to volume. It is recommended to map to numbers from 0 to 1. It is recommended that the integers used are consecutive and that the mapping is increasing.
-
-
instruments
: An array containing the different types of instruments, as objects. Each object in the array has the following:-
type
: Either "sine", "triangle", "square", "sawtooth" or "custom", or any instrument inInstruments
. If "custom", thewave
property of this instrument should be used to store a return value fromAudioContext.createPeriodicWave()
. -
notes
: A string of notes. This would be explained below.
-
new PlayableMusic({ // construct object
// song data
title: "Tetris Theme A",
composer: "",
arranger: "Hirokazu Tanaka",
transcriber: "",
noteMapping: { // we will use this for now
a: 39,
w: 40,
s: 41,
e: 42,
d: 43,
f: 44,
t: 45,
g: 46,
y: 47,
h: 48,
u: 49,
j: 50,
},
volume: {
characters: {
soft: "*",
loud: "#"
},
mapping: {
"-4": 0.1,
"-3": Math.pow(10, -3/4),
"-2": Math.pow(10, -1/2),
"-1": Math.pow(10, -1/4),
0: 1,
1: Math.pow(10, 1/4),
2: Math.pow(10, 1/2),
3: Math.pow(10, 3/4),
4: 10
},
},
instruments: [{ // an array
type: "sample1", // instrument name
notes: "240(/-[d3,y1,j2,y1,d1,|h3,a+1,d+2,s+1,a+1,|j3,a+1,s+2,d+2,|a+2,h2,h4,|]f3,g1,h2,g1,f1,|d3,f1,d2,s1,a1,|j-3,a1,s2,d2,|a2,h-2,h-4,)"
}]
})
A single note is written as follows:
[note][octave][length]
a ++ 4
This a++4
gives the note and time, which means to play some notes two octaves higher. Of course, notes can be grouped together to form things playing at the same time.
a++4a+4,
This plays two notes an octave apart at the same time, with the same duration of 4 for each.
It is safe to insert random characters between notes, which are not:
- () for BPM
- /[] for modifiers
- , for note groups
- 0123456789. for numbers
- The characters used for volume
I recommend | as a barline (syntactic sugar only, no effect).
Any character can be used for a rest, but I recommend "&".
&12
means rest for 12 ticks.
g++4&2,a++4
means play first note for 4 ticks at time 0, then play second note for 4 ticks at time 2.
As you see, the last thing before the comma tells the interpreter how long to wait until the next frame of music. This allows for polyphonic music to be easily written.
Brackets allow for octave modifiers and time modifiers /[]. Modifiers occur between the / and [ characters. The notes which are modified are within the square brackets: []. Modifiers can be nested.
There are two types of modifiers, time modifiers and octave modifiers.
Time modifier 3: /3[notes]
Every number that represents an amount of time in the square brackets would be divided by 3.
Octave modifier (+2 octaves) /++[notes]
Every note in the square brackets would be played higher by 2 octaves.
Example: /3++-7+[a42,]
divides the numbers inside by 21 (3 times 7), and increments by 2 octaves (++-+), hence, this is equivalent to a++2,
.
Round brackets are required around everything. Do not nest them. Round brackets can be used to input BPM.
This shows a excerpt with 2 sections, one at 240 BPM and one at 140 BPM.
240(a24,)140(a+14,)
The result of this is two notes played for six seconds each, an octave apart.
Volume can be set for each instrument at any point in the song. To use this custom volume, remember to set the volume object. We will use the volume object in our example here.
a1a+1##a++1,
The result of this is three notes played at the same time for the same amount of time, with the highest pitch played at a volume louder than the initial volume.
This works via counting the number of loud and soft characters used consecutively. The number of soft characters is subtracted from the number of loud characters and the volume is obtain from a lookup of the mapping.