Class: SPCore::Oscillator

Inherits:
Object
  • Object
show all
Includes:
Hashmake::HashMakeable
Defined in:
lib/spcore/generation/oscillator.rb

Overview

Author:

  • James Tunnell

Constant Summary collapse

WAVE_SINE =

Defines a sine wave type.

:waveSine
WAVE_TRIANGLE =

Defines a triangle wave type.

:waveTriangle
WAVE_SAWTOOTH =

Defines a sawtooth wave type.

:waveSawtooth
WAVE_SQUARE =

Defines a square wave type.

:waveSquare
WAVES =

Defines a list of the valid wave types.

[WAVE_SINE, WAVE_TRIANGLE, WAVE_SAWTOOTH, WAVE_SQUARE]
ARG_SPECS =

Used to process hashed arguments in #initialize.

{
  :sample_rate => arg_spec(:reqd => true, :type => Fixnum, :validator => ->(a){ a > 0 } ),
  :wave_type => arg_spec(:reqd => false, :type => Symbol, :default => WAVE_SINE, :validator => ->(a){ WAVES.include? a } ),
  :frequency => arg_spec(:reqd => false, :type => Numeric, :default => 1.0, :validator => ->(a){ a > 0.0 } ),
  :amplitude => arg_spec(:reqd => false, :type => Numeric, :default => 1.0 ),
  :phase_offset => arg_spec(:reqd => false, :type => Numeric, :default => 0.0 ),
  :dc_offset => arg_spec(:reqd => false, :type => Numeric, :default => 0.0 ),
}
K_SINE_B =

constant used to calculate sine wave

4.0 / Math::PI
K_SINE_C =

constant used to calculate sine wave

-4.0 / (Math::PI * Math::PI)
K_SINE_P =

Q = 0.775 constant used to calculate sine wave

0.225
K_TRIANGLE_A =

constant used to calculate triangle wave

2.0 / Math::PI
K_SAWTOOTH_A =

constant used to calculate sawtooth wave

1.0 / Math::PI

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args) ⇒ Oscillator

A new instance of Oscillator. The controllable wave parameters are frequency, amplitude, phase offset, and DC offset. The current phase angle is initialized to the given phase offset.

Parameters:

  • args (Hash)

    Hashed arguments. Required key is :sample_rate. Optional keys are :wave_type, :frequency, :amplitude, :phase_offset, and :dc_offset. See ARG_SPECS for more details.



40
41
42
43
44
45
# File 'lib/spcore/generation/oscillator.rb', line 40

def initialize args
  hash_make args, Oscillator::ARG_SPECS
  
  @phase_angle_incr = (@frequency * TWO_PI) / @sample_rate
  @current_phase_angle = @phase_offset
end

Instance Attribute Details

#amplitudeObject

Returns the value of attribute amplitude.



8
9
10
# File 'lib/spcore/generation/oscillator.rb', line 8

def amplitude
  @amplitude
end

#dc_offsetObject

Returns the value of attribute dc_offset.



8
9
10
# File 'lib/spcore/generation/oscillator.rb', line 8

def dc_offset
  @dc_offset
end

#frequencyObject

Returns the value of attribute frequency.



9
10
11
# File 'lib/spcore/generation/oscillator.rb', line 9

def frequency
  @frequency
end

#phase_offsetObject

Returns the value of attribute phase_offset.



9
10
11
# File 'lib/spcore/generation/oscillator.rb', line 9

def phase_offset
  @phase_offset
end

#sample_rateObject

Returns the value of attribute sample_rate.



9
10
11
# File 'lib/spcore/generation/oscillator.rb', line 9

def sample_rate
  @sample_rate
end

#wave_typeObject

Returns the value of attribute wave_type.



8
9
10
# File 'lib/spcore/generation/oscillator.rb', line 8

def wave_type
  @wave_type
end

Instance Method Details

#sampleObject

Step forward one sampling period and sample the oscillator waveform.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/spcore/generation/oscillator.rb', line 70

def sample
  output = 0.0

  while(@current_phase_angle < -Math::PI)
    @current_phase_angle += TWO_PI
  end

  while(@current_phase_angle > Math::PI)
    @current_phase_angle -= TWO_PI
  end

  case @wave_type
  when WAVE_SINE
    output = @amplitude * sine(@current_phase_angle) + @dc_offset
  when WAVE_TRIANGLE
    output = @amplitude * triangle(@current_phase_angle) + @dc_offset
  when WAVE_SQUARE
    output = @amplitude * square(@current_phase_angle) + @dc_offset
  when WAVE_SAWTOOTH
    output = @amplitude * sawtooth(@current_phase_angle) + @dc_offset
  else
    raise "Encountered unexpected wave type #{@wave_type}"
  end
  
  @current_phase_angle += @phase_angle_incr
  return output
end

#sawtooth(x) ⇒ Object

generate a sawtooth wave: input range: -PI to PI ouput range: -1 to 1



142
143
144
# File 'lib/spcore/generation/oscillator.rb', line 142

def sawtooth x
  K_SAWTOOTH_A * x
end

#sine(x) ⇒ Object

generate a sine wave: input range: -PI to PI ouput range: -1 to 1



109
110
111
112
113
114
115
116
117
# File 'lib/spcore/generation/oscillator.rb', line 109

def sine x
  y = K_SINE_B * x + K_SINE_C * x * x.abs
  # for extra precision
  y = K_SINE_P * (y * y.abs - y) + y   # Q * y + P * y * y.abs
  
  # sin normally output outputs -1 to 1, so to adjust
  # it to output 0 to 1, return (y*0.5)+0.5
  return y
end

#square(x) ⇒ Object

generate a square wave (50% duty cycle): input range: -PI to PI ouput range: 0 to 1



132
133
134
# File 'lib/spcore/generation/oscillator.rb', line 132

def square x
  (x >= 0.0) ? 1.0 : -1.0
end

#triangle(x) ⇒ Object

generate a triangle wave: input range: -PI to PI ouput range: -1 to 1



125
126
127
# File 'lib/spcore/generation/oscillator.rb', line 125

def triangle x
  (K_TRIANGLE_A * x).abs - 1.0
end