Module: OutroRails::Instruments::Piano
- Defined in:
- lib/outro_rails/instruments/piano.rb
Overview
Piano keyboard logic.
Constant Summary collapse
- WHITE_PITCH_CLASSES =
Pitch classes of the naturals, i.e. the white keys of an octave.
Theory::NoteName::NATURAL_PITCH_CLASSES.values.freeze
Class Method Summary collapse
-
.black_key?(midi) ⇒ Boolean
Whether a MIDI number lands on a black key.
-
.display_range(pitches, prefer: :sharps) ⇒ Object
Display range for a collection of pitches: the first white key strictly below the lowest note through the first white key strictly above the highest, so the keyboard always has one free white key of margin on each side (and never starts or ends on a black key): display_range(c_major.pitched_notes) => [B3, D5] (as Pitches) display_range(f_sharp_major.pitched_notes) => [F4, G5].
-
.keys_between(start_note, end_note, prefer: :sharps) ⇒ Object
Inclusive list of key hashes between two note names, low to high: [{ midi: 48, note: 'C3', black: false }, ...].
-
.white_key?(midi) ⇒ Boolean
Whether a MIDI number lands on a white key.
Class Method Details
.black_key?(midi) ⇒ Boolean
Whether a MIDI number lands on a black key
21 22 23 |
# File 'lib/outro_rails/instruments/piano.rb', line 21 def black_key?(midi) !white_key?(midi) end |
.display_range(pitches, prefer: :sharps) ⇒ Object
Display range for a collection of pitches: the first white key strictly below the lowest note through the first white key strictly above the highest, so the keyboard always has one free white key of margin on each side (and never starts or ends on a black key):
display_range(c_major.pitched_notes) => [B3, D5] (as Pitches)
display_range(f_sharp_major.pitched_notes) => [F4, G5]
46 47 48 49 50 51 52 53 54 55 |
# File 'lib/outro_rails/instruments/piano.rb', line 46 def display_range(pitches, prefer: :sharps) midis = pitches.map { |pitch| Theory::Pitch.parse(pitch).midi } [ Theory::Pitch.from_midi(next_white_key(midis.min - 1, -1), prefer: prefer), Theory::Pitch.from_midi(next_white_key(midis.max + 1, 1), prefer: prefer) ] end |
.keys_between(start_note, end_note, prefer: :sharps) ⇒ Object
Inclusive list of key hashes between two note names, low to high:
[{ midi: 48, note: 'C3', black: false }, ...]
27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/outro_rails/instruments/piano.rb', line 27 def keys_between(start_note, end_note, prefer: :sharps) low = Theory::Pitch.parse(start_note).midi high = Theory::Pitch.parse(end_note).midi low, high = high, low if low > high (low..high).map do |midi| { midi: midi, note: Theory::Pitch.from_midi(midi, prefer: prefer).to_s, black: black_key?(midi) } end end |
.white_key?(midi) ⇒ Boolean
Whether a MIDI number lands on a white key
14 15 16 17 18 |
# File 'lib/outro_rails/instruments/piano.rb', line 14 def white_key?(midi) pitch_class = midi % Theory::Interval::SEMITONES_PER_OCTAVE WHITE_PITCH_CLASSES.include?(pitch_class) end |