[xiph-commits] r18628 - in websites/opus-codec.org/examples: . img js

jm at svn.xiph.org jm at svn.xiph.org
Fri Sep 21 16:53:23 PDT 2012


Author: jm
Date: 2012-09-21 16:53:23 -0700 (Fri, 21 Sep 2012)
New Revision: 18628

Added:
   websites/opus-codec.org/examples/img/
   websites/opus-codec.org/examples/img/jgauge_face_default.png
   websites/opus-codec.org/examples/img/jgauge_needle_default.png
   websites/opus-codec.org/examples/img/mono.png
   websites/opus-codec.org/examples/img/stereo.png
   websites/opus-codec.org/examples/jgauge.css
   websites/opus-codec.org/examples/js/
   websites/opus-codec.org/examples/js/jQueryRotate.min.js
   websites/opus-codec.org/examples/js/jgauge-0.3.0.a3.js
   websites/opus-codec.org/examples/sweep.ogg
Modified:
   websites/opus-codec.org/examples/index.shtml.en
Log:
Adds maikmerten code for the sweep demo


Added: websites/opus-codec.org/examples/img/jgauge_face_default.png
===================================================================
(Binary files differ)


Property changes on: websites/opus-codec.org/examples/img/jgauge_face_default.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: websites/opus-codec.org/examples/img/jgauge_needle_default.png
===================================================================
(Binary files differ)


Property changes on: websites/opus-codec.org/examples/img/jgauge_needle_default.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: websites/opus-codec.org/examples/img/mono.png
===================================================================
(Binary files differ)


Property changes on: websites/opus-codec.org/examples/img/mono.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Added: websites/opus-codec.org/examples/img/stereo.png
===================================================================
(Binary files differ)


Property changes on: websites/opus-codec.org/examples/img/stereo.png
___________________________________________________________________
Added: svn:mime-type
   + image/png

Modified: websites/opus-codec.org/examples/index.shtml.en
===================================================================
--- websites/opus-codec.org/examples/index.shtml.en	2012-09-21 19:38:29 UTC (rev 18627)
+++ websites/opus-codec.org/examples/index.shtml.en	2012-09-21 23:53:23 UTC (rev 18628)
@@ -1,9 +1,11 @@
 <!--#include virtual="/ssi/header.include" -->
 <!--#include virtual="/ssi/contentheader.include" -->
 
+    <link rel="stylesheet" href="jgauge.css" type="text/css" />
     <script type="text/javascript" src="../jquery.js"></script>
     <script type="text/javascript" src="../audiodemo.js"></script>
-
+    <script language="javascript" type="text/javascript" src="js/jQueryRotate.min.js"></script>
+    <script language="javascript" type="text/javascript" src="js/jgauge-0.3.0.a3.js"></script> 
 <h1>Opus Examples</h1>
 
 <h2>Audio samples</h2>
@@ -69,6 +71,133 @@
 
 </div>
 
+<h2>Bitrate scalability</h2>
+
+<p>
+The following example demonstrates what happens when grdually varying the
+bitrate from 8 kb/s to 64 kb/s. It's an extreme example, but it shows how Opus
+can change bandwidth and bitrate seamlessly without any glitch. In practical
+applications, bitrate changes are expected to occur much more slowly.
+</p>
+
+
+<table border="0">
+<tr>
+<td>
+	
+	<div id="gauge" class="jgauge"></div><br style="clear:both"/>
+	<center>Bitrate</center>
+</td>
+<td style="width:120px">
+	<center>
+		<span id="mono" style="display:none;font-family:serif;font-size:16pt;"><img src="img/mono.png" style="height:20px;vertical-align:middle;margin:5px;margin-right:20px;"/>Mono</span>
+		<span id="stereo" style="display:none;font-size:16pt;"><img src="img/stereo.png" style="height:20px;vertical-align:middle;margin:5px"/>Stereo</span>
+	</center>
+</td>
+<td>
+
+	<div id="gauge2" class="jgauge"></div><br style="clear:both"/> 
+	<center>Audio bandwidth</center>
+</td>
+<tr>
+<td colspan="3">
+	<br/>
+	<center><audio id="sweepaudio" src="sweep.ogg" controls style="width:400px"></audio></center>
+</td>
+</tr>
+</table>
+
+
+<script type="text/javascript">
+
+	var bitrateStart = 8;
+	var bitrateEnd = 64;
+
+
+	var bitrateGauge = new jGauge();
+	bitrateGauge.id = 'gauge';
+
+	var bandwidthGauge = new jGauge();
+	bandwidthGauge.id = 'gauge2';
+ 
+	// ugly, stupid way to update things. Welcome to 1997!
+	updateGauge = function() {
+		var audio = document.getElementById("sweepaudio");
+
+		if(audio.duration) {
+			var time = audio.currentTime;
+			var progress = time / audio.duration;
+			var bitrate = (bitrateEnd - bitrateStart) * progress + bitrateStart;
+			bitrateGauge.setValue(bitrate);
+
+			var stereo = document.getElementById("stereo");
+			var mono = document.getElementById("mono");
+
+			if(time < 8.3) {
+				stereo.style.display = "none";
+				mono.style.display = "";
+			} else {
+				stereo.style.display = "";
+				mono.style.display = "none";
+
+			}
+
+			var bandwidth = 4;
+			if(time > 1.4) {
+				bandwidth = 6;
+			}
+			if(time > 3.8) {
+				bandwidth = 8;
+			}
+			if(time > 6.2) {
+				bandwidth = 12;
+			}
+			if(time > 10.6) {
+				bandwidth = 20;
+			}
+			bandwidthGauge.setValue(bandwidth);
+
+		}
+
+		window.setTimeout(updateGauge, 100);
+	};
+
+
+	// This function is called by jQuery once the page has finished loading.
+	$(document).ready(function(){
+		bitrateGauge.init(); // Put the jGauge on the page by initialising it.
+
+		bitrateGauge.label.suffix = "kbps";
+		bitrateGauge.label.precision = 0;
+
+		bitrateGauge.ticks.count = 8;
+		bitrateGauge.ticks.start = 8;
+		bitrateGauge.ticks.end = bitrateEnd;
+
+		bitrateGauge.range.radius = 0;
+
+		bitrateGauge.updateRange();
+		bitrateGauge.updateTicks();
+
+		bandwidthGauge.init(); // Put the jGauge on the page by initialising it.
+
+		bandwidthGauge.label.suffix = "kHz";
+		bandwidthGauge.label.precision = 0;
+
+		bandwidthGauge.ticks.count = 5;
+		bandwidthGauge.ticks.start = 4;
+		bandwidthGauge.ticks.end = 20;
+
+		bandwidthGauge.range.radius = 0;
+
+		bandwidthGauge.updateRange();
+		bandwidthGauge.updateTicks();	
+
+		window.setTimeout(updateGauge, 10);
+	});
+</script> 
+
+
 <h2>Example of use in a web page</h2>
 <p>Opus works with the &lt;audio&gt; element just like any other audio format.</p>
 <p>For example, this code in a web page:</p>

