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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -6
  3. data/README.md +5 -0
  4. data/Rakefile +50 -1
  5. data/lib/deftones/analysis/meter.rb +22 -2
  6. data/lib/deftones/component/channel.rb +1 -1
  7. data/lib/deftones/component/compressor.rb +127 -22
  8. data/lib/deftones/component/filter.rb +29 -19
  9. data/lib/deftones/component/merge.rb +14 -0
  10. data/lib/deftones/component/multiband_compressor.rb +1 -1
  11. data/lib/deftones/component/one_pole_filter.rb +10 -3
  12. data/lib/deftones/component/panner.rb +25 -2
  13. data/lib/deftones/component/panner3d.rb +0 -10
  14. data/lib/deftones/component/split.rb +14 -0
  15. data/lib/deftones/context.rb +90 -9
  16. data/lib/deftones/core/audio_block.rb +64 -5
  17. data/lib/deftones/core/audio_node.rb +98 -8
  18. data/lib/deftones/core/gain.rb +0 -8
  19. data/lib/deftones/core/instrument.rb +52 -10
  20. data/lib/deftones/core/param.rb +51 -1
  21. data/lib/deftones/core/signal.rb +79 -28
  22. data/lib/deftones/core/source.rb +71 -11
  23. data/lib/deftones/destination.rb +41 -17
  24. data/lib/deftones/draw.rb +6 -10
  25. data/lib/deftones/dsp/biquad.rb +9 -4
  26. data/lib/deftones/dsp/delay_line.rb +2 -2
  27. data/lib/deftones/dsp/helpers.rb +7 -0
  28. data/lib/deftones/effect/bit_crusher.rb +10 -2
  29. data/lib/deftones/effect/chebyshev.rb +7 -3
  30. data/lib/deftones/effect/distortion.rb +5 -3
  31. data/lib/deftones/effect/feedback_delay.rb +2 -1
  32. data/lib/deftones/effect/oversampling.rb +43 -0
  33. data/lib/deftones/effect/phaser.rb +2 -1
  34. data/lib/deftones/effect/pitch_shift.rb +1 -2
  35. data/lib/deftones/effect/reverb.rb +73 -5
  36. data/lib/deftones/event/callback_behavior.rb +7 -3
  37. data/lib/deftones/event/loop.rb +7 -2
  38. data/lib/deftones/event/part.rb +18 -3
  39. data/lib/deftones/event/pattern.rb +51 -6
  40. data/lib/deftones/event/sequence.rb +19 -5
  41. data/lib/deftones/event/tone_event.rb +7 -2
  42. data/lib/deftones/event/transport.rb +243 -21
  43. data/lib/deftones/instrument/poly_synth.rb +81 -15
  44. data/lib/deftones/instrument/sampler.rb +53 -10
  45. data/lib/deftones/io/buffer.rb +376 -55
  46. data/lib/deftones/io/buffers.rb +28 -4
  47. data/lib/deftones/io/recorder.rb +2 -1
  48. data/lib/deftones/music/frequency.rb +13 -8
  49. data/lib/deftones/music/midi.rb +132 -9
  50. data/lib/deftones/music/note.rb +13 -3
  51. data/lib/deftones/music/time.rb +42 -4
  52. data/lib/deftones/offline_context.rb +194 -17
  53. data/lib/deftones/portaudio_support.rb +68 -9
  54. data/lib/deftones/source/fat_oscillator.rb +28 -9
  55. data/lib/deftones/source/grain_player.rb +49 -2
  56. data/lib/deftones/source/noise.rb +42 -10
  57. data/lib/deftones/source/omni_oscillator.rb +1 -2
  58. data/lib/deftones/source/oscillator.rb +83 -19
  59. data/lib/deftones/source/player.rb +24 -6
  60. data/lib/deftones/source/players.rb +39 -6
  61. data/lib/deftones/source/tone_buffer_source.rb +12 -6
  62. data/lib/deftones/source/tone_oscillator_node.rb +4 -3
  63. data/lib/deftones/source/user_media.rb +83 -10
  64. data/lib/deftones/version.rb +1 -1
  65. data/lib/deftones.rb +108 -31
  66. metadata +3 -44
