deftones 0.1.0 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -6
- data/README.md +5 -0
- data/Rakefile +50 -1
- data/lib/deftones/analysis/meter.rb +22 -2
- data/lib/deftones/component/channel.rb +1 -1
- data/lib/deftones/component/compressor.rb +127 -22
- data/lib/deftones/component/filter.rb +29 -19
- data/lib/deftones/component/merge.rb +14 -0
- data/lib/deftones/component/multiband_compressor.rb +1 -1
- data/lib/deftones/component/one_pole_filter.rb +10 -3
- data/lib/deftones/component/panner.rb +25 -2
- data/lib/deftones/component/panner3d.rb +0 -10
- data/lib/deftones/component/split.rb +14 -0
- data/lib/deftones/context.rb +90 -9
- data/lib/deftones/core/audio_block.rb +64 -5
- data/lib/deftones/core/audio_node.rb +98 -8
- data/lib/deftones/core/gain.rb +0 -8
- data/lib/deftones/core/instrument.rb +52 -10
- data/lib/deftones/core/param.rb +51 -1
- data/lib/deftones/core/signal.rb +79 -28
- data/lib/deftones/core/source.rb +71 -11
- data/lib/deftones/destination.rb +41 -17
- data/lib/deftones/draw.rb +6 -10
- data/lib/deftones/dsp/biquad.rb +9 -4
- data/lib/deftones/dsp/delay_line.rb +2 -2
- data/lib/deftones/dsp/helpers.rb +7 -0
- data/lib/deftones/effect/bit_crusher.rb +10 -2
- data/lib/deftones/effect/chebyshev.rb +7 -3
- data/lib/deftones/effect/distortion.rb +5 -3
- data/lib/deftones/effect/feedback_delay.rb +2 -1
- data/lib/deftones/effect/oversampling.rb +43 -0
- data/lib/deftones/effect/phaser.rb +2 -1
- data/lib/deftones/effect/pitch_shift.rb +1 -2
- data/lib/deftones/effect/reverb.rb +73 -5
- data/lib/deftones/event/callback_behavior.rb +7 -3
- data/lib/deftones/event/loop.rb +7 -2
- data/lib/deftones/event/part.rb +18 -3
- data/lib/deftones/event/pattern.rb +51 -6
- data/lib/deftones/event/sequence.rb +19 -5
- data/lib/deftones/event/tone_event.rb +7 -2
- data/lib/deftones/event/transport.rb +243 -21
- data/lib/deftones/instrument/poly_synth.rb +81 -15
- data/lib/deftones/instrument/sampler.rb +53 -10
- data/lib/deftones/io/buffer.rb +376 -55
- data/lib/deftones/io/buffers.rb +28 -4
- data/lib/deftones/io/recorder.rb +2 -1
- data/lib/deftones/music/frequency.rb +13 -8
- data/lib/deftones/music/midi.rb +132 -9
- data/lib/deftones/music/note.rb +13 -3
- data/lib/deftones/music/time.rb +42 -4
- data/lib/deftones/offline_context.rb +194 -17
- data/lib/deftones/portaudio_support.rb +68 -9
- data/lib/deftones/source/fat_oscillator.rb +28 -9
- data/lib/deftones/source/grain_player.rb +49 -2
- data/lib/deftones/source/noise.rb +42 -10
- data/lib/deftones/source/omni_oscillator.rb +1 -2
- data/lib/deftones/source/oscillator.rb +83 -19
- data/lib/deftones/source/player.rb +24 -6
- data/lib/deftones/source/players.rb +39 -6
- data/lib/deftones/source/tone_buffer_source.rb +12 -6
- data/lib/deftones/source/tone_oscillator_node.rb +4 -3
- data/lib/deftones/source/user_media.rb +83 -10
- data/lib/deftones/version.rb +1 -1
- data/lib/deftones.rb +108 -31
- metadata +3 -44
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Deftones
|
|
4
|
+
module Effects
|
|
5
|
+
module Oversampling
|
|
6
|
+
OVERSAMPLE_FACTORS = [1, 2, 4].freeze
|
|
7
|
+
|
|
8
|
+
attr_reader :oversample
|
|
9
|
+
|
|
10
|
+
def oversample=(value)
|
|
11
|
+
normalized = value.to_i
|
|
12
|
+
raise ArgumentError, "Unsupported oversample factor: #{value}" unless OVERSAMPLE_FACTORS.include?(normalized)
|
|
13
|
+
|
|
14
|
+
@oversample = normalized
|
|
15
|
+
@oversample_previous = []
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def process_oversampled(input_buffer, channel_index)
|
|
21
|
+
ensure_oversample_state(channel_index)
|
|
22
|
+
return input_buffer.map { |sample| yield sample } if @oversample == 1
|
|
23
|
+
|
|
24
|
+
input_buffer.map do |sample|
|
|
25
|
+
previous = @oversample_previous[channel_index]
|
|
26
|
+
current = sample.to_f
|
|
27
|
+
sum = 0.0
|
|
28
|
+
1.upto(@oversample) do |step|
|
|
29
|
+
position = step.to_f / @oversample
|
|
30
|
+
sum += yield Deftones::DSP::Helpers.lerp(previous, current, position)
|
|
31
|
+
end
|
|
32
|
+
@oversample_previous[channel_index] = current
|
|
33
|
+
sum / @oversample
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def ensure_oversample_state(channel_index)
|
|
38
|
+
required = [channel_index.to_i, 0].max
|
|
39
|
+
@oversample_previous.fill(0.0, @oversample_previous.length..required)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -5,7 +5,8 @@ module Deftones
|
|
|
5
5
|
class Phaser < Core::Effect
|
|
6
6
|
include ModulationControl
|
|
7
7
|
|
|
8
|
-
attr_accessor :frequency, :octaves, :q, :base_frequency, :
|
|
8
|
+
attr_accessor :frequency, :octaves, :q, :base_frequency, :type
|
|
9
|
+
attr_reader :stages
|
|
9
10
|
|
|
10
11
|
def initialize(
|
|
11
12
|
frequency: 0.5,
|
|
@@ -4,18 +4,46 @@ module Deftones
|
|
|
4
4
|
module Effects
|
|
5
5
|
class Reverb < Core::Effect
|
|
6
6
|
attr_accessor :decay, :pre_delay
|
|
7
|
+
attr_reader :damping, :freeze, :wet_normalization, :width
|
|
7
8
|
|
|
8
|
-
def initialize(decay: 0.7, pre_delay: 0.01,
|
|
9
|
+
def initialize(decay: 0.7, pre_delay: 0.01, damping: 0.0, freeze: false, wet_normalization: false,
|
|
10
|
+
width: 1.0, context: Deftones.context, **options)
|
|
9
11
|
super(context: context, **options)
|
|
10
12
|
@decay = decay.to_f
|
|
11
13
|
@pre_delay = pre_delay.to_f
|
|
14
|
+
self.damping = damping
|
|
15
|
+
self.freeze = freeze
|
|
16
|
+
self.wet_normalization = wet_normalization
|
|
17
|
+
self.width = width
|
|
12
18
|
@comb_times = [0.0297, 0.0371, 0.0411, 0.0437]
|
|
13
19
|
@allpass_times = [0.005, 0.0017]
|
|
14
20
|
@comb_lines = []
|
|
21
|
+
@comb_damping_state = []
|
|
15
22
|
@allpass_lines = []
|
|
16
23
|
@pre_delay_lines = []
|
|
17
24
|
end
|
|
18
25
|
|
|
26
|
+
def damping=(value)
|
|
27
|
+
@damping = value.to_f.clamp(0.0, 1.0)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def freeze=(value)
|
|
31
|
+
@freeze = !!value
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def wet_normalization=(value)
|
|
35
|
+
@wet_normalization = !!value
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def width=(value)
|
|
39
|
+
@width = value.to_f.clamp(0.0, 1.0)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
alias dampening damping
|
|
43
|
+
alias dampening= damping=
|
|
44
|
+
alias wetNormalization wet_normalization
|
|
45
|
+
alias wetNormalization= wet_normalization=
|
|
46
|
+
|
|
19
47
|
private
|
|
20
48
|
|
|
21
49
|
def process_effect_block(input_block, num_frames, start_frame, cache)
|
|
@@ -23,9 +51,9 @@ module Deftones
|
|
|
23
51
|
source = input_block.fit_channels(output_channels)
|
|
24
52
|
|
|
25
53
|
Core::AudioBlock.from_channel_data(
|
|
26
|
-
source.channel_data.each_with_index.map do |channel, channel_index|
|
|
54
|
+
apply_stereo_width(source.channel_data.each_with_index.map do |channel, channel_index|
|
|
27
55
|
process_effect(channel, num_frames, start_frame, cache, channel_index: channel_index)
|
|
28
|
-
end
|
|
56
|
+
end)
|
|
29
57
|
)
|
|
30
58
|
end
|
|
31
59
|
|
|
@@ -40,23 +68,37 @@ module Deftones
|
|
|
40
68
|
Array.new(num_frames) do |index|
|
|
41
69
|
dry = input_buffer[index]
|
|
42
70
|
delayed = pre_delay_line.tap(@pre_delay * context.sample_rate, input_sample: dry)
|
|
71
|
+
feedback = effective_decay
|
|
72
|
+
comb_input = @freeze ? 0.0 : delayed
|
|
43
73
|
comb_sum = comb_lines.each_with_index.sum do |line, comb_index|
|
|
44
|
-
line
|
|
74
|
+
process_comb(line, comb_times[comb_index] * context.sample_rate, comb_input, feedback, channel_index,
|
|
75
|
+
comb_index)
|
|
45
76
|
end / comb_lines.length.to_f
|
|
46
77
|
|
|
47
|
-
allpass_lines.each_with_index.reduce(comb_sum) do |sample, (line, allpass_index)|
|
|
78
|
+
wet_sample = allpass_lines.each_with_index.reduce(comb_sum) do |sample, (line, allpass_index)|
|
|
48
79
|
tap = line.read(allpass_times[allpass_index] * context.sample_rate)
|
|
49
80
|
line.write(sample + (tap * 0.5))
|
|
50
81
|
tap - (sample * 0.5)
|
|
51
82
|
end
|
|
83
|
+
normalize_wet_sample(wet_sample, feedback)
|
|
52
84
|
end
|
|
53
85
|
end
|
|
54
86
|
|
|
87
|
+
def process_comb(line, delay_samples, input_sample, feedback, channel_index, comb_index)
|
|
88
|
+
delayed_sample = line.read(delay_samples)
|
|
89
|
+
previous = @comb_damping_state[channel_index][comb_index]
|
|
90
|
+
filtered = DSP::Helpers.lerp(delayed_sample, previous, @damping)
|
|
91
|
+
@comb_damping_state[channel_index][comb_index] = filtered
|
|
92
|
+
line.write(input_sample + (filtered * feedback))
|
|
93
|
+
filtered
|
|
94
|
+
end
|
|
95
|
+
|
|
55
96
|
def ensure_delay_network(channel_index)
|
|
56
97
|
required = [channel_index.to_i, 0].max
|
|
57
98
|
while @pre_delay_lines.length <= required
|
|
58
99
|
@pre_delay_lines << DSP::DelayLine.new((0.1 * context.sample_rate).ceil)
|
|
59
100
|
@comb_lines << @comb_times.map { |seconds| DSP::DelayLine.new((seconds * context.sample_rate).ceil + 2) }
|
|
101
|
+
@comb_damping_state << Array.new(@comb_times.length, 0.0)
|
|
60
102
|
@allpass_lines << @allpass_times.map { |seconds| DSP::DelayLine.new((seconds * context.sample_rate).ceil + 2) }
|
|
61
103
|
end
|
|
62
104
|
end
|
|
@@ -66,6 +108,32 @@ module Deftones
|
|
|
66
108
|
|
|
67
109
|
times.map { |time| time + (offset * channel_index) }
|
|
68
110
|
end
|
|
111
|
+
|
|
112
|
+
def apply_stereo_width(channel_data)
|
|
113
|
+
return channel_data if channel_data.length < 2 || @width >= 1.0
|
|
114
|
+
|
|
115
|
+
left = channel_data[0]
|
|
116
|
+
right = channel_data[1]
|
|
117
|
+
widened_left = []
|
|
118
|
+
widened_right = []
|
|
119
|
+
left.each_index do |index|
|
|
120
|
+
mid = (left[index] + right[index]) * 0.5
|
|
121
|
+
side = (left[index] - right[index]) * 0.5 * @width
|
|
122
|
+
widened_left << (mid + side)
|
|
123
|
+
widened_right << (mid - side)
|
|
124
|
+
end
|
|
125
|
+
[widened_left, widened_right] + channel_data.drop(2)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def effective_decay
|
|
129
|
+
@freeze ? 0.995 : @decay.to_f.clamp(0.0, 0.995)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def normalize_wet_sample(sample, feedback)
|
|
133
|
+
return sample unless @wet_normalization
|
|
134
|
+
|
|
135
|
+
sample * (1.0 - ([feedback.abs, 0.95].min * 0.35))
|
|
136
|
+
end
|
|
69
137
|
end
|
|
70
138
|
end
|
|
71
139
|
end
|
|
@@ -18,11 +18,13 @@ module Deftones
|
|
|
18
18
|
|
|
19
19
|
private
|
|
20
20
|
|
|
21
|
-
def initialize_callback_behavior(probability: 1.0, humanize: false, mute: false, playback_rate: 1.0
|
|
21
|
+
def initialize_callback_behavior(probability: 1.0, humanize: false, mute: false, playback_rate: 1.0,
|
|
22
|
+
seed: nil, rng: nil)
|
|
22
23
|
@probability = probability.to_f
|
|
23
24
|
@humanize = humanize
|
|
24
25
|
@mute = !!mute
|
|
25
26
|
@playback_rate = playback_rate.to_f
|
|
27
|
+
@rng = rng || (seed.nil? ? Random : Random.new(seed))
|
|
26
28
|
@state = :stopped
|
|
27
29
|
end
|
|
28
30
|
|
|
@@ -46,15 +48,17 @@ module Deftones
|
|
|
46
48
|
|
|
47
49
|
def callback_permitted?
|
|
48
50
|
return false if @mute
|
|
51
|
+
return true if @probability >= 1.0
|
|
52
|
+
return false if @probability <= 0.0
|
|
49
53
|
|
|
50
|
-
rand <= @probability
|
|
54
|
+
@rng.rand <= @probability
|
|
51
55
|
end
|
|
52
56
|
|
|
53
57
|
def humanized_time(time)
|
|
54
58
|
return time unless @humanize
|
|
55
59
|
|
|
56
60
|
amount = @humanize == true ? 0.01 : Deftones::Music::Time.parse(@humanize)
|
|
57
|
-
time + (((rand * 2.0) - 1.0) * amount)
|
|
61
|
+
time + (((@rng.rand * 2.0) - 1.0) * amount)
|
|
58
62
|
end
|
|
59
63
|
end
|
|
60
64
|
end
|
data/lib/deftones/event/loop.rb
CHANGED
|
@@ -8,7 +8,10 @@ module Deftones
|
|
|
8
8
|
attr_reader :interval, :iterations
|
|
9
9
|
|
|
10
10
|
def initialize(interval:, iterations: nil, transport: Deftones.transport,
|
|
11
|
-
probability: 1.0, humanize: false, mute: false, playback_rate: 1.0,
|
|
11
|
+
probability: 1.0, humanize: false, mute: false, playback_rate: 1.0,
|
|
12
|
+
seed: nil, rng: nil, &callback)
|
|
13
|
+
raise ArgumentError, "callback is required" unless callback
|
|
14
|
+
|
|
12
15
|
@interval = interval
|
|
13
16
|
@iterations = iterations
|
|
14
17
|
@transport = transport
|
|
@@ -18,7 +21,9 @@ module Deftones
|
|
|
18
21
|
probability: probability,
|
|
19
22
|
humanize: humanize,
|
|
20
23
|
mute: mute,
|
|
21
|
-
playback_rate: playback_rate
|
|
24
|
+
playback_rate: playback_rate,
|
|
25
|
+
seed: seed,
|
|
26
|
+
rng: rng
|
|
22
27
|
)
|
|
23
28
|
end
|
|
24
29
|
|
data/lib/deftones/event/part.rb
CHANGED
|
@@ -6,8 +6,11 @@ module Deftones
|
|
|
6
6
|
include CallbackBehavior
|
|
7
7
|
|
|
8
8
|
def initialize(events:, transport: Deftones.transport,
|
|
9
|
-
probability: 1.0, humanize: false, mute: false, playback_rate: 1.0,
|
|
10
|
-
|
|
9
|
+
probability: 1.0, humanize: false, mute: false, playback_rate: 1.0,
|
|
10
|
+
seed: nil, rng: nil, &callback)
|
|
11
|
+
raise ArgumentError, "callback is required" unless callback
|
|
12
|
+
|
|
13
|
+
@events = normalize_events(events)
|
|
11
14
|
@transport = transport
|
|
12
15
|
@callback = callback
|
|
13
16
|
@event_ids = []
|
|
@@ -15,7 +18,9 @@ module Deftones
|
|
|
15
18
|
probability: probability,
|
|
16
19
|
humanize: humanize,
|
|
17
20
|
mute: mute,
|
|
18
|
-
playback_rate: playback_rate
|
|
21
|
+
playback_rate: playback_rate,
|
|
22
|
+
seed: seed,
|
|
23
|
+
rng: rng
|
|
19
24
|
)
|
|
20
25
|
end
|
|
21
26
|
|
|
@@ -46,6 +51,16 @@ module Deftones
|
|
|
46
51
|
cancel
|
|
47
52
|
self
|
|
48
53
|
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def normalize_events(events)
|
|
58
|
+
Array(events).map do |event|
|
|
59
|
+
next { time: event[0], value: event[1] } if event.is_a?(Array)
|
|
60
|
+
|
|
61
|
+
event
|
|
62
|
+
end
|
|
63
|
+
end
|
|
49
64
|
end
|
|
50
65
|
end
|
|
51
66
|
end
|
|
@@ -5,11 +5,23 @@ module Deftones
|
|
|
5
5
|
class Pattern
|
|
6
6
|
include CallbackBehavior
|
|
7
7
|
|
|
8
|
-
PATTERNS = %i[up down up_down random].freeze
|
|
8
|
+
PATTERNS = %i[up down up_down down_up alternate_up alternate_down random random_walk].freeze
|
|
9
|
+
PATTERN_ALIASES = {
|
|
10
|
+
upDown: :up_down,
|
|
11
|
+
downUp: :down_up,
|
|
12
|
+
alternateUp: :alternate_up,
|
|
13
|
+
alternateDown: :alternate_down,
|
|
14
|
+
randomWalk: :random_walk
|
|
15
|
+
}.freeze
|
|
9
16
|
|
|
10
17
|
def initialize(values:, pattern: :up, interval: "4n", transport: Deftones.transport,
|
|
11
|
-
probability: 1.0, humanize: false, mute: false, playback_rate: 1.0,
|
|
12
|
-
|
|
18
|
+
probability: 1.0, humanize: false, mute: false, playback_rate: 1.0,
|
|
19
|
+
seed: nil, rng: nil, &callback)
|
|
20
|
+
raise ArgumentError, "callback is required" unless callback
|
|
21
|
+
|
|
22
|
+
@values = Array(values)
|
|
23
|
+
raise ArgumentError, "Pattern values must not be empty" if @values.empty?
|
|
24
|
+
|
|
13
25
|
@pattern = normalize_pattern(pattern)
|
|
14
26
|
@interval = interval
|
|
15
27
|
@transport = transport
|
|
@@ -21,7 +33,9 @@ module Deftones
|
|
|
21
33
|
probability: probability,
|
|
22
34
|
humanize: humanize,
|
|
23
35
|
mute: mute,
|
|
24
|
-
playback_rate: playback_rate
|
|
36
|
+
playback_rate: playback_rate,
|
|
37
|
+
seed: seed,
|
|
38
|
+
rng: rng
|
|
25
39
|
)
|
|
26
40
|
end
|
|
27
41
|
|
|
@@ -58,8 +72,16 @@ module Deftones
|
|
|
58
72
|
descending_value
|
|
59
73
|
when :up_down
|
|
60
74
|
bounce_value
|
|
75
|
+
when :down_up
|
|
76
|
+
descending_bounce_value
|
|
77
|
+
when :alternate_up
|
|
78
|
+
alternate_value(:up)
|
|
79
|
+
when :alternate_down
|
|
80
|
+
alternate_value(:down)
|
|
61
81
|
when :random
|
|
62
|
-
@values.
|
|
82
|
+
@values[@rng.rand(@values.length)]
|
|
83
|
+
when :random_walk
|
|
84
|
+
random_walk_value
|
|
63
85
|
end
|
|
64
86
|
end
|
|
65
87
|
|
|
@@ -83,8 +105,31 @@ module Deftones
|
|
|
83
105
|
value
|
|
84
106
|
end
|
|
85
107
|
|
|
108
|
+
def descending_bounce_value
|
|
109
|
+
value = @values.reverse[@index]
|
|
110
|
+
@direction = -1 if @index >= @values.length - 1
|
|
111
|
+
@direction = 1 if @index <= 0
|
|
112
|
+
@index += @direction
|
|
113
|
+
value
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def alternate_value(start_direction)
|
|
117
|
+
cycle = @index / @values.length
|
|
118
|
+
offset = @index % @values.length
|
|
119
|
+
@index += 1
|
|
120
|
+
descending = start_direction == :down ? cycle.even? : cycle.odd?
|
|
121
|
+
descending ? @values.reverse[offset] : @values[offset]
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def random_walk_value
|
|
125
|
+
value = @values[@index]
|
|
126
|
+
@direction = [-1, 1][@rng.rand(2)]
|
|
127
|
+
@index = (@index + @direction).clamp(0, @values.length - 1)
|
|
128
|
+
value
|
|
129
|
+
end
|
|
130
|
+
|
|
86
131
|
def normalize_pattern(pattern)
|
|
87
|
-
normalized = pattern.to_sym
|
|
132
|
+
normalized = PATTERN_ALIASES.fetch(pattern.to_sym, pattern.to_sym)
|
|
88
133
|
return normalized if PATTERNS.include?(normalized)
|
|
89
134
|
|
|
90
135
|
raise ArgumentError, "Unsupported pattern: #{pattern}"
|
|
@@ -7,8 +7,13 @@ module Deftones
|
|
|
7
7
|
include CallbackBehavior
|
|
8
8
|
|
|
9
9
|
def initialize(notes:, subdivision: "4n", loop: true, transport: Deftones.transport,
|
|
10
|
-
probability: 1.0, humanize: false, mute: false, playback_rate: 1.0,
|
|
11
|
-
|
|
10
|
+
probability: 1.0, humanize: false, mute: false, playback_rate: 1.0,
|
|
11
|
+
seed: nil, rng: nil, &callback)
|
|
12
|
+
raise ArgumentError, "callback is required" unless callback
|
|
13
|
+
|
|
14
|
+
@notes = Array(notes)
|
|
15
|
+
raise ArgumentError, "Sequence notes must not be empty" if @notes.empty?
|
|
16
|
+
|
|
12
17
|
@subdivision = subdivision
|
|
13
18
|
@loop = loop
|
|
14
19
|
@transport = transport
|
|
@@ -19,7 +24,9 @@ module Deftones
|
|
|
19
24
|
probability: probability,
|
|
20
25
|
humanize: humanize,
|
|
21
26
|
mute: mute,
|
|
22
|
-
playback_rate: playback_rate
|
|
27
|
+
playback_rate: playback_rate,
|
|
28
|
+
seed: seed,
|
|
29
|
+
rng: rng
|
|
23
30
|
)
|
|
24
31
|
end
|
|
25
32
|
|
|
@@ -76,12 +83,19 @@ module Deftones
|
|
|
76
83
|
note.each_with_index do |nested_note, index|
|
|
77
84
|
next if nested_note.nil?
|
|
78
85
|
|
|
79
|
-
|
|
86
|
+
process_note(humanized_time(scheduled_time + (sub_duration * index)), nested_note)
|
|
80
87
|
end
|
|
81
88
|
else
|
|
82
|
-
|
|
89
|
+
process_note(humanized_time(scheduled_time), note)
|
|
83
90
|
end
|
|
84
91
|
end
|
|
92
|
+
|
|
93
|
+
def process_note(time, note)
|
|
94
|
+
payload = note.is_a?(Hash) ? note : { note: note }
|
|
95
|
+
return if payload.fetch(:probability, 1.0).to_f < @rng.rand
|
|
96
|
+
|
|
97
|
+
@callback.call(time, payload.fetch(:note, payload[:value]), payload)
|
|
98
|
+
end
|
|
85
99
|
end
|
|
86
100
|
end
|
|
87
101
|
end
|
|
@@ -8,7 +8,10 @@ module Deftones
|
|
|
8
8
|
attr_accessor :loop, :loop_start, :loop_end, :probability
|
|
9
9
|
|
|
10
10
|
def initialize(transport: Deftones.transport, probability: 1.0, loop: false,
|
|
11
|
-
loop_start: 0.0, loop_end: nil, humanize: false, mute: false, playback_rate: 1.0,
|
|
11
|
+
loop_start: 0.0, loop_end: nil, humanize: false, mute: false, playback_rate: 1.0,
|
|
12
|
+
seed: nil, rng: nil, &callback)
|
|
13
|
+
raise ArgumentError, "callback is required" unless callback
|
|
14
|
+
|
|
12
15
|
@transport = transport
|
|
13
16
|
@callback = callback
|
|
14
17
|
@loop = loop
|
|
@@ -19,7 +22,9 @@ module Deftones
|
|
|
19
22
|
probability: probability,
|
|
20
23
|
humanize: humanize,
|
|
21
24
|
mute: mute,
|
|
22
|
-
playback_rate: playback_rate
|
|
25
|
+
playback_rate: playback_rate,
|
|
26
|
+
seed: seed,
|
|
27
|
+
rng: rng
|
|
23
28
|
)
|
|
24
29
|
end
|
|
25
30
|
|