class Sidtool::Voice

Attributes

attack_decay[W]
control_register[W]
frequency_high[W]
frequency_low[W]
pulse_high[W]
pulse_low[W]
sustain_release[W]
synths[R]

Public Class Methods

new() click to toggle source
# File lib/sidtool/voice.rb, line 12
def initialize
  @frequency_low = @frequency_high = 0
  @pulse_low = @pulse_high = 0
  @attack_decay = @sustain_release = 0
  @control_register = 0
  @current_synth = nil
  @synths = []
end

Public Instance Methods

finish_frame() click to toggle source
# File lib/sidtool/voice.rb, line 21
def finish_frame
  if gate
    if @current_synth&.released?
      @current_synth.stop!
      @current_synth = nil
    end

    if frequency > 0
      if !@current_synth
        @current_synth = Synth.new(STATE.current_frame)
        @synths << @current_synth
      end
      @current_synth.frequency = frequency
      @current_synth.waveform = waveform
      @current_synth.attack = attack
      @current_synth.decay = decay
      @current_synth.release = release
    end
  else
    @current_synth&.release!
  end
end
stop!() click to toggle source
# File lib/sidtool/voice.rb, line 44
def stop!
  @current_synth&.stop!
  @current_synth = nil
end

Private Instance Methods

attack() click to toggle source
# File lib/sidtool/voice.rb, line 67
def attack
  # Approximated... should be multiplied by 1.000.000 / clock
  convert_attack(@attack_decay >> 4)
end
convert_attack(attack) click to toggle source
# File lib/sidtool/voice.rb, line 82
def convert_attack(attack)
  case attack
  when 0 then 0.002
  when 1 then 0.008
  when 2 then 0.016
  when 3 then 0.024
  when 4 then 0.038
  when 5 then 0.056
  when 6 then 0.068
  when 7 then 0.08
  when 8 then 0.1
  when 9 then 0.25
  when 10 then 0.5
  when 11 then 0.8
  when 12 then 1
  when 13 then 3
  when 14 then 5
  when 15 then 8
  else raise "Unknown value: #{attack}"
  end
end
convert_decay_or_release(decay_or_release) click to toggle source
# File lib/sidtool/voice.rb, line 104
def convert_decay_or_release(decay_or_release)
  case decay_or_release
  when 0 then 0.006
  when 1 then 0.024
  when 2 then 0.048
  when 3 then 0.072
  when 4 then 0.114
  when 5 then 0.168
  when 6 then 0.204
  when 7 then 0.240
  when 8 then 0.3
  when 9 then 0.75
  when 10 then 1.5
  when 11 then 2.4
  when 12 then 3
  when 13 then 9
  when 14 then 15
  when 15 then 24
  else raise "Unknown value: #{decay_or_release}"
  end
end
decay() click to toggle source
# File lib/sidtool/voice.rb, line 72
def decay
  # Approximated... should be multiplied by 1.000.000 / clock
  convert_decay_or_release(@attack_decay & 0xF)
end
frequency() click to toggle source
# File lib/sidtool/voice.rb, line 54
def frequency
  (@frequency_high << 8) + @frequency_low
end
gate() click to toggle source
# File lib/sidtool/voice.rb, line 50
def gate
  @control_register & 1 == 1
end
release() click to toggle source
# File lib/sidtool/voice.rb, line 77
def release
  # Approximated... should be multiplied by 1.000.000 / clock
  convert_decay_or_release(@sustain_release >> 4)
end
waveform() click to toggle source
# File lib/sidtool/voice.rb, line 58
def waveform
  return :tri if @control_register & 16 != 0
  return :saw if @control_register & 32 != 0
  return :pulse if @control_register & 64 != 0
  return :noise if @control_register & 128 != 0
  STDERR.puts "Unknown waveform: #{@control_register}"
  return :noise
end