diff --git a/app/lib/AudioPlayer.coffee b/app/lib/AudioPlayer.coffee
index b5eb4f70d..40b07974d 100644
--- a/app/lib/AudioPlayer.coffee
+++ b/app/lib/AudioPlayer.coffee
@@ -38,6 +38,7 @@ class AudioPlayer extends CocoClass
   constructor: () ->
     super()
     @ext = if createjs.Sound.getCapability('mp3') then '.mp3' else '.ogg'
+    @camera = null
     @listenToSound()
     @createNewManifest()
     @soundsToPlayWhenLoaded = {}
@@ -51,6 +52,14 @@ class AudioPlayer extends CocoClass
     # So for now, we'll just load through SoundJS instead.
     createjs.Sound.on 'fileload', @onSoundLoaded
 
+  applyPanning: (options, pos) ->
+    sup = @camera.worldToSurface pos
+    svp = @camera.surfaceViewport
+    pan = Math.max -1, Math.min 1, ((sup.x - svp.x) - svp.width / 2) / svp.width
+    dst = @camera.distanceRatioTo pos
+    vol = Math.min 1, options.volume / Math.pow (dst + 0.2), 2
+    volume: options.volume, delay: options.delay, pan: pan
+
   # PUBLIC LOADING METHODS
 
   soundForDialogue: (message, soundTriggers) ->
@@ -78,8 +87,11 @@ class AudioPlayer extends CocoClass
       @preloadInterfaceSounds [name] unless filename of cache
       @soundsToPlayWhenLoaded[name] = volume
 
-  playSound: (name, volume=1, delay=0) ->
-    instance = createjs.Sound.play name, {volume: (me.get('volume') ? 1) * volume, delay: delay}
+  playSound: (name, volume=1, delay=0, pos=null) ->
+    audioOptions = {volume: (me.get('volume') ? 1) * volume, delay: delay}
+    unless @camera is null or pos is null
+      audioOptions = @applyPanning audioOptions, pos
+    instance = createjs.Sound.play name, audioOptions
     instance
 
 #  # TODO: load Interface sounds somehow, somewhere, somewhen
diff --git a/app/lib/surface/CocoSprite.coffee b/app/lib/surface/CocoSprite.coffee
index 3a56f77e7..57146866a 100644
--- a/app/lib/surface/CocoSprite.coffee
+++ b/app/lib/surface/CocoSprite.coffee
@@ -188,14 +188,18 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     return 0 unless @thang.bobHeight
     @thang.bobHeight * (1 + Math.sin(@age * Math.PI / @thang.bobTime))
 
-  updatePosition: ->
-    return unless @thang?.pos and @options.camera?
-    [p0, p1] = [@lastPos, @thang.pos]
+  getWorldPosition: ->
+    p1 = @thang.pos
     if bobOffset = @getBobOffset()
       p1 = p1.copy?() or _.clone(p1)
       p1.z += bobOffset
+    x: p1.x, y: p1.y, z: if @thang.isLand then 0 else p1.z - @thang.depth / 2
+
+  updatePosition: ->
+    return unless @thang?.pos and @options.camera?
+    wop = @getWorldPosition()
+    [p0, p1] = [@lastPos, @thang.pos]
     return if p0 and p0.x is p1.x and p0.y is p1.y and p0.z is p1.z and not @options.camera.tweeningZoomTo
-    wop = x: p1.x, y: p1.y, z: if @thang.isLand then 0 else p1.z - @thang.depth / 2
     sup = @options.camera.worldToSurface wop
     [@displayObject.x, @displayObject.y] = [sup.x, sup.y]
     @lastPos = p1.copy?() or _.clone(p1)
@@ -477,6 +481,6 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
     return null unless sound
     delay = if withDelay and sound.delay then 1000 * sound.delay / createjs.Ticker.getFPS() else 0
     name = AudioPlayer.nameForSoundReference sound
-    instance = AudioPlayer.playSound name, volume, delay
+    instance = AudioPlayer.playSound name, volume, delay, @getWorldPosition()
 #    console.log @thang?.id, "played sound", name, "with delay", delay, "volume", volume, "and got sound instance", instance
     instance
diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee
index ec006d449..c5e15813d 100644
--- a/app/lib/surface/Surface.coffee
+++ b/app/lib/surface/Surface.coffee
@@ -360,6 +360,7 @@ module.exports = Surface = class Surface extends CocoClass
     canvasHeight = parseInt(@canvas.attr('height'), 10)
     @camera?.destroy()
     @camera = new Camera canvasWidth, canvasHeight
+    AudioPlayer.camera = @camera
     @layers.push @surfaceLayer = new Layer name: "Surface", layerPriority: 0, transform: Layer.TRANSFORM_SURFACE, camera: @camera
     @layers.push @surfaceTextLayer = new Layer name: "Surface Text", layerPriority: 1, transform: Layer.TRANSFORM_SURFACE_TEXT, camera: @camera
     @layers.push @screenLayer = new Layer name: "Screen", layerPriority: 2, transform: Layer.TRANSFORM_SCREEN, camera: @camera