Class: Beats::Kit

Inherits:
Object
  • Object
show all
Defined in:
lib/beats/kit.rb

Overview

This class provides a repository for the sounds used in a song. Most usefully, it also handles converting the sounds to a common format. For example, if a song requires a sound that is mono/8-bit, another that is stereo/8-bit, and another that is stereo/16-bit, they have to be converted to a common format before they can be used together. Kit handles this conversion; all sounds retrieved using get_sample_data() will be in a common format.

Sounds can only be added at initialization. During initialization, the sample data for each sound is loaded into memory, and converted to the common format if necessary. This format is:

Bits per sample: 16
Sample rate:     44100
Channels:        Stereo, unless all of the kit sounds are mono.

For example if the kit has these sounds:

my_sound_1.wav:  mono, 16-bit
my_sound_2.wav:  stereo, 8-bit
my_sound_3.wav:  mono, 8-bit

they will all be converted to stereo/16-bit during initialization.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base_path, kit_items) ⇒ Kit

Returns a new instance of Kit.



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/beats/kit.rb', line 33

def initialize(base_path, kit_items)
  @base_path = base_path
  @label_mappings = {}
  @sound_bank = {}
  @num_channels = 1
  @bits_per_sample = 16  # Only use 16-bit files as output. Supporting 8-bit output
                         # means extra complication for no real gain (I'm skeptical
                         # anyone would explicitly want 8-bit output instead of 16-bit).

  load_sounds(base_path, kit_items)
end

Instance Attribute Details

#base_pathObject (readonly)

Returns the value of attribute base_path.



110
111
112
# File 'lib/beats/kit.rb', line 110

def base_path
  @base_path
end

#bits_per_sampleObject (readonly)

Returns the value of attribute bits_per_sample.



110
111
112
# File 'lib/beats/kit.rb', line 110

def bits_per_sample
  @bits_per_sample
end

#label_mappingsObject (readonly)

Returns the value of attribute label_mappings.



110
111
112
# File 'lib/beats/kit.rb', line 110

def label_mappings
  @label_mappings
end

#num_channelsObject (readonly)

Returns the value of attribute num_channels.



110
111
112
# File 'lib/beats/kit.rb', line 110

def num_channels
  @num_channels
end

Instance Method Details

#get_sample_data(label) ⇒ Object

Returns the sample data for a sound contained in the Kit. If the all sounds in the kit are mono, then this will be a flat Array of Fixnums between -32768 and 32767. Otherwise, this will be an Array of Fixnums pairs between -32768 and 32767.

label - The name of the sound to get sample data for. If the sound was defined in

the Kit section of a song file, this will generally be a descriptive label
such as "bass" or "snare". If defined in a track but not the kit, it will
generally be a file name such as "my_sounds/hihat/hi_hat.wav".

Examples

# If @num_channels is 1, a flat Array of Fixnums:
get_sample_data("bass")
# => [154, 7023, 8132, 2622, -132, 34, ..., -6702]

# If @num_channels is 2, a Array of Fixnums pairs:
get_sample_data("snare")
# => [[57, 1265], [-452, 10543], [-2531, 12643], [-6372, 11653], ..., [5482, 25673]]

Returns the sample data Array for the sound bound to label.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/beats/kit.rb', line 65

def get_sample_data(label)
  if label == "placeholder"
    return []
  end

  sample_data = @sound_bank[label]

  if sample_data.nil?
    # TODO: Should we really throw an exception here rather than just returning nil?
    raise StandardError, "Kit doesn't contain sound '#{label}'."
  else
    return sample_data
  end
end

#scale!(scale_factor) ⇒ Object



80
81
82
83
84
# File 'lib/beats/kit.rb', line 80

def scale!(scale_factor)
  @sound_bank.each do |label, sample_array|
    @sound_bank[label] = AudioUtils.scale(sample_array, @num_channels, scale_factor)
  end
end

#to_yaml(indent_space_count = 0) ⇒ Object

Returns a YAML representation of the Kit. Produces nicer looking output than the default version of to_yaml().

indent_space_count - The number of spaces to indent each line in the output (default: 0).

Returns a String representation of the Kit in YAML format.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/beats/kit.rb', line 92

def to_yaml(indent_space_count = 0)
  yaml = ""
  longest_label_mapping_length =
    @label_mappings.keys.inject(0) do |max_length, name|
      (name.to_s.length > max_length) ? name.to_s.length : max_length
    end

  if @label_mappings.length > 0
    yaml += " " * indent_space_count + "Kit:\n"
    ljust_amount = longest_label_mapping_length + 1  # The +1 is for the trailing ":"
    @label_mappings.sort.each do |label, path|
      yaml += " " * indent_space_count + "  - #{(label + ":").ljust(ljust_amount)}  #{path}\n"
    end
  end

  yaml
end