├── .gitignore ├── bootstrap ├── img │ ├── glyphicons-halflings.png │ └── glyphicons-halflings-white.png ├── js │ ├── bootstrap-transition.js │ ├── bootstrap-alert.js │ ├── bootstrap-button.js │ ├── bootstrap-dropdown.js │ ├── bootstrap-popover.js │ ├── bootstrap-tab.js │ ├── bootstrap-scrollspy.js │ ├── bootstrap-collapse.js │ ├── bootstrap-carousel.js │ ├── bootstrap-modal.js │ ├── bootstrap-typeahead.js │ ├── bootstrap-tooltip.js │ └── bootstrap.min.js └── css │ ├── bootstrap-responsive.min.css │ └── bootstrap-responsive.css ├── app ├── js │ ├── mathutilities.js │ ├── editorapp.js │ ├── SpectrumDisplay.js │ ├── SpectrumWorker.js │ ├── filesystemutility.js │ ├── recorder.js │ ├── filedropbox.js │ ├── fft.js │ ├── recorderWorker.js │ ├── ACSpectrum.js │ ├── ACFIRFilter.js │ ├── ACAAFilter.js │ ├── binarytoolkit.js │ ├── audioplayback.js │ ├── wavetrack.js │ ├── ACFFT.js │ └── audiosequence.js └── mainstyle.css ├── README.md └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /bootstrap/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plucked/html5-audio-editor/HEAD/bootstrap/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /bootstrap/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/plucked/html5-audio-editor/HEAD/bootstrap/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /app/js/mathutilities.js: -------------------------------------------------------------------------------- 1 | var MathEx = new function MathEx() 2 | { 3 | this.lerp = function lerp(start, end, percentage) 4 | { 5 | if (start < end) 6 | { 7 | return start + (end - start) * percentage; 8 | } 9 | else 10 | { 11 | return end + (start - end) * (1.0 - percentage); 12 | } 13 | }; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | html5-audio-editor 2 | ================== 3 | 4 | A small audio editor written in html5 and javascript without usage of external plugins. 5 | 6 | 7 | You need the latest build of Google Chrome or the nightly build for Safari. Firefox is not supported yet. 8 | 9 | I'm working with Chrome Version 20.0.1132.47 beta and have to start Chrome with the parameter "--allow-file-access-from-files". You need this to start the web application from the local filesystem. 10 | 11 | If you want to see this application in action, go to http://plucked.de 12 | 13 | -------------------------------------------------------------------------------- /app/js/editorapp.js: -------------------------------------------------------------------------------- 1 | 2 | function onDocumentLoaded() 3 | { 4 | console.log("Loaded"); 5 | 6 | ACInitFFT(); 7 | 8 | initializeAudioLayerControls(); 9 | 10 | var audioLayerControl = document.querySelector("#audioLayerControl"); 11 | audioLayerControl.removeAllSequenceEditors(); 12 | var leftEditor = audioLayerControl.createSequenceEditor("Left Channel"); 13 | var rightEditor = audioLayerControl.createSequenceEditor("Right Channel"); 14 | 15 | audioLayerControl.setLinkMode(true); 16 | } -------------------------------------------------------------------------------- /bootstrap/js/bootstrap-transition.js: -------------------------------------------------------------------------------- 1 | /* =================================================== 2 | * bootstrap-transition.js v2.0.4 3 | * http://twitter.github.com/bootstrap/javascript.html#transitions 4 | * =================================================== 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | $(function () { 24 | 25 | "use strict"; // jshint ;_; 26 | 27 | 28 | /* CSS TRANSITION SUPPORT (http://www.modernizr.com/) 29 | * ======================================================= */ 30 | 31 | $.support.transition = (function () { 32 | 33 | var transitionEnd = (function () { 34 | 35 | var el = document.createElement('bootstrap') 36 | , transEndEventNames = { 37 | 'WebkitTransition' : 'webkitTransitionEnd' 38 | , 'MozTransition' : 'transitionend' 39 | , 'OTransition' : 'oTransitionEnd' 40 | , 'msTransition' : 'MSTransitionEnd' 41 | , 'transition' : 'transitionend' 42 | } 43 | , name 44 | 45 | for (name in transEndEventNames){ 46 | if (el.style[name] !== undefined) { 47 | return transEndEventNames[name] 48 | } 49 | } 50 | 51 | }()) 52 | 53 | return transitionEnd && { 54 | end: transitionEnd 55 | } 56 | 57 | })() 58 | 59 | }) 60 | 61 | }(window.jQuery); -------------------------------------------------------------------------------- /app/js/SpectrumDisplay.js: -------------------------------------------------------------------------------- 1 | function SpectrumDisplay(rootElement, divElement) 2 | { 3 | this.rootElement = rootElement; 4 | 5 | this.canvasRef = document.createElement("canvas"); 6 | this.canvasRef.id = "editor-spectrum"; 7 | divElement.appendChild(this.canvasRef); 8 | this.canvasRef.width = divElement.clientWidth; 9 | this.canvasRef.height = divElement.clientHeight; 10 | this.buffer = new Float32Array(this.canvasRef.width); 11 | this.min = -150;// decibel 12 | this.max = 0;// decibel 13 | this.range = this.max - this.min; 14 | this.minRange = this.canvasRef.height; 15 | 16 | this.updateBuffer = function updateBuffer(frequencyData) 17 | { 18 | this.min = -150; 19 | this.max = 0; 20 | 21 | for(var i = 0; i < this.buffer.length; ++i) 22 | { 23 | var data = frequencyData[Math.round(frequencyData.length / this.buffer.length * i)]; 24 | // clamp into range 25 | data = Math.min(this.max, Math.max(this.min, data)); 26 | this.buffer[i] = data; 27 | } 28 | }; 29 | 30 | this.paintSpectrum = function paintSpectrum() 31 | { 32 | var canvasContext = this.canvasRef.getContext('2d'); 33 | canvasContext.clearRect(0, 0, this.canvasRef.width, this.canvasRef.height); 34 | 35 | canvasContext.strokeStyle = "#369bd7"; 36 | canvasContext.beginPath(); 37 | 38 | // fit the y to display all values 39 | var yFactor = this.canvasRef.height / this.range; 40 | 41 | for(var i = 0 ; i < this.buffer.length - 1; ++i) 42 | { 43 | canvasContext.moveTo(i + 0.5, this.buffer[i] * -1.0 * yFactor); 44 | canvasContext.lineTo(i + 1.5, this.buffer[i + 1] * -1.0 * yFactor); 45 | } 46 | canvasContext.stroke(); 47 | 48 | canvasContext.fillStyle = canvasContext.strokeStyle; 49 | canvasContext.fillText(Math.round(this.max) + " db",0, 20); 50 | canvasContext.fillText(Math.round(this.min) + " db",0, this.canvasRef.height); 51 | }; 52 | } -------------------------------------------------------------------------------- /app/js/SpectrumWorker.js: -------------------------------------------------------------------------------- 1 | function SpectrumWorker() 2 | { 3 | this.toFrequencyDomain = function toFrequencyDomain(timeDomainRealIn, timeDomainImagIn, start, len, realOut, imagOut) 4 | { 5 | if (start === undefined) start = 0; 6 | if (len === undefined) len = timeDomainRealIn.length; 7 | 8 | if (IsPowerOfTwo(len) !== true) throw "The length of the timeDomain has to be power of two!"; 9 | 10 | var tempR = timeDomainRealIn.slice(start, start + len); 11 | var tempI = (timeDomainImagIn === undefined) ? undefined : timeDomainImagIn.slice(start, start + len); 12 | ACFFT(tempR.length, false, tempR, tempI, realOut, imagOut); 13 | }; 14 | 15 | this.fromFrequencyDomain = function fromFrequencyDomain(freqDomainRealIn, freqDomainImagIn, realOut, imagOut) 16 | { 17 | if (freqDomainRealIn.length !== freqDomainImagIn) throw "The real and imaginary arrays have a different size"; 18 | 19 | ACFFT(freqDomainRealIn.length, true, freqDomainRealIn, freqDomainImagIn, realOut, imagOut); 20 | }; 21 | 22 | this.toAmplitudeSpectrum = function toAmplitudeSpectrum(timeDomainData, sampleRate, start, len, windowSize, windowFuncId) 23 | { 24 | if (start === undefined) start = 0; 25 | if (len === undefined) len = timeDomainData.length; 26 | if (windowSize === undefined) windowSize = 1024; 27 | if (windowFuncId === undefined) windowFuncId = 4; 28 | if (sampleRate === undefined) sampleRate = 44100; 29 | 30 | if (timeDomainData.length < windowSize || len < windowSize) throw "Length of the timeDomainData is to small (minimum is the windowSize: " + windowSize + ")"; 31 | if (start < 0 || start >= timeDomainData.length) throw "Start is out of range"; 32 | if (start + len > timeDomainData.length) throw "Length is out of range"; 33 | 34 | var temp = timeDomainData.slice(start, start + len); 35 | var result = []; 36 | ComputeSpectrum(temp, temp.length, windowSize, sampleRate, result, false, windowFuncId); 37 | 38 | return result; 39 | }; 40 | 41 | this.toAmplitudeSpectrumFromAudioSequence = function toAmplitudeSpectrumFromAudioSequence(audioSequence, start, len, windowSize, windowFuncId) 42 | { 43 | return this.toAmplitudeSpectrum(audioSequence.data, audioSequence.sampleRate, start, len, windowSize, windowFuncId); 44 | }; 45 | 46 | 47 | } -------------------------------------------------------------------------------- /app/js/filesystemutility.js: -------------------------------------------------------------------------------- 1 | window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; 2 | 3 | 4 | var callback_requestSuccess = undefined; 5 | var callback_requestFailed = undefined; 6 | var fileSystemEntry = undefined; 7 | 8 | function getLocalStorage(sizeInBytes, requestSuccess, requestFailed) 9 | { 10 | callback_requestSuccess = requestSuccess; 11 | callback_requestFailed = requestFailed; 12 | 13 | // Webkit quota request for persistant storage 14 | window.webkitStorageInfo.requestQuota(PERSISTENT, sizeInBytes, successfulQuotaRequest,failedQuotaRequest); 15 | } 16 | 17 | function successfulQuotaRequest(grantedBytes) 18 | { 19 | window.requestFileSystem(PERSISTENT, grantedBytes, successfulFileSystemCreated, failedFileSystemCreation); 20 | } 21 | 22 | function failedQuotaRequest(errorCode) 23 | { 24 | if (callback_requestFailed !== undefined) callback_requestFailed(errorCode); 25 | } 26 | 27 | function successfulFileSystemCreated(fileSystem) 28 | { 29 | fileSystemEntry = fileSystem; 30 | if (callback_requestSuccess !== undefined) callback_requestSuccess(fileSystem); 31 | 32 | } 33 | 34 | function failedFileSystemCreation(errorCode) 35 | { 36 | if (callback_requestFailed !== undefined) callback_requestFailed(errorCode); 37 | } 38 | 39 | 40 | 41 | function readFile(filename, readSuccess, readError) 42 | { 43 | if (fileSystemEntry === undefined) debugger; 44 | 45 | fileSystemEntry.root.getFile(filename, {}, function(fileEntry) 46 | { 47 | fileEntry.file(function(file) 48 | { 49 | var reader = new FileReader(); 50 | reader.onload = function(evt) 51 | { 52 | readSuccess(evt, this); 53 | }; 54 | reader.readAsArrayBuffer(file); 55 | }); 56 | }, readError); 57 | } 58 | 59 | function writeFile(filename, writeFunction, writeError) 60 | { 61 | if (fileSystemEntry === undefined) debugger; 62 | 63 | var writeFunc = function() 64 | { 65 | var file = fileSystemEntry.root.getFile(filename, {create: true}, function(fileEntry) 66 | { 67 | var writer = fileEntry.createWriter(writeFunction); 68 | }, writeError); 69 | }; 70 | 71 | removeFile(filename, writeFunc, writeFunc); 72 | } 73 | 74 | function removeFile(filename, removeCallback, removeError) 75 | { 76 | fileSystemEntry.root.getFile(filename, {create: false}, function(fileEntry) 77 | { 78 | fileEntry.remove(removeCallback, removeError); 79 | }, removeError); 80 | } -------------------------------------------------------------------------------- /app/js/recorder.js: -------------------------------------------------------------------------------- 1 | (function(window){ 2 | 3 | var WORKER_PATH = 'recorderWorker.js'; 4 | 5 | var Recorder = function(source, cfg){ 6 | var config = cfg || {}; 7 | var bufferLen = config.bufferLen || 4096; 8 | this.context = source.context; 9 | this.node = (this.context.createScriptProcessor || 10 | this.context.createJavaScriptNode).call(this.context, 11 | bufferLen, 2, 2); 12 | var worker = new Worker(config.workerPath || WORKER_PATH); 13 | worker.postMessage({ 14 | command: 'init', 15 | config: { 16 | sampleRate: this.context.sampleRate 17 | } 18 | }); 19 | var recording = false, 20 | currCallback; 21 | 22 | this.node.onaudioprocess = function(e){ 23 | if (!recording) return; 24 | worker.postMessage({ 25 | command: 'record', 26 | buffer: [ 27 | e.inputBuffer.getChannelData(0), 28 | e.inputBuffer.getChannelData(1) 29 | ] 30 | }); 31 | } 32 | 33 | this.configure = function(cfg){ 34 | for (var prop in cfg){ 35 | if (cfg.hasOwnProperty(prop)){ 36 | config[prop] = cfg[prop]; 37 | } 38 | } 39 | } 40 | 41 | this.record = function(){ 42 | recording = true; 43 | } 44 | 45 | this.stop = function(){ 46 | recording = false; 47 | } 48 | 49 | this.clear = function(){ 50 | worker.postMessage({ command: 'clear' }); 51 | } 52 | 53 | this.getBuffer = function(cb) { 54 | currCallback = cb || config.callback; 55 | worker.postMessage({ command: 'getBuffer' }) 56 | } 57 | 58 | this.exportWAV = function(cb, type){ 59 | currCallback = cb || config.callback; 60 | type = type || config.type || 'audio/wav'; 61 | if (!currCallback) throw new Error('Callback not set'); 62 | worker.postMessage({ 63 | command: 'exportWAV', 64 | type: type 65 | }); 66 | } 67 | 68 | worker.onmessage = function(e){ 69 | var blob = e.data; 70 | currCallback(blob); 71 | } 72 | 73 | source.connect(this.node); 74 | this.node.connect(this.context.destination); //this should not be necessary 75 | }; 76 | 77 | Recorder.forceDownload = function(blob, filename){ 78 | var url = (window.URL || window.webkitURL).createObjectURL(blob); 79 | var link = window.document.createElement('a'); 80 | link.href = url; 81 | link.download = filename || 'output.wav'; 82 | var click = document.createEvent("Event"); 83 | click.initEvent("click", true, true); 84 | link.dispatchEvent(click); 85 | } 86 | 87 | window.Recorder = Recorder; 88 | 89 | })(window); 90 | -------------------------------------------------------------------------------- /bootstrap/js/bootstrap-alert.js: -------------------------------------------------------------------------------- 1 | /* ========================================================== 2 | * bootstrap-alert.js v2.0.4 3 | * http://twitter.github.com/bootstrap/javascript.html#alerts 4 | * ========================================================== 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* ALERT CLASS DEFINITION 27 | * ====================== */ 28 | 29 | var dismiss = '[data-dismiss="alert"]' 30 | , Alert = function (el) { 31 | $(el).on('click', dismiss, this.close) 32 | } 33 | 34 | Alert.prototype.close = function (e) { 35 | var $this = $(this) 36 | , selector = $this.attr('data-target') 37 | , $parent 38 | 39 | if (!selector) { 40 | selector = $this.attr('href') 41 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 42 | } 43 | 44 | $parent = $(selector) 45 | 46 | e && e.preventDefault() 47 | 48 | $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) 49 | 50 | $parent.trigger(e = $.Event('close')) 51 | 52 | if (e.isDefaultPrevented()) return 53 | 54 | $parent.removeClass('in') 55 | 56 | function removeElement() { 57 | $parent 58 | .trigger('closed') 59 | .remove() 60 | } 61 | 62 | $.support.transition && $parent.hasClass('fade') ? 63 | $parent.on($.support.transition.end, removeElement) : 64 | removeElement() 65 | } 66 | 67 | 68 | /* ALERT PLUGIN DEFINITION 69 | * ======================= */ 70 | 71 | $.fn.alert = function (option) { 72 | return this.each(function () { 73 | var $this = $(this) 74 | , data = $this.data('alert') 75 | if (!data) $this.data('alert', (data = new Alert(this))) 76 | if (typeof option == 'string') data[option].call($this) 77 | }) 78 | } 79 | 80 | $.fn.alert.Constructor = Alert 81 | 82 | 83 | /* ALERT DATA-API 84 | * ============== */ 85 | 86 | $(function () { 87 | $('body').on('click.alert.data-api', dismiss, Alert.prototype.close) 88 | }) 89 | 90 | }(window.jQuery); -------------------------------------------------------------------------------- /app/js/filedropbox.js: -------------------------------------------------------------------------------- 1 | /* Cross Browser Support */ 2 | window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; 3 | window.BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder; 4 | window.URL = window.URL || window.webkitURL; 5 | 6 | /* The FileDropbox prepares a HTMLElement to be a drop container and loads the first dropped file into a array */ 7 | function FileDropbox() 8 | { 9 | this.result = null; 10 | this.resultArrayBuffer = null; 11 | this.onFinish = null; 12 | this.onFail = null; 13 | 14 | this.defineDropHandler = function defineDropHandler(dropContainerElement) 15 | { 16 | // init event handlers 17 | dropContainerElement.addEventListener("dragenter", this.skipEventHandler, false); 18 | dropContainerElement.addEventListener("dragexit", this.skipEventHandler, false); 19 | dropContainerElement.addEventListener("dragover", this.skipEventHandler, false); 20 | dropContainerElement.addEventListener("drop", this.dropHandler, false); 21 | dropContainerElement.masterObj = this; // need to define this controller for further events 22 | }; 23 | 24 | this.skipEventHandler = function skipEventHandler(evt) 25 | { 26 | evt.stopPropagation(); 27 | evt.preventDefault(); 28 | }; 29 | 30 | this.dropHandler = function dropHandler(evt) 31 | { 32 | evt.stopPropagation(); 33 | evt.preventDefault(); 34 | 35 | // get list of dropped files 36 | var files = evt.dataTransfer.files; 37 | // amount of dropped files 38 | var count = files.length; 39 | 40 | // One file at least neccessary to continue 41 | if (count > 0) 42 | { 43 | handleFiles(files, evt.currentTarget.masterObj); 44 | } 45 | }; 46 | 47 | function handleFiles(files, masterObj) 48 | { 49 | // handle only the first file (no multifile support) 50 | var file = files[0]; 51 | // create the reader to access the local file (note: browser have different security restrictions) 52 | var reader = new FileReader(); 53 | 54 | // init the reader event handlers 55 | reader.onload = function (evt) 56 | { 57 | var arrayBuffer = evt.target.result; 58 | 59 | masterObj.resultArrayBuffer = arrayBuffer; 60 | // write into the result array 61 | masterObj.result = new Uint8Array(arrayBuffer); 62 | 63 | // callback 64 | if (masterObj.onFinish !== null) 65 | { 66 | masterObj.onFinish(); 67 | } 68 | }; // event handle on success 69 | 70 | reader.onerror = masterObj.onFail; // event handle on failure 71 | 72 | // load the file as array buffer 73 | reader.readAsArrayBuffer(file); 74 | } 75 | 76 | 77 | }; -------------------------------------------------------------------------------- /bootstrap/js/bootstrap-button.js: -------------------------------------------------------------------------------- 1 | /* ============================================================ 2 | * bootstrap-button.js v2.0.4 3 | * http://twitter.github.com/bootstrap/javascript.html#buttons 4 | * ============================================================ 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================ */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* BUTTON PUBLIC CLASS DEFINITION 27 | * ============================== */ 28 | 29 | var Button = function (element, options) { 30 | this.$element = $(element) 31 | this.options = $.extend({}, $.fn.button.defaults, options) 32 | } 33 | 34 | Button.prototype.setState = function (state) { 35 | var d = 'disabled' 36 | , $el = this.$element 37 | , data = $el.data() 38 | , val = $el.is('input') ? 'val' : 'html' 39 | 40 | state = state + 'Text' 41 | data.resetText || $el.data('resetText', $el[val]()) 42 | 43 | $el[val](data[state] || this.options[state]) 44 | 45 | // push to event loop to allow forms to submit 46 | setTimeout(function () { 47 | state == 'loadingText' ? 48 | $el.addClass(d).attr(d, d) : 49 | $el.removeClass(d).removeAttr(d) 50 | }, 0) 51 | } 52 | 53 | Button.prototype.toggle = function () { 54 | var $parent = this.$element.parent('[data-toggle="buttons-radio"]') 55 | 56 | $parent && $parent 57 | .find('.active') 58 | .removeClass('active') 59 | 60 | this.$element.toggleClass('active') 61 | } 62 | 63 | 64 | /* BUTTON PLUGIN DEFINITION 65 | * ======================== */ 66 | 67 | $.fn.button = function (option) { 68 | return this.each(function () { 69 | var $this = $(this) 70 | , data = $this.data('button') 71 | , options = typeof option == 'object' && option 72 | if (!data) $this.data('button', (data = new Button(this, options))) 73 | if (option == 'toggle') data.toggle() 74 | else if (option) data.setState(option) 75 | }) 76 | } 77 | 78 | $.fn.button.defaults = { 79 | loadingText: 'loading...' 80 | } 81 | 82 | $.fn.button.Constructor = Button 83 | 84 | 85 | /* BUTTON DATA-API 86 | * =============== */ 87 | 88 | $(function () { 89 | $('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) { 90 | var $btn = $(e.target) 91 | if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') 92 | $btn.button('toggle') 93 | }) 94 | }) 95 | 96 | }(window.jQuery); -------------------------------------------------------------------------------- /bootstrap/js/bootstrap-dropdown.js: -------------------------------------------------------------------------------- 1 | /* ============================================================ 2 | * bootstrap-dropdown.js v2.0.4 3 | * http://twitter.github.com/bootstrap/javascript.html#dropdowns 4 | * ============================================================ 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================ */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* DROPDOWN CLASS DEFINITION 27 | * ========================= */ 28 | 29 | var toggle = '[data-toggle="dropdown"]' 30 | , Dropdown = function (element) { 31 | var $el = $(element).on('click.dropdown.data-api', this.toggle) 32 | $('html').on('click.dropdown.data-api', function () { 33 | $el.parent().removeClass('open') 34 | }) 35 | } 36 | 37 | Dropdown.prototype = { 38 | 39 | constructor: Dropdown 40 | 41 | , toggle: function (e) { 42 | var $this = $(this) 43 | , $parent 44 | , selector 45 | , isActive 46 | 47 | if ($this.is('.disabled, :disabled')) return 48 | 49 | selector = $this.attr('data-target') 50 | 51 | if (!selector) { 52 | selector = $this.attr('href') 53 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 54 | } 55 | 56 | $parent = $(selector) 57 | $parent.length || ($parent = $this.parent()) 58 | 59 | isActive = $parent.hasClass('open') 60 | 61 | clearMenus() 62 | 63 | if (!isActive) $parent.toggleClass('open') 64 | 65 | return false 66 | } 67 | 68 | } 69 | 70 | function clearMenus() { 71 | $(toggle).parent().removeClass('open') 72 | } 73 | 74 | 75 | /* DROPDOWN PLUGIN DEFINITION 76 | * ========================== */ 77 | 78 | $.fn.dropdown = function (option) { 79 | return this.each(function () { 80 | var $this = $(this) 81 | , data = $this.data('dropdown') 82 | if (!data) $this.data('dropdown', (data = new Dropdown(this))) 83 | if (typeof option == 'string') data[option].call($this) 84 | }) 85 | } 86 | 87 | $.fn.dropdown.Constructor = Dropdown 88 | 89 | 90 | /* APPLY TO STANDARD DROPDOWN ELEMENTS 91 | * =================================== */ 92 | 93 | $(function () { 94 | $('html').on('click.dropdown.data-api', clearMenus) 95 | $('body') 96 | .on('click.dropdown', '.dropdown form', function (e) { e.stopPropagation() }) 97 | .on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle) 98 | }) 99 | 100 | }(window.jQuery); -------------------------------------------------------------------------------- /bootstrap/js/bootstrap-popover.js: -------------------------------------------------------------------------------- 1 | /* =========================================================== 2 | * bootstrap-popover.js v2.0.4 3 | * http://twitter.github.com/bootstrap/javascript.html#popovers 4 | * =========================================================== 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * =========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* POPOVER PUBLIC CLASS DEFINITION 27 | * =============================== */ 28 | 29 | var Popover = function ( element, options ) { 30 | this.init('popover', element, options) 31 | } 32 | 33 | 34 | /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js 35 | ========================================== */ 36 | 37 | Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, { 38 | 39 | constructor: Popover 40 | 41 | , setContent: function () { 42 | var $tip = this.tip() 43 | , title = this.getTitle() 44 | , content = this.getContent() 45 | 46 | $tip.find('.popover-title')[this.isHTML(title) ? 'html' : 'text'](title) 47 | $tip.find('.popover-content > *')[this.isHTML(content) ? 'html' : 'text'](content) 48 | 49 | $tip.removeClass('fade top bottom left right in') 50 | } 51 | 52 | , hasContent: function () { 53 | return this.getTitle() || this.getContent() 54 | } 55 | 56 | , getContent: function () { 57 | var content 58 | , $e = this.$element 59 | , o = this.options 60 | 61 | content = $e.attr('data-content') 62 | || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) 63 | 64 | return content 65 | } 66 | 67 | , tip: function () { 68 | if (!this.$tip) { 69 | this.$tip = $(this.options.template) 70 | } 71 | return this.$tip 72 | } 73 | 74 | }) 75 | 76 | 77 | /* POPOVER PLUGIN DEFINITION 78 | * ======================= */ 79 | 80 | $.fn.popover = function (option) { 81 | return this.each(function () { 82 | var $this = $(this) 83 | , data = $this.data('popover') 84 | , options = typeof option == 'object' && option 85 | if (!data) $this.data('popover', (data = new Popover(this, options))) 86 | if (typeof option == 'string') data[option]() 87 | }) 88 | } 89 | 90 | $.fn.popover.Constructor = Popover 91 | 92 | $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, { 93 | placement: 'right' 94 | , content: '' 95 | , template: '

' 96 | }) 97 | 98 | }(window.jQuery); -------------------------------------------------------------------------------- /app/js/fft.js: -------------------------------------------------------------------------------- 1 | var FFT = (function(){ 2 | 3 | var sin = Math.sin, 4 | cos = Math.cos, 5 | pi2 = Math.PI * 2; 6 | 7 | function twiddle(output, i, n, inverse){ 8 | var phase = (inverse ? pi2 : -pi2) * i / n; 9 | output[0] = cos(phase); 10 | output[1] = sin(phase); 11 | } 12 | 13 | function pass2(input, output, inverse, product){ 14 | var size = input.length * .5, 15 | i = 0, 16 | j = 0, 17 | factor = 2, 18 | m = size / factor, 19 | q = size / product, 20 | product1 = product / factor, 21 | jump = (factor - 1) * product1, 22 | twidlz = new Float32Array(2), 23 | k, k1, z0r, z0i, z1r, z1i, x0r, x0i, x1r, x1i; 24 | for (k=0; k> 1; 106 | if (v != 0) ++r; 107 | else break; 108 | } 109 | return r; 110 | 111 | }, 112 | forward: function(input){ 113 | fft(input, this.scratch, this.factors, true); 114 | }, 115 | backward: function(input){ 116 | fft(input, this.scratch, this.factors, false); 117 | } 118 | }; 119 | 120 | return FFT; 121 | 122 | }()); 123 | -------------------------------------------------------------------------------- /app/js/recorderWorker.js: -------------------------------------------------------------------------------- 1 | var recLength = 0, 2 | recBuffersL = [], 3 | recBuffersR = [], 4 | sampleRate; 5 | 6 | this.onmessage = function(e){ 7 | switch(e.data.command){ 8 | case 'init': 9 | init(e.data.config); 10 | break; 11 | case 'record': 12 | record(e.data.buffer); 13 | break; 14 | case 'exportWAV': 15 | exportWAV(e.data.type); 16 | break; 17 | case 'getBuffer': 18 | getBuffer(); 19 | break; 20 | case 'clear': 21 | clear(); 22 | break; 23 | } 24 | }; 25 | 26 | function init(config){ 27 | sampleRate = config.sampleRate; 28 | } 29 | 30 | function record(inputBuffer){ 31 | recBuffersL.push(inputBuffer[0]); 32 | recBuffersR.push(inputBuffer[1]); 33 | recLength += inputBuffer[0].length; 34 | } 35 | 36 | function exportWAV(type){ 37 | var bufferL = mergeBuffers(recBuffersL, recLength); 38 | var bufferR = mergeBuffers(recBuffersR, recLength); 39 | var interleaved = interleave(bufferL, bufferR); 40 | var dataview = encodeWAV(interleaved); 41 | var audioBlob = new Blob([dataview], { type: type }); 42 | 43 | this.postMessage(audioBlob); 44 | } 45 | 46 | function getBuffer() { 47 | var buffers = []; 48 | buffers.push( mergeBuffers(recBuffersL, recLength) ); 49 | buffers.push( mergeBuffers(recBuffersR, recLength) ); 50 | this.postMessage(buffers); 51 | } 52 | 53 | function clear(){ 54 | recLength = 0; 55 | recBuffersL = []; 56 | recBuffersR = []; 57 | } 58 | 59 | function mergeBuffers(recBuffers, recLength){ 60 | var result = new Float32Array(recLength); 61 | var offset = 0; 62 | for (var i = 0; i < recBuffers.length; i++){ 63 | result.set(recBuffers[i], offset); 64 | offset += recBuffers[i].length; 65 | } 66 | return result; 67 | } 68 | 69 | function interleave(inputL, inputR){ 70 | var length = inputL.length + inputR.length; 71 | var result = new Float32Array(length); 72 | 73 | var index = 0, 74 | inputIndex = 0; 75 | 76 | while (index < length){ 77 | result[index++] = inputL[inputIndex]; 78 | result[index++] = inputR[inputIndex]; 79 | inputIndex++; 80 | } 81 | return result; 82 | } 83 | 84 | function floatTo16BitPCM(output, offset, input){ 85 | for (var i = 0; i < input.length; i++, offset+=2){ 86 | var s = Math.max(-1, Math.min(1, input[i])); 87 | output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true); 88 | } 89 | } 90 | 91 | function writeString(view, offset, string){ 92 | for (var i = 0; i < string.length; i++){ 93 | view.setUint8(offset + i, string.charCodeAt(i)); 94 | } 95 | } 96 | 97 | function encodeWAV(samples){ 98 | var buffer = new ArrayBuffer(44 + samples.length * 2); 99 | var view = new DataView(buffer); 100 | 101 | /* RIFF identifier */ 102 | writeString(view, 0, 'RIFF'); 103 | /* file length */ 104 | view.setUint32(4, 32 + samples.length * 2, true); 105 | /* RIFF type */ 106 | writeString(view, 8, 'WAVE'); 107 | /* format chunk identifier */ 108 | writeString(view, 12, 'fmt '); 109 | /* format chunk length */ 110 | view.setUint32(16, 16, true); 111 | /* sample format (raw) */ 112 | view.setUint16(20, 1, true); 113 | /* channel count */ 114 | view.setUint16(22, 2, true); 115 | /* sample rate */ 116 | view.setUint32(24, sampleRate, true); 117 | /* byte rate (sample rate * block align) */ 118 | view.setUint32(28, sampleRate * 4, true); 119 | /* block align (channel count * bytes per sample) */ 120 | view.setUint16(32, 4, true); 121 | /* bits per sample */ 122 | view.setUint16(34, 16, true); 123 | /* data chunk identifier */ 124 | writeString(view, 36, 'data'); 125 | /* data chunk length */ 126 | view.setUint32(40, samples.length * 2, true); 127 | 128 | floatTo16BitPCM(view, 44, samples); 129 | 130 | return view; 131 | } 132 | -------------------------------------------------------------------------------- /app/js/ACSpectrum.js: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | 3 | Audacity: A Digital Audio Editor 4 | 5 | Spectrum.cpp 6 | 7 | Dominic Mazzoni 8 | 9 | *******************************************************************//*! 10 | 11 | \file Spectrum.cpp 12 | \brief Functions for computing Spectra. 13 | 14 | *//*******************************************************************/ 15 | 16 | 17 | 18 | 19 | function ComputeSpectrum(data, width, 20 | windowSize, 21 | rate, output, 22 | autocorrelation, windowFunc) 23 | { 24 | if (width < windowSize) 25 | return false; 26 | 27 | if (!data || !output) 28 | return true; 29 | 30 | var processed = new Float32Array(windowSize); 31 | 32 | var i; 33 | for (var i = 0; i < windowSize; i++) 34 | processed[i] = 0.0; 35 | var half = windowSize / 2; 36 | 37 | var inData = new Float32Array(windowSize); 38 | var out = new Float32Array(windowSize); 39 | var out2 = new Float32Array(windowSize); 40 | 41 | var start = 0; 42 | var windows = 0; 43 | while (start + windowSize <= width) { 44 | for (var i = 0; i < windowSize; i++) 45 | inData[i] = data[start + i]; 46 | 47 | WindowFunc(windowFunc, windowSize, inData); 48 | 49 | if (autocorrelation) { 50 | // Take FFT 51 | ACFFT(windowSize, false, inData, undefined, out, out2); 52 | 53 | // Compute power 54 | for (var i = 0; i < windowSize; i++) 55 | inData[i] = (out[i] * out[i]) + (out2[i] * out2[i]); 56 | 57 | // Tolonen and Karjalainen recommend taking the cube root 58 | // of the power, instead of the square root 59 | 60 | for (var i = 0; i < windowSize; i++) 61 | inData[i] = Math.pow(inData[i], 1.0 / 3.0); 62 | 63 | ACFFT(windowSize, false, inData, undefined, out, out2); 64 | } 65 | else 66 | PowerSpectrum(windowSize, inData, out); 67 | 68 | // Take real part of result 69 | for (var i = 0; i < half; i++) 70 | processed[i] += out[i]; 71 | 72 | start += half; 73 | windows++; 74 | } 75 | 76 | if (autocorrelation) { 77 | 78 | // Peak Pruning as described by Tolonen and Karjalainen, 2000 79 | /* 80 | Combine most of the calculations in a Math.Math.Math.single for loop. 81 | It should be safe, as indexes refer only to current and previous elements, 82 | that have already been clipped, etc... 83 | */ 84 | for (var i = 0; i < half; i++) { 85 | // Clip at zero, copy to temp array 86 | if (processed[i] < 0.0) 87 | processed[i] = 0.0; 88 | out[i] = processed[i]; 89 | // Subtract a time-doubled signal (linearly interp.) from the original 90 | // (clipped) signal 91 | if ((i % 2) == 0) 92 | processed[i] -= out[i / 2]; 93 | else 94 | processed[i] -= ((out[i / 2] + out[i / 2 + 1]) / 2); 95 | 96 | // Clip at zero again 97 | if (processed[i] < 0.0) 98 | processed[i] = 0.0; 99 | } 100 | 101 | // Reverse and scale 102 | for (var i = 0; i < half; i++) 103 | inData[i] = processed[i] / (windowSize / 4); 104 | for (var i = 0; i < half; i++) 105 | processed[half - 1 - i] = inData[i]; 106 | } else { 107 | // Convert to decibels 108 | // But do it safely; -Inf is nobody's friend 109 | for (var i = 0; i < half; i++){ 110 | var temp=(processed[i] / windowSize / windows); 111 | if (temp > 0.0) 112 | processed[i] = 10 * Math.log(temp) / Math.LN10; 113 | else 114 | processed[i] = 0; 115 | } 116 | } 117 | 118 | for (var i = 0; i < half; i++) 119 | output[i] = processed[i]; 120 | 121 | 122 | return true; 123 | } -------------------------------------------------------------------------------- /bootstrap/js/bootstrap-tab.js: -------------------------------------------------------------------------------- 1 | /* ======================================================== 2 | * bootstrap-tab.js v2.0.4 3 | * http://twitter.github.com/bootstrap/javascript.html#tabs 4 | * ======================================================== 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ======================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* TAB CLASS DEFINITION 27 | * ==================== */ 28 | 29 | var Tab = function ( element ) { 30 | this.element = $(element) 31 | } 32 | 33 | Tab.prototype = { 34 | 35 | constructor: Tab 36 | 37 | , show: function () { 38 | var $this = this.element 39 | , $ul = $this.closest('ul:not(.dropdown-menu)') 40 | , selector = $this.attr('data-target') 41 | , previous 42 | , $target 43 | , e 44 | 45 | if (!selector) { 46 | selector = $this.attr('href') 47 | selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 48 | } 49 | 50 | if ( $this.parent('li').hasClass('active') ) return 51 | 52 | previous = $ul.find('.active a').last()[0] 53 | 54 | e = $.Event('show', { 55 | relatedTarget: previous 56 | }) 57 | 58 | $this.trigger(e) 59 | 60 | if (e.isDefaultPrevented()) return 61 | 62 | $target = $(selector) 63 | 64 | this.activate($this.parent('li'), $ul) 65 | this.activate($target, $target.parent(), function () { 66 | $this.trigger({ 67 | type: 'shown' 68 | , relatedTarget: previous 69 | }) 70 | }) 71 | } 72 | 73 | , activate: function ( element, container, callback) { 74 | var $active = container.find('> .active') 75 | , transition = callback 76 | && $.support.transition 77 | && $active.hasClass('fade') 78 | 79 | function next() { 80 | $active 81 | .removeClass('active') 82 | .find('> .dropdown-menu > .active') 83 | .removeClass('active') 84 | 85 | element.addClass('active') 86 | 87 | if (transition) { 88 | element[0].offsetWidth // reflow for transition 89 | element.addClass('in') 90 | } else { 91 | element.removeClass('fade') 92 | } 93 | 94 | if ( element.parent('.dropdown-menu') ) { 95 | element.closest('li.dropdown').addClass('active') 96 | } 97 | 98 | callback && callback() 99 | } 100 | 101 | transition ? 102 | $active.one($.support.transition.end, next) : 103 | next() 104 | 105 | $active.removeClass('in') 106 | } 107 | } 108 | 109 | 110 | /* TAB PLUGIN DEFINITION 111 | * ===================== */ 112 | 113 | $.fn.tab = function ( option ) { 114 | return this.each(function () { 115 | var $this = $(this) 116 | , data = $this.data('tab') 117 | if (!data) $this.data('tab', (data = new Tab(this))) 118 | if (typeof option == 'string') data[option]() 119 | }) 120 | } 121 | 122 | $.fn.tab.Constructor = Tab 123 | 124 | 125 | /* TAB DATA-API 126 | * ============ */ 127 | 128 | $(function () { 129 | $('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 130 | e.preventDefault() 131 | $(this).tab('show') 132 | }) 133 | }) 134 | 135 | }(window.jQuery); -------------------------------------------------------------------------------- /app/js/ACFIRFilter.js: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | /// 3 | /// General FIR digital filter routines with MMX optimization. 4 | /// 5 | /// Note : MMX optimized functions reside in a separate, platform-specific file, 6 | /// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp' 7 | /// 8 | /// Author : Copyright (c) Olli Parviainen 9 | /// Author e-mail : oparviai 'at' iki.fi 10 | /// SoundTouch WWW: http://www.surina.net/soundtouch 11 | /// 12 | //////////////////////////////////////////////////////////////////////////////// 13 | // 14 | // Last changed : $Date: 2006-09-18 22:29:22 $ 15 | // File revision : $Revision: 1.4 $ 16 | // 17 | // $Id: FIRFilter.cpp,v 1.4 2006-09-18 22:29:22 martynshaw Exp $ 18 | // 19 | //////////////////////////////////////////////////////////////////////////////// 20 | // 21 | // License : 22 | // 23 | // SoundTouch audio processing library 24 | // Copyright (c) Olli Parviainen 25 | // 26 | // This library is free software; you can redistribute it and/or 27 | // modify it under the terms of the GNU Lesser General Public 28 | // License as published by the Free Software Foundation; either 29 | // version 2.1 of the License, or (at your option) any later version. 30 | // 31 | // This library is distributed in the hope that it will be useful, 32 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 33 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 34 | // Lesser General Public License for more details. 35 | // 36 | // You should have received a copy of the GNU Lesser General Public 37 | // License along with this library; if not, write to the Free Software 38 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 39 | // 40 | //////////////////////////////////////////////////////////////////////////////// 41 | 42 | 43 | /***************************************************************************** 44 | * 45 | * Implementation of the class 'FIRFilter' 46 | * 47 | *****************************************************************************/ 48 | 49 | function ACFIRFilter() 50 | { 51 | this.resultDivFactor = 0; 52 | this.length = 0; 53 | this.lengthDiv8 = 0; 54 | this.filterCoeffs = undefined; 55 | this.resultDivider = 0; 56 | 57 | this.evaluateFilter = function(dest, src, numSamples) 58 | { 59 | var i, j, end; 60 | var sum; 61 | var dScaler = 1.0 / this.resultDivider; 62 | 63 | 64 | if (this.length === 0) debugger; 65 | 66 | end = numSamples - this.length; 67 | var srcPos = 0; 68 | for (var j = 0; j < end; j ++) 69 | { 70 | sum = 0; 71 | for (var i = 0; i < this.length; i += 4) 72 | { 73 | // loop is unrolled by factor of 4 here for efficiency 74 | sum += src[srcPos + i + 0] * this.filterCoeffs[i + 0] + 75 | src[srcPos + i + 1] * this.filterCoeffs[i + 1] + 76 | src[srcPos + i + 2] * this.filterCoeffs[i + 2] + 77 | src[srcPos + i + 3] * this.filterCoeffs[i + 3]; 78 | } 79 | 80 | sum *= dScaler; 81 | 82 | dest[j] = sum; 83 | srcPos++; 84 | } 85 | return end; 86 | } 87 | 88 | this.setCoefficients = function setCoefficients(coeffs, newLength, uResultDivFactor) 89 | { 90 | if (newLength === 0) debugger; 91 | if (newLength % 8) throw ("FIR filter length not divisible by 8"); 92 | 93 | this.lengthDiv8 = newLength / 8; 94 | this.length = this.lengthDiv8 * 8; 95 | if (this.length !== newLength) debugger; 96 | 97 | this.resultDivFactor = uResultDivFactor; 98 | this.resultDivider = Math.pow(2., this.resultDivFactor); 99 | 100 | this.filterCoeffs = new Float32Array(this.length); 101 | for (var i = 0; i < this.filterCoeffs.length; ++i) 102 | { 103 | this.filterCoeffs[i] = coeffs[i]; 104 | } 105 | } 106 | 107 | this.getLength = function getLength() 108 | { 109 | return this.length; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /bootstrap/js/bootstrap-scrollspy.js: -------------------------------------------------------------------------------- 1 | /* ============================================================= 2 | * bootstrap-scrollspy.js v2.0.4 3 | * http://twitter.github.com/bootstrap/javascript.html#scrollspy 4 | * ============================================================= 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* SCROLLSPY CLASS DEFINITION 27 | * ========================== */ 28 | 29 | function ScrollSpy( element, options) { 30 | var process = $.proxy(this.process, this) 31 | , $element = $(element).is('body') ? $(window) : $(element) 32 | , href 33 | this.options = $.extend({}, $.fn.scrollspy.defaults, options) 34 | this.$scrollElement = $element.on('scroll.scroll.data-api', process) 35 | this.selector = (this.options.target 36 | || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 37 | || '') + ' .nav li > a' 38 | this.$body = $('body') 39 | this.refresh() 40 | this.process() 41 | } 42 | 43 | ScrollSpy.prototype = { 44 | 45 | constructor: ScrollSpy 46 | 47 | , refresh: function () { 48 | var self = this 49 | , $targets 50 | 51 | this.offsets = $([]) 52 | this.targets = $([]) 53 | 54 | $targets = this.$body 55 | .find(this.selector) 56 | .map(function () { 57 | var $el = $(this) 58 | , href = $el.data('target') || $el.attr('href') 59 | , $href = /^#\w/.test(href) && $(href) 60 | return ( $href 61 | && href.length 62 | && [[ $href.position().top, href ]] ) || null 63 | }) 64 | .sort(function (a, b) { return a[0] - b[0] }) 65 | .each(function () { 66 | self.offsets.push(this[0]) 67 | self.targets.push(this[1]) 68 | }) 69 | } 70 | 71 | , process: function () { 72 | var scrollTop = this.$scrollElement.scrollTop() + this.options.offset 73 | , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight 74 | , maxScroll = scrollHeight - this.$scrollElement.height() 75 | , offsets = this.offsets 76 | , targets = this.targets 77 | , activeTarget = this.activeTarget 78 | , i 79 | 80 | if (scrollTop >= maxScroll) { 81 | return activeTarget != (i = targets.last()[0]) 82 | && this.activate ( i ) 83 | } 84 | 85 | for (i = offsets.length; i--;) { 86 | activeTarget != targets[i] 87 | && scrollTop >= offsets[i] 88 | && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) 89 | && this.activate( targets[i] ) 90 | } 91 | } 92 | 93 | , activate: function (target) { 94 | var active 95 | , selector 96 | 97 | this.activeTarget = target 98 | 99 | $(this.selector) 100 | .parent('.active') 101 | .removeClass('active') 102 | 103 | selector = this.selector 104 | + '[data-target="' + target + '"],' 105 | + this.selector + '[href="' + target + '"]' 106 | 107 | active = $(selector) 108 | .parent('li') 109 | .addClass('active') 110 | 111 | if (active.parent('.dropdown-menu')) { 112 | active = active.closest('li.dropdown').addClass('active') 113 | } 114 | 115 | active.trigger('activate') 116 | } 117 | 118 | } 119 | 120 | 121 | /* SCROLLSPY PLUGIN DEFINITION 122 | * =========================== */ 123 | 124 | $.fn.scrollspy = function ( option ) { 125 | return this.each(function () { 126 | var $this = $(this) 127 | , data = $this.data('scrollspy') 128 | , options = typeof option == 'object' && option 129 | if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options))) 130 | if (typeof option == 'string') data[option]() 131 | }) 132 | } 133 | 134 | $.fn.scrollspy.Constructor = ScrollSpy 135 | 136 | $.fn.scrollspy.defaults = { 137 | offset: 10 138 | } 139 | 140 | 141 | /* SCROLLSPY DATA-API 142 | * ================== */ 143 | 144 | $(function () { 145 | $('[data-spy="scroll"]').each(function () { 146 | var $spy = $(this) 147 | $spy.scrollspy($spy.data()) 148 | }) 149 | }) 150 | 151 | }(window.jQuery); -------------------------------------------------------------------------------- /bootstrap/js/bootstrap-collapse.js: -------------------------------------------------------------------------------- 1 | /* ============================================================= 2 | * bootstrap-collapse.js v2.0.4 3 | * http://twitter.github.com/bootstrap/javascript.html#collapse 4 | * ============================================================= 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================ */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* COLLAPSE PUBLIC CLASS DEFINITION 27 | * ================================ */ 28 | 29 | var Collapse = function (element, options) { 30 | this.$element = $(element) 31 | this.options = $.extend({}, $.fn.collapse.defaults, options) 32 | 33 | if (this.options.parent) { 34 | this.$parent = $(this.options.parent) 35 | } 36 | 37 | this.options.toggle && this.toggle() 38 | } 39 | 40 | Collapse.prototype = { 41 | 42 | constructor: Collapse 43 | 44 | , dimension: function () { 45 | var hasWidth = this.$element.hasClass('width') 46 | return hasWidth ? 'width' : 'height' 47 | } 48 | 49 | , show: function () { 50 | var dimension 51 | , scroll 52 | , actives 53 | , hasData 54 | 55 | if (this.transitioning) return 56 | 57 | dimension = this.dimension() 58 | scroll = $.camelCase(['scroll', dimension].join('-')) 59 | actives = this.$parent && this.$parent.find('> .accordion-group > .in') 60 | 61 | if (actives && actives.length) { 62 | hasData = actives.data('collapse') 63 | if (hasData && hasData.transitioning) return 64 | actives.collapse('hide') 65 | hasData || actives.data('collapse', null) 66 | } 67 | 68 | this.$element[dimension](0) 69 | this.transition('addClass', $.Event('show'), 'shown') 70 | this.$element[dimension](this.$element[0][scroll]) 71 | } 72 | 73 | , hide: function () { 74 | var dimension 75 | if (this.transitioning) return 76 | dimension = this.dimension() 77 | this.reset(this.$element[dimension]()) 78 | this.transition('removeClass', $.Event('hide'), 'hidden') 79 | this.$element[dimension](0) 80 | } 81 | 82 | , reset: function (size) { 83 | var dimension = this.dimension() 84 | 85 | this.$element 86 | .removeClass('collapse') 87 | [dimension](size || 'auto') 88 | [0].offsetWidth 89 | 90 | this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') 91 | 92 | return this 93 | } 94 | 95 | , transition: function (method, startEvent, completeEvent) { 96 | var that = this 97 | , complete = function () { 98 | if (startEvent.type == 'show') that.reset() 99 | that.transitioning = 0 100 | that.$element.trigger(completeEvent) 101 | } 102 | 103 | this.$element.trigger(startEvent) 104 | 105 | if (startEvent.isDefaultPrevented()) return 106 | 107 | this.transitioning = 1 108 | 109 | this.$element[method]('in') 110 | 111 | $.support.transition && this.$element.hasClass('collapse') ? 112 | this.$element.one($.support.transition.end, complete) : 113 | complete() 114 | } 115 | 116 | , toggle: function () { 117 | this[this.$element.hasClass('in') ? 'hide' : 'show']() 118 | } 119 | 120 | } 121 | 122 | 123 | /* COLLAPSIBLE PLUGIN DEFINITION 124 | * ============================== */ 125 | 126 | $.fn.collapse = function (option) { 127 | return this.each(function () { 128 | var $this = $(this) 129 | , data = $this.data('collapse') 130 | , options = typeof option == 'object' && option 131 | if (!data) $this.data('collapse', (data = new Collapse(this, options))) 132 | if (typeof option == 'string') data[option]() 133 | }) 134 | } 135 | 136 | $.fn.collapse.defaults = { 137 | toggle: true 138 | } 139 | 140 | $.fn.collapse.Constructor = Collapse 141 | 142 | 143 | /* COLLAPSIBLE DATA-API 144 | * ==================== */ 145 | 146 | $(function () { 147 | $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) { 148 | var $this = $(this), href 149 | , target = $this.attr('data-target') 150 | || e.preventDefault() 151 | || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 152 | , option = $(target).data('collapse') ? 'toggle' : $this.data() 153 | $(target).collapse(option) 154 | }) 155 | }) 156 | 157 | }(window.jQuery); -------------------------------------------------------------------------------- /app/js/ACAAFilter.js: -------------------------------------------------------------------------------- 1 | 2 | //////////////////////////////////////////////////////////////////////////////// 3 | /// 4 | /// FIR low-pass (anti-alias) filter with filter coefficient design routine and 5 | /// MMX optimization. 6 | /// 7 | /// Anti-alias filter is used to prevent folding of high frequencies when 8 | /// transposing the sample rate with interpolation. 9 | /// 10 | /// Author : Copyright (c) Olli Parviainen 11 | /// Author e-mail : oparviai 'at' iki.fi 12 | /// SoundTouch WWW: http://www.surina.net/soundtouch 13 | /// 14 | //////////////////////////////////////////////////////////////////////////////// 15 | // 16 | // Last changed : $Date: 2006-09-18 22:29:22 $ 17 | // File revision : $Revision: 1.4 $ 18 | // 19 | // $Id: AAFilter.cpp,v 1.4 2006-09-18 22:29:22 martynshaw Exp $ 20 | // 21 | //////////////////////////////////////////////////////////////////////////////// 22 | // 23 | // License : 24 | // 25 | // SoundTouch audio processing library 26 | // Copyright (c) Olli Parviainen 27 | // 28 | // This library is free software; you can redistribute it and/or 29 | // modify it under the terms of the GNU Lesser General Public 30 | // License as published by the Free Software Foundation; either 31 | // version 2.1 of the License, or (at your option) any later version. 32 | // 33 | // This library is distributed in the hope that it will be useful, 34 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 35 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 36 | // Lesser General Public License for more details. 37 | // 38 | // You should have received a copy of the GNU Lesser General Public 39 | // License along with this library; if not, write to the Free Software 40 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 41 | // 42 | //////////////////////////////////////////////////////////////////////////////// 43 | 44 | function ACAAFilter(length) 45 | { 46 | if (length === undefined) length = 32; 47 | 48 | this.pFIR = new ACFIRFilter(); 49 | this.cutoffFreq = 0.9; 50 | this.length = 0; 51 | 52 | this.setCutoffFreq = function setCutoffFreq(newCutoffFreq) 53 | { 54 | this.cutoffFreq = newCutoffFreq; 55 | this.calculateCoeffs(); 56 | }; 57 | 58 | this.setLength = function setLength(newLength) 59 | { 60 | this.length = newLength; 61 | this.calculateCoeffs(); 62 | }; 63 | 64 | this.calculateCoeffs = function calculateCoeffs() 65 | { 66 | var i; 67 | var cntTemp, temp, tempCoeff,h, w; 68 | var fc2, wc; 69 | var scaleCoeff, sum; 70 | var work; 71 | var coeffs; 72 | 73 | if (this.length <= 0 || this.length % 4 != 0 || this.cutoffFreq < 0 || this.cutoffFreq > 1.5) debugger; 74 | 75 | work = new Float32Array(this.length); 76 | this.coeffs = new Float32Array(this.length); 77 | 78 | fc2 = 2.0 * this.cutoffFreq; 79 | wc = Math.PI * fc2; 80 | tempCoeff = Math.PI * 2 / length; 81 | 82 | sum = 0; 83 | for (i = 0; i < this.length; i ++) 84 | { 85 | cntTemp = i - (this.length / 2); 86 | 87 | temp = cntTemp * wc; 88 | if (temp != 0) 89 | { 90 | h = fc2 * Math.sin(temp) / temp; // sinc function 91 | } 92 | else 93 | { 94 | h = 1.0; 95 | } 96 | w = 0.54 + 0.46 * Math.cos(tempCoeff * cntTemp); // hamming window 97 | 98 | temp = w * h; 99 | work[i] = temp; 100 | 101 | // calc net sum of coefficients 102 | sum += temp; 103 | } 104 | 105 | // ensure the sum of coefficients is larger than zero 106 | /* assert(sum > 0); 107 | 108 | // ensure we've really designed a lowpass filter... 109 | assert(work[length/2] > 0); 110 | assert(work[length/2 + 1] > -1e-6); 111 | assert(work[length/2 - 1] > -1e-6); 112 | */ 113 | // Calculate a scaling coefficient in such a way that the result can be 114 | // divided by 16384 115 | scaleCoeff = 16384.0 / sum; 116 | 117 | for (var i = 0; i < this.length; i ++) 118 | { 119 | // scale & round to nearest integer 120 | temp = work[i] * scaleCoeff; 121 | temp += (temp >= 0) ? 0.5 : -0.5; 122 | // ensure no overfloods 123 | if (temp < -32768 || temp > 32767) debugger; 124 | this.coeffs[i] = temp; 125 | } 126 | 127 | // Set coefficients. Use divide factor 14 => divide result by 2^14 = 16384 128 | this.pFIR.setCoefficients(this.coeffs, this.length, 14); 129 | } 130 | 131 | this.evaluate = function evaluate(dest, src, numSamples) 132 | { 133 | return this.pFIR.evaluateFilter(dest, src, numSamples); 134 | }; 135 | 136 | this.getLength = function getLength() 137 | { 138 | return this.pFIR.getLength(); 139 | }; 140 | 141 | this.setLength(length); 142 | } 143 | 144 | -------------------------------------------------------------------------------- /bootstrap/js/bootstrap-carousel.js: -------------------------------------------------------------------------------- 1 | /* ========================================================== 2 | * bootstrap-carousel.js v2.0.4 3 | * http://twitter.github.com/bootstrap/javascript.html#carousel 4 | * ========================================================== 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================== */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* CAROUSEL CLASS DEFINITION 27 | * ========================= */ 28 | 29 | var Carousel = function (element, options) { 30 | this.$element = $(element) 31 | this.options = options 32 | this.options.slide && this.slide(this.options.slide) 33 | this.options.pause == 'hover' && this.$element 34 | .on('mouseenter', $.proxy(this.pause, this)) 35 | .on('mouseleave', $.proxy(this.cycle, this)) 36 | } 37 | 38 | Carousel.prototype = { 39 | 40 | cycle: function (e) { 41 | if (!e) this.paused = false 42 | this.options.interval 43 | && !this.paused 44 | && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) 45 | return this 46 | } 47 | 48 | , to: function (pos) { 49 | var $active = this.$element.find('.active') 50 | , children = $active.parent().children() 51 | , activePos = children.index($active) 52 | , that = this 53 | 54 | if (pos > (children.length - 1) || pos < 0) return 55 | 56 | if (this.sliding) { 57 | return this.$element.one('slid', function () { 58 | that.to(pos) 59 | }) 60 | } 61 | 62 | if (activePos == pos) { 63 | return this.pause().cycle() 64 | } 65 | 66 | return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos])) 67 | } 68 | 69 | , pause: function (e) { 70 | if (!e) this.paused = true 71 | clearInterval(this.interval) 72 | this.interval = null 73 | return this 74 | } 75 | 76 | , next: function () { 77 | if (this.sliding) return 78 | return this.slide('next') 79 | } 80 | 81 | , prev: function () { 82 | if (this.sliding) return 83 | return this.slide('prev') 84 | } 85 | 86 | , slide: function (type, next) { 87 | var $active = this.$element.find('.active') 88 | , $next = next || $active[type]() 89 | , isCycling = this.interval 90 | , direction = type == 'next' ? 'left' : 'right' 91 | , fallback = type == 'next' ? 'first' : 'last' 92 | , that = this 93 | , e = $.Event('slide') 94 | 95 | this.sliding = true 96 | 97 | isCycling && this.pause() 98 | 99 | $next = $next.length ? $next : this.$element.find('.item')[fallback]() 100 | 101 | if ($next.hasClass('active')) return 102 | 103 | if ($.support.transition && this.$element.hasClass('slide')) { 104 | this.$element.trigger(e) 105 | if (e.isDefaultPrevented()) return 106 | $next.addClass(type) 107 | $next[0].offsetWidth // force reflow 108 | $active.addClass(direction) 109 | $next.addClass(direction) 110 | this.$element.one($.support.transition.end, function () { 111 | $next.removeClass([type, direction].join(' ')).addClass('active') 112 | $active.removeClass(['active', direction].join(' ')) 113 | that.sliding = false 114 | setTimeout(function () { that.$element.trigger('slid') }, 0) 115 | }) 116 | } else { 117 | this.$element.trigger(e) 118 | if (e.isDefaultPrevented()) return 119 | $active.removeClass('active') 120 | $next.addClass('active') 121 | this.sliding = false 122 | this.$element.trigger('slid') 123 | } 124 | 125 | isCycling && this.cycle() 126 | 127 | return this 128 | } 129 | 130 | } 131 | 132 | 133 | /* CAROUSEL PLUGIN DEFINITION 134 | * ========================== */ 135 | 136 | $.fn.carousel = function (option) { 137 | return this.each(function () { 138 | var $this = $(this) 139 | , data = $this.data('carousel') 140 | , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) 141 | if (!data) $this.data('carousel', (data = new Carousel(this, options))) 142 | if (typeof option == 'number') data.to(option) 143 | else if (typeof option == 'string' || (option = options.slide)) data[option]() 144 | else if (options.interval) data.cycle() 145 | }) 146 | } 147 | 148 | $.fn.carousel.defaults = { 149 | interval: 5000 150 | , pause: 'hover' 151 | } 152 | 153 | $.fn.carousel.Constructor = Carousel 154 | 155 | 156 | /* CAROUSEL DATA-API 157 | * ================= */ 158 | 159 | $(function () { 160 | $('body').on('click.carousel.data-api', '[data-slide]', function ( e ) { 161 | var $this = $(this), href 162 | , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 163 | , options = !$target.data('modal') && $.extend({}, $target.data(), $this.data()) 164 | $target.carousel(options) 165 | e.preventDefault() 166 | }) 167 | }) 168 | 169 | }(window.jQuery); -------------------------------------------------------------------------------- /app/js/binarytoolkit.js: -------------------------------------------------------------------------------- 1 | /* BinaryToolkit written by Rainer Heynke */ 2 | window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; 3 | window.BlobBuilder = window.WebKitBlobBuilder || window.MozBlobBuilder; 4 | window.URL = window.URL || window.webkitURL; 5 | 6 | 7 | function BinaryReader(data) 8 | { 9 | this.data = new Uint8Array(data); 10 | this.pos = 0; 11 | 12 | this.signMasks = [ 0x0, 0x80, 0x8000, 0x800000, 0x80000000 ]; 13 | this.masks = [ 0x0, 0xFF + 1, 0xFFFF + 1, 0xFFFFFF + 1, 0xFFFFFFFF + 1 ]; 14 | 15 | this.gotoString = function gotoString(value) 16 | { 17 | for(var i = this.pos; i < this.data.length; ++i) 18 | { 19 | if (value[0] == String.fromCharCode(this.data[i])) 20 | { 21 | var complete = true; 22 | for (var j = i; j < value.length + i; ++j) 23 | { 24 | if (value[j - i] != String.fromCharCode(this.data[j])) 25 | { 26 | complete = false; 27 | break; 28 | } 29 | } 30 | 31 | if (complete == true) 32 | { 33 | this.pos = i; 34 | break; 35 | } 36 | } 37 | } 38 | } 39 | 40 | this.readUInt8 = function readUInt8(bigEndian) 41 | { 42 | return this.readInteger(1, false, bigEndian); 43 | }; 44 | 45 | this.readInt8 = function readInt8(bigEndian) 46 | { 47 | return this.readInteger(1, true, bigEndian); 48 | }; 49 | 50 | this.readUInt16 = function readUInt16(bigEndian) 51 | { 52 | return this.readInteger(2, false, bigEndian); 53 | }; 54 | 55 | this.readInt16 = function readInt16(bigEndian) 56 | { 57 | return this.readInteger(2, true, bigEndian); 58 | }; 59 | 60 | this.readUInt32 = function readUInt32(bigEndian) 61 | { 62 | return this.readInteger(4, false, bigEndian); 63 | }; 64 | 65 | this.readInt32 = function readInt32(bigEndian) 66 | { 67 | return this.readInteger(4, true, bigEndian); 68 | }; 69 | 70 | this.readString = function readString(size) 71 | { 72 | var r = ""; 73 | var i = 0; 74 | 75 | for(i = 0; i < size; ++i) 76 | { 77 | r += String.fromCharCode(this.data[this.pos++]); 78 | } 79 | return r; 80 | }; 81 | 82 | /* size = size in bytes (e.g. 1 = 8 bits, ...) 83 | * signed = boolean flag to define if the value is signed 84 | * bigEndian = boolean flag to define the decoding in big endian style 85 | */ 86 | this.readInteger = function readInteger(size, signed, bigEndian) 87 | { 88 | if (this.pos + (size - 1) >= this.data.length) throw "Buffer overflow during reading."; 89 | 90 | var i = 0; 91 | var r = 0; 92 | 93 | // read the bytes 94 | for(i = 0; i < size; ++i) 95 | { 96 | if (bigEndian === true) 97 | { 98 | r = this.data[this.pos++] + (r << (i * 8)); 99 | } 100 | else 101 | { 102 | r += (this.data[this.pos++] << (i * 8)); 103 | } 104 | } 105 | 106 | // convert from unsigned to signed 107 | if (signed && r & this.signMasks[size]) 108 | { 109 | r = r - this.masks[size]; 110 | } 111 | 112 | return r; 113 | }; 114 | 115 | this.eof = function eof() 116 | { 117 | return (this.data.length >= this.pos); 118 | }; 119 | } 120 | 121 | function BinaryWriter(estimatedSize) 122 | { 123 | this.estimatedSize = estimatedSize; 124 | this.pos = 0; 125 | this.data = new Uint8Array(estimatedSize); 126 | 127 | this.masks = [ 0x0, 0xFF + 1, 0xFFFF + 1, 0xFFFFFF + 1, 0xFFFFFFFF + 1 ]; 128 | 129 | this.writeUInt8 = function writeUInt8(value, bigEndian) 130 | { 131 | return this.writeInteger(value, 1, bigEndian); 132 | }; 133 | 134 | this.writeInt8 = function writeInt8(value, bigEndian) 135 | { 136 | return this.writeInteger(value, 1, bigEndian); 137 | }; 138 | 139 | this.writeUInt16 = function writeUInt16(value, bigEndian) 140 | { 141 | return this.writeInteger(value, 2, bigEndian); 142 | }; 143 | 144 | this.writeInt16 = function writeInt16(value, bigEndian) 145 | { 146 | return this.writeInteger(value, 2, bigEndian); 147 | }; 148 | 149 | this.writeUInt32 = function writeUInt32(value, bigEndian) 150 | { 151 | return this.writeInteger(value, 4, bigEndian); 152 | }; 153 | 154 | this.writeInt32 = function writeInt32(value, bigEndian) 155 | { 156 | return this.writeInteger(value, 4, bigEndian); 157 | }; 158 | 159 | this.writeString = function writeString(value) 160 | { 161 | var i = 0; 162 | for(i = 0; i < value.length; ++i) 163 | { 164 | this.data[this.pos++] = value.charCodeAt(i); 165 | } 166 | }; 167 | 168 | /* value = the actual value which want to get stored 169 | * size = size in bytes of the value 170 | * bigEndian = flag to store the number in big endian style 171 | */ 172 | this.writeInteger = function writeInteger(value, size, bigEndian) 173 | { 174 | var r = value; 175 | var i = 0; 176 | 177 | // convert to unsigned if value is negative 178 | if (value < 0) 179 | { 180 | r += this.masks[size]; 181 | } 182 | 183 | // write the bytes 184 | for(i = 0; i < size; ++i) 185 | { 186 | if (bigEndian === true) 187 | { 188 | this.data[this.pos++] = (r >> ((size - i - 1) * 8)) & 0xFF; 189 | } 190 | else 191 | { 192 | this.data[this.pos++] = (r >> (i * 8)) & 0xFF; 193 | } 194 | } 195 | }; 196 | } -------------------------------------------------------------------------------- /bootstrap/js/bootstrap-modal.js: -------------------------------------------------------------------------------- 1 | /* ========================================================= 2 | * bootstrap-modal.js v2.0.4 3 | * http://twitter.github.com/bootstrap/javascript.html#modals 4 | * ========================================================= 5 | * Copyright 2012 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================= */ 19 | 20 | 21 | !function ($) { 22 | 23 | "use strict"; // jshint ;_; 24 | 25 | 26 | /* MODAL CLASS DEFINITION 27 | * ====================== */ 28 | 29 | var Modal = function (content, options) { 30 | this.options = options 31 | this.$element = $(content) 32 | .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)) 33 | } 34 | 35 | Modal.prototype = { 36 | 37 | constructor: Modal 38 | 39 | , toggle: function () { 40 | return this[!this.isShown ? 'show' : 'hide']() 41 | } 42 | 43 | , show: function () { 44 | var that = this 45 | , e = $.Event('show') 46 | 47 | this.$element.trigger(e) 48 | 49 | if (this.isShown || e.isDefaultPrevented()) return 50 | 51 | $('body').addClass('modal-open') 52 | 53 | this.isShown = true 54 | 55 | escape.call(this) 56 | backdrop.call(this, function () { 57 | var transition = $.support.transition && that.$element.hasClass('fade') 58 | 59 | if (!that.$element.parent().length) { 60 | that.$element.appendTo(document.body) //don't move modals dom position 61 | } 62 | 63 | that.$element 64 | .show() 65 | 66 | if (transition) { 67 | that.$element[0].offsetWidth // force reflow 68 | } 69 | 70 | that.$element.addClass('in') 71 | 72 | transition ? 73 | that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) : 74 | that.$element.trigger('shown') 75 | 76 | }) 77 | } 78 | 79 | , hide: function (e) { 80 | e && e.preventDefault() 81 | 82 | var that = this 83 | 84 | e = $.Event('hide') 85 | 86 | this.$element.trigger(e) 87 | 88 | if (!this.isShown || e.isDefaultPrevented()) return 89 | 90 | this.isShown = false 91 | 92 | $('body').removeClass('modal-open') 93 | 94 | escape.call(this) 95 | 96 | this.$element.removeClass('in') 97 | 98 | $.support.transition && this.$element.hasClass('fade') ? 99 | hideWithTransition.call(this) : 100 | hideModal.call(this) 101 | } 102 | 103 | } 104 | 105 | 106 | /* MODAL PRIVATE METHODS 107 | * ===================== */ 108 | 109 | function hideWithTransition() { 110 | var that = this 111 | , timeout = setTimeout(function () { 112 | that.$element.off($.support.transition.end) 113 | hideModal.call(that) 114 | }, 500) 115 | 116 | this.$element.one($.support.transition.end, function () { 117 | clearTimeout(timeout) 118 | hideModal.call(that) 119 | }) 120 | } 121 | 122 | function hideModal(that) { 123 | this.$element 124 | .hide() 125 | .trigger('hidden') 126 | 127 | backdrop.call(this) 128 | } 129 | 130 | function backdrop(callback) { 131 | var that = this 132 | , animate = this.$element.hasClass('fade') ? 'fade' : '' 133 | 134 | if (this.isShown && this.options.backdrop) { 135 | var doAnimate = $.support.transition && animate 136 | 137 | this.$backdrop = $('