head_music 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 349efa7dc5c27c7c22b46c5d21b4e6fe9a407fc7
4
- data.tar.gz: d435a40658a1b0c5479479e1ac4877845cfd56e0
3
+ metadata.gz: 17a6cfc4f189a661c7f095056b429e32ce17468a
4
+ data.tar.gz: d3a3cc4b18e87fa0f7af9ba584b5f28946329784
5
5
  SHA512:
6
- metadata.gz: 7e689e373db60d8991b72cb6699e16ac174ee830d641b327cad7cc5ae128700f4822fc95e2926103074b281b0bf73f743e58541a1550234f1f3faf1aa6a7e9b2
7
- data.tar.gz: a6aa35cdf0166b4a9a7dcb12364c4daab304a7724d6b9d64e5133276e2c4a3975ca301dff7e5a1a90c789852420dc1728c8c71386c3ac702f0a56289f36e3914
6
+ metadata.gz: 2e9b674c4bde48f3ce71ef0768b60461f3af1ebfcfc501ab9500af24b9b61cbc071f176a43d064fba5e5d9e83f0bc53ee80ffd8d34551ea2bd2777926437f1dc
7
+ data.tar.gz: 04fb64922f6c47d6df0f0cb637ad68b188fffe448dbefe02992aa85169c6ae8993b83383bdf59118391e94c3651ea76ddb7c52c9dd7b93d266d9a0aa8a9d28f0
@@ -34,8 +34,8 @@ class HeadMusic::Chord
34
34
  end
35
35
 
36
36
  def intervals
37
- pitches.drop(1).map.with_index do |pitch, i|
38
- HeadMusic::FunctionalInterval.new(pitches[i], pitch)
37
+ pitches.each_cons(2).map do |pitch_pair|
38
+ HeadMusic::FunctionalInterval.new(*pitch_pair)
39
39
  end
40
40
  end
41
41
 
File without changes
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # A composition is a portion of music.
3
+ # A composition is musical content.
4
4
  class HeadMusic::Composition
5
5
  attr_reader :name, :key_signature, :meter, :voices
6
6
 
@@ -56,6 +56,10 @@ class HeadMusic::Composition
56
56
  voices.reject(&:cantus_firmus?).first
57
57
  end
58
58
 
59
+ def to_s
60
+ "#{name} — #{voices.count} voice(s)"
61
+ end
62
+
59
63
  private
60
64
 
61
65
  def ensure_attributes(name, key_signature, meter)
File without changes
@@ -29,25 +29,25 @@ class HeadMusic::Placement
29
29
  end
30
30
 
31
31
  def during?(other_placement)
32
- starts_during?(other_placement) || ends_during?(other_placement) || within?(other_placement)
32
+ starts_during?(other_placement) || ends_during?(other_placement) || wraps?(other_placement)
33
33
  end
34
34
 
35
35
  def to_s
36
- "#{pitch ? pitch : 'rest'} at #{position}"
36
+ "#{rhythmic_value} #{pitch ? pitch : 'rest'} at #{position}"
37
37
  end
38
38
 
39
39
  private
40
40
 
41
41
  def starts_during?(other_placement)
42
- (other_placement.next_position > position && other_placement.next_position <= next_position)
42
+ position >= other_placement.position && position < other_placement.next_position
43
43
  end
44
44
 
45
45
  def ends_during?(other_placement)
46
- (other_placement.position >= position && other_placement.position < next_position)
46
+ next_position > other_placement.position && next_position <= other_placement.next_position
47
47
  end
48
48
 
49
- def within?(other_placement)
50
- (other_placement.position <= position && other_placement.next_position >= next_position)
49
+ def wraps?(other_placement)
50
+ position <= other_placement.position && next_position >= other_placement.next_position
51
51
  end
52
52
 
53
53
  def ensure_attributes(voice, position, rhythmic_value, pitch)
@@ -95,7 +95,7 @@ end
95
95
 
96
96
  # In Logic Pro X, the 'beat' is determined by the denominator, even if compound.
97
97
  # Logic then divides the beat into 'divisions' that are a sixteenth in length.
98
- # Each division is then divided into 240 ticks (960 PPQN / 4 sixteenths-per-quarter)
98
+ # Each division is then divided into 240 ticks (960 PPQN / 4 sixteenths-per-quarter = 240 ticks per sixteenth note)
99
99
 
100
100
  # Tempo specifies the beat unit, usually the traditional beat unit in the case of compound meters,
101
101
  # so 6/8 would specify [dotted-quarter] = 132 (or whatever).
@@ -96,4 +96,8 @@ class HeadMusic::RhythmicValue
96
96
  def ==(other)
97
97
  to_s == other.to_s
98
98
  end
99
+
100
+ def to_s
101
+ name.tr('_', '-')
102
+ end
99
103
  end
@@ -59,9 +59,7 @@ class HeadMusic::Voice
59
59
 
60
60
  def melodic_intervals
61
61
  @melodic_intervals ||=
62
- notes.map.with_index do |note, i|
63
- HeadMusic::MelodicInterval.new(notes[i - 1], note) if i.positive?
64
- end.compact
62
+ notes.each_cons(2).map { |note_pair| HeadMusic::MelodicInterval.new(*note_pair) }
65
63
  end
66
64
 
67
65
  def leaps
@@ -102,6 +100,10 @@ class HeadMusic::Voice
102
100
  placements.last.position.bar_number
103
101
  end
104
102
 
103
+ def to_s
104
+ "#{role}: #{pitches.first(10).map(&:to_s)}"
105
+ end
106
+
105
107
  private
106
108
 
107
109
  def insert_into_placements(placement)
@@ -54,7 +54,7 @@ class HeadMusic::KeySignature
54
54
  end
55
55
 
56
56
  def signs
57
- !flats.empty? ? flats : sharps
57
+ flats.any? ? flats : sharps
58
58
  end
59
59
 
60
60
  def name
@@ -61,9 +61,9 @@ class HeadMusic::Scale
61
61
  end
62
62
 
63
63
  def octave_scale_pitches(direction, semitones_from_root)
64
- direction_intervals(direction).map.with_index do |semitones, i|
64
+ direction_intervals(direction).map.with_index(1) do |semitones, i|
65
65
  semitones_from_root += semitones * direction_sign(direction)
66
- pitch_for_step(i + 1, semitones_from_root, direction)
66
+ pitch_for_step(i, semitones_from_root, direction)
67
67
  end
68
68
  end
69
69
 
@@ -101,10 +101,9 @@ class HeadMusic::Style::Annotation
101
101
  end
102
102
 
103
103
  def motions
104
- downbeat_harmonic_intervals.map.with_index do |harmonic_interval, i|
105
- next_harmonic_interval = downbeat_harmonic_intervals[i + 1]
106
- HeadMusic::Motion.new(harmonic_interval, next_harmonic_interval) if next_harmonic_interval
107
- end.compact
104
+ downbeat_harmonic_intervals.each_cons(2).map do |harmonic_interval_pair|
105
+ HeadMusic::Motion.new(*harmonic_interval_pair)
106
+ end
108
107
  end
109
108
 
110
109
  def downbeat_harmonic_intervals
@@ -8,8 +8,8 @@ class HeadMusic::Style::Annotations::AlwaysMove < HeadMusic::Style::Annotation
8
8
  MESSAGE = 'Always move to a different note.'
9
9
 
10
10
  def marks
11
- melodic_intervals.map.with_index do |interval, i|
12
- HeadMusic::Style::Mark.for_all(notes[i..i + 1]) if interval.shorthand == 'PU'
13
- end.compact
11
+ melodic_intervals.
12
+ select { |interval| interval.perfect? && interval.unison? }.
13
+ map { |interval| HeadMusic::Style::Mark.for_all(interval.notes) }
14
14
  end
15
15
  end
@@ -23,9 +23,8 @@ class HeadMusic::Style::Annotations::DirectionChanges < HeadMusic::Style::Annota
23
23
  end
24
24
 
25
25
  def melodic_intervals_changing_direction
26
- melodic_intervals.drop(1).select.with_index do |interval, i|
27
- previous_direction = melodic_intervals[i].direction
28
- interval.direction != previous_direction
26
+ melodic_intervals.each_cons(2).reject do |interval_pair|
27
+ interval_pair[0].direction == interval_pair[1].direction
29
28
  end
30
29
  end
31
30
  end
@@ -8,7 +8,7 @@ class HeadMusic::Style::Annotations::EndOnTonic < HeadMusic::Style::Annotation
8
8
  MESSAGE = 'End on the first scale degree.'
9
9
 
10
10
  def marks
