beats 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (158) hide show
  1. data/README.markdown +29 -4
  2. data/bin/beats +36 -71
  3. data/lib/beats.rb +57 -0
  4. data/lib/beatswavefile.rb +93 -0
  5. data/lib/kit.rb +67 -11
  6. data/lib/pattern.rb +131 -86
  7. data/lib/song.rb +145 -114
  8. data/lib/songoptimizer.rb +154 -0
  9. data/lib/songparser.rb +40 -28
  10. data/lib/songsplitter.rb +38 -0
  11. data/lib/track.rb +33 -31
  12. data/lib/wavefile.rb +475 -0
  13. data/test/examples/combined.wav +0 -0
  14. data/test/examples/split-agogo_high.wav +0 -0
  15. data/test/examples/split-bass.wav +0 -0
  16. data/test/examples/split-hh_closed.wav +0 -0
  17. data/test/examples/split-snare.wav +0 -0
  18. data/test/examples/split-tom2.wav +0 -0
  19. data/test/examples/split-tom4.wav +0 -0
  20. data/test/fixtures/expected_output/example_combined_mono_16.wav +0 -0
  21. data/test/fixtures/expected_output/example_combined_mono_8.wav +0 -0
  22. data/test/fixtures/expected_output/example_combined_stereo_16.wav +0 -0
  23. data/test/fixtures/expected_output/example_combined_stereo_8.wav +0 -0
  24. data/test/fixtures/expected_output/example_split_mono_16-agogo.wav +0 -0
  25. data/test/fixtures/expected_output/example_split_mono_16-bass.wav +0 -0
  26. data/test/fixtures/expected_output/example_split_mono_16-hh_closed.wav +0 -0
  27. data/test/fixtures/expected_output/example_split_mono_16-snare.wav +0 -0
  28. data/test/fixtures/expected_output/example_split_mono_16-tom2_mono_16.wav +0 -0
  29. data/test/fixtures/expected_output/example_split_mono_16-tom4_mono_16.wav +0 -0
  30. data/test/fixtures/expected_output/example_split_mono_8-agogo.wav +0 -0
  31. data/test/fixtures/expected_output/example_split_mono_8-bass.wav +0 -0
  32. data/test/fixtures/expected_output/example_split_mono_8-hh_closed.wav +0 -0
  33. data/test/fixtures/expected_output/example_split_mono_8-snare.wav +0 -0
  34. data/test/fixtures/expected_output/example_split_mono_8-tom2_mono_8.wav +0 -0
  35. data/test/fixtures/expected_output/example_split_mono_8-tom4_mono_8.wav +0 -0
  36. data/test/fixtures/expected_output/example_split_stereo_16-agogo.wav +0 -0
  37. data/test/fixtures/expected_output/example_split_stereo_16-bass.wav +0 -0
  38. data/test/fixtures/expected_output/example_split_stereo_16-hh_closed.wav +0 -0
  39. data/test/fixtures/expected_output/example_split_stereo_16-snare.wav +0 -0
  40. data/test/fixtures/expected_output/example_split_stereo_16-tom2_stereo_16.wav +0 -0
  41. data/test/fixtures/expected_output/example_split_stereo_16-tom4_stereo_16.wav +0 -0
  42. data/test/fixtures/expected_output/example_split_stereo_8-agogo.wav +0 -0
  43. data/test/fixtures/expected_output/example_split_stereo_8-bass.wav +0 -0
  44. data/test/fixtures/expected_output/example_split_stereo_8-hh_closed.wav +0 -0
  45. data/test/fixtures/expected_output/example_split_stereo_8-snare.wav +0 -0
  46. data/test/fixtures/expected_output/example_split_stereo_8-tom2_stereo_8.wav +0 -0
  47. data/test/fixtures/expected_output/example_split_stereo_8-tom4_stereo_8.wav +0 -0
  48. data/test/fixtures/invalid/bad_repeat_count.txt +8 -0
  49. data/test/fixtures/invalid/bad_rhythm.txt +9 -0
  50. data/test/fixtures/invalid/bad_structure.txt +9 -0
  51. data/test/fixtures/invalid/bad_tempo.txt +8 -0
  52. data/test/fixtures/invalid/no_header.txt +3 -0
  53. data/test/fixtures/invalid/no_structure.txt +6 -0
  54. data/test/fixtures/invalid/pattern_with_no_tracks.txt +12 -0
  55. data/test/fixtures/invalid/sound_in_kit_not_found.txt +10 -0
  56. data/test/fixtures/invalid/sound_in_track_not_found.txt +8 -0
  57. data/test/fixtures/invalid/template.txt +31 -0
  58. data/test/fixtures/valid/example_mono_16.txt +28 -0
  59. data/test/fixtures/valid/example_mono_8.txt +28 -0
  60. data/test/fixtures/valid/example_no_kit.txt +30 -0
  61. data/test/fixtures/valid/example_stereo_16.txt +28 -0
  62. data/test/fixtures/valid/example_stereo_8.txt +28 -0
  63. data/test/fixtures/valid/example_with_empty_track.txt +10 -0
  64. data/test/fixtures/valid/example_with_kit.txt +34 -0
  65. data/test/fixtures/valid/no_tempo.txt +8 -0
  66. data/test/fixtures/valid/pattern_with_overflow.txt +9 -0
  67. data/test/fixtures/valid/repeats_not_specified.txt +10 -0
  68. data/test/fixtures/yaml/song_yaml.txt +30 -0
  69. data/test/includes.rb +11 -4
  70. data/test/integration.rb +100 -0
  71. data/test/kit_test.rb +39 -39
  72. data/test/pattern_test.rb +119 -71
  73. data/test/song_test.rb +87 -62
  74. data/test/songoptimizer_test.rb +162 -0
  75. data/test/songparser_test.rb +36 -165
  76. data/test/sounds/agogo_high_mono_16.wav +0 -0
  77. data/test/sounds/agogo_high_mono_8.wav +0 -0
  78. data/test/sounds/agogo_high_stereo_16.wav +0 -0
  79. data/test/sounds/agogo_high_stereo_8.wav +0 -0
  80. data/test/sounds/agogo_low_mono_16.wav +0 -0
  81. data/test/sounds/agogo_low_mono_8.wav +0 -0
  82. data/test/sounds/agogo_low_stereo_16.wav +0 -0
  83. data/test/sounds/agogo_low_stereo_8.wav +0 -0
  84. data/test/sounds/bass2_mono_16.wav +0 -0
  85. data/test/sounds/bass2_mono_8.wav +0 -0
  86. data/test/sounds/bass2_stereo_16.wav +0 -0
  87. data/test/sounds/bass2_stereo_8.wav +0 -0
  88. data/test/sounds/bass_mono_8.wav +0 -0
  89. data/test/sounds/bass_stereo_16.wav +0 -0
  90. data/test/sounds/bass_stereo_8.wav +0 -0
  91. data/test/sounds/clave_high_mono_16.wav +0 -0
  92. data/test/sounds/clave_high_mono_8.wav +0 -0
  93. data/test/sounds/clave_high_stereo_16.wav +0 -0
  94. data/test/sounds/clave_high_stereo_8.wav +0 -0
  95. data/test/sounds/clave_low_mono_16.wav +0 -0
  96. data/test/sounds/clave_low_mono_8.wav +0 -0
  97. data/test/sounds/clave_low_stereo_16.wav +0 -0
  98. data/test/sounds/clave_low_stereo_8.wav +0 -0
  99. data/test/sounds/conga_high_mono_16.wav +0 -0
  100. data/test/sounds/conga_high_mono_8.wav +0 -0
  101. data/test/sounds/conga_high_stereo_16.wav +0 -0
  102. data/test/sounds/conga_high_stereo_8.wav +0 -0
  103. data/test/sounds/conga_low_mono_16.wav +0 -0
  104. data/test/sounds/conga_low_mono_8.wav +0 -0
  105. data/test/sounds/conga_low_stereo_16.wav +0 -0
  106. data/test/sounds/conga_low_stereo_8.wav +0 -0
  107. data/test/sounds/cowbell_high_mono_16.wav +0 -0
  108. data/test/sounds/cowbell_high_mono_8.wav +0 -0
  109. data/test/sounds/cowbell_high_stereo_16.wav +0 -0
  110. data/test/sounds/cowbell_high_stereo_8.wav +0 -0
  111. data/test/sounds/cowbell_low_mono_16.wav +0 -0
  112. data/test/sounds/cowbell_low_mono_8.wav +0 -0
  113. data/test/sounds/cowbell_low_stereo_16.wav +0 -0
  114. data/test/sounds/cowbell_low_stereo_8.wav +0 -0
  115. data/test/sounds/hh_closed_mono_16.wav +0 -0
  116. data/test/sounds/hh_closed_mono_8.wav +0 -0
  117. data/test/sounds/hh_closed_stereo_16.wav +0 -0
  118. data/test/sounds/hh_closed_stereo_8.wav +0 -0
  119. data/test/sounds/hh_open_mono_16.wav +0 -0
  120. data/test/sounds/hh_open_mono_8.wav +0 -0
  121. data/test/sounds/hh_open_stereo_16.wav +0 -0
  122. data/test/sounds/hh_open_stereo_8.wav +0 -0
  123. data/test/sounds/ride_mono_16.wav +0 -0
  124. data/test/sounds/ride_mono_8.wav +0 -0
  125. data/test/sounds/ride_stereo_16.wav +0 -0
  126. data/test/sounds/ride_stereo_8.wav +0 -0
  127. data/test/sounds/rim_mono_16.wav +0 -0
  128. data/test/sounds/rim_mono_8.wav +0 -0
  129. data/test/sounds/rim_stereo_16.wav +0 -0
  130. data/test/sounds/rim_stereo_8.wav +0 -0
  131. data/test/sounds/sine-mono-8bit.wav +0 -0
  132. data/test/sounds/snare2_mono_16.wav +0 -0
  133. data/test/sounds/snare2_mono_8.wav +0 -0
  134. data/test/sounds/snare2_stereo_16.wav +0 -0
  135. data/test/sounds/snare2_stereo_8.wav +0 -0
  136. data/test/sounds/snare_mono_16.wav +0 -0
  137. data/test/sounds/snare_mono_8.wav +0 -0
  138. data/test/sounds/snare_stereo_16.wav +0 -0
  139. data/test/sounds/snare_stereo_8.wav +0 -0
  140. data/test/sounds/tom1_mono_16.wav +0 -0
  141. data/test/sounds/tom1_mono_8.wav +0 -0
  142. data/test/sounds/tom1_stereo_16.wav +0 -0
  143. data/test/sounds/tom1_stereo_8.wav +0 -0
  144. data/test/sounds/tom2_mono_16.wav +0 -0
  145. data/test/sounds/tom2_mono_8.wav +0 -0
  146. data/test/sounds/tom2_stereo_16.wav +0 -0
  147. data/test/sounds/tom2_stereo_8.wav +0 -0
  148. data/test/sounds/tom3_mono_16.wav +0 -0
  149. data/test/sounds/tom3_mono_8.wav +0 -0
  150. data/test/sounds/tom3_stereo_16.wav +0 -0
  151. data/test/sounds/tom3_stereo_8.wav +0 -0
  152. data/test/sounds/tom4_mono_16.wav +0 -0
  153. data/test/sounds/tom4_mono_8.wav +0 -0
  154. data/test/sounds/tom4_stereo_16.wav +0 -0
  155. data/test/sounds/tom4_stereo_8.wav +0 -0
  156. data/test/sounds/tone.wav +0 -0
  157. data/test/track_test.rb +78 -72
  158. metadata +277 -15