@@ -47,15 +47,17 @@ module Deftones
47
47
  def process(_input_buffer, num_frames, start_frame, _cache)
48
48
  rates = @playback_rate.process(num_frames, start_frame)
49
49
  detunes = @detune.process(num_frames, start_frame)
50
- return process_multichannel_buffer(num_frames, start_frame, rates, detunes) if multichannel_process?
50
+ effective_rates = effective_playback_rates(rates, detunes)
51
+ return process_multichannel_buffer(num_frames, start_frame, effective_rates) if multichannel_process?
52
+
53
+ sample_positions = sample_positions_for(num_frames, start_frame, effective_rates)
51
54
 
52
55
  Array.new(num_frames) do |index|
53
56
  current_time = (start_frame + index).to_f / context.sample_rate
54
57
  notify_ended(current_time) if @stop_time && current_time >= @stop_time
55
58
  next 0.0 unless active_at?(current_time)
56
59
 
57
- rate = rates[index] * detune_ratio(detunes[index])
58
- sample_position = sample_position_for(current_time, rate)
60
+ sample_position = sample_positions[index]
59
61
  if sample_position.negative?
60
62
  @stop_time ||= current_time
61
63
  notify_ended(current_time)
@@ -68,16 +70,16 @@ module Deftones
68
70
 
69
71
  private
70
72
 
71
- def process_multichannel_buffer(num_frames, start_frame, rates, detunes)
73
+ def process_multichannel_buffer(num_frames, start_frame, effective_rates)
72
74
  output = Array.new(@buffer.channels) { Array.new(num_frames, 0.0) }
75
+ sample_positions = sample_positions_for(num_frames, start_frame, effective_rates)
73
76
 
74
77
  num_frames.times do |index|
75
78
  current_time = (start_frame + index).to_f / context.sample_rate
76
79
  notify_ended(current_time) if @stop_time && current_time >= @stop_time
77
80
  next unless active_at?(current_time)
78
81
 
79
- rate = rates[index] * detune_ratio(detunes[index])
80
- sample_position = sample_position_for(current_time, rate)
82
+ sample_position = sample_positions[index]
81
83
  if sample_position.negative?
82
84
  @stop_time ||= current_time
83
85
  notify_ended(current_time)
@@ -93,6 +95,10 @@ module Deftones
93
95
  Core::AudioBlock.from_channel_data(output)
94
96
  end
95
97
 
98
+ def effective_playback_rates(rates, detunes)
99
+ rates.each_with_index.map { |rate, index| rate * detune_ratio(detunes[index]) }
100
+ end
101
+
96
102
  def detune_ratio(cents)
97
103
  2.0**(cents.to_f / 1200.0)
98
104
  end
@@ -32,7 +32,7 @@ module Deftones
32
32
  end
33
33
 
34
34
  def process(_input_buffer, num_frames, start_frame, _cache)
35
- generator = GENERATORS.fetch(send(:normalize_type, @type))
35
+ oscillator_type = send(:normalize_type, @type)
36
36
  frequencies = @frequency.process(num_frames, start_frame)
37
37
  detunes = @detune.process(num_frames, start_frame)
38
38
 
@@ -41,9 +41,10 @@ module Deftones
41
41
  notify_ended(current_time) if @stop_time && current_time >= @stop_time
42
42
  next 0.0 unless active_at?(current_time)
43
43
 
44
- sample = generator.call(@phase)
45
44
  frequency = frequencies[index] * detune_ratio(detunes[index])
46
- @phase = (@phase + (frequency / context.sample_rate)) % 1.0
45
+ phase_increment = frequency / context.sample_rate
46
+ sample = sample_for(oscillator_type, @phase, phase_increment)
47
+ @phase = (@phase + phase_increment) % 1.0
47
48
  sample
48
49
  end
49
50
  end
@@ -20,6 +20,9 @@ module Deftones
20
20
  @label = label
21
21
  @channels = normalize_channel_count(channels)
22
22
  @sample_cursor = 0
