Class: Deftones::Analysis::Analyser

Inherits:
Core::AudioNode show all
Defined in:
lib/deftones/analysis/analyser.rb

Constant Summary collapse

TYPES =
%i[fft waveform].freeze
RETURN_TYPES =
%i[float byte].freeze

Instance Attribute Summary collapse

Attributes inherited from Core::AudioNode

#context, #input

Instance Method Summary collapse

Methods inherited from Core::AudioNode

#>>, #attach_destination, #attach_source, #block_time, #chain, #channel_count, #channel_count_mode, #channel_interpretation, #connect, #connected?, #default_input_channels, #default_output_channels, #destination_for_connection, #detach_all_destinations, #detach_destination, #detach_source, #disconnect, #dispose, #disposed?, #fan, #get, #immediate, #input_for_index, #inputs, #mix_source_blocks, #name, #normalize_connection_index, #normalize_output_block, #now, #number_of_inputs, #number_of_outputs, #output, #output_for_connection, #output_for_index, #outputs, #raise_connection_index_error!, #reaches_node?, #render, #render_block, #sample_time, #set, #to_destination, #to_frequency, #to_master, #to_midi, #to_output, #to_s, #to_seconds, #to_ticks, #uses_legacy_render_for_block?, #validate_connectable!, #validate_connection_index!

Constructor Details

#initialize(size: 1024, type: :fft, return_type: :float, smoothing: 0.8, normal_range: false, min_decibels: -100.0,, max_decibels: 0.0, context: Deftones.context) ⇒ Analyser

Returns a new instance of Analyser.



12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/deftones/analysis/analyser.rb', line 12

def initialize(size: 1024, type: :fft, return_type: :float, smoothing: 0.8,
               normal_range: false, min_decibels: -100.0, max_decibels: 0.0,
               context: Deftones.context)
  super(context: context)
  @type = normalize_type(type)
  @return_type = normalize_return_type(return_type)
  @normal_range = !!normal_range
  @min_decibels = min_decibels.to_f
  @max_decibels = max_decibels.to_f
  self.smoothing = smoothing
  self.size = size
end

Instance Attribute Details

#max_decibelsObject Also known as: maxDecibels

Returns the value of attribute max_decibels.



9
10
11
# File 'lib/deftones/analysis/analyser.rb', line 9

def max_decibels
  @max_decibels
end

#min_decibelsObject Also known as: minDecibels

Returns the value of attribute min_decibels.



9
10
11
# File 'lib/deftones/analysis/analyser.rb', line 9

def min_decibels
  @min_decibels
end

#normal_rangeObject Also known as: normalRange

Returns the value of attribute normal_range.



10
11
12
# File 'lib/deftones/analysis/analyser.rb', line 10

def normal_range
  @normal_range
end

#return_typeObject Also known as: returnType

Returns the value of attribute return_type.



9
10
11
# File 'lib/deftones/analysis/analyser.rb', line 9

def return_type
  @return_type
end

#sizeObject

Returns the value of attribute size.



9
10
11
# File 'lib/deftones/analysis/analyser.rb', line 9

def size
  @size
end

#typeObject

Returns the value of attribute type.



9
10
11
# File 'lib/deftones/analysis/analyser.rb', line 9

def type
  @type
end

Instance Method Details

#fftObject



29
30
31
# File 'lib/deftones/analysis/analyser.rb', line 29

def fft
  FFT.magnitudes(@recent_samples)
end

#format_fft_values(values) ⇒ Object (private)



144
145
146
147
148
149
# File 'lib/deftones/analysis/analyser.rb', line 144

def format_fft_values(values)
  return values.map { |value| scale_to_byte_range(value) } if @return_type == :byte
  return values.map { |value| scale_to_normal_range(value) } if @normal_range

  values.map { |value| Deftones::DSP::Helpers.clamp(value, @min_decibels, @max_decibels) }
end

#format_waveform_values(values) ⇒ Object (private)



134
135
136
137
138
139
140
141
142
# File 'lib/deftones/analysis/analyser.rb', line 134

def format_waveform_values(values)
  if @return_type == :byte
    values.map { |sample| (((Deftones::DSP::Helpers.clamp(sample, -1.0, 1.0) + 1.0) * 0.5) * 255.0).round }
  elsif @normal_range
    values.map { |sample| Deftones::DSP::Helpers.clamp((sample + 1.0) * 0.5, 0.0, 1.0) }
  else
    values.map { |sample| Deftones::DSP::Helpers.clamp(sample, -1.0, 1.0) }
  end
