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,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deftones
4
+ module Core
5
+ class Instrument < AudioNode
6
+ class VolumeProxy
7
+ attr_reader :instrument
8
+ attr_accessor :value
9
+
10
+ def initialize(instrument, value: 0.0)
11
+ @instrument = instrument
12
+ @value = value.to_f
13
+ end
14
+
15
+ def value=(new_value)
16
+ @value = new_value.to_f
17
+ instrument.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 :output, :volume
30
+ attr_accessor :mute
31
+
32
+ def initialize(context: Deftones.context)
33
+ super(context: context)
34
+ @output = Gain.new(context: context, gain: 1.0)
35
+ @volume = VolumeProxy.new(self)
36
+ @mute = false
37
+ apply_volume!
38
+ end
39
+
40
+ def input
41
+ @output
42
+ end
43
+
44
+ def render(num_frames, start_frame = 0, cache = {})
45
+ @output.render(num_frames, start_frame, cache)
46
+ end
47
+
48
+ def render_block(num_frames, start_frame = 0, cache = {})
49
+ @output.send(:render_block, num_frames, start_frame, cache)
50
+ end
51
+
52
+ def mute=(value)
53
+ @mute = !!value
54
+ apply_volume!
55
+ end
56
+
57
+ def mute?
58
+ @mute
59
+ end
60
+
61
+ def set(**params)
62
+ params.each do |key, value|
63
+ writer = :"#{key}="
64
+ public_send(writer, value) if respond_to?(writer)
65
+ end
66
+ self
67
+ end
68
+
69
+ def get(*keys)
70
+ requested = keys.flatten
71
+ requested.each_with_object({}) do |key, values|
72
+ reader = key.to_sym
73
+ values[reader] = public_send(reader) if respond_to?(reader)
74
+ end
75
+ end
76
+
77
+ def release_all(time = nil)
78
+ trigger_release(time) if respond_to?(:trigger_release)
79
+ self
80
+ end
81
+
82
+ def dispose
83
+ @output.dispose
84
+ super
85
+ end
86
+
87
+ def triggerAttack(*arguments)
88
+ trigger_attack(*arguments)
89
+ end
90
+
91
+ def triggerRelease(*arguments)
92
+ trigger_release(*arguments)
93
+ end
94
+
95
+ def triggerAttackRelease(*arguments)
96
+ trigger_attack_release(*arguments)
97
+ end
98
+
99
+ def releaseAll(time = nil)
100
+ release_all(time)
101
+ end
102
+
103
+ def apply_volume!
104
+ @output.gain.value = mute ? 0.0 : Deftones.db_to_gain(@volume.value)
105
+ self
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deftones
4
+ module Core
5
+ class Param < Signal
6
+ attr_reader :lfo
7
+
8
+ def initialize(**options)
9
+ super
10
+ @lfo = nil
11
+ end
12
+
13
+ def set_param(param)
14
+ @param = param
15
+ self
16
+ end
17
+
18
+ def connect(destination, output_index: 0, input_index: 0)
19
+ super
20
+ @param = destination if destination.respond_to?(:value=)
21
+ self
22
+ end
23
+
24
+ def lfo=(source)
25
+ @lfo = source
26
+ end
27
+
28
+ alias setParam set_param
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,452 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deftones
4
+ module Core
5
+ class Signal
6
+ EXPONENTIAL_UNITS = %i[frequency decibels].freeze
7
+
8
+ include SignalOperatorMethods
9
+
10
+ attr_reader :context, :units, :input, :output, :default_value
11
+ attr_accessor :min_value, :max_value, :convert_values
12
+
13
+ def initialize(value: 0.0, units: :number, context: Deftones.context)
14
+ @context = context
15
+ @units = units
16
+ @input = self
17
+ @output = self
18
+ @convert_values = true
19
+ @base_value = coerce_value(value)
20
+ @default_value = @base_value
21
+ @min_value = -Float::INFINITY
22
+ @max_value = Float::INFINITY
23
+ @events = []
24
+ @disposed = false
25
+ end
26
+
27
+ def value
28
+ @base_value
29
+ end
30
+
31
+ def value=(new_value)
32
+ @base_value = coerce_value(new_value)
33
+ @events.clear
34
+ end
35
+
36
+ def apply(value)
37
+ self.value = value.respond_to?(:value_of) ? value.value_of : value
38
+ self
39
+ end
40
+
41
+ def ramp_to(target_value, duration)
42
+ if EXPONENTIAL_UNITS.include?(@units)
43
+ exponential_ramp_to(target_value, duration)
44
+ else
45
+ linear_ramp_to(target_value, duration)
46
+ end
47
+ end
48
+
49
+ def linear_ramp_to(target_value, duration)
50
+ resolved_end = context.current_time + Deftones::Music::Time.parse(duration)
51
+ schedule_automation(
52
+ :linear,
53
+ coerce_value(target_value),
54
+ start_time: resolve_automation_start_time(resolved_end),
55
+ end_time: resolved_end
56
+ )
57
+ end
58
+
59
+ def linear_ramp_to_value_at_time(target_value, end_time)
60
+ resolved_end = resolve_time(end_time)
61
+ schedule_automation(
62
+ :linear,
63
+ coerce_value(target_value),
64
+ start_time: resolve_automation_start_time(resolved_end),
65
+ end_time: resolved_end
66
+ )
67
+ end
68
+
69
+ def exponential_ramp_to(target_value, duration)
70
+ resolved_end = context.current_time + Deftones::Music::Time.parse(duration)
71
+ schedule_automation(
72
+ :exponential,
73
+ coerce_value(target_value),
74
+ start_time: resolve_automation_start_time(resolved_end),
75
+ end_time: resolved_end
76
+ )
77
+ end
78
+
79
+ def exponential_ramp_to_value_at_time(target_value, end_time)
80
+ resolved_end = resolve_time(end_time)
81
+ schedule_automation(
82
+ :exponential,
83
+ coerce_value(target_value),
84
+ start_time: resolve_automation_start_time(resolved_end),
85
+ end_time: resolved_end
86
+ )
87
+ end
88
+
89
+ def set_value_at_time(target_value, time)
90
+ @events << { type: :set, time: resolve_time(time), value: coerce_value(target_value) }
91
+ sort_events!
92
+ self
93
+ end
94
+
95
+ def set_value_curve_at_time(values, start_time, duration)
96
+ curve = Array(values).map { |value| coerce_value(value) }
97
+ resolved_start = resolve_time(start_time)
98
+ resolved_duration = Deftones::Music::Time.parse(duration)
99
+ @events << {
100
+ type: :curve,
101
+ time: resolved_start,
102
+ start_time: resolved_start,
103
+ end_time: resolved_start + resolved_duration,
104
+ duration: resolved_duration,
105
+ values: curve
106
+ }
107
+ sort_events!
108
+ self
109
+ end
110
+
111
+ def set_target_at_time(target_value, start_time, time_constant)
112
+ resolved_start = resolve_time(start_time)
113
+ @events << {
114
+ type: :target,
115
+ time: resolved_start,
116
+ start_time: resolved_start,
117
+ time_constant: [Deftones::Music::Time.parse(time_constant), 1.0e-6].max,
118
+ from: value_at(resolved_start),
119
+ to: coerce_value(target_value)
120
+ }
121
+ sort_events!
122
+ self
123
+ end
124
+
125
+ def target_ramp_to(target_value, duration, start_time = context.current_time)
126
+ resolved_start = resolve_time(start_time)
127
+ resolved_duration = Deftones::Music::Time.parse(duration)
128
+ set_target_at_time(target_value, resolved_start, [resolved_duration / 5.0, 1.0e-6].max)
129
+ set_value_at_time(target_value, resolved_start + resolved_duration)
130
+ end
131
+
132
+ def cancel_scheduled_values(after_time = 0)
133
+ threshold = resolve_time(after_time)
134
+ @events.reject! do |event|
135
+ event.fetch(:time, event[:start_time]) >= threshold
136
+ end
137
+ self
138
+ end
139
+
140
+ def cancel_and_hold_at_time(time)
141
+ held_time = resolve_time(time)
142
+ held_value = value_at(held_time)
143
+ cancel_scheduled_values(held_time)
144
+ set_value_at_time(held_value, held_time)
145
+ end
146
+
147
+ def set_ramp_point(time = context.current_time)
148
+ cancel_and_hold_at_time(time)
149
+ end
150
+
151
+ def get_value_at_time(time)
152
+ value_at(resolve_time(time))
153
+ end
154
+
155
+ def dispose
156
+ @events.clear
157
+ @disposed = true
158
+ self
159
+ end
160
+
161
+ def disposed?
162
+ @disposed
163
+ end
164
+
165
+ alias linearRampToValueAtTime linear_ramp_to_value_at_time
166
+ alias exponentialRampToValueAtTime exponential_ramp_to_value_at_time
167
+ alias setValueAtTime set_value_at_time
168
+ alias setValueCurveAtTime set_value_curve_at_time
169
+ alias setTargetAtTime set_target_at_time
170
+ alias targetRampTo target_ramp_to
171
+ alias cancelScheduledValues cancel_scheduled_values
172
+ alias cancelAndHoldAtTime cancel_and_hold_at_time
173
+ alias setRampPoint set_ramp_point
174
+ alias getValueAtTime get_value_at_time
175
+
176
+ def connect(destination, output_index: 0, input_index: 0)
177
+ _ = output_index
178
+ _ = input_index
179
+ return self if destination.nil?
180
+
181
+ if destination.respond_to?(:value=)
182
+ destination.value = value
183
+ elsif destination.respond_to?(:apply)
184
+ destination.apply(self)
185
+ end
186
+ self
187
+ end
188
+
189
+ def disconnect(_destination = nil)
190
+ self
191
+ end
192
+
193
+ def set(**params)
194
+ params.each do |key, entry|
195
+ writer = :"#{key}="
196
+ public_send(writer, entry) if respond_to?(writer)
197
+ end
198
+ self
199
+ end
200
+
201
+ def get(*keys)
202
+ keys.flatten.each_with_object({}) do |key, values|
203
+ reader = key.to_sym
204
+ values[reader] = public_send(reader) if respond_to?(reader)
205
+ end
206
+ end
207
+
208
+ def get_defaults
209
+ {
210
+ value: default_value,
211
+ units: units
212
+ }
213
+ end
214
+
215
+ def now
216
+ context.current_time
217
+ end
218
+
219
+ def immediate
220
+ now
221
+ end
222
+
223
+ def to_seconds(time = value)
224
+ Deftones::Music::Time.parse(time)
225
+ end
226
+
227
+ def to_ticks(time = value)
228
+ Deftones.transport.seconds_to_ticks(to_seconds(time))
229
+ end
230
+
231
+ def to_frequency(entry = value)
232
+ Deftones::Music::Frequency.parse(entry)
233
+ end
234
+
235
+ def overridden?
236
+ false
237
+ end
238
+
239
+ def name
240
+ self.class.name.split("::").last
241
+ end
242
+
243
+ def to_s
244
+ name
245
+ end
246
+
247
+ def exponential_approach_value_at_time(target_value, start_time, ramp_time)
248
+ target_ramp_to(target_value, ramp_time, start_time)
249
+ end
250
+
251
+ alias minValue min_value
252
+ alias minValue= min_value=
253
+ alias maxValue max_value
254
+ alias maxValue= max_value=
255
+ alias defaultValue default_value
256
+ alias getDefaults get_defaults
257
+ alias toSeconds to_seconds
258
+ alias toTicks to_ticks
259
+ alias toFrequency to_frequency
260
+ alias toString to_s
261
+ alias exponentialApproachValueAtTime exponential_approach_value_at_time
262
+
263
+ def process(num_frames, start_frame = 0)
264
+ Array.new(num_frames) do |offset|
265
+ value_at(sample_time(start_frame + offset))
266
+ end
267
+ end
268
+
269
+ def value_at(time)
270
+ current_value = @base_value
271
+
272
+ @events.each do |event|
273
+ case event[:type]
274
+ when :set
275
+ break if time < event[:time]
276
+
277
+ current_value = event[:value]
278
+ when :linear, :exponential
279
+ break if time < event[:start_time]
280
+
281
+ if time >= event[:end_time]
282
+ current_value = event[:to]
283
+ next
284
+ end
285
+
286
+ current_value = interpolate(event, (time - event[:start_time]) / event[:duration])
287
+ when :curve
288
+ break if time < event[:start_time]
289
+
290
+ if time >= event[:end_time]
291
+ current_value = event[:values].last || current_value
292
+ next
293
+ end
294
+
295
+ current_value = curve_value(event, time)
296
+ when :target
297
+ break if time < event[:start_time]
298
+
299
+ current_value = target_value(event, time)
300
+ end
301
+ end
302
+
303
+ current_value
304
+ end
305
+
306
+ private
307
+
308
+ def schedule_automation(type, target_value, start_time:, end_time:)
309
+ duration_in_seconds = [end_time.to_f - start_time.to_f, 0.0].max
310
+ @events << {
311
+ type: type,
312
+ start_time: start_time,
313
+ end_time: end_time,
314
+ time: start_time,
315
+ duration: duration_in_seconds,
316
+ from: value_at(start_time),
317
+ to: target_value
318
+ }
319
+ sort_events!
320
+ self
321
+ end
322
+
323
+ def sort_events!
324
+ @events.sort_by! { |event| event.fetch(:time, event[:start_time]) }
325
+ end
326
+
327
+ def resolve_automation_start_time(end_time)
328
+ anchors = @events.filter_map do |event|
329
+ anchor = automation_anchor_time(event)
330
+ anchor if anchor <= end_time
331
+ end
332
+
333
+ anchors.max || context.current_time
334
+ end
335
+
336
+ def automation_anchor_time(event)
337
+ case event[:type]
338
+ when :linear, :exponential, :curve
339
+ event[:end_time]
340
+ else
341
+ event.fetch(:time, event[:start_time])
342
+ end
343
+ end
344
+
345
+ def interpolate(event, progress)
346
+ return event[:to] if event[:duration].zero?
347
+
348
+ bounded_progress = progress.clamp(0.0, 1.0)
349
+ case event[:type]
350
+ when :linear
351
+ event[:from] + ((event[:to] - event[:from]) * bounded_progress)
352
+ when :exponential
353
+ from = safe_exponential_value(event[:from])
354
+ to = safe_exponential_value(event[:to])
355
+ from * ((to / from)**bounded_progress)
356
+ else
357
+ event[:to]
358
+ end
359
+ end
360
+
361
+ def curve_value(event, time)
362
+ values = event[:values]
363
+ return values.first if values.length <= 1
364
+
365
+ progress = ((time - event[:start_time]) / event[:duration]).clamp(0.0, 1.0)
366
+ scaled_index = progress * (values.length - 1)
367
+ lower_index = scaled_index.floor
368
+ upper_index = [lower_index + 1, values.length - 1].min
369
+ fraction = scaled_index - lower_index
370
+ lower = values[lower_index]
371
+ upper = values[upper_index]
372
+ lower + ((upper - lower) * fraction)
373
+ end
374
+
375
+ def target_value(event, time)
376
+ elapsed = [time - event[:start_time], 0.0].max
377
+ event[:to] + ((event[:from] - event[:to]) * Math.exp(-(elapsed / event[:time_constant])))
378
+ end
379
+
380
+ def safe_exponential_value(value)
381
+ magnitude = value.abs < 1.0e-6 ? 1.0e-6 : value.abs
382
+ value.negative? ? -magnitude : magnitude
383
+ end
384
+
385
+ def sample_time(frame_index)
386
+ frame_index.to_f / context.sample_rate
387
+ end
388
+
389
+ def resolve_time(time)
390
+ return context.current_time if time.nil?
391
+
392
+ Deftones::Music::Time.parse(time)
393
+ end
394
+
395
+ public
396
+
397
+ def convert
398
+ @convert_values
399
+ end
400
+
401
+ def convert=(value)
402
+ @convert_values = !!value
403
+ end
404
+
405
+ private
406
+
407
+ def coerce_value(value)
408
+ return convert_without_units(value) unless @convert_values
409
+
410
+ case @units
411
+ when :frequency
412
+ convert_frequency(value)
413
+ when :time
414
+ Deftones::Music::Time.parse(value)
415
+ when :decibels
416
+ db_to_gain(value.to_f)
417
+ else
418
+ convert_generic(value)
419
+ end
420
+ end
421
+
422
+ def convert_without_units(value)
423
+ return value.value_of if value.respond_to?(:value_of)
424
+ return value.to_f if value.is_a?(Numeric) || value.respond_to?(:to_f)
425
+
426
+ value
427
+ end
428
+
429
+ def convert_frequency(value)
430
+ return value.to_f if value.is_a?(Numeric)
431
+
432
+ string_value = value.to_s
433
+ return Regexp.last_match(1).to_f if string_value.match(/\A(\d+(?:\.\d+)?)hz\z/i)
434
+
435
+ Deftones::Music::Note.to_frequency(string_value)
436
+ end
437
+
438
+ def convert_generic(value)
439
+ string_value = value.to_s
440
+ if string_value.match?(/\A[A-Ga-g][#b]?-?\d+\z/)
441
+ Deftones::Music::Note.to_frequency(string_value)
442
+ else
443
+ value.to_f
444
+ end
445
+ end
446
+
447
+ def db_to_gain(value)
448
+ 10.0**(value / 20.0)
449
+ end
450
+ end
451
+ end
452
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deftones
4
+ module Core
5
+ module SignalOperatorMethods
6
+ def add(value)
7
+ Add.new(input: self, addend: value, context: context)
8
+ end
9
+
10
+ def subtract(value)
11
+ Subtract.new(input: self, subtrahend: value, context: context)
12
+ end
13
+
14
+ def multiply(value)
15
+ Multiply.new(input: self, factor: value, context: context)
16
+ end
17
+
18
+ def negate
19
+ Negate.new(input: self, context: context)
20
+ end
21
+
22
+ def abs
23
+ Abs.new(input: self, context: context)
24
+ end
25
+
26
+ def equal_power_gain
27
+ EqualPowerGain.new(input: self, context: context)
28
+ end
29
+
30
+ def greater_than(value)
31
+ GreaterThan.new(input: self, threshold: value, context: context)
32
+ end
33
+
34
+ def greater_than_zero
35
+ GreaterThanZero.new(input: self, context: context)
36
+ end
37
+
38
+ def modulo(value)
39
+ Modulo.new(input: self, modulus: value, context: context)
40
+ end
41
+
42
+ def normalize(min, max)
43
+ Normalize.new(input: self, min: min, max: max, context: context)
44
+ end
45
+
46
+ def scale(min, max)
47
+ Scale.new(input: self, min: min, max: max, context: context)
48
+ end
49
+
50
+ def scale_exp(min, max, exponent: 2.0)
51
+ ScaleExp.new(input: self, min: min, max: max, exponent: exponent, context: context)
52
+ end
53
+
54
+ def pow(exponent)
55
+ Pow.new(input: self, exponent: exponent, context: context)
56
+ end
57
+
58
+ def wave_shaper(curve = nil, mapping: nil, &block)
59
+ WaveShaper.new(input: self, curve: curve, mapping: mapping, context: context, &block)
60
+ end
61
+
62
+ alias waveshaper wave_shaper
63
+
64
+ def to_audio
65
+ GainToAudio.new(input: self, context: context)
66
+ end
67
+
68
+ def to_gain
69
+ AudioToGain.new(input: self, context: context)
70
+ end
71
+ end
72
+ end
73
+ end