beats 1.2.0 → 1.2.1

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.
Files changed (69) hide show
  1. data/LICENSE +1 -1
  2. data/README.markdown +28 -10
  3. data/bin/beats +9 -7
  4. data/lib/audioengine.rb +172 -0
  5. data/lib/audioutils.rb +73 -0
  6. data/lib/beats.rb +14 -15
  7. data/lib/beatswavefile.rb +17 -37
  8. data/lib/kit.rb +148 -71
  9. data/lib/pattern.rb +20 -117
  10. data/lib/patternexpander.rb +111 -0
  11. data/lib/song.rb +78 -132
  12. data/lib/songoptimizer.rb +29 -33
  13. data/lib/songparser.rb +70 -45
  14. data/lib/track.rb +11 -82
  15. data/test/audioengine_test.rb +261 -0
  16. data/test/audioutils_test.rb +45 -0
  17. data/test/fixtures/expected_output/example_split_mono_16-hh_closed.wav +0 -0
  18. data/test/{examples/split-agogo_high.wav → fixtures/expected_output/example_split_mono_16-hh_closed2.wav} +0 -0
  19. data/test/fixtures/expected_output/example_split_mono_8-hh_closed.wav +0 -0
  20. data/test/{examples/split-tom4.wav → fixtures/expected_output/example_split_mono_8-hh_closed2.wav} +0 -0
  21. data/test/fixtures/expected_output/example_split_stereo_16-hh_closed.wav +0 -0
  22. data/test/fixtures/expected_output/example_split_stereo_16-hh_closed2.wav +0 -0
  23. data/test/fixtures/expected_output/example_split_stereo_8-hh_closed.wav +0 -0
  24. data/test/fixtures/expected_output/example_split_stereo_8-hh_closed2.wav +0 -0
  25. data/test/fixtures/invalid/{bad_structure.txt → bad_flow.txt} +2 -2
  26. data/test/fixtures/invalid/bad_repeat_count.txt +1 -1
  27. data/test/fixtures/invalid/bad_rhythm.txt +1 -1
  28. data/test/fixtures/invalid/bad_tempo.txt +1 -1
  29. data/test/fixtures/invalid/{no_structure.txt → no_flow.txt} +1 -1
  30. data/test/fixtures/invalid/pattern_with_no_tracks.txt +1 -1
  31. data/test/fixtures/invalid/sound_in_kit_not_found.txt +1 -1
  32. data/test/fixtures/invalid/sound_in_kit_wrong_format.txt +10 -0
  33. data/test/fixtures/invalid/sound_in_track_not_found.txt +1 -1
  34. data/test/fixtures/invalid/sound_in_track_wrong_format.txt +8 -0
  35. data/test/fixtures/invalid/template.txt +1 -1
  36. data/test/fixtures/valid/example_mono_16.txt +5 -3
  37. data/test/fixtures/valid/example_mono_8.txt +5 -3
  38. data/test/fixtures/valid/example_no_kit.txt +1 -1
  39. data/test/fixtures/valid/example_stereo_16.txt +7 -4
  40. data/test/fixtures/valid/example_stereo_8.txt +5 -3
  41. data/test/fixtures/valid/example_with_empty_track.txt +1 -1
  42. data/test/fixtures/valid/example_with_kit.txt +1 -1
  43. data/test/fixtures/valid/multiple_tracks_same_sound.txt +33 -0
  44. data/test/fixtures/valid/no_tempo.txt +1 -1
  45. data/test/fixtures/valid/optimize_pattern_collision.txt +28 -0
  46. data/test/fixtures/valid/pattern_with_overflow.txt +1 -1
  47. data/test/fixtures/valid/repeats_not_specified.txt +2 -2
  48. data/test/fixtures/valid/with_structure.txt +10 -0
  49. data/test/fixtures/yaml/song_yaml.txt +5 -5
  50. data/test/includes.rb +4 -2
  51. data/test/integration.rb +3 -3
  52. data/test/kit_test.rb +136 -109
  53. data/test/pattern_test.rb +31 -131
  54. data/test/patternexpander_test.rb +142 -0
  55. data/test/song_test.rb +104 -102
  56. data/test/songoptimizer_test.rb +52 -38
  57. data/test/songparser_test.rb +79 -46
  58. data/test/sounds/composite_snare_mono_8_tom3_mono_16_mono_16.wav +0 -0
  59. data/test/sounds/composite_snare_mono_8_tom3_mono_8_mono_16.wav +0 -0
  60. data/test/sounds/composite_snare_stereo_16_tom3_mono_16_stereo_16.wav +0 -0
  61. data/test/sounds/composite_snare_stereo_8_tom3_mono_16_stereo_16.wav +0 -0
  62. data/test/track_test.rb +30 -185
  63. metadata +56 -24
  64. data/lib/songsplitter.rb +0 -38
  65. data/test/examples/combined.wav +0 -0
  66. data/test/examples/split-bass.wav +0 -0
  67. data/test/examples/split-hh_closed.wav +0 -0
  68. data/test/examples/split-snare.wav +0 -0
  69. data/test/examples/split-tom2.wav +0 -0
@@ -3,16 +3,18 @@ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
3
3
  require 'test/includes'
4
4
 
5
5
  class MockSongOptimizer < SongOptimizer
