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.
Files changed (135) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +5 -0
  3. data/CHANGELOG.md +12 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +197 -0
  6. data/Rakefile +8 -0
  7. data/examples/poly_chord.rb +14 -0
  8. data/examples/render_sampler.rb +16 -0
  9. data/examples/render_sequence.rb +13 -0
  10. data/examples/render_synth.rb +18 -0
  11. data/lib/deftones/analysis/analyser.rb +162 -0
  12. data/lib/deftones/analysis/dc_meter.rb +56 -0
  13. data/lib/deftones/analysis/fft.rb +128 -0
  14. data/lib/deftones/analysis/meter.rb +83 -0
  15. data/lib/deftones/analysis/waveform.rb +93 -0
  16. data/lib/deftones/component/amplitude_envelope.rb +8 -0
  17. data/lib/deftones/component/biquad_filter.rb +7 -0
  18. data/lib/deftones/component/channel.rb +109 -0
  19. data/lib/deftones/component/compressor.rb +64 -0
  20. data/lib/deftones/component/convolver.rb +99 -0
  21. data/lib/deftones/component/cross_fade.rb +67 -0
  22. data/lib/deftones/component/envelope.rb +160 -0
  23. data/lib/deftones/component/eq3.rb +73 -0
  24. data/lib/deftones/component/feedback_comb_filter.rb +75 -0
  25. data/lib/deftones/component/filter.rb +75 -0
  26. data/lib/deftones/component/follower.rb +55 -0
  27. data/lib/deftones/component/frequency_envelope.rb +24 -0
  28. data/lib/deftones/component/gate.rb +46 -0
  29. data/lib/deftones/component/lfo.rb +88 -0
  30. data/lib/deftones/component/limiter.rb +11 -0
  31. data/lib/deftones/component/lowpass_comb_filter.rb +43 -0
  32. data/lib/deftones/component/merge.rb +45 -0
  33. data/lib/deftones/component/mid_side_compressor.rb +43 -0
  34. data/lib/deftones/component/mid_side_merge.rb +53 -0
  35. data/lib/deftones/component/mid_side_split.rb +54 -0
  36. data/lib/deftones/component/mono.rb +8 -0
  37. data/lib/deftones/component/multiband_compressor.rb +70 -0
  38. data/lib/deftones/component/multiband_split.rb +133 -0
  39. data/lib/deftones/component/one_pole_filter.rb +71 -0
  40. data/lib/deftones/component/pan_vol.rb +26 -0
  41. data/lib/deftones/component/panner.rb +75 -0
  42. data/lib/deftones/component/panner3d.rb +322 -0
  43. data/lib/deftones/component/solo.rb +56 -0
  44. data/lib/deftones/component/split.rb +47 -0
  45. data/lib/deftones/component/volume.rb +31 -0
  46. data/lib/deftones/context.rb +213 -0
  47. data/lib/deftones/core/audio_block.rb +82 -0
  48. data/lib/deftones/core/audio_node.rb +262 -0
  49. data/lib/deftones/core/clock.rb +91 -0
  50. data/lib/deftones/core/computed_signal.rb +69 -0
  51. data/lib/deftones/core/delay.rb +44 -0
  52. data/lib/deftones/core/effect.rb +66 -0
  53. data/lib/deftones/core/emitter.rb +51 -0
  54. data/lib/deftones/core/gain.rb +39 -0
  55. data/lib/deftones/core/instrument.rb +109 -0
  56. data/lib/deftones/core/param.rb +31 -0
  57. data/lib/deftones/core/signal.rb +452 -0
  58. data/lib/deftones/core/signal_operator_methods.rb +73 -0
  59. data/lib/deftones/core/signal_operators.rb +138 -0
  60. data/lib/deftones/core/signal_shapers.rb +83 -0
  61. data/lib/deftones/core/source.rb +213 -0
  62. data/lib/deftones/core/synced_signal.rb +88 -0
  63. data/lib/deftones/destination.rb +132 -0
  64. data/lib/deftones/draw.rb +100 -0
  65. data/lib/deftones/dsp/biquad.rb +129 -0
  66. data/lib/deftones/dsp/delay_line.rb +41 -0
  67. data/lib/deftones/dsp/helpers.rb +25 -0
  68. data/lib/deftones/effect/auto_filter.rb +92 -0
  69. data/lib/deftones/effect/auto_panner.rb +57 -0
  70. data/lib/deftones/effect/auto_wah.rb +98 -0
  71. data/lib/deftones/effect/bit_crusher.rb +38 -0
  72. data/lib/deftones/effect/chebyshev.rb +36 -0
  73. data/lib/deftones/effect/chorus.rb +73 -0
  74. data/lib/deftones/effect/distortion.rb +22 -0
  75. data/lib/deftones/effect/feedback_delay.rb +38 -0
  76. data/lib/deftones/effect/freeverb.rb +11 -0
  77. data/lib/deftones/effect/frequency_shifter.rb +89 -0
  78. data/lib/deftones/effect/jc_reverb.rb +11 -0
  79. data/lib/deftones/effect/modulation_control.rb +159 -0
  80. data/lib/deftones/effect/phaser.rb +72 -0
  81. data/lib/deftones/effect/ping_pong_delay.rb +40 -0
  82. data/lib/deftones/effect/pitch_shift.rb +156 -0
  83. data/lib/deftones/effect/reverb.rb +71 -0
  84. data/lib/deftones/effect/stereo_widener.rb +34 -0
  85. data/lib/deftones/effect/tremolo.rb +52 -0
  86. data/lib/deftones/effect/vibrato.rb +47 -0
  87. data/lib/deftones/event/callback_behavior.rb +61 -0
  88. data/lib/deftones/event/loop.rb +53 -0
  89. data/lib/deftones/event/part.rb +51 -0
  90. data/lib/deftones/event/pattern.rb +94 -0
  91. data/lib/deftones/event/sequence.rb +87 -0
  92. data/lib/deftones/event/tone_event.rb +77 -0
  93. data/lib/deftones/event/transport.rb +276 -0
  94. data/lib/deftones/instrument/am_synth.rb +56 -0
  95. data/lib/deftones/instrument/duo_synth.rb +68 -0
  96. data/lib/deftones/instrument/fm_synth.rb +60 -0
  97. data/lib/deftones/instrument/membrane_synth.rb +60 -0
  98. data/lib/deftones/instrument/metal_synth.rb +61 -0
  99. data/lib/deftones/instrument/mono_synth.rb +88 -0
  100. data/lib/deftones/instrument/noise_synth.rb +56 -0
  101. data/lib/deftones/instrument/pluck_synth.rb +41 -0
  102. data/lib/deftones/instrument/poly_synth.rb +96 -0
  103. data/lib/deftones/instrument/sampler.rb +97 -0
  104. data/lib/deftones/instrument/synth.rb +60 -0
  105. data/lib/deftones/io/buffer.rb +352 -0
  106. data/lib/deftones/io/buffers.rb +77 -0
  107. data/lib/deftones/io/recorder.rb +89 -0
  108. data/lib/deftones/listener.rb +120 -0
  109. data/lib/deftones/music/frequency.rb +128 -0
  110. data/lib/deftones/music/midi.rb +206 -0
  111. data/lib/deftones/music/note.rb +58 -0
  112. data/lib/deftones/music/ticks.rb +106 -0
  113. data/lib/deftones/music/time.rb +209 -0
  114. data/lib/deftones/music/transport_time.rb +94 -0
  115. data/lib/deftones/music/unit_helpers.rb +30 -0
  116. data/lib/deftones/offline_context.rb +46 -0
  117. data/lib/deftones/portaudio_support.rb +112 -0
  118. data/lib/deftones/source/am_oscillator.rb +42 -0
  119. data/lib/deftones/source/fat_oscillator.rb +49 -0
  120. data/lib/deftones/source/fm_oscillator.rb +47 -0
  121. data/lib/deftones/source/grain_player.rb +198 -0
  122. data/lib/deftones/source/karplus_strong.rb +51 -0
  123. data/lib/deftones/source/noise.rb +99 -0
  124. data/lib/deftones/source/omni_oscillator.rb +175 -0
  125. data/lib/deftones/source/oscillator.rb +74 -0
  126. data/lib/deftones/source/player.rb +228 -0
  127. data/lib/deftones/source/players.rb +133 -0
  128. data/lib/deftones/source/pulse_oscillator.rb +38 -0
  129. data/lib/deftones/source/pwm_oscillator.rb +49 -0
  130. data/lib/deftones/source/tone_buffer_source.rb +136 -0
  131. data/lib/deftones/source/tone_oscillator_node.rb +65 -0
  132. data/lib/deftones/source/user_media.rb +519 -0
  133. data/lib/deftones/version.rb +5 -0
  134. data/lib/deftones.rb +542 -0
  135. 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