diff --git a/src/import/load-sound.js b/src/import/load-sound.js
new file mode 100644
index 000000000..74856326a
--- /dev/null
+++ b/src/import/load-sound.js
@@ -0,0 +1,29 @@
+var AssetType = require('scratch-storage').AssetType;
+var log = require('../util/log');
+
+/**
+ * Load a sound's asset into memory asynchronously.
+ * @param {!object} sound - the Scratch sound object.
+ * @property {string} md5 - the MD5 and extension of the sound to be loaded.
+ * @property {Buffer} data - sound data will be written here once loaded.
+ * @param {!Runtime} runtime - Scratch runtime, used to access the storage module.
+ * @returns {!Promise} - a promise which will resolve after sound is loaded
+ */
+var loadSound = function (sound, runtime) {
+    if (!runtime.storage) {
+        log.error('No storage module present; cannot load sound asset: ', sound.md5);
+        return Promise.resolve(sound);
+    }
+    if (!runtime.audioEngine) {
+        log.error('No audio engine present; cannot load sound asset: ', sound.md5);
+        return Promise.resolve(sound);
+    }
+    var idParts = sound.md5.split('.');
+    var md5 = idParts[0];
+    return runtime.storage.load(AssetType.Sound, md5).then(function (soundAsset) {
+        sound.data = soundAsset.data;
+        return runtime.audioEngine.decodeSound(sound);
+    });
+};
+
+module.exports = loadSound;
diff --git a/src/import/sb2import.js b/src/import/sb2import.js
index 957eae38d..ac905d335 100644
--- a/src/import/sb2import.js
+++ b/src/import/sb2import.js
@@ -5,9 +5,6 @@
  * scratch-vm runtime structures.
  */
 
-var ScratchStorage = require('scratch-storage');
-var AssetType = ScratchStorage.AssetType;
-
 var Blocks = require('../engine/blocks');
 var RenderedTarget = require('../sprites/rendered-target');
 var Sprite = require('../sprites/sprite');
@@ -19,6 +16,7 @@ var Variable = require('../engine/variable');
 var List = require('../engine/list');
 
 var loadCostume = require('./load-costume.js');
+var loadSound = require('./load-sound.js');
 
 /**
  * Parse a single "Scratch object" and create all its in-memory VM objects.
@@ -148,30 +146,6 @@ var parseScratchObject = function (object, runtime, topLevel) {
     return target;
 };
 
-/**
- * Load a sound's asset into memory asynchronously.
- * @param {!object} sound - the Scratch sound object.
- * @property {string} md5 - the MD5 and extension of the sound to be loaded.
- * @property {Buffer} data - sound data will be written here once loaded.
- * @param {!Runtime} runtime - Scratch runtime, used to access the storage module.
- */
-var loadSound = function (sound, runtime) {
-    if (!runtime.storage) {
-        log.error('No storage module present; cannot load sound asset: ', sound.md5);
-        return;
-    }
-    if (!runtime.audioEngine) {
-        log.error('No audio engine present; cannot load sound asset: ', sound.md5);
-        return;
-    }
-    var idParts = sound.md5.split('.');
-    var md5 = idParts[0];
-    runtime.storage.load(AssetType.Sound, md5).then(function (soundAsset) {
-        sound.data = soundAsset.data;
-        runtime.audioEngine.decodeSound(sound);
-    });
-};
-
 /**
  * Top-level handler. Parse provided JSON,
  * and process the top-level object (the stage object).
diff --git a/src/virtual-machine.js b/src/virtual-machine.js
index 296cd45cf..b85705e37 100644
--- a/src/virtual-machine.js
+++ b/src/virtual-machine.js
@@ -8,6 +8,7 @@ var sb2import = require('./import/sb2import');
 var StringUtil = require('./util/string-util');
 
 var loadCostume = require('./import/load-costume.js');
+var loadSound = require('./import/load-sound.js');
 
 var RESERVED_NAMES = ['_mouse_', '_stage_', '_edge_', '_myself_', '_random_'];
 
@@ -209,6 +210,18 @@ VirtualMachine.prototype.addCostume = function (md5ext, costumeObject) {
     }.bind(this));
 };
 
+/**
+ * Add a sound to the current editing target.
+ * @param {!object} soundObject Object representing the costume.
+ * @returns {?Promise} - a promise that resolves when the sound has been decoded and added
+ */
+VirtualMachine.prototype.addSound = function (soundObject) {
+    return loadSound(soundObject, this.runtime).then(function () {
+        this.editingTarget.sprite.sounds.push(soundObject);
+        this.emitTargetsUpdate();
+    }.bind(this));
+};
+
 /**
  * Add a backdrop to the stage.
  * @param {string} md5ext - the MD5 and extension of the backdrop to be loaded.
diff --git a/test/unit/spec.js b/test/unit/spec.js
index 68485bf9d..b16f181f0 100644
--- a/test/unit/spec.js
+++ b/test/unit/spec.js
@@ -18,6 +18,7 @@ test('interface', function (t) {
     t.type(vm.addSprite2, 'function');
     t.type(vm.addCostume, 'function');
     t.type(vm.addBackdrop, 'function');
+    t.type(vm.addSound, 'function');
     t.type(vm.renameSprite, 'function');
     t.type(vm.deleteSprite, 'function');