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,519 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deftones
4
+ module Source
5
+ class UserMedia < Core::Source
6
+ DeviceInfo = Struct.new(:device_id, :label, :group_id, :input_channels, :output_channels, keyword_init: true)
7
+
8
+ attr_reader :buffer, :provider, :device_id, :group_id, :label
9
+
10
+ def initialize(buffer: nil, provider: nil, loop: false, live: false, capture_backend: nil,
11
+ device_id: nil, group_id: nil, label: nil, channels: nil, context: Deftones.context)
12
+ super(context: context)
13
+ @buffer = normalize_buffer(buffer)
14
+ @provider = normalize_provider(provider)
15
+ @loop = loop
16
+ @live_requested = live || !capture_backend.nil?
17
+ @capture_backend = normalize_capture_backend(capture_backend, live, channels)
18
+ @device_id = device_id
19
+ @group_id = group_id
20
+ @label = label
21
+ @channels = normalize_channel_count(channels)
22
+ @sample_cursor = 0
23
+ @opened = false
24
+ end
25
+
26
+ def start(time = nil)
27
+ rewind
28
+ @capture_backend&.start
29
+ @opened = true
30
+ super
31
+ end
32
+
33
+ def stop(time = nil)
34
+ @capture_backend&.stop
35
+ super
36
+ end
37
+
38
+ def open(time = nil, device_id: nil, group_id: nil, label: nil)
39
+ @device_id = device_id unless device_id.nil?
40
+ @group_id = group_id unless group_id.nil?
41
+ @label = label unless label.nil?
42
+ open_capture_backend!
43
+ sync_capture_metadata!
44
+ self.class.grant_permissions!
45
+ start(time)
46
+ end
47
+
48
+ def close(time = nil)
49
+ stop(time)
50
+ @capture_backend&.close if @capture_backend.respond_to?(:close)
51
+ @opened = false
52
+ self
53
+ end
54
+
55
+ def rewind
56
+ @sample_cursor = 0
57
+ @provider.rewind if @provider.respond_to?(:rewind)
58
+ @capture_backend&.rewind if @capture_backend.respond_to?(:rewind)
59
+ self
60
+ end
61
+
62
+ def live?
63
+ @live_requested
64
+ end
65
+
66
+ def opened?
67
+ @opened
68
+ end
69
+
70
+ def permission_state
71
+ self.class.permission_state
72
+ end
73
+
74
+ alias permissionState permission_state
75
+
76
+ def state(time = context.current_time)
77
+ return :stopped unless @opened
78
+
79
+ active_at?(resolve_time(time)) ? :started : :stopped
80
+ end
81
+
82
+ def dispose
83
+ close
84
+ super
85
+ end
86
+
87
+ class << self
88
+ def permission_state
89
+ @permission_state ||= :prompt
90
+ end
91
+
92
+ def grant_permissions!
93
+ @permission_state = :granted
94
+ self
95
+ end
96
+
97
+ def reset_permissions!
98
+ @permission_state = :prompt
99
+ self
100
+ end
101
+
102
+ def supported?
103
+ true
104
+ end
105
+
106
+ def input_devices
107
+ portaudio_devices.filter_map do |device|
108
+ info = build_device_info(device)
109
+ info if info.input_channels.positive?
110
+ end
111
+ end
112
+
113
+ def enumerate_devices
114
+ input_devices
115
+ end
116
+
117
+ alias supported supported?
118
+ alias enumerateDevices enumerate_devices
119
+ alias permissionState permission_state
120
+
121
+ private
122
+
123
+ def permissions_granted?
124
+ permission_state == :granted
125
+ end
126
+
127
+ def portaudio_devices
128
+ return [] unless Deftones.portaudio_available?
129
+ return [] unless defined?(PortAudio::Device)
130
+
131
+ return Array(PortAudio::Device.all) if PortAudio::Device.respond_to?(:all)
132
+ return Array(PortAudio::Device.devices) if PortAudio::Device.respond_to?(:devices)
133
+
134
+ []
135
+ rescue StandardError
136
+ []
137
+ end
138
+
139
+ def build_device_info(device)
140
+ DeviceInfo.new(
141
+ device_id: extract_device_id(device),
142
+ label: exposed_device_label(device),
143
+ group_id: exposed_device_group_id(device),
144
+ input_channels: extract_device_channels(device, :input),
145
+ output_channels: extract_device_channels(device, :output)
146
+ )
147
+ end
148
+
149
+ def extract_device_id(device)
150
+ return device.device_id if device.respond_to?(:device_id)
151
+ return device.index if device.respond_to?(:index)
152
+ return device.device_index if device.respond_to?(:device_index)
153
+
154
+ extract_device_label(device)
155
+ end
156
+
157
+ def extract_device_label(device)
158
+ return device.label if device.respond_to?(:label)
159
+ return device.name if device.respond_to?(:name)
160
+
161
+ device.to_s
162
+ end
163
+
164
+ def extract_device_group_id(device)
165
+ return device.group_id if device.respond_to?(:group_id)
166
+ return device.host_api if device.respond_to?(:host_api)
167
+ return device.host_api_name if device.respond_to?(:host_api_name)
168
+
169
+ nil
170
+ end
171
+
172
+ def exposed_device_label(device)
173
+ permissions_granted? ? extract_device_label(device) : ""
174
+ end
175
+
176
+ def exposed_device_group_id(device)
177
+ permissions_granted? ? extract_device_group_id(device) : nil
178
+ end
179
+
180
+ def extract_device_channels(device, direction)
181
+ methods =
182
+ case direction
183
+ when :input then %i[max_input_channels input_channels channels]
184
+ when :output then %i[max_output_channels output_channels channels]
185
+ else []
186
+ end
187
+
188
+ methods.each do |method_name|
189
+ return device.public_send(method_name).to_i if device.respond_to?(method_name)
190
+ end
191
+
192
+ 0
193
+ end
194
+ end
195
+
196
+ def process(_input_buffer, num_frames, start_frame, _cache)
197
+ return render_buffer_block(num_frames, start_frame) if @buffer && @buffer.channels > 1
198
+ return render_capture_block(num_frames, start_frame) if @capture_backend && capture_channels > 1
199
+ return render_buffer(num_frames, start_frame) if @buffer
200
+ return render_capture(num_frames, start_frame) if @capture_backend
201
+
202
+ Array.new(num_frames) do |index|
203
+ current_time = (start_frame + index).to_f / context.sample_rate
204
+ next 0.0 unless active_at?(current_time)
205
+
206
+ next_provider_sample
207
+ end
208
+ end
209
+
210
+ private
211
+
212
+ def multichannel_process?
213
+ (@buffer && @buffer.channels > 1) || capture_channels > 1
214
+ end
215
+
216
+ def capture_channels
217
+ return @buffer.channels if @buffer
218
+ return normalize_channel_count(@capture_backend.channels) if @capture_backend.respond_to?(:channels)
219
+
220
+ @channels
221
+ end
222
+
223
+ def normalize_buffer(buffer)
224
+ return if buffer.nil?
225
+
226
+ buffer.is_a?(IO::Buffer) ? buffer : IO::Buffer.load(buffer)
227
+ end
228
+
229
+ def normalize_provider(provider)
230
+ return if provider.nil?
231
+ return provider if provider.respond_to?(:call)
232
+
233
+ provider.to_enum
234
+ end
235
+
236
+ def normalize_capture_backend(capture_backend, live, channels)
237
+ return capture_backend if capture_backend
238
+ return unless live && Deftones.portaudio_available?
239
+
240
+ PortAudioCapture.new(
241
+ sample_rate: context.sample_rate,
242
+ buffer_size: context.buffer_size,
243
+ channels: normalize_channel_count(channels || context.channels)
244
+ )
245
+ end
246
+
247
+ def normalize_channel_count(channels)
248
+ [channels.to_i, 1].max
249
+ end
250
+
251
+ def open_capture_backend!
252
+ return self unless live?
253
+
254
+ raise Deftones::MissingRealtimeBackendError, "UserMedia live capture backend is unavailable" unless @capture_backend
255
+
256
+ if @capture_backend.respond_to?(:open)
257
+ @capture_backend.open(
258
+ device_id: @device_id,
259
+ group_id: @group_id,
260
+ label: @label,
261
+ channels: capture_channels
262
+ )
263
+ end
264
+
265
+ self
266
+ end
267
+
268
+ def sync_capture_metadata!
269
+ return self unless @capture_backend
270
+
271
+ @device_id = @capture_backend.device_id if @capture_backend.respond_to?(:device_id) && !@capture_backend.device_id.nil?
272
+ @group_id = @capture_backend.group_id if @capture_backend.respond_to?(:group_id) && !@capture_backend.group_id.nil?
273
+ @label = @capture_backend.label if @capture_backend.respond_to?(:label) && !@capture_backend.label.nil?
274
+ self
275
+ end
276
+
277
+ def render_buffer(num_frames, start_frame)
278
+ Array.new(num_frames) do |index|
279
+ current_time = (start_frame + index).to_f / context.sample_rate
280
+ next 0.0 unless active_at?(current_time)
281
+
282
+ sample_position = (current_time - @start_time) * @buffer.sample_rate
283
+ if @loop && @buffer.frames.positive?
284
+ sample_position %= @buffer.frames
285
+ elsif sample_position >= @buffer.frames
286
+ @opened = false
287
+ next 0.0
288
+ end
289
+
290
+ @buffer.sample_at(sample_position)
291
+ end
292
+ end
293
+
294
+ def render_buffer_block(num_frames, start_frame)
295
+ output = Array.new(@buffer.channels) { Array.new(num_frames, 0.0) }
296
+
297
+ num_frames.times do |index|
298
+ current_time = (start_frame + index).to_f / context.sample_rate
299
+ next unless active_at?(current_time)
300
+
301
+ sample_position = (current_time - @start_time) * @buffer.sample_rate
302
+ if @loop && @buffer.frames.positive?
303
+ sample_position %= @buffer.frames
304
+ elsif sample_position >= @buffer.frames
305
+ @opened = false
306
+ next
307
+ end
308
+
309
+ @buffer.channels.times do |channel_index|
310
+ output[channel_index][index] = @buffer.sample_at(sample_position, channel_index)
311
+ end
312
+ end
313
+
314
+ Core::AudioBlock.from_channel_data(output)
315
+ end
316
+
317
+ def render_capture(num_frames, start_frame)
318
+ Array.new(num_frames) do |index|
319
+ current_time = (start_frame + index).to_f / context.sample_rate
320
+ next 0.0 unless active_at?(current_time)
321
+
322
+ @capture_backend.next_sample
323
+ end
324
+ end
325
+
326
+ def render_capture_block(num_frames, start_frame)
327
+ output = Array.new(capture_channels) { Array.new(num_frames, 0.0) }
328
+
329
+ num_frames.times do |index|
330
+ current_time = (start_frame + index).to_f / context.sample_rate
331
+ next unless active_at?(current_time)
332
+
333
+ frame = next_capture_frame
334
+ capture_channels.times do |channel_index|
335
+ output[channel_index][index] = frame[channel_index] || 0.0
336
+ end
337
+ end
338
+
339
+ Core::AudioBlock.from_channel_data(output)
340
+ end
341
+
342
+ def next_capture_frame
343
+ return Array.new(capture_channels, 0.0) unless @capture_backend
344
+
345
+ frame = if @capture_backend.respond_to?(:next_frame)
346
+ @capture_backend.next_frame
347
+ else
348
+ @capture_backend.next_sample
349
+ end
350
+
351
+ frame = [frame] unless frame.is_a?(Array)
352
+ normalized = frame.map(&:to_f)
353
+ normalized.fill(0.0, normalized.length...capture_channels)
354
+ end
355
+
356
+ def next_provider_sample
357
+ return 0.0 unless @provider
358
+
359
+ sample = if @provider.respond_to?(:call)
360
+ @provider.call(@sample_cursor)
361
+ else
362
+ next_enumerator_sample
363
+ end
364
+ @sample_cursor += 1
365
+ sample.to_f
366
+ end
367
+
368
+ def next_enumerator_sample
369
+ @provider.next
370
+ rescue StopIteration
371
+ return 0.0 unless @loop && @provider.respond_to?(:rewind)
372
+
373
+ @provider.rewind
374
+ @provider.next
375
+ rescue StopIteration
376
+ @opened = false
377
+ 0.0
378
+ end
379
+
380
+ class PortAudioCapture
381
+ attr_reader :channels, :device_id, :group_id, :label
382
+
383
+ def initialize(sample_rate:, buffer_size:, channels: 1)
384
+ @sample_rate = sample_rate
385
+ @buffer_size = buffer_size
386
+ @channels = [channels.to_i, 1].max
387
+ @queue = Queue.new
388
+ @max_frames = buffer_size * 64
389
+ @stream = nil
390
+ @device_id = nil
391
+ @group_id = nil
392
+ @label = nil
393
+ end
394
+
395
+ def open(device_id: nil, group_id: nil, label: nil, channels: nil)
396
+ @device_id = device_id unless device_id.nil?
397
+ @group_id = group_id unless group_id.nil?
398
+ @label = label unless label.nil?
399
+ @channels = [channels.to_i, 1].max unless channels.nil?
400
+ close if @stream
401
+ self
402
+ end
403
+
404
+ def start
405
+ open_stream unless @stream
406
+ @stream.start
407
+ self
408
+ end
409
+
410
+ def stop
411
+ return self unless @stream
412
+ return self if @stream.stopped?
413
+
414
+ @stream.stop
415
+ self
416
+ end
417
+
418
+ def rewind
419
+ clear_queue
420
+ self
421
+ end
422
+
423
+ def close
424
+ return self unless @stream
425
+
426
+ stream = @stream
427
+ @stream = nil
428
+ clear_queue
429
+ stream.close
430
+ self
431
+ ensure
432
+ Deftones::PortAudioSupport.release
433
+ end
434
+
435
+ def next_sample
436
+ frame = next_frame
437
+ frame.sum / [frame.length, 1].max.to_f
438
+ rescue ThreadError
439
+ 0.0
440
+ end
441
+
442
+ def next_frame
443
+ @queue.pop(true)
444
+ rescue ThreadError
445
+ Array.new(@channels, 0.0)
446
+ end
447
+
448
+ private
449
+
450
+ def open_stream
451
+ Deftones::PortAudioSupport.acquire!
452
+ input_parameters = Deftones::PortAudioSupport.input_parameters(
453
+ @channels,
454
+ device_id: @device_id,
455
+ label: @label
456
+ )
457
+ assign_device_metadata(input_parameters[:device])
458
+ @stream = PortAudio::Stream.new(
459
+ input: input_parameters,
460
+ sample_rate: @sample_rate.to_f,
461
+ frames_per_buffer: @buffer_size,
462
+ &method(:process)
463
+ )
464
+ rescue StandardError
465
+ Deftones::PortAudioSupport.release
466
+ raise
467
+ end
468
+
469
+ def process(input, _output, frame_count, _time_info, _status_flags, _user_data)
470
+ return :continue if input.null?
471
+
472
+ input.read_array_of_float(frame_count * @channels).each_slice(@channels) do |frame|
473
+ @queue << frame.map(&:to_f)
474
+ end
475
+ trim_queue!
476
+ :continue
477
+ rescue StandardError
478
+ :abort
479
+ end
480
+
481
+ def assign_device_metadata(device)
482
+ return unless device
483
+
484
+ @device_id ||= if device.respond_to?(:device_id)
485
+ device.device_id
486
+ elsif device.respond_to?(:index)
487
+ device.index
488
+ elsif device.respond_to?(:device_index)
489
+ device.device_index
490
+ end
491
+ @label ||= if device.respond_to?(:label)
492
+ device.label
493
+ elsif device.respond_to?(:name)
494
+ device.name
495
+ end
496
+ @group_id ||= if device.respond_to?(:group_id)
497
+ device.group_id
498
+ elsif device.respond_to?(:host_api)
499
+ device.host_api
500
+ elsif device.respond_to?(:host_api_name)
501
+ device.host_api_name
502
+ end
503
+ end
504
+
505
+ def trim_queue!
506
+ @queue.pop(true) while @queue.size > @max_frames
507
+ rescue ThreadError
508
+ nil
509
+ end
510
+
511
+ def clear_queue
512
+ @queue.pop(true) while true
513
+ rescue ThreadError
514
+ nil
515
+ end
516
+ end
517
+ end
518
+ end
519
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Deftones
4
+ VERSION = "0.1.0"
5
+ end