@@ -1,9 +1,16 @@
1
+ # Standard Ruby libraries
1
2
  require 'test/unit'
2
3
  require 'yaml'
4
+ require 'rubygems'
5
+ require 'wavefile'
6
+
7
+ # BEATS classes
8
+ require 'beats'
9
+ require 'kit'
10
+ require 'pattern'
3
11
  require 'song'
4
12
  require 'songparser'
5
- require 'pattern'
13
+ require 'songoptimizer'
14
+ require 'songsplitter'
6
15
  require 'track'
7
- require 'kit'
8
- require 'rubygems'
9
- require 'wavefile'
16
+ require 'beatswavefile'
@@ -0,0 +1,100 @@
1
+ $:.unshift File.join(File.dirname(__FILE__),'..','lib')
2
+
3
+ require 'test/includes'
4
+
5
+ class SongParserTest < Test::Unit::TestCase
6
+ TRACK_NAMES = ["bass", "snare", "hh_closed", "agogo", "tom4", "tom2"]
7
+ OUTPUT_FOLDER = "test/integration_output"
8
+
9
+ def test_bad_song_errors
10
+ invalid_fixtures = ["bad_tempo.txt",
11
+ "bad_repeat_count.txt",
12
+ "bad_structure.txt",
13
+ "no_header.txt",
14
+ "no_structure.txt",
15
+ "sound_in_kit_not_found.txt",
16
+ "sound_in_track_not_found.txt"]
17
+
18
+ invalid_fixtures.each do |fixture_name|
19
+ assert_raise(SongParseError) do
20
+ beats = Beats.new("test/fixtures/invalid/#{fixture_name}", "doesn't matter", {:split => false, :pattern => nil})
21
+ beats.run()
22
+ end
23
+ end
24
+ end
25
+
26
+
27
+ # TODO: Add tests for the -p option
28
+ # TODO: Add test verify that song generated with and without SongOptimizer are identical.
29
+
30
+ def test_generate_combined
31
+ # Make sure no output from previous tests is still around
32
+ clean_output_folder()
33
+
34
+ run_combined_test("mono", 8)
35
+ run_combined_test("mono", 16)
36
+ run_combined_test("stereo", 8)
37
+ run_combined_test("stereo", 16)
38
+ end
39
+
40
+ def run_combined_test(num_channels, bits_per_sample)
41
+ # Make sure no output from previous tests is still around
42
+ assert_equal([".", ".."], Dir.new(OUTPUT_FOLDER).entries)
43
+
44
+ song_fixture = "test/fixtures/valid/example_#{num_channels}_#{bits_per_sample}.txt"
45
+ actual_output_file = "#{OUTPUT_FOLDER}/example_combined_#{num_channels}_#{bits_per_sample}.wav"
46
+ expected_output_file = "test/fixtures/expected_output/example_combined_#{num_channels}_#{bits_per_sample}.wav"
47
+
48
+ beats = Beats.new(song_fixture, actual_output_file, {:split => false, :pattern => nil})
49
+ beats.run()
50
+ assert(File.exists?(actual_output_file), "Expected file '#{actual_output_file}' to exist, but it doesn't.")
51
+ assert_equal(File.read(expected_output_file), File.read(actual_output_file))
52
+
53
+ # Clean up after ourselves
54
+ File.delete(actual_output_file)
55
+ end
56
+
57
+ def test_generate_split
58
+ # Make sure no output from previous tests is still around
59
+ clean_output_folder()
60
+
61
+ run_split_test("mono", 8)
62
+ run_split_test("mono", 16)
63
+ run_split_test("stereo", 8)
64
+ run_split_test("stereo", 16)
65
+ end
66
+
67
+ def run_split_test(num_channels, bits_per_sample)
68
+ # Make sure no output from previous tests is still around
69
+ assert_equal([".", ".."], Dir.new(OUTPUT_FOLDER).entries)
70
+
71
+ song_fixture = "test/fixtures/valid/example_#{num_channels}_#{bits_per_sample}.txt"
72
+ actual_output_prefix = "#{OUTPUT_FOLDER}/example_split_#{num_channels}_#{bits_per_sample}"
73
+ expected_output_prefix = "test/fixtures/expected_output/example_split_#{num_channels}_#{bits_per_sample}"
74
+
75
+ beats = Beats.new(song_fixture, actual_output_prefix + ".wav", {:split => true, :pattern => nil})
76
+ beats.run()
77
+ TRACK_NAMES.each do |track_name|
78
+ if(track_name.start_with?("tom"))
79
+ track_name += "_#{num_channels}_#{bits_per_sample}"
80
+ end
81
+ actual_output_file = "#{actual_output_prefix}-#{track_name}.wav"
82
+ expected_output_file = "#{expected_output_prefix}-#{track_name}.wav"
83
+ assert(File.exists?(actual_output_file), "Expected file '#{actual_output_file}' to exist, but it doesn't.")
84
+ assert_equal(File.read(expected_output_file), File.read(actual_output_file))
85
+
86
+ # Clean up after ourselves
87
+ File.delete(actual_output_file)
88
+ end
89
+ end
90
+
91
+ def clean_output_folder()
92
+ dir = Dir.new(OUTPUT_FOLDER)
93
+ file_names = dir.entries
94
+ file_names.each do |file_name|
95
+ if(file_name != "." && file_name != "..")
96
+ File.delete("#{OUTPUT_FOLDER}/#{file_name}")
97
+ end
98
+ end
99
+ end
100
+ end
@@ -10,36 +10,36 @@ class SongTest < Test::Unit::TestCase
10
10
  # Test adding sounds with progressively higher bits per sample and num channels.
