|
"use strict"; |
|
|
|
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); |
|
|
|
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; |
|
|
|
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } |
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } |
|
|
|
var nodeHeight = 200; |
|
var nodeWidth = 100; |
|
var pointSize = 16; |
|
var svg; |
|
var counter = 0; |
|
var audioNodes = []; |
|
|
|
var audioConnections = []; |
|
|
|
var NodeViewData = function NodeViewData(x, y) { |
|
_classCallCheck(this, NodeViewData); |
|
|
|
this.x = x | 0; |
|
this.y = y | 0; |
|
}; |
|
|
|
var AudioParam_ = (function (_NodeViewData) { |
|
_inherits(AudioParam_, _NodeViewData); |
|
|
|
function AudioParam_(name, param) { |
|
_classCallCheck(this, AudioParam_); |
|
|
|
_get(Object.getPrototypeOf(AudioParam_.prototype), 'constructor', this).call(this); |
|
this.id = counter++; |
|
this.name = name; |
|
this.audioParam = param; |
|
} |
|
|
|
return AudioParam_; |
|
})(NodeViewData); |
|
|
|
var AudioNode_ = (function (_NodeViewData2) { |
|
_inherits(AudioNode_, _NodeViewData2); |
|
|
|
function AudioNode_(audioNode) { |
|
var _this = this; |
|
|
|
_classCallCheck(this, AudioNode_); |
|
|
|
_get(Object.getPrototypeOf(AudioNode_.prototype), 'constructor', this).call(this); |
|
this.id = counter++; |
|
this.audioNode = audioNode; |
|
this.name = audioNode.constructor.toString().match(/function\s(.*)\(/)[1]; |
|
this.audioParams = []; |
|
for (var i in audioNode) { |
|
if (typeof audioNode[i] === 'function') { |
|
this[i] = audioNode[i].bind(audioNode); |
|
} else { |
|
if (typeof audioNode[i] === 'object') { |
|
this[i] = audioNode[i]; |
|
if (audioNode[i] instanceof AudioParam) { |
|
this.audioParams.push(new AudioParam_(i, audioNode[i])); |
|
} |
|
} else { |
|
Object.defineProperty(this, i, { |
|
get: (function (i) { |
|
return _this.audioNode[i]; |
|
}).bind(null, i), |
|
set: (function (i, v) { |
|
_this.audioNode[i] = v; |
|
}).bind(null, i), |
|
enumerable: true, |
|
configurable: false |
|
}); |
|
} |
|
} |
|
} |
|
} |
|
|
|
// 1つだけだとノードの削除で2つの場合はコネクションの削除 |
|
|
|
_createClass(AudioNode_, null, [{ |
|
key: 'remove', |
|
value: function remove(node, to) { |
|
if (!to) { |
|
for (var i = 0; i < AudioNode_.audioNodes.length; ++i) { |
|
if (AudioNode_.audioNodes[i] === node) { |
|
AudioNode_.audioNodes.splice(i--, 1); |
|
} |
|
} |
|
|
|
for (var i = 0; i < AudioNode_.audioConnections.length; ++i) { |
|
var n = AudioNode_.audioConnections[i]; |
|
if (n.from === node || n.to === node) { |
|
AudioNode_.audioConnections.splice(i--, 1); |
|
} else { |
|
if (!n.to.param) { |
|
for (var d in node.audioParams) { |
|
if (d === n.to.param) { |
|
AudioNode_.audioConnections.splice(i--, 1); |
|
} |
|
}; |
|
} |
|
} |
|
} |
|
} else { |
|
for (var i = 0; i < AudioNode_.audioConnections.length; ++i) { |
|
var _n = AudioNode_.audioConnections[i]; |
|
if (!to.param) { |
|
if (_n.from === node && _n.to === to) { |
|
AudioNode_.audioConnections.splice(i--, 1); |
|
} |
|
} else { |
|
if (_n.from === node && _n.to.param === to.param && _n.to.node === to.node) { |
|
AudioNode_.audioConnections.splice(i--, 1); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
}, { |
|
key: 'create', |
|
value: function create(audionode) { |
|
var obj = new AudioNode_(audionode); |
|
AudioNode_.audioNodes.push(obj); |
|
return obj; |
|
} |
|
}, { |
|
key: 'connect', |
|
value: function connect(from_, to_) { |
|
// 存在チェック |
|
for (var i = 0, l = AudioNode_.audioConnections.length; i < l; ++i) { |
|
if (AudioNode_.audioConnections[i].from === from_ && AudioNode_.audioConnections[i].to === to_) { |
|
throw new Error('接続が重複しています。'); |
|
} |
|
} |
|
if (from_ instanceof AudioNode_) { |
|
if (to_ instanceof AudioNode_) { |
|
from_.connect(to_.audioNode); |
|
} else { |
|
if (to_.param instanceof AudioParam_) { |
|
from_.connect(to_.param.audioParam); |
|
} else { |
|
from_.connect(to_.node, null, to_.param); |
|
} |
|
} |
|
} else if (from_.param) { |
|
if (to_ instanceof AudioNode_) { |
|
from_.node.connect(to_.audioNode, from_.param); |
|
} else { |
|
if (to_.param instanceof AudioParam_) { |
|
from_.node.connect(to_.param.audioParam, from_.param); |
|
} else { |
|
from_.node.connect(to_.node, from_.param, to_.param); |
|
} |
|
} |
|
} else { |
|
throw new Error('Connection Error'); |
|
} |
|
AudioNode_.audioConnections.push({ |
|
'from': from_, |
|
'to': to_ |
|
}); |
|
} |
|
}]); |
|
|
|
return AudioNode_; |
|
})(NodeViewData); |
|
|
|
AudioNode_.audioNodes = []; |
|
AudioNode_.audioConnections = []; |
|
var nodeGroup, lineGroup; |
|
var drag; |
|
|
|
window.onload = function () { |
|
var ctx = new AudioContext(); |
|
d3.select(window).on('resize', function () { |
|
if (svg) { |
|
svg.attr({ |
|
width: window.innerWidth, |
|
height: window.innerHeight |
|
}); |
|
} |
|
}); |
|
|
|
// for(var i in ctx){ |
|
// if(i.match(/create/)){ |
|
// try { |
|
// var o = ctx[i](); |
|
// for(var j in o){ |
|
// if(o[j] instanceof AudioParam){ |
|
// for(var k in o[j]){ |
|
// console.log(' ',k,o[j][k] instanceof AudioParam,o[j][k]); |
|
// } |
|
// } |
|
// } |
|
// |
|
// } catch (e){ |
|
// console.log(e); |
|
// } |
|
// |
|
// } |
|
// } |
|
// |
|
var osc = AudioNode_.create(ctx.createOscillator()); |
|
osc.x = 100; |
|
osc.y = 200; |
|
|
|
var gain = AudioNode_.create(ctx.createGain()); |
|
|
|
gain.x = 400; |
|
gain.y = 200; |
|
|
|
var filter = AudioNode_.create(ctx.createBiquadFilter()); |
|
filter.x = 250; |
|
filter.y = 330; |
|
|
|
var out = AudioNode_.create(ctx.destination); |
|
out.x = 550; |
|
out.y = 300; |
|
|
|
// for(var i in osc){ |
|
// console.log(i + ':' + osc[i]); |
|
// for(var j in osc[i]){ |
|
// console.log(' ' + j + ':' + osc[i][j]); |
|
// } |
|
// } |
|
AudioNode_.connect(osc, filter); |
|
AudioNode_.connect(osc, { node: gain, param: gain.audioParams[0] }); |
|
AudioNode_.connect(filter, gain); |
|
AudioNode_.connect(gain, out); |
|
|
|
console.log(AudioNode_.audioNodes.length); |
|
console.log(AudioNode_.audioConnections.length); |
|
console.log(AudioNode_.audioConnections[0]); |
|
|
|
// osc.audioNode.type = 'sawtooth'; |
|
osc.type = 'sawtooth'; |
|
console.log(osc.type); |
|
osc.frequency.value = 440; |
|
// osc.start(); |
|
// osc.stop(ctx.currentTime + 0.1); |
|
|
|
drag = d3.behavior.drag().origin(function (d) { |
|
return d; |
|
}).on("drag", function (d) { |
|
if (d3.event.sourceEvent.shiftKey) { |
|
console.log('aa'); |
|
return; |
|
} |
|
d.x += d3.event.dx; |
|
d.y += d3.event.dy; |
|
d3.select(this).attr('transform', 'translate(' + (d.x - nodeWidth / 2) + ',' + (d.y - nodeHeight / 2) + ')'); |
|
draw(); |
|
}); |
|
|
|
svg = d3.select('body').append('svg').attr({ 'width': window.innerWidth, 'height': window.innerHeight }); |
|
|
|
nodeGroup = svg.append('g'); |
|
lineGroup = svg.append('g'); |
|
|
|
draw(); |
|
|
|
// window.setTimeout(() => { |
|
// //AudioNode_.remove(osc); |
|
// //AudioNode_.remove(out); |
|
// console.log(AudioNode_.audioNodes.length); |
|
// console.log(AudioNode_.audioConnections.length); |
|
// draw(); |
|
// }, 2000); |
|
// |
|
// draw(); |
|
}; |
|
|
|
function draw() { |
|
// nodeGroup.selectAll('g').remove(); |
|
var gd = nodeGroup.selectAll('g').data(AudioNode_.audioNodes, function (d) { |
|
return d.id; |
|
}); |
|
|
|
var g = gd.enter().append('g').attr('transform', function (d) { |
|
return 'translate(' + (d.x - nodeWidth / 2) + ',' + (d.y - nodeHeight / 2) + ')'; |
|
}).call(drag); |
|
|
|
g.append('rect'); |
|
g.append('text'); |
|
gd.select('rect').attr({ 'width': nodeWidth, 'height': nodeHeight, 'class': 'audioNode' }); |
|
|
|
gd.each(function (d) { |
|
var sel = d3.select(this); |
|
console.log(d.name + '**'); |
|
d.audioParams.forEach(function (d) { |
|
console.log(d.name); |
|
}); |
|
var gp = sel.append('g'); |
|
var gpd = gp.selectAll('g').data(d.audioParams, function (d) { |
|
return d.id; |
|
}); |
|
|
|
var gpdg = gpd.enter().append('g'); |
|
|
|
gpdg.append('circle').attr({ 'r': pointSize / 2, cx: 0, cy: function cy(d, i) { |
|
d.x = 0;d.y = (i + 1) * 20;return d.y; |
|
}, 'class': 'param' }); |
|
|
|
gpdg.append('text').attr({ x: function x(d) { |
|
return d.x + pointSize / 2 + 5; |
|
}, y: function y(d) { |
|
return d.y; |
|
}, 'class': 'label' }).text(function (d) { |
|
return d.name; |
|
}); |
|
|
|
gpd.exit().remove(); |
|
}); |
|
|
|
gd.select('text').attr({ x: 0, y: -10, 'class': 'label' }).text(function (d) { |
|
return d.name; |
|
}); |
|
|
|
g.filter(function (d) { |
|
return d.numberOfOutputs > 0; |
|
}).append('rect').attr({ x: nodeWidth - pointSize / 2, y: nodeHeight / 2 - pointSize / 2, width: pointSize, height: pointSize, 'class': 'output' }); |
|
|
|
g.filter(function (d) { |
|
return d.numberOfInputs > 0; |
|
}).append('rect').attr({ x: -pointSize / 2, y: nodeHeight / 2 - pointSize / 2, width: pointSize, height: pointSize, 'class': 'input' }); |
|
|
|
gd.exit().remove(); |
|
|
|
// line 描画 |
|
var ld = lineGroup.selectAll('path').data(AudioNode_.audioConnections); |
|
|
|
ld.enter().append('path'); |
|
ld.each(function (d) { |
|
var path = d3.select(this); |
|
var x1, y1, x2, y2; |
|
|
|
// x1,y1 |
|
if (d.from instanceof AudioNode_) { |
|
x1 = d.from.x + nodeWidth / 2; |
|
y1 = d.from.y; |
|
} |
|
|
|
if (d.to instanceof AudioNode_) { |
|
x2 = d.to.x - nodeWidth / 2; |
|
y2 = d.to.y; |
|
} else { |
|
if (d.to.param instanceof AudioParam_) { |
|
x2 = d.to.node.x + d.to.param.x - nodeWidth / 2; |
|
y2 = d.to.node.y + d.to.param.y - nodeHeight / 2; |
|
} |
|
} |
|
var line = d3.svg.line().x(function (d) { |
|
return d.x; |
|
}).y(function (d) { |
|
return d.y; |
|
}).interpolate('basis'); |
|
|
|
var pos = [{ x: x1, y: y1 }, { x: x1 + (x2 - x1) / 4, y: y1 }, { x: x1 + (x2 - x1) / 2, y: y1 + (y2 - y1) / 2 }, { x: x1 + (x2 - x1) * 3 / 4, y: y2 }, { x: x2, y: y2 }]; |
|
path.attr({ 'd': line(pos), 'class': 'line' }); |
|
|
|
// |
|
// line.attr({ |
|
// x1: x1, |
|
// y1: y1, |
|
// x2: x2, |
|
// y2: y2, |
|
// 'class': 'line' |
|
// }); |
|
}); |
|
ld.exit().remove(); |
|
} |