grimmdude / MidiWriterJS

♬ A JavaScript library which provides an API for programmatically generating and creating expressive multi-track MIDI files and JSON.
MIT License
547 stars 58 forks source link

Durations greater than 4 quarter notes not supported #58

Closed mitchkm closed 5 years ago

mitchkm commented 5 years ago

While there is no support for dotted whole notes, dotted dotted whole notes, etc. More generally support to override the string based duration specification and opt for purely a numerical value of quarter notes does not seem to be supported.

grimmdude commented 5 years ago

Hi @mitchkm,

Thanks for your message. Here are a couple solutions for achieving durations longer than whole:

Passing an array of note durations will give you a duration equal to the sum of those durations. Here's how you could get a dotted whole note:

const note = new MidiWriter.NoteEvent({pitch:['C4'], duration: ['1',  '2']});

You can use the tick based duration option to achieve notes longer than whole. The library is setup to use 128 ticks per beat. So in 4/4 that's 512 ticks per whole note. Something like this would give you a dotted whole note:

const note = new MidiWriter.NoteEvent({pitch:['C4'], duration: 'T768'});
mitchkm commented 5 years ago

Thank you for showing me the ways to achieve my goal. But I will say for it to make the most sense in music theory it would be nice to provide a numeric quantity of a quarter note perhaps. ie. 10 quarter notes. I guess I can make an char. array of X quarter notes('4') but it feels a little less intuitive. Especially if arrays get changed to providing the duration for a multitude of pitches also provided in an array.

grimmdude commented 5 years ago

Hi @mitchkm,

Thanks, could you post an example syntax that you would prefer?

-Garrett

mitchkm commented 5 years ago

Following the way you specify ticks, perhaps:

const note = new MidiWriter.NoteEvent({pitch:['C4'], duration: 'Q10'});

Meaning a duration of 10 quarter notes

grimmdude commented 5 years ago

Hi @mitchkm,

I can see your logic with this, but I don't think it's worth implementing this way. It introduces a new prefix Q, and presumably every prefix for all other note types; E for eighth, S for sixteenth, etc. which can get out of hand quickly and not particularly intuitive.

In it's current implementation, using an array of durations to be summed seems much more friendly and flexible from a programmatic standpoint in my opinion. For instance, how would you create a duration of two whole notes and an eighth?

For your case, creating an array of ten "4" is fairly trivial:

const note = new MidiWriter.NoteEvent({pitch:['C4'], duration: new Array(10).fill('4')});

Appreciate your input.

-Garrett