11
11
  # Verify that kit.bits_per_sample and kit.num_channels is ratcheted up.
12
12
  kit = Kit.new("test/sounds")
13
- assert_equal(kit.bits_per_sample, 0)
14
- assert_equal(kit.num_channels, 0)
15
- assert_equal(kit.size, 0)
13
+ assert_equal(16, kit.bits_per_sample)
14
+ assert_equal(1, kit.num_channels)
15
+ assert_equal(0, kit.size)
16
16
  kit.add("mono8", "bass_mono_8.wav")
17
- assert_equal(kit.bits_per_sample, 8)
18
- assert_equal(kit.num_channels, 1)
19
- assert_equal(kit.size, 1)
17
+ assert_equal(16, kit.bits_per_sample)
18
+ assert_equal(1, kit.num_channels)
19
+ assert_equal(1, kit.size)
20
20
  kit.add("mono16", "bass_mono_16.wav")
21
- assert_equal(kit.bits_per_sample, 16)
22
- assert_equal(kit.num_channels, 1)
23
- assert_equal(kit.size, 2)
21
+ assert_equal(16, kit.bits_per_sample)
22
+ assert_equal(1, kit.num_channels)
23
+ assert_equal(2, kit.size)
24
24
  kit.add("stereo16", "bass_stereo_16.wav")
