motion-music 0.0.2

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.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/Gemfile +8 -0
  4. data/Guardfile +6 -0
  5. data/LICENSE +23 -0
  6. data/README.md +53 -0
  7. data/doc/Gemfile.html +111 -0
  8. data/doc/Gemfile_lock.html +168 -0
  9. data/doc/Guardfile.html +111 -0
  10. data/doc/LICENSE.html +124 -0
  11. data/doc/Object.html +116 -0
  12. data/doc/RBMusic.html +164 -0
  13. data/doc/RBMusic/Interval.html +440 -0
  14. data/doc/RBMusic/Note.html +620 -0
  15. data/doc/RBMusic/NoteSet.html +277 -0
  16. data/doc/RBMusic/Scale.html +274 -0
  17. data/doc/README_md.html +163 -0
  18. data/doc/created.rid +8 -0
  19. data/doc/fonts.css +167 -0
  20. data/doc/fonts/Lato-Light.ttf +0 -0
  21. data/doc/fonts/Lato-LightItalic.ttf +0 -0
  22. data/doc/fonts/Lato-Regular.ttf +0 -0
  23. data/doc/fonts/Lato-RegularItalic.ttf +0 -0
  24. data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
  25. data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
  26. data/doc/images/add.png +0 -0
  27. data/doc/images/arrow_up.png +0 -0
  28. data/doc/images/brick.png +0 -0
  29. data/doc/images/brick_link.png +0 -0
  30. data/doc/images/bug.png +0 -0
  31. data/doc/images/bullet_black.png +0 -0
  32. data/doc/images/bullet_toggle_minus.png +0 -0
  33. data/doc/images/bullet_toggle_plus.png +0 -0
  34. data/doc/images/date.png +0 -0
  35. data/doc/images/delete.png +0 -0
  36. data/doc/images/find.png +0 -0
  37. data/doc/images/loadingAnimation.gif +0 -0
  38. data/doc/images/macFFBgHack.png +0 -0
  39. data/doc/images/package.png +0 -0
  40. data/doc/images/page_green.png +0 -0
  41. data/doc/images/page_white_text.png +0 -0
  42. data/doc/images/page_white_width.png +0 -0
  43. data/doc/images/plugin.png +0 -0
  44. data/doc/images/ruby.png +0 -0
  45. data/doc/images/tag_blue.png +0 -0
  46. data/doc/images/tag_green.png +0 -0
  47. data/doc/images/transparent.png +0 -0
  48. data/doc/images/wrench.png +0 -0
  49. data/doc/images/wrench_orange.png +0 -0
  50. data/doc/images/zoom.png +0 -0
  51. data/doc/index.html +93 -0
  52. data/doc/js/darkfish.js +140 -0
  53. data/doc/js/jquery.js +18 -0
  54. data/doc/js/navigation.js +142 -0
  55. data/doc/js/search.js +109 -0
  56. data/doc/js/search_index.js +1 -0
  57. data/doc/js/searcher.js +228 -0
  58. data/doc/projections_json.html +115 -0
  59. data/doc/rb-music_gemspec.html +132 -0
  60. data/doc/rdoc.css +580 -0
  61. data/doc/table_of_contents.html +192 -0
  62. data/lib/motion-music.rb +9 -0
  63. data/lib/motion-music/version.rb +3 -0
  64. data/lib/rb-music.rb +8 -0
  65. data/lib/rb-music/constants.rb +105 -0
  66. data/lib/rb-music/interval.rb +50 -0
  67. data/lib/rb-music/note.rb +107 -0
  68. data/lib/rb-music/note_set.rb +61 -0
  69. data/lib/rb-music/scale.rb +30 -0
  70. data/lib/rb-music/version.rb +3 -0
  71. data/motion-music.gemspec +20 -0
  72. data/projections.json +12 -0
  73. data/rb-music.gemspec +29 -0
  74. data/spec/rb-music/constants_spec.rb +27 -0
  75. data/spec/rb-music/interval_spec.rb +90 -0
  76. data/spec/rb-music/note_set_spec.rb +191 -0
  77. data/spec/rb-music/note_spec.rb +318 -0
  78. data/spec/rb-music/scale_spec.rb +88 -0
  79. data/spec/spec_helper.rb +14 -0
  80. metadata +124 -0
