head_music 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 67e0581fd0dc08759395cc97286a1e96b538147d
4
- data.tar.gz: dc985557ff8d0e1aa4720a4732a8b29a643251d8
3
+ metadata.gz: 607c84eac4fe859f29c47a023d57f923b7d3d9dc
4
+ data.tar.gz: 6f2c73ba4b7ecfd7c5897668a270070f1082d3a5
5
5
  SHA512:
6
- metadata.gz: 09fcb0a4675636f67580e095b73e5640d122d7ad72df17b0677456f0234778df1a43137eb1d3c7c5e2852a0f8acada492a179bb0e8da3e6b64252164cc554fe2
7
- data.tar.gz: b1b1809ed935b1a03688220039cdce9ecd8c98a55d31d71a818077ce2b2a4e416d8a00ae6dbbba7fe742cf0dc4f507ce173b4a395d4638b4d0adef497f64fb18
6
+ metadata.gz: acb22d69a21f890b57e08e8a4a113ef491388222a33f3e0bf3ec1750673f2caaddd6928c5047023ef1d5bbe3a71f2f665adc23b2e934f4c0e252f7fad269d7c1
7
+ data.tar.gz: aeb7849fe4c6eb607804ebf6d3155c67f04dd477dcc412612dea0fd5929631859ea4f38992423599137659b338c3b3c6e6feb8a9bf40c5388b0d0b60bb0c7102
@@ -54,5 +54,13 @@ class HeadMusic::Letter
54
54
  to_s == value.to_s
55
55
  end
56
56
 
57
+ def cycle
58
+ cycle = NAMES
59
+ while cycle.first != self.to_s
60
+ cycle = cycle.rotate
61
+ end
62
+ cycle
63
+ end
64
+
57
65
  private_class_method :new
58
66
  end
@@ -4,7 +4,7 @@ class HeadMusic::Pitch
4
4
  attr_reader :spelling
5
5
  attr_reader :octave
6
6
 
7
- delegate :letter, to: :spelling
7
+ delegate :letter, :letter_cycle, to: :spelling
8
8
  delegate :accidental, :sharp?, :flat?, to: :spelling
9
9
  delegate :pitch_class, to: :spelling
10
10
 
@@ -88,5 +88,9 @@ class HeadMusic::Pitch
88
88
  self.midi_note_number <=> other.midi_note_number
89
89
  end
90
90
 
91
+ def scale(scale_type_name = nil)
92
+ HeadMusic::Scale.get(self, scale_type_name)
93
+ end
94
+
91
95
  private_class_method :new
92
96
  end
@@ -17,31 +17,14 @@ class HeadMusic::Scale
17
17
 
18
18
  def pitches
19
19
  @pitches ||= begin
20
- pitches = [root_pitch]
21
- letters_cycle = HeadMusic::Letter::NAMES
22
- letters_cycle = letters_cycle.rotate while letters_cycle.first != root_pitch.letter.to_s
20
+ letter_cycle = root_pitch.letter_cycle
23
21
  semitones_from_root = 0
24
- if scale_type.parent
25
- parent_scale_pitches = HeadMusic::Scale.get(root_pitch, scale_type.parent_name).pitches
26
- end
27
- scale_type.intervals.each_with_index do |semitones, i|
28
- semitones_from_root += semitones
29
- pitch_number = root_pitch.pitch_class.to_i + semitones_from_root
30
- if scale_type.intervals.length == 7
31
- current_letter = letters_cycle[(i + 1) % 7]
32
- elsif scale_type.intervals.length < 7 && scale_type.parent
33
- current_letter = parent_scale_pitches.detect { |parent_scale_pitches|
34
- parent_scale_pitches.pitch_class == (root_pitch + semitones_from_root).to_i % 12
35
- }.letter
36
- elsif root_pitch.flat?
37
- current_letter = HeadMusic::PitchClass::FLAT_SPELLINGS[pitch_number % 12]
38
- else
39
- current_letter = HeadMusic::PitchClass::SHARP_SPELLINGS[pitch_number % 12]
22
+ [root_pitch].tap do |pitches|
23
+ scale_type.intervals.each_with_index do |semitones, i|
24
+ semitones_from_root += semitones
25
+ pitches << pitch_for_step(i+1, semitones_from_root)
40
26
  end
41
- pitch = HeadMusic::Pitch.from_number_and_letter(pitch_number, current_letter)
42
- pitches << pitch
43
27
  end
44
- pitches
45
28
  end
46
29
  end
47
30
 
@@ -65,4 +48,43 @@ class HeadMusic::Scale
65
48
  end
66
49
  spellings
67
50
  end
51
+
52
+ def letter_cycle
53
+ @letter_cycle ||= root_pitch.letter_cycle
54
+ end
55
+
56
+ def root_pitch_class
57
+ @root_pitch_class ||= root_pitch.pitch_class
58
+ end
59
+
60
+ private
61
+
62
+ def parent_scale_pitches
63
+ HeadMusic::Scale.get(root_pitch, scale_type.parent_name).pitches if scale_type.parent
64
+ end
65
+
66
+ def parent_scale_pitch_for(semitones_from_root)
67
+ parent_scale_pitches.detect { |parent_scale_pitch|
68
+ parent_scale_pitch.pitch_class == (root_pitch + semitones_from_root).to_i % 12
69
+ }
70
+ end
71
+
72
+ def letter_for_step(step, semitones_from_root)
73
+ pitch_class_number = (root_pitch.pitch_class.to_i + semitones_from_root) % 12
74
+ if scale_type.intervals.length == 7
75
+ letter_cycle[step % 7]
76
+ elsif scale_type.intervals.length < 7 && parent_scale_pitches
77
+ parent_scale_pitch_for(semitones_from_root).letter
78
+ elsif root_pitch.flat?
79
+ HeadMusic::PitchClass::FLAT_SPELLINGS[pitch_class_number]
80
+ else
81
+ HeadMusic::PitchClass::SHARP_SPELLINGS[pitch_class_number]
82
+ end
83
+ end
84
+
85
+ def pitch_for_step(step, semitones_from_root)
86
+ pitch_number = root_pitch_class.to_i + semitones_from_root
87
+ letter = letter_for_step(step, semitones_from_root)
88
+ HeadMusic::Pitch.from_number_and_letter(pitch_number, letter)
89
+ end
68
90
  end
@@ -8,6 +8,8 @@ class HeadMusic::Spelling
8
8
  attr_reader :accidental
9
9
 
10
10
  delegate :number, to: :pitch_class, prefix: true
11
+ delegate :to_i, to: :pitch_class_number
12
+ delegate :cycle, to: :letter, prefix: true
11
13
 
12
14
  def self.get(identifier)
13
15
  from_name(identifier) || from_number(identifier)
@@ -75,5 +77,9 @@ class HeadMusic::Spelling
75
77
  to_s == value.to_s
76
78
  end
77
79
 
80
+ def scale(scale_type_name = nil)
81
+ HeadMusic::Scale.get(self, scale_type_name)
82
+ end
83
+
78
84
  private_class_method :new
79
85
  end
@@ -1,3 +1,3 @@
1
1
  module HeadMusic
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
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.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Head
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-02-19 00:00:00.000000000 Z
11
+ date: 2017-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport