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 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