end

#get_valueObject Also known as: getValue



67
68
69
70
71
72
73
# File 'lib/deftones/analysis/analyser.rb', line 67

def get_value
  if @type == :waveform
    format_waveform_values(@smoothed_waveform)
  else
    format_fft_values(@smoothed_fft)
  end
end

#maxDecibels=(value) ⇒ Object



106
107
108
# File 'lib/deftones/analysis/analyser.rb', line 106

def maxDecibels=(value)
  self.max_decibels = value
end

#minDecibels=(value) ⇒ Object



102
103
104
# File 'lib/deftones/analysis/analyser.rb', line 102

def minDecibels=(value)
  self.min_decibels = value
end

#multichannel_process?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/deftones/analysis/analyser.rb', line 75

def multichannel_process?
  true
end

#normalize_return_type(value) ⇒ Object (private)

Raises:

  • (ArgumentError)


119
120
121
122
123
124
# File 'lib/deftones/analysis/analyser.rb', line 119

def normalize_return_type(value)
  normalized = value.to_s.downcase.to_sym
  raise ArgumentError, "Unsupported analyser return type: #{value}" unless RETURN_TYPES.include?(normalized)

  normalized
end

#normalize_type(value) ⇒ Object (private)

Raises:

  • (ArgumentError)


112
113
114
115
116
117
# File 'lib/deftones/analysis/analyser.rb', line 112

def normalize_type(value)
  normalized = value.to_s.downcase.to_sym
  raise ArgumentError, "Unsupported analyser type: #{value}" unless TYPES.include?(normalized)

  normalized
end

#normalRange=(value) ⇒ Object



98
99
100
# File 'lib/deftones/analysis/analyser.rb', line 98

def normalRange=(value)
  self.normal_range = value
end

#process(input_block, num_frames, _start_frame, _cache) ⇒ Object



79
80
81
82
83
84
85
86
# File 'lib/deftones/analysis/analyser.rb', line 79

def process(input_block, num_frames, _start_frame, _cache)
  analysed = input_block.mono.first(num_frames)
  @recent_samples.concat(analysed)
  @recent_samples = @recent_samples.last(@size)
  @smoothed_waveform = smooth_values(@smoothed_waveform, @recent_samples)
  @smoothed_fft = smooth_values(@smoothed_fft, FFT.decibels(@recent_samples, floor: @min_decibels))
  input_block
end

#returnType=(value) ⇒ Object



94
95
96
# File 'lib/deftones/analysis/analyser.rb', line 94

def returnType=(value)
  self.return_type = value
end

#scale_to_byte_range(value) ⇒ Object (private)



157
158
159
# File 'lib/deftones/analysis/analyser.rb', line 157

def scale_to_byte_range(value)
  (scale_to_normal_range(value) * 255.0).round
end

#scale_to_normal_range(value) ⇒ Object (private)



151
152
153
154
155
# File 'lib/deftones/analysis/analyser.rb', line 151

def scale_to_normal_range(value)
  return 0.0 if @max_decibels <= @min_decibels

  Deftones::DSP::Helpers.clamp((value - @min_decibels) / (@max_decibels - @min_decibels), 0.0, 1.0)
end

#smooth_values(previous, current) ⇒ Object (private)



126
127
128
129
130
131
132
# File 'lib/deftones/analysis/analyser.rb', line 126

def smooth_values(previous, current)
  return current.dup if @smoothing.zero?

  previous.zip(current).map do |prior, sample|
    (prior.to_f * @smoothing) + (sample.to_f * (1.0 - @smoothing))
  end
end

#smoothingObject



50
51
52
# File 'lib/deftones/analysis/analyser.rb', line 50

def smoothing
  @smoothing
end

#smoothing=(value) ⇒ Object



54
55
56
# File 'lib/deftones/analysis/analyser.rb', line 54

def smoothing=(value)
  @smoothing = Deftones::DSP::Helpers.clamp(value.to_f, 0.0, 1.0)
end

#waveformObject



25
26
27
# File 'lib/deftones/analysis/analyser.rb', line 25

def waveform
  Waveform::Snapshot.new(@recent_samples.dup)
end