25
- assert_equal(kit.bits_per_sample, 16)
26
- assert_equal(kit.num_channels, 2)
27
- assert_equal(kit.size, 3)
25
+ assert_equal(16, kit.bits_per_sample)
26
+ assert_equal(2, kit.num_channels)
27
+ assert_equal(3, kit.size)
28
28
 
29
29
  # Test adding sounds with progressively lower bits per sample and num channels.
30
30
  # Verify that kit.bits_per_sample and kit.num_channels doesn't change.
31
31
  kit = Kit.new("test/sounds")
32
- assert_equal(kit.bits_per_sample, 0)
33
- assert_equal(kit.num_channels, 0)
32
+ assert_equal(16, kit.bits_per_sample)
33
+ assert_equal(1, kit.num_channels)
34
34
  kit.add("stereo16", "bass_stereo_16.wav")
35
- assert_equal(kit.bits_per_sample, 16)
36
- assert_equal(kit.num_channels, 2)
35
+ assert_equal(16, kit.bits_per_sample)
36
+ assert_equal(2, kit.num_channels)
37
37
  kit.add("mono16", "bass_mono_16.wav")
38
- assert_equal(kit.bits_per_sample, 16)
39
- assert_equal(kit.num_channels, 2)
38
+ assert_equal(16, kit.bits_per_sample)
39
+ assert_equal(2, kit.num_channels)
40
40
  kit.add("mono8", "bass_mono_8.wav")
