beats 1.3.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.markdown +22 -42
  4. data/bin/beats +6 -7
  5. data/lib/beats.rb +2 -1
  6. data/lib/beats/audioengine.rb +13 -13
  7. data/lib/beats/beatsrunner.rb +7 -8
  8. data/lib/beats/kit.rb +12 -156
  9. data/lib/beats/kit_builder.rb +74 -0
  10. data/lib/beats/pattern.rb +2 -22
  11. data/lib/beats/song.rb +5 -55
  12. data/lib/beats/songoptimizer.rb +3 -3
  13. data/lib/beats/songparser.rb +25 -46
  14. data/lib/beats/track.rb +20 -31
  15. data/lib/beats/transforms/song_swinger.rb +2 -4
  16. data/lib/wavefile/cachingwriter.rb +2 -2
  17. data/test/audioengine_test.rb +22 -24
  18. data/test/audioutils_test.rb +1 -1
  19. data/test/cachingwriter_test.rb +13 -12
  20. data/test/fixtures/invalid/leading_bar_line.txt +15 -0
  21. data/test/fixtures/{valid → invalid}/with_structure.txt +2 -2
  22. data/test/fixtures/valid/multiple_tracks_same_sound.txt +2 -1
  23. data/test/fixtures/valid/optimize_pattern_collision.txt +4 -5
  24. data/test/fixtures/valid/track_with_spaces.txt +13 -0
  25. data/test/includes.rb +1 -4
  26. data/test/integration_test.rb +5 -5
  27. data/test/kit_builder_test.rb +52 -0
  28. data/test/kit_test.rb +18 -141
  29. data/test/pattern_test.rb +66 -1
  30. data/test/song_swinger_test.rb +2 -2
  31. data/test/song_test.rb +9 -33
  32. data/test/songoptimizer_test.rb +18 -18
  33. data/test/songparser_test.rb +20 -10
  34. data/test/track_test.rb +23 -9
  35. metadata +26 -31
  36. data/ext/mkrf_conf.rb +0 -28
  37. data/test/fixtures/invalid/template.txt +0 -31
  38. data/test/fixtures/valid/foo.txt +0 -18
  39. data/test/sounds/bass.wav +0 -0
  40. data/test/sounds/bass2.wav +0 -0
  41. data/test/sounds/sine-mono-8bit.wav +0 -0
  42. data/test/sounds/tone.wav +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bc3e2d1d7e7730ec749de9aacb9446ef847cfcbd
4
- data.tar.gz: 42bff66e1caa2ff6ff503e57aac501ac36c0d445
3
+ metadata.gz: 386d1a9b9e83c848b2f9ae9c802f1ce9c717c99a
4
+ data.tar.gz: 287a1390bed816c4bcf65bb5749af04297d8bfd9
5
5
  SHA512:
6
- metadata.gz: c5782528094a11cd93d7a49fa944787fd8150066ebc8f72a75253c4fd1326ae106c58fdb337591f815f4bf4cc85b58fdae497660e96c86789d365b833a72b15f
7
- data.tar.gz: 666d0a00cf0da6f21e7c1476ded37fd97b41db884add895aff0e627a8e0e9bebbd6c8ee6f5f76d4a2f5916e9d9e83c203846082bc9ce0fad78a681000e0c87be
6
+ metadata.gz: dd8197163c74429d9e1ba1c5ded23af90f423ac48702e085732c5476e788064f497854d585da512f0babd1fb2ad85119fa21caea591e821105e4133cfa8ab443
7
+ data.tar.gz: 24f11590f134ee21e801d463c6be28334f009ab2da5294b27aa23af2db7ab27550817a61a6db1c3b699ae821e351f1c892da2f2644252ed2bd8faebe4f908236
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  == BEATS
2
2
 
3
- # Copyright (c) 2010-14 Joel Strait
3
+ # Copyright (c) 2010-17 Joel Strait
4
4
  #
5
5
  # Permission is hereby granted, free of charge, to any person
6
6
  # obtaining a copy of this software and associated documentation
@@ -13,13 +13,13 @@ Beats is a command-line drum machine written in pure Ruby. Feed it a song notate
13
13
  - snare: roland_tr_909_2.wav
14
14
  - hihat: house_2_5.wav