Added: websites/opus-codec.org/examples/jgauge.css
===================================================================
--- websites/opus-codec.org/examples/jgauge.css	                        (rev 0)
+++ websites/opus-codec.org/examples/jgauge.css	2012-09-21 23:53:23 UTC (rev 18628)
@@ -0,0 +1,80 @@
+/*!
+ * jGauge v0.3.0 Alpha 2
+ * Gauge styling
+ * 
+ * Developed by Darian Cabot
+ * http://www.dariancabot.com/
+ * 
+ * Date: 28 October 2010
+ */
+
+div.jgauge
+{
+	background-repeat: no-repeat;
+	background-position: top center;
+	float: left;
+	height: 114px;
+	margin: 25px;
+	overflow: hidden;
+	position: relative;
+	width: 160px;
+	z-index: 0;
+}
+
+div.jgauge p.tick-label
+{
+	color: #327a9e;
+	display: none;
+	font-family: Verdana, Tahoma, Arial, Helvetica, sans-serif;
+	font-size: 9px;
+	height: 10px;
+	line-height: 10px;
+	margin: 0;
+	padding: 0;
+	position: absolute;
+	text-align: center;
+	width: 50px;
+	z-index: 3;
+}
+
+div.jgauge img.needle
+{
+	border: 0;
+	display: none;
+	margin: 0;
+	padding: 0;
+	position: absolute;
+	z-index: 5;
+}
+
+div.jgauge .needle
+{
+	z-index: 5;
+}
+
+div.jgauge p.label
+{
+	color: #144b66;
+	display: none;
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 16px;
+	height: 16px;
+	line-height: 16px;
+	margin: 0;
+	padding: 0;
+	position: absolute;
+	text-align: center;
+	text-shadow: 1px 1px 2px #bbb;
+	width: 100%;
+	z-index: 4;
+}
+
+div.jgauge canvas
+{
+	left: 0;
+	margin: 0;
+	padding: 0;
+	position: absolute;
+	top: 0;
+	z-index: 1;
+}