@@ -0,0 +1,192 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html>
4
+ <head>
5
+ <meta charset="UTF-8">
6
+
7
+ <title>Table of Contents - RDoc Documentation</title>
8
+
9
+ <link href="./fonts.css" rel="stylesheet">
10
+ <link href="./rdoc.css" rel="stylesheet">
11
+
12
+ <script type="text/javascript">
13
+ var rdoc_rel_prefix = "./";
14
+ </script>
15
+
16
+ <script src="./js/jquery.js"></script>
17
+ <script src="./js/navigation.js"></script>
18
+ <script src="./js/search_index.js"></script>
19
+ <script src="./js/search.js"></script>
20
+ <script src="./js/searcher.js"></script>
21
+ <script src="./js/darkfish.js"></script>
22
+
23
+
24
+ <body id="top" class="table-of-contents">
25
+ <main role="main">
26
+ <h1 class="class">Table of Contents - RDoc Documentation</h1>
27
+
28
+
29
+ <h2 id="classes">Classes and Modules</h2>
30
+ <ul>
31
+ <li class="class">
32
+ <a href="Object.html">Object</a>
33
+ </li>
34
+ <li class="module">
35
+ <a href="RBMusic.html">RBMusic</a>
36
+ </li>
37
+ <li class="class">
38
+ <a href="RBMusic/Interval.html">RBMusic::Interval</a>
39
+ </li>
40
+ <li class="class">
41
+ <a href="RBMusic/Note.html">RBMusic::Note</a>
42
+ </li>
43
+ <li class="class">
44
+ <a href="RBMusic/NoteSet.html">RBMusic::NoteSet</a>
45
+ </li>
46
+ <li class="class">
47
+ <a href="RBMusic/Scale.html">RBMusic::Scale</a>
48
+ </li>
49
+ </ul>
50
+
51
+ <h2 id="methods">Methods</h2>
52
+ <ul>
53
+
54
+ <li class="method">
55
+ <a href="RBMusic/Note.html#method-c-from_latin">::from_latin</a>
56
+ &mdash;
57
+ <span class="container">RBMusic::Note</span>
58
+
59
+ <li class="method">
60
+ <a href="RBMusic/Interval.html#method-c-from_name">::from_name</a>
61
+ &mdash;
62
+ <span class="container">RBMusic::Interval</span>
63
+
64
+ <li class="method">
65
+ <a href="RBMusic/Interval.html#method-c-from_semitones">::from_semitones</a>
66
+ &mdash;
67
+ <span class="container">RBMusic::Interval</span>
68
+
69
+ <li class="method">
70
+ <a href="RBMusic/Interval.html#method-c-from_tones_semitones">::from_tones_semitones</a>
71
+ &mdash;
72
+ <span class="container">RBMusic::Interval</span>
73
+
74
+ <li class="method">
75
+ <a href="RBMusic/NoteSet.html#method-c-new">::new</a>
76
+ &mdash;
77
+ <span class="container">RBMusic::NoteSet</span>
78
+
79
+ <li class="method">
80
+ <a href="RBMusic/Scale.html#method-c-new">::new</a>
81
+ &mdash;
82
+ <span class="container">RBMusic::Scale</span>
83
+
84
+ <li class="method">
85
+ <a href="RBMusic/Interval.html#method-c-new">::new</a>
86
+ &mdash;
87
+ <span class="container">RBMusic::Interval</span>
88
+
89
+ <li class="method">
90
+ <a href="RBMusic/Note.html#method-c-new">::new</a>
91
+ &mdash;
92
+ <span class="container">RBMusic::Note</span>
93
+
94
+ <li class="method">
95
+ <a href="RBMusic/Note.html#method-i-3D-3D">#==</a>
96
+ &mdash;
97
+ <span class="container">RBMusic::Note</span>
98
+
99
+ <li class="method">
100
+ <a href="RBMusic/Note.html#method-i-accidental">#accidental</a>
101
+ &mdash;
102
+ <span class="container">RBMusic::Note</span>
103
+
104
+ <li class="method">
105
+ <a href="RBMusic/NoteSet.html#method-i-add">#add</a>
106
+ &mdash;
107
+ <span class="container">RBMusic::NoteSet</span>
108
+
109
+ <li class="method">
110
+ <a href="RBMusic/Interval.html#method-i-add">#add</a>
111
+ &mdash;
112
+ <span class="container">RBMusic::Interval</span>
113
+
114
+ <li class="method">
115
+ <a href="RBMusic/Note.html#method-i-add">#add</a>
116
+ &mdash;
117
+ <span class="container">RBMusic::Note</span>
118
+
119
+ <li class="method">
120
+ <a href="RBMusic/Scale.html#method-i-degree_count">#degree_count</a>
121
+ &mdash;
122
+ <span class="container">RBMusic::Scale</span>
123
+
124
+ <li class="method">
125
+ <a href="RBMusic/Note.html#method-i-enharmonic-3F">#enharmonic?</a>
126
+ &mdash;
127
+ <span class="container">RBMusic::Note</span>
128
+
129
+ <li class="method">
130
+ <a href="RBMusic/Note.html#method-i-enharmonically_equivalent_to-3F">#enharmonically_equivalent_to?</a>
131
+ &mdash;
132
+ <span class="container">RBMusic::Note</span>
133
+
134
+ <li class="method">
135
+ <a href="RBMusic/Note.html#method-i-frequency">#frequency</a>
136
+ &mdash;
137
+ <span class="container">RBMusic::Note</span>
138
+
139
+ <li class="method">
140
+ <a href="RBMusic/Note.html#method-i-latin">#latin</a>
141
+ &mdash;
142
+ <span class="container">RBMusic::Note</span>
143
+
144
+ <li class="method">
145
+ <a href="RBMusic/Scale.html#method-i-notes_in_range">#notes_in_range</a>
146
+ &mdash;
147
+ <span class="container">RBMusic::Scale</span>
148
+
149
+ <li class="method">
150
+ <a href="RBMusic/Note.html#method-i-octave">#octave</a>
151
+ &mdash;
152
+ <span class="container">RBMusic::Note</span>
153
+
154
+ <li class="method">
155
+ <a href="RBMusic/Note.html#method-i-scale">#scale</a>
156
+ &mdash;
157
+ <span class="container">RBMusic::Note</span>
158
+
159
+ <li class="method">
160
+ <a href="RBMusic/Interval.html#method-i-semitone">#semitone</a>
161
+ &mdash;
162
+ <span class="container">RBMusic::Interval</span>
163
+
164
+ <li class="method">
165
+ <a href="RBMusic/Interval.html#method-i-subtract">#subtract</a>
166
+ &mdash;
167
+ <span class="container">RBMusic::Interval</span>
168
+
169
+ <li class="method">
170
+ <a href="RBMusic/Note.html#method-i-subtract">#subtract</a>
171
+ &mdash;
172
+ <span class="container">RBMusic::Note</span>
173
+
174
+ <li class="method">
175
+ <a href="RBMusic/NoteSet.html#method-i-subtract">#subtract</a>
176
+ &mdash;
177
+ <span class="container">RBMusic::NoteSet</span>
178
+
179
+ <li class="method">
180
+ <a href="RBMusic/Interval.html#method-i-tone_semitone">#tone_semitone</a>
181
+ &mdash;
182
+ <span class="container">RBMusic::Interval</span>
183
+ </ul>
184
+ </main>
185
+
186
+
187
+ <footer id="validator-badges" role="contentinfo">
188
+ <p><a href="http://validator.w3.org/check/referer">Validate</a>
189
+ <p>Generated by <a href="http://rdoc.rubyforge.org">RDoc</a> 4.1.1.
190
+ <p>Based on <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish</a> by <a href="http://deveiate.org">Michael Granger</a>.
191
+ </footer>
192
+
@@ -0,0 +1,9 @@
1
+ unless defined?(Motion::Project::Config)
2
+ raise "This file must be required within a RubyMotion project Rakefile."
3
+ end
4
+
5
+ Motion::Project::App.setup do |app|
6
+ Dir.glob(File.join(File.dirname(__FILE__), 'rb-music/*.rb')).each do |file|
7
+ app.files.unshift(file)
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module MotionMusic
2
+ VERSION = "0.0.2" unless defined? MotionMusic::VERSION
3
+ end
data/lib/rb-music.rb ADDED
@@ -0,0 +1,8 @@
1
+ dir = File.dirname(__FILE__) + '/rb-music'
2
+ require dir + '/constants'
3
+ require dir + '/note'
4
+ require dir + '/scale'
5
+ require dir + '/note_set'
6
+ require dir + '/interval'
7
+
8
+ include RBMusic
@@ -0,0 +1,105 @@
1
+ module RBMusic
2
+ Error = Class.new(StandardError)
3
+ ArgumentError = Class.new(ArgumentError)
4
+
5
+ NOTE_NAMES = ["F", "C", "G", "D", "A", "E", "B"]
6
+ ACCIDENTALS = ["bb", "b", "", "#", "x"]
7
+
8
+ # notes - two dimensional [octave, fifth] - relative to the 'main' note
9
+ NOTES = {
10
+ "Fbb" => [10, -17],
11
+ "Cbb" => [10, -16],
12
+ "Gbb" => [9, -15],
13
+ "Dbb" => [8, -14],
14
+ "Abb" => [8, -13],
15
+ "Ebb" => [7, -12],
16
+ "Bbb" => [7, -11],
17
+
18
+ "Fb" => [6, -10],
19
+ "Cb" => [5, -9],
20
+ "Gb" => [5, -8],
21
+ "Db" => [4, -7],
22
+ "Ab" => [4, -6],
23
+ "Eb" => [3, -5],
24
+ "Bb" => [3, -4],
25
+
26
+ "F" => [2, -3],
27
+ "C" => [1, -2],
28
+ "G" => [1, -1],
29
+ "D" => [0, 0],
30
+ "A" => [0, 1],
31
+ "E" => [-1, 2],
32
+ "B" => [-1, 3],
33
+
34
+ "F#" => [-2, 4],
35
+ "C#" => [-3, 5],
36
+ "G#" => [-3, 6],
37
+ "D#" => [-4, 7],
38
+ "A#" => [-4, 8],
39
+ "E#" => [-5, 9],
40
+ "B#" => [-5, 10],
41
+
42
+ "Fx" => [-6, 11],
43
+ "Cx" => [-7, 12],
44
+ "Gx" => [-7, 13],
45
+ "Dx" => [-8, 14],
46
+ "Ax" => [-8, 15],
47
+ "Ex" => [-9, 16],
48
+ "Bx" => [-10, 17]
49
+ }
50
+
51
+ BASE_FREQ = 440 # A4 'main' note
52
+ BASE_OFFSET = [4, 1] # offset of base note from D0
53
+
54
+ # intervals - two dimensional [octave, fifth] - relative to the 'main' note
55
+ INTERVALS = {
56
+ unison: [0, 0],
57
+ minor_second: [3, -5],
58
+ major_second: [-1, 2],
59
+ minor_third: [2, -3],
60
+ major_third: [-2, 4],
61
+ fourth: [1, -1],
62
+ augmented_fourth: [-3, 6],
63
+ tritone: [-3, 6],
64
+ diminished_fifth: [4, -6],
65
+ fifth: [0, 1],
66
+ minor_sixth: [3, -4],
67
+ major_sixth: [-1, 3],
68
+ minor_seventh: [2, -2],
69
+ major_seventh: [-2, 5],
70
+ octave: [1, 0]
71
+ }
72
+
73
+ INTERVALS_SEMITONES = {
74
+ 0 => [0, 0],
75
+ 1 => [3, -5],
76
+ 2 => [-1, 2],
77
+ 3 => [2, -3],
78
+ 4 => [-2, 4],
79
+ 5 => [1, -1],
80
+ 6 => [-3, 6],
81
+ 7 => [0, 1],
82
+ 8 => [3, -4],
83
+ 9 => [-1, 3],
84
+ 10 => [2, -2],
85
+ 11 => [-2, 5],
86
+ 12 => [1, 0]
87
+ }
88
+
89
+ SCALES = {
90
+ major: [:major_second, :major_third, :fourth, :fifth, :major_sixth, :major_seventh],
91
+ natural_minor: [:major_second, :minor_third, :fourth, :fifth, :minor_sixth, :minor_seventh],
92
+ harmonic_minor: [:major_second, :minor_third, :fourth, :fifth, :minor_sixth, :major_seventh],
93
+ major_pentatonic: [:major_second, :major_third, :fifth, :major_sixth],
94
+ minor_pentatonic: [:minor_third, :fourth, :fifth, :minor_seventh],
95
+ blues: [:minor_third, :fourth, :augmented_fourth, :fifth, :minor_seventh],
96
+ dorian: [:major_second, :minor_third, :fourth, :fifth, :major_sixth, :minor_seventh],
97
+ phrygian: [:minor_second, :minor_third, :fourth, :fifth, :major_sixth, :minor_seventh],
98
+ lydian: [:major_second, :major_third, :augmented_fourth, :fifth, :major_sixth, :major_seventh],
99
+ mixolydian: [:major_second, :major_third, :fourth, :fifth, :major_sixth, :minor_seventh],
100
+ locrian: [:minor_second, :minor_third, :fourth, :diminished_fifth, :minor_sixth, :minor_seventh],
101
+ }
102
+ SCALES[:ionian] = SCALES[:major]
103
+ SCALES[:aeolian] = SCALES[:natural_minor]
104
+
105
+ end
@@ -0,0 +1,50 @@
1
+ module RBMusic
2
+
3
+ class Interval
4
+ attr_accessor :coord
5
+
6
+ def initialize(coord)
7
+ self.coord = coord
8
+ end
9
+
10
+ def self.from_name(name)
11
+ Interval.new(INTERVALS[name.to_sym])
12
+ end
13
+
14
+ def self.from_semitones(num)
15
+ Interval.new(INTERVALS_SEMITONES[num])
16
+ end
17
+
18
+ def self.from_tones_semitones(tone_semitone)
19
+ # multiply [tones, semitones] vector with [-1 2;3 -5] to get coordinate from tones and semitones
20
+ Interval.new([tone_semitone[0] * -1 + tone_semitone[1] * 3, tone_semitone[0] * 2 + tone_semitone[1] * -5])
21
+ end
22
+
23
+ def tone_semitone
24
+ # multiply coord vector with [5 2;3 1] to get coordinate in tones and semitones
25
+ # [5 2;3 1] is the inverse of [-1 2;3 -5], which is the coordinates of [tone; semitone]
26
+ @tone_semitone ||= [coord[0] * 5 + coord[1] * 3, coord[0] * 2 + coord[1] * 1]
27
+ end
28
+
29
+ def semitone
30
+ # number of semitones of interval = tones * 2 + semitones
31
+ tone_semitone[0] * 2 + tone_semitone[1]
32
+ end
33
+
34
+ def add(interval)
35
+ if interval.is_a?(String)
36
+ interval = Interval.from_name(interval)
37
+ end
38
+ Interval.new([coord[0] + interval.coord[0], coord[1] + interval.coord[1]])
39
+ end
40
+
41
+ def subtract(interval)
42
+ if interval.is_a?(String)
43
+ interval = Interval.from_name(interval)
44
+ end
45
+ Interval.new([coord[0] - interval.coord[0], coord[1] - interval.coord[1]])
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,107 @@
1
+ module RBMusic
2
+
3
+ class Note
4
+ attr_accessor :coord
5
+
6
+ def initialize(coord)
7
+ self.coord = coord
8
+ end
9
+
10
+ def self.from_latin(name)
11
+ raise ArgumentError unless name.is_a?(String)
12
+
13
+ note_parts = name.split(/(\d+)/)
14
+ note_name = note_parts.first
15
+ octave = note_parts.last.to_i
16
+
17
+ unless NOTES.has_key?(note_name) && note_parts.size < 3
18
+ raise ArgumentError
19
+ end
20
+
21
+ coordinate = [NOTES[note_name][0] + octave, NOTES[note_name][1]]
22
+
23
+ coordinate[0] -= BASE_OFFSET[0]
24
+ coordinate[1] -= BASE_OFFSET[1]
25
+
26
+ Note.new(coordinate)
27
+ end
28
+
29
+ def frequency
30
+ BASE_FREQ * (2.0 ** ((coord[0] * 1200 + coord[1] * 700.0) / 1200.0))
31
+ end
32
+
33
+ def accidental
34
+ @accidental ||= ((coord[1] + BASE_OFFSET[1]) / 7.0).round
35
+ end
36
+
37
+ def octave
38
+ # calculate octave of base note without accidentals
39
+ @octave ||= coord[0] + BASE_OFFSET[0] + 4 * accidental + ((coord[1] + BASE_OFFSET[1] - 7 * accidental) / 2).floor
40
+ end
41
+
42
+ def latin
43
+ return @latin if @latin
44
+ accidentalName = ACCIDENTALS[accidental + 2]
45
+ @latin ||= base_note_name + accidentalName
46
+ end
47
+
48
+ def ==(other)
49
+ other.is_a?(Note) && other.latin == latin && other.octave == octave
50
+ end
51
+
52
+ def enharmonic?(other)
53
+ raise ArgumentError unless other.is_a?(Note)
54
+
55
+ other.frequency == frequency
56
+ end
57
+ alias_method :enharmonically_equivalent_to?, :enharmonic?
58
+
59
+ def midi_note_number
60
+ # see http://www.phys.unsw.edu.au/jw/notes.html
61
+ 12 * Math.log2(frequency / 440) + 69
62
+ end
63
+
64
+ def scale(name, octaves = 1)
65
+ NoteSet.from_scale(Scale.new(latin, name), octave, octaves)
66
+ end
67
+
68
+ def add(that)
69
+ # if input is an array return an array
70
+ if that.is_a?(Array)
71
+ notes = that.map { |thing| add(thing) }
72
+ return NoteSet.new(notes)
73
+ end
74
+
75
+ # if input is string/symbol try to parse it as interval
76
+ if that.is_a?(String) || that.is_a?(Symbol)
77
+ that = Interval.from_name(that)
78
+ end
79
+
80
+ Note.new([coord[0] + that.coord[0], coord[1] + that.coord[1]])
81
+ end
82
+
83
+ def subtract(that)
84
+ if that.is_a?(Array)
85
+ notes = that.map { |thing| subtract(thing) }
86
+ return NoteSet.new(notes)
87
+ end
88
+
89
+ # if input is string try to parse it as interval
90
+ if that.is_a?(String) || that.is_a?(Symbol)
91
+ that = Interval.from_name(that)
92
+ end
93
+
94
+ coordinate = [coord[0] - that.coord[0], coord[1] - that.coord[1]]
95
+
96
+ # if input is another note return the difference as an Interval
97
+ that.is_a?(Note) ? Interval.new(coordinate) : Note.new(coordinate)
98
+ end
99
+
100
+ private
101
+
102
+ def base_note_name
103
+ @base_note_name ||= NOTE_NAMES[coord[1] + BASE_OFFSET[1] - accidental * 7 + 3]
104
+ end
105
+ end
106
+
107
+ end