11
- HeadMusic::Style::Mark.for(notes.last) if !notes.empty? && !ends_on_tonic?
11
+ HeadMusic::Style::Mark.for(notes.last) if notes.any? && !ends_on_tonic?
12
12
  end
13
13
 
14
14
  private
@@ -18,9 +18,9 @@ class HeadMusic::Style::Annotations::MostlyConjunct < HeadMusic::Style::Annotati
18
18
  private
19
19
 
20
20
  def marks_for_skips_and_leaps
21
- melodic_intervals.map.with_index do |interval, i|
22
- HeadMusic::Style::Mark.for_all(notes[i..i + 1], fitness: HeadMusic::SMALL_PENALTY_FACTOR) unless interval.step?
23
- end.compact
21
+ melodic_intervals.
22
+ reject(&:step?).
23
+ map { |interval| HeadMusic::Style::Mark.for_all(interval.notes, fitness: HeadMusic::SMALL_PENALTY_FACTOR) }
24
24
  end
25
25
 
26
26
  def conjunct_ratio
@@ -16,7 +16,7 @@ class HeadMusic::Style::Annotations::SingableRange < HeadMusic::Style::Annotatio
16
16
  private
17
17
 
18
18
  def overage
19
- !notes.empty? ? [range.number - MAXIMUM_RANGE, 0].max : 0
19
+ notes.any? ? [range.number - MAXIMUM_RANGE, 0].max : 0
20
20
  end
21
21
 
22
22
  def extremes
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HeadMusic
4
- VERSION = '0.18.0'
4
+ VERSION = '0.19.0'
5
5
  end
data/lib/head_music.rb CHANGED
@@ -20,11 +20,9 @@ require 'head_music/utilities/hash_key'
20
20
  require 'head_music/named_rudiment'
21
21
 
22
22
  # rudiments
23
- require 'head_music/bar'
24
23
  require 'head_music/chord'
25
24
  require 'head_music/circle'
26
25
  require 'head_music/clef'
27
- require 'head_music/composition'
28
26
  require 'head_music/consonance'
29
27
  require 'head_music/functional_interval'
30
28
  require 'head_music/grand_staff'
@@ -32,28 +30,31 @@ require 'head_music/harmonic_interval'
32
30
  require 'head_music/instrument'
33
31
  require 'head_music/interval'
34
32
  require 'head_music/key_signature'
35
- require 'head_music/language'
36
33
  require 'head_music/letter_name'
37
34
  require 'head_music/melodic_interval'
38
35
  require 'head_music/meter'
39
36
  require 'head_music/motion'
40
- require 'head_music/note'
41
37
  require 'head_music/octave'
42
38
  require 'head_music/pitch'
43
39
  require 'head_music/pitch_class'
44
- require 'head_music/placement'
45
- require 'head_music/position'
46
40
  require 'head_music/quality'
47
41
  require 'head_music/rhythm'
48
42
  require 'head_music/rhythmic_unit'
49
- require 'head_music/rhythmic_value'
50
43
  require 'head_music/scale'
51
44
  require 'head_music/scale_degree'
52
45
  require 'head_music/scale_type'
53
46
  require 'head_music/sign'
54
47
  require 'head_music/spelling'
55
48
  require 'head_music/staff'
56
- require 'head_music/voice'
49
+
50
+ # content
51
+ require 'head_music/content/bar'
52
+ require 'head_music/content/composition'
53
+ require 'head_music/content/note'
54
+ require 'head_music/content/placement'
55
+ require 'head_music/content/position'
56
+ require 'head_music/content/rhythmic_value'
57
+ require 'head_music/content/voice'
57
58
 
58
59
  # analysis
59
60
  require 'head_music/style/analysis'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: head_music
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Head
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-24 00:00:00.000000000 Z
11
+ date: 2018-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -116,34 +116,34 @@ files:
116
116
  - circle.yml
117
117
  - head_music.gemspec
118
118
  - lib/head_music.rb
119
- - lib/head_music/bar.rb
120
119
  - lib/head_music/chord.rb
121
120
  - lib/head_music/circle.rb
122
121
  - lib/head_music/clef.rb
123
- - lib/head_music/composition.rb
124
122
  - lib/head_music/consonance.rb