41
- assert_equal(kit.bits_per_sample, 16)
42
- assert_equal(kit.num_channels, 2)
41
+ assert_equal(16, kit.bits_per_sample)
42
+ assert_equal(2, kit.num_channels)
43
43
  end
44
44
 
45
45
  def test_invalid_add
@@ -56,32 +56,32 @@ class SongTest < Test::Unit::TestCase
56
56
  # Verify that sample data bits per sample and num channels is ratcheted up.
57
57
  kit.add("mono8", "bass_mono_8.wav")
58
58
  sample_data = kit.get_sample_data("mono8")
59
- assert(sample_data.max <= MAX_SAMPLE_8BIT)
60
- assert(sample_data.min >= MIN_SAMPLE_8BIT)
59
+ assert(sample_data.max > MAX_SAMPLE_8BIT)
60
+ assert(sample_data.min < 0)
61
61
  all_are_fixnums = true
62
- sample_data.each {|sample|
62
+ sample_data.each do |sample|
63
63
  all_are_fixnums &&= sample.class == Fixnum
64
- }
64
+ end
65
65
  assert(all_are_fixnums)
66
66
 
67
67
  kit.add("mono16", "bass_mono_16.wav")
68
68
  sample_data = kit.get_sample_data("mono8")
69
69
  assert(sample_data.max > MAX_SAMPLE_8BIT)
70
- assert(sample_data.min < MIN_SAMPLE_8BIT)
70
+ assert(sample_data.min < 0)
71
71
  all_are_fixnums = true
72
- sample_data.each {|sample|
72
+ sample_data.each do |sample|
73
73
  all_are_fixnums &&= sample.class == Fixnum
74
- }
74
+ end
75
75
  assert(all_are_fixnums)
76
76
 
77
77
  kit.add("stereo16", "bass_stereo_16.wav")
78
78
  sample_data = kit.get_sample_data("stereo16")
79
79
  assert(sample_data.flatten.max > MAX_SAMPLE_8BIT)
80
- assert(sample_data.flatten.min < MIN_SAMPLE_8BIT)
80
+ assert(sample_data.flatten.min < 0)
81
81
  all_are_arrays = true
82
- sample_data.each {|sample|
82
+ sample_data.each do |sample|
83
83
  all_are_arrays &&= sample.class == Array
84
- }
84
+ end
85
85
  assert(all_are_arrays)
86
86
  assert(sample_data.first.length == 2)
87
87
 
@@ -93,33 +93,33 @@ class SongTest < Test::Unit::TestCase
93
93
  kit.add("stereo16", "bass_stereo_16.wav")
94
94
  sample_data = kit.get_sample_data("stereo16")
95
95
  assert(sample_data.flatten.max > MAX_SAMPLE_8BIT)
96
- assert(sample_data.flatten.min < MIN_SAMPLE_8BIT)
96
+ assert(sample_data.flatten.min < 0)
97
97
  all_are_arrays = true
98
- sample_data.each {|sample|
98
+ sample_data.each do |sample|
99
99
  all_are_arrays &&= sample.class == Array
100
- }
100
+ end
101
101
  assert(all_are_arrays)
102
102
  assert(sample_data.first.length == 2)
103
103
 
104
104
  kit.add("mono16", "bass_mono_16.wav")
105
105
  sample_data = kit.get_sample_data("mono16")
106
106
  assert(sample_data.flatten.max > MAX_SAMPLE_8BIT)
107
- assert(sample_data.flatten.min < MIN_SAMPLE_8BIT)
107
+ assert(sample_data.flatten.min < 0)
108
108
  all_are_arrays = true
109
- sample_data.each {|sample|
109
+ sample_data.each do |sample|
110
110
  all_are_arrays &&= sample.class == Array
111
- }
111
+ end
112
112
  assert(all_are_arrays)
113
113
  assert(sample_data.first.length == 2)
114
114
 
115
115
  kit.add("mono8", "bass_mono_8.wav")
116
116
  sample_data = kit.get_sample_data("mono8")
117
117
  assert(sample_data.flatten.max > MAX_SAMPLE_8BIT)
118
- assert(sample_data.flatten.min < MIN_SAMPLE_8BIT)
118
+ assert(sample_data.flatten.min < 0)
119
119
  all_are_arrays = true
120
- sample_data.each {|sample|
120
+ sample_data.each do |sample|
121
121
  all_are_arrays &&= sample.class == Array
122
- }
122
+ end
123
123
  assert(all_are_arrays)
124
124
  assert(sample_data.first.length == 2)
125
125
  end
@@ -13,23 +13,23 @@ class PatternTest < Test::Unit::TestCase
13
13
  kit.add("hh_closed.wav", "hh_closed_mono_8.wav")
14
14
  kit.add("hh_open.wav", "hh_open_mono_8.wav")
15
15
 
