beats 2.1.1 → 2.1.2

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -23
  3. data/README.markdown +7 -15
  4. data/Rakefile +3 -3
  5. data/bin/beats +5 -5
  6. data/lib/beats.rb +15 -15
  7. data/lib/beats/kit.rb +1 -1
  8. data/lib/beats/kit_builder.rb +5 -1
  9. data/lib/beats/song.rb +1 -1
  10. data/lib/beats/song_parser.rb +45 -23
  11. data/test/audio_engine_test.rb +1 -1
  12. data/test/audio_utils_test.rb +1 -1
  13. data/test/caching_writer_test.rb +1 -1
  14. data/test/fixtures/invalid/flow_invalid_repeat_count_prefix.txt +8 -0
  15. data/test/fixtures/invalid/flow_invalid_repeat_count_suffix.txt +8 -0
  16. data/test/fixtures/invalid/{bad_repeat_count.txt → flow_missing_repeat_count.txt} +3 -3
  17. data/test/fixtures/invalid/flow_negative_repeat_count.txt +8 -0
  18. data/test/fixtures/invalid/{bad_flow.txt → flow_non_existent_pattern.txt} +0 -0
  19. data/test/fixtures/invalid/flow_non_string_repeat_count.txt +8 -0
  20. data/test/fixtures/invalid/flow_not_an_array.txt +15 -0
  21. data/test/fixtures/invalid/flow_pattern_name_not_a_string.txt +15 -0
  22. data/test/fixtures/invalid/flow_repeat_count_is_missing_prefix.txt +8 -0
  23. data/test/fixtures/invalid/flow_section_not_a_string_or_hash.txt +15 -0
  24. data/test/fixtures/invalid/kit_filename_not_a_string.txt +17 -0
  25. data/test/fixtures/invalid/kit_not_an_array.txt +17 -0
  26. data/test/fixtures/invalid/pattern_not_an_array.txt +17 -0
  27. data/test/fixtures/invalid/pattern_referenced_pattern_name_not_a_string.txt +19 -0
  28. data/test/fixtures/invalid/pattern_unreferenced_pattern_name_not_a_string.txt +18 -0
  29. data/test/fixtures/invalid/pattern_with_incomplete_track.txt +10 -0
  30. data/test/fixtures/invalid/pattern_with_nil_track.txt +10 -0
  31. data/test/fixtures/valid/composite_sounds_trailing_comma.txt +16 -0
  32. data/test/fixtures/valid/example_alternate_array_syntax.txt +11 -0
  33. data/test/fixtures/valid/{multiple_song_header_sections.txt → multiple_copies_of_song_components.txt} +28 -4
  34. data/test/fixtures/valid/multiple_yaml_documents.txt +33 -0
  35. data/test/fixtures/valid/track_sound_has_mixed_capitalization.txt +13 -0
  36. data/test/includes.rb +2 -2
  37. data/test/integration_test.rb +3 -3
  38. data/test/kit_builder_test.rb +3 -3
  39. data/test/kit_test.rb +7 -7
  40. data/test/pattern_test.rb +176 -176
  41. data/test/song_optimizer_test.rb +1 -1
  42. data/test/song_parser_test.rb +86 -11
  43. data/test/song_swinger_test.rb +1 -1
  44. data/test/song_test.rb +1 -1
  45. data/test/sounds/MiXeD_CaPiTaLiZaTiOn.wav +0 -0
  46. data/test/sounds/bass_mono_16_11025.wav +0 -0
  47. data/test/sounds/bass_mono_16_22050.wav +0 -0
  48. data/test/sounds/bass_mono_24.wav +0 -0
  49. data/test/sounds/bass_mono_8.mp3 +0 -0
  50. data/test/track_test.rb +1 -1
  51. metadata +58 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ae934eac074a47b7bb5f587fd96eb457f0ddabfbf18f5667e838dd01832c247
4
- data.tar.gz: ee54703a136d795679807ea67f4f5cb79532f090d0c641f924590a036a35b2d9
3
+ metadata.gz: 387b94eb7731f5bf659134c0e6ceb9d0ba01947e130a64a18517fde233a8a958
4
+ data.tar.gz: c2b0b0b67d07f471861b5b457b522739f0cdc68f6240e66ee999e935633ebfd0
5
5
  SHA512:
