changeset 1360:a9eb4f6443d8

Interfaces have startPlayback and stopPlayback methods to clean up code management. Looping playbacks now have a 2s cross-fade.
author Nicholas Jillings <nickjillings@users.noreply.github.com>
date Tue, 26 Jan 2016 13:52:56 +0000
parents 89ad0630d860
children 10ddee18db8d
files core.js example_eval/radio_example.xml interfaces/AB.js interfaces/ape.js interfaces/blank.js interfaces/discrete.js interfaces/horizontal-sliders.js interfaces/mushra.js
diffstat 8 files changed, 193 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/core.js	Tue Jan 26 11:32:11 2016 +0000
+++ b/core.js	Tue Jan 26 13:52:56 2016 +0000
@@ -1060,24 +1060,24 @@
 				interfaceContext.playhead.setTimePerPixel(this.audioObjects[id]);
 			}
 			if (this.loopPlayback) {
+                var setTime = audioContext.currentTime+2;
 				for (var i=0; i<this.audioObjects.length; i++)
 				{
-					this.audioObjects[i].play(this.timer.getTestTime()+1);
+					this.audioObjects[i].play(setTime-2);
 					if (id == i) {
-						this.audioObjects[i].loopStart();
+						this.audioObjects[i].loopStart(setTime);
 					} else {
-						this.audioObjects[i].loopStop();
+						this.audioObjects[i].loopStop(setTime);
 					}
 				}
 			} else {
+                var setTime = audioContext.currentTime+0.1;
 				for (var i=0; i<this.audioObjects.length; i++)
 				{
 					if (i != id) {
-						this.audioObjects[i].outputGain.gain.value = 0.0;
-						this.audioObjects[i].stop();
+						this.audioObjects[i].stop(setTime);
 					} else if (i == id) {
-						this.audioObjects[id].outputGain.gain.value = this.audioObjects[id].onplayGain;
-						this.audioObjects[id].play(audioContext.currentTime+0.01);
+						this.audioObjects[id].play(setTime);
 					}
 				}
 			}
@@ -1088,9 +1088,10 @@
 	this.stop = function() {
 		// Send stop and reset command to all playback buffers and set audioEngine state to stopped (1)
 		if (this.status == 1) {
+            var setTime = audioContext.currentTime+0.1;
 			for (var i=0; i<this.audioObjects.length; i++)
 			{
-				this.audioObjects[i].stop();
+				this.audioObjects[i].stop(setTime);
 			}
 			interfaceContext.playhead.stop();
 			this.status = 0;
@@ -1227,8 +1228,6 @@
 	this.bufferNode = undefined;
 	this.outputGain = audioContext.createGain();
 	
-	// Default output gain to be zero
-	this.outputGain.gain.value = 0.0;
 	this.onplayGain = 1.0;
 	
 	// Connect buffer to the audio graph
@@ -1287,16 +1286,18 @@
 		this.storeDOM.setAttribute('presentedId',interfaceObject.getPresentedId());
 	};
     
-	this.loopStart = function() {
-		this.outputGain.gain.value = this.onplayGain;
+	this.loopStart = function(setTime) {
+		this.outputGain.gain.linearRampToValueAtTime(this.onplayGain,setTime);
 		this.metric.startListening(audioEngineContext.timer.getTestTime());
+        this.interfaceDOM.startPlayback();
 	};
 	
-	this.loopStop = function() {
+	this.loopStop = function(setTime) {
 		if (this.outputGain.gain.value != 0.0) {
-			this.outputGain.gain.value = 0.0;
+			this.outputGain.gain.linearRampToValueAtTime(0.0,setTime);
 			this.metric.stopListening(audioEngineContext.timer.getTestTime());
 		}
+        this.interfaceDOM.stopPlayback();
 	};
 	
 	this.play = function(startTime) {
@@ -1309,22 +1310,29 @@
 			this.bufferNode.onended = function(event) {
 				// Safari does not like using 'this' to reference the calling object!
 				//event.currentTarget.owner.metric.stopListening(audioEngineContext.timer.getTestTime(),event.currentTarget.owner.getCurrentPosition());
-				event.currentTarget.owner.stop();
+				event.currentTarget.owner.stop(audioContext.currentTime+1);
 			};
 			if (this.bufferNode.loop == false) {
 				this.metric.startListening(audioEngineContext.timer.getTestTime());
-			}
+                this.outputGain.gain.setValueAtTime(this.onplayGain,startTime);
+                this.interfaceDOM.startPlayback();
+			} else {
+                 this.outputGain.gain.setValueAtTime(0.0,startTime);
+            }
 			this.bufferNode.start(startTime);
 		}
 	};
 	
-	this.stop = function() {
+	this.stop = function(stopTime) {
+        this.outputGain.gain.cancelScheduledValues(audioContext.currentTime);
 		if (this.bufferNode != undefined)
 		{
 			this.metric.stopListening(audioEngineContext.timer.getTestTime(),this.getCurrentPosition());
-			this.bufferNode.stop(0);
+			this.bufferNode.stop(stopTime);
 			this.bufferNode = undefined;
 		}
+        this.outputGain.gain.value = 0.0;
+        this.interfaceDOM.stopPlayback();
 	};
 	
 	this.getCurrentPosition = function() {
--- a/example_eval/radio_example.xml	Tue Jan 26 11:32:11 2016 +0000
+++ b/example_eval/radio_example.xml	Tue Jan 26 13:52:56 2016 +0000
@@ -28,7 +28,7 @@
 				<scalelabel position="100">(5) Inaudible</scalelabel>
 			</scales>
 		</interface>
-		<audioelement url="1.wav" id="track-1"/>
+		<audioelement url="0.wav" id="track-1"/>
 		<audioelement url="1.wav" id="track-2"/>
 	</page>
 </waet>
--- a/interfaces/AB.js	Tue Jan 26 11:32:11 2016 +0000
+++ b/interfaces/AB.js	Tue Jan 26 13:52:56 2016 +0000
@@ -208,10 +208,8 @@
 		};
 		this.playback.onclick = function(event)
 		{
-			$('.comparitor-button').text('Listen');
 			var id = event.currentTarget.parentElement.getAttribute('track-id');
 			audioEngineContext.play(id);
-			$(event.currentTarget).text('Playing');
 		};
 		
 		this.enable = function()
@@ -233,6 +231,15 @@
 				this.playback.textContent = "Listen";
 			}
 		};
