beats 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
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