tone.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /*
  2. The MIT License (MIT)
  3. Copyright (c) 2014-2020 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
  4. */
  5. // VWF & ToneJS model driver
  6. import { Fabric } from '/core/vwf/fabric.js';
  7. class ToneModel extends Fabric {
  8. constructor(module) {
  9. console.log("ToneModel constructor");
  10. super(module, "Model");
  11. }
  12. factory() {
  13. let _self_ = this;
  14. return this.load(this.module,
  15. {
  16. // == Module Definition ====================================================================
  17. // -- pipeline -----------------------------------------------------------------------------
  18. // pipeline: [ log ], // vwf <=> log <=> scene
  19. // -- initialize ---------------------------------------------------------------------------
  20. initialize: function () {
  21. var self = this;
  22. this.state = {
  23. nodes: {},
  24. scenes: {},
  25. prototypes: {},
  26. createLocalNode: function (nodeID, childID, childExtendsID, childImplementsIDs,
  27. childSource, childType, childIndex, childName, callback) {
  28. return {
  29. "parentID": nodeID,
  30. "ID": childID,
  31. "extendsID": childExtendsID,
  32. "implementsIDs": childImplementsIDs,
  33. "source": childSource,
  34. "type": childType,
  35. "name": childName,
  36. "prototypes": undefined
  37. };
  38. },
  39. isToneNodeComponent: function (prototypes) {
  40. var found = false;
  41. if (prototypes) {
  42. for (var i = 0; i < prototypes.length && !found; i++) {
  43. found = (prototypes[i] === "proxy/tonejs/node.vwf");
  44. }
  45. }
  46. return found;
  47. },
  48. isToneClass: function (prototypes, classID) {
  49. if (prototypes) {
  50. for (var i = 0; i < prototypes.length; i++) {
  51. if (prototypes[i] === classID) {
  52. //console.info( "prototypes[ i ]: " + prototypes[ i ] );
  53. return true;
  54. }
  55. }
  56. }
  57. return false;
  58. },
  59. isTransportDefinition: function (prototypes) {
  60. var found = false;
  61. if (prototypes) {
  62. for (var i = 0; i < prototypes.length && !found; i++) {
  63. found = (prototypes[i] == "proxy/tonejs/transport.vwf");
  64. }
  65. }
  66. return found;
  67. },
  68. isPlayerDefinition: function (prototypes) {
  69. var found = false;
  70. if (prototypes) {
  71. for (var i = 0; i < prototypes.length && !found; i++) {
  72. found = (prototypes[i] == "proxy/tonejs/player.vwf");
  73. }
  74. }
  75. return found;
  76. },
  77. isSynthDefinition: function (prototypes) {
  78. var found = false;
  79. if (prototypes) {
  80. for (var i = 0; i < prototypes.length && !found; i++) {
  81. found = (prototypes[i] == "proxy/tonejs/synth.vwf");
  82. }
  83. }
  84. return found;
  85. },
  86. isMembraneSynthDefinition: function (prototypes) {
  87. var found = false;
  88. if (prototypes) {
  89. for (var i = 0; i < prototypes.length && !found; i++) {
  90. found = (prototypes[i] == "proxy/tonejs/membraneSynth.vwf");
  91. }
  92. }
  93. return found;
  94. },
  95. isNoiseSynthDefinition: function (prototypes) {
  96. var found = false;
  97. if (prototypes) {
  98. for (var i = 0; i < prototypes.length && !found; i++) {
  99. found = (prototypes[i] == "proxy/tonejs/noiseSynth.vwf");
  100. }
  101. }
  102. return found;
  103. },
  104. createToneObject: function (node, config) {
  105. var protos = node.prototypes;
  106. var toneObj = undefined;
  107. if (this.isToneClass(protos, "proxy/tonejs/transport.vwf")) {
  108. // global transport for now
  109. toneObj = Tone.getTransport();
  110. }
  111. if (this.isToneClass(protos, "proxy/tonejs/player.vwf")) {
  112. toneObj = new Tone.Player(); //GrainPlayer
  113. toneObj.autostart = false;
  114. }
  115. if (this.isToneClass(protos, "proxy/tonejs/synth.vwf")) {
  116. toneObj = new Tone.PolySynth(Tone.synth);
  117. }
  118. if (this.isToneClass(protos, "proxy/tonejs/membraneSynth.vwf")) {
  119. toneObj = new Tone.PolySynth(Tone.MembraneSynth);
  120. // toneObj.set({
  121. // envelope: {
  122. // release: 0.1
  123. // }
  124. // });
  125. }
  126. if (this.isToneClass(protos, "proxy/tonejs/noiseSynth.vwf")) {
  127. toneObj = new Tone.NoiseSynth();
  128. }
  129. if (this.isToneClass(protos, "proxy/tonejs/pluckSynth.vwf")) {
  130. toneObj = new Tone.PolySynth(Tone.PluckSynth);
  131. }
  132. return toneObj
  133. }
  134. };
  135. this.state.kernel = this.kernel.kernel.kernel;
  136. //this.Tone = Tone;
  137. //this.state.kernel = this.kernel.kernel.kernel;
  138. },
  139. // == Model API ============================================================================
  140. // -- creatingNode -------------------------------------------------------------------------
  141. creatingNode: function (nodeID, childID, childExtendsID, childImplementsIDs,
  142. childSource, childType, childIndex, childName, callback /* ( ready ) */) {
  143. // If the parent nodeID is 0, this node is attached directly to the root and is therefore either
  144. // the scene or a prototype. In either of those cases, save the uri of the new node
  145. var childURI = (nodeID === 0 ? childIndex : undefined);
  146. var appID = this.kernel.application();
  147. // If the node being created is a prototype, construct it and add it to the array of prototypes,
  148. // and then return
  149. var prototypeID = _self_.utility.ifPrototypeGetId(appID, this.state.prototypes, nodeID, childID);
  150. if (prototypeID !== undefined) {
  151. this.state.prototypes[prototypeID] = {
  152. parentID: nodeID,
  153. ID: childID,
  154. extendsID: childExtendsID,
  155. implementsID: childImplementsIDs,
  156. source: childSource,
  157. type: childType,
  158. name: childName
  159. };
  160. return;
  161. }
  162. var protos = _self_.getPrototypes(this.kernel, childExtendsID);
  163. //var kernel = this.kernel.kernel.kernel;
  164. var node;
  165. if (this.state.isToneNodeComponent(protos)) {
  166. // Create the local copy of the node properties
  167. if (this.state.nodes[childID] === undefined) {
  168. this.state.nodes[childID] = this.state.createLocalNode(nodeID, childID, childExtendsID, childImplementsIDs,
  169. childSource, childType, childIndex, childName, callback);
  170. }
  171. node = this.state.nodes[childID];
  172. node.prototypes = protos;
  173. //this.state.createToneObject(node);
  174. let aframeDriver = vwf.views["/drivers/view/aframe"];
  175. if (aframeDriver) {
  176. let parentNode = aframeDriver.state.nodes[nodeID];
  177. if (parentNode.aframeObj) {
  178. let sceneEl = aframeDriver.state.nodes[nodeID].scene.sceneEl;
  179. if (!sceneEl.audioListener) {
  180. sceneEl.audioListener = new THREE.AudioListener();
  181. sceneEl.camera && sceneEl.camera.add(sceneEl.audioListener);
  182. // sceneEl.addEventListener('camera-set-active', function (evt) {
  183. // evt.detail.cameraEl.getObject3D('camera').add(sceneEl.audioListener);
  184. // });
  185. //this.gainNode = new Tone.Gain(0).toDestination();
  186. Tone.setContext(sceneEl.audioListener.context);
  187. }
  188. node.sound = new THREE.PositionalAudio(sceneEl.audioListener);
  189. //Tone.setContext(node.sound.context);
  190. //node.sound.context.resume();
  191. node.toneObj = this.state.createToneObject(node);
  192. //node.toneObj.connect(this.gainNode);
  193. if (!this.state.isTransportDefinition(node.prototypes)) {
  194. node.sound.setNodeSource(node.toneObj);
  195. parentNode.aframeObj.object3D.add(node.sound);
  196. }
  197. }
  198. } else {
  199. node.toneObj = this.state.createToneObject(node);
  200. if (!this.state.isTransportDefinition(node.prototypes)) {
  201. node.toneObj.toDestination();
  202. }
  203. //node.sound.setNodeSource(node.toneObj);
  204. }
  205. //addNodeToHierarchy(node);
  206. //notifyDriverOfPrototypeAndBehaviorProps();
  207. }
  208. },
  209. // -- initializingNode -------------------------------------------------------------------------
  210. // initializingNode: function( nodeID, childID, childExtendsID, childImplementsIDs,
  211. // childSource, childType, childIndex, childName ) {
  212. // },
  213. // -- deletingNode -------------------------------------------------------------------------
  214. //deletingNode: function( nodeID ) {
  215. //},
  216. // -- initializingProperty -----------------------------------------------------------------
  217. initializingProperty: function (nodeID, propertyName, propertyValue) {
  218. var value = undefined;
  219. var node = this.state.nodes[nodeID];
  220. if (node !== undefined) {
  221. value = this.settingProperty(nodeID, propertyName, propertyValue);
  222. }
  223. return value;
  224. },
  225. // -- creatingProperty ---------------------------------------------------------------------
  226. creatingProperty: function (nodeID, propertyName, propertyValue) {
  227. return this.initializingProperty(nodeID, propertyName, propertyValue);
  228. },
  229. // -- settingProperty ----------------------------------------------------------------------
  230. settingProperty: function (nodeID, propertyName, propertyValue) {
  231. let self = this;
  232. let node = this.state.nodes[nodeID];
  233. var value = undefined;
  234. if (node && node.toneObj && _self_.utility.validObject(propertyValue)) {
  235. let toneObject = node.toneObj;
  236. // if (self.state.isComponentNodeDefinition(node.prototypes)) {
  237. // value = propertyValue;
  238. // switch (propertyName) {
  239. // default:
  240. // value = undefined;
  241. // break;
  242. // }
  243. // }
  244. if (value === undefined && self.state.isTransportDefinition(node.prototypes)) {
  245. value = propertyValue;
  246. switch (propertyName) {
  247. case "bpm":
  248. toneObject.bpm.value = propertyValue
  249. toneObject.initbpm = propertyValue
  250. break;
  251. // case "state":
  252. // toneObject.state = propertyValue
  253. // break;
  254. case "position":
  255. toneObject.position = propertyValue
  256. break;
  257. case "loop":
  258. toneObject.loop = propertyValue
  259. break;
  260. case "loopStart":
  261. if (typeof propertyValue == "string") {
  262. propertyValue = Tone.Time(propertyValue).toSeconds();
  263. }
  264. toneObject.loopStart = propertyValue
  265. break;
  266. case "loopEnd":
  267. if (typeof propertyValue == "string") {
  268. propertyValue = Tone.Time(propertyValue).toSeconds();
  269. }
  270. toneObject.loopEnd = propertyValue
  271. break;
  272. case "duration":
  273. if (typeof propertyValue == "string") {
  274. propertyValue = Tone.Time(propertyValue).toSeconds();
  275. }
  276. toneObject.duration = propertyValue
  277. break;
  278. default:
  279. value = undefined;
  280. break;
  281. }
  282. }
  283. if (value === undefined && self.state.isPlayerDefinition(node.prototypes)) {
  284. value = propertyValue;
  285. switch (propertyName) {
  286. // case "url":
  287. // toneObject.load(propertyValue)
  288. // break;
  289. // case "state":
  290. // toneObject.state = propertyValue
  291. // break;
  292. case "startTime":
  293. toneObject.startTime = propertyValue
  294. break;
  295. case "volume":
  296. toneObject.volume.value = propertyValue
  297. break;
  298. case "mute":
  299. toneObject.mute = propertyValue
  300. break;
  301. case "autostart":
  302. toneObject.autostart = propertyValue
  303. break;
  304. case "loop":
  305. toneObject.loop = propertyValue
  306. break;
  307. case "loopStart":
  308. toneObject.loopStart = propertyValue
  309. break;
  310. case "loopEnd":
  311. toneObject.loopEnd = propertyValue
  312. break;
  313. // case "duration":
  314. // toneObject.duration = propertyValue
  315. // break;
  316. default:
  317. value = undefined;
  318. break;
  319. }
  320. }
  321. if (value === undefined && self.state.isSynthDefinition(node.prototypes)) {
  322. value = propertyValue;
  323. switch (propertyName) {
  324. case "type":
  325. toneObject.set({ oscillator: { type: propertyValue } })
  326. //"sine"; "square"; "triangle"; "sawtooth";
  327. break;
  328. default:
  329. value = undefined;
  330. break;
  331. }
  332. }
  333. }
  334. return value;
  335. },
  336. // -- gettingProperty ----------------------------------------------------------------------
  337. gettingProperty: function (nodeID, propertyName, propertyValue) {
  338. let self = this;
  339. let node = this.state.nodes[nodeID];
  340. let value = undefined;
  341. if (node && node.toneObj) {
  342. let toneObject = node.toneObj;
  343. // if (self.state.isComponentNodeDefinition(node.prototypes)) {
  344. // switch (propertyName) {
  345. // }
  346. // }
  347. if (value === undefined && self.state.isTransportDefinition(node.prototypes)) {
  348. switch (propertyName) {
  349. case "bpm":
  350. value = toneObject.bpm.value
  351. break;
  352. // case "state":
  353. // value = toneObject.state
  354. // break;
  355. case "position":
  356. value = toneObject.position
  357. break;
  358. case "loopStart":
  359. value = toneObject.loopStart
  360. break;
  361. case "loopEnd":
  362. value = toneObject.loopEnd
  363. break;
  364. case "duration":
  365. value = toneObject.duration
  366. break;
  367. case "loop":
  368. value = toneObject.loop
  369. break;
  370. }
  371. }
  372. if (value === undefined && self.state.isPlayerDefinition(node.prototypes)) {
  373. switch (propertyName) {
  374. case "autostart":
  375. value = toneObject.autostart
  376. break;
  377. // case "state":
  378. // value = toneObject.state
  379. // break;
  380. case "startTime":
  381. value = toneObject.startTime
  382. break;
  383. case "volume":
  384. value = toneObject.volume.value
  385. break;
  386. case "mute":
  387. value = toneObject.mute
  388. break;
  389. case "loopStart":
  390. value = toneObject.loopStart
  391. break;
  392. case "loopEnd":
  393. value = toneObject.loopEnd
  394. break;
  395. case "duration":
  396. value = toneObject.buffer.duration
  397. break;
  398. case "loop":
  399. value = toneObject.loop
  400. break;
  401. }
  402. }
  403. if (value === undefined && self.state.isSynthDefinition(node.prototypes)) {
  404. switch (propertyName) {
  405. case "type":
  406. value = toneObject.options.oscillator.type
  407. break;
  408. }
  409. }
  410. }
  411. if (value !== undefined) {
  412. propertyValue = value;
  413. }
  414. return value;
  415. }
  416. });
  417. }
  418. getPrototypes(kernel, extendsID) {
  419. var prototypes = [];
  420. var id = extendsID;
  421. while (id !== undefined) {
  422. prototypes.push(id);
  423. id = kernel.prototype(id);
  424. }
  425. return prototypes;
  426. }
  427. }
  428. export {
  429. ToneModel as default
  430. }