6
- metadata.gz: 2f2e931c783acab297d17187cadd51ebbba9cd5bd55ec9a81a6fddd15b0d95b8b03027508cbed4e3b07740a3e0d04d25e9e000b06074b916bc23cc6e4e0df3ed
7
- data.tar.gz: f6fe7883c7a9f21d62d252eec3f646aa2af5f47acda24d20dc43c8761fcf84c87716a2cbc53248fdcf31f4c7832cb5d24353ea49520ada5555a6a9cb85234898
6
+ metadata.gz: fe882750e5035fb61aed261c9d7b7e61f3d048da16ee09aaeca089c07aba44abdc15ccceec8f0cc7b7885ddd1c997f3eb19d6abc46d64891aac48996a396c35b
7
+ data.tar.gz: 5f9a9ffcc09a015fd8bdd00a6308be9af14029924ba9d65967b0fa6d5b9a37c3545155b3ad51f79d8328770310788e82cafd49bb4314272686b7f0dbc9504240
data/LICENSE CHANGED
@@ -1,24 +1,22 @@
1
- == Beats Drum Machine
1
+ Copyright (c) 2010-19 Joel Strait
2
2
 
3
- # Copyright (c) 2010-18 Joel Strait
4
- #
5
- # Permission is hereby granted, free of charge, to any person
6
- # obtaining a copy of this software and associated documentation
7
- # files (the "Software"), to deal in the Software without
8
- # restriction, including without limitation the rights to use,
9
- # copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- # copies of the Software, and to permit persons to whom the
11
- # Software is furnished to do so, subject to the following
12
- # conditions:
13
- #
14
- # The above copyright notice and this permission notice shall be
15
- # included in all copies or substantial portions of the Software.
16
- #
17
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
- # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
- # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
- # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
- # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
- # OTHER DEALINGS IN THE SOFTWARE.
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -35,7 +35,7 @@ For more, check out [beatsdrummachine.com](https://beatsdrummachine.com)
35
35
  Installation
36
36
  ------------
37
37
 
38
- To install the latest stable version (2.1.1) from [rubygems.org](https://rubygems.org/gems/beats), run the following from the command line:
38
+ To install the latest stable version (2.1.2) from [rubygems.org](https://rubygems.org/gems/beats), run the following from the command line:
39
39
 
40
40
  gem install beats
41
41
 
@@ -49,25 +49,17 @@ Beats is not very useful unless you have some sounds to use with it. You can dow
49
49
  Usage
50
50
  -----
51
51
 
52
- Beats runs from the command-line. Run `beats -h` to see the available options. For more detailed instructions, visit [https://github.com/jstrait/beats/wiki/Usage](https://github.com/jstrait/beats/wiki/Usage) on the [Beats Wiki](https://github.com/jstrait/beats/wiki).
52
+ Beats runs from the command-line. Run `beats -h` to see the available options. For more detailed instructions, visit <https://beatsdrummachine.com/usage/>.
53
53
 
54
- Check out [this tutorial at beatsdrummachine.com](https://beatsdrummachine.com/tutorial/) to see an example of how to create a beat from sratch.
54
+ Check out [this tutorial at beatsdrummachine.com](https://beatsdrummachine.com/tutorial/) to see an example of how to create a beat from scratch.
55
55
 
56
56
 
57
- What's New in v2.1.1
57
+ What's New in v2.1.2
58
58
  --------------------
59
59
 
60
- The latest version of Beats is 2.1.1, released on June 29, 2018. It contains these changes:
60
+ The latest version of Beats is 2.1.2, released on December 18, 2019. It contains these changes:
61
61
 
62
- * Several error messages are improved to be more accurate or specific.
63
- * **Bug fix**: Songs can now use *.wav files with more than 2 channels. Previously, using a sound with more than 2 channels would cause a fatal `Invalid sample data array in AudioUtils.normalize()` error.
64
- * **Bug fix**: If a sound is defined multiple times in a Kit, the final definition should be used as the winner. However, previously this did not occur if the earlier definition was for a composite sound. For example, with this Kit:
65
-
66
- Kit:
67
- - sound: [sound1.wav, sound2.wav]
68
- - sound: sound3.wav
69
-
70
- `sound` will now be bound to `sound3.wav`, not `[sound1.wav, sound2.wav]`.
62
+ * Several confusing/unhelpful errors shown due to an error in an input file have been improved. For example, if a pattern has the invalid name "4", the error message will now be `Pattern name '4' is not valid. It must be a value that will be parsed from YAML as a String.`, instead of `undefined method 'downcase' for 4:Integer`.
71
63
 
72
64
  For info about previous releases, visit https://github.com/jstrait/beats/releases.
73
65
 
@@ -92,7 +84,7 @@ To run the tests:
92
84
  Found a Bug? Have a Suggestion? Want to Contribute?
93
85
  ---------------------------------------------------
94
86
 
95
- Contact me (Joel Strait) by sending a GitHub message or opening a GitHub issue.
87
+ Contact me (Joel Strait) by opening a GitHub issue.
96
88
 
97
89
 
98
90
  License
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
- require 'rake/testtask'
1
+ require "rake/testtask"
2
2
 
3
3
  Rake::TestTask.new do |t|
4
- t.libs << 'lib' << 'test'
5
- t.pattern = 'test/**/*_test.rb'
4
+ t.libs << "lib" << "test"
5
+ t.pattern = "test/**/*_test.rb"
6
6
  end
data/bin/beats CHANGED
@@ -15,24 +15,24 @@ def parse_options
15
15
  optparse = OptionParser.new do |opts|
16
16
  opts.banner = "usage: beats [options] input_file [output_file]"
17
17
 
18
- opts.on('-s', '--split', "Save each track to an individual wave file") do
18
+ opts.on("-s", "--split", "Save each track to an individual wave file") do
19
19
  options[:split] = true
20
20
  end
21
21
 
22
- opts.on('-p', '--pattern PATTERN_NAME', "Output a single pattern instead of the whole song" ) do |p|
22
+ opts.on("-p", "--pattern PATTERN_NAME", "Output a single pattern instead of the whole song") do |p|
23
23
  options[:pattern] = p
24
24
  end
25
25
 
26
- opts.on('--path BASE_PATH', "The base path used to load sound files with relative paths.") do |base_path|
26
+ opts.on("--path BASE_PATH", "The base path used to load sound files with relative paths.") do |base_path|
27
27
  options[:base_path] = base_path
28
28
  end
29
29
 
30
- opts.on('-v', '--version', "Display version number and exit") do
30
+ opts.on("-v", "--version", "Display version number and exit") do
31
31
  puts "Beats Drum Machine #{Beats::VERSION}"
32
32
  exit
33
33
  end
34
34
 
35
- opts.on( '-h', '--help', "Display this screen and exit" ) do
35
+ opts.on("-h", "--help", "Display this screen and exit") do
36
36
  puts opts
37
37
  exit
38
38
  end
@@ -1,21 +1,21 @@
1
- require 'yaml'
1
+ require "yaml"
2
2
 
3
3
  gem "wavefile", "=0.8.1"
4
- require 'wavefile'
5
- require 'wavefile/caching_writer'
4
+ require "wavefile"
5
+ require "wavefile/caching_writer"
6
6
 
7
- require 'beats/audio_engine'
8
- require 'beats/audio_utils'
9
- require 'beats/beats_runner'
10
- require 'beats/kit'
11
- require 'beats/kit_builder'
12
- require 'beats/pattern'
13
- require 'beats/song'
14
- require 'beats/song_parser'
15
- require 'beats/song_optimizer'
16
- require 'beats/track'
17
- require 'beats/transforms/song_swinger'
7
+ require "beats/audio_engine"
8
+ require "beats/audio_utils"
9
+ require "beats/beats_runner"
10
+ require "beats/kit"
11
+ require "beats/kit_builder"
12
+ require "beats/pattern"
13
+ require "beats/song"
14
+ require "beats/song_parser"
15
+ require "beats/song_optimizer"
16
+ require "beats/track"
17
+ require "beats/transforms/song_swinger"
18
18
 
19
19
  module Beats
20
- VERSION = "2.1.1"
20
+ VERSION = "2.1.2"
21
21
  end
@@ -2,7 +2,7 @@ module Beats
2
2
  class Kit
3
3
  class LabelNotFoundError < RuntimeError; end
4
4
 
5
- PLACEHOLDER_TRACK_NAME = 'empty_track_placeholder_name_234hkj32hjk4hjkhds23'
5
+ PLACEHOLDER_TRACK_NAME = "empty_track_placeholder_name_234hkj32hjk4hjkhds23"
6
6
 
7
7
  def initialize(items, num_channels, bits_per_sample)
8
8
  @items = items
@@ -27,13 +27,17 @@ module Beats
27
27
 
28
28
  filenames.each do |filename|
29
29
  unless filename.is_a?(String)
30
- raise SoundFileNotFoundError, "The Kit sound '#{label}' contains an invalid file: '#{filename}'"
30
+ raise SoundFileNotFoundError, "Kit sound '#{label}' contains an invalid filename: '#{filename}'. It must be a value that will be parsed from YAML as a String."
31
31
  end
32
32
  composite_replacement = "#{label}-#{File.basename(filename, ".*")}"
33
33
  @labels_to_filenames[composite_replacement] = absolute_file_name(filename)
34
34
  @composite_replacements[label] << composite_replacement
35
35
  end
36
36
  else
37
+ unless filenames.is_a?(String)
38
+ raise SoundFileNotFoundError, "Kit sound '#{label}' has an invalid filename: '#{filenames}'. It must be a value that will be parsed from YAML as a String."
39
+ end
40
+
37
41
  @labels_to_filenames[label] = absolute_file_name(filenames)
38
42
  @composite_replacements.delete(label)
39
43
  end
@@ -50,7 +50,7 @@ module Beats
50
50
  end
51
51
 
52
52
  def tempo=(new_tempo)
53
- unless (new_tempo.is_a?(Integer) || new_tempo.class == Float) && new_tempo > 0
53
+ unless (new_tempo.is_a?(Integer) || new_tempo.is_a?(Float)) && new_tempo > 0
54
54
  raise InvalidTempoError, "Invalid tempo: '#{new_tempo}'. Tempo must be a number greater than 0."
55
55
  end
56
56
 
@@ -86,11 +86,9 @@ Song:
86
86
  raw_song_definition = YAML.load(raw_yaml_string)
87
87
  rescue Psych::SyntaxError => detail
88
88
  raise ParseError, "Syntax error in YAML file: #{detail}"
89
- rescue ArgumentError => detail
90
- raise ParseError, "Syntax error in YAML file: #{detail}"
91
89
  end
92
90
 
93
- header_keys = raw_song_definition.keys.select {|key| key.downcase == "song" }
91
+ header_keys = raw_song_definition.keys.select {|key| key.is_a?(String) && key.downcase == "song" }
94
92
 
95
93
  if header_keys.empty?
96
94
  raise ParseError, NO_SONG_HEADER_ERROR_MSG
@@ -115,6 +113,10 @@ Song:
115
113
  def self.add_kit_sounds_from_kit(kit_builder, raw_kit)
116
114
  return if raw_kit.nil?
117
115
 
116
+ unless raw_kit.is_a?(Array)
117
+ raise ParseError, "Kit is not an array. Make sure each sound in the Kit is placed on new indented line prefixed with a '-'"
118
+ end
119
+
118
120
  # Add sounds defined in the Kit section of the song header
119
121
  # Converts [{a=>1}, {b=>2}, {c=>3}] from raw YAML to {a=>1, b=>2, c=>3}
120
122
  raw_kit.each do |kit_item|
@@ -137,14 +139,26 @@ Song:
137
139
 
138
140
  def self.add_patterns_to_song(song, kit_builder, raw_patterns)
139
141
  raw_patterns.each do |pattern_name, raw_tracks|
142
+ if !pattern_name.is_a?(String)
143
+ raise ParseError, "Pattern name '#{pattern_name}' is not valid. It must be a value that will be parsed from YAML as a String."
144
+ end
145
+
140
146
  if raw_tracks.nil?
141
147
  # TODO: Possibly allow if pattern not referenced in the Flow, or has 0 repeats?
142
148
  raise ParseError, "Pattern '#{pattern_name}' has no tracks. It needs at least one."
143
149
  end
144
150
 
151
+ if !raw_tracks.is_a?(Array)
152
+ raise ParseError, "Tracks in pattern '#{pattern_name}' are not an Array. Make sure each track is placed on new indented line prefixed with a '-'"
153
+ end
154
+
145
155
  tracks = []
146
156
 
147
- raw_tracks.each do |raw_track|
157
+ raw_tracks.each_with_index do |raw_track, index|
158
+ if !raw_track.is_a?(Hash)
159
+ raise ParseError, "Track ##{index + 1} in pattern '#{pattern_name}' is incomplete. Must be in form '- <kit/file name>: <rhythm>'"
160
+ end
161
+
148
162
  track_names = raw_track.keys.first
149
163
  rhythm = raw_track.values.first
150
164
 
@@ -158,7 +172,7 @@ Song:
158
172
 
159
173
  track_names.map! do |track_name|
160
174
  unless track_name.is_a?(String)
161
- raise ParseError, "'#{track_name}' in pattern '#{pattern_name}' is not a valid track sound"
175
+ raise ParseError, "'#{track_name}' in pattern '#{pattern_name}' is not a valid filename/kit sound. It must be a value that will be parsed from YAML as a String."
162
176
  end
163
177
  kit_builder.composite_replacements[track_name] || track_name
164
178
  end
@@ -177,34 +191,42 @@ Song:
177
191
  def self.set_song_flow(song, raw_flow)
178
192
  flow = []
179
193
 
194
+ if !raw_flow.is_a?(Array)
195
+ raise ParseError, "Song flow is not an array. Make sure each section of the flow is placed on new indented line prefixed with a '-'"
196
+ end
197
+
180
198
  raw_flow.each do |pattern_item|
181
- if pattern_item.class == String
182
- pattern_item = {pattern_item => "x1"}
199
+ if !pattern_item.is_a?(Hash)
200
+ if pattern_item.is_a?(String)
201
+ pattern_item = {pattern_item => "x1"}
202
+ else
203
+ raise ParseError, "'#{pattern_item}' is invalid flow section; must be in form '- <pattern name>: <repeat count>'"
204
+ end
183
205
  end
184
206
 
185
207
  pattern_name = pattern_item.keys.first
208
+ if !pattern_name.is_a?(String)
209
+ raise ParseError, "Pattern name '#{pattern_name}' in flow is not valid. It must be a value that will be parsed from YAML as a String."
210
+ end
186
211
  pattern_name_sym = pattern_name.downcase.to_sym
187
212
 
188
- # Convert the number of repeats from a String such as "x4" into an integer such as 4.
189
- multiples_str = pattern_item[pattern_name]
190
- multiples_str.slice!(0)
191
- multiples = multiples_str.to_i
213
+ repeat_count_str = pattern_item[pattern_name]
192
214
 
193
- unless multiples_str.match(/[^0-9]/).nil?
215
+ unless repeat_count_str.is_a?(String) && repeat_count_str.match(/^x[0-9]+$/) != nil
194
216
  raise ParseError,
195
- "'#{multiples_str}' is an invalid number of repeats for pattern '#{pattern_name}'. Number of repeats should be a whole number."
196
- else
197
- if multiples < 0
198
- raise ParseError, "'#{multiples_str}' is an invalid number of repeats for pattern '#{pattern_name}'. Must be 0 or greater."
199
- elsif multiples > 0 && !song.patterns.has_key?(pattern_name_sym)
200
- # This test is purposefully designed to only throw an error if the number of repeats is greater
201
- # than 0. This allows you to specify an undefined pattern in the flow with "x0" repeats.
202
- # This can be convenient for defining the flow before all patterns have been added to the song file.
203
- raise ParseError, "Song flow includes non-existent pattern: '#{pattern_name}'"
204
- end
217
+ "'#{repeat_count_str}' is an invalid number of repeats for pattern '#{pattern_name}'. Number of repeats must be a whole number >= 0, prefixed with 'x'."
218
+ end
219
+
220
+ repeat_count = repeat_count_str[1..-1].to_i
221
+
222
+ if repeat_count > 0 && !song.patterns.has_key?(pattern_name_sym)
223
+ # This test is purposefully designed to only throw an error if the number of repeats is greater
224
+ # than 0. This allows you to specify an undefined pattern in the flow with "x0" repeats.
225
+ # This can be convenient for defining the flow before all patterns have been added to the song file.
226
+ raise ParseError, "Song flow includes non-existent pattern: '#{pattern_name}'"
205
227
  end
206
228
 
207
- multiples.times { flow << pattern_name_sym }
229
+ repeat_count.times { flow << pattern_name_sym }
208
230
  end
209
231
 
210
232
  song.flow = flow
@@ -1,4 +1,4 @@
1
- require 'includes'
1
+ require "includes"
2
2
 
3
3
  # Make private methods public for testing
4
4
  class MockAudioEngine < AudioEngine
@@ -1,4 +1,4 @@
1
- require 'includes'
1
+ require "includes"
2
2
 
3
3
  class AudioUtilsTest < Minitest::Test
4
4
  def test_composite
@@ -1,4 +1,4 @@
1
- require 'includes'
1
+ require "includes"
2
2
 
3
3
  # Basic tests for CachingWriter; the integration tests test it more thoroughly.
4
4
  class CachingWriterTest < Minitest::Test
@@ -0,0 +1,8 @@
1
+ # Invalid song, since the number of repeats for pattern Verse has an invalid prefix
2
+ Song:
3
+ Tempo: 100
4
+ Flow:
5
+ - Verse: ax2
6
+
7
+ Verse:
8
+ - test/sounds/bass_mono_8.wav: X...X...X...XX..X...X...XX..X...
@@ -0,0 +1,8 @@
1
+ # Invalid song, since the number of repeats for pattern Verse has an invalid suffix
2
+ Song:
3
+ Tempo: 100
4
+ Flow:
5
+ - Verse: x2a
6
+
7
+ Verse:
8
+ - test/sounds/bass_mono_8.wav: X...X...X...XX..X...X...XX..X...
@@ -1,8 +1,8 @@
1
- # Invalid song, since the number of repeats for pattern Verse is not a number
1
+ # Invalid song, since the number of repeats for pattern Verse is missing
2
2
  Song:
3
3
  Tempo: 100
4
4
  Flow:
5
- - Verse: x2a
5
+ - Verse:
6
6
 
7
7
  Verse:
8
- - test/sounds/bass_mono_8.wav: X...X...X...XX..X...X...XX..X...
8
+ - test/sounds/bass_mono_8.wav: X...X...X...XX..X...X...XX..X...
@@ -0,0 +1,8 @@
1
+ # Invalid song, since the flow repeat count is less than 0
2
+ Song:
3
+ Tempo: 100
4
+ Flow:
5
+ - Verse: x-2
6
+
7
+ Verse:
8
+ - test/sounds/bass_mono_8.wav: X...X...X...XX..X...X...XX..X...
@@ -0,0 +1,8 @@
1
+ # Invalid song, since the flow repeat count is not a String like "x4"
2
+ Song:
3
+ Tempo: 100
4
+ Flow:
5
+ - Verse: [1, 2, 3]
6
+
7
+ Verse:
8
+ - test/sounds/bass_mono_8.wav: X...X...X...XX..X...X...XX..X...
@@ -0,0 +1,15 @@
1
+ # Invalid song, since the flow is not an array (i.e., each line is not prefixed with "-")
2
+ Song:
3
+ Tempo: 100
4
+ Flow:
5
+ Verse: x2
6
+ Chorus: x2
7
+ Verse: x2
8
+ Chorus: x2
9
+
10
+
11
+ Verse:
12
+ - test/sounds/bass_mono_8.wav: X...X...
13
+
14
+ Chorus:
15
+ - test/sounds/snare_mono_8.wav: X...X...
@@ -0,0 +1,15 @@
1
+ # Invalid song, a pattern used in the flow has a name which will not be parsed as a String
2
+ Song:
3
+ Tempo: 120
4
+ Flow:
5
+ - Verse: x2
6
+ - 4: x2 # Invalid pattern name!
7
+ Kit:
8
+ - bass: ../../sounds/bass_mono_8.wav
9
+ - snare: ../../sounds/snare_mono_8.wav
10
+ - hh_closed: ../../sounds/hh_closed_mono_8.wav
11
+ - agogo: ../../sounds/agogo_high_mono_8.wav
12
+
13
+ Verse:
14
+ - bass: X...X...X...X...
15
+ - snare: ..............X.