diff --git a/.gitignore b/.gitignore index bdd63e2..856db27 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ build/bundle.js node_modules *.log dist +package.json +todo +recordings/ \ No newline at end of file diff --git a/README.md b/README.md index 6fd514b..5db220c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,30 @@ # Macaron Vibrotactile Icon Editor + +### Fun keyboard shortcuts: + +`arrow keys` : move playhead left or right. +`ctrl`+(`>`/`<`) : x-scale +`ctrl`+`/` : Divides selected keyframes in half. +`space` : play. +`backspace`/`delete` : remove selected keyframe(s) +`ctrl`+(`left`/`right`) : increment playhead + + +#### Changelog: + +2016.05.31 : added a random noise parameter. +2016.05.31 : changed simplify shortcut from ctrl+s to ctrl+/ because ctrl+s also saves the page. +2016.05.30 : added x-scale functionality with ctrl-< and ctrl->, where selected points are scaled, and the rest are translated. +2016.05.30 : added a simplify functionality with ctrl-s, where points are decimated by half + ## Quick install: `npm install` + `npm run deploy` Run with: diff --git a/app/classes/parameters.js b/app/classes/parameters.js new file mode 100644 index 0000000..9c0f156 --- /dev/null +++ b/app/classes/parameters.js @@ -0,0 +1,85 @@ +// Constructor +function Parameters() { + // always initialize all instance properties + // this.io = io; + // this.baz = 'baz'; // default value + this.parameters = { + + position : { + valueScale:[0,1], //normalized + data : [ + { id: 1, t: 1500, value:0.5, selected:false}], + fun: function(out,paramvalue){ + return paramvalue + } + }, + + random : { + valueScale:[0,1], + data : [ + {id:2,t:1500,value:0,selected:false}], + fun: function(out,paramvalue){ + return out+mapValue(Math.random(),0,1,0,paramvalue) + } + }, + + maxValue : { + valueScale:[0,1], + data : [ + {id:3,t:1500,value:1, selected:false}], + fun: function(out,paramvalue){ + if (out > paramvalue){ + return paramvalue + } + else{ + return out + } + } + }, + + minValue : { + valueScale:[0,1], + data : [ + {id:3,t:1500,value:0, selected:false}], + fun: function(out,paramvalue){ + if (out < paramvalue){ + return paramvalue + } + else{ + return out + } + } + }, + } + +} +// class methods +Parameters.prototype.getParameters = function() { + return this.parameters; +}; +Parameters.prototype.getParameterKeyArray = function() { + return Object.keys(this.parameters); +}; +Parameters.prototype.initParamsWith = function(val) { + var ret = {} + Object.keys(this.parameters).forEach(function(key){ + ret[key] = val + }) + return ret; +}; + + + +// export the class +module.exports = Parameters; + + +function mapValue(value, minIn, maxIn, minOut, maxOut){ + if (value>maxIn){ + value = maxIn; + } + if (value
+ diff --git a/app/editorheader.jsx b/app/editorheader.jsx index 74ef954..e56c10a 100644 --- a/app/editorheader.jsx +++ b/app/editorheader.jsx @@ -14,8 +14,9 @@ var UserAgreement = require('./useragreement.jsx'); var UserInstructions = require('./userinstructions.jsx'); -var IO = require('./../thirdparty/socket/socket.io.js'); -var socket = io(); +var io = require('./../thirdparty/socket/socket.io.js'); + +var FileInput = require('react-file-input'); //for reset button var VTIconStore = require('./stores/vticonstore.js'); @@ -23,6 +24,21 @@ var VTIconStore = require('./stores/vticonstore.js'); var EditorHeader = React.createClass({ + + + getInitialState: function(){ + return{ + socket:{} + } + }, + emit: function(st,msg) { + this.state.socket.emit(st,msg) + }, + componentDidMount: function() { + var socket = io.connect("http://localhost:3000"); + this.setState({socket:socket}); + + }, mixins : [ Reflux.connect(AnimationStore.store, 'animation'), //emitted updates go to 'animation' key Reflux.connect(StudyStore.store, 'study'), //emitted updates go to 'study' key @@ -42,7 +58,10 @@ var EditorHeader = React.createClass({ displayRenderButton:true, displayStopButton:true, displayResetButton:true, - uploadFileID:"uploadedFile" + displayGetSetPointsButton:true, + displayLoadVoodleButton:true, + uploadFileID:"uploadedFile", + uploadVoodleFileID: "voodleFile" } @@ -70,29 +89,63 @@ var EditorHeader = React.createClass({ }, _onLoadClick : function(e) { + + var uploadedFiles = document.getElementById(this.props.uploadFileID); + console.log('normal _onLoadClick uploaded file: ',uploadedFiles.files[0].name) if (uploadedFiles.files.length > 0) { SaveLoadStore.actions.loadMacaronFile(uploadedFiles.files[0]); + } uploadedFiles.value = []; }, _onTestClick : function(e) { - socket.emit('test'); + this.emit('test'); }, _onRenderClick : function(e) { - socket.emit('render'); + console.log("_onRenderClick called!!") + this.emit('render'); }, _onStopClick : function(e) { - socket.emit('stop_render'); + this.emit('stop_render'); }, _onResetClick : function(e) { VTIconStore.actions.reset(); }, + _onGetSetPointsClick : function(e) { + this.emit('get_setPoints'); + }, + _onLoadSetPointsClick: function(e){ + + console.log('in _onLoadSetPointsClick!') + var uploadedFiles = document.getElementById(this.props.uploadVoodleFileID); + console.log('uploadedFiles: ',uploadedFiles) + if (uploadedFiles.files.length > 0) { + console.log('name of file: ',uploadedFiles.files[0].name) + this.emit('load_setPoints',uploadedFiles.files[0].name) + + } + uploadedFiles.value = []; + + }, + _onLoadSetPointsButtonClick: function(e){ + console.log('in _onLoadSetPoints~BUTTON~Click') + document.getElementById(this.props.uploadVoodleFileID).click(); + }, + handleChange: function(event) { + console.log('Selected file:', event.target.files[0].name); + name = event.target.files[0].name + if(name != undefined){ + console.log('we are emitting!!!!') + this.emit('load_setPoints', name); + + } + }, /** * Rendering * @@ -200,28 +253,28 @@ var EditorHeader = React.createClass({ { resetButton = (); } + var getSetPointsButton = + if (this.props.displayGetSetPointsButton) + { + getSetPointsButton = (); + } + var loadVoodleButton = + if (this.props.displayLoadVoodleButton) + { + + + loadVoodleButton = ( + + Load Voodle + ); + } return ( - //
- // {startButton} - // Macaron - // - // {animationOptionDisplay} - // {interfaceModeDisplay} - // - // - // {saveButton} - // {loadButton} - // {saveButton} - // {testButton} - // {renderButton} - // {stopButton} - - // - - - //
+ +
+ +
@@ -235,10 +288,31 @@ var EditorHeader = React.createClass({ {startButton} {stopButton} {resetButton} + {getSetPointsButton} + {loadVoodleButton} +
+
+ + +
+ ); } }); + + + + + + + + + module.exports = EditorHeader; diff --git a/app/iconvis.jsx b/app/iconvis.jsx index 4f54d90..3e7b04c 100644 --- a/app/iconvis.jsx +++ b/app/iconvis.jsx @@ -9,13 +9,51 @@ var WaveformPathMixin = require('./util/waveformpathmixin.js'); var VTIconStore = require('./stores/vticonstore.js'); var DragStore = require('./stores/dragstore.js'); +var io = require('socket.io-client/socket.io') + var IconVis = React.createClass({ + getInitialState: function(){ + return{ + socket:{} + } + }, + loadPosition : function(setPoints) { + // still a stub + var points = setPoints.map(function(p,i){ + var obj = { + selected : false, + t: i * 34, + value: p + } + return obj; + }); + + var parameter_keyframe_map = { + position: points, + }; + VTIconStore.actions.newMultipleKeyframes(parameter_keyframe_map); + console.log("loaded position"); + + }, + componentDidMount: function(){ + var socket = io.connect("http://localhost:3000"); + socket.on("process_buffer_done",function(){ + socket.emit("get_setPoints") + }) + socket.on("send_setPoints",function(msg){ + this.loadPosition(msg); + }.bind(this)) + this.setState({socket:socket}); + }, + emit: function(st,msg) { + this.state.socket.emit(st,msg) + }, mixins : [ TimelineMixin("divWrapper"), WaveformPathMixin, - Reflux.listenTo(VTIconStore.store,"onVTIconChange")], - + Reflux.listenTo(VTIconStore.store,"onVTIconChange") + ], propTypes: { vticon : React.PropTypes.object.isRequired, currentTime: React.PropTypes.number.isRequired, @@ -23,11 +61,11 @@ var IconVis = React.createClass({ playheadFill: React.PropTypes.string.isRequired, interpolateParameters: React.PropTypes.func.isRequired, name : React.PropTypes.string.isRequired, - selection : React.PropTypes.object.isRequired }, - + selection : React.PropTypes.object.isRequired + }, getDefaultProps: function() { return { - height: 50, //was 25 + height: 100, //was 25 width:'100%', visColor:'#4C4233', background:"#FAFAFA", @@ -45,21 +83,25 @@ var IconVis = React.createClass({ var scaleY = d3.scale.linear() .domain( [-1, 1]) // return value from sine .range([0, this.props.height]); - var scaleX = this.props.scaleX; + this._visPath = this.computePositionPath( + this.props.vticon, + scaleX, + scaleY, + this.props.resolution + ) + var actual_height = this.props.height / 2; - this._visPath = this.computeWaveformPath(this.props.vticon, - scaleX, scaleY, - this.props.resolution, this.props.maxFrequencyRendered, this.props.limitFrequencies); - console.log('changing vticon'); if (this.props.logValues) { - var socket = io(); - socket.emit('path',{range:this.props.height,path:this._visPath,name:this.props.name}); - + + var the_path = { + range: actual_height, + path: this._visPath, + name: this.props.name + } + this.emit('path', the_path); } - }, - onMouseDown: function(e) { VTIconStore.actions.selectVTIcon(this.props.name); if(this.props.selectable) { @@ -68,8 +110,6 @@ var IconVis = React.createClass({ }, render : function() { - - var divStyle = { height:this.props.height, width:this.props.width, diff --git a/app/keyframeeditor.jsx b/app/keyframeeditor.jsx index 03022da..25a2fff 100644 --- a/app/keyframeeditor.jsx +++ b/app/keyframeeditor.jsx @@ -14,9 +14,6 @@ var KeyframeEditor = React.createClass({ TimelineMixin("divWrapper"), Reflux.connect(ScaleStore.store, 'scales') //emitted updates go to 'scales' key ], - - - propTypes: { name : React.PropTypes.string.isRequired, parameter : React.PropTypes.string.isRequired, @@ -29,7 +26,7 @@ var KeyframeEditor = React.createClass({ getDefaultProps: function() { return { - height: 80, //was 190, works to shrink editor elements well + height: 180, //was 190, works to shrink editor elements well width:"100%", circleColor:'#FF8400', selectedCircleColor:'#B05B00', @@ -66,7 +63,6 @@ var KeyframeEditor = React.createClass({ render : function() { - var keyframeCircleRadius = this.props.keyframeCircleRadius; var circleColor = this.props.circleColor; var selectedCircleColor = this.props.selectedCircleColor; @@ -94,7 +90,7 @@ var KeyframeEditor = React.createClass({ var divStyle = { height:this.props.height, width:this.props.width, - background:this.props.background + background:this.props.backgroundColor }; @@ -234,7 +230,8 @@ var KeyframeEditor = React.createClass({ return (
- + + {visPath} {paramLabels} diff --git a/app/playhead.jsx b/app/playhead.jsx index 97ec8ac..5e4483f 100644 --- a/app/playhead.jsx +++ b/app/playhead.jsx @@ -17,7 +17,7 @@ var PlayHead = React.createClass({ currentTime: React.PropTypes.number.isRequired, playheadFill: React.PropTypes.string.isRequired, displayPlayhead: React.PropTypes.bool.isRequired - }, + }, getDefaultProps: function() { return { @@ -25,7 +25,7 @@ var PlayHead = React.createClass({ width:'100%', playheadWidth: 20, background:'#EEEEEE', - axisTickLength:7 + axisTickLength:7, } }, @@ -70,6 +70,7 @@ var PlayHead = React.createClass({ lineProps['x2'] = scaleX(tick); lineProps['y1'] = 0; lineProps['y2'] = 0 + axisTickLength; + var line = React.DOM.line(lineProps); //tick label @@ -81,9 +82,17 @@ var PlayHead = React.createClass({ //hacky way of centering labelProps['x'] = scaleX(tick)-2.5*tick.toString().length; labelProps['y'] = axisTickLength+10; - var label = React.DOM.text(labelProps, tick); + + var label = React.DOM.text(labelProps, tick); + // var label = tick + // var label = function() { + // return ( + // + // ) + // } + return ( {line} {label} diff --git a/app/stores/examplestore.js b/app/stores/examplestore.js index 6c6760e..b0dc4c9 100644 --- a/app/stores/examplestore.js +++ b/app/stores/examplestore.js @@ -3,1436 +3,40 @@ import Reflux from 'reflux'; var LogStore = require('./logstore.js'); var VTIconStore = require('./vticonstore.js'); var PlaybackStore = require('./playbackstore.js'); +var Parameters = require('../classes/parameters.js'); +var params = new Parameters(); var EXAMPLE_KEY = "example"; //TODO: More general? -var sineExample = function(frequency, duration, dt) { - var rv = {}; - rv.duration = duration; - rv.selected=false; - rv.selectedTimeRange={ - active:false, - time1:0, - time2:0 - }; +// var sineExample = function(frequency, duration, dt) { +// var rv = {}; +// rv.duration = duration; +// rv.selected=false; +// rv.selectedTimeRange={ +// active:false, +// time1:0, +// time2:0 +// }; - rv.parameters = { - amplitude: { - valueScale:[0,1], //normalized - data : [] - }, +// rv.parameters = params.getParameters() - frequency: { - valueScale:[50,500], //Hz - data : [ - { - "t": 1025.1572327044023, - "value": 312.50000000000057, - }, - { - "t": 1943.3962264150944, - "value": 157.4999999999999, - }] - }, - ampTex: { //testing - valueScale:[0,1], //normalized - data :[ - { id: 2, t: 1500, value:0.5, selected:false}] - }, - freqTex: { - valueScale:[10,50], //Hz - data : [ - { id: 3, t: 1500, value:25, selected:false}] - }, +// for (var t = 0; t < duration; t+=dt) +// { - bias: { - valueScale:[0.10,0.90], //normalized - data : [ - { id: 4, t: 1500, value:0.5, selected:false}] - } - }; +// rv.parameters.amplitude.data.push( +// { +// t:t, +// value:Math.sin(2*Math.PI*frequency*t/1000 - Math.PI/2*frequency)/2.0+0.5 +// }); +// } - for (var t = 0; t < duration; t+=dt) - { - rv.parameters.amplitude.data.push( - { - t:t, - value:Math.sin(2*Math.PI*frequency*t/1000 - Math.PI/2*frequency)/2.0+0.5 - }); - } - - return rv; -}; - - -var randomNoiseExample = function(duration, dt) { - var rv = {}; - rv.duration = duration; - rv.selected=false; - rv.selectedTimeRange={ - active:false, - time1:0, - time2:0 - }; - - rv.parameters = { - amplitude: { - valueScale:[0,1], //normalized - data : [] - }, - - frequency: { - valueScale:[50,500], //Hz - data : [] - }, - ampTex: { //testing - valueScale:[0,1], //normalized - data :[ - { id: 2, t: 1500, value:0.5, selected:false}] - }, - freqTex: { - valueScale:[10,50], //Hz - data : [ - { id: 3, t: 1500, value:25, selected:false}] - }, - - bias: { - valueScale:[0.10,0.90], //normalized - data : [ - { id: 4, t: 1500, value:0.5, selected:false}] - } - }; - - for (var t = 0; t < duration; t+=dt) - { - //TODO: Make this use "seedrandom" package - rv.parameters.frequency.data.push( - { - t:t, - value:Math.random()*(rv.parameters.frequency.valueScale[1]-rv.parameters.frequency.valueScale[0])+rv.parameters.frequency.valueScale[0] - }); - - rv.parameters.amplitude.data.push( - { - t:t, - value:Math.random() - }); - } - - return rv; -}; +// return rv; +// }; var examples = { - v4: { - "duration": 3000, - "selected": true, - "selectedTimeRange": { - "active": false, - "time1": 0, - "time2": 0 - }, - "parameters": { - "amplitude": { - "valueScale": [ - 0, - 1 - ], - "data": [ - { - "id": 36, - "t": 0, - "value": 2.220446049250313e-16, - "selected": true - }, - { - "id": 29, - "t": 347.10743801652893, - "value": 0.07222222222222222, - "selected": true - }, - { - "id": 30, - "t": 638.4297520661158, - "value": 0.18888888888888894, - "selected": true - }, - { - "id": 31, - "t": 873.9669421487602, - "value": 0.33333333333333337, - "selected": true - }, - { - "id": 32, - "t": 1028.9256198347107, - "value": 0.49444444444444435, - "selected": true - }, - { - "id": 33, - "t": 1140.495867768595, - "value": 0.6833333333333332, - "selected": true - }, - { - "id": 34, - "t": 1221.0743801652893, - "value": 1, - "selected": true - }, - { - "id": 35, - "t": 1239.6694214876034, - "value": 2.7755575615628914e-17, - "selected": true - }, - { - "id": 45, - "t": 1591.194968553459, - "value": 2.220446049250313e-16, - "selected": true - }, - { - "id": 46, - "t": 1938.3024065699879, - "value": 0.07222222222222222, - "selected": true - }, - { - "id": 47, - "t": 2229.624720619575, - "value": 0.18888888888888894, - "selected": true - }, - { - "id": 48, - "t": 2465.161910702219, - "value": 0.33333333333333337, - "selected": true - }, - { - "id": 49, - "t": 2620.1205883881694, - "value": 0.49444444444444435, - "selected": true - }, - { - "id": 50, - "t": 2731.6908363220537, - "value": 0.6833333333333332, - "selected": true - }, - { - "id": 51, - "t": 2812.269348718748, - "value": 1, - "selected": true - }, - { - "id": 52, - "t": 2830.8643900410625, - "value": 2.7755575615628914e-17, - "selected": true - } - ] - }, - "frequency": { - "valueScale": [ - 50, - 500 - ], - "data": [ - { - "id": 43, - "t": 0, - "value": 50, - "selected": true - }, - { - "id": 39, - "t": 591.1949685534591, - "value": 104.99999999999977, - "selected": true - }, - { - "id": 40, - "t": 962.2641509433959, - "value": 192.4999999999999, - "selected": true - }, - { - "id": 41, - "t": 1264.1509433962265, - "value": 305, - "selected": true - }, - { - "id": 42, - "t": 1289.308176100629, - "value": 50.00000000000023, - "selected": true - }, - { - "id": 53, - "t": 1591.194968553459, - "value": 50, - "selected": true - }, - { - "id": 54, - "t": 2182.3899371069183, - "value": 104.99999999999977, - "selected": true - }, - { - "id": 55, - "t": 2553.459119496855, - "value": 192.4999999999999, - "selected": true - }, - { - "id": 56, - "t": 2855.3459119496856, - "value": 305, - "selected": true - }, - { - "id": 57, - "t": 2880.503144654088, - "value": 50.00000000000023, - "selected": true - } - ] - }, - "ampTex": { //testing - "valueScale":[0,1], //normalized - "data" :[ - { "id": 2, "t": 1500, "value":0.5, "selected":false}] - }, - "freqTex": { - "valueScale":[10,50], //Hz - "data" : [ - { "id": 3, "t": 1500, "value":25, "selected":false}] - }, - - "bias": { - "valueScale":[0.10,0.90], //normalized - "data" : [ - { "id": 4, "t": 1500, "value":0.5, "selected":false}] - } - } -}, - - v3: { - "duration": 3000, - "selectedTimeRange": { - "active": false, - "time1": 0, - "time2": 0 - }, - "selected": false, - "parameters": { - "amplitude": { - "valueScale": [ - 0, - 1 - ], - "data": [ - { - "t": 81.76100628930817, - "value": 1.8041124150158794e-16, - "selected": false, - "id": 49 - }, - { - "t": 88.0503144654088, - "value": 0.20000000000000007, - "selected": false, - "id": 50 - }, - { - "t": 182.38993710691824, - "value": 0.20000000000000007, - "selected": false, - "id": 52 - }, - { - "t": 226.41509433962273, - "value": 0.8111111111111111, - "selected": false, - "id": 53 - }, - { - "t": 339.62264150943395, - "value": 0.8111111111111111, - "selected": false, - "id": 66 - }, - { - "t": 352.20125786163516, - "value": 0.20000000000000007, - "selected": false, - "id": 68 - }, - { - "t": 452.83018867924517, - "value": 0.20000000000000007, - "selected": false, - "id": 69 - }, - { - "t": 496.8553459119499, - "value": 0.8111111111111111, - "selected": false, - "id": 70 - }, - { - "t": 672.9559748427675, - "value": 0.8111111111111111, - "selected": false, - "id": 71 - }, - { - "t": 1433.9622641509425, - "value": 2.7755575615628914e-16, - "selected": false, - "id": 60 - }, - { - "id": 156, - "t": 1578.6163522012578, - "value": 1.8041124150158794e-16, - "selected": true - }, - { - "id": 157, - "t": 1584.9056603773583, - "value": 0.20000000000000007, - "selected": true - }, - { - "id": 158, - "t": 1679.245283018868, - "value": 0.20000000000000007, - "selected": true - }, - { - "id": 159, - "t": 1723.2704402515724, - "value": 0.8111111111111111, - "selected": true - }, - { - "id": 160, - "t": 1836.4779874213837, - "value": 0.8111111111111111, - "selected": true - }, - { - "id": 161, - "t": 1849.0566037735848, - "value": 0.20000000000000007, - "selected": true - }, - { - "id": 162, - "t": 1949.6855345911947, - "value": 0.20000000000000007, - "selected": true - }, - { - "id": 163, - "t": 1993.7106918238994, - "value": 0.8111111111111111, - "selected": true - }, - { - "id": 164, - "t": 2169.811320754717, - "value": 0.8111111111111111, - "selected": true - }, - { - "id": 165, - "t": 2930.817610062892, - "value": 2.7755575615628914e-16, - "selected": true - } - ] - }, - "frequency": { - "valueScale": [ - 50, - 500 - ], - "data": [ - { - "t": 0, - "value": 57.5, - "selected": false, - "id": 3 - }, - { - "t": 1500, - "value": 57.5, - "selected": false, - "id": 200 - } - ] - }, - "ampTex": { //testing - "valueScale":[0,1], //normalized - "data" :[ - { "id": 2, "t": 1500, "value":0.5, "selected":false}] - }, - "freqTex": { - "valueScale":[10,50], //Hz - "data" : [ - { "id": 3, "t": 1500, "value":25, "selected":false}] - }, - - "bias": { - "valueScale":[0.10,0.90], //normalized - "data" : [ - { "id": 4, "t": 1500, "value":0.5, "selected":false}] - } - } - - }, - -sineExample: sineExample(1, 3000, 25), - -randomExample: randomNoiseExample(3000, 100), - -v10_augmented: { //w/ v-10-21-3-11 - "duration": 3000, - "selectedTimeRange": { - "active": false, - "time1": 0, - "time2": 0 - }, - "selected": false, - "parameters": { - "amplitude": { - "valueScale": [ - 0, - 1 - ], - "data": [ - { - "t": 70.4350537969747, - "value": 5.551115123125783e-17, - "selected": false, - "id": 1078 - }, - { - "t": 71.49280108113695, - "value": 1, - "selected": false, - "id": 1080 - }, - { - "t": 421.3836477987428, - "value": 1, - "selected": false, - "id": 1091 - }, - { - "t": 490.5660377358495, - "value": 0.32222222222222224, - "selected": false, - "id": 1082 - }, - { - "t": 496.76438484328725, - "value": 0.32222222222222224, - "selected": false, - "id": 1083 - }, - { - "t": 528.3018867924541, - "value": 1, - "selected": false, - "id": 1092 - }, - { - "t": 878.1927335100597, - "value": 1, - "selected": false, - "id": 1093 - }, - { - "t": 962.2641509433981, - "value": 0.32222222222222224, - "selected": false, - "id": 1096 - }, - { - "t": 968.4624980508358, - "value": 0.32222222222222224, - "selected": false, - "id": 1097 - }, - { - "t": 1006.2893081761024, - "value": 1, - "selected": false, - "id": 1100 - }, - { - "t": 1349.8908467176072, - "value": 1, - "selected": false, - "id": 1101 - }, - { - "t": 1630.378398045637, - "value": 5.551115123125783e-17, - "selected": false, - "id": 1089 - }, - { - "t": 1779.8742138364782, - "value": 0.005555555555555425, - "selected": false, - "id": 1157 - }, - { - "t": 1781.1138832579659, - "value": 1, - "selected": false, - "id": 1158 - }, - { - "t": 1836.477987421384, - "value": 1, - "selected": false, - "id": 1172 - }, - { - "t": 1936.0725609439162, - "value": 0.17777777777777787, - "selected": false, - "id": 1159 - }, - { - "t": 1991.8576849108583, - "value": 0.17777777777777787, - "selected": false, - "id": 1160 - }, - { - "t": 1998.0560320182963, - "value": 1, - "selected": false, - "id": 1161 - }, - { - "t": 2050.3144654088055, - "value": 1, - "selected": false, - "id": 1173 - }, - { - "t": 2153.014709704247, - "value": 0.17777777777777787, - "selected": false, - "id": 1162 - }, - { - "t": 2208.799833671189, - "value": 0.17777777777777787, - "selected": false, - "id": 1163 - }, - { - "t": 2214.9981807786266, - "value": 0.17777777777777787, - "selected": false, - "id": 1164 - }, - { - "t": 2228.725505483653, - "value": 1, - "selected": false, - "id": 1165 - }, - { - "t": 2295.5974842767296, - "value": 1, - "selected": false, - "id": 1174 - }, - { - "t": 2902.0713134778307, - "value": 5.551115123125783e-17, - "selected": false, - "id": 1166 - } - ], - - }, - "frequency": { - "valueScale": [ - 50, - 500 - ], - "data": [ - { - "t": 490.56603773585016, - "value": 72.5, - "selected": false, - "id": 1103 - }, - { - "t": 496.85534591195056, - "value": 114.99999999999977, - "selected": false, - "id": 1102 - }, - { - "t": 943.3962264150962, - "value": 114.99999999999977, - "selected": false, - "id": 1106 - }, - { - "t": 949.6855345911965, - "value": 155.0000000000001, - "selected": false, - "id": 1104 - }, - { - "id": 1176, - "t": 1729.559748427673, - "value": 155.0000000000001, - "selected": false - }, - { - "t": 1742.1383647798746, - "value": 184.99999999999943, - "selected": false, - "id": 1170 - }, - { - "t": 2196.3121783876504, - "value": 184.99999999999943, - "selected": false, - "id": 1167 - }, - { - "t": 2196.312178387651, - "value": 125.00000000000057, - "selected": false, - "id": 1168 - } - ] - }, - "ampTex": { //testing - "valueScale":[0,1], //normalized - "data" :[ - { "id": 2, "t": 1500, "value":0.5, "selected":false}] - }, - "freqTex": { - "valueScale":[10,50], //Hz - "data" : [ - { "id": 3, "t": 1500, "value":25, "selected":false}] - }, - - "bias": { - "valueScale":[0.10,0.90], //normalized - "data" : [ - { "id": 4, "t": 1500, "value":0.5, "selected":false}] - } - } -}, - -//v-10-09-1-8 -v10_09_1_8: { - "duration": 3000, - "selectedTimeRange": { - "active": false, - "time1": 0, - "time2": 0 - }, - "selected": false, - "parameters": { - "amplitude": { - "valueScale": [ - 0, - 1 - ], - "data": [ - { - "t": 327.04402515723274, - "value": 0.005555555555555314, - "selected": true, - "id": 351 - }, - { - "t": 333.33333333333337, - "value": 1, - "selected": true, - "id": 307 - }, - { - "t": 433.6477987421385, - "value": 0.9755282581475768, - "selected": true, - "id": 309 - }, - { - "t": 483.64779874213843, - "value": 0.9045084971874737, - "selected": true, - "id": 311 - }, - { - "t": 533.6477987421384, - "value": 0.7938926261462367, - "selected": true, - "id": 313 - }, - { - "t": 583.6477987421384, - "value": 0.6545084971874737, - "selected": true, - "id": 315 - }, - { - "t": 658.1761006289308, - "value": 0.4283295960759858, - "selected": true, - "id": 321 - }, - { - "t": 708.1761006289308, - "value": 0.31771372503474865, - "selected": true, - "id": 323 - }, - { - "t": 758.1761006289308, - "value": 0.24669396407464556, - "selected": true, - "id": 325 - }, - { - "t": 833.1761006289308, - "value": 0.22837805192465344, - "selected": true, - "id": 328 - }, - { - "t": 883.1761006289308, - "value": 0.2767189601280383, - "selected": true, - "id": 330 - }, - { - "t": 933.1761006289308, - "value": 0.3686688316289485, - "selected": true, - "id": 332 - }, - { - "t": 982.5471698113206, - "value": 0.5726616769645598, - "selected": true, - "id": 338 - }, - { - "t": 1032.5471698113204, - "value": 0.7214396943142177, - "selected": true, - "id": 340 - }, - { - "t": 1082.5471698113204, - "value": 0.8479978350377182, - "selected": true, - "id": 342 - }, - { - "t": 1157.5471698113201, - "value": 0.9699727025920212, - "selected": true, - "id": 345 - }, - { - "t": 1276.7295597484278, - "value": 1, - "selected": true, - "id": 347 - }, - { - "t": 1289.3081761006295, - "value": 0.005555555555555508, - "selected": true, - "id": 349 - }, - { - "t": 1823.8993710691825, - "value": 0.005555555555555314, - "selected": true, - "id": 357 - }, - { - "t": 1830.188679245283, - "value": 1, - "selected": true, - "id": 358 - }, - { - "t": 1930.5031446540881, - "value": 0.9755282581475768, - "selected": true, - "id": 359 - }, - { - "t": 1980.5031446540881, - "value": 0.9045084971874737, - "selected": true, - "id": 360 - }, - { - "t": 2030.5031446540881, - "value": 0.7938926261462367, - "selected": true, - "id": 361 - }, - { - "t": 2080.5031446540884, - "value": 0.6545084971874737, - "selected": true, - "id": 362 - }, - { - "t": 2155.0314465408806, - "value": 0.4283295960759858, - "selected": true, - "id": 363 - }, - { - "t": 2205.0314465408806, - "value": 0.31771372503474865, - "selected": true, - "id": 364 - }, - { - "t": 2255.0314465408806, - "value": 0.24669396407464556, - "selected": true, - "id": 365 - }, - { - "t": 2330.0314465408806, - "value": 0.22837805192465344, - "selected": true, - "id": 366 - }, - { - "t": 2380.0314465408806, - "value": 0.2767189601280383, - "selected": true, - "id": 367 - }, - { - "t": 2430.0314465408806, - "value": 0.3686688316289485, - "selected": true, - "id": 368 - }, - { - "t": 2479.4025157232704, - "value": 0.5726616769645598, - "selected": true, - "id": 369 - }, - { - "t": 2529.40251572327, - "value": 0.7214396943142177, - "selected": true, - "id": 370 - }, - { - "t": 2579.40251572327, - "value": 0.8479978350377182, - "selected": true, - "id": 371 - }, - { - "t": 2654.40251572327, - "value": 0.9699727025920212, - "selected": true, - "id": 372 - }, - { - "t": 2773.5849056603774, - "value": 1, - "selected": true, - "id": 373 - }, - { - "t": 2786.163522012579, - "value": 0.005555555555555508, - "selected": true, - "id": 374 - } - ] - }, - "frequency": { - "valueScale": [ - 50, - 500 - ], - "data": [ - { - "t": 336.4779874213836, - "value": 357.5000000000002, - "selected": true, - "id": 184 - }, - { - "t": 798.7421383647799, - "value": 77.49999999999966, - "selected": true, - "id": 352 - }, - { - "t": 1270.440251572327, - "value": 357.5000000000002, - "selected": true, - "id": 355 - }, - { - "t": 1833.3333333333335, - "value": 357.5000000000002, - "selected": true, - "id": 375 - }, - { - "t": 2295.5974842767296, - "value": 77.49999999999966, - "selected": true, - "id": 376 - }, - { - "t": 2767.295597484277, - "value": 357.5000000000002, - "selected": true, - "id": 377 - } - ] - }, - "ampTex": { //testing - "valueScale":[0,1], //normalized - "data" :[ - { "id": 2, "t": 1500, "value":0.5, "selected":false}] - }, - "freqTex": { - "valueScale":[10,50], //Hz - "data" : [ - { "id": 3, "t": 1500, "value":25, "selected":false}] - }, - - "bias": { - "valueScale":[0.10,0.90], //normalized - "data" : [ - { "id": 4, "t": 1500, "value":0.5, "selected":false}] - } - - } -}, - - textures: { - "duration": 3000, - "selectedTimeRange": { - "active": false, - "time1": 0, - "time2": 0 - }, - "selected": false, - "parameters": { - "amplitude": { - "valueScale": [ - 0, - 1 - ], - "data": [ - { - "t": 433.96226415094316, - "value": 1.1102230246251565e-16, - "selected": false, - "id": 78 - }, - { - "t": 440.2515723270441, - "value": 0.38888888888888895, - "selected": false, - "id": 79 - }, - { - "t": 522.0125786163524, - "value": 0.38888888888888895, - "selected": false, - "id": 80 - }, - { - "t": 534.5911949685534, - "value": 0.2666666666666666, - "selected": false, - "id": 73 - }, - { - "t": 616.3522012578613, - "value": 0.2666666666666666, - "selected": false, - "id": 74 - }, - { - "t": 622.6415094339623, - "value": 0.6555555555555554, - "selected": false, - "id": 75 - }, - { - "t": 704.4025157232707, - "value": 0.6555555555555554, - "selected": false, - "id": 76 - }, - { - "t": 710.6918238993711, - "value": 0.4388888888888889, - "selected": false, - "id": 71 - }, - { - "t": 792.4528301886791, - "value": 0.4388888888888889, - "selected": false, - "id": 72 - }, - { - "t": 798.74213836478, - "value": 0.8277777777777777, - "selected": false, - "id": 69 - }, - { - "t": 880.5031446540884, - "value": 0.8277777777777777, - "selected": false, - "id": 70 - }, - { - "t": 886.7924528301886, - "value": 0.6166666666666667, - "selected": false, - "id": 67 - }, - { - "t": 968.5534591194966, - "value": 0.6166666666666667, - "selected": false, - "id": 68 - }, - { - "t": 968.5534591194967, - "value": 1, - "selected": false, - "id": 42 - }, - { - "t": 1050.314465408805, - "value": 1, - "selected": false, - "id": 45 - }, - { - "t": 1062.8930817610064, - "value": 0.6166666666666667, - "selected": false, - "id": 47 - }, - { - "t": 1144.6540880503144, - "value": 0.6166666666666667, - "selected": false, - "id": 50 - }, - { - "t": 1157.2327044025158, - "value": 1, - "selected": false, - "id": 51 - }, - { - "t": 1238.9937106918242, - "value": 1, - "selected": false, - "id": 52 - }, - { - "t": 1245.2830188679245, - "value": 0.6166666666666667, - "selected": false, - "id": 54 - }, - { - "t": 1327.0440251572325, - "value": 0.6166666666666667, - "selected": false, - "id": 55 - }, - { - "t": 1327.0440251572327, - "value": 1, - "selected": false, - "id": 56 - }, - { - "t": 1408.805031446541, - "value": 1, - "selected": false, - "id": 57 - }, - { - "t": 1421.3836477987422, - "value": 0.6166666666666667, - "selected": false, - "id": 58 - }, - { - "t": 1509.4339622641508, - "value": 0.6166666666666667, - "selected": false, - "id": 81 - }, - { - "t": 1509.433962264151, - "value": 1, - "selected": false, - "id": 82 - }, - { - "t": 1591.1949685534591, - "value": 1, - "selected": false, - "id": 83 - }, - { - "t": 1603.7735849056608, - "value": 0.6166666666666667, - "selected": false, - "id": 84 - }, - { - "t": 1685.5345911949685, - "value": 0.6166666666666667, - "selected": false, - "id": 85 - }, - { - "t": 1698.11320754717, - "value": 1, - "selected": false, - "id": 86 - }, - { - "t": 1779.8742138364782, - "value": 1, - "selected": false, - "id": 87 - }, - { - "t": 1786.1635220125786, - "value": 0.6166666666666667, - "selected": false, - "id": 88 - }, - { - "t": 1867.9245283018868, - "value": 0.6166666666666667, - "selected": false, - "id": 89 - }, - { - "t": 1867.9245283018868, - "value": 1, - "selected": false, - "id": 90 - }, - { - "t": 1949.6855345911954, - "value": 1, - "selected": false, - "id": 91 - }, - { - "t": 1962.2641509433965, - "value": 0.6166666666666667, - "selected": false, - "id": 92 - }, - { - "t": 2031.4465408805033, - "value": 0.6166666666666667, - "selected": false, - "id": 110 - }, - { - "t": 2037.7358490566037, - "value": 0.8277777777777777, - "selected": false, - "id": 113 - }, - { - "t": 2119.496855345912, - "value": 0.8277777777777777, - "selected": false, - "id": 114 - }, - { - "t": 2125.786163522013, - "value": 0.4388888888888889, - "selected": false, - "id": 115 - }, - { - "t": 2207.5471698113206, - "value": 0.4388888888888889, - "selected": false, - "id": 116 - }, - { - "id": 119, - "t": 2207.547169811321, - "value": 0.6555555555555554, - "selected": false - }, - { - "id": 120, - "t": 2289.308176100629, - "value": 0.6555555555555554, - "selected": false - }, - { - "id": 121, - "t": 2301.8867924528304, - "value": 0.2666666666666666, - "selected": false - }, - { - "id": 122, - "t": 2383.647798742138, - "value": 0.2666666666666666, - "selected": false - }, - { - "id": 123, - "t": 2389.937106918239, - "value": 0.38888888888888895, - "selected": false - }, - { - "id": 124, - "t": 2471.698113207547, - "value": 0.38888888888888895, - "selected": false - }, - { - "id": 125, - "t": 2477.9874213836474, - "value": 1.1102230246251565e-16, - "selected": false - } - ] - }, - "frequency": { - "valueScale": [ - 50, - 500 - ], - "data": [ - { - "id": 139, - "t": 427.67295597484275, - "value": 117.50000000000034, - "selected": false - }, - { - "id": 129, - "t": 886.7924528301886, - "value": 277.5, - "selected": false - }, - { - "id": 130, - "t": 1094.3396226415093, - "value": 235, - "selected": false - }, - { - "id": 132, - "t": 1276.7295597484276, - "value": 277.5, - "selected": false - }, - { - "id": 133, - "t": 1484.2767295597484, - "value": 235, - "selected": false - }, - { - "id": 134, - "t": 1672.955974842767, - "value": 277.5, - "selected": false - }, - { - "id": 135, - "t": 1880.503144654088, - "value": 235, - "selected": false - }, - { - "id": 136, - "t": 2081.761006289308, - "value": 277.5, - "selected": false - }, - { - "id": 138, - "t": 2471.698113207547, - "value": 117.50000000000034, - "selected": false - } - ] - }, - - "ampTex": { //testing - "valueScale":[0,1], //normalized - "data" :[ - { "id": 2, "t": 1500, "value":0.5, "selected":false}] - }, - "freqTex": { - "valueScale":[10,50], //Hz - "data" : [ - { "id": 3, "t": 1500, "value":25, "selected":false}] - }, - - "bias": { - "valueScale":[0.10,0.90], //normalized - "data" : [ - { "id": 4, "t": 1500, "value":0.5, "selected":false}] - } - - } -}, -}; + //sineExample: sineExample(1, 3000, 25) + paulsExample: params.getParameters() +} var exampleActions = Reflux.createActions( [ diff --git a/app/stores/saveloadstore.js b/app/stores/saveloadstore.js index a05259f..ccdf5ee 100644 --- a/app/stores/saveloadstore.js +++ b/app/stores/saveloadstore.js @@ -6,7 +6,8 @@ var LogStore = require('./logstore.js'); var saveLoadActions = Reflux.createActions( [ 'save', - 'loadMacaronFile' + 'loadMacaronFile', + 'loadVoodleFile' ] ); @@ -43,7 +44,15 @@ var saveLoadStore = Reflux.createStore({ }; reader.readAsText(file); //assumes 'utf8' - } + }, + + onLoadVoodleFile(file) { + var reader = new FileReader(); + reader.onload = function(e){ + var data = reader.result + return data + } + }, }); diff --git a/app/stores/scalestore.js b/app/stores/scalestore.js index 52a67fe..6569246 100644 --- a/app/stores/scalestore.js +++ b/app/stores/scalestore.js @@ -6,6 +6,9 @@ var VTIconStore = require('./vticonstore.js'); //Testing to see if loading example store default will lead to different console output var ExampleStore = require('./examplestore.js'); +var Parameters = require('../classes/parameters.js'); +var params = new Parameters(); + var scaleActions = Reflux.createActions([ 'setTimelineRange', 'setTrackrange', @@ -32,23 +35,14 @@ var scaleStore = Reflux.createStore({ }; for (var i = 0; i < this._names.length; i++) { + var sp = params.initParamsWith(stub_fn); + var top = params.initParamsWith(0); + this._data[this._names[i]] = { scaleTimeline:stub_fn, - scaleParameter:{ - amplitude:stub_fn, - frequency:stub_fn, - ampTex:stub_fn, - freqTex:stub_fn, - bias:stub_fn - }, + scaleParameter:sp, leftOffset:0, - topOffsetParameter:{ - amplitude:0, - frequency:0, - ampTex:0, - freqTex:0, - bias:0 - } + topOffsetParameter:top, }; this._parameterValues[this._names[i]] = {}; diff --git a/app/stores/selectionstore.js b/app/stores/selectionstore.js index ccb21eb..504a67e 100644 --- a/app/stores/selectionstore.js +++ b/app/stores/selectionstore.js @@ -1,6 +1,7 @@ import Reflux from 'reflux'; var VTIconStore = require('./vticonstore.js'); - +var Parameters = require('../classes/parameters.js'); +var params = new Parameters(); var selectActions = Reflux.createActions([ 'startSelecting', @@ -17,37 +18,24 @@ var selectStore = Reflux.createStore({ listenables: [selectActions], + init() { + var parameters = {} + Object.keys(params.getParameters()).forEach(function(param){ + var obj = { + value1: 0, + value2: 0, + } + parameters[param] = obj; + }) + this._data = { active:false, adding:false, targetName:"", time1:0, time2:0, - parameters: { - frequency: { - value1: 0, - value2: 0 - }, - amplitude: { - value1: 0, - value2: 0 - }, //testing - ampTex: { - value1: 0, - value2: 0 - }, - freqTex: { - value1: 0, - value2: 0 - }, - bias: { - value1: 0, - value2: 0 - } - - } - + parameters: parameters, }; }, diff --git a/app/stores/vticonstore.js b/app/stores/vticonstore.js index 6cdc4bd..6393b1e 100644 --- a/app/stores/vticonstore.js +++ b/app/stores/vticonstore.js @@ -1,6 +1,8 @@ import Reflux from 'reflux'; var LogStore = require('./logstore.js'); +var Parameters = require('../classes/parameters.js'); +var params = new Parameters(); var vticonActions = Reflux.createActions( [ @@ -33,7 +35,9 @@ var vticonActions = Reflux.createActions( 'redo', 'reset', - 'deleteSelectedKeyframes' + 'deleteSelectedKeyframes', + 'simplifyKeyframes', + 'xScaleKeyframes' ] ); @@ -42,11 +46,9 @@ var vticonActions = Reflux.createActions( var vticonStore = Reflux.createStore({ listenables: [vticonActions], - init : function() { - this._data = { - - main: { //left side editor + // console.log(ParameterStore.actions.getParameters()) + this._defaultParams = { //left side editor duration: 3000, //ms //was 3000 selected: true, @@ -56,91 +58,17 @@ var vticonStore = Reflux.createStore({ time1:0, time2:0 }, + parameters: params.getParameters(), + }; - parameters: { - amplitude: { - valueScale:[0,1], //normalized - data : [ - { id: 0, t: 1500, value:0.5, selected:false}] - }, - - frequency: { - valueScale:[50,500], //Hz - data : [ - { id: 1, t: 1500, value:300, selected:false}] - }, - ampTex: { - valueScale:[0,1], //normalized - data : [ - { id: 2, t: 1500, value:0.5, selected:false}] - }, - freqTex: { - valueScale:[10,50], //Hz - data : [ - { id: 3, t: 1500, value:25, selected:false}] - }, - - bias: { - valueScale:[0.10,0.90], //normalized - data : [ - { id: 4, t: 1500, value:0.5, selected:false}] - } - - } - }, - - example: { //right side editor - duration: 3000, //ms - - selected: true, - - selectedTimeRange: { - active:false, - time1:0, - time2:0 - }, + this._data = { + main: deepCopy(this._defaultParams), + example: deepCopy(this._defaultParams), + }; - parameters: { - amplitude: { - valueScale:[0,1], - data : [ - { id: 6, t: 600, value:0.5, selected:false}, - { id: 7, t: 1500, value:1, selected:false}, - { id: 8, t: 3000, value:0, selected:false}] - }, - - frequency: { - valueScale:[50,500], //Hz , was [50,500] - data : [ - { id: 9, t: 1500, value:1, selected:false}] - }, - - ampTex: { - valueScale:[0,1], //normalized - data : [ - { id: 2, t: 1500, value:0.5, selected:false}] - }, - freqTex: { - valueScale:[10,50], //Hz - data : [ - { id: 3, t: 1500, value:25, selected:false}] - }, - - bias: { - valueScale:[0.10,0.90], //normalized - data : [ - { id: 12, t: 1500, value:0.5, selected:false}] - - - } - } - } - - }; this._previousStates = []; //for undo this._nextStates = []; //for redo - this._kfuidCount = 0; for (var n in this._data) { for (var p in this._data[n].parameters) { @@ -242,6 +170,7 @@ var vticonStore = Reflux.createStore({ onNewMultipleKeyframes(parameter_keyframe_map, overwrite=true, name="") { + console.log("onNewMultipleKeyframes", parameter_keyframe_map) this._saveStateForUndo(); name = this._selectVTIcon(name); var leftover_ids_to_delete = []; @@ -598,6 +527,119 @@ var vticonStore = Reflux.createStore({ this.trigger(this._data); }, + onSimplifyKeyframes(name="") { + // right now scales between first and last selected point + // TODO add this to a in/outpoint framework + // var inpoint = 0; + // var outpoint = 100; + + var kfNotSelected = function(value) { + return !value.selected; + }; + var kfSelected = function(value) { + return value.selected; + }; + + var compare = function (a, b) { + if (a.t < b.t) { + return -1; + } + if (a.t > b.t) { + return 1; + } + // a must be equal to b + return 0; + } + + + name = this._selectVTIcon(name); + + LogStore.actions.log("VTICON_SIMPLIFYKEYFRAMES_"+name); + + this._saveStateForUndo(); + + for (var p in this._data[name].parameters) { + // for(var i = 3; ) + var keep = this._data[name].parameters[p].data.filter(kfNotSelected); + var simplify = this._data[name].parameters[p].data.filter(kfSelected).filter(function(e,i,arr){ + if (i % 2 == 0 || i == arr.length - 1) { + return true; + } else { + return false; + } + }); + this._data[name].parameters[p].data = keep.concat(simplify).sort(compare); + } + + this.trigger(this._data); + }, + + onXScaleKeyframes(scaleFactor,name="") { + + var kfNotSelected = function(value) { + return !value.selected; + }; + var kfSelected = function(value) { + return value.selected; + }; + + var compare = function (a, b) { + if (a.t < b.t) { + return -1; + } + if (a.t > b.t) { + return 1; + } + // a must be equal to b + return 0; + } + + name = this._selectVTIcon(name); + + LogStore.actions.log("VTICON_XSCALEKEYFRAMES_"+name); + + this._saveStateForUndo(); + + for (var p in this._data[name].parameters) { + + var originalPoints = this._data[name].parameters[p].data.sort(compare) + + var middle = originalPoints.filter(kfSelected); + + if (middle.length > 0) { + var start_i = originalPoints.indexOf(middle[0]) + var end_i = originalPoints.indexOf(middle[middle.length - 1]) + var end_t = middle[middle.length - 1].t + var start_t = middle[0].t + + + var start = originalPoints.slice(0,start_i); + var end = originalPoints.slice(end_i + 1,originalPoints.length); + + middle.forEach(function(m,i,arr){ + m.t = Math.floor(m.t + ((m.t - start_t) * scaleFactor)); + }) + + var end_pos = middle[middle.length - 1].t; + + end.forEach(function(e){ + e.t = (e.t - end_t) + end_pos + }) + + var ret = start.concat(end).concat(middle).sort(compare).filter(function(kf){ + if (kf.t > this._defaultParams.duration) { + return false; + } else { + return true; + } + }.bind(this)); + this._data[name].parameters[p].data = ret; + } + } + + this.trigger(this._data); + }, + /** * KF Guards */ @@ -734,95 +776,8 @@ var vticonStore = Reflux.createStore({ onReset() { this._data = { - main: { //left side editor - duration: 3000, //ms //was 3000 - - selected: true, - - selectedTimeRange: { - active:false, - time1:0, - time2:0 - }, - - parameters: { - amplitude: { - valueScale:[0,1], //normalized - data : [ - { id: 0, t: 1500, value:0.5, selected:false}] - }, - - frequency: { - valueScale:[50,500], //Hz - data : [ - { id: 1, t: 1500, value:300, selected:false}] - }, - ampTex: { - valueScale:[0,1], //normalized - data : [ - { id: 2, t: 1500, value:0.5, selected:false}] - }, - freqTex: { - valueScale:[10,50], //Hz - data : [ - { id: 3, t: 1500, value:25, selected:false}] - }, - - bias: { - valueScale:[0.10,0.90], //normalized - data : [ - { id: 4, t: 1500, value:0.5, selected:false}] - } - - } - }, - - example: { //right side editor - duration: 3000, //ms - - selected: true, - - selectedTimeRange: { - active:false, - time1:0, - time2:0 - }, - - parameters: { - amplitude: { - valueScale:[0,1], - data : [ - { id: 6, t: 600, value:0.5, selected:false}, - { id: 7, t: 1500, value:1, selected:false}, - { id: 8, t: 3000, value:0, selected:false}] - }, - - frequency: { - valueScale:[50,500], //Hz , was [50,500] - data : [ - { id: 9, t: 1500, value:1, selected:false}] - }, - - ampTex: { - valueScale:[0,1], //normalized - data : [ - { id: 2, t: 1500, value:0.5, selected:false}] - }, - freqTex: { - valueScale:[10,50], //Hz - data : [ - { id: 3, t: 1500, value:25, selected:false}] - }, - - bias: { - valueScale:[0.10,0.90], //normalized - data : [ - { id: 12, t: 1500, value:0.5, selected:false}] - - - } - } - } + main: deepCopy(this._defaultParams), + example: deep(this._defaultParams), }; @@ -849,9 +804,22 @@ var vticonStore = Reflux.createStore({ }); - +// recursive function to clone an object. If a non object parameter +// is passed in, that parameter is returned and no recursion occurs. +function deepCopy(obj) { + if (obj === null || typeof obj !== 'object') { + return obj; + } + var temp = obj.constructor(); // give temp the original obj's constructor + for (var key in obj) { + temp[key] = deepCopy(obj[key]); + } + + return temp; +} module.exports = { actions:vticonActions, store:vticonStore -}; \ No newline at end of file +}; + diff --git a/app/util/waveformpathmixin.js b/app/util/waveformpathmixin.js index f0f1b26..e79b516 100644 --- a/app/util/waveformpathmixin.js +++ b/app/util/waveformpathmixin.js @@ -1,6 +1,9 @@ import React from 'react'; import d3 from 'd3'; +var Parameters = require('../classes/parameters.js') +var params = new Parameters() + var WaveformPathMixin = { _iconChanged : function (vticon) { @@ -160,9 +163,8 @@ var WaveformPathMixin = { return state; }, - - - computeWaveformPath(vticon, scaleX, scaleY, resolution, maxFrequencyRendered, limitFrequencies) { + // PB add -------------------------------------------------------------------------------- + computePositionPath(vticon, scaleX, scaleY, resolution) { if (this._iconChanged(vticon)) { @@ -171,62 +173,27 @@ var WaveformPathMixin = { return scaleX(d[0]) }) .y(function(d) { - return scaleY(d[1]) + return scaleY(1-d[1]) }); - limitFrequencies = false; - //do icon visualization var visPoints = []; - var lastFrequency = 0; var dt_in_s = vticon.duration/1000/resolution; - var phaseIntegral = 0; - var phaseIntegralTexture = 0; - var frequencyScaleFactor = Math.max(vticon.parameters.frequency.valueScale[0], vticon.parameters.frequency.valueScale[1])/maxFrequencyRendered; + for (var i = 0; i < resolution; i++) { var t_in_ms = i/resolution*vticon.duration; var t_in_s = t_in_ms/1000; - var amplitude = this.interpolateParameter("amplitude", t_in_ms, vticon);//paramValues.amplitude; - var frequency = this.interpolateParameter("frequency", t_in_ms, vticon); //paramValues.frequency; - var ampTex = 0; - if ("ampTex" in vticon.parameters) - { - ampTex = this.interpolateParameter("ampTex", t_in_ms, vticon); //paramValues.bias; - } - var freqTex = 10; - if ("freqTex" in vticon.parameters) - { - freqTex = this.interpolateParameter("freqTex", t_in_ms, vticon); //paramValues.bias; - } - var bias = 0.5; - if ("bias" in vticon.parameters) - { - bias = this.interpolateParameter("bias", t_in_ms, vticon); //paramValues.bias; - } - - if (limitFrequencies) { - frequency = Math.min(maxFrequencyRendered, frequency/frequencyScaleFactor); - } - //console.log("Frequency for ", i, " at time", t_in_ms, "is", frequency); - //var frequency = interpolateParameter("frequency", t_in_ms); - - if (i == 0) { - // phaseIntegral = frequency; - } else { - // console.log(phaseIntegral); - var biasedFrequency = frequency/bias; - if ( phaseIntegral-Math.floor(phaseIntegral) > 0.25 - && phaseIntegral-Math.floor(phaseIntegral) <= 0.75) - { - biasedFrequency = frequency/(1-bias); + var output = 0; + params.getParameterKeyArray().forEach(function(paramName){ + if (paramName in vticon.parameters) { + var interpolatedKeyframeValue = this.interpolateParameter(paramName, t_in_ms, vticon) + var fn = params.getParameters()[paramName].fun + output = params.getParameters()[paramName].fun(output,interpolatedKeyframeValue) } - phaseIntegral += biasedFrequency*dt_in_s; - phaseIntegralTexture += freqTex*dt_in_s - }; - var v = amplitude * Math.sin(2*Math.PI*phaseIntegral) + ampTex*Math.sin(2*Math.PI*phaseIntegralTexture); - visPoints.push ( [t_in_ms, v]); - lastFrequency = frequency; + + }.bind(this)) + visPoints.push ( [t_in_ms, output]); } this._last_updated_vticon = this._copyIcon(vticon); @@ -234,7 +201,90 @@ var WaveformPathMixin = { } return this._waveformpath; - } + }, + + + // end PB add ---------------------------------------------------------------------------- + + + // computeWaveformPath(vticon, scaleX, scaleY, resolution, maxFrequencyRendered, limitFrequencies) { + // if (this._iconChanged(vticon)) + // { + + // var vticonline = d3.svg.line() + // .x(function(d) { + // return scaleX(d[0]) + // }) + // .y(function(d) { + // return scaleY(d[1]) + // }); + + // limitFrequencies = false; + + // //do icon visualization + // var visPoints = []; + // var lastFrequency = 0; + // var dt_in_s = vticon.duration/1000/resolution; + // var phaseIntegral = 0; + // var phaseIntegralTexture = 0; + // var frequencyScaleFactor = Math.max(vticon.parameters.frequency.valueScale[0], vticon.parameters.frequency.valueScale[1])/maxFrequencyRendered; + // for (var i = 0; i < resolution; i++) { + // var t_in_ms = i/resolution*vticon.duration; + // var t_in_s = t_in_ms/1000; + + // var amplitude = this.interpolateParameter("amplitude", t_in_ms, vticon);//paramValues.amplitude; + // var frequency = this.interpolateParameter("frequency", t_in_ms, vticon); //paramValues.frequency; + // var ampTex = 0; + // if ("ampTex" in vticon.parameters) + // { + // ampTex = this.interpolateParameter("ampTex", t_in_ms, vticon); //paramValues.bias; + // } + // var freqTex = 10; + // if ("freqTex" in vticon.parameters) + // { + // freqTex = this.interpolateParameter("freqTex", t_in_ms, vticon); //paramValues.bias; + // } + // var bias = 0.5; + // if ("bias" in vticon.parameters) + // { + // bias = this.interpolateParameter("bias", t_in_ms, vticon); //paramValues.bias; + // } + // var position = 0.5; + // if ("position" in vticon.parameters) + // { + // position = this.interpolateParameter("position", t_in_ms, vticon); //paramValues.bias; + // } + + // if (limitFrequencies) { + // frequency = Math.min(maxFrequencyRendered, frequency/frequencyScaleFactor); + // } + // //console.log("Frequency for ", i, " at time", t_in_ms, "is", frequency); + // //var frequency = interpolateParameter("frequency", t_in_ms); + + // if (i == 0) { + // // phaseIntegral = frequency; + // } else { + // // console.log(phaseIntegral); + // var biasedFrequency = frequency/bias; + // if ( phaseIntegral-Math.floor(phaseIntegral) > 0.25 + // && phaseIntegral-Math.floor(phaseIntegral) <= 0.75) + // { + // biasedFrequency = frequency/(1-bias); + // } + // phaseIntegral += biasedFrequency*dt_in_s; + // phaseIntegralTexture += freqTex*dt_in_s + // }; + // var v = amplitude * Math.sin(2*Math.PI*phaseIntegral) + ampTex*Math.sin(2*Math.PI*phaseIntegralTexture); + // visPoints.push ( [t_in_ms, v]); + // lastFrequency = frequency; + // } + + // this._last_updated_vticon = this._copyIcon(vticon); + // this._waveformpath = vticonline(visPoints); + // } + + // return this._waveformpath; + // } diff --git a/app/vteditor.jsx b/app/vteditor.jsx index c48fd5d..2816c9d 100644 --- a/app/vteditor.jsx +++ b/app/vteditor.jsx @@ -1,4 +1,3 @@ - import React from 'react'; import Reflux from 'reflux'; import d3 from 'd3'; @@ -165,7 +164,7 @@ var VTEditor = React.createClass({ }, _handleKeyboard : function(e) { - + // console.log(e.keyCode) //use keyCode because it's supported by more browsers //especially Safari, which has best performance so far //look for deprecations in future versions @@ -239,6 +238,27 @@ var VTEditor = React.createClass({ e.preventDefault(); } break; + case 191: // forward slash "/" + if (e.ctrlKey || e.metaKey) { + // VTIconStore.actions.redo(); + VTIconStore.actions.simplifyKeyframes(); + // e.preventDefault(); + } + break; + case 190: //< + if (e.ctrlKey || e.metaKey) { + // VTIconStore.actions.redo(); + VTIconStore.actions.xScaleKeyframes(0.1); + // e.preventDefault(); + } + break; + case 188: //> + if (e.ctrlKey || e.metaKey) { + // VTIconStore.actions.redo(); + VTIconStore.actions.xScaleKeyframes(-0.1); + // e.preventDefault(); + } + break; case 85: //u case 90: //z if(e.ctrlKey || e.metaKey) { @@ -263,14 +283,14 @@ var VTEditor = React.createClass({ render : function() { // TODO: sound of SELECTED icon - var frequency = this.interpolateParameter('frequency', this.state.playback.currentTime, this.state.playback.playingIcon); - var amplitude = this.interpolateParameter('amplitude', this.state.playback.currentTime, this.state.playback.playingIcon); + // var frequency = this.interpolateParameter('frequency', this.state.playback.currentTime, this.state.playback.playingIcon); + // var amplitude = this.interpolateParameter('amplitude', this.state.playback.currentTime, this.state.playback.playingIcon); - var amplitude_for_soundgen = 0; - if (this.props.playbackAtEndOfVTIcon) - { - amplitude_for_soundgen = amplitude; - } + // var amplitude_for_soundgen = 0; + // if (this.props.playbackAtEndOfVTIcon) + // { + // amplitude_for_soundgen = amplitude; + // } var scaleXMain = this.state.scales.main.scaleTimeline; var scaleXExample = this.state.scales.example.scaleTimeline; @@ -280,7 +300,7 @@ var VTEditor = React.createClass({ var designStyle = { - width:"44%", + width:"100%", marginLeft:'auto', marginRight:'auto', display:"block", @@ -288,7 +308,7 @@ var VTEditor = React.createClass({ borderWidth:0 }; var exampleStyle = { - width:"44%", + width:"0%", marginLeft:'auto', marginRight:'auto', display:"block", @@ -305,7 +325,7 @@ var VTEditor = React.createClass({ exampleStyle.borderColor="white"; if (this.state.playback.currentTime < this.state.vticons.main.duration) { - amplitude_for_soundgen = amplitude; + // amplitude_for_soundgen = amplitude; } } else { @@ -313,7 +333,7 @@ var VTEditor = React.createClass({ exampleStyle.borderColor="black"; if (this.state.playback.currentTime < this.state.vticons.example.duration) { - amplitude_for_soundgen = amplitude; + // amplitude_for_soundgen = amplitude; } } @@ -372,8 +392,6 @@ var VTEditor = React.createClass({ return (
- -
{exampleEditor} {exampleGallery} -
); }, diff --git a/backend/functions.js b/backend/functions.js new file mode 100755 index 0000000..be6c407 --- /dev/null +++ b/backend/functions.js @@ -0,0 +1,14 @@ +function mapValue(value, minIn, maxIn, minOut, maxOut){ + if (value>maxIn){ + value = maxIn; + } + if (value - + @@ -36,7 +36,7 @@
Hold your horses, MacaronBit is loading.
- + diff --git a/css/macaron.css b/css/macaron.css index af074c9..ea39103 100644 --- a/css/macaron.css +++ b/css/macaron.css @@ -1,6 +1,7 @@ body { margin:0; - font-family:"Helvetica Nueue", sans-serif; + font-family:"Comic Sans", sans-serif; + font-style: bold; } * { @@ -68,14 +69,17 @@ a:active { /* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#ffc170+0,ffcc8e+100 */ background: #ffc170; /* Old browsers */ background: -moz-linear-gradient(top, #ffc170 0%, #ffcc8e 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffc170), color-stop(100%,#ffcc8e)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #ffc170 0%,#ffcc8e 100%); /* Chrome10+,Safari5.1+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fff), color-stop(100%,#fff)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #fff 0%,#fff 100%); /* Chrome10+,Safari5.1+ #ffcc8e */ background: -o-linear-gradient(top, #ffc170 0%,#ffcc8e 100%); /* Opera 11.10+ */ background: -ms-linear-gradient(top, #ffc170 0%,#ffcc8e 100%); /* IE10+ */ - background: linear-gradient(to bottom, #ffc170 0%,#ffcc8e 100%); /* W3C */ + background: linear-gradient(to bottom, #fff 0%,#fff 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffc170', endColorstr='#ffcc8e',GradientType=0 ); /* IE6-9 */ +} +#keyframeContainer { + background-color: #0f0; } .header .menu { diff --git a/package.json b/package.json index 60ee4f6..84241c8 100644 --- a/package.json +++ b/package.json @@ -3,15 +3,18 @@ "build": "webpack", "dev": "webpack-dev-server --devtool eval --progress --colors --hot --content-base build", "deploy": "NODE_ENV=production webpack -p --config webpack.production.config.js", - "start": "node server.js" + "start": "node backend/server.js" }, "dependencies": { + "colors": "^1.1.2", "d3": "^3.5.6", "exports-loader": "^0.6.2", "express": "^4.13.3", + "fast-csv": "^2.0.0", "firebase": "^2.3.1", "imports-loader": "^0.6.4", - "johnny-five": "^0.9.44", + "johnny-five": "^0.9.44", + "pitchfinder": "^2.0.3", "react": "^0.13.3", "reflux": "^0.2.12", "script-loader": "^0.6.1", diff --git a/package[mac_use_this].json b/package[mac_use_this].json new file mode 100644 index 0000000..2ddfa16 --- /dev/null +++ b/package[mac_use_this].json @@ -0,0 +1,50 @@ +{ + "scripts": { + "build": "webpack", + "dev": "webpack-dev-server --devtool eval --progress --colors --hot --content-base build", + "deploy": "NODE_ENV=production webpack -p --config webpack.production.config.js", + "start": "node backend/server.js" + }, + "dependencies": { + "colors": "^1.1.2", + "d3": "^3.5.6", + "exports-loader": "^0.6.2", + "express": "^4.13.3", + "fast-csv": "^2.0.0", + "firebase": "^2.3.1", + "imports-loader": "^0.6.4", + "johnny-five": "^0.9.44", + "pitchfinder": "^2.0.3", + "react": "^0.13.3", + "reflux": "^0.2.12", + "script-loader": "^0.6.1", + "socket.io": "^1.3.7", + "socket.io-client": "^1.3.7", + "webpack-dev-server": "^1.12.0" + }, + "devDependencies": { + "babel-core": "^5.8.25", + "babel-loader": "^5.3.2", + "css-loader": "^0.19.0", + "file-loader": "^0.8.5", + "node-libs-browser": "^0.5.2", + "style-loader": "^0.12.4", + "url": "^0.11.0", + "url-loader": "^0.5.7", + "webpack": "^1.12.2" + }, + "name": "macaronbit", + "description": "Vibrotactile Icon Editor", + "version": "1.0.0", + "main": "server.js", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/pbucci/MacaronBit.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/pbucci/MacaronBit/issues" + }, + "homepage": "https://github.com/pbucci/MacaronBit#readme" +} diff --git a/package[windows_use_this].json b/package[windows_use_this].json new file mode 100644 index 0000000..379d129 --- /dev/null +++ b/package[windows_use_this].json @@ -0,0 +1,50 @@ +{ + "scripts": { + "build": "webpack", + "dev": "webpack-dev-server --devtool eval --progress --colors --hot --content-base build", + "deploy": "set NODE_ENV=production && webpack -p --config webpack.production.config.js", + "start": "node backend/server.js" + }, + "dependencies": { + "colors": "^1.1.2", + "d3": "^3.5.6", + "exports-loader": "^0.6.2", + "express": "^4.13.3", + "firebase": "^2.3.1", + "fast-csv": "^2.0.0", + "imports-loader": "^0.6.4", + "johnny-five": "^0.9.44", + "pitchfinder": "^2.0.3", + "react": "^0.13.3", + "reflux": "^0.2.12", + "script-loader": "^0.6.1", + "socket.io": "^1.3.7", + "socket.io-client": "^1.3.7", + "webpack-dev-server": "^1.12.0" + }, + "devDependencies": { + "babel-core": "^5.8.25", + "babel-loader": "^5.3.2", + "css-loader": "^0.19.0", + "file-loader": "^0.8.5", + "node-libs-browser": "^0.5.2", + "style-loader": "^0.12.4", + "url": "^0.11.0", + "url-loader": "^0.5.7", + "webpack": "^1.12.2" + }, + "name": "macaronbit", + "description": "Vibrotactile Icon Editor", + "version": "1.0.0", + "main": "server.js", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/pbucci/MacaronBit.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/pbucci/MacaronBit/issues" + }, + "homepage": "https://github.com/pbucci/MacaronBit#readme" +} diff --git a/server.js b/server.js deleted file mode 100755 index dd3701c..0000000 --- a/server.js +++ /dev/null @@ -1,177 +0,0 @@ -//------------------------------------------------------------------------------ -// Requires -//------------------------------------------------------------------------------ -var express = require('express'); -var app = express(); -var five = require("johnny-five"); -var fs = require('fs'); -var path = require('path'); - -//------------------------------------------------------------------------------ -// Globals -//------------------------------------------------------------------------------ -var board, myServo; -var rendered_path_main = []; -var rendered_path_example = []; - -//------------------------------------------------------------------------------ -// Server setup -//------------------------------------------------------------------------------ - - -app.use("/css", express.static(__dirname + '/css')); -app.use("/build", express.static(__dirname + '/build')); -app.use("/dist", express.static(__dirname + '/dist')); -app.use("/thirdparty", express.static(__dirname + '/thirdparty')); -app.get('/', function (req, res) { - res.sendFile(__dirname + '/build/index.html'); //was res.sendfile(__dirname + '/build/index.html'); -}); -var server = app.listen(8080, function () { - var host = server.address().address; - var port = server.address().port; - - console.log('Example app listening at http://%s:%s', host, port); -}); - -//------------------------------------------------------------------------------ -// Socket setup -//------------------------------------------------------------------------------ -var io = require('socket.io')(server); - -//------------------------------------------------------------------------------ -// Socket functions (connect to index.html) -//------------------------------------------------------------------------------ -io.on('connection', function(socket){ - console.log('User connected.'); - - //User disconnects - socket.on('disconnect', function(){ - console.log('User disconnected.'); - }); - - // Test servo motion - socket.on('test', function(){ - io.emit('server_message', 'Started arduino sweep.'); - myMotor.start(255); - console.log('Arduino test.'); - }); - - // Move to degree - socket.on('degree', function(degree){ - var d = parseInt(degree); - io.emit('server_message', 'Moving to degree ' + degree + "."); - myMotor.start(255); - console.log('Moving to degree ' + degree + "."); - }); - - socket.on('stop_render', function() { - stop_render(); - }); - - socket.on('path', function(msg){ - var path = msg['path']; - var range = msg['range']; - var name = msg['name'] - console.log("Path received for " + name + "."); - makepath(range,path,name); - }); - - socket.on('render', function(){ - console.log('Rendering...'); - render(); - }); -}); - -board = new five.Board(); -var myMotor; -board.on("ready", function() { - var standby = new five.Pin(7); - standby.high() - - myMotor = new five.Motor({ - pins: { - pwm:3, - dir:9, - cdir:8 - } - }); - - myServo = new five.Servo({ - pin:10, - center:true, - range: [0,180] - }); - - board.repl.inject({ - motor: myMotor, - servo: myServo - }); - io.emit('server_message','Ready to start board.'); - console.log('Sweep away, my captain.'); -}); - -function makepath(range,path,name) { - var unscaled_points = []; - var scaled_points = []; - var scale_factor = 180 - var offset = 0 - var values = path.split(','); - - if (name=="example") { - scale_factor = 255; - offset = 100 - } - - - for (var i=10; i