23
+ @provider_exhausted = false
24
+ @underflow_count = 0
25
+ @overflow_count = 0
23
26
  @opened = false
24
27
  end
25
28
 
@@ -54,6 +57,7 @@ module Deftones
54
57
 
55
58
  def rewind
56
59
  @sample_cursor = 0
60
+ @provider_exhausted = false
57
61
  @provider.rewind if @provider.respond_to?(:rewind)
58
62
  @capture_backend&.rewind if @capture_backend.respond_to?(:rewind)
59
63
  self
@@ -67,11 +71,34 @@ module Deftones
67
71
  @opened
68
72
  end
69
73
 
74
+ def provider_exhausted?
75
+ @provider_exhausted
76
+ end
77
+
78
+ def underflow_count
79
+ @underflow_count + backend_stat(:underflow_count)
80
+ end
81
+
82
+ def overflow_count
83
+ @overflow_count + backend_stat(:overflow_count)
84
+ end
85
+
86
+ def reset_stats
87
+ @underflow_count = 0
88
+ @overflow_count = 0
89
+ @capture_backend.reset_stats if @capture_backend.respond_to?(:reset_stats)
90
+ self
91
+ end
92
+
70
93
  def permission_state
71
94
  self.class.permission_state
72
95
  end
73
96
 
74
97
  alias permissionState permission_state
98
+ alias providerExhausted provider_exhausted?
99
+ alias underflowCount underflow_count
100
+ alias overflowCount overflow_count
101
+ alias resetStats reset_stats
75
102
 
76
103
  def state(time = context.current_time)
77
104
  return :stopped unless @opened
@@ -319,7 +346,7 @@ module Deftones
319
346
  current_time = (start_frame + index).to_f / context.sample_rate
320
347
  next 0.0 unless active_at?(current_time)
321
348
 
322
- @capture_backend.next_sample
349
+ next_capture_sample
323
350
  end
324
351
  end
325
352
 
@@ -347,12 +374,22 @@ module Deftones
347
374
  else
348
375
  @capture_backend.next_sample
349
376
  end
377
+ return mark_capture_frame_underflow! if frame.nil?
350
378
 
351
379
  frame = [frame] unless frame.is_a?(Array)
352
380
  normalized = frame.map(&:to_f)
353
381
  normalized.fill(0.0, normalized.length...capture_channels)
354
382
  end
355
383
 
384
+ def next_capture_sample
385
+ return 0.0 unless @capture_backend
386
+
387
+ sample = @capture_backend.next_sample
388
+ return mark_underflow! if sample.nil?
389
+
390
+ sample.to_f
391
+ end
392
+
356
393
  def next_provider_sample
357
394
  return 0.0 unless @provider
358
395
 
@@ -362,23 +399,48 @@ module Deftones
362
399
  next_enumerator_sample
363
400
  end
364
401
  @sample_cursor += 1
402
+ return mark_underflow! if sample.nil?
403
+
365
404
  sample.to_f
366
405
  end
367
406
 
368
407
  def next_enumerator_sample
369
408
  @provider.next
370
409
  rescue StopIteration
371
- return 0.0 unless @loop && @provider.respond_to?(:rewind)
410
+ return mark_provider_exhausted! unless @loop && @provider.respond_to?(:rewind)
372
411
 
373
- @provider.rewind
374
- @provider.next
375
- rescue StopIteration
412
+ begin
413
+ @provider.rewind
414
+ @provider.next
415
+ rescue StopIteration
416
+ mark_provider_exhausted!
417
+ end
418
+ end
419
+
420
+ def mark_provider_exhausted!
421
+ @provider_exhausted = true
376
422
  @opened = false
423
+ mark_underflow!
424
+ end
425
+
426
+ def mark_underflow!
427
+ @underflow_count += 1
377
428
  0.0
378
429
  end
379
430
 
431
+ def mark_capture_frame_underflow!
432
+ @underflow_count += 1
433
+ Array.new(capture_channels, 0.0)
434
+ end
435
+
436
+ def backend_stat(name)
437
+ return 0 unless @capture_backend.respond_to?(name)
438
+
439
+ @capture_backend.public_send(name).to_i
440
+ end
441
+
380
442
  class PortAudioCapture