Added: websites/opus-codec.org/examples/js/jQueryRotate.min.js
===================================================================
--- websites/opus-codec.org/examples/js/jQueryRotate.min.js	                        (rev 0)
+++ websites/opus-codec.org/examples/js/jQueryRotate.min.js	2012-09-21 23:53:23 UTC (rev 18628)
@@ -0,0 +1,60 @@
+// VERSION: 1.4 LAST UPDATE: 23.06.2010
+/*!
+ * THIS IS FREE SCRIPT BUT LEAVE THIS COMMENT IF
+ * YOU WANT USE THIS CODE ON YOUR SITE
+ * 
+ * Made by Wilq32, wilq32 at gmail.com, Wroclaw, Poland, 01.2009
+ * http://wilq32.blogspot.com
+ * 
+ */
+
+ // Packed by Darian Cabot for jGauge on 20101012.
+(function($){var supportedCSS,styles=document.getElementsByTagName("head")[0].style,toCheck="transformProperty WebkitTransform OTransform".split(" ");for(var a=0;a<toCheck.length;a++)if(styles[toCheck[a]]!==undefined)supportedCSS=toCheck[a];jQuery.fn.extend({ImageRotate:function(parameters)
+{if(this.Wilq32&&this.Wilq32.PhotoEffect)return;var paramClone=$.extend(true,{},parameters)
+return(new Wilq32.PhotoEffect(this.get(0),paramClone))._temp;},rotate:function(parameters)
+{if(this.length===0)return;if(typeof parameters=="undefined")return;if(typeof parameters=="number")parameters={angle:parameters};var returned=[];for(var i=0,i0=this.length;i<i0;i++)
+{var element=this.get(i);if(typeof element.Wilq32=="undefined")
+returned.push($($(element).ImageRotate(parameters)));else
+{element.Wilq32.PhotoEffect._rotate(parameters.angle);}}
+return returned;},rotateAnimation:function(parameters)
+{if(this.length===0)return;if(typeof parameters=="undefined")return;if(typeof parameters=="number")parameters={angle:parameters};var returned=[];for(var i=0,i0=this.length;i<i0;i++)
+{var element=this.get(i);if(typeof element.Wilq32=="undefined")
+returned.push($($(element).ImageRotate(parameters)));else
+{element.Wilq32.PhotoEffect._parameters.animateAngle=parameters.angle;element.Wilq32.PhotoEffect._parameters.callback=parameters.callback||element.Wilq32.PhotoEffect._parameters.callback||function(){};element.Wilq32.PhotoEffect._animateStart();}}
+return returned;}});Wilq32={};Wilq32.PhotoEffect=(function(){if(supportedCSS)
+return function(img,parameters){this._img=img;this._parameters=parameters||{};this._parameters.animateAngle=0;this._parameters.angle=parameters.angle||0;this._angle=0;img.Wilq32={PhotoEffect:this};this._BindEvents(this._img,this._parameters.bind);this._rotate(this._parameters.angle);}
+else
+return function(img,parameters)
+{this._img=img;this._parameters=parameters||{};this._parameters.className=img.className;this._parameters.id=img.getAttribute('id');this._parameters.animateAngle=0;this._angle=0;this._parameters.angle=parameters.angle||0;this._temp=document.createElement('span');this._temp.style.display="inline-block";this._temp.Wilq32={PhotoEffect:this};img.parentNode.insertBefore(this._temp,img);this._img._ref=this;if(this._img.complete){this._Loader();}
+else{jQuery(this._img).bind("load",function()
+{this._ref._Loader.call(this._ref);});}}})();if(jQuery.browser.msie)
+{Wilq32.PhotoEffect.prototype.createVMLNode=(function(){document.createStyleSheet().addRule(".rvml","behavior:url(#default#VML)");try{!document.namespaces.rvml&&document.namespaces.add("rvml","urn:schemas-microsoft-com:vml");return function(tagName){return document.createElement('<rvml:'+tagName+' class="rvml">');};}catch(e){return function(tagName){return document.createElement('<'+tagName+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');};}})();}
+Wilq32.PhotoEffect.prototype._BindEvents=function(element,events){if(events)
+{for(var a in events)if(events.hasOwnProperty(a))
+for(var b in events[a])if(events[a].hasOwnProperty(b))
+jQuery(element).bind(b,events[a][b]);}}
+Wilq32.PhotoEffect.prototype._Loader=(function()
+{if(jQuery.browser.msie)
+return function()
+{var src=this._img.src;this._temp.setAttribute('id',this._parameters.id);this._temp.className=this._parameters.className;var width=this._img.width;var height=this._img.height;this._img.parentNode.removeChild(this._img);this._img._widthMax=this._img._heightMax=Math.sqrt((height)*(height)+(width)*(width));this._img._heightMax=Math.sqrt((height)*(height)+(width)*(width));this._vimage=this.createVMLNode('image');this._vimage._ref=this;this._vimage.style.height=height+"px";this._vimage.style.width=width+"px";this._temp.style.position="relative";this._vimage.style.position="absolute";this._temp.style.width=this._temp.style.height=this._img._heightMax+"px";this._vimage.src=src;this._temp.appendChild(this._vimage);this._temp.style.width=width+"px";this._temp.style.height=height+"px";this._vimage.style.top="0px";this._vimage.style.left="0px";var self=this;this._BindEvents(this._temp,this._parameters.bind);this._rotate(this._parameters.angle);}
+else
+return function()
+{this._temp.setAttribute('id',this._parameters.id);this._temp.className=this._parameters.className;var width=this._img.width;var height=this._img.height;this._img.parentNode.removeChild(this._img);this._img._widthMax=this._img._heightMax=Math.sqrt((height)*(height)+(width)*(width));this._canvas=document.createElement('canvas');this._canvas._ref=this;this._canvas.height=height;this._canvas.width=width;this._canvas.setAttribute('width',width);this._canvas.Wilq32=this._temp.Wilq32;this._temp.appendChild(this._canvas);this._temp.style.width=width+"px";this._temp.style.height=height+"px";this._canvas.style.position="relative";this._canvas.style.left=-(this._img._widthMax-width)/2+"px";this._canvas.style.top=-(this._img._widthMax-height)/2+"px";var self=this;this._BindEvents(this._canvas,this._parameters.bind);this._cnv=this._canvas.getContext('2d');this._rotate(this._parameters.angle);}})();Wilq32.PhotoEffect.prototype._animateStart=function()
+{if(this._timer){clearTimeout(this._timer);}
+this._animate();}
+Wilq32.PhotoEffect.prototype._animate=function()
+{if(this._canvas||this._vimage||this._img)this._angle-=(this._angle-this._parameters.animateAngle)*0.1;if(typeof this._parameters.minAngle!="undefined")if(this._angle<this._parameters.minAngle)this._angle=this._parameters.minAngle;if(typeof this._parameters.maxAngle!="undefined")if(this._angle>this._parameters.maxAngle)this._angle=this._parameters.maxAngle;var checkEnd=!!(Math.round(this._angle*100-this._parameters.animateAngle*100))==0&&!!this._timer;if(this._parameters.callback&&checkEnd){this._parameters.callback();}
+if(checkEnd&&!this._parameters.animatedGif)
+{clearTimeout(this._timer);}
+else
+{if(this._canvas||this._vimage||this._img)this._rotate((~~(this._angle*10))/10);var self=this;this._timer=setTimeout(function()
+{self._animate.call(self);},10);}}
+Wilq32.PhotoEffect.prototype._rotate=(function()
+{if(jQuery.browser.msie)
+return function(angle)
+{this._vimage.style.rotation=angle;}
+else if(supportedCSS)
+return function(angle){this._img.style[supportedCSS]="rotate("+angle+"deg)";}
+else
+return function(angle)
+{if(!this._img.width)return;if(typeof angle!="number")return;angle=(angle%360)*Math.PI/180;var width=this._img.width;var height=this._img.height;var widthAdd=this._img._widthMax-width;var heightAdd=this._img._heightMax-height;this._canvas.width=width+widthAdd;this._canvas.height=height+heightAdd;this._cnv.save();this._cnv.translate(widthAdd/2,heightAdd/2);this._cnv.translate(width/2,height/2);this._cnv.rotate(angle);this._cnv.translate(-width/2,-height/2);this._cnv.drawImage(this._img,0,0);this._cnv.restore();}})();})(jQuery);
\ No newline at end of file

Added: websites/opus-codec.org/examples/js/jgauge-0.3.0.a3.js
===================================================================
--- websites/opus-codec.org/examples/js/jgauge-0.3.0.a3.js	                        (rev 0)
+++ websites/opus-codec.org/examples/js/jgauge-0.3.0.a3.js	2012-09-21 23:53:23 UTC (rev 18628)
@@ -0,0 +1,749 @@
+/*!
+ * jGauge v0.3.0 Alpha 3
+ * http://www.jgauge.com/
+ * Date: 03 March 2011
+ *
+ * Copyright 2010-2011, Darian Cabot
+ * Licensed under the MIT license
+ * http://www.jgauge.com/#licence
+ */
+
+
+/*
+ * CHANGE LOG: VERSION 0.3.0 ALPHA 3:
+ * ====================================
+ *
+ *  - Added automatic 'SI/binary prefix' option for k, M, G, etc...
+ *
+ *  - Added SI/binary prefix support for gauge auto-ranging.
+ *
+ *  - Added auto-update off CSS from jGauge size settings.
+ *
+ *  - Added label and ticks.label color setting.
+ *
+ *  - Fixed findUpperLimit bug (not rounding value up).
+ *
+ *  - Fixed tick values and needle position when tick.start isn't 0 (zero).
+ *
+ *  - Fixed needle z-index issue.
+ *
+ *  - jGauge internals are more object oriented.
+ *
+ *  - All spelling for functions, vars, etc. changed to American-English from
+ *    Australian-English. This is to follow the general code standards and
+ *    avoid confusion.
+ *
+ * CHANGE LOG: VERSION 0.3.0 ALPHA 2:
+ * ====================================
+ *
+ *  - Angles now referenced with 0deg to the right (not to the top). This is the
+ *    more common standard.
+ *
+ *  - Defined 'jG' as base state for 'this' making code simpler and improving 
+ *    readability.
+ *
+ *  - Fixed canvas element sizing. Now done through DOM, not CSS which never
+ *    worked. This was only noticeable in gauges larger than 300x150 (the canvas
+ *    element's default size).
+ *    See: http://www.whatwg.org/specs/web-apps/current-work/#the-canvas-element
+ *
+ *  - All offsets now relative to gauge center point (not upper left corner).
+ *    This has made positioning elements more intuative for a dial/circle gauge.
+ *
+ *  - Finished the .updateRange() function.
+ *
+ *  - Created the .resetLayers() function to tidy up after gauge changes that
+ *    would otherwise bring the modified layer to front causing design problems.
+ *
+ *  - Consolidated number precision operations into a new .numberPrecision()
+ *    function to eliminate code doubling-up.
+ *
+ *  - The .findUpperLimit() function has been simplified and now allows for a
+ *    'multiple' to be specified to round up to.
+ *
+ *  - Made use of the .getHiddenDimensions() plugin to correctly layout label 
+ *    elements during initialisation even if the jGauge (or parent) is hidden.
+ *
+ *  - Various other code tweaks.
+ *
+ * KNOWN ISSUES:
+ * =============
+ *
+ *  - Canvas not working in Internet Explorer (ticks and range) despite 
+ *    excanvas.min.js.
+ *
+ *  - Updating range after initialisation renders arc as black 100% opacity
+ *    I've seen this behaviour in Chrome 7.0 and Safari.
+ *
+ *  - The limitAction only works for the upper bounds, not lower bounds.
+ *
+ *  - Upon first load (not cached) and using .setValue() for the first time
+ *    after .initialize(), the needle animates from 0deg (right-side), not from
+ *    the .tickStart value (usually left-side) as it should.
+ *
+ */
+
+
+// Global vars...
+
+// Expose the Limit Action Enum globally...
+var limitAction = 
+{
+        spin: 0,
+        clamp: 1,
+        autoRange: 2
+};
+
+var autoPrefix = 
+{
+        none: 0, // No SI or binary prefixing, normal comma segmented number.
+        si: 1, // SI prefixing (i.e. 1000^n) used for SI units / metric.
+        binary: 2 // Binary prefixing (i.e. 1024^n) used for computer units.
+};
+
+function jGauge()
+{
+        // Define var of current 'this' state (helps prevent 'this' abuse).
+        var jG = this;
+        
+        jG.version = '0.3.0.3'; // Major, minor, fix, release.
+        
+        jG.centerX = 0; // Internal use for positioning elements.
+        jG.centerY = 0; // Internal use for positioning elements.
+        
+        // DEFAULT PARAMETERS FOR jGAUGE...
+        jG.id = ''; // Default: nothing. Must be unique per jGauge instance.
+        jG.segmentStart = -200; // Relative to 0deg (3-o-clock position).
+        jG.segmentEnd = 20; // Relative to 0deg (3-o-clock position).
+        jG.imagePath = 'img/jgauge_face_default.png'; // Background image path.
+        jG.width = 160; // Total width of jGauge.
+        jG.height = 114; // Total height of jGauge.
+        jG.showAlerts = false; // Show error alerts? Useful when debugging.
+        
+        jG.autoPrefix = autoPrefix.si; // Automatically assigns prefix on label when approapriate (after value, before suffix) i.e. k, M, G, etc.
+        
+        jG.siPrefixes = ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
+        jG.binaryPrefixes = jG.siPrefixes;
+        
+        // Define the jGauge.needle object...
+        function needle()
+        {
+                var ndl = this;
+                ndl.imagePath = 'img/jgauge_needle_default.png'; // Needle image path.
+                ndl.limitAction = limitAction.autoRange; // What to do when the needle hits the limit.
+                ndl.xOffset = 0; // Shift needle position horizontally from center.
+                ndl.yOffset = 24; // Shift needle position vertically from center.
+        }
+        
+        // Add the needle object to the jGauge object.
+        jG.needle = new needle();
+        
+        // Define the jGauge.label object...
+        function label()
+        {
+                var lbl = this;
+                lbl.color = '#144b66'; // Text color applied as CSS.
+                lbl.precision = 1; // Value label rounding decimal places.
+                lbl.prefix = ''; // Prefix for the value label (i.e. '$').
+                lbl.suffix = ''; // Suffic for the value label (i.e. '&deg;C')
+                lbl.xOffset = 0; // Shift label horizontally from center.
+                lbl.yOffset = 20; // Shift label vertically from center.
+        }
+        
+        // Add the label object to the jGauge object.
+        jG.label = new label();
+        
+        // Define the jGauge.label object...
+        function ticks()
+        {
+                var tks = this;
+                tks.count = 11; // Number of tick marks around the gauge face.
+                tks.start = 0; // Value of the first tick mark.
+                tks.end = 10; // Value of the last tick mark.
+                tks.color = 'rgba(255, 255, 255, 1)'; // Tick mark color.
+                tks.thickness = 3; // Tick mark thickness.
+                tks.radius = 76; // Tick mark radius (from gauge center point).
+                tks.labelPrecision = 1; // Rounding decimals for tick labels.
+                tks.labelRadius = 63; // Tick label radius (from gauge center).
+                tks.labelColor = '#327a9e'; // Text color applied as CSS.
+        }
+        
+        // Add the ticks object to the jGauge object.
+        jG.ticks = new ticks();
+        
+        function range()
+        {
+                var rng = this;
+                rng.radius = 55; // Range arc radius (from gauge center).
+                rng.thickness = 36; // Range arc thickness (spread of the arc outwards).
+                rng.start = -24; // Range start point as an angle relative to 0deg (pointing right).
+                rng.end = 25; // Range end point as an angle relative to 0deg (pointing right).
+                rng.color = 'rgba(255, 32, 0, 0.2)'; // Color and alpha (opacity) of the range arc.
+        }
+        
+        jG.range = new range();
+        
+        jG.value = 0;
+        
+        // Function calls...
+        jG.init = init; // Initialises the gauge and puts it on the page.
+        jG.setValue = setValue; // Sets or updates the gauge value.
+        jG.getValue = getValue; // Gets the current gauge value.
+        jG.updateTicks = updateTicks; // Updates the tick marks and tick labels (call after changing tick parameters).
+        jG.updateRange = updateRange; // Updates the range (call after changing range parameters).
+        jG.resetLayers = resetLayers; // Puts all jGauge elements in the correct order. Intended for internal use.
+        jG.prefixNumber = prefixNumber; // Modifies number to SI/binary prefixing (i.e. 5000 becomes 5k).
+
+
+	/**
+	 * Initialises the gauge.
+	 * This creates the gauge and placing it on the page ready for use.
+	 * @author Darian Cabot
+	 */
+        function init()
+        {
+                var labelCssLeft;  // For horizontally positioning label.
+                var labelCssTop;   // For vertically positioning label.
+                var needleCssLeft; // For horizontally positioning needle.
+                var neeldeCssTop;  // For vertically positioning needle.
+                
+                // Find center of the gauge for positioning reference...
+                // TODO: Verify the .gaugeWidth with the placeholder DIV width (same for height).
+                jG.centerX = jG.width / 2;
+                jG.centerY = jG.height / 2;
+                
+                // Update gauge CSS with set jGauge dimensions.
+                $('#' + jG.id).css({'width': jG.width, 'height': jG.height});
+                
+                // Wipe the slate clean in case gauge already initialized.
+                $('#' + jG.id).children().remove();
+                
+                // Add the background image.
+                $('#' + jG.id).css('background-image', 'url("' + jG.imagePath + '")');
+                
+                // Create the range arcs and put them on the gauge.
+                jG.updateRange();
+                
+                // Create the ticks and put them on the gauge.
+                jG.updateTicks();
+                
+                // Add the main label...
+                htmlString = '<p id="' + jG.id + '-label" class="label">' + 
+                        jG.label.prefix + '<strong>' + jG.ticks.start + 
+                        '</strong>' + jG.label.suffix + '</p>';
+                        
+                $('#' + jG.id).append(htmlString);
+                
+                // Position the main label...
+                labelCssLeft = Math.round(jG.centerX - $('#' + jG.id + '-label').getHiddenDimensions().w / 2 + jG.label.xOffset) + 'px';
+                labelCssTop = Math.round(jG.centerY - $('#' + jG.id + '-label').getHiddenDimensions().h / 2 + jG.label.yOffset) + 'px';
+                $('#' + jG.id + '-label').css({'left': labelCssLeft, 'top': labelCssTop});
+                
+                // Apply label color...
+                $('#' + jG.id + ' .label').css('color', jG.label.color);
+                
+                
+                // Label created, so reveal it.
+                $('#' + jG.id + '-label').fadeIn('slow');
+                
+                
+                // Add the needle...
+                htmlString = '<img id="' + jG.id + '-needle" class="needle" src="' + jG.needle.imagePath + '" />';
+                $('#' + jG.id).append(htmlString);
+                
+                $('#' + jG.id + '-needle').load(function() {
+                        // Position needle once it's done loading...
+                        needleCssLeft = Math.round(jG.centerX - ($('#' + jG.id + '-needle').getHiddenDimensions().w / 2) + jG.needle.xOffset) + 'px';
+                        neeldeCssTop = Math.round(jG.centerY - ($('#' + jG.id + '-needle').getHiddenDimensions().h / 2) + jG.needle.yOffset) + 'px';
+                        $('#' + jG.id + '-needle').css({'left': needleCssLeft, 'top': neeldeCssTop});
+                });
+                
+                // Needle created, so reveal it.
+                $('#' + jG.id + '-needle').fadeIn('slow');
+                
+                // Ensure everything's in the correct order.
+                jG.resetLayers();
+                
+                // Set the needle to the lowest value.
+                // This is initially run TWICE to stop an animation glitch.
+                // If it's run only once, the next value will be animated from the needle in
+                // the 3-o-clock position even though it should come from it's initial position.
+                // I'll look into this further soon but it *may* be caused by jQueryRotate?
+                jG.setValue(jG.ticks.start);
+                jG.setValue(jG.ticks.start);
+        }
+
+
+	/**
+	 * Puts all of the jGauge elements in the correct order.
+	 * This is required because updating a single canvas layer was bringing
+	 * that layer to top messing up the design.
+	 * @author Darian Cabot
+	 */
+	function resetLayers()
+	{
+		$('#' + jG.id).css('z-index', 0);
+		$('#' + jG.id + '-canvas-ranges').css('z-index', 1);
+		$('#' + jG.id + '-canvas-ticks').css('z-index', 2);
+		$('#' + jG.id + ' .tick-label').css('z-index', 3);
+		$('#' + jG.id + '-label').css('z-index', 4);
+		$('#' + jG.id + '-needle').css('z-index', 5); // This one doesn't work (overwritten by jQueryRotate??).
+	}
+	
+	
+	/**
+	 * Creates the range arcs on the gauge face.
+	 * @author Darian Cabot
+	 */
+	function updateRange()
+	{
+	        var canvas; // The canvas used for the range.
+	        var ctx; // The 2D convas context for drawing.
+	        
+		// Remove any existing ticks canvas.
+		$('#' + jG.id + '-canvas-ranges').remove();
+		
+		// Create range arcs by drawing on a new canvas...
+		htmlString =  '<canvas id="' + jG.id + '-canvas-ranges"></canvas>';
+		$('#' + jG.id).append(htmlString);
+		
+		// Reference the canvas element we just created.
+		canvas = document.getElementById(jG.id + '-canvas-ranges');
+		
+		// Resize canvas...
+		canvas.width = jG.width;
+		canvas.height = jG.height;
+		
+		// Make sure we don't execute when canvas isn't supported.
+		if (canvas.getContext)
+		{
+			// Use getContext to use the canvas for drawing.
+			ctx = canvas.getContext('2d');
+			
+			ctx.strokeStyle = jG.range.color;
+			ctx.lineWidth = jG.range.thickness;
+			
+			ctx.beginPath();
+			
+			// The canvas arc parameters are as follows:...
+			// arc(x, y, radius, startAngle, endAngle, anticlockwise).
+			ctx.arc(jG.centerX + jG.needle.xOffset, 
+				jG.centerY + jG.needle.yOffset, 
+				jG.range.radius, 
+				(Math.PI / 180) * jG.range.start, 
+				(Math.PI / 180) * jG.range.end, 
+				false);
+			
+			// Draw range arc on canvas.
+			ctx.stroke();
+			jG.resetLayers();
+		}
+		else
+		{
+			// Canvas not supported!
+			
+			/* @TODO: alert() is a bit blunt, some other notification
+			 * should be used instead.
+			 */
+			
+			if (jG.showAlerts === true)
+			{
+				alert('Sorry, canvas is not supported by your browser!');
+			}
+		}
+	}
+	
+	
+	/**
+	 * Creates the tick marks and labels on the gauge face.
+	 * @author Darian Cabot
+	 */
+	function updateTicks()
+	{
+		var gaugeSegmentStep;
+		var htmlString;
+		var canvas;
+		var ctx;
+		var startAngle;
+		var endAngle;
+		var tickStep;
+		
+                var leftOffset;
+                var topOffset;
+                var tickLabelCssLeft;
+                var tickLabelCssTop;
+		
+		// FIRST: Draw ticks on gauge...
+		
+		// Remove any existing ticks canvas.
+		$('#' + jG.id + '-canvas-ticks').remove();
+		
+		// Check if there is actually anything to draw...
+		if (jG.ticks.count !== 0 || jG.ticks.thickness !== 0)
+		{
+			// Create ticks by drawing on a canvas...
+			htmlString = '<canvas id="' + jG.id + '-canvas-ticks"></canvas>';
+			$('#' + jG.id).append(htmlString);
+			
+			// Reference the canvas element we just created.
+			canvas = document.getElementById(jG.id + '-canvas-ticks');
+			
+			// Resize canvas...
+			canvas.width = jG.width;
+			canvas.height = jG.height;
+
+			// Make sure we don't execute when canvas isn't supported
+			if (canvas.getContext)
+			{
+				// use getContext to use the canvas for drawing
+				ctx = canvas.getContext('2d');
+				
+				// Draw ticks
+				gaugeSegmentStep = Math.abs(jG.segmentStart - jG.segmentEnd) / (jG.ticks.count - 1);
+				ctx.strokeStyle = jG.ticks.color;
+				ctx.lineWidth = 5;
+				
+				for (i = 0; i <= jG.ticks.count - 1; i ++)
+				{
+					startAngle = (Math.PI / 180) * (jG.segmentStart + (gaugeSegmentStep * i) - (jG.ticks.thickness / 2));
+					endAngle = (Math.PI / 180) * (jG.segmentStart + (gaugeSegmentStep * i) + (jG.ticks.thickness / 2));
+					
+					ctx.beginPath();
+					
+					ctx.arc(jG.centerX + jG.needle.xOffset, 
+						jG.centerY + jG.needle.yOffset, 
+						jG.ticks.radius, 
+						startAngle, 
+						endAngle, 
+						false);
+					
+					ctx.stroke();
+				}
+				jG.resetLayers();
+			}
+			else
+			{
+				// Canvas not supported!
+				
+				/* @TODO: alert() is a bit blunt, some other notification
+				 * should be used instead.
+				 */
+				 
+				if (jG.showAlerts === true)
+				{
+					alert('Sorry, canvas is not supported by your browser!');
+				}
+			}
+		}
+		
+		
+		// THIRD: Place tick labels on gauge...
+		
+		// Remove the existing tick labels.
+		$('#' + jG.id + ' .tick-label').remove();
+		
+		// Check if there is actually anything to draw...
+		if (jG.tickCount !== 0)
+		{
+			// Calculate the step value between each tick.
+			tickStep = (jG.ticks.end - jG.ticks.start) / (jG.ticks.count - 1);
+			gaugeSegmentStep = Math.abs(jG.segmentStart - jG.segmentEnd) / (jG.ticks.count - 1);
+
+			for (i = 0; i <= jG.ticks.count - 1; i ++)
+			{
+				// Calculate the tick value, round it, stick it in html...
+				//var htmlString = '<p class="tick-label">' + addCommas(numberPrecision((i * tickStep), jG.ticks.labelPrecision)) + '</p>';
+				htmlString = '<p class="tick-label">' + prefixNumber(jG.ticks.start + i * tickStep, false) + '</p>';
+				
+				
+				// Add the tick label...
+				$('#' + jG.id).append(htmlString);
+				
+				// Calculate the position of the tick label...
+				leftOffset = jG.centerX + jG.needle.xOffset - $('#' + jG.id + ' .tick-label').getHiddenDimensions().w / 2;
+				topOffset = jG.centerY + jG.needle.yOffset - $('#' + jG.id + ' .tick-label').getHiddenDimensions().h / 2;
+				tickLabelCssLeft = Math.round((jG.ticks.labelRadius * Math.cos((jG.segmentStart + (i * gaugeSegmentStep)) * Math.PI / 180)) + leftOffset) + 'px';
+				tickLabelCssTop = Math.round(jG.ticks.labelRadius * Math.sin(Math.PI / 180 * (jG.segmentStart + (i * gaugeSegmentStep))) + topOffset) + 'px';
+				
+				$('#' + jG.id + ' p:last').css({'left': tickLabelCssLeft, 'top': tickLabelCssTop});
+			}
+
+                        // Apply label color...
+                        $('#' + jG.id + ' .tick-label').css('color', jG.ticks.labelColor);
+                        
+			// Tick labels are all created, so reveal them together.
+			$('#' + jG.id + ' .tick-label').fadeIn('slow');
+		}
+	}
+
+
+	/**
+	 * Changes the gauge value (needle and read-out label).
+	 * The gauge must be initialized with createGauge() before this is called.
+	 * @author Darian Cabot
+	 * @param {Number} newValue The new value for the gauge.
+	 */
+	function setValue(newValue)
+	{
+	        var degreesMult;
+	        var valueDegrees;
+	        var htmlString;
+	        var needleCssLeft;
+	        var needleCssTop;
+	        
+		// First set the internal value variable (so we can return if required).
+		jG.value = newValue;
+		
+		// Scale the 'value' to 'degrees' around the gauge.
+		degreesMult = (jG.segmentEnd - jG.segmentStart) / (jG.ticks.end - jG.ticks.start);
+		valueDegrees = degreesMult * (newValue - jG.ticks.start);
+
+		// Check the needle is in bounds...
+		// TODO: This is only checking the upper limit, we should also be checking the lower limit.
+		if (valueDegrees > Math.abs(jG.segmentStart - jG.segmentEnd))
+		{
+			if (jG.needle.limitAction === limitAction.autoRange)
+			{
+                                jG.ticks.end = findUpperLimit(newValue, 10);
+                                jG.updateTicks();
+                                // TODO: update range also (range should be set with gauge values, not degress).
+
+                                // Scale the 'value' to 'degrees' around the gauge AGAIN.
+                                valueDegrees = newValue * (jG.segmentEnd - jG.segmentStart) / (jG.ticks.end - jG.ticks.start);
+			}
+			else if (jG.needle.limitAction === limitAction.clamp)
+			{
+                                // Clamp needle to gauge limit (stops the needle spinning).
+                                valueDegrees = Math.abs(jG.segmentStart - jG.segmentEnd);
+
+                                // Shake the needle to simulate bouncing off the limit...
+                                // TODO: wait until needle finished moving before 'bouncing'.
+                                $('#' + jG.id + '-needle')
+                                        .animate({ top: '+=2', left: '-=2' }, 50)
+                                        .animate({ top: '-=2', left: '+=2' }, 50)
+                                        .animate({ top: '+=2', left: '-=2' }, 50)
+                                        .animate({ top: '-=2', left: '+=2' }, 50);
+			}
+		}
+		
+		// Rotate the needle...
+		$('#' + jG.id + '-needle').rotateAnimation(jG.segmentStart + valueDegrees);
+		$('#' + jG.id + '-needle').css('position', 'absolute'); // This *MUST* be set after image-rotation!
+		
+		// Reposition needle (sometimes the needle moves off axis - witnessed in Firefox 3.6)...
+		needleCssLeft = Math.round(jG.centerX - $('#' + jG.id + '-needle').width() / 2 + jG.needle.xOffset) + 'px';
+		needleCssTop = Math.round(jG.centerY - $('#' + jG.id + '-needle').height() / 2 + jG.needle.yOffset) + 'px';
+		$('#' + jG.id + '-needle').css({'left': needleCssLeft, 'top': needleCssTop});
+		
+		// Build the label string (and apply any SI / binary prefix)...
+		htmlString = prefixNumber(newValue, true);
+		
+		// Update label value...
+		$('#' + jG.id + '-label').html(htmlString);
+	}
+	
+	
+	/**
+	 * Gets the gauge value.
+	 * @returns The current gauge value.
+	 * @type Number
+	 */
+	function getValue()
+	{
+		return this.value;
+	}
+	
+	
+	/**
+	 * Returns a SI / binary prefixed string from a number.
+	 * @author Darian Cabot
+	 * @param {Number} value A number to be rounded.
+	 * @param {Boolean} formatting Whether to include prefix/suffix and bold value (usually true for gauge label and false for tick labels).
+	 * @returns the SI/binary prefixed number as a string (i.e. 2500 becomes 2.5k).
+	 * @type String
+	 */
+	function prefixNumber(value, formatting)
+	{
+		var power = 0;
+		var prefix = '';
+		
+		switch (jG.autoPrefix)
+		{
+			case autoPrefix.si:
+				
+				while (value >= 1000)
+				{
+					power ++;
+					value /= 1000;
+				}
+				
+				prefix = jG.siPrefixes[power];
+				
+				break;
+			
+			case autoPrefix.binary:
+				
+				while (value >= 1024)
+				{
+					power ++;
+					value /= 1024;
+				}
+				
+				prefix = jG.binaryPrefixes[power];
+				
+				break;
+		}
+		
+		// Build the label string (and apply any SI / binary prefix)...
+		if (formatting === true)
+		{
+			return jG.label.prefix + '<strong>' + addCommas(numberPrecision(value, jG.label.precision)) + '</strong> ' + prefix + jG.label.suffix;
+		}
+		else
+		{
+			return addCommas(numberPrecision(value, jG.label.precision)) + prefix;
+		}
+	}
+	
+	
+	/**
+	 * Returns an upper limit (range) based on the value and multiple.
+	 * It rounds the value up the the closest multiple.
+	 * TODO: Factor in the number of ticks and avoid wierd decimal values for ticks.
+	 * @author Darian Cabot
+	 * @param {Number} value The gauge value that the range is to be suited to.
+	 * @param {Number} multiple The multiple to round up to.
+	 * @returns the closest multiple above the value.
+	 * @type Number
+	 */
+	function findUpperLimit(value, multiple)
+	{
+		
+		//return Math.ceil(Math.ceil(value) / multiple) * multiple; // Old method (prior to SI/binary prefixing).
+		
+		var power = 0;
+		var bump = 0;
+		
+		if (jG.autoPrefix === autoPrefix.binary)				
+		{
+			// Special case for binary mode...
+			
+			while (value >= 2)
+			{
+				power ++;
+				value /= 2;
+			}
+			
+			return Math.pow(2, power + 1);
+		}
+		else
+		{
+			multiple /= 10;
+			
+			while (value >= 10)
+			{
+				power ++;
+				value /= 10;
+			}
+			
+			while (value > bump)
+			{
+				bump += multiple;
+			}
+			
+			// parseInt is used to ensure there aren't any wierd float decimals (i.e. 4.999~ instead of 5).
+			return parseInt(bump * Math.pow(10, power), 10);
+		}
+	}
+	
+}
+
+
+// Helper functions...
+
+/**
+ * Returns a rounded number to the precision specified.
+ * @author Darian Cabot
+ * @param {Number} value A number to be rounded.
+ * @param {Number} decimals The number of decimal places to round to.
+ * @returns the value rounded to the number of decimal places specified.
+ * @type Number
+ */
+numberPrecision = function(value, decimals)
+{
+	return Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals);
+};
+
+
+/**
+ * Formats a numeric string by adding commas for cosmetic purposes.
+ * @author Keith Jenci
+ * @see http://www.mredkj.com/javascript/nfbasic.html
+ * @param {String} nStr A number with or without decimals.
+ * @returns a nicely formatted number.
+ * @type String
+ */
+addCommas = function(nStr)
+{
+	nStr += '';
+	var x = nStr.split('.');
+	var x1 = x[0];
+	var x2 = x.length > 1 ? '.' + x[1] : '';
+	var rgx = /(\d+)(\d{3})/;
+	
+	while (rgx.test(x1))
+	{
+		x1 = x1.replace(rgx, '$1' + ',' + '$2');
+	}
+	
+	return x1 + x2;
+};
+
+
+(function($)
+{
+	$.fn.getHiddenDimensions = function(boolOuter)
+	{
+		var $item = this;
+		var props = { position: 'absolute', visibility: 'hidden', display: 'block' };
+		var dim = { 'w':0, 'h':0 };
+		var $hiddenParents = $item.parents().andSelf().not(':visible');
+		
+		var oldProps = [];
+		$hiddenParents.each(function()
+		{
+			var old = {};
+			
+			for (var name in props)
+			{
+				old[ name ] = this.style[ name ];
+				this.style[ name ] = props[ name ];
+			}
+			
+			oldProps.push(old);
+		});
+		
+		if (!false === boolOuter)
+		{
+			dim.w = $item.outerWidth();
+			dim.h = $item.outerHeight();
+		}
+		else
+		{
+			dim.w = $item.width();
+			dim.h = $item.height();
+		}
+		
+		$hiddenParents.each(function(i)
+		{
+			var old = oldProps[i];
+			for (var name in props)
+			{
+				this.style[ name ] = old[ name ];
+			}
+		});
+		
+		return dim;
+	};
+}(jQuery));
+

Added: websites/opus-codec.org/examples/sweep.ogg
===================================================================
(Binary files differ)


Property changes on: websites/opus-codec.org/examples/sweep.ogg
___________________________________________________________________
Added: svn:mime-type
   + application/ogg



More information about the commits mailing list