16
- test_patterns = []
16
+ test_patterns = {}
17
17
 
18
- p1 = Pattern.new :blank
19
- test_patterns << p1
18
+ pattern = Pattern.new :blank
19
+ test_patterns[:blank] = pattern
20
20
 
21
- p2 = Pattern.new :verse
22
- p2.track "bass.wav", kit.get_sample_data("bass.wav"), "X...X...X...XX..X...X...XX..X..."
23
- p2.track "snare.wav", kit.get_sample_data("snare.wav"), "..X...X...X...X.X...X...X...X..."
24
- p2.track "hh_closed.wav", kit.get_sample_data("hh_closed.wav"), "X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X."
25
- p2.track "hh_open.wav", kit.get_sample_data("hh_open.wav"), "X...............X..............X"
26
- test_patterns << p2
21
+ pattern = Pattern.new :verse
22
+ pattern.track "bass.wav", kit.get_sample_data("bass.wav"), "X...X...X...XX..X...X...XX..X..."
23
+ pattern.track "snare.wav", kit.get_sample_data("snare.wav"), "..X...X...X...X.X...X...X...X..."
24
+ pattern.track "hh_closed.wav", kit.get_sample_data("hh_closed.wav"), "X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X."
25
+ pattern.track "hh_open.wav", kit.get_sample_data("hh_open.wav"), "X...............X..............X"
26
+ test_patterns[:verse] = pattern
27
27
 
28
- p3 = Pattern.new :staircase
29
- p3.track "bass.wav", kit.get_sample_data("bass.wav"), "X..."
30
- p3.track "snare.wav", kit.get_sample_data("snare.wav"), "X.."
31
- p3.track "hh_closed.wav", kit.get_sample_data("hh_closed.wav"), "X."
32
- test_patterns << p3
28
+ pattern = Pattern.new :staircase
29
+ pattern.track "bass.wav", kit.get_sample_data("bass.wav"), "X..."
30
+ pattern.track "snare.wav", kit.get_sample_data("snare.wav"), "X.."
31
+ pattern.track "hh_closed.wav", kit.get_sample_data("hh_closed.wav"), "X."
32
+ test_patterns[:staircase] = pattern
33
33
 
34
34
  return test_patterns
35
35
  end
@@ -37,15 +37,15 @@ class PatternTest < Test::Unit::TestCase
37
37
  def test_initialize
38
38
  test_patterns = generate_test_data()
39
39
 
40
- pattern = test_patterns.shift()
40
+ pattern = test_patterns[:blank]
41
41
  assert_equal(pattern.name, :blank)
42
42
  assert_equal(pattern.tracks.length, 0)
43
43
 
44
- pattern = test_patterns.shift()
44
+ pattern = test_patterns[:verse]
45
45
  assert_equal(pattern.name, :verse)
46
46
  assert_equal(pattern.tracks.length, 4)
47
47
 
48
- pattern = test_patterns.shift()
48
+ pattern = test_patterns[:staircase]
49
49
  assert_equal(pattern.name, :staircase)
50
50
  assert_equal(pattern.tracks.length, 3)
51
51
  end
@@ -54,21 +54,76 @@ class PatternTest < Test::Unit::TestCase
54
54
  test_patterns = generate_test_data()
55
55
 
56
56
  tick_sample_length = 13860.0
57
- assert_equal(test_patterns[0].sample_length(tick_sample_length), 0)
58
- assert_equal(test_patterns[1].sample_length(tick_sample_length), tick_sample_length * 32)
59
- assert_equal(test_patterns[2].sample_length(tick_sample_length), tick_sample_length * 4)
57
+ assert_equal(test_patterns[:blank].sample_length(tick_sample_length), 0)
58
+ assert_equal(test_patterns[:verse].sample_length(tick_sample_length), tick_sample_length * 32)
59
+ assert_equal(test_patterns[:staircase].sample_length(tick_sample_length), tick_sample_length * 4)
60
60
 
61
61
  tick_sample_length = 6681.81818181818
62
- assert_equal(test_patterns[0].sample_length(tick_sample_length), 0)
63
- assert_equal(test_patterns[1].sample_length(tick_sample_length), (tick_sample_length * 32).floor)
64
- assert_equal(test_patterns[2].sample_length(tick_sample_length), (tick_sample_length * 4).floor)
62
+ assert_equal(test_patterns[:blank].sample_length(tick_sample_length), 0)
63
+ assert_equal(test_patterns[:verse].sample_length(tick_sample_length), (tick_sample_length * 32).floor)
64
+ assert_equal(test_patterns[:staircase].sample_length(tick_sample_length), (tick_sample_length * 4).floor)
65
65
 
66
66
  tick_sample_length = 16134.1463414634
