beats 1.3.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.markdown +22 -42
  4. data/bin/beats +6 -7
  5. data/lib/beats.rb +2 -1
  6. data/lib/beats/audioengine.rb +13 -13
  7. data/lib/beats/beatsrunner.rb +7 -8
  8. data/lib/beats/kit.rb +12 -156
  9. data/lib/beats/kit_builder.rb +74 -0
  10. data/lib/beats/pattern.rb +2 -22
  11. data/lib/beats/song.rb +5 -55
  12. data/lib/beats/songoptimizer.rb +3 -3
  13. data/lib/beats/songparser.rb +25 -46
  14. data/lib/beats/track.rb +20 -31
  15. data/lib/beats/transforms/song_swinger.rb +2 -4
  16. data/lib/wavefile/cachingwriter.rb +2 -2
  17. data/test/audioengine_test.rb +22 -24
  18. data/test/audioutils_test.rb +1 -1
  19. data/test/cachingwriter_test.rb +13 -12
  20. data/test/fixtures/invalid/leading_bar_line.txt +15 -0
  21. data/test/fixtures/{valid → invalid}/with_structure.txt +2 -2
  22. data/test/fixtures/valid/multiple_tracks_same_sound.txt +2 -1
  23. data/test/fixtures/valid/optimize_pattern_collision.txt +4 -5
  24. data/test/fixtures/valid/track_with_spaces.txt +13 -0
  25. data/test/includes.rb +1 -4
  26. data/test/integration_test.rb +5 -5
  27. data/test/kit_builder_test.rb +52 -0
  28. data/test/kit_test.rb +18 -141
  29. data/test/pattern_test.rb +66 -1
  30. data/test/song_swinger_test.rb +2 -2
  31. data/test/song_test.rb +9 -33
  32. data/test/songoptimizer_test.rb +18 -18
  33. data/test/songparser_test.rb +20 -10
  34. data/test/track_test.rb +23 -9
  35. metadata +26 -31
  36. data/ext/mkrf_conf.rb +0 -28
  37. data/test/fixtures/invalid/template.txt +0 -31
  38. data/test/fixtures/valid/foo.txt +0 -18
  39. data/test/sounds/bass.wav +0 -0
  40. data/test/sounds/bass2.wav +0 -0
  41. data/test/sounds/sine-mono-8bit.wav +0 -0
  42. data/test/sounds/tone.wav +0 -0
@@ -1,6 +1,6 @@
1
1
  require 'includes'
2
2
 
3
- class PatternTest < Test::Unit::TestCase
3
+ class PatternTest < Minitest::Test
4
4
  SAMPLE_RATE = 44100
5
5
  SECONDS_IN_MINUTE = 60.0
6
6
 
@@ -42,6 +42,60 @@ class PatternTest < Test::Unit::TestCase
42
42
  assert_equal(pattern.tracks.length, 3)
43
43
  end
44
44
 
45
+ def test_track
46
+ pattern = Pattern.new("whatevs")
47
+
48
+ assert_equal({}, pattern.tracks)
49
+
50
+ pattern.track("my_sound", "X...X...")
51
+ assert_pattern_tracks(pattern, {"my_sound" => {name: "my_sound", rhythm: "X...X..."}})
52
+
53
+ # Rhythm is shorter than length of current longer rhythm, so should be made same length
54
+ pattern.track("my_other_sound", "X...")
55
+ assert_pattern_tracks(pattern, {"my_sound" => {name: "my_sound", rhythm: "X...X..."},
56
+ "my_other_sound" => {name: "my_other_sound", rhythm: "X......."}})
57
+
58
+ # Track has same name as previous track, and longer rhythm than previous tracks.
59
+ # Track should have expected name, but pattern key be unique.
60
+ # The rhythm of other existing tracks should be lengthened.
61
+ pattern.track("my_sound", ".X..........")
62
+ assert_pattern_tracks(pattern, {"my_sound" => {name: "my_sound", rhythm: "X...X......."},
63
+ "my_other_sound" => {name: "my_other_sound", rhythm: "X..........."},
64
+ "my_sound2" => {name: "my_sound", rhythm: ".X.........."}})
65
+
66
+ pattern.track("my_sound2", "..X.........")
67
+ assert_pattern_tracks(pattern, {"my_sound" => {name: "my_sound", rhythm: "X...X......."},
68
+ "my_other_sound" => {name: "my_other_sound", rhythm: "X..........."},
69
+ "my_sound2" => {name: "my_sound", rhythm: ".X.........."},
70
+ "my_sound22" => {name: "my_sound2", rhythm: "..X........."}})
71
+
72
+ pattern.track("my_sound", "..")
73
+ assert_pattern_tracks(pattern, {"my_sound" => {name: "my_sound", rhythm: "X...X......."},
74
+ "my_other_sound" => {name: "my_other_sound", rhythm: "X..........."},
75
+ "my_sound2" => {name: "my_sound", rhythm: ".X.........."},
76
+ "my_sound22" => {name: "my_sound2", rhythm: "..X........."},
77
+ "my_sound3" => {name: "my_sound", rhythm: "............"},})
78
+ end
79
+
80
+ def test_track_unique_name_already_taken
81
+ pattern = Pattern.new("whatevs")
82
+
83
+ assert_equal({}, pattern.tracks)
84
+
85
+ pattern.track("my_sound2", "X...X...")
86
+ assert_pattern_tracks(pattern, {"my_sound2" => {name: "my_sound2", rhythm: "X...X..."}})
87
+
88
+ pattern.track("my_sound", "X.X.X.X.")
89
+ assert_pattern_tracks(pattern, {"my_sound2" => {name: "my_sound2", rhythm: "X...X..."},
90
+ "my_sound" => {name: "my_sound", rhythm: "X.X.X.X."}})
91
+
92
+ # The first attempt at a unique name would be "my_sound2", but that is already taken
93
+ pattern.track("my_sound", "XXXXXXXX")
94
+ assert_pattern_tracks(pattern, {"my_sound2" => {name: "my_sound2", rhythm: "X...X..."},
95
+ "my_sound" => {name: "my_sound", rhythm: "X.X.X.X."},
96
+ "my_sound3" => {name: "my_sound", rhythm: "XXXXXXXX"}})
97
+ end
98
+
45
99
  def test_step_count
46
100
  test_patterns = generate_test_data
47
101
 
@@ -96,4 +150,15 @@ class PatternTest < Test::Unit::TestCase
96
150
  assert_equal(false, left_pattern.same_tracks_as?(something_extra))
97
151
  assert_equal(false, something_extra.same_tracks_as?(left_pattern))
98
152
  end
153
+
154
+ private
155
+
156
+ def assert_pattern_tracks(pattern, expected_pattern_structure)
157
+ assert_equal(expected_pattern_structure.keys, pattern.tracks.keys)
158
+
159
+ expected_pattern_structure.each do |pattern_key, expected_track|
160
+ assert_equal(expected_track[:name], pattern.tracks[pattern_key].name)
161
+ assert_equal(expected_track[:rhythm], pattern.tracks[pattern_key].rhythm)
162
+ end
163
+ end
99
164
  end
@@ -1,6 +1,6 @@
1
1
  require 'includes'
2
2
 
3
- class SongSwingerTest < Test::Unit::TestCase
3
+ class SongSwingerTest < Minitest::Test
4
4
  def test_full_song_swing_rate_8
5
5
  base_path = File.dirname(__FILE__) + "/sounds"
6
6
  song, kit = SongParser.new.parse(base_path, File.read("test/fixtures/valid/example_mono_16_base_path.txt"))
@@ -145,7 +145,7 @@ class SongSwingerTest < Test::Unit::TestCase
145
145
  song = Song.new
146
146
  song.tempo = 100
147
147
 
148
- assert_raise(Transforms::InvalidSwingRateError) do
148
+ assert_raises(Transforms::SongSwinger::InvalidSwingRateError) do
149
149
  song = Transforms::SongSwinger.transform(song, invalid_swing_rate)
150
150
  end
151
151
  end
@@ -1,6 +1,6 @@
1
1
  require 'includes'
2
2
 