381
- attr_reader :channels, :device_id, :group_id, :label
443
+ attr_reader :channels, :device_id, :group_id, :label, :underflow_count, :overflow_count
382
444
 
383
445
  def initialize(sample_rate:, buffer_size:, channels: 1)
384
446
  @sample_rate = sample_rate
@@ -390,6 +452,8 @@ module Deftones
390
452
  @device_id = nil
391
453
  @group_id = nil
392
454
  @label = nil
455
+ @underflow_count = 0
456
+ @overflow_count = 0
393
457
  end
394
458
 
395
459
  def open(device_id: nil, group_id: nil, label: nil, channels: nil)
@@ -420,6 +484,12 @@ module Deftones
420
484
  self
421
485
  end
422
486
 
487
+ def reset_stats
488
+ @underflow_count = 0
489
+ @overflow_count = 0
490
+ self
491
+ end
492
+
423
493
  def close
424
494
  return self unless @stream
425
495
 
@@ -435,13 +505,12 @@ module Deftones
435
505
  def next_sample
436
506
  frame = next_frame
437
507
  frame.sum / [frame.length, 1].max.to_f
438
- rescue ThreadError
439
- 0.0
440
508
  end
441
509
 
442
510
  def next_frame
443
511
  @queue.pop(true)
444
512
  rescue ThreadError
513
+ @underflow_count += 1
445
514
  Array.new(@channels, 0.0)
446
515
  end
447
516
 
@@ -452,7 +521,8 @@ module Deftones
452
521
  input_parameters = Deftones::PortAudioSupport.input_parameters(
453
522
  @channels,
454
523
  device_id: @device_id,
455
- label: @label
524
+ label: @label,
525
+ sample_rate: @sample_rate
456
526
  )
457
527
  assign_device_metadata(input_parameters[:device])
458
528
  @stream = PortAudio::Stream.new(
@@ -503,7 +573,10 @@ module Deftones
503
573
  end
504
574
 
505
575
  def trim_queue!
506
- @queue.pop(true) while @queue.size > @max_frames
576
+ while @queue.size > @max_frames
577
+ @queue.pop(true)
578
+ @overflow_count += 1
579
+ end
507
580
  rescue ThreadError
508
581
  nil
509
582
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Deftones
4
- VERSION = "0.1.0"
4
+ VERSION = "1.0.0"
5
5
  end
data/lib/deftones.rb CHANGED
@@ -1,20 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- begin
4
- require "portaudio"
5
- rescue LoadError
6
- nil
7
- end
3
+ module Deftones
4
+ class Error < StandardError; end
5
+ class MissingRealtimeBackendError < Error; end
6
+ class MissingCodecBackendError < Error; end
7
+ class CodecCommandError < Error
8
+ attr_reader :command, :stdout, :stderr, :status
8
9
 
9
- begin
10
- require "wavify/errors"
11
- require "wavify/core/format"
12
- require "wavify/core/duration"
13
- require "wavify/core/sample_buffer"
14
- require "wavify/codecs/base"
15
- require "wavify/codecs/wav"
16
- rescue LoadError
17
- nil
10
+ def initialize(message, command:, stdout:, stderr:, status:)
11
+ super(message)
12
+ @command = command
13
+ @stdout = stdout
14
+ @stderr = stderr
15
+ @status = status
16
+ end
17
+ end
18
+ class MissingMidiBackendError < Error; end
19
+ class UnsupportedAudioFormatError < Error; end
20
+ class InvalidNoteError < ArgumentError; end
21
+ class InvalidFrequencyError < ArgumentError; end
22
+ class InvalidTimeError < ArgumentError; end
18
23
  end
19
24
 
20
25
  require_relative "deftones/version"
@@ -111,6 +116,7 @@ require_relative "deftones/analysis/analyser"
111
116
  require_relative "deftones/analysis/meter"
112
117
  require_relative "deftones/analysis/dc_meter"
113
118
  require_relative "deftones/effect/modulation_control"
119
+ require_relative "deftones/effect/oversampling"
114
120
  require_relative "deftones/effect/distortion"
115
121
  require_relative "deftones/effect/bit_crusher"
116
122
  require_relative "deftones/effect/chebyshev"
@@ -142,9 +148,6 @@ require_relative "deftones/instrument/sampler"
142
148
  require_relative "deftones/instrument/poly_synth"
143
149
 
144
150
  module Deftones
145
- class Error < StandardError; end
146
- class MissingRealtimeBackendError < Error; end
147
-
148
151
  class << self
149
152
  def context
150
153
  @context ||= Context.new
@@ -208,31 +211,41 @@ module Deftones
208
211
  end
209
212
 
210
213
  def render(duration:, sample_rate: Context::DEFAULT_SAMPLE_RATE, channels: 2,
211
- buffer_size: Context::DEFAULT_BUFFER_SIZE, &block)
214
+ buffer_size: Context::DEFAULT_BUFFER_SIZE, seed: nil, metadata: false,
215
+ progress: nil, cancel: nil, &block)
212
216
  ctx = OfflineContext.new(
213
217
  duration: duration,
214
218
  sample_rate: sample_rate,
215
219
  channels: channels,
216
220
  buffer_size: buffer_size
217
221
  )
218
- block&.call(ctx)
219
- ctx.render
222
+ with_random_seed(seed) do
223
+ block&.call(ctx)
224
+ ctx.render(metadata: metadata, progress: progress, cancel: cancel)
225
+ end
220
226
  end
221
227
 
222
228
  def offline(duration:, sample_rate: Context::DEFAULT_SAMPLE_RATE, channels: 2,
223
- buffer_size: Context::DEFAULT_BUFFER_SIZE, &block)
224
- render(duration: duration, sample_rate: sample_rate, channels: channels, buffer_size: buffer_size, &block)
229
+ buffer_size: Context::DEFAULT_BUFFER_SIZE, **render_options, &block)
230
+ render(duration: duration, sample_rate: sample_rate, channels: channels, buffer_size: buffer_size,
231
+ **render_options, &block)
225
232
  end
226
233
 
227
234
  def Offline(duration:, sample_rate: Context::DEFAULT_SAMPLE_RATE, channels: 2,
228
- buffer_size: Context::DEFAULT_BUFFER_SIZE, &block)
229
- offline(duration: duration, sample_rate: sample_rate, channels: channels, buffer_size: buffer_size, &block)
235
+ buffer_size: Context::DEFAULT_BUFFER_SIZE, **render_options, &block)
236
+ offline(duration: duration, sample_rate: sample_rate, channels: channels, buffer_size: buffer_size,
237
+ **render_options, &block)
230
238
  end
231
239
 
232
- def render_to_file(path, duration:, format: nil, **options, &block)
233
- ctx = OfflineContext.new(duration: duration, **options)
234
- block&.call(ctx)
235
- ctx.render_to_file(path, format: format)
240
+ def render_to_file(path, duration:, format: nil, streaming: false, **options, &block)
241
+ file_options = options.slice(:bit_depth, :dither, :dither_rng)
242
+ render_options = options.slice(:seed, :metadata, :progress, :cancel)
243
+ context_options = options.reject { |key, _| render_options.key?(key) || file_options.key?(key) }
244
+ ctx = OfflineContext.new(duration: duration, **context_options)
245
+ with_random_seed(render_options.delete(:seed)) do
246
+ block&.call(ctx)
247
+ ctx.render_to_file(path, format: format, streaming: streaming, **file_options, **render_options)
248
+ end
236
249
  end
237
250
 
238
251
  def loaded
@@ -261,11 +274,47 @@ module Deftones
261
274
  end
262
275
 
263
276
  def wavify_available?
264
- !!defined?(Wavify::Core::SampleBuffer) && !!defined?(Wavify::Codecs::Wav)
277
+ load_wavify!
265
278
  end
266
279
 