6
- def clone_song_ignoring_patterns_and_structure(original_song)
6
+ def clone_song_ignoring_patterns_and_flow(original_song)
7
7
  return super
8
8
  end
9
9
  end
10
10
 
11
11
  class SongOptimizerTest < Test::Unit::TestCase
12
+ FIXTURE_BASE_PATH = File.dirname(__FILE__) + "/.."
13
+
12
14
  EXAMPLE_SONG_YAML = "
13
15
  Song:
14
16
  Tempo: 135
15
- Structure:
17
+ Flow:
16
18
  - Verse: x2
17
19
  - Chorus: x4
18
20
  - Verse: x2
@@ -39,7 +41,7 @@ Chorus:
39
41
  EXAMPLE_SONG_YAML_EMPTY_SUB_PATTERN = "
40
42
  Song:
41
43
  Tempo: 135
42
- Structure:
44
+ Flow:
43
45
  - Verse: x1
44
46
  Kit:
45
47
  - bass: sounds/bass.wav
@@ -49,114 +51,126 @@ Verse:
49
51
  - bass: X.......X...
50
52
  - snare: ..........X."
51
53
 
54
+ def self.load_fixture(fixture_name)
55
+ return SongParser.new().parse(FIXTURE_BASE_PATH, File.read("test/fixtures/#{fixture_name}"))
56
+ end
57
+
52
58
  def test_optimize
53
59
  parser = SongParser.new()
54
- original_song = parser.parse(File.dirname(__FILE__) + "/..", EXAMPLE_SONG_YAML)
60
+ original_song, kit = parser.parse(File.dirname(__FILE__) + "/..", EXAMPLE_SONG_YAML)
55
61
 
56
62
  optimizer = SongOptimizer.new()
57
63
  optimized_song = optimizer.optimize(original_song, 4)
58
64
 
59
65
  assert_equal(optimized_song.tempo, 135)
60
66
  #assert_equal(optimized_song.total_tracks, 5)
61
- assert_equal(original_song.kit, optimized_song.kit)
62
- assert_equal(original_song.sample_length, optimized_song.sample_length)
63
- assert_equal(original_song.sample_length_with_overflow, optimized_song.sample_length_with_overflow)
67
+
68
+ # TODO: Add some sort of AudioEngine test to verify that optimized and unoptimized song have same sample data.
69
+ #assert_equal(original_song.sample_length, optimized_song.sample_length)
70
+ #assert_equal(original_song.sample_length_with_overflow, optimized_song.sample_length_with_overflow)
64
71
  #assert_equal(original_song.sample_data(false), optimized_song.sample_data(false))
65
72
 
