JSME: JavaScript Music Engine
For specifics on JSME and how to use it in your own programs, go to
https://www.stellimare.com/JSME-JavaScript-Music-Engine/.
The rest of this information relates specifically to the JSME Composer tool.
INFO
This tool is a work in progress.
JSME is a pure JavaScript based player. It needs no external audio files, only
an array with playback instructions. It makes use of modern browsers sound
context to synthesize notes which is very similar to early computers "chip tune"
playback systems. The file format is detailed in the "LLM Prompt Helper,"
which you can copy-paste into a LLM and see if it'll generate some sensible music
for you. You can, of course, use the editor to manually compose your own music
(which I recommend if you have an music skill of your own).
This tool allows you to save files to your browser, or to a file that you can share.
It also has import/export function were you can import or export a raw JS array
to edit or copy into your own JavaScript web app making use of JSME. Browser
storage should only be used for temporary backups. You may find backups
of your songs temporally stored there.
Remember: The user must interact with the web page before audio can be played.
Clicking a "start" button is perfect.
LLM PROMPT HELPER
LLM's like Google Gemini, are able to generate music data for playback
using this system. The prompt below will provide instructions for the LLMs to
follow. Your success will vary (all the example music here was generated with
Google Gemini prompts).
Act as a composer for JSME: JavaScript Music Engine and generate a song as a
raw JavaScript array. Your output must only contain the raw array with no comments nor
markdown prose, and no empty strings. Each array index represents a 1/8th note tick.
You must use sparse arrays with consecutive commas to represent empty space or rests.
The first element of the array contains metadata, only the "emd-metadata" and tempo
tags are required, the rest are optional. The format of the metadata is
'[ ""emd-metadata" , ["TAG","Value"],["TAG","Value"],...]'. The following array elements
are the channel lists. They take the form of '[ [<instruments data>],
[<note>,<note>,...]]'. The notes take the form of
<duration><name><octave><volume>. The duration takes two forms,
one is the note form where 1 (or none) ,2,4,8,16 are for a whole, 1/2, 1/4, 1/8. and 1/16th
note duration (if it is a whole note the 1 can, and should, be omitted, also note the
scale is 1/8th, so a 1/16th note would only play for half of a tick, with a forced 1/16th
pause); the other is S+n, where where 'n' is the number of 1/8th note steps to play. Next
is the note name:C,D,E,F,G,A,B (this is the only required note, do not use '-' for a pause,
simply add empty cells for the consecutive 1/8th note pauses). Next is the optional accent,
# for sharp and b for flat. Next is the octave with 4 being the middle octave (4 is optional,
it is only required for those not in the 4th octave). Next is the volume when the note
is to play at a lower volume than 100% of the master volume. This is a single digit fractional
number, so ".5" is 50% volume and ".9" is 90%, and nothing is 100%, and .95 isn't allowed
because it's two digits. The instrument data is an array that contains information about
the waveform to use and takes the form of [ramp,filter,resonance,waveform]. Never use "-"
for the note name or "." alone without a number as neither will play.
Example (there is no limit on the number of channels, but keeping it under 8 is easier
to manage):
[
["emd-metadata", [
["tempo", "120"],
["title", "Crossed Buns"],
["author", "JSME"],
["notes"," optional long-form comments and notes"]]
],
[ [1.0, 1100, 1, "sawtooth"],
[ "4B.8",, "4A.8",, "2G.9",,,, "4B.8",, "4A.8",, "2G.9",,,,
"16G.7", "16G.7", "16G.7", "16G.7", "16A.7", "16A.7", "16A.7", "16A.7",
"4B.8",, "4A.8",, "2G.9" ]
],
[ [1.0, 150, 0, "sine"],
[ "S+4G2.6",,,, "S+4G2.6",,,, "S+4G2.6",,,, "S+4G2.6",,,,
"S+4G2.6",,,, "S+4D2.6",,,, "S+4G2.6",,,, "S+4G2.6" ]
]
]
Instruments presets: