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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deftones
4
+ module Component
5
+ class Mono < Core::AudioNode
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deftones
4
+ module Component
5
+ class MultibandCompressor < Core::AudioNode
6
+ attr_reader :high, :high_frequency, :input, :low, :low_frequency, :mid, :output, :q, :split
7
+
8
+ def initialize(low_frequency: 400.0, high_frequency: 2_500.0, q: 1.0, low: {}, mid: {}, high: {},
9
+ context: Deftones.context)
10
+ super(context: context)
11
+ @split = MultibandSplit.new(
12
+ low_frequency: low_frequency,
13
+ high_frequency: high_frequency,
14
+ q: q,
15
+ context: context
16
+ )
17
+ @input = @split.input
18
+ @output = self
19
+ @low = Compressor.new(context: context, **compressor_options(low))
20
+ @mid = Compressor.new(context: context, **compressor_options(mid))
21
+ @high = Compressor.new(context: context, **compressor_options(high))
22
+ @split.low >> @low
23
+ @split.mid >> @mid
24
+ @split.high >> @high
25
+ end
26
+
27
+ def low_frequency
28
+ @split.low_frequency
29
+ end
30
+
31
+ def high_frequency
32
+ @split.high_frequency
33
+ end
34
+
35
+ def q
36
+ @split.q
37
+ end
38
+
39
+ def render(num_frames, start_frame = 0, cache = {})
40
+ render_block(num_frames, start_frame, cache).mono
41
+ end
42
+
43
+ def render_block(num_frames, start_frame = 0, cache = {})
44
+ cache_key = [object_id, start_frame, num_frames]
45
+ return cache.fetch(cache_key).dup if cache.key?(cache_key)
46
+
47
+ low_buffer = @low.send(:render_block, num_frames, start_frame, cache)
48
+ mid_buffer = @mid.send(:render_block, num_frames, start_frame, cache)
49
+ high_buffer = @high.send(:render_block, num_frames, start_frame, cache)
50
+ channels = [low_buffer.channels, mid_buffer.channels, high_buffer.channels].max
51
+ output_buffer = Core::AudioBlock.silent(num_frames, channels)
52
+ output_buffer.mix!(low_buffer).mix!(mid_buffer).mix!(high_buffer)
53
+
54
+ cache[cache_key] = output_buffer
55
+ output_buffer.dup
56
+ end
57
+
58
+ private
59
+
60
+ def compressor_options(options)
61
+ {
62
+ threshold: options.fetch(:threshold, -24.0),
63
+ ratio: options.fetch(:ratio, 3.0),
64
+ attack: options.fetch(:attack, 0.01),
65
+ release: options.fetch(:release, 0.1)
66
+ }
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deftones
4
+ module Component
5
+ class MultibandSplit < Core::AudioNode
6
+ attr_reader :input, :high, :high_frequency, :low, :low_frequency, :mid, :output, :q
7
+
8
+ def initialize(low_frequency: 400.0, high_frequency: 2_500.0, q: 1.0, context: Deftones.context)
9
+ super(context: context)
10
+ @input = Core::Gain.new(context: context)
11
+ @output = self
12
+ @low_frequency = Core::Signal.new(value: low_frequency, units: :frequency, context: context)
13
+ @high_frequency = Core::Signal.new(value: high_frequency, units: :frequency, context: context)
14
+ @q = Core::Signal.new(value: q, units: :number, context: context)
15
+ @low = OutputTap.new(parent: self, band: :low, context: context)
16
+ @mid = OutputTap.new(parent: self, band: :mid, context: context)
17
+ @high = OutputTap.new(parent: self, band: :high, context: context)
18
+ @low_filters = []
19
+ @mid_highpasses = []
20
+ @mid_lowpasses = []
21
+ @high_filters = []
22
+ end
23
+
24
+ def render(num_frames, start_frame = 0, cache = {})
25
+ render_block(num_frames, start_frame, cache).mono
26
+ end
27
+
28
+ def render_band(band, num_frames, start_frame = 0, cache = {})
29
+ render_band_block(band, num_frames, start_frame, cache).mono
30
+ end
31
+
32
+ def render_block(num_frames, start_frame = 0, cache = {})
33
+ cache_key = [object_id, :block, start_frame, num_frames]
34
+ return cache.fetch(cache_key).dup if cache.key?(cache_key)
35
+
36
+ bands = render_bands_block(num_frames, start_frame, cache)
37
+ channels = bands[:low].channels
38
+ output = Core::AudioBlock.silent(num_frames, channels)
39
+ output.mix!(bands[:low]).mix!(bands[:mid]).mix!(bands[:high])
40
+
41
+ cache[cache_key] = output
42
+ output.dup
43
+ end
44
+
45
+ def render_band_block(band, num_frames, start_frame = 0, cache = {})
46
+ render_bands_block(num_frames, start_frame, cache).fetch(band).dup
47
+ end
48
+
49
+ def reset!
50
+ [@low_filters, @mid_highpasses, @mid_lowpasses, @high_filters].each do |filters|
51
+ filters.each(&:reset!)
52
+ end
53
+ self
54
+ end
55
+
56
+ private
57
+
58
+ def render_bands_block(num_frames, start_frame, cache)
59
+ cache_key = [object_id, :bands_block, start_frame, num_frames]
60
+ return cache.fetch(cache_key) if cache.key?(cache_key)
61
+
62
+ input_block = @input.send(:render_block, num_frames, start_frame, cache)
63
+ update_filters(input_block.channels, start_frame)
64
+
65
+ low = Array.new(input_block.channels) { Array.new(num_frames, 0.0) }
66
+ mid = Array.new(input_block.channels) { Array.new(num_frames, 0.0) }
67
+ high = Array.new(input_block.channels) { Array.new(num_frames, 0.0) }
68
+
69
+ input_block.channel_data.each_with_index do |channel, channel_index|
70
+ num_frames.times do |index|
71
+ sample = channel[index]
72
+ low[channel_index][index] = @low_filters[channel_index].process_sample(sample)
73
+ mid[channel_index][index] =
74
+ @mid_lowpasses[channel_index].process_sample(@mid_highpasses[channel_index].process_sample(sample))
75
+ high[channel_index][index] = @high_filters[channel_index].process_sample(sample)
76
+ end
77
+ end
78
+
79
+ cache[cache_key] = {
80
+ low: Core::AudioBlock.from_channel_data(low),
81
+ mid: Core::AudioBlock.from_channel_data(mid),
82
+ high: Core::AudioBlock.from_channel_data(high)
83
+ }
84
+ end
85
+
86
+ def update_filters(channels, start_frame)
87
+ ensure_filter_banks(channels)
88
+ current_low_frequency = @low_frequency.process(1, start_frame).first
89
+ current_high_frequency = @high_frequency.process(1, start_frame).first
90
+ current_q = @q.process(1, start_frame).first
91
+
92
+ @low_filters.each do |filter|
93
+ filter.update(type: :lowpass, frequency: current_low_frequency, q: current_q, gain_db: 0.0, sample_rate: context.sample_rate)
94
+ end
95
+ @mid_highpasses.each do |filter|
96
+ filter.update(type: :highpass, frequency: current_low_frequency, q: current_q, gain_db: 0.0, sample_rate: context.sample_rate)
97
+ end
98
+ @mid_lowpasses.each do |filter|
99
+ filter.update(type: :lowpass, frequency: current_high_frequency, q: current_q, gain_db: 0.0, sample_rate: context.sample_rate)
100
+ end
101
+ @high_filters.each do |filter|
102
+ filter.update(type: :highpass, frequency: current_high_frequency, q: current_q, gain_db: 0.0, sample_rate: context.sample_rate)
103
+ end
104
+ end
105
+
106
+ def ensure_filter_banks(channels)
107
+ required = [channels.to_i, 1].max
108
+ while @low_filters.length < required
109
+ @low_filters << DSP::Biquad.new
110
+ @mid_highpasses << DSP::Biquad.new
111
+ @mid_lowpasses << DSP::Biquad.new
112
+ @high_filters << DSP::Biquad.new
113
+ end
114
+ end
115
+
116
+ class OutputTap < Core::AudioNode
117
+ def initialize(parent:, band:, context: Deftones.context)
118
+ super(context: context)
119
+ @parent = parent
120
+ @band = band
121
+ end
122
+
123
+ def render(num_frames, start_frame = 0, cache = {})
124
+ @parent.render_band(@band, num_frames, start_frame, cache)
125
+ end
126
+
127
+ def render_block(num_frames, start_frame = 0, cache = {})
128
+ @parent.render_band_block(@band, num_frames, start_frame, cache)
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deftones
4
+ module Component
5
+ class OnePoleFilter < Core::AudioNode
6
+ TYPES = %i[lowpass highpass].freeze
7
+
8
+ attr_reader :frequency
9
+ attr_accessor :type
10
+
11
+ def initialize(frequency: 880.0, type: :lowpass, context: Deftones.context)
12
+ super(context: context)
13
+ @frequency = Core::Signal.new(value: frequency, units: :frequency, context: context)
14
+ @type = normalize_type(type)
15
+ @lowpass_state = []
16
+ end
17
+
18
+ def frequency=(value)
19
+ @frequency.value = value
20
+ end
21
+
22
+ def multichannel_process?
23
+ true
24
+ end
25
+
26
+ def process(input_block, num_frames, start_frame, _cache)
27
+ frequencies = @frequency.process(num_frames, start_frame)
28
+ ensure_state(input_block.channels)
29
+ output_channels = input_block.channel_data.each_with_index.map do |channel, channel_index|
30
+ Array.new(num_frames) do |index|
31
+ input_sample = channel[index]
32
+ coefficient = coefficient_for(frequencies[index])
33
+ @lowpass_state[channel_index] += (1.0 - coefficient) * (input_sample - @lowpass_state[channel_index])
34
+
35
+ if normalize_type(@type) == :lowpass
36
+ @lowpass_state[channel_index]
37
+ else
38
+ input_sample - @lowpass_state[channel_index]
39
+ end
40
+ end
41
+ end
42
+
43
+ Core::AudioBlock.from_channel_data(output_channels)
44
+ end
45
+
46
+ def reset!
47
+ @lowpass_state = []
48
+ self
49
+ end
50
+
51
+ private
52
+
53
+ def coefficient_for(frequency)
54
+ normalized = [[frequency.to_f, 1.0].max, (context.sample_rate * 0.49)].min
55
+ Math.exp((-2.0 * Math::PI * normalized) / context.sample_rate)
56
+ end
57
+
58
+ def normalize_type(type)
59
+ normalized = type.to_sym
60
+ return normalized if TYPES.include?(normalized)
61
+
62
+ raise ArgumentError, "Unsupported one pole filter type: #{type}"
63
+ end
64
+
65
+ def ensure_state(channels)
66
+ required = [channels.to_i, 1].max
67
+ @lowpass_state.fill(0.0, @lowpass_state.length...required)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deftones
4
+ module Component
5
+ class PanVol < Core::AudioNode
6
+ attr_reader :input, :output, :panner, :volume
7
+
8
+ def initialize(pan: 0.0, volume: 0.0, context: Deftones.context)
9
+ super(context: context)
10
+ @panner = Panner.new(pan: pan, context: context)
11
+ @volume = Volume.new(volume: volume, context: context)
12
+ @input = @panner
13
+ @output = @volume
14
+ @panner >> @volume
15
+ end
16
+
17
+ def render(num_frames, start_frame = 0, cache = {})
18
+ @output.render(num_frames, start_frame, cache)
19
+ end
20
+
21
+ def render_block(num_frames, start_frame = 0, cache = {})
22
+ @output.send(:render_block, num_frames, start_frame, cache)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deftones
4
+ module Component
5
+ class Panner < Core::AudioNode
6
+ attr_reader :pan
7
+
8
+ def initialize(pan: 0.0, context: Deftones.context)
9
+ super(context: context)
10
+ @pan = Core::Signal.new(value: pan, units: :number, context: context)
11
+ end
12
+
13
+ def pan=(value)
14
+ @pan.value = value
15
+ end
16
+
17
+ def multichannel_process?
18
+ true
19
+ end
20
+
21
+ def process(input_block, num_frames, start_frame, _cache)
22
+ pans = @pan.process(num_frames, start_frame)
23
+ return process_mono_input(input_block, num_frames, pans) if input_block.channels == 1
24
+
25
+ stereo_input = input_block.fit_channels(2)
26
+ left = Array.new(num_frames)
27
+ right = Array.new(num_frames)
28
+
29
+ num_frames.times do |index|
30
+ left[index] = stereo_input.channel_data[0][index] * stereo_left_gain(pans[index])
31
+ right[index] = stereo_input.channel_data[1][index] * stereo_right_gain(pans[index])
32
+ end
33
+
34
+ Core::AudioBlock.from_channel_data([left, right])
35
+ end
36
+
37
+ private
38
+
39
+ def process_mono_input(input_block, num_frames, pans)
40
+ mono_input = input_block.mono
41
+
42
+ Core::AudioBlock.from_channel_data([
43
+ Array.new(num_frames) { |index| mono_input[index] * left_gain(pans[index]) },
44
+ Array.new(num_frames) { |index| mono_input[index] * right_gain(pans[index]) }
45
+ ])
46
+ end
47
+
48
+ def stereo_left_gain(pan)
49
+ normalized = pan.to_f.clamp(-1.0, 1.0)
50
+ return 1.0 if normalized <= 0.0
51
+
52
+ Math.cos(normalized * Math::PI * 0.5)
53
+ end
54
+
55
+ def stereo_right_gain(pan)
56
+ normalized = pan.to_f.clamp(-1.0, 1.0)
57
+ return 1.0 if normalized >= 0.0
58
+
59
+ Math.cos(normalized.abs * Math::PI * 0.5)
60
+ end
61
+
62
+ def left_gain(pan)
63
+ Math.cos(angle_for(pan))
64
+ end
65
+
66
+ def right_gain(pan)
67
+ Math.sin(angle_for(pan))
68
+ end
69
+
70
+ def angle_for(pan)
71
+ ((pan.to_f.clamp(-1.0, 1.0) + 1.0) * Math::PI) * 0.25
72
+ end
73
+ end
74
+ end
75
+ end