musical_spec 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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 = MusicalSpec::Note.new
10
- @player = MusicalSpec::Player.new
9
+ @note = Note.new
10
+ @player = Player.new
11
11
  end
12
12
 
13
13
  attr_reader :player
@@ -1,22 +1,24 @@
1
1
  module MusicalSpec
2
2
  # Uses scientific notation, e.g. C4 is middle C.
3
3
  class Note
4
- # The highest octave this will play. If it goes higher than this, it will be
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
- def initialize
12
- @letter = 'C'
13
- @octave = 4
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
- # A string like "C4". Octave (the number) does not go above MAX_OCTAVE or
17
- # below MIN_OCTAVE.
18
- def note
19
- "#{@letter}#{normalized_octave}"
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
- note
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 @letter == 'B'
34
- @letter = 'C'
35
- @octave += 1
36
- elsif @letter == 'G'
37
- @letter = 'A'
38
- else
39
- @letter.next!
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 @letter == 'C'
46
- @letter = 'B'
47
- @octave -= 1
48
- elsif @letter == 'A'
49
- @letter = 'G'
50
- else
51
- @letter = (@letter.ord - 1).chr
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
- private
56
-
57
- def normalized_octave
58
- if @octave > MAX_OCTAVE
59
- MAX_OCTAVE
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
- @octave
69
+ octave <=> other_octave
64
70
  end
65
71
  end
66
72
  end
@@ -1,3 +1,3 @@
1
1
  module MusicalSpec
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
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 middle C' do
5
- subject.note.should == 'C4'
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 'sets MAX_OCTAVE to 6' do
9
- MusicalSpec::Note::MAX_OCTAVE.should == 6
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 'sets MIN_OCTAVE to 2' do
13
- MusicalSpec::Note::MIN_OCTAVE.should == 2
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 'allows setting the note' do
17
- subject.note = 'A4'
18
- subject.note.should == 'A4'
19
- end
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 'does not let the octave go below MIN_OCTAVE' do
28
- very_low_octave = MusicalSpec::Note::MIN_OCTAVE - 1
29
- subject.note = "A#{very_low_octave}"
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.note.should == 'D4'
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.note.should == 'C5'
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.note.should == 'A4'
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.note.should == 'D4'
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.note.should == 'B3'
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.note.should == 'G4'
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.1
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: &2153435480 !ruby/object:Gem::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: *2153435480
24
+ version_requirements: *2153575200
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec-core
27
- requirement: &2153433840 !ruby/object:Gem::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: *2153433840
35
+ version_requirements: *2153574000
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &2153433380 !ruby/object:Gem::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: *2153433380
46
+ version_requirements: *2153573280
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bourne
49
- requirement: &2153432720 !ruby/object:Gem::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: *2153432720
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