15
15
  - cowbell: big_beat_5.wav
16
- - deep: house_2_2.wav
17
-
16
+ - deep: house_2_2.wav
17
+
18
18
  Verse:
19
19
  - bass: X..X...X..X.....
20
20
  - snare: ....X.......X...
21
21
  - hihat: ..X...X...X...X.
22
-
22
+
23
23
  Chorus:
24
24
  - bass: X..X...X..X.....
25
25
  - snare: ....X.......X...
@@ -29,48 +29,13 @@ Beats is a command-line drum machine written in pure Ruby. Feed it a song notate
29
29
 
30
30
  And [here's what it sounds like](http://beatsdrummachine.com/media/beat.mp3) after getting the Beats treatment. What a glorious groove!
31
31
 
32
-
33
- Current Status
34
- --------------
35
-
36
- The latest stable version of Beats is 1.3.0, released on March 4, 2013.
37
-
38
- This release is for all you swingers out there. A new `Swing` declaration in the song header will cause the song to be played with either a swung 8th note or swung 16th note rhythm. For example, take this song:
39
-
40
- Song:
41
- Tempo: 120
42
- Flow:
43
- - Verse: x4
44
-
45
- Verse:
46
- - bass.wav: X...X...X...X...
47
- - snare.wav: ....X.......X...
48
- - hihat.wav: X.X.X.X.X.X.X.X.
49
-
50
- It will [sound like this](http://beatsdrummachine.com/media/straight.wav).
51
-
52
- You can add an 8th note swing like this (notice the 3rd line, everything else is the same):
53
-
54
- Song:
55
- Tempo: 120
56
- Swing: 8 # Or, 16
57
- Flow:
58
- - Verse: x4
59
-
60
- Verse:
61
- - bass.wav: X...X...X...X...
62
- - snare.wav: ....X.......X...
63
- - hihat.wav: X.X.X.X.X.X.X.X.
64
-
65
- And it will now [sound like this](http://beatsdrummachine.com/media/swing.wav).
66
-
67
- This release also includes a small bug fix. When you run the `beats` command with no arguments, it now displays the help screen, rather than an error message.
32
+ For more, check out [beatsdrummachine.com](http://beatsdrummachine.com)
68
33
 
69
34
 
70
35
  Installation
71
36
  ------------
72
37
 
73
- To install the latest stable version (1.3.0) from [rubygems.org](http://rubygems.org/gems/beats), run the following from the command line:
38
+ To install the latest stable version (2.0.0) from [rubygems.org](http://rubygems.org/gems/beats), run the following from the command line:
74
39
 
75
40
  gem install beats
76
41
 
@@ -86,7 +51,22 @@ Usage
86
51
 
87
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).
88
53
 
89
- The Beats wiki also has a [Getting Started](https://github.com/jstrait/beats/wiki/Getting-Started) tutorial which shows how to create an example beat from scratch.
54
+ Check out [this tutorial at beatsdrummachine.com](http://beatsdrummachine.com/tutorial/) to see an example of how to create a beat from sratch.
55
+
56
+
57
+ What's New
58
+ ----------
59
+
60
+ The latest stable version of Beats is 2.0.0, released on September 4, 2017. It is primarily a modernization release, and contains some relatively small backwards incompatible changes.
61
+
62
+ * Track rhythms can now have spaces in them. For example, `X... .... X... ....` is now a valid rhythm. Spaces are ignored, and don't affect the rhythm. For example, `X... X...` is treated as the same rhythm as `X...X...`
63
+ * Wave files using `WAVEFORMATEXTENSIBLE` format can now be used, due to upgrading the WaveFile gem dependency to v0.8.1 behind the scenes.
64
+ * Installing the gem is now simpler, since it no longer requires installing the legacy `syck` YAML parser via an extension.
65
+ * A `Fixnum is deprecated` message is no longer shown when using Ruby 2.4
66
+ * **Backwards incompatible changes**:
67
+ * Song files containing a `Structure` section are no longer supported. A `Flow` section should be used instead. Support for the `Structure` section has been deprecated since v1.2.1 (released in 2011).
68
+ * Track rhythms can no longer start with a `|` character. For example, `|X...X...` is no longer a valid rhythm. However, bar lines are still allowed to appear elsewhere in the rhythm. For example, `X...X...|X...X...|` _is_ a valid rhythm. The reason for this change is that a rhythm starting with `|` is parsed as a YAML scalar block now that Beats is using the Psych YAML library behind the scenes. The fact that the old Syck YAML library didn't treat rhythms starting with a `|` as a YAML scalar block appears to have been a bug in Syck?
69
+ * The minimum supported Ruby version is now 1.9.3, instead of 1.8.7
90
70
 
91
71
 
92
72
  Local Development
@@ -114,5 +94,5 @@ Contact me (Joel Strait) by sending a GitHub message or opening a GitHub issue.
114
94
 
115
95
  License
116
96
  -------
117
- Beats is released under the MIT license.
97
+ Beats Drum Machine is released under the MIT license.
118
98
 
data/bin/beats CHANGED
@@ -3,9 +3,9 @@
3
3
  start_time = Time.now
4
4
 
5
5
  $:.unshift File.dirname(__FILE__) + "/../lib"
6
+ gem "wavefile", "=0.8.1"
6
7
  require "optparse"
7
8
  require "yaml"
8
- require "syck"
9
9
  require "wavefile"
10
10
  require "beats"
11
11
  require "wavefile/cachingwriter"
@@ -13,9 +13,8 @@ require "wavefile/cachingwriter"
13
13
  include Beats
14
14
 
15
15
  USAGE_INSTRUCTIONS = ""
16
- YAML::ENGINE.yamler = 'syck' if defined?(YAML::ENGINE)
17
16
 
18
- def parse_options()
17
+ def parse_options
19
18
  options = {:split => false}
20
19
 
21
20
  optparse = OptionParser.new do |opts|
@@ -45,9 +44,9 @@ def parse_options()
45
44
  end
46
45
 
47
46
  USAGE_INSTRUCTIONS << optparse.to_s
48
- optparse.parse!()
47
+ optparse.parse!
49
48
 
50
- return options
49
+ options
51
50
  end
52
51
 
53
52
  def print_error(error, input_file_name)
@@ -57,7 +56,7 @@ def print_error(error, input_file_name)
57
56
  puts USAGE_INSTRUCTIONS
58
57
  when Errno::ENOENT
59
58
  puts "Song file '#{input_file_name}' not found.\n"
60
- when SongParseError
59
+ when SongParser::ParseError
61
60
  puts "Song file '#{input_file_name}' has an error:\n"
62
61
  puts " #{error}\n"
63
62
  when StandardError
@@ -70,7 +69,7 @@ def print_error(error, input_file_name)
70
69
  end
71
70
 
72
71
  begin
73
- options = parse_options()
72
+ options = parse_options
74
73
 
75
74
  if ARGV.empty?
76
75
  puts USAGE_INSTRUCTIONS
@@ -2,6 +2,7 @@ require 'beats/audioengine'
2
2
  require 'beats/audioutils'
3
3
  require 'beats/beatsrunner'
4
4
  require 'beats/kit'
5
+ require 'beats/kit_builder'
5
6
  require 'beats/pattern'
6
7
  require 'beats/song'
7
8
  require 'beats/songparser'
@@ -10,5 +11,5 @@ require 'beats/track'
10
11
  require 'beats/transforms/song_swinger'
11
12
 
12
13
  module Beats
13
- VERSION = "1.3.0"
14
+ VERSION = "2.0.0"
14
15
  end
@@ -27,7 +27,7 @@ module Beats
27
27
  num_tracks_in_song = @song.total_tracks
28
28
 
29
29
  # Open output wave file and prepare it for writing sample data.
30
- format = WaveFile::Format.new(@kit.num_channels, @kit.bits_per_sample, SAMPLE_RATE)
30
+ format = WaveFile::Format.new(@kit.num_channels, "pcm_#{@kit.bits_per_sample}".to_sym, SAMPLE_RATE)
31
31
  writer = WaveFile::CachingWriter.new(output_file_name, format)
32
32
 
33
33
  # Generate each pattern's sample data, or pull it from cache, and append it to the wave file.
@@ -50,7 +50,7 @@ module Beats
50
50
  final_overflow_composite = AudioUtils.scale(final_overflow_composite, format.channels, num_tracks_in_song)
51
51
  writer.write(WaveFile::Buffer.new(final_overflow_composite, format))
52
52
 
53
- writer.close()
53
+ writer.close
54
54
 
55
55
  writer.total_duration
56
56
  end
@@ -61,27 +61,27 @@ module Beats
61
61
 
62
62
  # Generates the sample data for a single track, using the specified sound's sample data.
63
63
  def generate_track_sample_data(track, sound)
64
- beats = track.beats
65
- if beats == [0]
64
+ trigger_step_lengths = track.trigger_step_lengths
65
+ if trigger_step_lengths == [0]
66
66
  return {:primary => [], :overflow => []} # Is this really what should happen? Why throw away overflow?
67
67
  end
68
68
 
69
69
  fill_value = (@kit.num_channels == 1) ? 0 : [0, 0]
70
70
  primary_sample_data = [].fill(fill_value, 0, AudioUtils.step_start_sample(track.step_count, @step_sample_length))
71
71
 
72
- step_index = beats[0]
73
- beat_sample_length = 0
74
- beats[1...(beats.length)].each do |beat_step_length|
72
+ step_index = trigger_step_lengths[0]
73
+ trigger_sample_length = 0
74
+ trigger_step_lengths[1...(trigger_step_lengths.length)].each do |trigger_step_length|
75
75
  start_sample = AudioUtils.step_start_sample(step_index, @step_sample_length)
76
76
  end_sample = [(start_sample + sound.length), primary_sample_data.length].min
77
- beat_sample_length = end_sample - start_sample
77
+ trigger_sample_length = end_sample - start_sample
78
78
 
79
- primary_sample_data[start_sample...end_sample] = sound[0...beat_sample_length]
79
+ primary_sample_data[start_sample...end_sample] = sound[0...trigger_sample_length]
80
80
 
81
- step_index += beat_step_length
81
+ step_index += trigger_step_length
82
82
  end
83
83
 
84
- overflow_sample_data = (sound == [] || beats.length == 1) ? [] : sound[beat_sample_length...(sound.length)]
84
+ overflow_sample_data = (sound == [] || trigger_step_lengths.length == 1) ? [] : sound[trigger_sample_length...(sound.length)]
85
85
 
86
86
  {:primary => primary_sample_data, :overflow => overflow_sample_data}
87
87
  end
@@ -143,8 +143,8 @@ module Beats
143
143
  if pattern_track_names.member?(incoming_track_name)
144
144
  track = pattern.tracks[incoming_track_name]
145
145
 
146
- if track.beats.length > 1
147
- intro_length = (pattern.tracks[incoming_track_name].beats[0] * step_sample_length).floor
146
+ if track.trigger_step_lengths.length > 1
147
+ intro_length = (pattern.tracks[incoming_track_name].trigger_step_lengths[0] * step_sample_length).floor
148
148
  end_sample = [end_sample, intro_length].min
149
149
  end
150
150
  end
@@ -18,15 +18,15 @@ module Beats
18
18
 
19
19
  def run
20
20
  base_path = @options[:base_path] || File.dirname(@input_file_name)
21
- song, kit = SongParser.new().parse(base_path, File.read(@input_file_name))
21
+ song, kit = SongParser.new.parse(base_path, File.read(@input_file_name))
22
22
 
23
23
  song = normalize_for_pattern_option(song)
24
24
  songs_to_generate = normalize_for_split_option(song)
25
25
 
26
- song_optimizer = SongOptimizer.new()
27
- durations = songs_to_generate.collect do |output_file_name, song|
28
- song = song_optimizer.optimize(song, OPTIMIZED_PATTERN_LENGTH)
29
- AudioEngine.new(song, kit).write_to_file(output_file_name)
26
+ song_optimizer = SongOptimizer.new
27
+ durations = songs_to_generate.collect do |output_file_name, song_to_generate|
28
+ optimized_song = song_optimizer.optimize(song_to_generate, OPTIMIZED_PATTERN_LENGTH)
29
+ AudioEngine.new(optimized_song, kit).write_to_file(output_file_name)
30
30
  end
31
31
 
32
32
  {:duration => durations.last}
@@ -45,7 +45,7 @@ module Beats
45
45
  end
46
46
 
47
47
  song.flow = [pattern_name]
48
- song.remove_unused_patterns()
48
+ song.remove_unused_patterns
49
49
  end
50
50
 
51
51
  song
@@ -56,9 +56,8 @@ module Beats
56
56
  songs_to_generate = {}
57
57
 
58
58
  if @options[:split]
59
- split_songs = song.split()
59
+ split_songs = song.split
60
60
  split_songs.each do |track_name, split_song|
61
- # TODO: Move building the output file name into its own method?
62
61
  extension = File.extname(@output_file_name)
63
62
  file_name = File.dirname(@output_file_name) + "/" +
64
63
  File.basename(@output_file_name, extension) + "-" + File.basename(track_name, extension) +
@@ -1,47 +1,17 @@
1
1
  module Beats
2
- # Raised when trying to load a sound file which can't be found at the path specified
3
- class SoundFileNotFoundError < RuntimeError; end
4
-
5
- # Raised when trying to load a sound file which either isn't actually a sound file, or
6
- # is in an unsupported format.
7
- class InvalidSoundFormatError < RuntimeError; end
8
-
9
-
10
- # This class provides a repository for the sounds used in a song. Most usefully, it
11
- # also handles converting the sounds to a common format. For example, if a song requires
12
- # a sound that is mono/8-bit, another that is stereo/8-bit, and another that is
13
- # stereo/16-bit, they have to be converted to a common format before they can be used
14
- # together. Kit handles this conversion; all sounds retrieved using
15
- # get_sample_data() will be in a common format.
16
- #
17
- # Sounds can only be added at initialization. During initialization, the sample data
18
- # for each sound is loaded into memory, and converted to the common format if necessary.
19
- # This format is:
20
- #
21
- # Bits per sample: 16
22
- # Sample rate: 44100
23
- # Channels: Stereo, unless all of the kit sounds are mono.
24
- #
25
- # For example if the kit has these sounds:
26
- #
27
- # my_sound_1.wav: mono, 16-bit
28
- # my_sound_2.wav: stereo, 8-bit
29
- # my_sound_3.wav: mono, 8-bit
30
- #
31
- # they will all be converted to stereo/16-bit during initialization.
32
2
  class Kit
33
- def initialize(base_path, kit_items)
34
- @base_path = base_path
35
- @label_mappings = {}
36
- @sound_bank = {}
37
- @num_channels = 1
38
- @bits_per_sample = 16 # Only use 16-bit files as output. Supporting 8-bit output
39
- # means extra complication for no real gain (I'm skeptical
40
- # anyone would explicitly want 8-bit output instead of 16-bit).
3
+ class LabelNotFoundError < RuntimeError; end
41
4
 
42
- load_sounds(base_path, kit_items)
5
+ PLACEHOLDER_TRACK_NAME = 'empty_track_placeholder_name_234hkj32hjk4hjkhds23'
6
+
7
+ def initialize(items, num_channels, bits_per_sample)
8
+ @items = items
9
+ @num_channels = num_channels
10
+ @bits_per_sample = bits_per_sample
43
11
  end
44
12
 
13
+ attr_reader :num_channels, :bits_per_sample
14
+
45
15
  # Returns the sample data for a sound contained in the Kit. If the all sounds in the
46
16
  # kit are mono, then this will be a flat Array of Fixnums between -32768 and 32767.
47
17
  # Otherwise, this will be an Array of Fixnums pairs between -32768 and 32767.
@@ -63,125 +33,11 @@ module Beats
63
33
  #
64
34
  # Returns the sample data Array for the sound bound to label.
65
35
  def get_sample_data(label)
66
- if label == "placeholder"
67
- return []
68
- end
69
-
70
- sample_data = @sound_bank[label]
71
-
72
- if sample_data.nil?
73
- # TODO: Should we really throw an exception here rather than just returning nil?
74
- raise StandardError, "Kit doesn't contain sound '#{label}'."
75
- else
76
- return sample_data
77
- end
78
- end
79
-
80
- def scale!(scale_factor)
81
- @sound_bank.each do |label, sample_array|
82
- @sound_bank[label] = AudioUtils.scale(sample_array, @num_channels, scale_factor)
83
- end
84
- end
85
-
86
- # Returns a YAML representation of the Kit. Produces nicer looking output than the default version
87
- # of to_yaml().
88
- #
89
- # indent_space_count - The number of spaces to indent each line in the output (default: 0).
90
- #
91
- # Returns a String representation of the Kit in YAML format.
92
- def to_yaml(indent_space_count = 0)
93
- yaml = ""
94
- longest_label_mapping_length =
95
- @label_mappings.keys.inject(0) do |max_length, name|
96
- (name.to_s.length > max_length) ? name.to_s.length : max_length
97
- end
98
-
99
- if @label_mappings.length > 0
100
- yaml += " " * indent_space_count + "Kit:\n"
101
- ljust_amount = longest_label_mapping_length + 1 # The +1 is for the trailing ":"
102
- @label_mappings.sort.each do |label, path|
103
- yaml += " " * indent_space_count + " - #{(label + ":").ljust(ljust_amount)} #{path}\n"
104
- end
105
- end
106
-
107
- yaml
108
- end
109
-
110
- attr_reader :base_path, :label_mappings, :bits_per_sample, :num_channels
111
-
112
- private
113
-
114
- def load_sounds(base_path, kit_items)
115
- # Set label mappings
116
- kit_items.each do |label, sound_file_names|
117
- if sound_file_names.class == Array
118
- raise StandardError, "Composite sounds aren't allowed (yet...)"
119
- end
120
-
121
- unless label == sound_file_names
122
- @label_mappings[label] = sound_file_names
123
- end
36
+ unless @items.has_key?(label)
37
+ raise LabelNotFoundError, "Kit doesn't contain sound '#{label}'."
124
38
  end
125
39
 
126
- kit_items = make_file_names_absolute(kit_items)
127
- sound_buffers = load_raw_sounds(kit_items)
128
-
129
- canonical_format = WaveFile::Format.new(@num_channels, @bits_per_sample, 44100)
130
-
131
- # Convert each sound to a common format
132
- sound_buffers.each {|file_name, buffer| sound_buffers[file_name] = buffer.convert(canonical_format) }
133
-
134
- # If necessary, mix component sounds into a composite
135
- kit_items.each do |label, sound_file_names|
136
- @sound_bank[label] = mixdown(sound_file_names, sound_buffers)
137
- end
138
- end
139
-
140
- # Converts relative paths into absolute paths. Note that this will also handle
141
- # expanding ~ on platforms that support that.
142
- def make_file_names_absolute(kit_items)
143
- kit_items.each do |label, sound_file_names|
144
- unless sound_file_names.class == Array
145
- sound_file_names = [sound_file_names]
146
- end
147
-
148
- sound_file_names.map! {|sound_file_name| File.expand_path(sound_file_name, base_path) }
149
- kit_items[label] = sound_file_names
150
- end
151
-
152
- kit_items
153
- end
154
-
155
- # Load all sound files, bailing if any are invalid
156
- def load_raw_sounds(kit_items)
157
- raw_sounds = {}
158
- kit_items.values.flatten.each do |sound_file_name|
159
- begin
160
- info = WaveFile::Reader.info(sound_file_name)
161
- WaveFile::Reader.new(sound_file_name).each_buffer(info.sample_frame_count) do |buffer|
162
- raw_sounds[sound_file_name] = buffer
163
- @num_channels = [@num_channels, buffer.channels].max
164
- end
165
- rescue Errno::ENOENT
166
- raise SoundFileNotFoundError, "Sound file #{sound_file_name} not found."
167
- rescue StandardError
168
- raise InvalidSoundFormatError, "Sound file #{sound_file_name} is either not a sound file, " +
169
- "or is in an unsupported format. BEATS can handle 8, 16, 24, or 32-bit PCM *.wav files."
170
- end
171
- end
172
-
173
- raw_sounds
174
- end
175
-
176
- def mixdown(sound_file_names, raw_sounds)
177
- sample_arrays = []
178
- sound_file_names.each do |sound_file_name|
179
- sample_arrays << raw_sounds[sound_file_name].samples
180
- end
181
-
182
- composited_sample_data = AudioUtils.composite(sample_arrays, @num_channels)
183
-
184
- AudioUtils.scale(composited_sample_data, @num_channels, sound_file_names.length)
40
+ @items[label]
185
41
  end
186
42
  end
187
43
  end