3
- class SongTest < Test::Unit::TestCase
3
+ class SongTest < Minitest::Test
4
4
  FIXTURES = [:repeats_not_specified,
5
5
  :pattern_with_overflow,
6
6
  :example_no_kit,
@@ -50,40 +50,28 @@ class SongTest < Test::Unit::TestCase
50
50
 
51
51
  song.tempo = 150
52
52
  assert_equal(150, song.tempo)
53
-
53
+
54
54
  song.tempo = 145.854
55
55
  assert_equal(145.854, song.tempo)
56
56
 
57
- assert_raise(InvalidTempoError) do
58
- song.tempo = -1
59
- end
60
-
61
- assert_raise(InvalidTempoError) do
62
- song.tempo = -1.0
63
- end
64
-
65
- assert_raise(InvalidTempoError) do
66
- song.tempo = "abc"
67
- end
68
-
69
- assert_raise(InvalidTempoError) do
70
- song.tempo = "150"
57
+ [-1, -1.0, "abc", "150"].each do |invalid_tempo|
58
+ assert_raises(Song::InvalidTempoError) { song.tempo = invalid_tempo }
71
59
  end
72
60
  end
73
61
 
74
62
  def test_pattern
75
63
  song = Song.new
76
- verse1 = song.pattern :Verse
64
+ verse1 = song.pattern(:Verse)
77
65
 
78
66
  assert_equal(:Verse, verse1.name)
79
67
  assert_equal({:Verse => verse1}, song.patterns)
80
68
 
81
- verse2 = song.pattern :Verse
69
+ verse2 = song.pattern(:Verse)
82
70
  assert_equal(:Verse, verse2.name)
83
71
  assert_equal({:Verse => verse2}, song.patterns)
84
- assert_not_equal(verse1, verse2)
72
+ refute_equal(verse1, verse2)
85
73
 
86
- chorus = song.pattern :Chorus
74
+ chorus = song.pattern(:Chorus)
87
75
  assert_equal(2, song.patterns.length)
88
76
  assert_equal({:Chorus => chorus, :Verse => verse2}, song.patterns)
89
77
  end
@@ -128,7 +116,7 @@ class SongTest < Test::Unit::TestCase
128
116
  original_song = test_songs[:example_no_kit]
129
117
  cloned_song = original_song.copy_ignoring_patterns_and_flow
130
118
 
131
- assert_not_equal(cloned_song, original_song)
119
+ refute_equal(cloned_song, original_song)
132
120
  assert_equal(cloned_song.tempo, original_song.tempo)
133
121
  assert_equal([], cloned_song.flow)
134
122
  assert_equal({}, cloned_song.patterns)
@@ -178,16 +166,4 @@ class SongTest < Test::Unit::TestCase
178
166
  assert_equal(3, test_songs[:example_no_kit].patterns.length)
179
167
  assert_equal(Hash, test_songs[:example_no_kit].patterns.class)
180
168
  end
181
-
182
- def test_to_yaml
183
- test_songs = generate_test_data
184
- kit = Kit.new("test/sounds", {"bass" => "bass_mono_8.wav",
185
- "snare" => "snare_mono_8.wav",
186
- "hhclosed" => "hh_closed_mono_8.wav",
187
- "hhopen" => "hh_open_mono_8.wav"})
188
-
189
- result = test_songs[:example_with_kit].to_yaml(kit)
190
-
191
- assert_equal(File.read("test/fixtures/yaml/song_yaml.txt"), result)
192
- end
193
169
  end
@@ -6,7 +6,7 @@ class MockSongOptimizer < SongOptimizer
6
6
  end
7
7
  end
8
8
 
9
- class SongOptimizerTest < Test::Unit::TestCase
9
+ class SongOptimizerTest < Minitest::Test
10
10
  FIXTURE_BASE_PATH = File.dirname(__FILE__) + "/.."
11
11
 
12
12
  EXAMPLE_SONG_YAML = "
@@ -18,10 +18,10 @@ Song:
18
18
  - Verse: x2
19
19
  - Chorus: x4
20
20
  Kit:
21
- - bass: sounds/bass.wav
22
- - snare: sounds/snare.wav
23
- - hh_closed: sounds/hh_closed.wav
24
- - agogo: sounds/agogo_high.wav
21
+ - bass: sounds/bass_mono_8.wav
22
+ - snare: sounds/snare_mono_8.wav
23
+ - hh_closed: sounds/hh_closed_mono_8.wav
24
+ - agogo: sounds/agogo_high_mono_8.wav
25
25
 
26
26
  Verse:
27
27
  - bass: X...X...X...X...
@@ -33,8 +33,8 @@ Chorus:
33
33
  - bass: X...X...XX..X...
34
34
  - snare: ....X.......X...
35
35
  - hh_closed: X.XXX.XXX.XX..X.
36
- - sounds/tom4.wav: ...........X....
37
- - sounds/tom2.wav: ..............X."
36
+ - sounds/tom4_mono_8.wav: ...........X....
37
+ - sounds/tom2_mono_8.wav: ..............X."
38
38
 
39
39
  EXAMPLE_SONG_YAML_EMPTY_SUB_PATTERN = "
40
40
  Song:
@@ -42,8 +42,8 @@ Song:
42
42
  Flow:
43
43
  - Verse: x1
44
44
  Kit:
45
- - bass: sounds/bass.wav
46
- - snare: sounds/snare.wav
45
+ - bass: sounds/bass_mono_8.wav
46
+ - snare: sounds/snare_mono_8.wav
47
47
 
48
48
  Verse:
49
49
  - bass: X.......X...
@@ -55,7 +55,7 @@ Verse:
55
55
 
56
56
  def test_optimize
57
57
  parser = SongParser.new
58
- original_song, kit = parser.parse(File.dirname(__FILE__) + "/..", EXAMPLE_SONG_YAML)
58
+ original_song, kit = parser.parse(File.dirname(__FILE__), EXAMPLE_SONG_YAML)
59
59
 
60
60
  optimizer = SongOptimizer.new
61
61
  optimized_song = optimizer.optimize(original_song, 4)
@@ -96,17 +96,17 @@ Verse:
96
96
  assert_equal(pattern.tracks["hh_closed"].rhythm, "X.XX")
97
97
 
98
98
  pattern = optimized_song.patterns[:chorus_8]
99
- assert_equal(pattern.tracks.keys.sort, ["bass", "hh_closed", "sounds/tom4.wav"])
99
+ assert_equal(pattern.tracks.keys.sort, ["bass", "hh_closed", "sounds/tom4_mono_8.wav"])
100
100
  assert_equal(pattern.tracks["bass"].rhythm, "XX..")
101
101
  assert_equal(pattern.tracks["hh_closed"].rhythm, "X.XX")
102
- assert_equal(pattern.tracks["sounds/tom4.wav"].rhythm, "...X")
102
+ assert_equal(pattern.tracks["sounds/tom4_mono_8.wav"].rhythm, "...X")
103
103
 
104
104
  pattern = optimized_song.patterns[:chorus_12]
105
- assert_equal(pattern.tracks.keys.sort, ["bass", "hh_closed", "snare", "sounds/tom2.wav"])
105
+ assert_equal(pattern.tracks.keys.sort, ["bass", "hh_closed", "snare", "sounds/tom2_mono_8.wav"])
106
106
  assert_equal(pattern.tracks["bass"].rhythm, "X...")
107
107
  assert_equal(pattern.tracks["snare"].rhythm, "X...")
108
108
  assert_equal(pattern.tracks["hh_closed"].rhythm, "..X.")
109
- assert_equal(pattern.tracks["sounds/tom2.wav"].rhythm, "..X.")
109
+ assert_equal(pattern.tracks["sounds/tom2_mono_8.wav"].rhythm, "..X.")
110
110
 
111
111
  assert_equal(optimized_song.flow, [:chorus_0, :chorus_0, :verse_8, :verse_12,
112
112
  :chorus_0, :chorus_0, :verse_8, :verse_12,
@@ -124,7 +124,7 @@ Verse:
124
124
 
125
125
  def test_optimize_song_nondivisible_max_pattern_length
126
126
  parser = SongParser.new
127
- original_song, kit = parser.parse(File.dirname(__FILE__) + "/..", EXAMPLE_SONG_YAML_EMPTY_SUB_PATTERN)
127
+ original_song, kit = parser.parse(File.dirname(__FILE__), EXAMPLE_SONG_YAML_EMPTY_SUB_PATTERN)
128
128
 
129
129
  optimizer = SongOptimizer.new
130
130
  optimized_song = optimizer.optimize(original_song, 7)
@@ -151,7 +151,7 @@ Verse:
151
151
 
152
152
  def test_optimize_song_containing_empty_pattern
153
153
  parser = SongParser.new
154
- original_song, kit = parser.parse(File.dirname(__FILE__) + "/..", EXAMPLE_SONG_YAML_EMPTY_SUB_PATTERN)
154
+ original_song, kit = parser.parse(File.dirname(__FILE__), EXAMPLE_SONG_YAML_EMPTY_SUB_PATTERN)
155
155
 
156
156
  optimizer = SongOptimizer.new
157
157
  optimized_song = optimizer.optimize(original_song, 4)
@@ -161,8 +161,8 @@ Verse:
161
161
  assert_equal("X...", pattern.tracks["bass"].rhythm)
162
162
 
163
163
  pattern = optimized_song.patterns[:verse_4]
164
- assert_equal(["placeholder"], pattern.tracks.keys.sort)
165
- assert_equal("....", pattern.tracks["placeholder"].rhythm)
164
+ assert_equal([Kit::PLACEHOLDER_TRACK_NAME], pattern.tracks.keys.sort)
165
+ assert_equal("....", pattern.tracks[Kit::PLACEHOLDER_TRACK_NAME].rhythm)
166
166
 
167
167
  pattern = optimized_song.patterns[:verse_8]
168
168
  assert_equal(["bass", "snare"], pattern.tracks.keys.sort)
@@ -1,6 +1,6 @@
1
1
  require 'includes'
2
2
 
3
- class SongParserTest < Test::Unit::TestCase
3
+ class SongParserTest < Minitest::Test
4
4
  FIXTURE_BASE_PATH = File.dirname(__FILE__) + "/.."
5
5
 
6
6
  # TODO: Add fixture for track with no rhythm
@@ -11,8 +11,8 @@ class SongParserTest < Test::Unit::TestCase
11
11
  :example_no_kit,
12
12
  :example_with_kit,
13
13
  :example_with_empty_track,
14
+ :track_with_spaces,
14
15
  :multiple_tracks_same_sound,
15
- :with_structure,
16
16
  :example_swung_8th,
17
17
  :example_swung_16th,
18
18
  :example_unswung]
@@ -24,7 +24,9 @@ class SongParserTest < Test::Unit::TestCase
24
24
  :bad_swing_rate_2,
25
25
  :no_header,
26
26
  :no_flow,
27
+ :with_structure,
27
28
  :pattern_with_no_tracks,
29
+ :leading_bar_line,
28
30
  :sound_in_kit_not_found,
29
31
  :sound_in_track_not_found,
30
32
  :sound_in_kit_wrong_format,
@@ -84,6 +86,12 @@ class SongParserTest < Test::Unit::TestCase
84
86
  assert_equal("........", song.patterns[:verse].tracks["test/sounds/bass_mono_8.wav"].rhythm)
85
87
  assert_equal("X...X...", song.patterns[:verse].tracks["test/sounds/snare_mono_8.wav"].rhythm)
86
88
 
89
+ song = test_songs[:track_with_spaces]
90
+ assert_equal(1, song.patterns.length)
91
+ assert_equal(2, song.patterns[:verse].tracks.length)
92
+ assert_equal("X...X...X...X...", song.patterns[:verse].tracks["bass"].rhythm)
93
+ assert_equal("....X.......X...", song.patterns[:verse].tracks["snare"].rhythm)
94
+
87
95
  song = test_songs[:multiple_tracks_same_sound]
88
96
  assert_equal(2, song.patterns.length)
89
97
  assert_equal(7, song.patterns[:verse].tracks.length)
@@ -96,12 +104,14 @@ class SongParserTest < Test::Unit::TestCase
96
104
  assert_equal("..............X.", song.patterns[:verse].tracks["snare"].rhythm)
97
105
  assert_equal("X.XXX.XXX.X.X.X.", song.patterns[:verse].tracks["hh_closed"].rhythm)
98
106
  assert_equal("..............XX", song.patterns[:verse].tracks["agogo"].rhythm)
99
-
100
- song = test_songs[:with_structure]
101
- assert_equal([:verse, :verse], song.flow)
102
- assert_equal(1, song.patterns.length)
103
- assert_equal(1, song.patterns[:verse].tracks.length)
104
- assert_equal("X...X...", song.patterns[:verse].tracks["test/sounds/bass_mono_8.wav"].rhythm)
107
+ assert_equal(["bass", "bass2", "hh_closed", "snare", "test/sounds/tom2_mono_16.wav", "test/sounds/tom4_mono_16.wav"],
108
+ song.patterns[:chorus].tracks.keys.sort)
109
+ assert_equal("X...X...XX..X...", song.patterns[:chorus].tracks["bass"].rhythm)
110
+ assert_equal("....X.......X...", song.patterns[:chorus].tracks["snare"].rhythm)
111
+ assert_equal("X.XXX.XXX.XX..X.", song.patterns[:chorus].tracks["hh_closed"].rhythm)
112
+ assert_equal("..X..X..X..X..X.", song.patterns[:chorus].tracks["bass2"].rhythm)
113
+ assert_equal("...........X....", song.patterns[:chorus].tracks["test/sounds/tom4_mono_16.wav"].rhythm)
114
+ assert_equal("..............X.", song.patterns[:chorus].tracks["test/sounds/tom2_mono_16.wav"].rhythm)
105
115
 
106
116
  song = test_songs[:example_swung_8th]
107
117
  assert_equal(180, song.tempo)
@@ -139,12 +149,12 @@ class SongParserTest < Test::Unit::TestCase
139
149
 
140
150
  def test_invalid_parse
141
151
  INVALID_FIXTURES.each do |fixture|
142
- assert_raise(SongParseError) do
152
+ assert_raises(SongParser::ParseError) do
143
153
  song = SongParserTest.load_fixture("invalid/#{fixture}.txt")
144
154
  end
145
155
  end
146
156
 
147
- assert_raise(InvalidRhythmError) do
157
+ assert_raises(Track::InvalidRhythmError) do
148
158
  song = SongParserTest.load_fixture("invalid/bad_rhythm.txt")
149
159
  end
150
160
  end
@@ -1,6 +1,6 @@
1
1
  require 'includes'
2
2
 
3
- class TrackTest < Test::Unit::TestCase
3
+ class TrackTest < Minitest::Test
4
4
  def generate_test_data
5
5
  test_tracks = {}
6
6
 
@@ -8,8 +8,9 @@ class TrackTest < Test::Unit::TestCase
8
8
  test_tracks[:solo] = Track.new("bass", "X")
9
9
  test_tracks[:with_overflow] = Track.new("bass", "...X")
10
10
  test_tracks[:with_barlines] = Track.new("bass", "|X.X.|X.X.|")
11
+ test_tracks[:with_spaces] = Track.new("bass", " X... X.X. ")
11
12
  test_tracks[:placeholder] = Track.new("bass", "....")
12
- test_tracks[:complicated] = Track.new("bass", "..X...X...X...X.X...X...X...X...")
13
+ test_tracks[:complicated] = Track.new("bass", "..XX..X...X...X.X...X...X...X...")
13
14
 
14
15
  test_tracks
15
16
  end
@@ -17,26 +18,39 @@ class TrackTest < Test::Unit::TestCase
17
18
  def test_initialize
18
19
  test_tracks = generate_test_data
19
20
 
20
- assert_equal([0], test_tracks[:blank].beats)
21
+ assert_equal([0], test_tracks[:blank].trigger_step_lengths)
21
22
  assert_equal("bass", test_tracks[:blank].name)
22
23
  assert_equal("", test_tracks[:blank].rhythm)
23
24
 
24
- assert_equal([0, 1], test_tracks[:solo].beats)
25
+ assert_equal([0, 1], test_tracks[:solo].trigger_step_lengths)
25
26
  assert_equal("bass", test_tracks[:solo].name)
26
27
  assert_equal("X", test_tracks[:solo].rhythm)
27
28
 
28
- assert_equal([3, 1], test_tracks[:with_overflow].beats)
29
+ assert_equal([3, 1], test_tracks[:with_overflow].trigger_step_lengths)
29
30
  assert_equal("...X", test_tracks[:with_overflow].rhythm)
30
31
 
31
- assert_equal([0, 2, 2, 2, 2], test_tracks[:with_barlines].beats)
32
+ assert_equal([0, 2, 2, 2, 2], test_tracks[:with_barlines].trigger_step_lengths)
32
33
  # Bar lines should be removed from rhythm:
33
34
  assert_equal("X.X.X.X.", test_tracks[:with_barlines].rhythm)
34
35
 
35
- assert_equal([4], test_tracks[:placeholder].beats)
36
+ assert_equal([0, 4, 2, 2], test_tracks[:with_spaces].trigger_step_lengths)
37
+ # Spaces should be removed from rhythm:
38
+ assert_equal("X...X.X.", test_tracks[:with_spaces].rhythm)
39
+
40
+ assert_equal([4], test_tracks[:placeholder].trigger_step_lengths)
36
41
  assert_equal("....", test_tracks[:placeholder].rhythm)
37
42
 
38
- assert_equal([2, 4, 4, 4, 2, 4, 4, 4, 4], test_tracks[:complicated].beats)
39
- assert_equal("..X...X...X...X.X...X...X...X...", test_tracks[:complicated].rhythm)
43
+ assert_equal([2, 1, 3, 4, 4, 2, 4, 4, 4, 4], test_tracks[:complicated].trigger_step_lengths)
44
+ assert_equal("..XX..X...X...X.X...X...X...X...", test_tracks[:complicated].rhythm)
45
+ end
46
+
47
+ def test_invalid_rhythm
48
+ assert_raises(Track::InvalidRhythmError) { Track.new("bad_rhythm", "abcde") }
49
+ assert_raises(Track::InvalidRhythmError) { Track.new("bad_rhythm", "X.X.e.X") }
50
+
51
+ track = Track.new("test", "X...")
52
+ assert_raises(Track::InvalidRhythmError) { track.rhythm = "abcde" }
53
+ assert_raises(Track::InvalidRhythmError) { track.rhythm = "X.X.e.X" }
40
54
  end
41
55
 
42
56
  def test_step_count
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beats
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Strait
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-05 00:00:00.000000000 Z
11
+ date: 2017-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: wavefile
@@ -16,33 +16,32 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.6.0
19
+ version: 0.8.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.6.0
27
- description: A command-line drum machine. Feed it a song notated in YAML, and it will
28
- produce a precision-milled Wave file of impeccable timing and feel.
26
+ version: 0.8.1
27
+ description: A command-line drum machine. Takes a song notated in a YAML file as input,
28
+ and outputs a *.wav sound file.
29
29
  email: joel dot strait at Google's popular web mail service
30
30
  executables:
31
31
  - beats
32
- extensions:
33
- - ext/mkrf_conf.rb
32
+ extensions: []
34
33
  extra_rdoc_files: []
35
34
  files:
36
35
  - LICENSE
37
36
  - README.markdown
38
37
  - Rakefile
39
38
  - bin/beats
40
- - ext/mkrf_conf.rb
41
39
  - lib/beats.rb
42
40
  - lib/beats/audioengine.rb
43
41
  - lib/beats/audioutils.rb
44
42
  - lib/beats/beatsrunner.rb
45
43
  - lib/beats/kit.rb
44
+ - lib/beats/kit_builder.rb
46
45
  - lib/beats/pattern.rb
47
46
  - lib/beats/song.rb
48
47
  - lib/beats/songoptimizer.rb
@@ -91,6 +90,7 @@ files:
91
90
  - test/fixtures/invalid/bad_swing_rate_1.txt
92
91
  - test/fixtures/invalid/bad_swing_rate_2.txt
93
92
  - test/fixtures/invalid/bad_tempo.txt
93
+ - test/fixtures/invalid/leading_bar_line.txt
94
94
  - test/fixtures/invalid/no_flow.txt
95
95
  - test/fixtures/invalid/no_header.txt
96
96
  - test/fixtures/invalid/pattern_with_no_tracks.txt
@@ -98,7 +98,7 @@ files:
98
98
  - test/fixtures/invalid/sound_in_kit_wrong_format.txt
99
99
  - test/fixtures/invalid/sound_in_track_not_found.txt
100
100
  - test/fixtures/invalid/sound_in_track_wrong_format.txt
101
- - test/fixtures/invalid/template.txt
101
+ - test/fixtures/invalid/with_structure.txt
102
102
  - test/fixtures/valid/example_mono_16.txt
103
103
  - test/fixtures/valid/example_mono_16_base_path.txt
104
104
  - test/fixtures/valid/example_mono_8.txt
@@ -110,17 +110,17 @@ files:
110
110
  - test/fixtures/valid/example_unswung.txt
111
111
  - test/fixtures/valid/example_with_empty_track.txt
112
112
  - test/fixtures/valid/example_with_kit.txt
113
- - test/fixtures/valid/foo.txt
114
113
  - test/fixtures/valid/fractional_tempo.txt
115
114
  - test/fixtures/valid/multiple_tracks_same_sound.txt
116
115
  - test/fixtures/valid/no_tempo.txt
117
116
  - test/fixtures/valid/optimize_pattern_collision.txt
118
117
  - test/fixtures/valid/pattern_with_overflow.txt
119
118
  - test/fixtures/valid/repeats_not_specified.txt
120
- - test/fixtures/valid/with_structure.txt
119
+ - test/fixtures/valid/track_with_spaces.txt
121
120
  - test/fixtures/yaml/song_yaml.txt
122
121
  - test/includes.rb
123
122
  - test/integration_test.rb
123
+ - test/kit_builder_test.rb
124
124
  - test/kit_test.rb
125
125
  - test/pattern_test.rb
126
126
  - test/song_swinger_test.rb
@@ -135,8 +135,6 @@ files:
135
135
  - test/sounds/agogo_low_mono_8.wav
136
136
  - test/sounds/agogo_low_stereo_16.wav
137
137
  - test/sounds/agogo_low_stereo_8.wav
138
- - test/sounds/bass.wav
139
- - test/sounds/bass2.wav
140
138
  - test/sounds/bass2_mono_16.wav
141
139
  - test/sounds/bass2_mono_8.wav
142
140
  - test/sounds/bass2_stereo_16.wav
@@ -189,7 +187,6 @@ files:
189
187
  - test/sounds/rim_mono_8.wav
190
188
  - test/sounds/rim_stereo_16.wav
191
189
  - test/sounds/rim_stereo_8.wav
192
- - test/sounds/sine-mono-8bit.wav
193
190
  - test/sounds/snare2_mono_16.wav
194
191
  - test/sounds/snare2_mono_8.wav
195
192
  - test/sounds/snare2_stereo_16.wav
@@ -214,32 +211,33 @@ files:
214
211
  - test/sounds/tom4_mono_8.wav
215
212
  - test/sounds/tom4_stereo_16.wav
216
213
  - test/sounds/tom4_stereo_8.wav
217
- - test/sounds/tone.wav
218
214
  - test/track_test.rb
219
215
  homepage: http://beatsdrummachine.com/
220
- licenses: []
216
+ licenses:
217
+ - MIT
221
218
  metadata: {}
222
- post_install_message:
219
+ post_install_message: Thanks for installing Beats Drum Machine! For information on
220
+ how to use Beats, or to download some drum sounds to use with Beats, visit http://beatsdrummachine.com
223
221
  rdoc_options: []
224
222
  require_paths:
225
223
  - lib
226
224
  required_ruby_version: !ruby/object:Gem::Requirement
227
225
  requirements:
228
- - - '>='
226
+ - - ">="
229
227
  - !ruby/object:Gem::Version
230
- version: '0'
228
+ version: 1.9.3
231
229
  required_rubygems_version: !ruby/object:Gem::Requirement
232
230
  requirements:
233
- - - '>='
231
+ - - ">="
234
232
  - !ruby/object:Gem::Version
235
233
  version: '0'
236
234
  requirements: []
237
235
  rubyforge_project:
238
- rubygems_version: 2.2.2
236
+ rubygems_version: 2.6.13
239
237
  signing_key:
240
238
  specification_version: 4
241
- summary: A command-line drum machine. Feed it a song notated in YAML, and it will
242
- produce a precision-milled Wave file of impeccable timing and feel.
239
+ summary: A command-line drum machine. Takes a song notated in a YAML file as input,
240
+ and outputs a *.wav sound file.
243
241
  test_files:
244
242
  - test/audioengine_test.rb
245
243
  - test/audioutils_test.rb
@@ -282,6 +280,7 @@ test_files:
282
280
  - test/fixtures/invalid/bad_swing_rate_1.txt
283
281
  - test/fixtures/invalid/bad_swing_rate_2.txt
284
282
  - test/fixtures/invalid/bad_tempo.txt
283
+ - test/fixtures/invalid/leading_bar_line.txt
285
284
  - test/fixtures/invalid/no_flow.txt
286
285
  - test/fixtures/invalid/no_header.txt
287
286
  - test/fixtures/invalid/pattern_with_no_tracks.txt
@@ -289,7 +288,7 @@ test_files:
289
288
  - test/fixtures/invalid/sound_in_kit_wrong_format.txt
290
289
  - test/fixtures/invalid/sound_in_track_not_found.txt
291
290
  - test/fixtures/invalid/sound_in_track_wrong_format.txt
292
- - test/fixtures/invalid/template.txt
291
+ - test/fixtures/invalid/with_structure.txt
293
292
  - test/fixtures/valid/example_mono_16.txt
294
293
  - test/fixtures/valid/example_mono_16_base_path.txt
295
294
  - test/fixtures/valid/example_mono_8.txt
@@ -301,17 +300,17 @@ test_files:
301
300
  - test/fixtures/valid/example_unswung.txt
302
301
  - test/fixtures/valid/example_with_empty_track.txt
303
302
  - test/fixtures/valid/example_with_kit.txt
304
- - test/fixtures/valid/foo.txt
305
303
  - test/fixtures/valid/fractional_tempo.txt
306
304
  - test/fixtures/valid/multiple_tracks_same_sound.txt
307
305
  - test/fixtures/valid/no_tempo.txt
308
306
  - test/fixtures/valid/optimize_pattern_collision.txt
309
307
  - test/fixtures/valid/pattern_with_overflow.txt
310
308
  - test/fixtures/valid/repeats_not_specified.txt
311
- - test/fixtures/valid/with_structure.txt
309
+ - test/fixtures/valid/track_with_spaces.txt
312
310
  - test/fixtures/yaml/song_yaml.txt
313
311
  - test/includes.rb
314
312
  - test/integration_test.rb
313
+ - test/kit_builder_test.rb
315
314
  - test/kit_test.rb
316
315
  - test/pattern_test.rb
317
316
  - test/song_swinger_test.rb
@@ -326,8 +325,6 @@ test_files:
326
325
  - test/sounds/agogo_low_mono_8.wav
327
326
  - test/sounds/agogo_low_stereo_16.wav
328
327
  - test/sounds/agogo_low_stereo_8.wav
329
- - test/sounds/bass.wav
330
- - test/sounds/bass2.wav
331
328
  - test/sounds/bass2_mono_16.wav
332
329
  - test/sounds/bass2_mono_8.wav
333
330
  - test/sounds/bass2_stereo_16.wav
@@ -380,7 +377,6 @@ test_files:
380
377
  - test/sounds/rim_mono_8.wav
381
378
  - test/sounds/rim_stereo_16.wav
382
379
  - test/sounds/rim_stereo_8.wav
383
- - test/sounds/sine-mono-8bit.wav
384
380
  - test/sounds/snare2_mono_16.wav
385
381
  - test/sounds/snare2_mono_8.wav
386
382
  - test/sounds/snare2_stereo_16.wav
@@ -405,5 +401,4 @@ test_files:
405
401
  - test/sounds/tom4_mono_8.wav
406
402
  - test/sounds/tom4_stereo_16.wav
407
403
  - test/sounds/tom4_stereo_8.wav
408
- - test/sounds/tone.wav
409
404
  - test/track_test.rb