         
         source = @context.createBufferSource()
         source.buffer = @buffers[key]
-        source.gain.value = settings.volume
-        source.loop = settings.loop
-        
-        source.connect(@mainNode)
+        source.loop = settings.looping
+        
+        # handle volume level with a gain node
+        gainNode = @context.createGain()
+        gainNode.connect(@mainNode)
+        gainNode.gain.value = settings.volume
+        
+        source.connect(gainNode)
         
         if not source.start? then source.start = source.noteOn
         if not source.stop? then source.stop = source.noteOff

    # wrap the real play (_play()) in a load() call to ensure sound was loaded
    # calling play on an already playing Sound object has no effect
    play: () ->
        if not @playing or (@source? and @source.playbackState == @source.FINISHED_STATE)
            @playing = true
            @load(() => @_play(@loop, @volume))
        
    _play: (looping, volume) ->
        @source = gGame.soundManager.getSoundSource(@key, { loop: looping, volume: volume })
        @source.start(0)
    
    stop: ->
        @source?.stop(0)
        @source = null
        @playing = false


        @mainNode.gain.value = 0

    unmute: ->
        @mainNode.gain.value = @defaultVolume
            
    stopAll: ->
        @mainNode.disconnect()
        @mainNode = @context.createGain()
        @mainNode.connect(@context.destination)
        @mainNode.gain.value = @defaultVolume
        
    getSoundSource: (key, settings) ->
        if !@enabled then return false
