motion-music 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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