67
- assert_equal(test_patterns[0].sample_length(tick_sample_length), 0)
68
- assert_equal(test_patterns[1].sample_length(tick_sample_length), (tick_sample_length * 32).floor)
69
- assert_equal(test_patterns[2].sample_length(tick_sample_length), (tick_sample_length * 4).floor)
67
+ assert_equal(test_patterns[:blank].sample_length(tick_sample_length), 0)
68
+ assert_equal(test_patterns[:verse].sample_length(tick_sample_length), (tick_sample_length * 32).floor)
69
+ assert_equal(test_patterns[:staircase].sample_length(tick_sample_length), (tick_sample_length * 4).floor)
70
70
  end
71
71
 
72
+ def test_tick_count
73
+ test_patterns = generate_test_data()
74
+
75
+ assert_equal(0, test_patterns[:blank].tick_count())
76
+ assert_equal(32, test_patterns[:verse].tick_count())
77
+ assert_equal(4, test_patterns[:staircase].tick_count())
78
+ end
79
+
80
+ def test_same_tracks_as?
81
+ left_pattern = Pattern.new("left")
82
+ left_pattern.track("bass", nil, "X...X...")
83
+ left_pattern.track("snare", nil, "..X...X.")
84
+ left_pattern.track("hh_closed", nil, "X.X.X.X.")
85
+
86
+ right_pattern = Pattern.new("right")
87
+ right_pattern.track("bass", nil, "X...X...")
88
+ right_pattern.track("snare", nil, "..X...X.")
89
+ right_pattern.track("hh_closed", nil, "X.X.X.X.")
90
+ assert(left_pattern.same_tracks_as?(right_pattern))
91
+ assert(right_pattern.same_tracks_as?(left_pattern))
92
+
93
+ # Now switch up the order. Left and right should still be equal.
94
+ right_pattern = Pattern.new("right")
95
+ right_pattern.track("snare", nil, "..X...X.")
96
+ right_pattern.track("hh_closed", nil, "X.X.X.X.")
97
+ right_pattern.track("bass", nil, "X...X...")
98
+ assert(left_pattern.same_tracks_as?(right_pattern))
99
+ assert(right_pattern.same_tracks_as?(left_pattern))
100
+
101
+ # Now compare the pattern with same rhythms but different track names. Should not be equal.
102
+ different_names_pattern = Pattern.new("different_names")
103
+ different_names_pattern.track("tom", nil, "X...X...")
104
+ different_names_pattern.track("cymbal", nil, "..X...X.")
105
+ different_names_pattern.track("hh_open", nil, "X.X.X.X.")
106
+ assert_equal(false, left_pattern.same_tracks_as?(different_names_pattern))
107
+ assert_equal(false, different_names_pattern.same_tracks_as?(left_pattern))
108
+
109
+ # Now compare the pattern with same track names but different rhythms. Should not be equal.
110
+ different_beats_pattern = Pattern.new("different_beats")
111
+ different_beats_pattern.track("bass", nil, "X...X...")
112
+ different_beats_pattern.track("snare", nil, "..X...X.")
113
+ different_beats_pattern.track("hh_closed", nil, "X.XXX.X.")
114
+ assert_equal(false, left_pattern.same_tracks_as?(different_beats_pattern))
115
+ assert_equal(false, different_beats_pattern.same_tracks_as?(left_pattern))
116
+
117
+ # Now compare a pattern with the same tracks, but with one extra one as well. Should not be equal.
118
+ something_extra = Pattern.new("something_extra")
119
+ something_extra.track("bass", nil, "X...X...")
120
+ something_extra.track("snare", nil, "..X...X.")
121
+ something_extra.track("hh_closed", nil, "X.X.X.X.")
122
+ something_extra.track("extra", nil, "X..X..X.")
123
+ assert_equal(false, left_pattern.same_tracks_as?(something_extra))
124
+ assert_equal(false, something_extra.same_tracks_as?(left_pattern))
125
+ end
126
+
72
127
  def test_sample_data