66
- # Patterns :verse0 and :verse4 should be removed since they are identical to :chorus0
67
- assert_equal([:chorus0, :chorus12, :chorus4, :chorus8, :verse12, :verse8],
73
+ # Patterns :verse_0 and :verse_4 should be removed since they are identical to :chorus_0
74
+ assert_equal([:chorus_0, :chorus_12, :chorus_4, :chorus_8, :verse_12, :verse_8],
68
75
  optimized_song.patterns.keys.sort {|x, y| x.to_s <=> y.to_s })
69
76
 
70
- pattern = optimized_song.patterns[:verse8]
77
+ pattern = optimized_song.patterns[:verse_8]
71
78
  assert_equal(pattern.tracks.keys.sort, ["bass", "hh_closed"])
72
79
  assert_equal(pattern.tracks["bass"].rhythm, "X...")
73
80
  assert_equal(pattern.tracks["hh_closed"].rhythm, "X.X.")
74
81
 
75
- pattern = optimized_song.patterns[:verse12]
82
+ pattern = optimized_song.patterns[:verse_12]
76
83
  assert_equal(pattern.tracks.keys.sort, ["agogo", "bass", "hh_closed", "snare"])
77
84
  assert_equal(pattern.tracks["bass"].rhythm, "X...")
78
85
  assert_equal(pattern.tracks["snare"].rhythm, "..X.")
79
86
  assert_equal(pattern.tracks["hh_closed"].rhythm, "X.X.")
80
87
  assert_equal(pattern.tracks["agogo"].rhythm, "..XX")
81
88
 
82
- pattern = optimized_song.patterns[:chorus0]
89
+ pattern = optimized_song.patterns[:chorus_0]
83
90
  assert_equal(pattern.tracks.keys.sort, ["bass", "hh_closed"])
84
91
  assert_equal(pattern.tracks["bass"].rhythm, "X...")
85
92
  assert_equal(pattern.tracks["hh_closed"].rhythm, "X.XX")
86
93
 
87
- pattern = optimized_song.patterns[:chorus4]
94
+ pattern = optimized_song.patterns[:chorus_4]
88
95
  assert_equal(pattern.tracks.keys.sort, ["bass", "hh_closed", "snare"])
89
96
  assert_equal(pattern.tracks["bass"].rhythm, "X...")
90
97
  assert_equal(pattern.tracks["snare"].rhythm, "X...")
91
98
  assert_equal(pattern.tracks["hh_closed"].rhythm, "X.XX")
92
99
 
93
- pattern = optimized_song.patterns[:chorus8]
100
+ pattern = optimized_song.patterns[:chorus_8]
94
101
  assert_equal(pattern.tracks.keys.sort, ["bass", "hh_closed", "sounds/tom4.wav"])
95
102
  assert_equal(pattern.tracks["bass"].rhythm, "XX..")
96
103
  assert_equal(pattern.tracks["hh_closed"].rhythm, "X.XX")
97
104
  assert_equal(pattern.tracks["sounds/tom4.wav"].rhythm, "...X")
98
105
 
99
- pattern = optimized_song.patterns[:chorus12]
106
+ pattern = optimized_song.patterns[:chorus_12]
100
107
  assert_equal(pattern.tracks.keys.sort, ["bass", "hh_closed", "snare", "sounds/tom2.wav"])
101
108
  assert_equal(pattern.tracks["bass"].rhythm, "X...")
102
109
  assert_equal(pattern.tracks["snare"].rhythm, "X...")
103
110
  assert_equal(pattern.tracks["hh_closed"].rhythm, "..X.")
104
111
  assert_equal(pattern.tracks["sounds/tom2.wav"].rhythm, "..X.")
105
112
 
106
- assert_equal(optimized_song.structure, [:chorus0, :chorus0, :verse8, :verse12,
107
- :chorus0, :chorus0, :verse8, :verse12,
108
- :chorus0, :chorus4, :chorus8, :chorus12,
109
- :chorus0, :chorus4, :chorus8, :chorus12,
110
- :chorus0, :chorus4, :chorus8, :chorus12,
111
- :chorus0, :chorus4, :chorus8, :chorus12,
112
- :chorus0, :chorus0, :verse8, :verse12,
113
- :chorus0, :chorus0, :verse8, :verse12,
114
- :chorus0, :chorus4, :chorus8, :chorus12,
115
- :chorus0, :chorus4, :chorus8, :chorus12,
116
- :chorus0, :chorus4, :chorus8, :chorus12,
117
- :chorus0, :chorus4, :chorus8, :chorus12])
113
+ assert_equal(optimized_song.flow, [:chorus_0, :chorus_0, :verse_8, :verse_12,
114
+ :chorus_0, :chorus_0, :verse_8, :verse_12,
115
+ :chorus_0, :chorus_4, :chorus_8, :chorus_12,
116
+ :chorus_0, :chorus_4, :chorus_8, :chorus_12,
117
+ :chorus_0, :chorus_4, :chorus_8, :chorus_12,
118
+ :chorus_0, :chorus_4, :chorus_8, :chorus_12,
119
+ :chorus_0, :chorus_0, :verse_8, :verse_12,
120
+ :chorus_0, :chorus_0, :verse_8, :verse_12,
121
+ :chorus_0, :chorus_4, :chorus_8, :chorus_12,
122
+ :chorus_0, :chorus_4, :chorus_8, :chorus_12,
123
+ :chorus_0, :chorus_4, :chorus_8, :chorus_12,
124
+ :chorus_0, :chorus_4, :chorus_8, :chorus_12])
118
125
  end
119
126
 
120
127
  def test_optimize_song_nondivisible_max_pattern_length()
121
128
  parser = SongParser.new()
122
- original_song = parser.parse(File.dirname(__FILE__) + "/..", EXAMPLE_SONG_YAML_EMPTY_SUB_PATTERN)
129
+ original_song, kit = parser.parse(File.dirname(__FILE__) + "/..", EXAMPLE_SONG_YAML_EMPTY_SUB_PATTERN)
123
130
 
124
131
  optimizer = SongOptimizer.new()
125
132
  optimized_song = optimizer.optimize(original_song, 7)
126
133
 
127
- pattern = optimized_song.patterns[:verse0]
134
+ pattern = optimized_song.patterns[:verse_0]
128
135
  assert_equal(["bass"], pattern.tracks.keys.sort)
129
136
  assert_equal("X......", pattern.tracks["bass"].rhythm)
130
137
 
131
- pattern = optimized_song.patterns[:verse7]
138
+ pattern = optimized_song.patterns[:verse_7]
132
139
  assert_equal(["bass", "snare"], pattern.tracks.keys.sort)
133
140
  assert_equal(".X...", pattern.tracks["bass"].rhythm)
134
141
  assert_equal("...X.", pattern.tracks["snare"].rhythm)
135
142
 
136
- assert_equal([:verse0, :verse7], optimized_song.structure)
143
+ assert_equal([:verse_0, :verse_7], optimized_song.flow)
137
144
  end
138
145
 
146
+ def test_pattern_collision
147
+ original_song, kit = SongOptimizerTest.load_fixture("valid/optimize_pattern_collision.txt")
148
+ optimizer = SongOptimizer.new()
149
+ optimized_song = optimizer.optimize(original_song, 4)
150
+
151
+ assert_equal([:verse2_0, :verse_0, :verse_20], optimized_song.patterns.keys.sort {|x, y| x.to_s <=> y.to_s })
152
+ end
153
+
139
154
  def test_optimize_song_containing_empty_pattern()
140
155
  parser = SongParser.new()
141
- original_song = parser.parse(File.dirname(__FILE__) + "/..", EXAMPLE_SONG_YAML_EMPTY_SUB_PATTERN)
156
+ original_song, kit = parser.parse(File.dirname(__FILE__) + "/..", EXAMPLE_SONG_YAML_EMPTY_SUB_PATTERN)
142
157
 
143
158
  optimizer = SongOptimizer.new()
144
159
  optimized_song = optimizer.optimize(original_song, 4)
145
160
 
146
- pattern = optimized_song.patterns[:verse0]
161
+ pattern = optimized_song.patterns[:verse_0]
147
162
  assert_equal(["bass"], pattern.tracks.keys.sort)
148
163
  assert_equal("X...", pattern.tracks["bass"].rhythm)
149
164
 
150
- pattern = optimized_song.patterns[:verse4]
165
+ pattern = optimized_song.patterns[:verse_4]
151
166
  assert_equal(["placeholder"], pattern.tracks.keys.sort)
152
167
  assert_equal("....", pattern.tracks["placeholder"].rhythm)
153
- assert_equal([], pattern.tracks["placeholder"].wave_data)
154
168
 
155
- pattern = optimized_song.patterns[:verse8]
169
+ pattern = optimized_song.patterns[:verse_8]
156
170
  assert_equal(["bass", "snare"], pattern.tracks.keys.sort)
157
171
  assert_equal("X...", pattern.tracks["bass"].rhythm)
158
172
  assert_equal("..X.", pattern.tracks["snare"].rhythm)
159
173
 
160
- assert_equal([:verse0, :verse4, :verse8], optimized_song.structure)
174
+ assert_equal([:verse_0, :verse_4, :verse_8], optimized_song.flow)
161
175
  end
162
- end
176
+ end
@@ -2,77 +2,110 @@ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
2
 
3
3
  require 'test/includes'
4
4
 
5
- class SongParserTest < Test::Unit::TestCase
6
- def self.generate_test_data
7
- kit = Kit.new("test/sounds")
8
- kit.add("bass.wav", "bass_mono_8.wav")
9
- kit.add("snare.wav", "snare_mono_8.wav")
10
- kit.add("hh_closed.wav", "hh_closed_mono_8.wav")
11
- kit.add("ride.wav", "ride_mono_8.wav")
5
+ class SongParserTest < Test::Unit::TestCase
6
+ FIXTURE_BASE_PATH = File.dirname(__FILE__) + "/.."
12
7
 
13
- test_songs = {}
14
- base_path = File.dirname(__FILE__) + "/.."
8
+ # TODO: Add fixture for track with no rhythm
9
+ VALID_FIXTURES = [:no_tempo,
10
+ :repeats_not_specified,
11
+ :pattern_with_overflow,
12
+ :example_no_kit,
13
+ :example_with_kit,
14
+ :example_with_empty_track,
15
+ :multiple_tracks_same_sound,
16
+ :with_structure]
17
+
18
+ INVALID_FIXTURES = [:bad_repeat_count,
19
+ :bad_flow,
20
+ :bad_tempo,
21
+ :no_header,
22
+ :no_flow,
23
+ :pattern_with_no_tracks,
24
+ :sound_in_kit_not_found,
25
+ :sound_in_track_not_found,
26
+ :sound_in_kit_wrong_format,
27
+ :sound_in_track_wrong_format]
15
28
 
16
- test_songs[:no_tempo] = SongParser.new().parse(base_path, YAML.load_file("test/fixtures/valid/no_tempo.txt"))
17
- test_songs[:repeats_not_specified] = SongParser.new().parse(base_path, YAML.load_file("test/fixtures/valid/repeats_not_specified.txt"))
18
- test_songs[:overflow] = SongParser.new().parse(base_path, YAML.load_file("test/fixtures/valid/pattern_with_overflow.txt"))
19
- # TODO: Add fixture for track with no rhythm
20
- test_songs[:from_valid_yaml_string] = SongParser.new().parse(base_path, YAML.load_file("test/fixtures/valid/example_no_kit.txt"))
21
- test_songs[:from_valid_yaml_string_with_kit] = SongParser.new().parse(base_path, YAML.load_file("test/fixtures/valid/example_with_kit.txt"))
22
- test_songs[:from_valid_yaml_string_with_empty_track] = SongParser.new().parse(base_path, YAML.load_file("test/fixtures/valid/example_with_empty_track.txt"))
29
+ def self.load_fixture(fixture_name)
30
+ return SongParser.new().parse(FIXTURE_BASE_PATH, File.read("test/fixtures/#{fixture_name}"))
31
+ end
32
+
33
+ def self.generate_test_data
34
+ test_songs = {}
35
+ test_kits = {}
23
36
 
24
- return test_songs
37
+ VALID_FIXTURES.each do |fixture_name|
38
+ song, kit = load_fixture("valid/#{fixture_name}.txt")
39
+ test_songs[fixture_name] = song
40
+ test_kits[fixture_name] = kit
41
+ end
42
+
43
+ return test_songs, test_kits
25
44
  end
26
45
 
46
+ # TODO: Add somes tests to validate the Kits
27
47
  def test_valid_parse
28
- test_songs = SongParserTest.generate_test_data()
48
+ test_songs, test_kits = SongParserTest.generate_test_data()
29
49
 
30
- assert_equal(test_songs[:no_tempo].tempo, 120)
31
- assert_equal(test_songs[:no_tempo].structure, [:verse])
50
+ assert_equal(120, test_songs[:no_tempo].tempo)
51
+ assert_equal([:verse], test_songs[:no_tempo].flow)
32
52
 
33
- assert_equal(test_songs[:repeats_not_specified].tempo, 100)
34
- assert_equal(test_songs[:repeats_not_specified].structure, [:verse])
53
+ assert_equal(100, test_songs[:repeats_not_specified].tempo)
54
+ assert_equal([:verse], test_songs[:repeats_not_specified].flow)
35
55
 
36
56
  # These two songs should be the same, except that one uses a kit in the song header
37
57
  # and the other doesn't.
38
- [:from_valid_yaml_string, :from_valid_yaml_string_with_kit].each do |song_key|
58
+ [:example_no_kit, :example_with_kit].each do |song_key|
39
59
  song = test_songs[song_key]
40
- assert_equal(song.structure, [:verse, :verse, :chorus, :chorus, :verse, :verse, :chorus, :chorus, :chorus, :chorus, :bridge, :chorus, :chorus, :chorus, :chorus])
41
- assert_equal(song.tempo, 99)
42
- assert_equal(song.tick_sample_length, (Song::SAMPLE_RATE * Song::SECONDS_PER_MINUTE) / 99 / 4.0)
43
- assert_equal(song.patterns.keys.map{|key| key.to_s}.sort, ["bridge", "chorus", "verse"])
44
- assert_equal(song.patterns[:verse].tracks.length, 4)
45
- assert_equal(song.patterns[:chorus].tracks.length, 5)
46
- assert_equal(song.patterns[:bridge].tracks.length, 1)
60
+ assert_equal([:verse, :verse,
61
+ :chorus, :chorus,
62
+ :verse, :verse,
63
+ :chorus, :chorus, :chorus, :chorus,
64
+ :bridge,
65
+ :chorus, :chorus, :chorus, :chorus],
66
+ song.flow)
67
+ assert_equal(99, song.tempo)
68
+ assert_equal(["bridge", "chorus", "verse"], song.patterns.keys.map{|key| key.to_s}.sort)
69
+ assert_equal(4, song.patterns[:verse].tracks.length)
70
+ assert_equal(5, song.patterns[:chorus].tracks.length)
71
+ assert_equal(1, song.patterns[:bridge].tracks.length)
47
72
  end
48
73
 
49
- song = test_songs[:from_valid_yaml_string_with_empty_track]
74
+ song = test_songs[:example_with_empty_track]
50
75
  assert_equal(1, song.patterns.length)
51
76
  assert_equal(2, song.patterns[:verse].tracks.length)
52
77
  assert_equal("........", song.patterns[:verse].tracks["test/sounds/bass_mono_8.wav"].rhythm)
53
78
  assert_equal("X...X...", song.patterns[:verse].tracks["test/sounds/snare_mono_8.wav"].rhythm)
79
+
80
+ song = test_songs[:multiple_tracks_same_sound]
81
+ assert_equal(2, song.patterns.length)
82
+ assert_equal(7, song.patterns[:verse].tracks.length)
83
+ assert_equal(["agogo", "bass", "bass2", "bass3", "bass4", "hh_closed", "snare"],
84
+ song.patterns[:verse].tracks.keys.sort)
85
+ assert_equal("X...............", song.patterns[:verse].tracks["bass"].rhythm)
86
+ assert_equal("....X...........", song.patterns[:verse].tracks["bass2"].rhythm)
87
+ assert_equal("........X.......", song.patterns[:verse].tracks["bass3"].rhythm)
88
+ assert_equal("............X...", song.patterns[:verse].tracks["bass4"].rhythm)
89
+ assert_equal("..............X.", song.patterns[:verse].tracks["snare"].rhythm)
90
+ assert_equal("X.XXX.XXX.X.X.X.", song.patterns[:verse].tracks["hh_closed"].rhythm)
91
+ assert_equal("..............XX", song.patterns[:verse].tracks["agogo"].rhythm)
92
+
93
+ song = test_songs[:with_structure]
94
+ assert_equal([:verse, :verse], song.flow)
95
+ assert_equal(1, song.patterns.length)
96
+ assert_equal(1, song.patterns[:verse].tracks.length)
97
+ assert_equal("X...X...", song.patterns[:verse].tracks["test/sounds/bass_mono_8.wav"].rhythm)
54
98
  end
55
99
 
56
100
  def test_invalid_parse
57
- invalid_fixtures = ["bad_repeat_count",
58
- "bad_structure",
59
- "bad_tempo",
60
- "no_header",
61
- "no_structure",
62
- "pattern_with_no_tracks",
63
- "sound_in_track_not_found",
64
- "sound_in_kit_not_found",]
65
-
66
- invalid_fixtures.each do |fixture|
101
+ INVALID_FIXTURES.each do |fixture|
67
102
  assert_raise(SongParseError) do
68
- song = SongParser.new().parse(File.dirname(__FILE__) + "/..",
69
- YAML.load_file("test/fixtures/invalid/" + fixture + ".txt"))
103
+ song = SongParserTest.load_fixture("invalid/#{fixture}.txt")
70
104
  end
71
105
  end
72
106
 
73
107
  assert_raise(InvalidRhythmError) do
74
- song = SongParser.new().parse(File.dirname(__FILE__) + "/..",
75
- YAML.load_file("test/fixtures/invalid/bad_rhythm.txt"))
108
+ song = SongParserTest.load_fixture("invalid/bad_rhythm.txt")
76
109
  end
77
110
  end
78
- end
111
+ end
@@ -2,24 +2,16 @@ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
2
 
3
3
  require 'test/includes'
4
4
 
5
- class MockTrack < Track
6
- attr_reader :beats
7
- end
8
-
9
5
  class TrackTest < Test::Unit::TestCase
10
- SECONDS_IN_MINUTE = 60.0
11
- SOUND_FILE_PATH = "test/sounds/bass_mono_8.wav"
12
- W = WaveFile.open(SOUND_FILE_PATH)
13
-
14
6
  def generate_test_data
15
- test_tracks = []
7
+ test_tracks = {}
16
8
 
17
- test_tracks << MockTrack.new("bass", W.sample_data, "")
18
- test_tracks << MockTrack.new("bass", W.sample_data, "X")
19
- test_tracks << MockTrack.new("bass", W.sample_data, "...X")
20
- test_tracks << MockTrack.new("bass", W.sample_data, "X.X.X.X.")
21
- test_tracks << MockTrack.new("bass", W.sample_data, "....")
22
- test_tracks << MockTrack.new("bass", W.sample_data, "..X...X...X...X.X...X...X...X...")
9
+ test_tracks[:blank] = Track.new("bass", "")
10
+ test_tracks[:solo] = Track.new("bass", "X")
11
+ test_tracks[:with_overflow] = Track.new("bass", "...X")
12
+ test_tracks[:with_barlines] = Track.new("bass", "|X.X.|X.X.|")
13
+ test_tracks[:placeholder] = Track.new("bass", "....")
14
+ test_tracks[:complicated] = Track.new("bass", "..X...X...X...X.X...X...X...X...")
23
15
 
24
16
  return test_tracks
25
17
  end
@@ -27,183 +19,36 @@ class TrackTest < Test::Unit::TestCase
27
19
  def test_initialize
28
20
  test_tracks = generate_test_data()
29
21
 
30
- assert_equal([0], test_tracks[0].beats)
31
- assert_equal("bass", test_tracks[0].name)
22
+ assert_equal([0], test_tracks[:blank].beats)
23
+ assert_equal("bass", test_tracks[:blank].name)
24
+ assert_equal("", test_tracks[:blank].rhythm)
32
25
 
33
- assert_equal([0, 1], test_tracks[1].beats)
34
- assert_equal("bass", test_tracks[1].name)
26
+ assert_equal([0, 1], test_tracks[:solo].beats)
27
+ assert_equal("bass", test_tracks[:solo].name)
28
+ assert_equal("X", test_tracks[:solo].rhythm)
35
29
 
36
- assert_equal([3, 1], test_tracks[2].beats)
37
- assert_equal([0, 2, 2, 2, 2], test_tracks[3].beats)
38
- assert_equal([4], test_tracks[4].beats)
39
- assert_equal([2, 4, 4, 4, 2, 4, 4, 4, 4], test_tracks[5].beats)
40
- end
41
-
42
- def test_tick_count
43
- test_tracks = generate_test_data()
30
+ assert_equal([3, 1], test_tracks[:with_overflow].beats)
31
+ assert_equal("...X", test_tracks[:with_overflow].rhythm)
44
32
 
45
- assert_equal(0, test_tracks[0].tick_count())
46
- assert_equal(1, test_tracks[1].tick_count())
47
- assert_equal(4, test_tracks[2].tick_count())
48
- assert_equal(8, test_tracks[3].tick_count())
49
- assert_equal(4, test_tracks[4].tick_count())
50
- assert_equal(32, test_tracks[5].tick_count())
51
- end
52
-
53
- def test_intro_sample_length
54
- # TODO: Add tests for when tick_sample_length has a non-zero remainder
33
+ assert_equal([0, 2, 2, 2, 2], test_tracks[:with_barlines].beats)
34
+ # Bar lines should be removed from rhythm:
35
+ assert_equal("X.X.X.X.", test_tracks[:with_barlines].rhythm)
55
36
 
56
- test_tracks = generate_test_data()
57
-
58
- tick_sample_length = W.sample_data.length # 6179.0
59
- assert_equal(0, test_tracks[0].intro_sample_length(tick_sample_length))
60
- assert_equal(0, test_tracks[1].intro_sample_length(tick_sample_length))
61
- assert_equal(18537, test_tracks[2].intro_sample_length(tick_sample_length))
62
- assert_equal(0, test_tracks[3].intro_sample_length(tick_sample_length))
63
- assert_equal(24716, test_tracks[4].intro_sample_length(tick_sample_length))
64
- assert_equal(12358, test_tracks[5].intro_sample_length(tick_sample_length))
65
- end
66
-
67
- def test_sample_length
68
- tick_sample_lengths = [
69
- W.sample_data.length, # 13860.0 - FIXME, not correct
70
- (W.sample_rate * SECONDS_IN_MINUTE) / 99 / 4, # 6681.81818181818 - FIXME, not correct
71
- (W.sample_rate * SECONDS_IN_MINUTE) / 41 / 4 # 16134.1463414634 - FIXME, not correct
72
- ]
73
-
74
- tick_sample_lengths.each {|tick_sample_length| helper_test_sample_length(tick_sample_length) }
75
- end
76
-
77
- def helper_test_sample_length(tick_sample_length)
78
- test_tracks = generate_test_data()
79
-
80
- assert_equal(0, test_tracks[0].sample_length(tick_sample_length))
81
- assert_equal(test_tracks[0].sample_data(tick_sample_length)[:primary].length, test_tracks[0].sample_length(tick_sample_length))
82
-
83
- assert_equal(tick_sample_length.floor, test_tracks[1].sample_length(tick_sample_length))
84
- assert_equal(test_tracks[1].sample_data(tick_sample_length)[:primary].length, test_tracks[1].sample_length(tick_sample_length))
37
+ assert_equal([4], test_tracks[:placeholder].beats)
38
+ assert_equal("....", test_tracks[:placeholder].rhythm)
85
39
 
86
- assert_equal((tick_sample_length * 4).floor, test_tracks[2].sample_length(tick_sample_length))
87
- assert_equal(test_tracks[2].sample_data(tick_sample_length)[:primary].length, test_tracks[2].sample_length(tick_sample_length))
88
-
89
- assert_equal((tick_sample_length * 8).floor, test_tracks[3].sample_length(tick_sample_length))
90
- assert_equal(test_tracks[3].sample_data(tick_sample_length)[:primary].length, test_tracks[3].sample_length(tick_sample_length))
91
-
92
- assert_equal((tick_sample_length * 4).floor, test_tracks[4].sample_length(tick_sample_length))
93
- assert_equal(test_tracks[4].sample_data(tick_sample_length)[:primary].length, test_tracks[4].sample_length(tick_sample_length))
94
-
95
- assert_equal((tick_sample_length * 32).floor, test_tracks[5].sample_length(tick_sample_length))
96
- assert_equal(test_tracks[5].sample_data(tick_sample_length)[:primary].length, test_tracks[5].sample_length(tick_sample_length))
40
+ assert_equal([2, 4, 4, 4, 2, 4, 4, 4, 4], test_tracks[:complicated].beats)
41
+ assert_equal("..X...X...X...X.X...X...X...X...", test_tracks[:complicated].rhythm)
97
42
  end
98
43
 
99
- def test_sample_length_with_overflow
100
- tick_sample_lengths = [
101
- W.sample_data.length, # 13860.0 - FIXME, not correct
102
- (W.sample_rate * SECONDS_IN_MINUTE) / 99 / 4, # 6681.81818181818 - FIXME, not correct
103
- (W.sample_rate * SECONDS_IN_MINUTE) / 41 / 4 # 16134.1463414634 - FIXME, not correct
104
- ]
105
-
106
- tick_sample_lengths.each { |tick_sample_length| helper_test_sample_length_with_overflow(tick_sample_length) }
107
- end
108
-
109
- def helper_test_sample_length_with_overflow(tick_sample_length)
110
- wave_sample_length = W.sample_data.length
111
- test_tracks = generate_test_data()
112
-
113
- sample_data = test_tracks[0].sample_data(tick_sample_length)
114
- assert_equal(0, test_tracks[0].sample_length_with_overflow(tick_sample_length))
115
- assert_equal(sample_data[:primary].length + sample_data[:overflow].length, test_tracks[0].sample_length_with_overflow(tick_sample_length))
116
-
117
- sample_data = test_tracks[1].sample_data(tick_sample_length)
118
- if(wave_sample_length > tick_sample_length * test_tracks[1].beats.last)
119
- assert_equal(wave_sample_length, test_tracks[1].sample_length_with_overflow(tick_sample_length))
120
- else
121
- assert_equal(tick_sample_length.floor, test_tracks[1].sample_length_with_overflow(tick_sample_length))
122
- assert_equal(sample_data[:primary].length + sample_data[:overflow].length, test_tracks[1].sample_length_with_overflow(tick_sample_length))
123
- end
124
-
125
- sample_data = test_tracks[2].sample_data(tick_sample_length)
126
- if(wave_sample_length > tick_sample_length * test_tracks[2].beats.last)
127
- assert_equal((tick_sample_length * 4).floor + (wave_sample_length - tick_sample_length.floor), test_tracks[2].sample_length_with_overflow(tick_sample_length))
128
- assert_equal(sample_data[:primary].length + sample_data[:overflow].length, test_tracks[2].sample_length_with_overflow(tick_sample_length))
129
- else
130
- assert_equal((tick_sample_length * 4).floor, test_tracks[2].sample_length_with_overflow(tick_sample_length))
131
- assert_equal(sample_data[:primary].length + sample_data[:overflow].length, test_tracks[2].sample_length_with_overflow(tick_sample_length))
132
- end
133
-
134
- sample_data = test_tracks[3].sample_data(tick_sample_length)
135
- if(wave_sample_length > tick_sample_length * test_tracks[3].beats.last)
136
- assert_equal((tick_sample_length * 8).floor + (wave_sample_length - (tick_sample_length * 2).floor), test_tracks[3].sample_length_with_overflow(tick_sample_length))
137
- assert_equal(sample_data[:primary].length + sample_data[:overflow].length, test_tracks[3].sample_length_with_overflow(tick_sample_length))
138
- else
139
- assert_equal((tick_sample_length * 8).floor, test_tracks[3].sample_length_with_overflow(tick_sample_length))
140
- assert_equal(sample_data[:primary].length + sample_data[:overflow].length, test_tracks[3].sample_length_with_overflow(tick_sample_length))
141
- end
142
-
143
- sample_data = test_tracks[4].sample_data(tick_sample_length)
144
- assert_equal((tick_sample_length * 4).floor, test_tracks[4].sample_length_with_overflow(tick_sample_length))
145
- assert_equal(sample_data[:primary].length + sample_data[:overflow].length, test_tracks[4].sample_length_with_overflow(tick_sample_length))
146
-
147
- sample_data = test_tracks[5].sample_data(tick_sample_length)
148
- assert_equal((tick_sample_length * 32).floor, test_tracks[5].sample_length_with_overflow(tick_sample_length))
149
- assert_equal(sample_data[:primary].length + sample_data[:overflow].length, test_tracks[5].sample_length_with_overflow(tick_sample_length))
150
- end
151
-
152
- def test_sample_data
153
- sample_data = W.sample_data
154
-
155
- tick_sample_length = W.sample_data.length # 6179.0
44
+ def test_step_count
156
45
  test_tracks = generate_test_data()
157
- assert_equal({:primary => [], :overflow => []}, test_tracks[0].sample_data(tick_sample_length))
158
- helper_test_sample_data(test_tracks[1], tick_sample_length, sample_data[0...tick_sample_length], [])
159
- helper_test_sample_data(test_tracks[2], tick_sample_length, zeroes(tick_sample_length * 3) + sample_data, [])
160
- helper_test_sample_data(test_tracks[3], tick_sample_length, (sample_data + zeroes(tick_sample_length)) * 4, [])
161
- helper_test_sample_data(test_tracks[4], tick_sample_length, zeroes(tick_sample_length * 4), [])
162
- # Track 6 is complicated. Will add test later...
163
-
164
-
165
- tick_sample_length = (W.sample_rate * 60.0) / 220 / 4 # 3006.818181818181818
166
- test_tracks = generate_test_data()
167
- assert_equal({:primary => [], :overflow => []}, test_tracks[0].sample_data(tick_sample_length))
168
- helper_test_sample_data(test_tracks[1], tick_sample_length, sample_data[0...tick_sample_length.floor], sample_data[tick_sample_length.floor...sample_data.length])
169
- #helper_test_sample_data(test_tracks[2], tick_sample_length, zeroes(tick_sample_length * 3) + sample_data[0..tick_sample_length.floor], sample_data[(tick_sample_length.floor)...sample_data.length])
170
- #helper_test_sample_data(test_tracks[3], tick_sample_length,
171
- # sample_data[0...(tick_sample_length * 2)] +
172
- # sample_data[0..(tick_sample_length * 2)] +
173
- # sample_data[0...(tick_sample_length * 2)] +
174
- # sample_data[0..(tick_sample_length * 2)],
175
- # sample_data[(tick_sample_length * 2)..sample_data.length])
176
- helper_test_sample_data(test_tracks[4], tick_sample_length, zeroes(tick_sample_length * 4), [])
177
-
178
-
179
- tick_sample_length = (W.sample_rate * 60.0) / 99 / 4 # 6681.818181818181818
180
- test_tracks = generate_test_data()
181
- assert_equal({:primary => [], :overflow => []}, test_tracks[0].sample_data(tick_sample_length))
182
- helper_test_sample_data(test_tracks[1], tick_sample_length, sample_data + zeroes(tick_sample_length - W.sample_data.length), [])
183
- helper_test_sample_data(test_tracks[2], tick_sample_length, zeroes(tick_sample_length * 3) + sample_data + zeroes(tick_sample_length - sample_data.length + 1), [])
184
- helper_test_sample_data(test_tracks[3], tick_sample_length,
185
- sample_data + zeroes((tick_sample_length * 2) - sample_data.length) +
186
- sample_data + zeroes((tick_sample_length * 2) - sample_data.length + 1) +
187
- sample_data + zeroes((tick_sample_length * 2) - sample_data.length) +
188
- sample_data + zeroes((tick_sample_length * 2) - sample_data.length + 1),
189
- [])
190
- helper_test_sample_data(test_tracks[4], tick_sample_length, zeroes(tick_sample_length * 4), [])
191
- end
192
-
193
- def helper_test_sample_data(track, tick_sample_length, expected_primary, expected_overflow)
194
- sample_data = track.sample_data(tick_sample_length)
195
46
 
196
- assert_equal(Hash, sample_data.class)
197
- assert_equal(["overflow", "primary"], sample_data.keys.map{|key| key.to_s}.sort)
198
- assert_equal(expected_primary.length, sample_data[:primary].length)
199
- assert_equal(expected_overflow.length, sample_data[:overflow].length)
200
- assert_equal(expected_primary, sample_data[:primary])
201
- assert_equal(expected_overflow, sample_data[:overflow])
47
+ assert_equal(0, test_tracks[:blank].step_count())
48
+ assert_equal(1, test_tracks[:solo].step_count())
49
+ assert_equal(4, test_tracks[:with_overflow].step_count())
50
+ assert_equal(8, test_tracks[:with_barlines].step_count())
51
+ assert_equal(4, test_tracks[:placeholder].step_count())
52
+ assert_equal(32, test_tracks[:complicated].step_count())
202
53
  end
203
-
204
- private
205
-
206
- def zeroes(length)
207
- return [].fill(0, 0, length)
208
- end
209
- end
54
+ end