+        this.startPlayback = function()
+        {
+            $('.comparitor-button').text('Listen');
+            $(this.playback).text('Playing');
+        };
+        this.stopPlayback = function()
+        {
+            $(this.playback).text('Listen');
+        };
 		this.exportXMLDOM = function(audioObject)
 		{
 			var node = storage.document.createElement('value');
--- a/interfaces/ape.js	Tue Jan 26 11:32:11 2016 +0000
+++ b/interfaces/ape.js	Tue Jan 26 13:52:56 2016 +0000
@@ -409,16 +409,6 @@
 			var id = Number(obj.attributes['trackIndex'].value);
 			//audioEngineContext.metric.sliderPlayed(id);
 			audioEngineContext.play(id);
-	        // Currently playing track red, rest green
-	        
-	        $('.track-slider').removeClass('track-slider-playing');
-	        var name = ".track-slider-"+obj.getAttribute("trackindex");
-	        $(name).addClass('track-slider-playing');
-	        $('.comment-div').removeClass('comment-box-playing');
-	        $('#comment-div-'+id).addClass('comment-box-playing');
-	        var outsideReference = document.getElementById('outside-reference');
-	        if (outsideReference != undefined)
-	        $(outsideReference).removeClass('track-slider-playing');
 		}
 		interfaceContext.releaseObject();
 	});
@@ -617,6 +607,23 @@
 			this.trackSliderObjects[0].children[0].textContent = this.parent.id;
 		}
 	};
+    this.startPlayback = function()
+    {
+        $('.track-slider').removeClass('track-slider-playing');
+        var name = ".track-slider-"+this.parent.id;
+        $(name).addClass('track-slider-playing');
+        $('.comment-div').removeClass('comment-box-playing');
+        $('#comment-div-'+this.parent.id).addClass('comment-box-playing');
+        var outsideReference = document.getElementById('outside-reference');
+        if (outsideReference != undefined)
+        $(outsideReference).removeClass('track-slider-playing');
+    };
+    this.stopPlayback = function()
+    {
+        var name = ".track-slider-"+this.parent.id;
+        $(name).removeClass('track-slider-playing');
+        $('#comment-div-'+this.parent.id).removeClass('comment-box-playing');
+    };
 	this.exportXMLDOM = function(audioObject) {
 		// Called by the audioObject holding this element. Must be present
 		var obj = [];
@@ -683,6 +690,16 @@
 			this.outsideReferenceHolder[0].children[0].textContent = "Play Reference";
 		}
 	};