73
128
  tick_sample_lengths = [
74
129
  13860.0,
@@ -84,7 +139,7 @@ class PatternTest < Test::Unit::TestCase
84
139
  test_patterns = generate_test_data()
85
140
 
86
141
  # Combined
87
- test_patterns.each{|test_pattern|
142
+ test_patterns.each{|pattern_name, test_pattern|
88
143
  sample_data = test_pattern.sample_data(tick_sample_length, 1, test_pattern.tracks.length, {})
89
144
  assert_equal(sample_data.class, Hash)
90
145
  assert_equal(sample_data.keys.map{|key| key.to_s}.sort, ["overflow", "primary"])
@@ -93,61 +148,54 @@ class PatternTest < Test::Unit::TestCase
93
148
  full_sample_length = test_pattern.sample_length_with_overflow(tick_sample_length)
94
149
  assert_equal(sample_data[:primary].length, primary_sample_length)
95
150
  assert_equal(sample_data[:overflow].length, test_pattern.tracks.length)
96
- sample_data[:overflow].values.each {|track_overflow|
151
+ sample_data[:overflow].values.each do |track_overflow|
97
152
  assert_equal(track_overflow.class, Array)
98
- }
153
+ end
99
154
  # To do: add test to verify that longest overflow == full_sample_length - primary_sample_length
100
155
  }
101
-
102
- #Split
103
- track_samples = test_patterns[0].sample_data(tick_sample_length, 1, 0, {}, true)
104
- assert_equal(track_samples.class, Hash)
105
- assert_equal(track_samples.keys.map{|key| key.to_s}.sort, ["overflow", "primary"])
106
-
107
- track_samples = test_patterns[1].sample_data(tick_sample_length, 1, 4, {}, true)
108
- assert_equal(track_samples.class, Hash)
109
- assert_equal(track_samples[:primary].keys.map{|key| key.to_s}.sort,
110
- ["bass.wav", "hh_closed.wav", "hh_open.wav", "snare.wav"])
111
- primary = track_samples[:primary]
112
- primary.keys.each{|name|
113
- assert_equal(primary[name].length, test_patterns[1].sample_length(tick_sample_length))
114
- }
115
- overflow = track_samples[:overflow]
116
- longest_overflow = find_longest_overflow(overflow)
117
- overflow.keys.each{|name|
118
- assert_equal(overflow[name].class, Array)
119
- #assert_lessthan(overflow[name].length, test_patterns[1].sample_length_with_overflow(tick_sample_length) - test_patterns[1].sample_length(tick_sample_length))
120
- }
121
- assert_equal(overflow[longest_overflow].length, test_patterns[1].sample_length_with_overflow(tick_sample_length) - test_patterns[1].sample_length(tick_sample_length))
122
-
123
- track_samples = test_patterns[2].sample_data(tick_sample_length, 1, 3, {}, true)
124
- assert_equal(track_samples.class, Hash)
125
- assert_equal(track_samples[:primary].keys.map{|key| key.to_s}.sort,
126
- ["bass.wav", "hh_closed.wav", "snare.wav"])
127
- primary = track_samples[:primary]
128
- primary.keys.each{|name|
129
- assert_equal(primary[name].length, test_patterns[2].sample_length(tick_sample_length))
130
- }
131
- overflow = track_samples[:overflow]
132
- longest_overflow = find_longest_overflow(overflow)
133
- overflow.keys.each{|name|
134
- assert_equal(overflow[name].class, Array)
135
- }
136
- assert_equal(overflow[longest_overflow].length, test_patterns[2].sample_length_with_overflow(tick_sample_length) - test_patterns[2].sample_length(tick_sample_length))
137
- primary.keys.each{|name|
138
- assert_equal(primary[name].length, (tick_sample_length * 4).floor)
139
- assert_equal(primary[name].length, test_patterns[2].sample_length(tick_sample_length))
140
- }
141
156
  end
142
157
 
143
158
  def find_longest_overflow(overflow)
144
159
  longest_overflow = overflow.keys.first
145
- overflow.keys.each {|name|
160
+ overflow.keys.each do |name|
146
161
  if(overflow[name].length > overflow[longest_overflow].length)
147
162
  longest_overflow = name
148
163
  end
149
- }
164
+ end
150
165
 
151
166
  return longest_overflow
152
167
  end
168
+
169
+ # Test scenario where incoming overflow for a track not in the pattern is longer than the pattern itself.
170
+ # In this situation, the the overflow should continue into the outgoing overflow so it is handled in the
171
+ # next pattern.
172
+ def test_sample_data_incoming_overflow_longer_than_pattern_length
173
+ # bass.wav sample length: 6179
174
+ # snare.wav sample length: 14700
175
+ kit = Kit.new("test/sounds")
176
+ kit.add("bass", "bass_mono_8.wav")
177
+ kit.add("snare", "snare_mono_8.wav")
178
+ bass_sample_data = kit.get_sample_data("bass")
179
+ snare_sample_data = kit.get_sample_data("snare")
180
+ tick_sample_length = bass_sample_data.length.to_f
181
+
182
+ # Construct expected
183
+ expected_primary_sample_data = Array.new(bass_sample_data.length)
184
+ bass_sample_data.length.times do |i|
185
+ expected_primary_sample_data[i] = ((bass_sample_data[i] + snare_sample_data[i]) / 2).round
186
+ end
187
+ expected_overflow_sample_data = snare_sample_data[bass_sample_data.length...snare_sample_data.length]
188
+
189
+ # Get actual
190
+ pattern = Pattern.new :verse
191
+ pattern.track "bass", bass_sample_data, "X"
192
+ actual_sample_data = pattern.sample_data(tick_sample_length, 1, 2, {"snare" => snare_sample_data})
193
+
194
+ assert_equal(Hash, actual_sample_data.class)
195
+ assert_equal(["overflow", "primary"], actual_sample_data.keys.map{|key| key.to_s}.sort)
196
+ assert_equal(expected_primary_sample_data, actual_sample_data[:primary])
197
+ assert_equal(["bass", "snare"], actual_sample_data[:overflow].keys.sort)
198
+ assert_equal([], actual_sample_data[:overflow]["bass"])
199
+ assert_equal(expected_overflow_sample_data, actual_sample_data[:overflow]["snare"])
200
+ end
153
201
  end