     ###########################################################
 
     writeDutyEnvelope: (value) ->
-        @setDutyEnvelope value
-        @updateState()
-        @updateVolume()
-        value
-
-    setDutyEnvelope: (value) ->
         @dutySelection = (value & 0xC0) >>> 6      # Selects output waveform
         @lengthCounterHalt = (value & 0x20) isnt 0 # Disables length counter decrementation
         @useConstantVolume = (value & 0x10) isnt 0 # 0 - envelope volume is used / 1 - constant volume is used

        @envelopePeriod = @constantVolume          # Envelope duration period (constant volume alias)
        @envelopeCycle or= 0                       # Cycle of envelope divider
        @envelopeVolume or= 0                      # Envelope volume value

    ###########################################################
    # Sweep register
    ###########################################################

    writeSweep: (value) ->
        @setSweep value
        @updateState()
        value

    setSweep: (value) ->
        @sweepEnabled = (value & 0x80) isnt 0 # Sweeping enabled
        @sweepPeriod = (value & 0x70) >>> 4   # Period after which sweep is applied
        @sweepNegate = (value & 0x08) isnt 0  # 0 - sweep is added to timer period / 1 - sweep is subtracted from timer period
        @sweepShift = value & 0x07            # Shift of timer period when computing sweep
        @sweepReset = true                    # Sweep counter will be reseted
        @sweepCycle or= 0                     # Sweep counter

    ###########################################################
    # Timer register
    ###########################################################

    writeTimer: (value) ->
        @setTimer value
        @updateState()
        value

    setTimer: (value) ->
         @timerPeriod = (@timerPeriod or 0) & 0x700 | (value & 0xFF) # Lower 8 bits of timer
         @timerCycle or= 0

    ###########################################################
    # Length counter / Timer register
    ###########################################################

    writeLengthCounter: (value) ->
        @setLengthCounter value
        @updateState()
        value

    setLengthCounter: (value) ->
        @timerPeriod = (@timerPeriod or 0) & 0x0FF | (value & 0x7) << 8           # Higher 3 bits of timer
        @lengthCounter = LENGTH_COUNTER_VALUES[(value & 0xF8) >>> 3] if @enabled  # Length counter update
        @dutyPosition = 0     # Output waveform position is reseted
        @envelopeReset = true # Envelope and its divider will be reseted

    ###########################################################
    # Tick
    ###########################################################

    tick: ->
        # The timer actually counts T, T-1, ... 0, 1, ... T
        # and clocks waveform generator (duty position) when it goes from T-1 to T.
        # We are emulating it as 2*T, 2*T-1, ..., 0.
        if --@timerCycle <= 0
            @timerCycle = (@timerPeriod + 1) << 1 # Real period is T + 1 APU cycles
            @dutyPosition = (@dutyPosition + 1) & 0x7

    tickQuarterFrame: ->
        @updateEnvelope()
        @updateVolume()
        @updateState()

    tickHalfFrame: ->
        @updateLengthCounter()
        @updateSweep()
        @updateState()

    ###########################################################
    # Envelope

        else
            sweep

    isTimerPeriodValid: ->
        @timerPeriod >= 0x8 and @timerPeriod + @getSweep() < 0x800

    ###########################################################
    # Output value
    ###########################################################

    getOutputValue: ->
        if @enabled and @lengthCounter and @$isTimerPeriodValid()
            volume = if @useConstantVolume then @constantVolume else @envelopeVolume
            volume * DUTY_WAVEFORMS[@dutySelection][@dutyPosition]
        else
            0