267
- def supported?
268
- true
280
+ def midi_available?
281
+ Deftones::Music::Midi.available?
282
+ end
283
+
284
+ def compressed_audio_available?
285
+ Deftones::IO::Buffer.compressed_audio_available?
286
+ end
287
+
288
+ def capabilities
289
+ {
290
+ offline: true,
291
+ wav: wavify_available?,
292
+ compressed_audio: compressed_audio_available?,
293
+ realtime: portaudio_available?,
294
+ midi: midi_available?
295
+ }
296
+ end
297
+
298
+ def supported?(feature = nil)
299
+ return true if feature.nil?
300
+
301
+ normalized = feature.to_sym
302
+ available = capabilities
303
+ raise ArgumentError, "Unknown capability: #{feature}" unless available.key?(normalized)
304
+
305
+ available.fetch(normalized)
306
+ end
307
+
308
+ def feature_supported?(feature)
309
+ supported?(feature)
310
+ end
311
+
312
+ def supported_features
313
+ capabilities.select { |_feature, supported| supported }.keys
314
+ end
315
+
316
+ def unsupported_features
317
+ capabilities.reject { |_feature, supported| supported }.keys
269
318
  end
270
319
 
271
320
  def connect_series(*nodes)
@@ -381,8 +430,36 @@ module Deftones
381
430
  Music::TransportTime.new(value, transport: transport)
382
431
  end
383
432
 
433
+ def with_random_seed(seed)
434
+ return yield if seed.nil?
435
+
436
+ previous_seed = srand(seed)
437
+ yield
438
+ ensure
439
+ srand(previous_seed) unless seed.nil?
440
+ end
441
+
442
+ def load_wavify!
443
+ return true if defined?(Wavify::Core::SampleBuffer) && defined?(Wavify::Codecs::Wav)
444
+
445
+ require "wavify/errors"
446
+ require "wavify/core/format"
447
+ require "wavify/core/duration"
448
+ require "wavify/core/sample_buffer"
449
+ require "wavify/codecs/base"
450
+ require "wavify/codecs/wav"
451
+ true
452
+ rescue LoadError
453
+ false
454
+ end
455
+
384
456
  alias wavefile_available? wavify_available?
457
+ alias compressedAudioAvailable compressed_audio_available?
458
+ alias midi_available midi_available?
385
459
  alias supported supported?
460
+ alias featureSupported feature_supported?
461
+ alias supportedFeatures supported_features
462
+ alias unsupportedFeatures unsupported_features
386
463
  alias dbToGain db_to_gain
387
464
  alias gainToDb gain_to_db
388
465
  alias getContext get_context
metadata CHANGED
@@ -1,56 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deftones
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yudai Takada
8
8
  bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
- dependencies:
12
- - !ruby/object:Gem::Dependency
13
- name: portaudio
14
- requirement: !ruby/object:Gem::Requirement
15
- requirements:
16
- - - ">="
17
- - !ruby/object:Gem::Version
18
- version: '0'
19
- type: :runtime
20
- prerelease: false
21
- version_requirements: !ruby/object:Gem::Requirement
22
- requirements:
23
- - - ">="
24
- - !ruby/object:Gem::Version
25
- version: '0'
26
- - !ruby/object:Gem::Dependency
27
- name: wavify
28
- requirement: !ruby/object:Gem::Requirement
29
- requirements:
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: '0'
33
- type: :runtime
34
- prerelease: false
35
- version_requirements: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: '0'
40
- - !ruby/object:Gem::Dependency
41
- name: unimidi
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: '0'
47
- type: :runtime
48
- prerelease: false
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: '0'
11
+ dependencies: []
54
12
  description: Deftones provides a flexible node graph, synth voices, effects, transport
55
13
  scheduling, sample playback, analysis, and offline or realtime audio hooks.
56
14
  email:
@@ -138,6 +96,7 @@ files:
138
96
  - lib/deftones/effect/frequency_shifter.rb
139
97
  - lib/deftones/effect/jc_reverb.rb
140
98
  - lib/deftones/effect/modulation_control.rb
99
+ - lib/deftones/effect/oversampling.rb
141
100
  - lib/deftones/effect/phaser.rb
142
101
  - lib/deftones/effect/ping_pong_delay.rb
143
102
  - lib/deftones/effect/pitch_shift.rb