beats 1.1.0 → 1.2.0

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