+    this.startPlayback = function()
+    {
+        $('.track-slider').removeClass('track-slider-playing');
+        $(this.outsideReferenceHolder).addClass('track-slider-playing');
+        $('.comment-div').removeClass('comment-box-playing');
+    };
+    this.stopPlayback = function()
+    {
+        $(this.outsideReferenceHolder).removeClass('track-slider-playing');
+    };
 	this.exportXMLDOM = function(audioObject)
 	{
 		return null;
--- a/interfaces/blank.js	Tue Jan 26 11:32:11 2016 +0000
+++ b/interfaces/blank.js	Tue Jan 26 13:52:56 2016 +0000
@@ -29,6 +29,14 @@
 	{
 		// progress is a value from 0 to 100 indicating the current download state of media files
 	};
+    this.startPlayback = function()
+    {
+        // Called when playback has begun
+    };
+    this.stopPlayback = function()
+    {
+        // Called when playback has stopped. This gets called even if playback never started!
+    };
 	this.getValue = function()
 	{
 		// Return the current value of the object. If there is no value, return 0
--- a/interfaces/discrete.js	Tue Jan 26 11:32:11 2016 +0000
+++ b/interfaces/discrete.js	Tue Jan 26 13:52:56 2016 +0000
@@ -275,12 +275,6 @@
 		var id = Number(event.currentTarget.value);
 		//audioEngineContext.metric.sliderPlayed(id);
 		audioEngineContext.play(id);
-		$(".track-slider").removeClass('track-slider-playing');
-		$(event.currentTarget.parentElement).addClass('track-slider-playing');
-		var outsideReference = document.getElementById('outside-reference');
-		if (outsideReference != null) {
-			$(outsideReference).removeClass('track-slider-playing');
-		}
 	};
 	this.resize = function(event)
 	{
@@ -308,6 +302,23 @@
 	{
 		// progress is a value from 0 to 100 indicating the current download state of media files
 	};
+    
+    this.startPlayback = function()
+    {
+        // Called by audioObject when playback begins
+        $(".track-slider").removeClass('track-slider-playing');
+		$(this.holder).addClass('track-slider-playing');
+		var outsideReference = document.getElementById('outside-reference');
+		if (outsideReference != null) {
+			$(outsideReference).removeClass('track-slider-playing');
+		}
+    }
+    this.stopPlayback = function()
+    {
+        // Called by audioObject when playback stops
+        $(this.holder).removeClass('track-slider-playing');
+    }
+    
 	this.getValue = function()
 	{
 		// Return the current value of the object. If there is no value, return -1
--- a/interfaces/horizontal-sliders.js	Tue Jan 26 11:32:11 2016 +0000
+++ b/interfaces/horizontal-sliders.js	Tue Jan 26 13:52:56 2016 +0000
@@ -266,12 +266,6 @@
 		var id = Number(event.currentTarget.value);
 		//audioEngineContext.metric.sliderPlayed(id);
 		audioEngineContext.play(id);
-		$(".track-slider").removeClass('track-slider-playing');
-		$(event.currentTarget.parentElement).addClass('track-slider-playing');
-		var outsideReference = document.getElementById('outside-reference');
-		if (outsideReference != null) {
-			$(outsideReference).removeClass('track-slider-playing');
-		}
 	};
 	this.resize = function(event)
 	{
@@ -289,6 +283,21 @@
 	{
 		// progress is a value from 0 to 100 indicating the current download state of media files
 	};
+    this.startPlayback = function()
+    {
+        // Called when playback has begun
+        $(".track-slider").removeClass('track-slider-playing');
+		$(this.holder).addClass('track-slider-playing');
+		var outsideReference = document.getElementById('outside-reference');
+		if (outsideReference != null) {
+			$(outsideReference).removeClass('track-slider-playing');
+		}
+    };
+    this.stopPlayback = function()
+    {
+        // Called when playback has stopped. This gets called even if playback never started!
+        $(this.holder).removeClass('track-slider-playing');
+    };
 	this.getValue = function()
 	{
 		// Return the current value of the object. If there is no value, return 0
@@ -316,6 +325,69 @@
 	};
 };
 
+function outsideReferenceDOM(audioObject,index,inject)
+{
+	this.parent = audioObject;
+	this.outsideReferenceHolder = document.createElement('button');
+	this.outsideReferenceHolder.id = 'outside-reference';
+	this.outsideReferenceHolder.className = 'outside-reference';
+	this.outsideReferenceHolder.setAttribute('track-id',index);
+	this.outsideReferenceHolder.textContent = "Play Reference";
+	this.outsideReferenceHolder.disabled = true;
+	
+	this.outsideReferenceHolder.onclick = function(event)
+	{
+		audioEngineContext.play(event.currentTarget.getAttribute('track-id'));
+	};
+	inject.appendChild(this.outsideReferenceHolder);
+	this.enable = function()
+	{
+		if (this.parent.state == 1)
+		{
+			this.outsideReferenceHolder.disabled = false;
+		}
+	};
+	this.updateLoading = function(progress)
+	{
+		if (progress != 100)
+		{
+			progress = String(progress);
+			progress = progress.split('.')[0];
+			this.outsideReferenceHolder[0].children[0].textContent = progress+'%';
+		} else {
+			this.outsideReferenceHolder[0].children[0].textContent = "Play Reference";
+		}
+	};
+    this.startPlayback = function()
+    {
+        // Called when playback has begun
+        $('.track-slider').removeClass('track-slider-playing');
+        $('.comment-div').removeClass('comment-box-playing');
+        $(this.outsideReferenceHolder).addClass('track-slider-playing');
+    };
+    this.stopPlayback = function()
+    {
+        // Called when playback has stopped. This gets called even if playback never started!
+        $(this.outsideReferenceHolder).removeClass('track-slider-playing');
+    };
+	this.exportXMLDOM = function(audioObject)
+	{
+		return null;
+	};
+	this.getValue = function()
+	{
+		return 0;
+	};
+	this.getPresentedId = function()
+	{
+		return 'reference';
+	};
+	this.canMove = function()
+	{
+		return false;
+	};
+}
+
 function resizeWindow(event)
 {
 	// Called on every window resize event, use this to scale your page properly
--- a/interfaces/mushra.js	Tue Jan 26 11:32:11 2016 +0000
+++ b/interfaces/mushra.js	Tue Jan 26 13:52:56 2016 +0000
@@ -295,6 +295,21 @@
 		node.textContent = this.slider.value;
 		return node;
 	};
+    this.startPlayback = function()
+    {
+        // Called when playback has begun
+        $(".track-slider").removeClass('track-slider-playing');
+		$(this.holder).addClass('track-slider-playing');
+		var outsideReference = document.getElementById('outside-reference');
+		if (outsideReference != null) {
+			$(outsideReference).removeClass('track-slider-playing');
+		}
+    };
+    this.stopPlayback = function()
+    {
+        // Called when playback has stopped. This gets called even if playback never started!
+        $(this.holder).removeClass('track-slider-playing');
+    };
 	this.getValue = function() {
 		return this.slider.value;
 	};
@@ -338,9 +353,6 @@
 	this.outsideReferenceHolder.onclick = function(event)
 	{
 		audioEngineContext.play(event.currentTarget.getAttribute('track-id'));
-		$('.track-slider').removeClass('track-slider-playing');
-        $('.comment-div').removeClass('comment-box-playing');
-        $(event.currentTarget).addClass('track-slider-playing');
 	};
 	inject.appendChild(this.outsideReferenceHolder);
 	this.enable = function()
@@ -361,6 +373,18 @@
 			this.outsideReferenceHolder[0].children[0].textContent = "Play Reference";
 		}
 	};
+    this.startPlayback = function()
+    {
+        // Called when playback has begun
+        $('.track-slider').removeClass('track-slider-playing');
+        $('.comment-div').removeClass('comment-box-playing');
+        $(this.outsideReferenceHolder).addClass('track-slider-playing');
+    };
+    this.stopPlayback = function()
+    {
+        // Called when playback has stopped. This gets called even if playback never started!
+        $(this.outsideReferenceHolder).removeClass('track-slider-playing');
+    };
 	this.exportXMLDOM = function(audioObject)
 	{
 		return null;