Wintergatan / Midi-to-laser-cutter

https://wintergatan.github.io/Midi-to-laser-cutter/
MIT License
127 stars 13 forks source link

Request: long notes #19

Open DrSkunk opened 7 years ago

DrSkunk commented 7 years ago

I recently got this email from Alexander Karavaev

Hi Sebastian! My name is Alexander Karavaev, im from Moscow, Russia. I've seen your and your friends project, cutting cards for music boxes and want to say its amazing stuff that somebody solve this problem! i have my workshop (i making irish whistles) and has made there a music box for my friend and punched a paper card for it. https://youtu.be/AdXoyF1zLeU But also i want to build a street organ, And here is my question! Can you add an option in your program for long notes? In music box all notes sound like separetely, but in street organs there is a long cut for long not. If you can do that it will help to thousands people who trying to make music for street organs. Now they using very big and slow working metal punch machines, it looks like that https://www.youtube.com/watch?v=OIl9V213krQ. Will wait for your answer! Thanks!

Best wishes!

I believe this is something we can support?

Yuleblinker commented 7 years ago

Yes this is definately something we can support. In the experimental>sandbox>index.html https://github.com/Wintergatan/Midi-to-laser-cutter/tree/master/experimental/sandbox demo code I purposefully took all the events from the track and not just the note start events to account for this scenario. When rendering if the user wants long notes then I think it will just be a case of setting the shapes width based on a look forward to the note end event eg [index +1]. As long as there is always a note end event directly after the note start event in any one channel - is this how midi works??

Lars-Kristian commented 7 years ago

Every midi note has a property that describes how long the note is. Should be no problem. It is a little unclear from the video. But is one long note a longer hole in the paper of is it many consecutive holes?

Alexander-Karavaev commented 7 years ago

Hi everybody! Lars-Kristian: long notes looks like that https://s-media-cache-ak0.pinimg.com/736x/2f/33/ea/2f33ea68b2e429f72c4203d51765a1c1.jpg

Lars-Kristian commented 7 years ago

Nice, thank you.

Yuleblinker commented 7 years ago

@Lars-Kristian I've been looking for the property of MIDI notes that says how long the note is. I can't find this information (am I missing something?). As far as I can figure out you can only really tell the duration of note by findinig out when the note off event occurs and doing a calculation based on this. Along the lines of duration = noteoff time - noteon time. I have seen a javascript library (used here https://tonejs.github.io/MidiConvert/ and source here: https://github.com/Tonejs/MidiConvert) that does give duration for notes but I think this is a calculated value not something taken directly from the MIDI data. If there is a way to get duration directly then this would be useful.

nglade commented 7 years ago

Note duration must be a derived/calculated property, afaik the midi standard only specified note on / off events. Consider midi data created by playing on a keyboard. note on is sent, when the player presses a key, note off when they release the key. The device cannot know in advance, how long the note should be. Midi files could also be faulty (having note on events withouth corresponding note off events). Not so sure about that anymore. I had a midi file loaded, where some notes were never finished, but this could have other causes.

Yuleblinker commented 7 years ago

Does this mean that if you're not interesting in actually playing the note then all you really need to pay attention to are note off events? As the deltaT of a note off event gives the duration for the note.

Lars-Kristian commented 7 years ago

I did not know. I used Tonejs/MidiConvert in my prototype so I assumed it was a native thing in Midi files.

nglade commented 7 years ago

Sorry, I'm not sure if I understand your question. What do you mean with "not interested in playing the note"? (I've just started to look these things up in the midi specification, so I may be wrong on the following) According to http://www.somascape.org/midi/tech/mfile.html#delta those only give the time elapsed(in ticks) since the previous event. But the previous event does not have to be a note on event (could be a sysex event, tempo change, etc.). In order to get the duration of a note you could do sth. like duration = eventOff.rtime - eventOn.rtime, where eventOff and eventOn have the same key number(pitch) and eventOff is the first/closest note off event after eventOn,

Yuleblinker commented 7 years ago

When I say '...if you're not interested in playing the note...' I mean that in the application we may, or may not, support the ability for a user to play(listen to) the track they are working with. To simply create shapes representing holes on paper playing the file is not necessary. If we want the user to be able to amend the track - add, remove, move notes and to check what it will sound like on a music box then it would be good to be able to play the track.

To play the track we would need to know when the noteon event occurs and it's velocity. We would also need to know when the noteoff event occurs too. To create holes we only need to know when the noteon event occurs. This decides the position of the hole.

If we want the ability to create long holes we need to know the notes duration. The duration can be found in two ways (afaik)... either:

  1. duration = noteoff.time - noteon.time
  2. duration = noteoff.deltaT

If all we want to do is create shapes on paper then either method is fine and both support long notes. The second method just means we can ignore noteon events and don't need to store or process them. If we want to play a track we'll need both events.

Dealing with what a 'previous event' is is quite straightforward. We sort the note data into 'channels' according to the notenumber. We don't add sysex or other events to these chanels. If we find a noteoff event in this channel then the 'previous' noteon event is the on for this off. Its 'pair' if you like.

nglade commented 7 years ago

Not necessarily, when you have a midi file with multiple midi channels. You could have a midi file like the following: channel1: note 42 on, channel2: note 42 on, channel2: note 42 off, channel1: note 42 off. This would create overlapping holes/ a long hole, instead of two holes. In that case, the note duration would be off.time - on.time for consecutive on-off events and _second_on.time - firston.time - min-dist for consecutive note on events. Also, for the second case, we'd need to drop all but the last event from a sequence of consecutive note off events.

Yuleblinker commented 7 years ago

I should have explained that as we are creating a strip for single 'instrument' we are only going to support the creation of a strip from a single channel that respresents this instrument. In MIDI I don't believe (I may be totally wrong) it's possible to have overlapping notes of the same pitch for a single instrument. Imagine playing a MIDI keyboard. When you hit a key that creates a note on event. You can't hit the same key again without having released it first.

My understanding of why long notes have been requested is that some people want to create strips for instruments that can play notes of different durations e.g. barrel organs or pipe organs. Each of these 'long' holes will be playing a single pitch. The data for this note will come from a single channel. The duration for a note would be calculated as mentioned above. The need is simply to have hole shapes of a width that represents the duration of the note.

If you wan't to create a strip for a MIDI file that contains parts for more than one instrument (is this what is meant by a MIDI channel?) then you will either have to select a single intrument(channel) to use from the file or to somehow merge the channels before importing. I am no MIDI expert, as you can probably tell, so I have no idea what would happen to 'overlapping' events of the same pitch if you merge channels.

We would like to build in some very basic editing ability into the application such as delete, add or move notes and possibly transposing. It will be up to the user to make sure the track they are importing has suitable data for playback on a single simple instrument and that that data is in a single channel. It may be possible for use to provide some means of merging channels but at this stage of development I don't think that's being considered.

DrSkunk commented 7 years ago

It's to be determined that the new library supports all events so that long notes can be enabled. edit: the library has this functionality.