Class: RoadToRubykaigi::Audio::RoundedSquareOscillator
- Inherits:
-
Object
- Object
- RoadToRubykaigi::Audio::RoundedSquareOscillator
- Includes:
- Phasor
- Defined in:
- lib/road_to_rubykaigi/audio/oscillator.rb
Constant Summary collapse
- DUTY_CYCLE =
{ d0: 0.125, d1: 0.25, d2: 0.5, }
- SMOOTH_WIDTH =
0.05
Instance Method Summary collapse
Methods included from Phasor
Instance Method Details
#duty_cycle=(duty_cycle) ⇒ Object
143 144 145 |
# File 'lib/road_to_rubykaigi/audio/oscillator.rb', line 143 def duty_cycle=(duty_cycle) @duty_cycle = (DUTY_CYCLE.key?(duty_cycle) ? duty_cycle : :d0) end |
#generate(frequencies:) ⇒ Object
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/road_to_rubykaigi/audio/oscillator.rb', line 116 def generate(frequencies:) samples = frequencies.map do |frequency| phase = tick(frequency: frequency) off_to_on_end = SMOOTH_WIDTH / 2.0 on_to_off_start = duty_cycle - SMOOTH_WIDTH / 2.0 on_to_off_end = duty_cycle + SMOOTH_WIDTH / 2.0 case phase when 0..off_to_on_end t = phase / off_to_on_end smoothstep_weight = t ** 2 * (3 - 2 * t) -1.0 + smoothstep_weight * 2 when off_to_on_end..on_to_off_start 1.0 when on_to_off_start..on_to_off_end t = (phase - on_to_off_start) / SMOOTH_WIDTH cos_weight = 1 - Math.cos(Math::PI * t) 1.0 - cos_weight else # We don't need interpolate off_to_on_start..1 # because 1 is essentially contiguous with 0. -1.0 end end samples.sum / samples.size end |