deftones 0.1.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 +7 -0
- data/.yardopts +5 -0
- data/CHANGELOG.md +12 -0
- data/LICENSE.txt +21 -0
- data/README.md +197 -0
- data/Rakefile +8 -0
- data/examples/poly_chord.rb +14 -0
- data/examples/render_sampler.rb +16 -0
- data/examples/render_sequence.rb +13 -0
- data/examples/render_synth.rb +18 -0
- data/lib/deftones/analysis/analyser.rb +162 -0
- data/lib/deftones/analysis/dc_meter.rb +56 -0
- data/lib/deftones/analysis/fft.rb +128 -0
- data/lib/deftones/analysis/meter.rb +83 -0
- data/lib/deftones/analysis/waveform.rb +93 -0
- data/lib/deftones/component/amplitude_envelope.rb +8 -0
- data/lib/deftones/component/biquad_filter.rb +7 -0
- data/lib/deftones/component/channel.rb +109 -0
- data/lib/deftones/component/compressor.rb +64 -0
- data/lib/deftones/component/convolver.rb +99 -0
- data/lib/deftones/component/cross_fade.rb +67 -0
- data/lib/deftones/component/envelope.rb +160 -0
- data/lib/deftones/component/eq3.rb +73 -0
- data/lib/deftones/component/feedback_comb_filter.rb +75 -0
- data/lib/deftones/component/filter.rb +75 -0
- data/lib/deftones/component/follower.rb +55 -0
- data/lib/deftones/component/frequency_envelope.rb +24 -0
- data/lib/deftones/component/gate.rb +46 -0
- data/lib/deftones/component/lfo.rb +88 -0
- data/lib/deftones/component/limiter.rb +11 -0
- data/lib/deftones/component/lowpass_comb_filter.rb +43 -0
- data/lib/deftones/component/merge.rb +45 -0
- data/lib/deftones/component/mid_side_compressor.rb +43 -0
- data/lib/deftones/component/mid_side_merge.rb +53 -0
- data/lib/deftones/component/mid_side_split.rb +54 -0
- data/lib/deftones/component/mono.rb +8 -0
- data/lib/deftones/component/multiband_compressor.rb +70 -0
- data/lib/deftones/component/multiband_split.rb +133 -0
- data/lib/deftones/component/one_pole_filter.rb +71 -0
- data/lib/deftones/component/pan_vol.rb +26 -0
- data/lib/deftones/component/panner.rb +75 -0
- data/lib/deftones/component/panner3d.rb +322 -0
- data/lib/deftones/component/solo.rb +56 -0
- data/lib/deftones/component/split.rb +47 -0
- data/lib/deftones/component/volume.rb +31 -0
- data/lib/deftones/context.rb +213 -0
- data/lib/deftones/core/audio_block.rb +82 -0
- data/lib/deftones/core/audio_node.rb +262 -0
- data/lib/deftones/core/clock.rb +91 -0
- data/lib/deftones/core/computed_signal.rb +69 -0
- data/lib/deftones/core/delay.rb +44 -0
- data/lib/deftones/core/effect.rb +66 -0
- data/lib/deftones/core/emitter.rb +51 -0
- data/lib/deftones/core/gain.rb +39 -0
- data/lib/deftones/core/instrument.rb +109 -0
- data/lib/deftones/core/param.rb +31 -0
- data/lib/deftones/core/signal.rb +452 -0
- data/lib/deftones/core/signal_operator_methods.rb +73 -0
- data/lib/deftones/core/signal_operators.rb +138 -0
- data/lib/deftones/core/signal_shapers.rb +83 -0
- data/lib/deftones/core/source.rb +213 -0
- data/lib/deftones/core/synced_signal.rb +88 -0
- data/lib/deftones/destination.rb +132 -0
- data/lib/deftones/draw.rb +100 -0
- data/lib/deftones/dsp/biquad.rb +129 -0
- data/lib/deftones/dsp/delay_line.rb +41 -0
- data/lib/deftones/dsp/helpers.rb +25 -0
- data/lib/deftones/effect/auto_filter.rb +92 -0
- data/lib/deftones/effect/auto_panner.rb +57 -0
- data/lib/deftones/effect/auto_wah.rb +98 -0
- data/lib/deftones/effect/bit_crusher.rb +38 -0
- data/lib/deftones/effect/chebyshev.rb +36 -0
- data/lib/deftones/effect/chorus.rb +73 -0
- data/lib/deftones/effect/distortion.rb +22 -0
- data/lib/deftones/effect/feedback_delay.rb +38 -0
- data/lib/deftones/effect/freeverb.rb +11 -0
- data/lib/deftones/effect/frequency_shifter.rb +89 -0
- data/lib/deftones/effect/jc_reverb.rb +11 -0
- data/lib/deftones/effect/modulation_control.rb +159 -0
- data/lib/deftones/effect/phaser.rb +72 -0
- data/lib/deftones/effect/ping_pong_delay.rb +40 -0
- data/lib/deftones/effect/pitch_shift.rb +156 -0
- data/lib/deftones/effect/reverb.rb +71 -0
- data/lib/deftones/effect/stereo_widener.rb +34 -0
- data/lib/deftones/effect/tremolo.rb +52 -0
- data/lib/deftones/effect/vibrato.rb +47 -0
- data/lib/deftones/event/callback_behavior.rb +61 -0
- data/lib/deftones/event/loop.rb +53 -0
- data/lib/deftones/event/part.rb +51 -0
- data/lib/deftones/event/pattern.rb +94 -0
- data/lib/deftones/event/sequence.rb +87 -0
- data/lib/deftones/event/tone_event.rb +77 -0
- data/lib/deftones/event/transport.rb +276 -0
- data/lib/deftones/instrument/am_synth.rb +56 -0
- data/lib/deftones/instrument/duo_synth.rb +68 -0
- data/lib/deftones/instrument/fm_synth.rb +60 -0
- data/lib/deftones/instrument/membrane_synth.rb +60 -0
- data/lib/deftones/instrument/metal_synth.rb +61 -0
- data/lib/deftones/instrument/mono_synth.rb +88 -0
- data/lib/deftones/instrument/noise_synth.rb +56 -0
- data/lib/deftones/instrument/pluck_synth.rb +41 -0
- data/lib/deftones/instrument/poly_synth.rb +96 -0
- data/lib/deftones/instrument/sampler.rb +97 -0
- data/lib/deftones/instrument/synth.rb +60 -0
- data/lib/deftones/io/buffer.rb +352 -0
- data/lib/deftones/io/buffers.rb +77 -0
- data/lib/deftones/io/recorder.rb +89 -0
- data/lib/deftones/listener.rb +120 -0
- data/lib/deftones/music/frequency.rb +128 -0
- data/lib/deftones/music/midi.rb +206 -0
- data/lib/deftones/music/note.rb +58 -0
- data/lib/deftones/music/ticks.rb +106 -0
- data/lib/deftones/music/time.rb +209 -0
- data/lib/deftones/music/transport_time.rb +94 -0
- data/lib/deftones/music/unit_helpers.rb +30 -0
- data/lib/deftones/offline_context.rb +46 -0
- data/lib/deftones/portaudio_support.rb +112 -0
- data/lib/deftones/source/am_oscillator.rb +42 -0
- data/lib/deftones/source/fat_oscillator.rb +49 -0
- data/lib/deftones/source/fm_oscillator.rb +47 -0
- data/lib/deftones/source/grain_player.rb +198 -0
- data/lib/deftones/source/karplus_strong.rb +51 -0
- data/lib/deftones/source/noise.rb +99 -0
- data/lib/deftones/source/omni_oscillator.rb +175 -0
- data/lib/deftones/source/oscillator.rb +74 -0
- data/lib/deftones/source/player.rb +228 -0
- data/lib/deftones/source/players.rb +133 -0
- data/lib/deftones/source/pulse_oscillator.rb +38 -0
- data/lib/deftones/source/pwm_oscillator.rb +49 -0
- data/lib/deftones/source/tone_buffer_source.rb +136 -0
- data/lib/deftones/source/tone_oscillator_node.rb +65 -0
- data/lib/deftones/source/user_media.rb +519 -0
- data/lib/deftones/version.rb +5 -0
- data/lib/deftones.rb +542 -0
- metadata +221 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Deftones
|
|
4
|
+
module Core
|
|
5
|
+
class BinarySignal < ComputedSignal
|
|
6
|
+
attr_reader :other
|
|
7
|
+
|
|
8
|
+
def initialize(input:, other:, units: nil, context: nil)
|
|
9
|
+
super(input: input, units: units, context: context)
|
|
10
|
+
@other = coerce_signal(other, units: @units)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def value_at(time)
|
|
14
|
+
compute(@input.value_at(time), @other.value_at(time), time)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class Add < BinarySignal
|
|
19
|
+
def initialize(input:, addend:, units: nil, context: nil)
|
|
20
|
+
super(input: input, other: addend, units: units, context: context)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def compute(left, right, _time)
|
|
24
|
+
left + right
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class Subtract < BinarySignal
|
|
29
|
+
def initialize(input:, subtrahend:, units: nil, context: nil)
|
|
30
|
+
super(input: input, other: subtrahend, units: units, context: context)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def compute(left, right, _time)
|
|
34
|
+
left - right
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class Multiply < BinarySignal
|
|
39
|
+
def initialize(input:, factor:, units: nil, context: nil)
|
|
40
|
+
super(input: input, other: factor, units: units, context: context)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def compute(left, right, _time)
|
|
44
|
+
left * right
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class GreaterThan < BinarySignal
|
|
49
|
+
def initialize(input:, threshold:, context: nil)
|
|
50
|
+
super(input: input, other: threshold, units: :number, context: context)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def compute(left, right, _time)
|
|
54
|
+
left > right ? 1.0 : 0.0
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class GreaterThanZero < GreaterThan
|
|
59
|
+
def initialize(input:, context: nil)
|
|
60
|
+
super(input: input, threshold: 0.0, context: context)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class Negate < ComputedSignal
|
|
65
|
+
def value_at(time)
|
|
66
|
+
-@input.value_at(time)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class Abs < ComputedSignal
|
|
71
|
+
def value_at(time)
|
|
72
|
+
@input.value_at(time).abs
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class Pow < ComputedSignal
|
|
77
|
+
attr_reader :exponent
|
|
78
|
+
|
|
79
|
+
def initialize(input:, exponent:, context: nil)
|
|
80
|
+
super(input: input, units: :number, context: context)
|
|
81
|
+
@exponent = coerce_signal(exponent, units: :number)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def value_at(time)
|
|
85
|
+
exponentiate(@input.value_at(time), @exponent.value_at(time))
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class Scale < ComputedSignal
|
|
90
|
+
attr_reader :min, :max
|
|
91
|
+
|
|
92
|
+
def initialize(input:, min:, max:, context: nil)
|
|
93
|
+
super(input: input, units: :number, context: context)
|
|
94
|
+
@min = coerce_signal(min, units: :number)
|
|
95
|
+
@max = coerce_signal(max, units: :number)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def value_at(time)
|
|
99
|
+
min_value = @min.value_at(time)
|
|
100
|
+
max_value = @max.value_at(time)
|
|
101
|
+
|
|
102
|
+
min_value + ((max_value - min_value) * @input.value_at(time))
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
class ScaleExp < Scale
|
|
107
|
+
attr_reader :exponent
|
|
108
|
+
|
|
109
|
+
def initialize(input:, min:, max:, exponent: 2.0, context: nil)
|
|
110
|
+
super(input: input, min: min, max: max, context: context)
|
|
111
|
+
@exponent = coerce_signal(exponent, units: :number)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def value_at(time)
|
|
115
|
+
min_value = @min.value_at(time)
|
|
116
|
+
max_value = @max.value_at(time)
|
|
117
|
+
scaled = exponentiate(@input.value_at(time), @exponent.value_at(time))
|
|
118
|
+
|
|
119
|
+
min_value + ((max_value - min_value) * scaled)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
class AudioToGain < ComputedSignal
|
|
124
|
+
def value_at(time)
|
|
125
|
+
@input.value_at(time)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
class GainToAudio < AudioToGain
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
class Zero < Signal
|
|
133
|
+
def initialize(context: Deftones.context)
|
|
134
|
+
super(value: 0.0, units: :number, context: context)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Deftones
|
|
4
|
+
module Core
|
|
5
|
+
class EqualPowerGain < ComputedSignal
|
|
6
|
+
def initialize(input:, context: nil)
|
|
7
|
+
super(input: input, units: :number, context: context)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def value_at(time)
|
|
11
|
+
Math.sin(@input.value_at(time).clamp(0.0, 1.0) * Math::PI * 0.5)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class Modulo < BinarySignal
|
|
16
|
+
def initialize(input:, modulus:, context: nil)
|
|
17
|
+
super(input: input, other: modulus, units: :number, context: context)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def compute(left, right, _time)
|
|
21
|
+
return 0.0 if right.zero?
|
|
22
|
+
|
|
23
|
+
((left % right) + right) % right
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class Normalize < ComputedSignal
|
|
28
|
+
attr_reader :min, :max
|
|
29
|
+
|
|
30
|
+
def initialize(input:, min:, max:, context: nil)
|
|
31
|
+
super(input: input, units: :number, context: context)
|
|
32
|
+
@min = coerce_signal(min, units: :number)
|
|
33
|
+
@max = coerce_signal(max, units: :number)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def value_at(time)
|
|
37
|
+
min_value = @min.value_at(time)
|
|
38
|
+
max_value = @max.value_at(time)
|
|
39
|
+
span = max_value - min_value
|
|
40
|
+
return 0.0 if span.zero?
|
|
41
|
+
|
|
42
|
+
(@input.value_at(time) - min_value) / span
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class WaveShaper < ComputedSignal
|
|
47
|
+
def initialize(input:, curve: nil, mapping: nil, context: nil, &block)
|
|
48
|
+
super(input: input, units: :number, context: context)
|
|
49
|
+
@mapping = mapping || block
|
|
50
|
+
@curve = normalize_curve(curve)
|
|
51
|
+
raise ArgumentError, "curve or mapping is required" unless @mapping || @curve
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def value_at(time)
|
|
55
|
+
sample = @input.value_at(time)
|
|
56
|
+
return @mapping.call(sample, time) if @mapping
|
|
57
|
+
|
|
58
|
+
sample_curve(sample)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def normalize_curve(curve)
|
|
64
|
+
return if curve.nil?
|
|
65
|
+
|
|
66
|
+
values = curve.to_a.map(&:to_f)
|
|
67
|
+
raise ArgumentError, "curve must contain at least two points" if values.length < 2
|
|
68
|
+
|
|
69
|
+
values.freeze
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def sample_curve(sample)
|
|
73
|
+
position = ((sample.clamp(-1.0, 1.0) + 1.0) * 0.5) * (@curve.length - 1)
|
|
74
|
+
index = position.floor
|
|
75
|
+
upper_index = [index + 1, @curve.length - 1].min
|
|
76
|
+
lower = @curve[index]
|
|
77
|
+
upper = @curve[upper_index]
|
|
78
|
+
|
|
79
|
+
lower + ((upper - lower) * (position - index))
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Deftones
|
|
4
|
+
module Core
|
|
5
|
+
class Source < AudioNode
|
|
6
|
+
class VolumeProxy
|
|
7
|
+
attr_reader :source
|
|
8
|
+
attr_accessor :value
|
|
9
|
+
|
|
10
|
+
def initialize(source, value: 0.0)
|
|
11
|
+
@source = source
|
|
12
|
+
@value = value.to_f
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def value=(new_value)
|
|
16
|
+
@value = new_value.to_f
|
|
17
|
+
source.send(:apply_volume!)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def ramp_to(target_value, _duration = nil)
|
|
21
|
+
self.value = target_value
|
|
22
|
+
self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
alias linear_ramp_to ramp_to
|
|
26
|
+
alias exponential_ramp_to ramp_to
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
attr_reader :volume
|
|
30
|
+
attr_accessor :onstop
|
|
31
|
+
attr_accessor :mute
|
|
32
|
+
|
|
33
|
+
def initialize(context: Deftones.context)
|
|
34
|
+
super(context: context)
|
|
35
|
+
@input = nil
|
|
36
|
+
@volume = VolumeProxy.new(self)
|
|
37
|
+
@mute = false
|
|
38
|
+
@start_time = Float::INFINITY
|
|
39
|
+
@stop_time = nil
|
|
40
|
+
@onstop = nil
|
|
41
|
+
@stop_notified = false
|
|
42
|
+
@synced = false
|
|
43
|
+
@transport_event_ids = {}
|
|
44
|
+
apply_volume!
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def number_of_inputs
|
|
48
|
+
0
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def volume=(value)
|
|
52
|
+
@volume.value = value
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def mute=(value)
|
|
56
|
+
@mute = !!value
|
|
57
|
+
apply_volume!
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def mute?
|
|
61
|
+
@mute
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def source_type
|
|
65
|
+
class_name = self.class.name.split("::").last
|
|
66
|
+
words = class_name
|
|
67
|
+
.gsub(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
|
|
68
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
|
69
|
+
.downcase
|
|
70
|
+
.split("_")
|
|
71
|
+
|
|
72
|
+
[words.first, *words.drop(1).map(&:capitalize)].join
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def start(time = nil)
|
|
76
|
+
return schedule_transport_event(:start, time) if synced?
|
|
77
|
+
|
|
78
|
+
@start_time = resolve_time(time)
|
|
79
|
+
@stop_time = nil if @stop_time && @stop_time <= @start_time
|
|
80
|
+
@stop_notified = false
|
|
81
|
+
self
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def stop(time = nil)
|
|
85
|
+
return schedule_transport_event(:stop, time) if synced?
|
|
86
|
+
|
|
87
|
+
@stop_time = resolve_time(time)
|
|
88
|
+
self
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def restart(time = nil)
|
|
92
|
+
stop(time)
|
|
93
|
+
start(time)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def cancel_stop
|
|
97
|
+
clear_transport_event(:stop)
|
|
98
|
+
@stop_time = nil
|
|
99
|
+
self
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def state(time = context.current_time)
|
|
103
|
+
active_at?(resolve_time(time)) ? :started : :stopped
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def sync
|
|
107
|
+
@synced = true
|
|
108
|
+
self
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def unsync
|
|
112
|
+
@synced = false
|
|
113
|
+
clear_transport_event(:start)
|
|
114
|
+
clear_transport_event(:stop)
|
|
115
|
+
self
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def synced?
|
|
119
|
+
@synced
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def active_at?(time)
|
|
123
|
+
return false if time < @start_time
|
|
124
|
+
return true if @stop_time.nil?
|
|
125
|
+
|
|
126
|
+
time < @stop_time
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def render(num_frames, start_frame = 0, cache = {})
|
|
130
|
+
output_buffer = super.map { |sample| sample * @output_gain }
|
|
131
|
+
notify_stop_in_window(start_frame, num_frames)
|
|
132
|
+
output_buffer
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def render_block(num_frames, start_frame = 0, cache = {})
|
|
136
|
+
output_block = super
|
|
137
|
+
scaled = AudioBlock.from_channel_data(
|
|
138
|
+
output_block.channel_data.map do |channel|
|
|
139
|
+
channel.map { |sample| sample * @output_gain }
|
|
140
|
+
end
|
|
141
|
+
)
|
|
142
|
+
notify_stop_in_window(start_frame, num_frames)
|
|
143
|
+
scaled
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def dispose
|
|
147
|
+
unsync
|
|
148
|
+
super
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
alias cancelStop cancel_stop
|
|
152
|
+
alias numberOfInputs number_of_inputs
|
|
153
|
+
alias sourceType source_type
|
|
154
|
+
|
|
155
|
+
private
|
|
156
|
+
|
|
157
|
+
def uses_legacy_render_for_block?
|
|
158
|
+
false
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def apply_volume!
|
|
162
|
+
@output_gain = mute ? 0.0 : Deftones.db_to_gain(@volume.value)
|
|
163
|
+
self
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def resolve_time(time)
|
|
167
|
+
return context.current_time if time.nil?
|
|
168
|
+
|
|
169
|
+
Deftones::Music::Time.parse(time)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def resolve_transport_time(time)
|
|
173
|
+
return Deftones.transport.seconds if time.nil?
|
|
174
|
+
|
|
175
|
+
time
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def schedule_transport_event(kind, time)
|
|
179
|
+
clear_transport_event(kind)
|
|
180
|
+
@transport_event_ids[kind] = Deftones.transport.schedule(resolve_transport_time(time)) do |scheduled_time|
|
|
181
|
+
if kind == :start
|
|
182
|
+
@start_time = scheduled_time
|
|
183
|
+
@stop_time = nil if @stop_time && @stop_time <= @start_time
|
|
184
|
+
@stop_notified = false
|
|
185
|
+
else
|
|
186
|
+
@stop_time = scheduled_time
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
self
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def clear_transport_event(kind)
|
|
193
|
+
event_id = @transport_event_ids.delete(kind)
|
|
194
|
+
return self unless event_id
|
|
195
|
+
|
|
196
|
+
Deftones.transport.clear(event_id)
|
|
197
|
+
self
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def notify_stop_in_window(start_frame, num_frames)
|
|
201
|
+
return unless @stop_time
|
|
202
|
+
return if @stop_notified
|
|
203
|
+
|
|
204
|
+
start_time = start_frame.to_f / context.sample_rate
|
|
205
|
+
end_time = (start_frame + num_frames).to_f / context.sample_rate
|
|
206
|
+
return unless @stop_time >= start_time && @stop_time <= end_time
|
|
207
|
+
|
|
208
|
+
@stop_notified = true
|
|
209
|
+
@onstop&.call(@stop_time)
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Deftones
|
|
4
|
+
module Core
|
|
5
|
+
class SyncedSignal < Signal
|
|
6
|
+
attr_reader :transport
|
|
7
|
+
|
|
8
|
+
def initialize(transport: Deftones.transport, **options)
|
|
9
|
+
@transport = transport
|
|
10
|
+
@synced = true
|
|
11
|
+
super(**options)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def value
|
|
15
|
+
value_at(current_base_time)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def sync
|
|
19
|
+
@synced = true
|
|
20
|
+
self
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def unsync
|
|
24
|
+
@synced = false
|
|
25
|
+
self
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def synced?
|
|
29
|
+
@synced
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def linear_ramp_to(target_value, duration)
|
|
33
|
+
resolved_end = current_base_time + Deftones::Music::Time.parse(duration)
|
|
34
|
+
schedule_automation(
|
|
35
|
+
:linear,
|
|
36
|
+
coerce_value(target_value),
|
|
37
|
+
start_time: resolve_automation_start_time(resolved_end),
|
|
38
|
+
end_time: resolved_end
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def exponential_ramp_to(target_value, duration)
|
|
43
|
+
resolved_end = current_base_time + Deftones::Music::Time.parse(duration)
|
|
44
|
+
schedule_automation(
|
|
45
|
+
:exponential,
|
|
46
|
+
coerce_value(target_value),
|
|
47
|
+
start_time: resolve_automation_start_time(resolved_end),
|
|
48
|
+
end_time: resolved_end
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def process(num_frames, start_frame = 0)
|
|
53
|
+
timeline_offset = synced? ? transport.seconds : 0.0
|
|
54
|
+
|
|
55
|
+
Array.new(num_frames) do |offset|
|
|
56
|
+
value_at(timeline_offset + sample_time(start_frame + offset))
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def current_base_time
|
|
63
|
+
synced? ? transport.seconds : context.current_time
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def resolve_time(time)
|
|
67
|
+
return current_base_time if time.nil?
|
|
68
|
+
return super unless synced?
|
|
69
|
+
|
|
70
|
+
Deftones::Music::Time.parse(
|
|
71
|
+
time,
|
|
72
|
+
bpm: transport.bpm,
|
|
73
|
+
time_signature: transport.time_signature,
|
|
74
|
+
ppq: transport.ppq
|
|
75
|
+
)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def resolve_automation_start_time(end_time)
|
|
79
|
+
anchors = @events.filter_map do |event|
|
|
80
|
+
anchor = automation_anchor_time(event)
|
|
81
|
+
anchor if anchor <= end_time
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
anchors.max || current_base_time
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Deftones
|
|
4
|
+
class Destination
|
|
5
|
+
class VolumeProxy
|
|
6
|
+
attr_reader :destination
|
|
7
|
+
attr_accessor :value
|
|
8
|
+
|
|
9
|
+
def initialize(destination, value: 0.0)
|
|
10
|
+
@destination = destination
|
|
11
|
+
@value = value.to_f
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def value=(new_value)
|
|
15
|
+
@value = new_value.to_f
|
|
16
|
+
destination.apply_volume!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def ramp_to(target_value, _duration = nil)
|
|
20
|
+
self.value = target_value
|
|
21
|
+
self
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
alias linear_ramp_to ramp_to
|
|
25
|
+
alias exponential_ramp_to ramp_to
|
|
26
|
+
|
|
27
|
+
def set_value_at_time(target_value, _time)
|
|
28
|
+
self.value = target_value
|
|
29
|
+
self
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
attr_reader :context, :volume
|
|
34
|
+
attr_accessor :mute
|
|
35
|
+
|
|
36
|
+
class << self
|
|
37
|
+
def node(context: Deftones.context)
|
|
38
|
+
registry[context.object_id] ||= new(context: context)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def reset!
|
|
42
|
+
@registry = {}
|
|
43
|
+
self
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def method_missing(method_name, *arguments, &block)
|
|
47
|
+
return super unless node.respond_to?(method_name)
|
|
48
|
+
|
|
49
|
+
node.public_send(method_name, *arguments, &block)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
53
|
+
node.respond_to?(method_name, include_private) || super
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def registry
|
|
59
|
+
@registry ||= {}
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def initialize(context:)
|
|
64
|
+
@context = context
|
|
65
|
+
@volume = VolumeProxy.new(self)
|
|
66
|
+
@mute = false
|
|
67
|
+
apply_volume!
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def input
|
|
71
|
+
node
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def output
|
|
75
|
+
node
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def node
|
|
79
|
+
context.output
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def mute=(value)
|
|
83
|
+
@mute = !!value
|
|
84
|
+
apply_volume!
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def mute?
|
|
88
|
+
@mute
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def name
|
|
92
|
+
"Destination"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def sample_time
|
|
96
|
+
1.0 / context.sample_rate
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def block_time
|
|
100
|
+
context.buffer_size.to_f / context.sample_rate
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def max_channel_count
|
|
104
|
+
context.channels
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def connect(*arguments, **keywords)
|
|
108
|
+
node.connect(*arguments, **keywords)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def disconnect(*arguments)
|
|
112
|
+
node.disconnect(*arguments)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def chain(*nodes)
|
|
116
|
+
node.chain(*nodes)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def fan(*nodes)
|
|
120
|
+
node.fan(*nodes)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def apply_volume!
|
|
124
|
+
node.gain.value = mute ? 0.0 : Deftones.db_to_gain(@volume.value)
|
|
125
|
+
self
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
alias sampleTime sample_time
|
|
129
|
+
alias blockTime block_time
|
|
130
|
+
alias maxChannelCount max_channel_count
|
|
131
|
+
end
|
|
132
|
+
end
|