musical_spec 0.0.1 → 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.
- data/Changelog.md +11 -0
- data/lib/musical_spec/formatter.rb +2 -2
- data/lib/musical_spec/note.rb +44 -38
- data/lib/musical_spec/version.rb +1 -1
- data/lib/musical_spec.rb +9 -0
- data/spec/musical_spec/note_spec.rb +60 -25
- metadata +10 -9
data/Changelog.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
## 0.0.2 / 2011-11-27
|
2
|
+
|
3
|
+
* Formatter correctly will not go higher than the highest note now, instead of
|
4
|
+
doing that odd 3-note trill that it did before. The vagaries of scientific pitch
|
5
|
+
notation!
|
6
|
+
* Music starts at the lowest possible pitch and climbs to the highest, so now
|
7
|
+
you get the full scale instead of getting to the highest note too early.
|
8
|
+
|
9
|
+
## 0.0.1 / 2011-11-26
|
10
|
+
|
11
|
+
Yeah, so this exists now.
|
@@ -6,8 +6,8 @@ module MusicalSpec
|
|
6
6
|
class Formatter < RSpec::Core::Formatters::ProgressFormatter
|
7
7
|
def initialize(output)
|
8
8
|
super(output)
|
9
|
-
@note =
|
10
|
-
@player =
|
9
|
+
@note = Note.new
|
10
|
+
@player = Player.new
|
11
11
|
end
|
12
12
|
|
13
13
|
attr_reader :player
|
data/lib/musical_spec/note.rb
CHANGED
@@ -1,22 +1,24 @@
|
|
1
1
|
module MusicalSpec
|
2
2
|
# Uses scientific notation, e.g. C4 is middle C.
|
3
3
|
class Note
|
4
|
-
|
5
|
-
# normalized back down to MAX_OCTAVE.
|
6
|
-
MAX_OCTAVE = 6
|
7
|
-
# The lowest octave this will play. If it goes lower than this, it will be
|
8
|
-
# normalized back up to MIN_OCTAVE.
|
9
|
-
MIN_OCTAVE = 2
|
4
|
+
include Comparable
|
10
5
|
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
SCALE_PROGRESSION = %w(C D E F G A B)
|
7
|
+
|
8
|
+
# Takes 1 optional argument, a note string like "C4".
|
9
|
+
def initialize(desired_note_string = nil)
|
10
|
+
if desired_note_string.nil?
|
11
|
+
self.note = LOWEST_NOTE.to_s
|
12
|
+
else
|
13
|
+
self.note = desired_note_string
|
14
|
+
end
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
attr_reader :letter, :octave
|
18
|
+
|
19
|
+
# A string like "C4".
|
20
|
+
def to_s
|
21
|
+
"#{letter}#{octave}"
|
20
22
|
end
|
21
23
|
|
22
24
|
# Set the note to a new one, e.g. `note.note = 'A5'`
|
@@ -25,42 +27,46 @@ module MusicalSpec
|
|
25
27
|
@letter = new_letter
|
26
28
|
@octave = new_octave.to_i
|
27
29
|
|
28
|
-
|
30
|
+
to_s
|
29
31
|
end
|
30
32
|
|
31
|
-
# Increase the pitch, handling octave changes.
|
33
|
+
# Increase the pitch, handling octave changes. Will not go above
|
34
|
+
# MusicalSpec::HIGHEST_NOTE.
|
32
35
|
def next!
|
33
|
-
if
|
34
|
-
@letter
|
35
|
-
|
36
|
-
|
37
|
-
@letter
|
38
|
-
|
39
|
-
|
36
|
+
if self != HIGHEST_NOTE
|
37
|
+
if @letter == 'B'
|
38
|
+
@letter = 'C'
|
39
|
+
@octave += 1
|
40
|
+
elsif @letter == 'G'
|
41
|
+
@letter = 'A'
|
42
|
+
else
|
43
|
+
@letter.next!
|
44
|
+
end
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
43
|
-
# Decrease the pitch, handling octave changes.
|
48
|
+
# Decrease the pitch, handling octave changes. Will not go below
|
49
|
+
# MusicalSpec::LOWEST_NOTE.
|
44
50
|
def prev!
|
45
|
-
if
|
46
|
-
@letter
|
47
|
-
|
48
|
-
|
49
|
-
@letter
|
50
|
-
|
51
|
-
|
51
|
+
if self != LOWEST_NOTE
|
52
|
+
if @letter == 'C'
|
53
|
+
@letter = 'B'
|
54
|
+
@octave -= 1
|
55
|
+
elsif @letter == 'A'
|
56
|
+
@letter = 'G'
|
57
|
+
else
|
58
|
+
@letter = (@letter.ord - 1).chr
|
59
|
+
end
|
52
60
|
end
|
53
61
|
end
|
54
62
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
if
|
59
|
-
|
60
|
-
elsif @octave < MIN_OCTAVE
|
61
|
-
MIN_OCTAVE
|
63
|
+
def <=>(other_note)
|
64
|
+
other_letter = other_note.letter
|
65
|
+
other_octave = other_note.octave
|
66
|
+
if octave == other_octave
|
67
|
+
SCALE_PROGRESSION.index(letter) <=> SCALE_PROGRESSION.index(other_letter)
|
62
68
|
else
|
63
|
-
|
69
|
+
octave <=> other_octave
|
64
70
|
end
|
65
71
|
end
|
66
72
|
end
|
data/lib/musical_spec/version.rb
CHANGED
data/lib/musical_spec.rb
CHANGED
@@ -6,5 +6,14 @@ require "musical_spec/formatter"
|
|
6
6
|
require "musical_spec/version"
|
7
7
|
|
8
8
|
module MusicalSpec
|
9
|
+
# Create a singleton due to Bloopsaphone's thread wackiness.
|
9
10
|
ONE_TRUE_BLOOPSAPHONE = Bloops.new
|
11
|
+
|
12
|
+
# The highest note the formatter will play. If it goes higher than this, it
|
13
|
+
# will be normalized back down.
|
14
|
+
HIGHEST_NOTE = Note.new('B6')
|
15
|
+
|
16
|
+
# The lowest note this formatter will play. If it goes lower than this, it
|
17
|
+
# will be normalized back up.
|
18
|
+
LOWEST_NOTE = Note.new('C2')
|
10
19
|
end
|
@@ -1,52 +1,48 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe MusicalSpec::Note do
|
4
|
-
it 'defaults to
|
5
|
-
subject.
|
4
|
+
it 'defaults to the lowest note' do
|
5
|
+
subject.to_s.should == MusicalSpec::LOWEST_NOTE.to_s
|
6
6
|
end
|
7
7
|
|
8
|
-
it '
|
9
|
-
MusicalSpec::Note
|
8
|
+
it 'can be initialized with a note' do
|
9
|
+
MusicalSpec::Note.new('E4').to_s.should == 'E4'
|
10
10
|
end
|
11
11
|
|
12
|
-
it '
|
13
|
-
|
12
|
+
it 'does not go higher than B6' do
|
13
|
+
subject.note = 'B6'
|
14
|
+
subject.next!
|
15
|
+
subject.to_s.should == 'B6'
|
14
16
|
end
|
15
17
|
|
16
|
-
it '
|
17
|
-
subject.note = '
|
18
|
-
subject.
|
19
|
-
|
20
|
-
|
21
|
-
it 'does not let the octave go above MAX_OCTAVE' do
|
22
|
-
very_high_octave = MusicalSpec::Note::MAX_OCTAVE + 1
|
23
|
-
subject.note = "A#{very_high_octave}"
|
24
|
-
subject.note.should == "A#{MusicalSpec::Note::MAX_OCTAVE}"
|
18
|
+
it 'does not go lower than C2' do
|
19
|
+
subject.note = 'C2'
|
20
|
+
subject.prev!
|
21
|
+
subject.to_s.should == 'C2'
|
25
22
|
end
|
26
23
|
|
27
|
-
it '
|
28
|
-
|
29
|
-
subject.
|
30
|
-
subject.note.should == "A#{MusicalSpec::Note::MIN_OCTAVE}"
|
24
|
+
it 'allows setting the note' do
|
25
|
+
subject.note = 'A4'
|
26
|
+
subject.to_s.should == 'A4'
|
31
27
|
end
|
32
28
|
|
33
29
|
context '#next!' do
|
34
30
|
it 'increases the note by 1' do
|
35
31
|
subject.note = 'C4'
|
36
32
|
subject.next!
|
37
|
-
subject.
|
33
|
+
subject.to_s.should == 'D4'
|
38
34
|
end
|
39
35
|
|
40
36
|
it 'changes octaves when moving from B to C' do
|
41
37
|
subject.note = 'B4'
|
42
38
|
subject.next!
|
43
|
-
subject.
|
39
|
+
subject.to_s.should == 'C5'
|
44
40
|
end
|
45
41
|
|
46
42
|
it 'does not change octaves when moving from G to A' do
|
47
43
|
subject.note = 'G4'
|
48
44
|
subject.next!
|
49
|
-
subject.
|
45
|
+
subject.to_s.should == 'A4'
|
50
46
|
end
|
51
47
|
end
|
52
48
|
|
@@ -54,19 +50,58 @@ describe MusicalSpec::Note do
|
|
54
50
|
it 'decreases the note by 1' do
|
55
51
|
subject.note = 'E4'
|
56
52
|
subject.prev!
|
57
|
-
subject.
|
53
|
+
subject.to_s.should == 'D4'
|
58
54
|
end
|
59
55
|
|
60
56
|
it 'changes octaves when moving from C to B' do
|
61
57
|
subject.note = 'C4'
|
62
58
|
subject.prev!
|
63
|
-
subject.
|
59
|
+
subject.to_s.should == 'B3'
|
64
60
|
end
|
65
61
|
|
66
62
|
it 'does not change octaves when moving from A to G' do
|
67
63
|
subject.note = 'A4'
|
68
64
|
subject.prev!
|
69
|
-
subject.
|
65
|
+
subject.to_s.should == 'G4'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context '<=>' do
|
70
|
+
it 'knows that D4 < E4' do
|
71
|
+
d4.should be < e4
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'knows that E4 > D4' do
|
75
|
+
e4.should be > d4
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'knows that C4 > B3' do
|
79
|
+
c4.should be > b3
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'knows that B3 < C4' do
|
83
|
+
b3.should be < c4
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'knows that A4 > G4' do
|
87
|
+
a4.should be > g4
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'knows that A4 == A4' do
|
91
|
+
a4.should == a4
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'knows that G4 < A4' do
|
95
|
+
g4.should be < a4
|
70
96
|
end
|
97
|
+
|
98
|
+
let(:d4) { MusicalSpec::Note.new('D4') }
|
99
|
+
let(:e4) { MusicalSpec::Note.new('E4') }
|
100
|
+
|
101
|
+
let(:c4) { MusicalSpec::Note.new('C4') }
|
102
|
+
let(:b3) { MusicalSpec::Note.new('B3') }
|
103
|
+
|
104
|
+
let(:a4) { MusicalSpec::Note.new('A4') }
|
105
|
+
let(:g4) { MusicalSpec::Note.new('G4') }
|
71
106
|
end
|
72
107
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: musical_spec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2011-11-27 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bloopsaphone
|
16
|
-
requirement: &
|
16
|
+
requirement: &2153575200 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0.4'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2153575200
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec-core
|
27
|
-
requirement: &
|
27
|
+
requirement: &2153574000 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '2.0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2153574000
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rspec
|
38
|
-
requirement: &
|
38
|
+
requirement: &2153573280 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '2.0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2153573280
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: bourne
|
49
|
-
requirement: &
|
49
|
+
requirement: &2153572800 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: '1.0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2153572800
|
58
58
|
description: A musical formatter for RSpec.
|
59
59
|
email:
|
60
60
|
- gabe@thoughtbot.com
|
@@ -63,6 +63,7 @@ extensions: []
|
|
63
63
|
extra_rdoc_files: []
|
64
64
|
files:
|
65
65
|
- .gitignore
|
66
|
+
- Changelog.md
|
66
67
|
- Gemfile
|
67
68
|
- README.md
|
68
69
|
- Rakefile
|