Class: Wavify::DSP::Automation
- Inherits:
-
Object
- Object
- Wavify::DSP::Automation
- Defined in:
- lib/wavify/dsp/automation.rb,
sig/dsp.rbs
Overview
Linear automation curve for time-varying parameters.
Defined Under Namespace
Classes: Point
Instance Attribute Summary collapse
-
#points ⇒ Array[[Float, Float]]
readonly
Returns the value of attribute points.
Instance Method Summary collapse
- #apply(buffer) {|arg0, arg1, arg2| ... } ⇒ Core::SampleBuffer
- #apply_gain(buffer, unit: :db) ⇒ Core::SampleBuffer
-
#initialize(points) ⇒ Automation
constructor
A new instance of Automation.
- #value_at(time) ⇒ Float
Constructor Details
#initialize(points) ⇒ Automation
Returns a new instance of Automation.
11 12 13 14 15 16 |
# File 'lib/wavify/dsp/automation.rb', line 11 def initialize(points) normalized = Array(points).map { |point| coerce_point(point) }.sort_by(&:time) raise InvalidParameterError, "automation points must not be empty" if normalized.empty? @points = normalized.freeze end |
Instance Attribute Details
#points ⇒ Array[[Float, Float]] (readonly)
Returns the value of attribute points.
9 10 11 |
# File 'lib/wavify/dsp/automation.rb', line 9 def points @points end |
Instance Method Details
#apply(buffer) {|arg0, arg1, arg2| ... } ⇒ Core::SampleBuffer
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/wavify/dsp/automation.rb', line 33 def apply(buffer) raise InvalidParameterError, "buffer must be Core::SampleBuffer" unless buffer.is_a?(Core::SampleBuffer) raise InvalidParameterError, "automation apply requires a block" unless block_given? format = buffer.format point_index = 1 samples = [] buffer.samples.each_slice(format.channels).with_index do |frame, frame_index| time = frame_index.to_f / format.sample_rate point_index += 1 while point_index < @points.length && @points.fetch(point_index).time < time value = value_between_points(time, point_index) frame.each_with_index do |sample, channel| samples << yield(sample, value, time, channel) end end Core::SampleBuffer.new(samples, format) end |
#apply_gain(buffer, unit: :db) ⇒ Core::SampleBuffer
51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/wavify/dsp/automation.rb', line 51 def apply_gain(buffer, unit: :db) mode = unit.to_sym raise InvalidParameterError, "unit must be :db or :linear" unless %i[db linear].include?(mode) float_format = buffer.format.with(sample_format: :float, bit_depth: 32) processed = apply(buffer.convert(float_format)) do |sample, value, _time, _channel| factor = mode == :db ? (10.0**(value / 20.0)) : value sample * factor end processed.convert(buffer.format) rescue NoMethodError raise InvalidParameterError, "unit must be Symbol/String" end |
#value_at(time) ⇒ Float
18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/wavify/dsp/automation.rb', line 18 def value_at(time) seconds = validate_time!(time) return @points.first.value if seconds <= @points.first.time return @points.last.value if seconds >= @points.last.time right_index = @points.bsearch_index { |point| point.time >= seconds } left = @points.fetch(right_index - 1) right = @points.fetch(right_index) span = right.time - left.time return right.value if span.zero? ratio = (seconds - left.time) / span left.value + ((right.value - left.value) * ratio) end |