[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 <audio> 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. '°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