Module: Beats::AudioUtils
- Defined in:
- lib/beats/audioutils.rb
Overview
This class contains some utility methods for working with sample data.
Class Method Summary collapse
-
.composite(sample_arrays, num_channels) ⇒ Object
Combines multiple sample arrays into one, by adding them together.
-
.scale(sample_array, num_channels, scale) ⇒ Object
Scales the amplitude of the incoming sample array by scale amount.
-
.step_sample_length(samples_per_second, tempo) ⇒ Object
Returns the number of samples that each step (i.e. a ‘X’ or a ‘.’) lasts at a given sample rate and tempo.
-
.step_start_sample(step_index, step_sample_length) ⇒ Object
Returns the sample index that a given step (offset from 0) starts on.
Class Method Details
.composite(sample_arrays, num_channels) ⇒ Object
Combines multiple sample arrays into one, by adding them together. When the sample arrays are different lengths, the output array will be the length of the longest input array. WARNING: Incoming arrays can be modified.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/beats/audioutils.rb', line 9 def self.composite(sample_arrays, num_channels) if sample_arrays == [] return [] end # Sort from longest to shortest sample_arrays = sample_arrays.sort {|x, y| y.length <=> x.length} composited_output = sample_arrays.slice!(0) sample_arrays.each do |sample_array| unless sample_array == [] if num_channels == 1 sample_array.length.times {|i| composited_output[i] += sample_array[i] } elsif num_channels == 2 sample_array.length.times do |i| composited_output[i] = [composited_output[i][0] + sample_array[i][0], composited_output[i][1] + sample_array[i][1]] end end end end composited_output end |
.scale(sample_array, num_channels, scale) ⇒ Object
Scales the amplitude of the incoming sample array by scale amount. Can be used in conjunction with composite() to make sure composited sample arrays don’t have an amplitude greater than 1.0.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/beats/audioutils.rb', line 37 def self.scale(sample_array, num_channels, scale) if sample_array == [] return sample_array end if scale > 1 if num_channels == 1 sample_array = sample_array.map {|sample| sample / scale } elsif num_channels == 2 sample_array = sample_array.map {|sample| [sample[0] / scale, sample[1] / scale]} else raise StandardError, "Invalid sample data array in AudioUtils.normalize()" end end sample_array end |
.step_sample_length(samples_per_second, tempo) ⇒ Object
Returns the number of samples that each step (i.e. a ‘X’ or a ‘.’) lasts at a given sample rate and tempo. The sample length can be a non-integer value. Although there’s no such thing as a partial sample, this is required to prevent small timing errors from creeping in. If they accumulate, they can cause rhythms to drift out of time.
60 61 62 63 64 65 66 |
# File 'lib/beats/audioutils.rb', line 60 def self.step_sample_length(samples_per_second, tempo) samples_per_minute = samples_per_second * 60.0 samples_per_quarter_note = samples_per_minute / tempo # Each step is equivalent to a 16th note samples_per_quarter_note / 4.0 end |
.step_start_sample(step_index, step_sample_length) ⇒ Object
Returns the sample index that a given step (offset from 0) starts on.
70 71 72 |
# File 'lib/beats/audioutils.rb', line 70 def self.step_start_sample(step_index, step_sample_length) (step_index * step_sample_length).floor end |