salu133445 / pypianoroll

A toolkit for working with piano rolls
https://salu133445.github.io/pypianoroll/
MIT License
136 stars 17 forks source link

How to differentiate between a note pressed continuously and repeatedly? #12

Closed Yannik1337 closed 3 years ago

Yannik1337 commented 3 years ago

I am following your "Getting Started" section here:

!pip install pypianoroll
import numpy as np
import pypianoroll
from pypianoroll import Multitrack, Track
from matplotlib import pyplot as plt
from matplotlib.pyplot import figure
plt.rcParams["figure.figsize"] = (20,3)

import seaborn as sns

# Create a piano roll matrix, where the first and second axes represent time
# and pitch, respectively, and assign a C major chord to the piano roll
pianoroll = np.zeros((96, 128))
example_1 = [60]

pianoroll[0:10, example_1] = 100

for i in range(10):
  pianoroll[i, [70]] = 100

# Create a `pypianoroll.Track` instance
track = Track(name="Piano", program=0, is_drum=False,
              pianoroll=pianoroll)

# Plot the piano roll
ax = track.plot()
plt.savefig("single_track.png", dpi=100)
plt.show()

How can one differentiate between a note kept pressed over a long duration (e.g. one bar), and a note played repeatedly over the same time range?

Consider a 4/4 signature, with 16 notes of 16th duration. They would be stroked repeatedly. Now, for the same bar, one could hold a whole note, which in terms of duration is the same as 16 16th notes.

How and where can this difference be modeled? In my code I tried to set the note individually at every step, but they get merged into a note hold over the according duration.

Thanks for your help!

salu133445 commented 3 years ago

That's a limitation of the piano-roll representation, but there are some ways to overcome this.

Yannik1337 commented 3 years ago

Thank you for your fast response.

Since this is a limitation of the piano-roll representation, do you know how this case is handled in a plain midi file setting? As far as I know, there is (theoretically) no limit to the time resolution, meaning one could have e.g. 512 notes per bar.

In the plain midi setting, how can one differentiate between a note pressed over one bar and 512 repeatedly struck notes?

Thanks in advance!

salu133445 commented 3 years ago

In MIDI, you can set a resolution (in pulses per quarter note, PPQN) at the beginning of the file. MIDI has a note-off message that indicates the end of a note. In other words, a pair of note-on and note-off message defines a note. That makes it possible to differentiate a single long note from repeatedly played notes.

Yannik1337 commented 3 years ago

Thank you for your fast response.

If you don't mind, I have a further question: For sheet music, we often have changes of the time signature; one bar in 4/4, the next in 3/4. How can this be handled in the piano roll representation? How does your library handle this case?

salu133445 commented 3 years ago

There is a downbeat array designed for this. Basically, it's a boolean array that has a one at downbeat for indicating time signature changes. Reading downbeat array from MIDI is supporting, but MIDI output is not working for now.

Yannik1337 commented 3 years ago

Reading downbeat array from MIDI is supporting, but MIDI output is not working for now.

If I understand this correctly, I currently can get such an array from a MIDI file, but I currently can not construct a MIDI file, given a piano roll array and secondary downbeat array?

salu133445 commented 3 years ago

Yes. You can still output MIDI files, but there will be no time signature messages for now.

On Fri, Jan 8, 2021 at 1:51 AM Yannik1337 notifications@github.com wrote:

Reading downbeat array from MIDI is supporting, but MIDI output is not working for now.

If I understand this correctly, I currently can get such an array from a MIDI file, but I currently can not construct a MIDI file, given a piano roll array and secondary downbeat array?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/salu133445/pypianoroll/issues/12#issuecomment-756274628, or unsubscribe https://github.com/notifications/unsubscribe-auth/AFK27V3UDCQAFOCPPDOG5ZTSYXYBNANCNFSM4VQ4NSOQ .

Yannik1337 commented 3 years ago

Thank you for taking the time to answer all my questions - really appreciate that.