@@ -14,7 +12,7 @@
{{range-slider start=hueRange orientation="vertical" step=beatOptions.hueRange.step range=beatOptions.hueRange.range connect=hueRangeConnect
- on-change="hueRangeChanged" pips=beatOptions.hueRange.pips}}
+ on-change=(action (mut hueRange)) pips=beatOptions.hueRange.pips}}
@@ -24,7 +22,7 @@
{{range-slider start=brightnessRange orientation="vertical" step=beatOptions.brightnessRange.step range=beatOptions.brightnessRange.range
- on-change="brightnessRangeChanged" pips=beatOptions.brightnessRange.pips}}
+ on-change=(action (mut brightnessRange)) pips=beatOptions.brightnessRange.pips}}
@@ -33,8 +31,8 @@
Sensitivity
- {{range-slider start=threshold orientation="vertical" step=beatOptions.threshold.step range=beatOptions.threshold.range on-change="thresholdChanged"
- pips=beatOptions.threshold.pips}}
+ {{range-slider start=threshold orientation="vertical" step=beatOptions.threshold.step range=beatOptions.threshold.range on-change=(action
+ (mut threshold)) pips=beatOptions.threshold.pips}}
diff --git a/chrome/app/styles/app.scss b/chrome/app/styles/app.scss
index 61c4712..8a0b53b 100644
--- a/chrome/app/styles/app.scss
+++ b/chrome/app/styles/app.scss
@@ -21,12 +21,11 @@ body {
body > .ember-view {
display: flex;
- min-height: 100vh;
flex-direction: column;
}
body, button {
- font-family: 'Slabo 27px', serif;
+ font-family: 'Raleway', sans-serif;
}
#huegasm {
diff --git a/chrome/app/styles/bridge-finder.scss b/chrome/app/styles/bridge-finder.scss
index f6ef407..79b355e 100644
--- a/chrome/app/styles/bridge-finder.scss
+++ b/chrome/app/styles/bridge-finder.scss
@@ -31,7 +31,6 @@
}
#bridge-finder {
- min-height: 500px;
.md-bar {
background-color: $secondaryThemeColor !important;
}
diff --git a/chrome/app/styles/hue-controls.scss b/chrome/app/styles/hue-controls.scss
index 90baa9c..8e7e3dd 100644
--- a/chrome/app/styles/hue-controls.scss
+++ b/chrome/app/styles/hue-controls.scss
@@ -1,6 +1,5 @@
#lights-tab {
padding: 0;
- margin-top: 5vh;
.paper-icon {
line-height: 0.8 !important;
}
@@ -19,7 +18,6 @@
#hue-controls {
max-width: 1200px;
- height: 90vh;
md-progress-circular {
position: absolute;
top: 50%;
@@ -35,7 +33,7 @@
}
#navigation {
- padding: 15px 0 4vh;
+ padding: 10px 0 2vh;
text-align: center;
margin: auto;
position: relative;
@@ -44,13 +42,13 @@
text-align: right;
position: absolute;
top: -10px;
- right: 10px;
+ right: -10px;
transform: scale(1.1);
}
}
.navigation-item {
- font-size: 18px;
+ font-size: 20px;
padding: 0 10px 0 10px;
&.active {
font-weight: bold;
diff --git a/chrome/app/styles/light-group.scss b/chrome/app/styles/light-group.scss
index c8e56f8..af8d3e2 100644
--- a/chrome/app/styles/light-group.scss
+++ b/chrome/app/styles/light-group.scss
@@ -58,7 +58,7 @@
.light-text {
width: 60px;
word-wrap: break-word;
- padding: 0 10px;
+ padding: 0 7px;
}
.light-text-content {
diff --git a/chrome/app/styles/music-tab.scss b/chrome/app/styles/music-tab.scss
index 14a1202..e7af8fd 100644
--- a/chrome/app/styles/music-tab.scss
+++ b/chrome/app/styles/music-tab.scss
@@ -8,87 +8,6 @@
margin-bottom: 20px;
}
-#slide-toggle {
- font-size: 22px;
- color: $playerDefaultIconColor;
- background: #730B07;
- div .paper-icon {
- color: inherit !important;
- font-size: 24px;
- font-weight: bold;
- }
-}
-
-#slide-toggle:hover {
- color: lighten($playerDefaultIconColor, 30%) !important;
-}
-
-
-#player-area {
- height: $playerHeight;
- background-color: black;
- display: inline-block;
- padding: 0;
- cursor: pointer;
-}
-
-#playlist {
- height: $playerHeight;
- background-color: #1E1E1E;
- padding: 0 5px 0 5px;
-}
-
-#player-area * .noUi-origin {
- background-color: $blackish;
- border-radius: 5px;
-}
-
-#player-area * .noUi-base {
- background-color: $blackish;
- border-radius: 5px;
-}
-
-#volume-bar {
- width: 5em;
- height: 0.5em;
- display: inline-block;
-}
-
-#player-area * .noUi-handle::after,
-#player-area * .noUi-handle::before {
- content: none;
-}
-
-#seek-slider {
- margin-bottom: 15px;
- transition-duration: 0.2s;
- height: 8px;
- .noUi-handle {
- opacity: 1 !important;
- }
-}
-
-#seek-slider:hover {
- height: 8px;
-}
-
-#seek-slider:hover * .noUi-handle {
- opacity: 1;
-}
-
-#seek-slider * .noUi-handle {
- border: none;
- height: 13px;
- width: 13px;
- border-radius: 50%;
- top: -4px;
- left: -6px;
- opacity: 0;
- transition-duration: 0.1s;
- background-color: $secondaryThemeColor !important;
- box-shadow: none;
-}
-
#beat-area {
position: relative;
padding: 0;
@@ -118,9 +37,10 @@
}
.option-description {
display: inline-flex;
- font-size: 20px;
+ font-size: 18px;
justify-content: center;
flex-direction: column;
+ padding: 10px 0;
}
button {
margin-top: 0;
@@ -155,65 +75,6 @@
}
}
-#add-music-choices {
- min-width: initial;
- right: 0;
- left: initial;
- width: 100px;
- top: 25px;
-}
-
-.add-new-music {
- padding: 0 5px 0 10px;
- font-size: 16px;
- border-radius: 5px;
- background: #f8f8f8;
- border: none;
-}
-
-.add-new-music:hover {
- background: darken(#f8f8f8, 5%);
-}
-
-.sound-cloud-link {
- position: absolute;
- right: 55px;
- bottom: 22px;
-}
-
-
-
-#save-beat-preferences-star {
- position: absolute;
- top: 5px;
- left: 5px;
- z-index: 1000;
- md-icon {
- color: $secondaryThemeColor !important;
- font-size: 25px;
- cursor: default;
- }
-}
-
-.visualizers-menu {
- left: -135px;
-}
-
-.display-icon {
- background: url(images/huegasm.png) center center no-repeat;
- background-size: 80px 80px;
-}
-
-.keyboard-arrow-down {
- font-size: 20px;
-}
-
-.visualizers-menu .paper-icon {
- margin-left: 10px;
- position: relative;
- top: -4px;
-}
-
.close {
font-size: 18px !important;
color: rgb(51, 51, 51);
@@ -224,36 +85,66 @@
}
}
-.ember-notify-default.ember-notify-cn {
- top: 0;
- bottom: initial;
+#fancy-button-wrapper {
+ display: flex;
+ justify-content: center;
}
-#soundcloud-logo {
- display: block;
-}
-
-#soundcloud-logo-small {
- display: none;
-}
-
-#soundcloud-tutorial {
- width: 100%;
-}
-
-@media(max-width:1100px) {
- #soundcloud-logo {
- display: none;
- }
- #soundcloud-logo-small {
+.fancy-button {
+ background-image: -webkit-linear-gradient(top, #f4f1ee, #fff);
+ background-image: linear-gradient(top, #f4f1ee, #fff);
+ border-radius: 50%;
+ box-shadow: 0px 8px 10px 0px rgba(0, 0, 0, .3), inset 0px 4px 1px 1px white, inset 0px -3px 1px 1px rgba(204,198,197,.5);
+ float:left;
+ height: 90px;
+ margin: 0 30px 30px 0;
+ position: relative;
+ width: 90px;
+ -webkit-transition: all .1s linear;
+ transition: all .1s linear;
+ &:after {
+ color:#e9e6e4;
+ content: "";
display: block;
+ font-size: 50px;
+ height: 30px;
+ text-decoration: none;
+ text-shadow: 0px -1px 1px #bdb5b4, 1px 1px 1px white;
+ position: absolute;
+ width: 30px;
+ }
+ &:hover {
+ background-image: -webkit-linear-gradient(top, #fff, #f4f1ee);
+ background-image: linear-gradient(top, #fff, #f4f1ee);
+ color:#0088cc;
+ }
+ &:active {
+ background-image: -webkit-linear-gradient(top, #efedec, #f7f4f4);
+ background-image: linear-gradient(top, #efedec, #f7f4f4);
+ box-shadow: 0 3px 5px 0 rgba(0,0,0,.4), inset 0px -3px 1px 1px rgba(204,198,197,.5);
+ &:after{
+ color:#dbd2d2;
+ text-shadow: 0px -1px 1px #bdb5b4, 0px 1px 1px white;
+ }
+ }
+}
+
+.note {
+ &.active:after {
+ color: $secondaryThemeColor;
+ }
+ &:after{
+ content: "♪";
+ left: 32px;
+ top: 14px;
+ }
+ &:hover:after {
+ color: $secondaryThemeColor;
+ text-shadow: 0px 0px 6px $secondaryThemeColor;
}
}
@media(min-width:767px) and (max-width:1200px) {
- #add-new-music-label {
- display: none;
- }
#play-list-controls .paper-button {
border: 1px solid $whitish;
border-radius: 5px;
@@ -289,10 +180,6 @@
.close {
display: block;
}
- #save-beat-preferences-star {
- right: 5px;
- left: initial;
- }
md-checkbox {
padding-right: 20px !important;
}
diff --git a/chrome/app/styles/paper.scss b/chrome/app/styles/paper.scss
index 901c2b4..8873127 100644
--- a/chrome/app/styles/paper.scss
+++ b/chrome/app/styles/paper.scss
@@ -18,6 +18,7 @@ md-checkbox .md-label {
}
.md-button {
+ font-size: 13px;
flex-direction: unset;
span {
width: 100%;
@@ -62,7 +63,7 @@ md-switch.md-default-theme.md-checked .md-thumb {
}
md-list-item {
- margin-bottom: 2vh;
+ margin-bottom: 1vh;
}
@media(max-width:500px) {
diff --git a/chrome/ember-cli-build.js b/chrome/ember-cli-build.js
index e4b3409..b75f4af 100644
--- a/chrome/ember-cli-build.js
+++ b/chrome/ember-cli-build.js
@@ -14,8 +14,6 @@ module.exports = function (defaults) {
destDir: '/fonts/bootstrap'
});
- app.import('vendor/dancer.js');
-
app.import('bower_components/bootstrap-sass/assets/javascripts/bootstrap/tooltip.js');
app.import('bower_components/velocity/velocity.js');
diff --git a/chrome/public/background.js b/chrome/public/background.js
index 7dfbcb5..2c90e13 100644
--- a/chrome/public/background.js
+++ b/chrome/public/background.js
@@ -1,11 +1,827 @@
-chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
- if (request.action === 'start-listen') {
- chrome.tabCapture.capture({
- audio: true,
- video: false
- }, function (stream) {
- console.log('stream', stream);
- //I can attach all my filter here...
- });
+'use strict';
+
+/*
+ * dancer - v0.4.0 - 2014-02-01
+ * https://github.com/jsantell/dancer.js
+ * Copyright (c) 2014 Jordan Santell
+ * Licensed MIT
+ */
+(function () {
+
+ var Dancer = function () {
+ this.audioAdapter = Dancer._getAdapter(this);
+ this.events = {};
+ this.sections = [];
+ this.bind('update', update);
+ };
+
+ Dancer.version = 'X.X.X';
+ Dancer.adapters = {};
+
+ Dancer.prototype = {
+
+ load: function (source, micBoost, useMic) {
+ // Loading an Audio element
+ if (source instanceof HTMLElement) {
+ this.source = source;
+ // Loading an object with src, [codecs]
+ } else if (source instanceof EventTarget) {
+ this.source = source;
+ } else {
+ this.source = window.Audio ? new Audio() : {};
+ this.source.src = Dancer._makeSupportedPath(source.src, source.codecs);
+ }
+
+ this.useMic = useMic === true;
+ this.boost = micBoost ? micBoost : 1;
+ this.audio = this.audioAdapter.load(this.source, this.useMic, this.boost);
+
+ return this;
+ },
+
+ /* Controls */
+ play: function () {
+ this.audioAdapter.play();
+ return this;
+ },
+
+ pause: function () {
+ this.audioAdapter.pause();
+ return this;
+ },
+
+ setVolume: function (volume) {
+ this.audioAdapter.setVolume(volume);
+ return this;
+ },
+
+ setBoost: function (boost) {
+ this.audioAdapter.setBoost(boost);
+ return this;
+ },
+
+ /* Actions */
+ createKick: function (options) {
+ return new Dancer.Kick(this, options);
+ },
+
+ bind: function (name, callback) {
+ if (!this.events[name]) {
+ this.events[name] = [];
+ }
+ this.events[name].push(callback);
+ return this;
+ },
+
+ unbind: function (name) {
+ if (this.events[name]) {
+ delete this.events[name];
+ }
+ return this;
+ },
+
+ trigger: function (name) {
+ var _this = this;
+ if (this.events[name]) {
+ this.events[name].forEach(function (callback) {
+ callback.call(_this);
+ });
+ }
+ return this;
+ },
+
+
+ /* Getters */
+
+ getVolume: function () {
+ return this.audioAdapter.getVolume();
+ },
+
+ getProgress: function () {
+ return this.audioAdapter.getProgress();
+ },
+
+ getTime: function () {
+ return this.audioAdapter.getTime();
+ },
+
+ // Returns the magnitude of a frequency or average over a range of frequencies
+ getFrequency: function (freq, endFreq) {
+ var sum = 0;
+ if (endFreq !== undefined) {
+ for (var i = freq; i <= endFreq; i++) {
+ sum += this.getSpectrum()[i];
+ }
+ return sum / (endFreq - freq + 1);
+ } else {
+ return this.getSpectrum()[freq];
+ }
+ },
+
+ getWaveform: function () {
+ return this.audioAdapter.getWaveform();
+ },
+
+ getSpectrum: function () {
+ return this.audioAdapter.getSpectrum();
+ },
+
+ isLoaded: function () {
+ return this.audioAdapter.isLoaded;
+ },
+
+ isPlaying: function () {
+ return this.audioAdapter.isPlaying;
+ },
+
+
+ /* Sections */
+
+ after: function (time, callback) {
+ var _this = this;
+ this.sections.push({
+ condition: function () {
+ return _this.getTime() > time;
+ },
+ callback: callback
+ });
+ return this;
+ },
+
+ before: function (time, callback) {
+ var _this = this;
+ this.sections.push({
+ condition: function () {
+ return _this.getTime() < time;
+ },
+ callback: callback
+ });
+ return this;
+ },
+
+ between: function (startTime, endTime, callback) {
+ var _this = this;
+ this.sections.push({
+ condition: function () {
+ return _this.getTime() > startTime && _this.getTime() < endTime;
+ },
+ callback: callback
+ });
+ return this;
+ },
+
+ onceAt: function (time, callback) {
+ var
+ _this = this,
+ thisSection = null;
+ this.sections.push({
+ condition: function () {
+ return _this.getTime() > time && !this.called;
+ },
+ callback: function () {
+ callback.call(this);
+ thisSection.called = true;
+ },
+ called: false
+ });
+ // Baking the section in the closure due to callback's this being the dancer instance
+ thisSection = this.sections[this.sections.length - 1];
+ return this;
+ }
+ };
+
+ function update() {
+ for (var i in this.sections) {
+ if (this.sections[i].condition && this.sections[i].condition())
+ this.sections[i].callback.call(this);
+ }
}
-});
\ No newline at end of file
+
+ window.Dancer = Dancer;
+})();
+
+(function (Dancer) {
+
+ var CODECS = {
+ 'mp3': 'audio/mpeg;',
+ 'ogg': 'audio/ogg; codecs="vorbis"',
+ 'wav': 'audio/wav; codecs="1"',
+ 'aac': 'audio/mp4; codecs="mp4a.40.2"'
+ },
+ audioEl = document.createElement('audio');
+
+ Dancer.options = {};
+
+ Dancer.setOptions = function (o) {
+ for (var option in o) {
+ if (o.hasOwnProperty(option)) {
+ Dancer.options[option] = o[option];
+ }
+ }
+ };
+
+ Dancer.isSupported = function () {
+ if (!window.Float32Array || !window.Uint32Array) {
+ return null;
+ } else if (!isUnsupportedSafari() && (window.AudioContext || window.webkitAudioContext)) {
+ return 'webaudio';
+ } else {
+ return '';
+ }
+ };
+
+ Dancer.canPlay = function (type) {
+ var canPlay = audioEl.canPlayType;
+ return !!(
+ type.toLowerCase() === 'mp3' ||
+ audioEl.canPlayType &&
+ audioEl.canPlayType(CODECS[type.toLowerCase()]).replace(/no/, ''));
+ };
+
+ Dancer.addPlugin = function (name, fn) {
+ if (Dancer.prototype[name] === undefined) {
+ Dancer.prototype[name] = fn;
+ }
+ };
+
+ Dancer._makeSupportedPath = function (source, codecs) {
+ if (!codecs) { return source; }
+
+ for (var i = 0; i < codecs.length; i++) {
+ if (Dancer.canPlay(codecs[i])) {
+ return source + '.' + codecs[i];
+ }
+ }
+ return source;
+ };
+
+ Dancer._getAdapter = function (instance) {
+ switch (Dancer.isSupported()) {
+ case 'webaudio':
+ return new Dancer.adapters.webaudio(instance);
+ default:
+ return null;
+ }
+ };
+
+ Dancer._getMP3SrcFromAudio = function (audioEl) {
+ var sources = audioEl.children;
+ if (audioEl.src) { return audioEl.src; }
+ for (var i = sources.length; i--;) {
+ if ((sources[i].type || '').match(/audio\/mpeg/)) return sources[i].src;
+ }
+ return null;
+ };
+
+ // Browser detection is lame, but Safari 6 has Web Audio API,
+ // but does not support processing audio from a Media Element Source
+ // https://gist.github.com/3265344
+ function isUnsupportedSafari() {
+ var
+ isApple = !!(navigator.vendor || '').match(/Apple/),
+ version = navigator.userAgent.match(/Version\/([^ ]*)/);
+ version = version ? parseFloat(version[1]) : 0;
+ return isApple && version <= 6;
+ }
+
+})(window.Dancer);
+
+(function (undefined) {
+ var Kick = function (dancer, o) {
+ o = o || {};
+ this.dancer = dancer;
+ this.frequency = o.frequency !== undefined ? o.frequency : [0, 5];
+ this.threshold = o.threshold !== undefined ? o.threshold : 0.3;
+ this.decay = o.decay !== undefined ? o.decay : 0.02;
+ this.onKick = o.onKick;
+ this.offKick = o.offKick;
+ this.isOn = false;
+ this.currentThreshold = this.threshold;
+ this.previousMag = 0;
+ this.canUseRatio = true;
+ this.canUseRatioHandle = null;
+
+ var _this = this;
+ this.dancer.bind('update', function () {
+ _this.onUpdate();
+ });
+ };
+
+ Kick.prototype = {
+ on: function () {
+ this.isOn = true;
+ return this;
+ },
+ off: function () {
+ this.isOn = false;
+ return this;
+ },
+
+ set: function (o) {
+ o = o || {};
+ this.frequency = o.frequency !== undefined ? o.frequency : this.frequency;
+ this.threshold = o.threshold !== undefined ? o.threshold : this.threshold;
+ this.decay = o.decay !== undefined ? o.decay : this.decay;
+ this.onKick = o.onKick || this.onKick;
+ this.offKick = o.offKick || this.offKick;
+ },
+
+ onUpdate: function () {
+ if (!this.isOn) { return; }
+
+ var magnitude = this.maxAmplitude(this.frequency);
+
+ if (magnitude >= this.currentThreshold && magnitude >= this.threshold) {
+ this.currentThreshold = magnitude;
+ this.onKick && this.onKick.call(this.dancer, magnitude);
+ this.canUseRatio = false;
+
+ if (this.canUseRatioHandle) {
+ clearTimeout(this.canUseRatioHandle);
+ this.canUseRatioHandle = null;
+ }
+
+ var self = this;
+ this.canUseRatioHandle = setTimeout(function () {
+ self.canUseRatio = true;
+ }, 5000);
+ } else {
+ if (magnitude / this.previousMag > this.threshold * 5 && magnitude > 0.1 && this.canUseRatio) {
+ this.onKick && this.onKick.call(this.dancer, magnitude, magnitude / this.previousMag);
+ } else {
+ this.offKick && this.offKick.call(this.dancer, magnitude);
+ }
+
+ this.currentThreshold -= this.decay;
+ this.previousMag = (magnitude > 0) ? magnitude : 0.0001;
+ }
+ },
+ maxAmplitude: function (frequency) {
+ var max = 0, fft = this.dancer.getSpectrum();
+
+ // Sloppy array check
+ if (!frequency.length) {
+ return frequency < fft.length ?
+ fft[~~frequency] :
+ null;
+ }
+
+ for (var i = frequency[0], l = frequency[1]; i <= l; i++) {
+ if (fft[i] > max) { max = fft[i]; }
+ }
+ return max;
+ }
+ };
+
+ window.Dancer.Kick = Kick;
+})();
+
+(function () {
+ var
+ SAMPLE_SIZE = 2048,
+ SAMPLE_RATE = 44100;
+
+ var adapter = function (dancer) {
+ var context;
+
+ if ('AudioContext' in window) {
+ context = new AudioContext();
+ } else {
+ context = new webkitAudioContext();
+ }
+
+ this.dancer = dancer;
+ this.audio = new Audio();
+ this.context = context;
+ };
+
+ adapter.prototype = {
+
+ load: function (_source, useMic, boost) {
+ var _this = this;
+ this.audio = _source;
+ this.useMic = useMic;
+ this.boost = boost;
+
+ this.isLoaded = false;
+ this.progress = 0;
+
+ if (this.proc) {
+ this.proc.onaudioprocess = null;
+ delete this.proc;
+ }
+
+ this.proc = this.context.createScriptProcessor(SAMPLE_SIZE / 2, 1, 1);
+
+ this.proc.onaudioprocess = function (e) {
+ _this.update.call(_this, e);
+ };
+
+ this.gain = this.context.createGain();
+
+ this.fft = new FFT(SAMPLE_SIZE / 2, SAMPLE_RATE, this.boost);
+ this.signal = new Float32Array(SAMPLE_SIZE / 2);
+
+ if (this.audio.readyState < 3) {
+ this.audio.addEventListener('canplay', function () {
+ connectContext.call(_this);
+ });
+ } else {
+ connectContext.call(_this);
+ }
+
+ this.audio.addEventListener('progress', function (e) {
+ if (e.currentTarget.duration && e.currentTarget.duration !== Infinity) {
+ _this.progress = e.currentTarget.seekable.end(0) / e.currentTarget.duration;
+ }
+ });
+
+ return this.audio;
+ },
+
+ play: function () {
+ this.audio.play();
+ this.isPlaying = true;
+ },
+
+ pause: function () {
+ this.audio.pause();
+ this.isPlaying = false;
+ },
+
+ setVolume: function (volume) {
+ this.gain.gain.value = volume;
+ },
+
+ setBoost: function (boost) {
+ if (this.fft) {
+ this.fft.setBoost(boost);
+ }
+
+ this.boost = boost;
+ },
+
+ getVolume: function () {
+ return this.gain.gain.value;
+ },
+
+ getProgress: function () {
+ return this.progress;
+ },
+
+ getWaveform: function () {
+ return this.signal;
+ },
+
+ getSpectrum: function () {
+ return this.fft.spectrum;
+ },
+
+ getTime: function () {
+ return this.audio.currentTime;
+ },
+
+ update: function (e) {
+ if ((!this.isPlaying || !this.isLoaded) && this.useMic !== true) return;
+
+ var
+ buffers = [],
+ channels = e.inputBuffer.numberOfChannels,
+ resolution = SAMPLE_SIZE / channels,
+ sum = function (prev, curr) {
+ return prev[i] + curr[i];
+ }, i;
+
+ for (i = channels; i--;) {
+ buffers.push(e.inputBuffer.getChannelData(i));
+ }
+
+ for (i = 0; i < resolution; i++) {
+ this.signal[i] = channels > 1 ?
+ buffers.reduce(sum) / channels :
+ buffers[0][i];
+ }
+
+ this.fft.forward(this.signal);
+ this.dancer.trigger('update');
+ }
+ };
+
+ function connectContext() {
+ try {
+ if (this.useMic) {
+ this.source = this.context.createMediaStreamSource(this.audio);
+ } else {
+ this.source = this.context.createMediaElementSource(this.audio);
+ }
+ } catch (err) {
+ console.info('Dancer: ' + err);
+ return;
+ }
+
+ this.source.connect(this.proc);
+ this.source.connect(this.gain);
+ this.gain.connect(this.context.destination);
+ this.proc.connect(this.context.destination);
+
+ this.isLoaded = true;
+ this.progress = 1;
+ this.dancer.trigger('loaded');
+ }
+
+ Dancer.adapters.webaudio = adapter;
+
+})();
+
+
+/*
+ * DSP.js - a comprehensive digital signal processing library for javascript
+ *
+ * Created by Corban Brook on 2010-01-01.
+ * Copyright 2010 Corban Brook. All rights reserved.
+ *
+ */
+
+// Fourier Transform Module used by DFT, FFT, RFFT
+function FourierTransform(bufferSize, sampleRate, boost) {
+ this.bufferSize = bufferSize;
+ this.sampleRate = sampleRate;
+ this.bandwidth = 2 / bufferSize * sampleRate / 2;
+ this.boost = boost ? boost : 1;
+
+ this.spectrum = new Float32Array(bufferSize / 2);
+ this.real = new Float32Array(bufferSize);
+ this.imag = new Float32Array(bufferSize);
+
+ this.peakBand = 0;
+ this.peak = 0;
+
+ /**
+ * Calculates the *middle* frequency of an FFT band.
+ *
+ * @param {Number} index The index of the FFT band.
+ *
+ * @returns The middle frequency in Hz.
+ */
+ this.getBandFrequency = function (index) {
+ return this.bandwidth * index + this.bandwidth / 2;
+ };
+
+ this.setBoost = function (boost) {
+ this.boost = boost;
+ };
+
+ this.calculateSpectrum = function () {
+ var spectrum = this.spectrum,
+ real = this.real,
+ imag = this.imag,
+ boost = this.boost,
+ bSi = 2 / this.bufferSize,
+ sqrt = Math.sqrt,
+ rval,
+ ival,
+ mag;
+
+ for (var i = 0, N = bufferSize / 2; i < N; i++) {
+ rval = real[i];
+ ival = imag[i];
+ mag = bSi * sqrt(rval * rval + ival * ival);
+
+ if (mag > this.peak) {
+ this.peakBand = i;
+ this.peak = mag;
+ }
+
+ spectrum[i] = mag * boost;
+ }
+ };
+}
+
+/**
+ * FFT is a class for calculating the Discrete Fourier Transform of a signal
+ * with the Fast Fourier Transform algorithm.
+ *
+ * @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2
+ * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100)
+ * @param {Number} boost The coefficient
+ *
+ * @constructor
+ */
+function FFT(bufferSize, sampleRate, boost) {
+ FourierTransform.call(this, bufferSize, sampleRate, boost);
+
+ this.reverseTable = new Uint32Array(bufferSize);
+
+ var limit = 1;
+ var bit = bufferSize >> 1;
+
+ var i;
+
+ while (limit < bufferSize) {
+ for (i = 0; i < limit; i++) {
+ this.reverseTable[i + limit] = this.reverseTable[i] + bit;
+ }
+
+ limit = limit << 1;
+ bit = bit >> 1;
+ }
+
+ this.sinTable = new Float32Array(bufferSize);
+ this.cosTable = new Float32Array(bufferSize);
+
+ for (i = 0; i < bufferSize; i++) {
+ this.sinTable[i] = Math.sin(-Math.PI / i);
+ this.cosTable[i] = Math.cos(-Math.PI / i);
+ }
+}
+
+/**
+ * Performs a forward transform on the sample buffer.
+ * Converts a time domain signal to frequency domain spectra.
+ *
+ * @param {Array} buffer The sample buffer. Buffer Length must be power of 2
+ *
+ * @returns The frequency spectrum array
+ */
+FFT.prototype.forward = function (buffer) {
+ // Locally scope variables for speed up
+ var bufferSize = this.bufferSize,
+ cosTable = this.cosTable,
+ sinTable = this.sinTable,
+ reverseTable = this.reverseTable,
+ real = this.real,
+ imag = this.imag,
+ spectrum = this.spectrum;
+
+ var k = Math.floor(Math.log(bufferSize) / Math.LN2);
+
+ if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; }
+ if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; }
+
+ var halfSize = 1,
+ phaseShiftStepReal,
+ phaseShiftStepImag,
+ currentPhaseShiftReal,
+ currentPhaseShiftImag,
+ off,
+ tr,
+ ti,
+ tmpReal,
+ i;
+
+ for (i = 0; i < bufferSize; i++) {
+ real[i] = buffer[reverseTable[i]];
+ imag[i] = 0;
+ }
+
+ while (halfSize < bufferSize) {
+ //phaseShiftStepReal = Math.cos(-Math.PI/halfSize);
+ //phaseShiftStepImag = Math.sin(-Math.PI/halfSize);
+ phaseShiftStepReal = cosTable[halfSize];
+ phaseShiftStepImag = sinTable[halfSize];
+
+ currentPhaseShiftReal = 1;
+ currentPhaseShiftImag = 0;
+
+ for (var fftStep = 0; fftStep < halfSize; fftStep++) {
+ i = fftStep;
+
+ while (i < bufferSize) {
+ off = i + halfSize;
+ tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
+ ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
+
+ real[off] = real[i] - tr;
+ imag[off] = imag[i] - ti;
+ real[i] += tr;
+ imag[i] += ti;
+
+ i += halfSize << 1;
+ }
+
+ tmpReal = currentPhaseShiftReal;
+ currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
+ currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
+ }
+
+ halfSize = halfSize << 1;
+ }
+
+ return this.calculateSpectrum();
+};
+
+
+chrome.storage.local.get('threshold', ({threshold}) => {
+ threshold = threshold || 0.3;
+
+ let dancer = new window.Dancer(),
+ paused = false,
+ simulateKick = (mag, ratioKickMag) => {
+ console.log('mag: ' + mag + ', ratioKickMag: ' + ratioKickMag);
+ },
+ kick = dancer.createKick({
+ threshold,
+ onKick: (mag, ratioKickMag) => {
+ if (paused === false) {
+ simulateKick(mag, ratioKickMag);
+ }
+ }
+ });
+
+ kick.on();
+
+ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
+ if (request.action === 'start-listening') {
+ chrome.tabCapture.capture({
+ audio: true,
+ video: false
+ }, function (stream) {
+ let error = null;
+
+ if (!stream) {
+ error = chrome.runtime.lastError.message;
+ } else {
+ // let audio = new Audio();
+ // audio.src = URL.createObjectURL(stream);
+ // audio.crossOrigin = "anonymous";
+ //dancer.load(audio, 1);
+ }
+
+ sendResponse({ error });
+
+ return true;
+ });
+ }
+
+ return true;
+ });
+});
+
+// simulateKick(/*mag, ratioKickMag*/) {
+// let activeLights = this.get('activeLights'),
+// lightsData = this.get('lightsData'),
+// color = null,
+
+// transitiontime = this.get('flashingTransitions'),
+// stimulateLight = (light, brightness, hue) => {
+// let options = { 'bri': brightness };
+
+// if (transitiontime) {
+// options['transitiontime'] = 0;
+// } else {
+// options['transitiontime'] = 1;
+// }
+
+// if (!isNone(hue)) {
+// options.hue = hue;
+// }
+
+// if (lightsData[light].state.on === false) {
+// options.on = true;
+// }
+
+// $.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
+// data: JSON.stringify(options),
+// contentType: 'application/json',
+// type: 'PUT'
+// });
+// },
+// timeToBriOff = 100;
+
+// if (activeLights.length > 0) {
+// let lastLightBopIndex = this.get('lastLightBopIndex'),
+// lightBopIndex,
+// brightnessRange = this.get('brightnessRange'),
+// light;
+
+// lightBopIndex = Math.floor(Math.random() * activeLights.length);
+
+// // let's try not to select the same light twice in a row
+// if (activeLights.length > 1) {
+// while (lightBopIndex === lastLightBopIndex) {
+// lightBopIndex = Math.floor(Math.random() * activeLights.length);
+// }
+// }
+
+// light = activeLights[lightBopIndex];
+// this.set('lastLightBopIndex', lightBopIndex);
+
+// if (!this.get('colorloopMode')) {
+// let hueRange = this.get('hueRange');
+
+// color = Math.floor(Math.random() * (hueRange[1] - hueRange[0] + 1) + hueRange[0]);
+// }
+
+// if (transitiontime) {
+// timeToBriOff = 80;
+// }
+
+// stimulateLight(light, brightnessRange[1], color);
+// later(this, stimulateLight, light, brightnessRange[0], timeToBriOff);
+// }
+
+// this.set('paused', true);
+// later(this, function () {
+// this.set('paused', false);
+// }, 150);
+// }
\ No newline at end of file
diff --git a/chrome/vendor/dancer.js b/chrome/vendor/dancer.js
deleted file mode 100644
index 72d2894..0000000
--- a/chrome/vendor/dancer.js
+++ /dev/null
@@ -1,709 +0,0 @@
-/*
- * dancer - v0.4.0 - 2014-02-01
- * https://github.com/jsantell/dancer.js
- * Copyright (c) 2014 Jordan Santell
- * Licensed MIT
- */
-(function() {
-
- var Dancer = function () {
- this.audioAdapter = Dancer._getAdapter( this );
- this.events = {};
- this.sections = [];
- this.bind( 'update', update );
- };
-
- Dancer.version = 'X.X.X';
- Dancer.adapters = {};
-
- Dancer.prototype = {
-
- load : function ( source, micBoost, useMic ) {
- // Loading an Audio element
- if ( source instanceof HTMLElement ) {
- this.source = source;
- // Loading an object with src, [codecs]
- } else if(source instanceof EventTarget){
- this.source = source;
- } else {
- this.source = window.Audio ? new Audio() : {};
- this.source.src = Dancer._makeSupportedPath( source.src, source.codecs );
- }
-
- this.useMic = useMic === true;
- this.boost = micBoost ? micBoost : 1;
- this.audio = this.audioAdapter.load(this.source, this.useMic, this.boost);
-
- return this;
- },
-
- /* Controls */
- play : function () {
- this.audioAdapter.play();
- return this;
- },
-
- pause : function () {
- this.audioAdapter.pause();
- return this;
- },
-
- setVolume : function ( volume ) {
- this.audioAdapter.setVolume( volume );
- return this;
- },
-
- setBoost : function ( boost ) {
- this.audioAdapter.setBoost( boost );
- return this;
- },
-
- /* Actions */
- createKick : function ( options ) {
- return new Dancer.Kick( this, options );
- },
-
- bind : function ( name, callback ) {
- if ( !this.events[ name ] ) {
- this.events[ name ] = [];
- }
- this.events[ name ].push( callback );
- return this;
- },
-
- unbind : function ( name ) {
- if ( this.events[ name ] ) {
- delete this.events[ name ];
- }
- return this;
- },
-
- trigger : function ( name ) {
- var _this = this;
- if ( this.events[ name ] ) {
- this.events[ name ].forEach(function( callback ) {
- callback.call( _this );
- });
- }
- return this;
- },
-
-
- /* Getters */
-
- getVolume : function () {
- return this.audioAdapter.getVolume();
- },
-
- getProgress : function () {
- return this.audioAdapter.getProgress();
- },
-
- getTime : function () {
- return this.audioAdapter.getTime();
- },
-
- // Returns the magnitude of a frequency or average over a range of frequencies
- getFrequency : function ( freq, endFreq ) {
- var sum = 0;
- if ( endFreq !== undefined ) {
- for ( var i = freq; i <= endFreq; i++ ) {
- sum += this.getSpectrum()[ i ];
- }
- return sum / ( endFreq - freq + 1 );
- } else {
- return this.getSpectrum()[ freq ];
- }
- },
-
- getWaveform : function () {
- return this.audioAdapter.getWaveform();
- },
-
- getSpectrum : function () {
- return this.audioAdapter.getSpectrum();
- },
-
- isLoaded : function () {
- return this.audioAdapter.isLoaded;
- },
-
- isPlaying : function () {
- return this.audioAdapter.isPlaying;
- },
-
-
- /* Sections */
-
- after : function ( time, callback ) {
- var _this = this;
- this.sections.push({
- condition : function () {
- return _this.getTime() > time;
- },
- callback : callback
- });
- return this;
- },
-
- before : function ( time, callback ) {
- var _this = this;
- this.sections.push({
- condition : function () {
- return _this.getTime() < time;
- },
- callback : callback
- });
- return this;
- },
-
- between : function ( startTime, endTime, callback ) {
- var _this = this;
- this.sections.push({
- condition : function () {
- return _this.getTime() > startTime && _this.getTime() < endTime;
- },
- callback : callback
- });
- return this;
- },
-
- onceAt : function ( time, callback ) {
- var
- _this = this,
- thisSection = null;
- this.sections.push({
- condition : function () {
- return _this.getTime() > time && !this.called;
- },
- callback : function () {
- callback.call( this );
- thisSection.called = true;
- },
- called : false
- });
- // Baking the section in the closure due to callback's this being the dancer instance
- thisSection = this.sections[ this.sections.length - 1 ];
- return this;
- }
- };
-
- function update () {
- for (var i in this.sections) {
- if (this.sections[i].condition && this.sections[i].condition() )
- this.sections[i].callback.call(this);
- }
- }
-
- window.Dancer = Dancer;
-})();
-
-(function ( Dancer ) {
-
- var CODECS = {
- 'mp3' : 'audio/mpeg;',
- 'ogg' : 'audio/ogg; codecs="vorbis"',
- 'wav' : 'audio/wav; codecs="1"',
- 'aac' : 'audio/mp4; codecs="mp4a.40.2"'
- },
- audioEl = document.createElement( 'audio' );
-
- Dancer.options = {};
-
- Dancer.setOptions = function ( o ) {
- for ( var option in o ) {
- if ( o.hasOwnProperty( option ) ) {
- Dancer.options[ option ] = o[ option ];
- }
- }
- };
-
- Dancer.isSupported = function () {
- if ( !window.Float32Array || !window.Uint32Array ) {
- return null;
- } else if ( !isUnsupportedSafari() && ( window.AudioContext || window.webkitAudioContext )) {
- return 'webaudio';
- } else {
- return '';
- }
- };
-
- Dancer.canPlay = function ( type ) {
- var canPlay = audioEl.canPlayType;
- return !!(
- type.toLowerCase() === 'mp3' ||
- audioEl.canPlayType &&
- audioEl.canPlayType( CODECS[ type.toLowerCase() ] ).replace( /no/, ''));
- };
-
- Dancer.addPlugin = function ( name, fn ) {
- if ( Dancer.prototype[ name ] === undefined ) {
- Dancer.prototype[ name ] = fn;
- }
- };
-
- Dancer._makeSupportedPath = function ( source, codecs ) {
- if ( !codecs ) { return source; }
-
- for ( var i = 0; i < codecs.length; i++ ) {
- if ( Dancer.canPlay( codecs[ i ] ) ) {
- return source + '.' + codecs[ i ];
- }
- }
- return source;
- };
-
- Dancer._getAdapter = function ( instance ) {
- switch ( Dancer.isSupported() ) {
- case 'webaudio':
- return new Dancer.adapters.webaudio( instance );
- default:
- return null;
- }
- };
-
- Dancer._getMP3SrcFromAudio = function ( audioEl ) {
- var sources = audioEl.children;
- if ( audioEl.src ) { return audioEl.src; }
- for ( var i = sources.length; i--; ) {
- if (( sources[ i ].type || '' ).match( /audio\/mpeg/ )) return sources[ i ].src;
- }
- return null;
- };
-
- // Browser detection is lame, but Safari 6 has Web Audio API,
- // but does not support processing audio from a Media Element Source
- // https://gist.github.com/3265344
- function isUnsupportedSafari () {
- var
- isApple = !!( navigator.vendor || '' ).match( /Apple/ ),
- version = navigator.userAgent.match( /Version\/([^ ]*)/ );
- version = version ? parseFloat( version[ 1 ] ) : 0;
- return isApple && version <= 6;
- }
-
-})( window.Dancer );
-
-(function ( undefined ) {
- var Kick = function ( dancer, o ) {
- o = o || {};
- this.dancer = dancer;
- this.frequency = o.frequency !== undefined ? o.frequency : [ 0, 5 ];
- this.threshold = o.threshold !== undefined ? o.threshold : 0.3;
- this.decay = o.decay !== undefined ? o.decay : 0.02;
- this.onKick = o.onKick;
- this.offKick = o.offKick;
- this.isOn = false;
- this.currentThreshold = this.threshold;
- this.previousMag = 0;
- this.canUseRatio = true;
- this.canUseRatioHandle = null;
-
- var _this = this;
- this.dancer.bind( 'update', function () {
- _this.onUpdate();
- });
- };
-
- Kick.prototype = {
- on : function () {
- this.isOn = true;
- return this;
- },
- off : function () {
- this.isOn = false;
- return this;
- },
-
- set : function ( o ) {
- o = o || {};
- this.frequency = o.frequency !== undefined ? o.frequency : this.frequency;
- this.threshold = o.threshold !== undefined ? o.threshold : this.threshold;
- this.decay = o.decay !== undefined ? o.decay : this.decay;
- this.onKick = o.onKick || this.onKick;
- this.offKick = o.offKick || this.offKick;
- },
-
- onUpdate : function () {
- if ( !this.isOn ) { return; }
-
- var magnitude = this.maxAmplitude(this.frequency);
-
- if (magnitude >= this.currentThreshold && magnitude >= this.threshold) {
- this.currentThreshold = magnitude;
- this.onKick && this.onKick.call(this.dancer, magnitude);
- this.canUseRatio = false;
-
- if(this.canUseRatioHandle) {
- clearTimeout(this.canUseRatioHandle);
- this.canUseRatioHandle = null;
- }
-
- var self = this;
- this.canUseRatioHandle = setTimeout(function(){
- self.canUseRatio = true;
- }, 5000);
- } else {
- if(magnitude/this.previousMag > this.threshold*5 && magnitude>0.1 && this.canUseRatio) {
- this.onKick && this.onKick.call(this.dancer, magnitude, magnitude/this.previousMag);
- } else {
- this.offKick && this.offKick.call(this.dancer, magnitude);
- }
-
- this.currentThreshold -= this.decay;
- this.previousMag = (magnitude > 0) ? magnitude : 0.0001;
- }
- },
- maxAmplitude : function ( frequency ) {
- var max = 0, fft = this.dancer.getSpectrum();
-
- // Sloppy array check
- if ( !frequency.length ) {
- return frequency < fft.length ?
- fft[ ~~frequency ] :
- null;
- }
-
- for ( var i = frequency[ 0 ], l = frequency[ 1 ]; i <= l; i++ ) {
- if ( fft[ i ] > max ) { max = fft[ i ]; }
- }
- return max;
- }
- };
-
- window.Dancer.Kick = Kick;
-})();
-
-(function() {
- var
- SAMPLE_SIZE = 2048,
- SAMPLE_RATE = 44100;
-
- var adapter = function ( dancer ) {
- var context;
-
- if('AudioContext' in window) {
- context = new AudioContext();
- } else {
- context = new webkitAudioContext();
- }
-
- this.dancer = dancer;
- this.audio = new Audio();
- this.context = context;
- };
-
- adapter.prototype = {
-
- load : function (_source, useMic, boost) {
- var _this = this;
- this.audio = _source;
- this.useMic = useMic;
- this.boost = boost;
-
- this.isLoaded = false;
- this.progress = 0;
-
- if(this.proc){
- this.proc.onaudioprocess = null;
- delete this.proc;
- }
-
- this.proc = this.context.createScriptProcessor( SAMPLE_SIZE / 2, 1, 1 );
-
- this.proc.onaudioprocess = function ( e ) {
- _this.update.call( _this, e );
- };
-
- this.gain = this.context.createGain();
-
- this.fft = new FFT( SAMPLE_SIZE / 2, SAMPLE_RATE, this.boost );
- this.signal = new Float32Array( SAMPLE_SIZE / 2 );
-
- if ( this.audio.readyState < 3 ) {
- this.audio.addEventListener( 'canplay', function () {
- connectContext.call( _this );
- });
- } else {
- connectContext.call( _this );
- }
-
- this.audio.addEventListener( 'progress', function ( e ) {
- if ( e.currentTarget.duration && e.currentTarget.duration !== Infinity ) {
- _this.progress = e.currentTarget.seekable.end( 0 ) / e.currentTarget.duration;
- }
- });
-
- return this.audio;
- },
-
- play : function () {
- this.audio.play();
- this.isPlaying = true;
- },
-
- pause : function () {
- this.audio.pause();
- this.isPlaying = false;
- },
-
- setVolume : function ( volume ) {
- this.gain.gain.value = volume;
- },
-
- setBoost : function( boost ){
- if(this.fft){
- this.fft.setBoost(boost);
- }
-
- this.boost = boost;
- },
-
- getVolume : function () {
- return this.gain.gain.value;
- },
-
- getProgress : function() {
- return this.progress;
- },
-
- getWaveform : function () {
- return this.signal;
- },
-
- getSpectrum : function () {
- return this.fft.spectrum;
- },
-
- getTime : function () {
- return this.audio.currentTime;
- },
-
- update : function ( e ) {
- if ((!this.isPlaying || !this.isLoaded) && this.useMic !== true ) return;
-
- var
- buffers = [],
- channels = e.inputBuffer.numberOfChannels,
- resolution = SAMPLE_SIZE / channels,
- sum = function ( prev, curr ) {
- return prev[ i ] + curr[ i ];
- }, i;
-
- for ( i = channels; i--; ) {
- buffers.push( e.inputBuffer.getChannelData( i ) );
- }
-
- for ( i = 0; i < resolution; i++ ) {
- this.signal[ i ] = channels > 1 ?
- buffers.reduce( sum ) / channels :
- buffers[ 0 ][ i ];
- }
-
- this.fft.forward( this.signal );
- this.dancer.trigger( 'update' );
- }
- };
-
- function connectContext () {
- try {
- if(this.useMic){
- this.source = this.context.createMediaStreamSource(this.audio);
- } else {
- this.source = this.context.createMediaElementSource(this.audio);
- }
- } catch (err) {
- console.info('Dancer: '+ err);
- return;
- }
-
- this.source.connect(this.proc);
- this.source.connect(this.gain);
- this.gain.connect(this.context.destination);
- this.proc.connect(this.context.destination);
-
- this.isLoaded = true;
- this.progress = 1;
- this.dancer.trigger( 'loaded' );
- }
-
- Dancer.adapters.webaudio = adapter;
-
-})();
-
-
-/*
- * DSP.js - a comprehensive digital signal processing library for javascript
- *
- * Created by Corban Brook on 2010-01-01.
- * Copyright 2010 Corban Brook. All rights reserved.
- *
- */
-
-// Fourier Transform Module used by DFT, FFT, RFFT
-function FourierTransform(bufferSize, sampleRate, boost) {
- this.bufferSize = bufferSize;
- this.sampleRate = sampleRate;
- this.bandwidth = 2 / bufferSize * sampleRate / 2;
- this.boost = boost ? boost : 1;
-
- this.spectrum = new Float32Array(bufferSize/2);
- this.real = new Float32Array(bufferSize);
- this.imag = new Float32Array(bufferSize);
-
- this.peakBand = 0;
- this.peak = 0;
-
- /**
- * Calculates the *middle* frequency of an FFT band.
- *
- * @param {Number} index The index of the FFT band.
- *
- * @returns The middle frequency in Hz.
- */
- this.getBandFrequency = function(index) {
- return this.bandwidth * index + this.bandwidth / 2;
- };
-
- this.setBoost = function(boost){
- this.boost = boost;
- };
-
- this.calculateSpectrum = function() {
- var spectrum = this.spectrum,
- real = this.real,
- imag = this.imag,
- boost = this.boost,
- bSi = 2 / this.bufferSize,
- sqrt = Math.sqrt,
- rval,
- ival,
- mag;
-
- for (var i = 0, N = bufferSize/2; i < N; i++) {
- rval = real[i];
- ival = imag[i];
- mag = bSi * sqrt(rval * rval + ival * ival);
-
- if (mag > this.peak) {
- this.peakBand = i;
- this.peak = mag;
- }
-
- spectrum[i] = mag * boost;
- }
- };
-}
-
-/**
- * FFT is a class for calculating the Discrete Fourier Transform of a signal
- * with the Fast Fourier Transform algorithm.
- *
- * @param {Number} bufferSize The size of the sample buffer to be computed. Must be power of 2
- * @param {Number} sampleRate The sampleRate of the buffer (eg. 44100)
- * @param {Number} boost The coefficient
- *
- * @constructor
- */
-function FFT(bufferSize, sampleRate, boost) {
- FourierTransform.call(this, bufferSize, sampleRate, boost);
-
- this.reverseTable = new Uint32Array(bufferSize);
-
- var limit = 1;
- var bit = bufferSize >> 1;
-
- var i;
-
- while (limit < bufferSize) {
- for (i = 0; i < limit; i++) {
- this.reverseTable[i + limit] = this.reverseTable[i] + bit;
- }
-
- limit = limit << 1;
- bit = bit >> 1;
- }
-
- this.sinTable = new Float32Array(bufferSize);
- this.cosTable = new Float32Array(bufferSize);
-
- for (i = 0; i < bufferSize; i++) {
- this.sinTable[i] = Math.sin(-Math.PI/i);
- this.cosTable[i] = Math.cos(-Math.PI/i);
- }
-}
-
-/**
- * Performs a forward transform on the sample buffer.
- * Converts a time domain signal to frequency domain spectra.
- *
- * @param {Array} buffer The sample buffer. Buffer Length must be power of 2
- *
- * @returns The frequency spectrum array
- */
-FFT.prototype.forward = function(buffer) {
- // Locally scope variables for speed up
- var bufferSize = this.bufferSize,
- cosTable = this.cosTable,
- sinTable = this.sinTable,
- reverseTable = this.reverseTable,
- real = this.real,
- imag = this.imag,
- spectrum = this.spectrum;
-
- var k = Math.floor(Math.log(bufferSize) / Math.LN2);
-
- if (Math.pow(2, k) !== bufferSize) { throw "Invalid buffer size, must be a power of 2."; }
- if (bufferSize !== buffer.length) { throw "Supplied buffer is not the same size as defined FFT. FFT Size: " + bufferSize + " Buffer Size: " + buffer.length; }
-
- var halfSize = 1,
- phaseShiftStepReal,
- phaseShiftStepImag,
- currentPhaseShiftReal,
- currentPhaseShiftImag,
- off,
- tr,
- ti,
- tmpReal,
- i;
-
- for (i = 0; i < bufferSize; i++) {
- real[i] = buffer[reverseTable[i]];
- imag[i] = 0;
- }
-
- while (halfSize < bufferSize) {
- //phaseShiftStepReal = Math.cos(-Math.PI/halfSize);
- //phaseShiftStepImag = Math.sin(-Math.PI/halfSize);
- phaseShiftStepReal = cosTable[halfSize];
- phaseShiftStepImag = sinTable[halfSize];
-
- currentPhaseShiftReal = 1;
- currentPhaseShiftImag = 0;
-
- for (var fftStep = 0; fftStep < halfSize; fftStep++) {
- i = fftStep;
-
- while (i < bufferSize) {
- off = i + halfSize;
- tr = (currentPhaseShiftReal * real[off]) - (currentPhaseShiftImag * imag[off]);
- ti = (currentPhaseShiftReal * imag[off]) + (currentPhaseShiftImag * real[off]);
-
- real[off] = real[i] - tr;
- imag[off] = imag[i] - ti;
- real[i] += tr;
- imag[i] += ti;
-
- i += halfSize << 1;
- }
-
- tmpReal = currentPhaseShiftReal;
- currentPhaseShiftReal = (tmpReal * phaseShiftStepReal) - (currentPhaseShiftImag * phaseShiftStepImag);
- currentPhaseShiftImag = (tmpReal * phaseShiftStepImag) + (currentPhaseShiftImag * phaseShiftStepReal);
- }
-
- halfSize = halfSize << 1;
- }
-
- return this.calculateSpectrum();
-};
diff --git a/mobile/app/index.html b/mobile/app/index.html
index dbe0ee4..9e8be9c 100644
--- a/mobile/app/index.html
+++ b/mobile/app/index.html
@@ -1,41 +1,42 @@
-
-
-
- Huegasm
-
-
-
-
- {{content-for 'head'}}
+
+
+
+ Huegasm
+
+
+
+ {{content-for 'head'}}
-
+
-
-
+
+ {{content-for 'head-footer'}}
- {{content-for 'head-footer'}}
+
-
+
+
- ga('create', 'UA-69470561-1', 'auto');
- ga('send', 'pageview');
-
-
-
- {{content-for 'body'}}
+
+ {{content-for 'body'}}
-
-
+
+
- {{content-for 'body-footer'}}
-
-
+ {{content-for 'body-footer'}}
+
+
+