123
+ - lib/head_music/content/bar.rb
124
+ - lib/head_music/content/composition.rb
125
+ - lib/head_music/content/note.rb
126
+ - lib/head_music/content/placement.rb
127
+ - lib/head_music/content/position.rb
128
+ - lib/head_music/content/rhythmic_value.rb
129
+ - lib/head_music/content/voice.rb
125
130
  - lib/head_music/functional_interval.rb
126
131
  - lib/head_music/grand_staff.rb
127
132
  - lib/head_music/harmonic_interval.rb
128
133
  - lib/head_music/instrument.rb
129
134
  - lib/head_music/interval.rb
130
135
  - lib/head_music/key_signature.rb
131
- - lib/head_music/language.rb
132
136
  - lib/head_music/letter_name.rb
133
137
  - lib/head_music/melodic_interval.rb
134
138
  - lib/head_music/meter.rb
135
139
  - lib/head_music/motion.rb
136
140
  - lib/head_music/named_rudiment.rb
137
- - lib/head_music/note.rb
138
141
  - lib/head_music/octave.rb
139
142
  - lib/head_music/pitch.rb
140
143
  - lib/head_music/pitch_class.rb
141
- - lib/head_music/placement.rb
142
- - lib/head_music/position.rb
143
144
  - lib/head_music/quality.rb
144
145
  - lib/head_music/rhythm.rb
145
146
  - lib/head_music/rhythmic_unit.rb
146
- - lib/head_music/rhythmic_value.rb
147
147
  - lib/head_music/scale.rb
148
148
  - lib/head_music/scale_degree.rb
149
149
  - lib/head_music/scale_type.rb
@@ -192,7 +192,6 @@ files:
192
192
  - lib/head_music/style/rulesets/modern_cantus_firmus.rb
193
193
  - lib/head_music/utilities/hash_key.rb
194
194
  - lib/head_music/version.rb
195
- - lib/head_music/voice.rb
196
195
  homepage: https://github.com/roberthead/head_music
197
196
  licenses:
198
197
  - MIT
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # A language.
4
- class HeadMusic::Language
5
- include Comparable
6
- include HeadMusic::NamedRudiment
7
-
8
- LANGUAGES = [
9
- { name: 'American English', short_name: 'English', abbreviation: 'en-US' },
10
- { name: 'British English', abbreviation: 'en-GB' },
11
- { name: 'French', native_name: 'Français', abbreviation: 'fr' },
12
- { name: 'German', native_name: 'Deutsche', abbreviation: 'de' },
13
- { name: 'Italian', native_name: 'Italiano', abbreviation: 'it' },
14
- { name: 'Spanish', native_name: 'Español', abbreviation: 'es' },
15
- { name: 'Russian', native_name: 'русский', abbreviation: 'ru' },
16
- ].freeze
17
-
18
- LANGUAGES.
19
- map { |language| ::HeadMusic::Utilities::HashKey.for(language[:name]) }.
20
- each { |language_key| define_singleton_method(language_key) { HeadMusic::Language.get(language_key) } }
21
-
22
- LANGUAGES.
23
- map { |language| ::HeadMusic::Utilities::HashKey.for(language[:native_name]) }.
24
- reject(&:nil?).
25
- each { |language_key| define_singleton_method(language_key) { HeadMusic::Language.get(language_key) } }
26
-
27
- LANGUAGES.
28
- map { |language| ::HeadMusic::Utilities::HashKey.for(language[:short_name]) }.
29
- reject(&:nil?).
30
- each { |language_key| define_singleton_method(language_key) { HeadMusic::Language.get(language_key) } }
31
-
32
- def self.default
33
- english
34
- end
35
-
36
- def self.get(name)
37
- get_by_name(name) || default
38
- end
39
-
40
- attr_accessor :name, :native_name, :short_name
41
-
42
- def initialize(identifier)
43
- identifier_key = HeadMusic::Utilities::HashKey.for(identifier)
44
- language_data = LANGUAGES.detect do |data|
45
- %i[name native_name short_name].
46
- map { |key| HeadMusic::Utilities::HashKey.for(data[key]) }.
47
- include?(identifier_key)
48
- end
49
- @name = language_data[:name]
50
- @native_name = language_data[:native_name]
51
- @short_name = language_data[:short_name]
52
- end
53
-
54
- def <=>(other)
55
- name.to_s <=> other.to_s
56
- end
57
-
58
- def inspect
59
- [name, native_name, short_name].reject(&:nil?).join(' / ')
60
- end
61
- end