simplifying controls
This commit is contained in:
parent
2c866db997
commit
272701813f
6 changed files with 107 additions and 633 deletions
|
|
@ -66,15 +66,6 @@ export default Em.Component.extend({
|
|||
'<i><b>TIP</b>: Beat settings are saved per song as indicated by the red star icon in the top left corner. These settings they will be restored if you ever listen to the same song again.</i>',
|
||||
position: 'top'
|
||||
},
|
||||
{
|
||||
element: '#beatOptionButtonGroup',
|
||||
intro: 'Some additional settings:<br>' +
|
||||
'<b>Default</b> - Revert to the default beat detection settings<br>' +
|
||||
'<b>Random/Sequential</b> - The transition order of lights on beat<br>' +
|
||||
'<b>Brightness/Brightness & Color</b> - The properties of the lights to change on beat<br><br>' +
|
||||
'<i><b>TIP</b>: Turn the colorloop \'on\' in the <b>Lights</b> tab and set only the brightness to change on beat for a cool visual effect.</i>',
|
||||
position: 'top'
|
||||
},
|
||||
{
|
||||
element: '#beatContainer',
|
||||
intro: 'An interactive speaker that will bump when a beat is registered. Switch over to the <b>Debug View</b> to see the intesity of all the registered and unregistered beats.<br><br>' +
|
||||
|
|
|
|||
|
|
@ -198,13 +198,6 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
|
|||
this.send('goToSong', index, true, true);
|
||||
}
|
||||
},
|
||||
defaultControls(){
|
||||
var beatOptions = this.get('beatOptions');
|
||||
|
||||
this.changePlayerControl('threshold', beatOptions.threshold.defaultValue);
|
||||
this.changePlayerControl('interval', beatOptions.interval.defaultValue);
|
||||
this.changePlayerControl('transitionTime', beatOptions.transitionTime.defaultValue);
|
||||
},
|
||||
playerAreaPlay(){
|
||||
if(Em.isEmpty(Em.$('#playerControls:hover')) && this.get('playQueuePointer') !== -1 ){
|
||||
this.send('play');
|
||||
|
|
@ -260,8 +253,6 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
|
|||
repeat = this.get('repeat'),
|
||||
shuffle = this.get('shuffle');
|
||||
|
||||
this.get('beatHistory').clear();
|
||||
|
||||
if(repeat === 2){ // repeating one song takes precedence over shuffling
|
||||
if(playQueuePointer === -1 && playQueue.length > 0) {
|
||||
nextSong = 0;
|
||||
|
|
@ -380,9 +371,6 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
|
|||
this.get('storage').set('huegasm.micBoost', value);
|
||||
this.get('dancer').setBoost(value);
|
||||
},
|
||||
intervalChanged(value){
|
||||
this.changePlayerControl('interval', value, true);
|
||||
},
|
||||
audioModeChanged(value){
|
||||
if(value === 1) {
|
||||
this.startUsingMic();
|
||||
|
|
@ -454,6 +442,11 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
|
|||
changePlayerControl(name, value, saveBeatPrefs){
|
||||
this.set(name, value);
|
||||
|
||||
|
||||
if(name === 'threshold'){
|
||||
this.get('kick').set({threshold: value});
|
||||
}
|
||||
|
||||
if(saveBeatPrefs && this.get('usingLocalAudio') && this.get('playQueuePointer') !== -1){
|
||||
this.saveSongBeatPreferences();
|
||||
}
|
||||
|
|
@ -466,7 +459,7 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
|
|||
title = Em.isEmpty(song.artist) ? song.fileName : song.artist + '-' + song.title,
|
||||
songBeatPreferences = this.get('songBeatPreferences');
|
||||
|
||||
songBeatPreferences[title] = {threshold: this.get('threshold'), interval: this.get('interval')};
|
||||
songBeatPreferences[title] = {threshold: this.get('threshold')};
|
||||
|
||||
this.set('usingBeatPreferences', true);
|
||||
this.get('storage').set('huegasm.songBeatPreferences', songBeatPreferences);
|
||||
|
|
@ -481,14 +474,12 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
|
|||
newOldBeatPrefCache = null;
|
||||
|
||||
if(!Em.isNone(preference)) { // load existing beat prefs
|
||||
newOldBeatPrefCache = {threshold: this.get('threshold'), interval: this.get('interval')};
|
||||
newOldBeatPrefCache = {threshold: this.get('threshold')};
|
||||
|
||||
this.changePlayerControl('threshold', preference.threshold);
|
||||
this.changePlayerControl('interval', preference.interval);
|
||||
this.set('usingBeatPreferences', true);
|
||||
} else if(!Em.isNone(oldBeatPrefCache)) { // revert to using beat prefs before the remembered song
|
||||
this.changePlayerControl('threshold', oldBeatPrefCache.threshold);
|
||||
this.changePlayerControl('interval', oldBeatPrefCache.interval);
|
||||
this.set('usingBeatPreferences', false);
|
||||
}
|
||||
|
||||
|
|
@ -517,7 +508,7 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
|
|||
dancer.load(stream, this.get('micBoost'), true);
|
||||
this.set('usingBeatPreferences', false);
|
||||
|
||||
// much more sensitive beath preference settings are needed for mic mode
|
||||
// much more sensitive beat preference settings are needed for mic mode
|
||||
this.setProperties({
|
||||
oldThreshold: this.get('threshold'),
|
||||
threshold: 0.1
|
||||
|
|
@ -589,97 +580,65 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
|
|||
this.set('dragLeaveTimeoutHandle', setTimeout(function(){ self.set('dragging', false); }, 500));
|
||||
},
|
||||
|
||||
simulateKick(mag) {
|
||||
var validBeat = (this.get('threshold') < mag),
|
||||
beatInterval = this.get('interval');
|
||||
simulateKick() {
|
||||
var activeLights = this.get('activeLights'),
|
||||
transitionTime = this.get('transitionTime') * 10,
|
||||
onBeatBriAndColor = this.get('onBeatBriAndColor'),
|
||||
lightsData = this.get('lightsData'),
|
||||
color = null,
|
||||
beatInterval = 1,
|
||||
stimulateLight = (light, brightness, hue) => {
|
||||
var options = {'bri': brightness, 'transitiontime': transitionTime};
|
||||
|
||||
if(validBeat){
|
||||
var activeLights = this.get('activeLights'),
|
||||
transitionTime = this.get('transitionTime') * 10,
|
||||
onBeatBriAndColor = this.get('onBeatBriAndColor'),
|
||||
lightsData = this.get('lightsData'),
|
||||
color = null,
|
||||
stimulateLight = (light, brightness, hue) => {
|
||||
var options = {'bri': brightness, 'transitiontime': transitionTime};
|
||||
if(!Em.isNone(hue)) {
|
||||
options.hue = hue;
|
||||
}
|
||||
|
||||
if(!Em.isNone(hue)) {
|
||||
options.hue = hue;
|
||||
}
|
||||
if(lightsData[light].state.on === false){
|
||||
options.on = true;
|
||||
}
|
||||
|
||||
if(lightsData[light].state.on === false){
|
||||
options.on = true;
|
||||
}
|
||||
Em.$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||
data: JSON.stringify(options),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
};
|
||||
|
||||
Em.$.ajax(this.get('apiURL') + '/lights/' + light + '/state', {
|
||||
data: JSON.stringify(options),
|
||||
contentType: 'application/json',
|
||||
type: 'PUT'
|
||||
});
|
||||
};
|
||||
if(activeLights.length > 0){
|
||||
var lastLightBopIndex = this.get('lastLightBopIndex'),
|
||||
lightBopIndex,
|
||||
light;
|
||||
|
||||
if(activeLights.length > 0){
|
||||
var lastLightBopIndex = this.get('lastLightBopIndex'),
|
||||
randomTransition = this.get('randomTransition'),
|
||||
lightBopIndex,
|
||||
light;
|
||||
lightBopIndex = Math.floor(Math.random() * activeLights.length);
|
||||
|
||||
if(randomTransition) {
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lightBopIndex = (lastLightBopIndex + 1) % activeLights.length;
|
||||
}
|
||||
|
||||
light = activeLights[lightBopIndex];
|
||||
this.set('lastLightBopIndex', lightBopIndex);
|
||||
|
||||
if(onBeatBriAndColor) {
|
||||
color = Math.floor(Math.random() * 65535);
|
||||
}
|
||||
|
||||
stimulateLight(light, 254, color);
|
||||
setTimeout(stimulateLight, transitionTime + 50, light, 1);
|
||||
}
|
||||
|
||||
light = activeLights[lightBopIndex];
|
||||
this.set('lastLightBopIndex', lightBopIndex);
|
||||
|
||||
if(onBeatBriAndColor) {
|
||||
color = Math.floor(Math.random() * 65535);
|
||||
}
|
||||
|
||||
stimulateLight(light, 254, color);
|
||||
setTimeout(stimulateLight, transitionTime + 50, light, 1);
|
||||
}
|
||||
|
||||
if(beatInterval > 0 && validBeat){
|
||||
this.set('paused', true);
|
||||
setTimeout(() => {
|
||||
this.set('paused', false);
|
||||
}, beatInterval * 1000);
|
||||
}
|
||||
this.set('paused', true);
|
||||
setTimeout(() => {
|
||||
this.set('paused', false);
|
||||
}, beatInterval * 100);
|
||||
|
||||
//work the music beat area
|
||||
if(this.get('speakerViewed')){
|
||||
if(validBeat){
|
||||
// simulate the speaker vibration by running a CSS animation on it
|
||||
Em.$('#beatSpeakerCenterOuter').removeClass('vibrateOuter').prop('offsetWidth', Em.$('#beatSpeakerCenterOuter').prop('offsetWidth')).addClass('vibrateOuter');
|
||||
Em.$('#beatSpeakerCenterInner').removeClass('vibrateInner').prop('offsetWidth', Em.$('#beatSpeakerCenterInner').prop('offsetWidth')).addClass('vibrateInner');
|
||||
}
|
||||
} else {
|
||||
var beatHistory = this.get('beatHistory'),
|
||||
debugFiltered = this.get('debugFiltered'),
|
||||
maxSize = this.get('maxBeatHistorySize'),
|
||||
html = 'Beat intesity of <b>' + mag.toFixed(3) + '</b> at <b>' + this.get('timeElapsedTxt') + '</b>';
|
||||
|
||||
if(!validBeat){
|
||||
if(!debugFiltered){
|
||||
return;
|
||||
}
|
||||
html = '<span class="filterBeat">' + html + ' ( filtered ) </span>';
|
||||
}
|
||||
beatHistory.unshiftObjects(html);
|
||||
|
||||
if(beatHistory.length > maxSize){
|
||||
beatHistory.popObject();
|
||||
}
|
||||
}
|
||||
// simulate the speaker vibration by running a CSS animation on it
|
||||
Em.$('#beatSpeakerCenterOuter').removeClass('vibrateOuter').prop('offsetWidth', Em.$('#beatSpeakerCenterOuter').prop('offsetWidth')).addClass('vibrateOuter');
|
||||
Em.$('#beatSpeakerCenterInner').removeClass('vibrateInner').prop('offsetWidth', Em.$('#beatSpeakerCenterInner').prop('offsetWidth')).addClass('vibrateInner');
|
||||
},
|
||||
|
||||
init() {
|
||||
|
|
@ -690,13 +649,13 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
|
|||
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
|
||||
|
||||
var dancer = new Dancer(),
|
||||
self = this,
|
||||
storage = this.get('storage'),
|
||||
kick = dancer.createKick({
|
||||
threshold: this.beatOptions.threshold.range.min,
|
||||
onKick: function (mag) {
|
||||
if (self.get('paused') === false) {
|
||||
self.simulateKick(mag);
|
||||
frequency: [0,100],
|
||||
threshold: this.get('threshold'),
|
||||
onKick: (mag) => {
|
||||
if (this.get('paused') === false) {
|
||||
this.simulateKick(mag);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -712,14 +671,14 @@ export default Em.Component.extend(helperMixin, visualizerMixin, {
|
|||
this.set('usingMicSupported', false);
|
||||
}
|
||||
|
||||
['volume', 'shuffle', 'repeat', 'volumeMuted', 'threshold', 'interval', 'speakerViewed', 'transitionTime', 'randomTransition', 'playerBottomDisplayed', 'onBeatBriAndColor', 'audioMode', 'songBeatPreferences', 'debugFiltered', 'firstVisit', 'currentVisName', 'playQueue', 'playQueuePointer', 'micBoost'].forEach(function (item) {
|
||||
['volume', 'shuffle', 'repeat', 'volumeMuted', 'threshold', 'transitionTime', 'playerBottomDisplayed', 'onBeatBriAndColor', 'audioMode', 'songBeatPreferences', 'firstVisit', 'currentVisName', 'playQueue', 'playQueuePointer', 'micBoost'].forEach((item)=>{
|
||||
if (!Em.isNone(storage.get('huegasm.' + item))) {
|
||||
var itemVal = storage.get('huegasm.' + item);
|
||||
|
||||
if(Em.isNone(self.actions[item+'Changed'])){
|
||||
self.set(item, itemVal);
|
||||
if(Em.isNone(this.actions[item+'Changed'])){
|
||||
this.set(item, itemVal);
|
||||
} else {
|
||||
self.send(item + 'Changed', itemVal);
|
||||
this.send(item + 'Changed', itemVal);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,23 +11,9 @@ export default Em.Mixin.create({
|
|||
|
||||
beatOptions: {
|
||||
threshold: {
|
||||
range: {min: 0.1, max: 1.0},
|
||||
range: {min: 0, max: 1.0},
|
||||
step: 0.01,
|
||||
defaultValue: 0.3,
|
||||
pips: {
|
||||
mode: 'positions',
|
||||
values: [0,25,50,75,100],
|
||||
density: 3,
|
||||
format: {
|
||||
to: function ( value ) {return value;},
|
||||
from: function ( value ) { return value; }
|
||||
}
|
||||
}
|
||||
},
|
||||
interval: {
|
||||
range: {min: 0, max: 0.5},
|
||||
step: 0.01,
|
||||
defaultValue: 0.1,
|
||||
pips: {
|
||||
mode: 'positions',
|
||||
values: [0,20,40,60,80,100],
|
||||
|
|
@ -70,14 +56,11 @@ export default Em.Mixin.create({
|
|||
|
||||
transitionTime: 0.1,
|
||||
threshold: 0.3,
|
||||
interval: 0.1,
|
||||
micBoost: 5,
|
||||
oldThreshold: null,
|
||||
|
||||
playQueuePointer: -1,
|
||||
playQueue: Em.A(),
|
||||
beatHistory: Em.A(),
|
||||
maxBeatHistorySize: 200,
|
||||
timeElapsed: 0,
|
||||
timeTotal: 0,
|
||||
lastLightBopIndex: 0,
|
||||
|
|
@ -163,39 +146,6 @@ export default Em.Mixin.create({
|
|||
return this.get('playing');
|
||||
}.property('playing'),
|
||||
|
||||
speakerViewed: true,
|
||||
debugFiltered: false,
|
||||
speakerLabel: function() {
|
||||
this.get('storage').set('huegasm.speakerViewed', this.get('speakerViewed'));
|
||||
|
||||
if(this.get('speakerViewed')){
|
||||
this.get('beatHistory').clear();
|
||||
return 'Speaker View';
|
||||
} else {
|
||||
return 'Debug View';
|
||||
}
|
||||
}.property('speakerViewed'),
|
||||
debugFilteredText: function(){
|
||||
var debugFiltered = this.get('debugFiltered');
|
||||
this.get('storage').set('huegasm.debugFiltered', debugFiltered);
|
||||
Em.$('#beatHistory .filterBeat').css('display', debugFiltered === true ? 'inline' : 'none');
|
||||
|
||||
if(debugFiltered){
|
||||
return 'View Filtered';
|
||||
} else {
|
||||
return 'Hide Filtered';
|
||||
}
|
||||
}.property('debugFiltered'),
|
||||
|
||||
randomTransition: true,
|
||||
randomTransitionLabel: function() {
|
||||
if(this.get('randomTransition')){
|
||||
return 'Random';
|
||||
} else {
|
||||
return 'Sequential';
|
||||
}
|
||||
}.property('randomTransition'),
|
||||
|
||||
onBeatBriAndColor: true,
|
||||
onBeatBriAndColorLabel: function() {
|
||||
if(this.get('onBeatBriAndColor')){
|
||||
|
|
@ -296,7 +246,7 @@ export default Em.Mixin.create({
|
|||
onOptionChange: function(self, option){
|
||||
option = option.replace('.[]', '');
|
||||
this.get('storage').set('huegasm.' + option, this.get(option));
|
||||
}.observes('randomTransition', 'onBeatBriAndColor', 'playQueue.[]', 'playQueuePointer'),
|
||||
}.observes('onBeatBriAndColor', 'playQueue.[]', 'playQueuePointer'),
|
||||
|
||||
onRepeatChange: function () {
|
||||
var tooltipTxt = 'Repeat all', type = 'repeat';
|
||||
|
|
|
|||
|
|
@ -146,79 +146,50 @@
|
|||
<div id="playerBottom" class="row {{if dimmerOn "dimmerOn"}}">
|
||||
<div id="beatArea" class="col-sm-7 col-xs-12">
|
||||
{{#if usingBeatPreferences}}
|
||||
<span data-toggle="tooltip" data-placement="bottom auto" data-title="Using your saved beat preferences from the last time you listened to this song" class="bootstrapTooltip savedStarTooltip">
|
||||
<span data-toggle="tooltip" data-placement="bottom" data-title="Using your saved beat preferences from the last time you listened to this song" class="bootstrapTooltip savedStarTooltip">
|
||||
{{paper-icon id="saveBeatPreferencesStar" icon="star"}}
|
||||
</span>
|
||||
{{/if}}
|
||||
|
||||
<div class="row" id="beatOptionRow">
|
||||
<div class="beatOption col-xs-4">
|
||||
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The minimum sound intensity for the beat to register" class="optionDescription bootstrapTooltip">Beat Threshold</span>
|
||||
{{range-slider start=threshold orientation="vertical" step=beatOptions.threshold.step range=beatOptions.threshold.range slide="thresholdChanged" pips=beatOptions.threshold.pips}}
|
||||
<div class="text-center">{{threshold}}</div>
|
||||
<div class="beatOption col-xs-4">
|
||||
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The minimum sound intensity for the beat to register" class="optionDescription bootstrapTooltip">Sensitivity</span>
|
||||
{{range-slider start=threshold orientation="vertical" step=beatOptions.threshold.step range=beatOptions.threshold.range slide="thresholdChanged" pips=beatOptions.threshold.pips}}
|
||||
</div>
|
||||
|
||||
<div class="beatOption col-xs-4">
|
||||
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The time it takes for a light to change color or brightness" class="optionDescription bootstrapTooltip">Transition Time</span>
|
||||
{{range-slider start=transitionTime orientation="vertical" step=beatOptions.transitionTime.step range=beatOptions.transitionTime.range slide="transitionTimeChanged" pips=beatOptions.transitionTime.pips}}
|
||||
</div>
|
||||
|
||||
<div class="beatOption col-xs-4">
|
||||
{{#paper-switch checked=onBeatBriAndColor disabled=trial}}<span data-toggle="tooltip"
|
||||
data-placement="bottom auto"
|
||||
data-title="The properties of the lights to change on beat"
|
||||
class="optionDescription bootstrapTooltip">
|
||||
{{onBeatBriAndColorLabel}}</span>{{/paper-switch}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="beatOption col-xs-4">
|
||||
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The minimum amount of time between each registered beat" class="optionDescription bootstrapTooltip">Beat Interval</span>
|
||||
{{range-slider start=interval orientation="vertical" step=beatOptions.interval.step range=beatOptions.interval.range slide="intervalChanged" pips=beatOptions.interval.pips}}
|
||||
<div class="text-center">{{interval}} sec</div>
|
||||
</div>
|
||||
|
||||
<div class="beatOption col-xs-4">
|
||||
<span data-toggle="tooltip" data-placement="bottom auto" data-title="The time it takes for a light to change color or brightness" class="optionDescription bootstrapTooltip">Transition Time</span>
|
||||
{{range-slider start=transitionTime orientation="vertical" step=beatOptions.transitionTime.step range=beatOptions.transitionTime.range slide="transitionTimeChanged" pips=beatOptions.transitionTime.pips}}
|
||||
<div class="text-center">{{transitionTime}} sec</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="beatOptionButtonGroup" class="row">
|
||||
<div class="beatOption col-xs-3">
|
||||
{{#paper-button raised=true warn=true action="defaultControls"}}Default{{/paper-button}}
|
||||
</div>
|
||||
<div class="beatOption col-xs-4">
|
||||
{{#paper-switch checked=randomTransition disabled=trial}}<span data-toggle="tooltip"
|
||||
data-placement="bottom auto"
|
||||
data-title="The transition order of lights on beat"
|
||||
class="optionDescription bootstrapTooltip">{{randomTransitionLabel}}</span>{{/paper-switch}}
|
||||
</div>
|
||||
<div class="beatOption col-xs-5">
|
||||
{{#paper-switch checked=onBeatBriAndColor disabled=trial}}<span data-toggle="tooltip"
|
||||
data-placement="bottom auto"
|
||||
data-title="The properties of the lights to change on beat"
|
||||
class="optionDescription bootstrapTooltip"> {{onBeatBriAndColorLabel}}</span>{{/paper-switch}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="beatContainer" class="col-sm-5 col-xs-12">
|
||||
{{#if speakerViewed}}
|
||||
<div id="beatContainer" class="col-sm-5 col-xs-12">
|
||||
<div class="bezel">
|
||||
<div class="rivet1"></div>
|
||||
<div class="rivet2"></div>
|
||||
<div class="rivet3"></div>
|
||||
<div class="rivet4"></div>
|
||||
<div class="rivet5"></div>
|
||||
<div class="rivet6"></div>
|
||||
<div class="rivet7"></div>
|
||||
<div class="rivet8"></div>
|
||||
<div class="rivet1"></div>
|
||||
<div class="rivet2"></div>
|
||||
<div class="rivet3"></div>
|
||||
<div class="rivet4"></div>
|
||||
<div class="rivet5"></div>
|
||||
<div class="rivet6"></div>
|
||||
<div class="rivet7"></div>
|
||||
<div class="rivet8"></div>
|
||||
|
||||
<div id="beatSpeakerCenterOuter">
|
||||
<div id="beatSpeakerCenterInner" class="cursorPointer" {{action "clickSpeaker"}}>
|
||||
<div id="beatSpeakerCenterOuter">
|
||||
<div id="beatSpeakerCenterInner" class="cursorPointer" {{action "clickSpeaker"}}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div id="beatHistory">
|
||||
{{#each beatHistory as |item|}}
|
||||
<p>{{{item}}}</p>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
||||
{{#paper-switch checked=debugFiltered class="debugFilteredSwitch"}} {{debugFilteredText}} {{/paper-switch}}
|
||||
{{/if}}
|
||||
|
||||
{{#paper-switch checked=speakerViewed class="speakerSwitch"}} {{speakerLabel}} {{/paper-switch}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ember-notify closeAfter=5000}}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
$playerHeight: 400px;
|
||||
$playerDefaultIconColor: #BBBBBB;
|
||||
$footerHeight: 40px;
|
||||
$playerBottomHeight: 340px;
|
||||
$playerBottomHeight: 300px;
|
||||
$secondaryThemeColor: #F12B24;
|
||||
$glowingText: 0 0 5px #fff, 0 0 10px #fff, 0 0 20px #228DFF;
|
||||
$dimmerOnButtonColor: #404040;
|
||||
|
|
@ -833,23 +833,8 @@ md-switch.md-default-theme.md-checked .md-thumb {
|
|||
}
|
||||
|
||||
#beatContainer {
|
||||
-webkit-transform: translate3d(0, 0, 0); // hack for chrome to force hardware acceleration and stop flickering
|
||||
padding: 0;
|
||||
height: $playerBottomHeight;
|
||||
.speakerSwitch {
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
margin-left: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.debugFilteredSwitch {
|
||||
top: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
margin-left: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
#beatArea .lightGroup {
|
||||
|
|
@ -865,31 +850,6 @@ md-switch.md-default-theme.md-checked .md-thumb {
|
|||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#beatHistory {
|
||||
border: 1px solid #C5C5C5;
|
||||
color: black;
|
||||
height: 85%;
|
||||
background-color: white;
|
||||
border-radius: 10px;
|
||||
width: 290px;
|
||||
margin: 40px auto 0 auto;
|
||||
overflow: auto;
|
||||
padding: 10px;
|
||||
box-shadow: 5px 10px 15px 5px rgba(0, 0, 0, 0.1);
|
||||
p {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.filterBeat {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
#ytplayer{
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%
|
||||
}
|
||||
|
||||
.dimmerBulbOn {
|
||||
fill: gold;
|
||||
stroke: gold;
|
||||
|
|
|
|||
375
vendor/dancer.js
vendored
375
vendor/dancer.js
vendored
|
|
@ -13,7 +13,7 @@
|
|||
this.bind( 'update', update );
|
||||
};
|
||||
|
||||
Dancer.version = '0.4.0';
|
||||
Dancer.version = 'X.X.X';
|
||||
Dancer.adapters = {};
|
||||
|
||||
Dancer.prototype = {
|
||||
|
|
@ -22,10 +22,6 @@
|
|||
// Loading an Audio element
|
||||
if ( source instanceof HTMLElement ) {
|
||||
this.source = source;
|
||||
if ( Dancer.isSupported() === 'flash' ) {
|
||||
this.source = { src: Dancer._getMP3SrcFromAudio( source ) };
|
||||
}
|
||||
|
||||
// Loading an object with src, [codecs]
|
||||
} else if(source instanceof EventTarget){
|
||||
this.source = source;
|
||||
|
|
@ -227,8 +223,6 @@
|
|||
return null;
|
||||
} else if ( !isUnsupportedSafari() && ( window.AudioContext || window.webkitAudioContext )) {
|
||||
return 'webaudio';
|
||||
} else if ( FlashDetect.versionAtLeast( 9 ) ) {
|
||||
return 'flash';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
|
|
@ -237,8 +231,7 @@
|
|||
Dancer.canPlay = function ( type ) {
|
||||
var canPlay = audioEl.canPlayType;
|
||||
return !!(
|
||||
Dancer.isSupported() === 'flash' ?
|
||||
type.toLowerCase() === 'mp3' :
|
||||
type.toLowerCase() === 'mp3' ||
|
||||
audioEl.canPlayType &&
|
||||
audioEl.canPlayType( CODECS[ type.toLowerCase() ] ).replace( /no/, ''));
|
||||
};
|
||||
|
|
@ -264,8 +257,6 @@
|
|||
switch ( Dancer.isSupported() ) {
|
||||
case 'webaudio':
|
||||
return new Dancer.adapters.webaudio( instance );
|
||||
case 'flash':
|
||||
return new Dancer.adapters.flash( instance );
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
@ -333,10 +324,12 @@
|
|||
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 );
|
||||
console.log('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxKICK:' + magnitude);
|
||||
} else {
|
||||
this.offKick && this.offKick.call( this.dancer, magnitude );
|
||||
this.currentThreshold -= this.decay;
|
||||
|
|
@ -368,15 +361,15 @@
|
|||
SAMPLE_RATE = 44100;
|
||||
|
||||
var adapter = function ( dancer ) {
|
||||
var context = new AudioContext(), filter = context.createBiquadFilter();
|
||||
var context = new AudioContext();//, filter = context.createBiquadFilter();
|
||||
|
||||
filter.type = "lowpass";
|
||||
filter.frequency.value = 440;
|
||||
//filter.type = "lowpass";
|
||||
//filter.frequency.value = 440;
|
||||
|
||||
this.dancer = dancer;
|
||||
this.audio = new Audio();
|
||||
this.context = context;
|
||||
this.filter = filter;
|
||||
//this.filter = filter;
|
||||
};
|
||||
|
||||
adapter.prototype = {
|
||||
|
|
@ -505,7 +498,7 @@
|
|||
|
||||
this.source.connect(this.proc);
|
||||
this.source.connect(this.gain);
|
||||
this.source.connect( this.filter );
|
||||
//this.source.connect( this.filter );
|
||||
this.gain.connect(this.context.destination);
|
||||
this.proc.connect(this.context.destination);
|
||||
//this.filter.connect( this.context.destination );
|
||||
|
|
@ -519,154 +512,6 @@
|
|||
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var
|
||||
SAMPLE_SIZE = 1024,
|
||||
SAMPLE_RATE = 44100,
|
||||
smLoaded = false,
|
||||
smLoading = false,
|
||||
CONVERSION_COEFFICIENT = 0.93;
|
||||
|
||||
var adapter = function ( dancer ) {
|
||||
this.dancer = dancer;
|
||||
this.wave_L = [];
|
||||
this.wave_R = [];
|
||||
this.spectrum = [];
|
||||
window.SM2_DEFER = true;
|
||||
};
|
||||
|
||||
adapter.prototype = {
|
||||
// `source` can be either an Audio element, if supported, or an object
|
||||
// either way, the path is stored in the `src` property
|
||||
load : function ( source ) {
|
||||
var _this = this;
|
||||
this.path = source ? source.src : this.path;
|
||||
|
||||
this.isLoaded = false;
|
||||
this.progress = 0;
|
||||
|
||||
!window.soundManager && !smLoading && loadSM.call( this );
|
||||
|
||||
if ( window.soundManager ) {
|
||||
this.audio = soundManager.createSound({
|
||||
id : 'dancer' + Math.random() + '',
|
||||
url : this.path,
|
||||
stream : true,
|
||||
autoPlay : false,
|
||||
autoLoad : true,
|
||||
whileplaying : function () {
|
||||
_this.update();
|
||||
},
|
||||
whileloading : function () {
|
||||
_this.progress = this.bytesLoaded / this.bytesTotal;
|
||||
},
|
||||
onload : function () {
|
||||
_this.fft = new FFT( SAMPLE_SIZE, SAMPLE_RATE );
|
||||
_this.signal = new Float32Array( SAMPLE_SIZE );
|
||||
_this.waveform = new Float32Array( SAMPLE_SIZE );
|
||||
_this.isLoaded = true;
|
||||
_this.progress = 1;
|
||||
_this.dancer.trigger( 'loaded' );
|
||||
}
|
||||
});
|
||||
this.dancer.audio = this.audio;
|
||||
}
|
||||
|
||||
// Returns audio if SM already loaded -- otherwise,
|
||||
// sets dancer instance's audio property after load
|
||||
return this.audio;
|
||||
},
|
||||
|
||||
play : function () {
|
||||
this.audio.play();
|
||||
this.isPlaying = true;
|
||||
},
|
||||
|
||||
pause : function () {
|
||||
this.audio.pause();
|
||||
this.isPlaying = false;
|
||||
},
|
||||
|
||||
setVolume : function ( volume ) {
|
||||
this.audio.setVolume( volume * 100 );
|
||||
},
|
||||
|
||||
getVolume : function () {
|
||||
return this.audio.volume / 100;
|
||||
},
|
||||
|
||||
getProgress : function () {
|
||||
return this.progress;
|
||||
},
|
||||
|
||||
getWaveform : function () {
|
||||
return this.waveform;
|
||||
},
|
||||
|
||||
getSpectrum : function () {
|
||||
return this.fft.spectrum;
|
||||
},
|
||||
|
||||
getTime : function () {
|
||||
return this.audio.position / 1000;
|
||||
},
|
||||
|
||||
update : function () {
|
||||
if ( !this.isPlaying && !this.isLoaded ) return;
|
||||
this.wave_L = this.audio.waveformData.left;
|
||||
this.wave_R = this.audio.waveformData.right;
|
||||
var avg;
|
||||
for ( var i = 0, j = this.wave_L.length; i < j; i++ ) {
|
||||
avg = parseFloat(this.wave_L[ i ]) + parseFloat(this.wave_R[ i ]);
|
||||
this.waveform[ 2 * i ] = avg / 2;
|
||||
this.waveform[ i * 2 + 1 ] = avg / 2;
|
||||
this.signal[ 2 * i ] = avg * CONVERSION_COEFFICIENT;
|
||||
this.signal[ i * 2 + 1 ] = avg * CONVERSION_COEFFICIENT;
|
||||
}
|
||||
|
||||
this.fft.forward( this.signal );
|
||||
this.dancer.trigger( 'update' );
|
||||
}
|
||||
};
|
||||
|
||||
function loadSM () {
|
||||
var adapter = this;
|
||||
smLoading = true;
|
||||
loadScript( Dancer.options.flashJS, function () {
|
||||
soundManager = new SoundManager();
|
||||
soundManager.flashVersion = 9;
|
||||
soundManager.flash9Options.useWaveformData = true;
|
||||
soundManager.useWaveformData = true;
|
||||
soundManager.useHighPerformance = true;
|
||||
soundManager.useFastPolling = true;
|
||||
soundManager.multiShot = false;
|
||||
soundManager.debugMode = false;
|
||||
soundManager.debugFlash = false;
|
||||
soundManager.url = Dancer.options.flashSWF;
|
||||
soundManager.onready(function () {
|
||||
smLoaded = true;
|
||||
adapter.load();
|
||||
});
|
||||
soundManager.ontimeout(function(){
|
||||
console.error( 'Error loading SoundManager2.swf' );
|
||||
});
|
||||
soundManager.beginDelayedInit();
|
||||
});
|
||||
}
|
||||
|
||||
function loadScript ( url, callback ) {
|
||||
var
|
||||
script = document.createElement( 'script' ),
|
||||
appender = document.getElementsByTagName( 'script' )[0];
|
||||
script.type = 'text/javascript';
|
||||
script.src = url;
|
||||
script.onload = callback;
|
||||
appender.parentNode.insertBefore( script, appender );
|
||||
}
|
||||
|
||||
Dancer.adapters.flash = adapter;
|
||||
|
||||
})();
|
||||
|
||||
/*
|
||||
* DSP.js - a comprehensive digital signal processing library for javascript
|
||||
|
|
@ -843,205 +688,3 @@ FFT.prototype.forward = function(buffer) {
|
|||
|
||||
return this.calculateSpectrum();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Copyright (c) Copyright (c) 2007, Carl S. Yestrau All rights reserved.
|
||||
Code licensed under the BSD License: http://www.featureblend.com/license.txt
|
||||
Version: 1.0.4
|
||||
*/
|
||||
var FlashDetect = new function(){
|
||||
var self = this;
|
||||
self.installed = false;
|
||||
self.raw = "";
|
||||
self.major = -1;
|
||||
self.minor = -1;
|
||||
self.revision = -1;
|
||||
self.revisionStr = "";
|
||||
var activeXDetectRules = [
|
||||
{
|
||||
"name":"ShockwaveFlash.ShockwaveFlash.7",
|
||||
"version":function(obj){
|
||||
return getActiveXVersion(obj);
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"ShockwaveFlash.ShockwaveFlash.6",
|
||||
"version":function(obj){
|
||||
var version = "6,0,21";
|
||||
try{
|
||||
obj.AllowScriptAccess = "always";
|
||||
version = getActiveXVersion(obj);
|
||||
}catch(err){}
|
||||
return version;
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"ShockwaveFlash.ShockwaveFlash",
|
||||
"version":function(obj){
|
||||
return getActiveXVersion(obj);
|
||||
}
|
||||
}
|
||||
];
|
||||
/**
|
||||
* Extract the ActiveX version of the plugin.
|
||||
*
|
||||
* @param {Object} The flash ActiveX object.
|
||||
* @type String
|
||||
*/
|
||||
var getActiveXVersion = function(activeXObj){
|
||||
var version = -1;
|
||||
try{
|
||||
version = activeXObj.GetVariable("$version");
|
||||
}catch(err){}
|
||||
return version;
|
||||
};
|
||||
/**
|
||||
* Try and retrieve an ActiveX object having a specified name.
|
||||
*
|
||||
* @param {String} name The ActiveX object name lookup.
|
||||
* @return One of ActiveX object or a simple object having an attribute of activeXError with a value of true.
|
||||
* @type Object
|
||||
*/
|
||||
var getActiveXObject = function(name){
|
||||
var obj = -1;
|
||||
try{
|
||||
obj = new ActiveXObject(name);
|
||||
}catch(err){
|
||||
obj = {activeXError:true};
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
/**
|
||||
* Parse an ActiveX $version string into an object.
|
||||
*
|
||||
* @param {String} str The ActiveX Object GetVariable($version) return value.
|
||||
* @return An object having raw, major, minor, revision and revisionStr attributes.
|
||||
* @type Object
|
||||
*/
|
||||
var parseActiveXVersion = function(str){
|
||||
var versionArray = str.split(",");//replace with regex
|
||||
return {
|
||||
"raw":str,
|
||||
"major":parseInt(versionArray[0].split(" ")[1], 10),
|
||||
"minor":parseInt(versionArray[1], 10),
|
||||
"revision":parseInt(versionArray[2], 10),
|
||||
"revisionStr":versionArray[2]
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Parse a standard enabledPlugin.description into an object.
|
||||
*
|
||||
* @param {String} str The enabledPlugin.description value.
|
||||
* @return An object having raw, major, minor, revision and revisionStr attributes.
|
||||
* @type Object
|
||||
*/
|
||||
var parseStandardVersion = function(str){
|
||||
var descParts = str.split(/ +/);
|
||||
var majorMinor = descParts[2].split(/\./);
|
||||
var revisionStr = descParts[3];
|
||||
return {
|
||||
"raw":str,
|
||||
"major":parseInt(majorMinor[0], 10),
|
||||
"minor":parseInt(majorMinor[1], 10),
|
||||
"revisionStr":revisionStr,
|
||||
"revision":parseRevisionStrToInt(revisionStr)
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Parse the plugin revision string into an integer.
|
||||
*
|
||||
* @param {String} The revision in string format.
|
||||
* @type Number
|
||||
*/
|
||||
var parseRevisionStrToInt = function(str){
|
||||
return parseInt(str.replace(/[a-zA-Z]/g, ""), 10) || self.revision;
|
||||
};
|
||||
/**
|
||||
* Is the major version greater than or equal to a specified version.
|
||||
*
|
||||
* @param {Number} version The minimum required major version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.majorAtLeast = function(version){
|
||||
return self.major >= version;
|
||||
};
|
||||
/**
|
||||
* Is the minor version greater than or equal to a specified version.
|
||||
*
|
||||
* @param {Number} version The minimum required minor version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.minorAtLeast = function(version){
|
||||
return self.minor >= version;
|
||||
};
|
||||
/**
|
||||
* Is the revision version greater than or equal to a specified version.
|
||||
*
|
||||
* @param {Number} version The minimum required revision version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.revisionAtLeast = function(version){
|
||||
return self.revision >= version;
|
||||
};
|
||||
/**
|
||||
* Is the version greater than or equal to a specified major, minor and revision.
|
||||
*
|
||||
* @param {Number} major The minimum required major version.
|
||||
* @param {Number} (Optional) minor The minimum required minor version.
|
||||
* @param {Number} (Optional) revision The minimum required revision version.
|
||||
* @type Boolean
|
||||
*/
|
||||
self.versionAtLeast = function(major){
|
||||
var properties = [self.major, self.minor, self.revision];
|
||||
var len = Math.min(properties.length, arguments.length);
|
||||
for(i=0; i<len; i++){
|
||||
if(properties[i]>=arguments[i]){
|
||||
if(i+1<len && properties[i]==arguments[i]){
|
||||
continue;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Constructor, sets raw, major, minor, revisionStr, revision and installed public properties.
|
||||
*/
|
||||
self.FlashDetect = function(){
|
||||
if(navigator.plugins && navigator.plugins.length>0){
|
||||
var type = 'application/x-shockwave-flash';
|
||||
var mimeTypes = navigator.mimeTypes;
|
||||
if(mimeTypes && mimeTypes[type] && mimeTypes[type].enabledPlugin && mimeTypes[type].enabledPlugin.description){
|
||||
var version = mimeTypes[type].enabledPlugin.description;
|
||||
var versionObj = parseStandardVersion(version);
|
||||
self.raw = versionObj.raw;
|
||||
self.major = versionObj.major;
|
||||
self.minor = versionObj.minor;
|
||||
self.revisionStr = versionObj.revisionStr;
|
||||
self.revision = versionObj.revision;
|
||||
self.installed = true;
|
||||
}
|
||||
}else if(navigator.appVersion.indexOf("Mac")==-1 && window.execScript){
|
||||
var version = -1;
|
||||
for(var i=0; i<activeXDetectRules.length && version==-1; i++){
|
||||
var obj = getActiveXObject(activeXDetectRules[i].name);
|
||||
if(!obj.activeXError){
|
||||
self.installed = true;
|
||||
version = activeXDetectRules[i].version(obj);
|
||||
if(version!=-1){
|
||||
var versionObj = parseActiveXVersion(version);
|
||||
self.raw = versionObj.raw;
|
||||
self.major = versionObj.major;
|
||||
self.minor = versionObj.minor;
|
||||
self.revision = versionObj.revision;
|
||||
self.revisionStr = versionObj.revisionStr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}();
|
||||
};
|
||||
FlashDetect.JS_RELEASE = "1.0.4";
|
||||
|
|
|
|||
Reference in a new issue