MusicAlgorithm.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. var o0 = require('o0');
  2. var o0Project = require('o0Project');
  3. var o0CC = require('o0CC');
  4. var o0Game = require('o0Game');
  5. //var fft = require("fft");
  6. var jsfft = require("jsfft");
  7. //var webAudioAnalyser = require('web-audio-analyser');
  8. cc.Class({
  9. extends: cc.Component,
  10. properties: {
  11. canvas: {
  12. default: null,
  13. type: cc.Canvas
  14. },
  15. camera: {
  16. default: null,
  17. type: cc.Camera
  18. },
  19. UICamera: {
  20. default: null,
  21. type: cc.Camera
  22. },
  23. gameScene:null,
  24. menuNode:null,
  25. DeviceMs:1,
  26. map:null,
  27. mapHit:null,
  28. mapRadius: 200,
  29. chart:null,
  30. TestButton:[],
  31. Filter:null,
  32. LastTime:new Date().getTime(),
  33. audioSource:null,
  34. },
  35. // use this for initialization
  36. onLoad: function () {
  37. //cc.director.setAnimationInterval(1.0/30);
  38. //cc.game.setFrameRate(30);//模拟器不能正常显示
  39. var self = this;
  40. this.audioSource = this.node.getComponent(cc.AudioSource);
  41. //cc.resources.load("music/Pink ditong", cc.AudioClip, (err, clip)=>{
  42. cc.resources.load("music/Pink Pineapple - PPAP Pen Pineapple Apple Pen", cc.AudioClip, (err, clip)=>{
  43. if (err) {
  44. cc.error(`AudioClip load error : ${err}`);
  45. return;
  46. }
  47. self.audioSource.clip = clip;
  48. self.audioBuffer = this.audioSource.clip._audio;
  49. var channel = self.audioBuffer.getChannelData(0);
  50. self.audioChannel = [];
  51. for(var i in channel){
  52. self.audioChannel.push(channel[i]);
  53. }
  54. self.audioSource.play();
  55. self.audioSource.pause();
  56. self.frequency = [];
  57. var halfFFTSize = 2048;
  58. for(var i = 0;i<self.audioChannel.length;i+=128){//step 采样率
  59. const data = new jsfft.ComplexArray(halfFFTSize).map((value, j, n) => {
  60. var v = self.audioChannel[i - halfFFTSize / 2 + j];
  61. value.real = v ? v : 0;
  62. });
  63. const frequencies = data.FFT();
  64. var mag = [];
  65. for(var j = 0;j<halfFFTSize;++j){
  66. mag.push(Math.sqrt(frequencies.real[j] * frequencies.real[j] + frequencies.imag[j] * frequencies.imag[j]));
  67. //mag.push(Math.abs(frequencies.imag[j]));
  68. }/** */
  69. self.frequency.push(mag);
  70. }
  71. console.log(self.frequency );
  72. var max = 0;
  73. for(var i = 0;i<self.frequency.length;++i){
  74. var freI = self.frequency[i];
  75. for(var j =0;j<freI.length;++j){
  76. max = Math.max(max,freI[j]);
  77. }
  78. }
  79. for(var i = 0;i<self.frequency.length;++i){
  80. var freI = self.frequency[i];
  81. for(var j =0;j<freI.length;++j){
  82. freI[j] /= max;
  83. }
  84. }
  85. self.frequencyStacked = [];
  86. for(var i = 0;i<self.frequency.length;++i){
  87. var freI = self.frequency[i];
  88. var v = 0;
  89. for(var j =0;j<freI.length && j<100;++j){
  90. v += freI[j] * Math.pow(10,(50-j));
  91. }
  92. self.frequencyStacked.push(v);
  93. }
  94. max = 0;
  95. for(var i = 0;i<self.frequencyStacked.length;++i){
  96. max = Math.max(max,self.frequencyStacked[i]);
  97. }
  98. for(var i = 0;i<self.frequencyStacked.length;++i){
  99. self.frequencyStacked[i] /= max;
  100. }
  101. /*
  102. var testArray = [];
  103. const data2 = new jsfft.ComplexArray(512).map((value, i, n) => {
  104. testArray.push(i);
  105. testArray.push(n);
  106. testArray.push((i > n/3 && i < 2*n/3) ? 1 : 0);
  107. });
  108. console.log(testArray);
  109. const data = new jsfft.ComplexArray(512).map((value, i, n) => {
  110. value.real = (i > n/3 && i < 2*n/3) ? 1 : 0;
  111. });
  112. const frequencies = data.FFT();
  113. console.log(data);
  114. console.log(frequencies);/** */
  115. console.log("o0o0o0o0o0o0o0o0o0o0o0o0o0 audioContext");
  116. console.log(self.audioSource.clip);
  117. if(false && (window.OfflineAudioContext || window.webkitOfflineAudioContext)){
  118. const {length, numberOfChannels, sampleRate} = self.audioBuffer;
  119. const OfflineContext = (window.OfflineAudioContext || window.webkitOfflineAudioContext);
  120. const context = new OfflineContext(numberOfChannels, length, sampleRate);
  121. const source = context.createBufferSource();
  122. source.buffer = self.audioBuffer;
  123. self.audioChannel = source.buffer.getChannelData(0);
  124. console.log(source.buffer.getChannelData(0));
  125. var channel = source.buffer.getChannelData(0);
  126. var max = 0;
  127. var min = 1;
  128. for(var i in channel){
  129. max = Math.max(channel[i],max);
  130. min = Math.min(channel[i],min);
  131. }
  132. console.log(max);
  133. console.log(min);
  134. //console.log(channel.min());
  135. }
  136. if(false && (window.OfflineAudioContext || window.webkitOfflineAudioContext)){
  137. const {length, numberOfChannels, sampleRate} = self.audioBuffer;
  138. var audioContext = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(numberOfChannels, length, sampleRate);
  139. var audioBufferSourceNode = audioContext.createBufferSource();
  140. audioBufferSourceNode.buffer = self.audioSource.clip._audio;
  141. var webAudioAnalyser = webAudioAnalyser(audioBufferSourceNode);
  142. //self.audioChannel = audioBufferSourceNode.buffer.getChannelData(0);
  143. var analyser = audioContext.createAnalyser();
  144. //analyser.fftSize = 256;
  145. audioBufferSourceNode.connect(analyser);
  146. analyser.connect(audioContext.destination);
  147. audioBufferSourceNode.start(0);
  148. self.analyser = analyser;
  149. /** */
  150. //analyser.getByteTimeDomainData(dataArray);
  151. var dataArray = new Uint8Array(analyser.frequencyBinCount);
  152. analyser.getByteFrequencyData(dataArray);
  153. console.log("dataArray");
  154. console.log(dataArray);
  155. /*
  156. for(var i in dataArray){
  157. console.log(dataArray[i]);
  158. }/** */
  159. }
  160. if(false && (window.AudioContext || window.webkitAudioContext)){
  161. const {length, numberOfChannels, sampleRate} = self.audioBuffer;
  162. //var audioContext = new (window.OfflineAudioContext || window.webkitOfflineAudioContext)(numberOfChannels, length, sampleRate);
  163. var audioContext = new (window.AudioContext || window.webkitAudioContext)();
  164. var audioBufferSourceNode = audioContext.createBufferSource();
  165. audioBufferSourceNode.buffer = self.audioSource.clip._audio;
  166. self.audioContext = audioContext;
  167. //self.audioChannel = audioBufferSourceNode.buffer.getChannelData(0);
  168. var analyser = audioContext.createAnalyser();
  169. analyser.fftSize = 256;
  170. audioBufferSourceNode.connect(analyser);
  171. analyser.connect(audioContext.destination);
  172. //audioBufferSourceNode.suspend();
  173. audioBufferSourceNode.start(0,40,20);
  174. //audioContext.startRendering();
  175. self.webAudioSource = audioBufferSourceNode;
  176. self.analyser = analyser;
  177. /** */
  178. //audioContext.currentTime = 10;
  179. //analyser.getByteTimeDomainData(dataArray);
  180. var dataArray = new Uint8Array(analyser.frequencyBinCount);
  181. analyser.getByteFrequencyData(dataArray);
  182. console.log("dataArray");
  183. console.log(audioContext.currentTime);
  184. console.log(dataArray);
  185. /*
  186. for(var i in dataArray){
  187. console.log(dataArray[i]);
  188. }/** */
  189. }
  190. });
  191. //
  192. /*
  193. return getTopCandidate(
  194. groupByTempo(buffer.sampleRate)(
  195. identifyIntervals(
  196. findPeaks(
  197. source.buffer.getChannelData(0)
  198. )
  199. )
  200. )
  201. );/** */
  202. /*
  203. //var file = this.files[0];
  204. var fr = new FileReader();
  205. fr.onload = function(e){
  206. audioCtx.decodeAudioData(e.target.result,function(buffer){
  207. console.log(buffer);
  208. for(var i in buffer){
  209. console.log(i);
  210. }
  211. //playFun(buffer); // 解码后返回的AudioBuffer对象作为播放函数的参数传入
  212. },function(err){
  213. console.log(err);
  214. })
  215. }
  216. fr.readAsArrayBuffer(this.audioSource.clip._audio);/** */
  217. //cc.director.getPhysicsManager().enabled = true;
  218. //this.cocos.node.x;
  219. //node.parent = this.canvas.node;
  220. //this.label.node.parent = node;
  221. //this.label.node.x = 0;
  222. //this.label.node.y = 0;
  223. //this.label.string = this.text;
  224. //var Snake = require("Snake");
  225. //cc.log("oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo "+Snake);
  226. /*var snake = new cc.Node('snake');
  227. snake.parent = this.camera.node;
  228. snake.addComponent('Snake');/** */
  229. //newSnake(this.camera.node);
  230. this.menuNode = new cc.Node();
  231. this.node.addChild(this.menuNode,1);
  232. this.map = o0CC.addScriptNode(this.node,'cc.Graphics',10);
  233. this.mapHit = o0CC.addScriptNode(this.node,'cc.Graphics',10);
  234. this.chart = o0CC.addScriptNode(this.node,'cc.Graphics',10);
  235. var col = 3;
  236. for(var i = 0;i<col;++i){
  237. this.TestButton.push([]);
  238. for(var j = 0;j<2;++j){
  239. var testButton = o0CC.addScriptNode(this.menuNode,'o0CCButton',11);
  240. o0CC.setGroup(testButton,o0Game.GroupIndex.UI);
  241. testButton.node.x = (i-(col-1)/2)*this.canvas.node.width/col;
  242. testButton.node.y = this.canvas.node.height/2 - 20 - j * 40;
  243. testButton.node.width = this.canvas.node.width/col;
  244. testButton.node.height = 40;/** */
  245. testButton.name = "null";
  246. this.TestButton[i].push(testButton);
  247. }
  248. }
  249. this.TestButton[1][0].name = "resume";
  250. this.TestButton[1][0].o0ClickEvent.push(function () {
  251. if(self.TestButton[1][0].name == "play"){
  252. self.TestButton[1][0].name = "pause";
  253. self.audioSource.play();
  254. //self.audioSource.resume();
  255. }else if(self.TestButton[1][0].name == "resume"){
  256. self.TestButton[1][0].name = "pause";
  257. //self.audioSource.play();
  258. self.audioSource.resume();
  259. }else{
  260. self.TestButton[1][0].name = "resume";
  261. //self.audioSource.stop();
  262. self.audioSource.pause();
  263. }
  264. });
  265. /*
  266. this.dragLabel = o0CC.addScriptNode(this.menuNode,'o0CCLabel',11);
  267. o0CC.setGroup(this.dragLabel,o0Game.GroupIndex.UI);
  268. this.dragLabel.node.x = 0;
  269. this.dragLabel.node.y = 0;
  270. this.dragLabel.node.width = this.canvas.node.width/2;
  271. this.dragLabel.node.height = this.canvas.node.height/2;/** */
  272. self.dragRate = 0;
  273. self.mouseLocation = new o0.Vector2(0,0);
  274. var listener = {
  275. event: cc.EventListener.MOUSE,
  276. onMouseDown: function (event) {
  277. self.mouseLocation = event.getLocation();
  278. if(self.mouseLocation.y > 1000)
  279. return;
  280. self.dragRate = 0.005;
  281. //console.log("onMouseDown");
  282. },
  283. onMouseUp: function (event) {
  284. self.mouseLocation = event.getLocation();
  285. self.dragRate = 0;
  286. //console.log("onMouseUp");
  287. //self.setTargetSpeeding(false);
  288. },
  289. onMouseMove: function (event) {
  290. //console.log("onMouseMove");
  291. if(self.audioSource != undefined && self.dragRate != 0){
  292. var newMouseLocation = event.getLocation();
  293. self.audioSource.setCurrentTime(self.audioSource.getCurrentTime() + (newMouseLocation.x - self.mouseLocation.x) * self.dragRate );
  294. //self.webAudioSource.setCurrentTime(self.webAudioSource.currentTime + (newMouseLocation.x - self.mouseLocation.x) * self.dragRate);
  295. self.mouseLocation = newMouseLocation;
  296. console.log(self.audioChannel);
  297. }
  298. },
  299. onMouseScroll: function (event) {
  300. }
  301. }
  302. cc.eventManager.addListener(listener, this.node);
  303. //cc.EventTarget.addListener(listener, this.node);
  304. /*
  305. this.gameScene = o0CC.addScriptNode(this.node,'GameScene',0);
  306. this.gameScene.canvas = this.canvas;
  307. this.gameScene.camera = this.camera;/** */
  308. this.backgroundGraphic = this.menuNode.addComponent(cc.Graphics,0);
  309. o0CC.setGroup(this.backgroundGraphic,o0Game.GroupIndex.UI);
  310. cc.director.getScheduler().setTimeScale(50);
  311. this.Filter = new o0Project.Filter();
  312. console.log("init finished");
  313. },
  314. onDeviceMotionEvent (event) {
  315. let newTime = new Date().getTime();
  316. var [acc,forceChanged,momentum] = this.Filter.Update(new o0.Vector3(event.acc),newTime - this.LastTime,new o0.Vector3(0,0,0));
  317. this.LastTime = newTime;
  318. },
  319. // called every frame
  320. update: function (dt) {
  321. var self = this;
  322. if(self.audioContext){
  323. console.log(self.audioContext.currentTime);
  324. }
  325. if(false && this.analyser != undefined){
  326. var dataArray = new Uint8Array(this.analyser.frequencyBinCount);
  327. this.analyser.getByteFrequencyData(dataArray);
  328. for(var i in dataArray){
  329. if(dataArray[i] != 0){
  330. if(this.logCount == undefined){
  331. this.logCount = 10;
  332. }else if(this.logCount > 0){
  333. this.logCount--;
  334. console.log(dataArray);
  335. }
  336. break;
  337. }
  338. }
  339. }
  340. this.chart.node.x = -this.canvas.node.width/2;
  341. this.chart.node.y = -this.canvas.node.height/2;
  342. if(this.audioChannel){
  343. this.audioChannelScaledLength = this.canvas.node.width - 20;
  344. if(this.audioChannelScaled == undefined || this.audioChannelScaled.length != this.audioChannelScaledLength){
  345. this.audioChannelScaled = [];
  346. var step = Math.ceil(this.audioChannel.length / this.audioChannelScaledLength);
  347. var k = 0;
  348. for(var i=0;i<this.audioChannelScaledLength;++i){
  349. var max = 0;
  350. var min = 0;
  351. for(var j=0;j<step;++j){
  352. var v;
  353. if(k >= this.audioChannel.length){
  354. break;
  355. }else{
  356. v = this.audioChannel[k];
  357. }
  358. max = Math.max(max,v);
  359. min = Math.min(min,v);
  360. ++k;
  361. }
  362. this.audioChannelScaled.push([min,max]);
  363. }
  364. //console.log(this.audioChannelScaled);
  365. }
  366. }
  367. this.chart.clear();
  368. if(this.audioChannelScaled){
  369. this.chart.strokeColor = new cc.Color(255,0,0,255);
  370. this.chart.moveTo(this.canvas.node.width/2, 0);
  371. this.chart.lineTo(this.canvas.node.width/2, 1000);
  372. this.chart.stroke();/** */
  373. var halfaudioChannelScaledLength = this.audioChannelScaled.length/2;
  374. var frequencyStackedDrawFrame = Math.floor(this.audioSource.getCurrentTime() / this.audioSource.getDuration() * this.frequencyStacked.length - halfaudioChannelScaledLength);
  375. for(var i = 0;i< this.audioChannelScaled.length;i++){
  376. var iFrequency = self.frequencyStacked[i+frequencyStackedDrawFrame];
  377. if(iFrequency == undefined){
  378. continue;
  379. }
  380. this.chart.strokeColor = new cc.Color(255,255,255,255);
  381. this.chart.moveTo(i+10, 750);
  382. this.chart.lineTo(i+10, 750 + iFrequency * 100);
  383. this.chart.stroke();
  384. }
  385. this.chart.lineWidth = 3;
  386. var frequencyDrawStep = 50;
  387. var frequencyStartDrawFrame = Math.floor(this.audioSource.getCurrentTime() / this.audioSource.getDuration() * this.frequency.length - halfaudioChannelScaledLength/frequencyDrawStep);
  388. for(var i = 0;i< this.audioChannelScaled.length/frequencyDrawStep;i++){
  389. var iFrequency = self.frequency[i+frequencyStartDrawFrame];
  390. if(iFrequency == undefined){
  391. continue;
  392. }
  393. for(var j = 0;j<iFrequency.length && j<100;++j){
  394. var color = iFrequency[j] * 255;
  395. this.chart.strokeColor = new cc.Color(color,color,color,255);
  396. this.chart.moveTo(i * frequencyDrawStep +10, 500 + j*2);
  397. this.chart.lineTo((i+1) * frequencyDrawStep +10, 500 + j*2);
  398. this.chart.stroke();
  399. }/** */
  400. }
  401. this.chart.lineWidth = 2;
  402. this.chart.strokeColor = new cc.Color(255,255,255,255);
  403. var currentFrame = Math.floor(this.audioSource.getCurrentTime() / this.audioSource.getDuration() * this.audioChannel.length);
  404. for(var i = 0;i< halfaudioChannelScaledLength;++i){
  405. this.chart.moveTo(-i+10 + halfaudioChannelScaledLength, 350);
  406. this.chart.lineTo(-i+10 + halfaudioChannelScaledLength, 350 + this.audioChannel[currentFrame-i] * 100);
  407. this.chart.stroke();
  408. this.chart.moveTo(i+10 + halfaudioChannelScaledLength, 350);
  409. this.chart.lineTo(i+10 + halfaudioChannelScaledLength, 350 + this.audioChannel[currentFrame+i] * 100);
  410. this.chart.stroke();
  411. }
  412. for(var i =0;i< this.audioChannelScaled.length;++i){
  413. this.chart.moveTo(i+10, 100);
  414. this.chart.lineTo(i+10, 100 + this.audioChannelScaled[i][0] * 100);
  415. this.chart.stroke();
  416. this.chart.moveTo(i+10, 100);
  417. this.chart.lineTo(i+10, 100 + this.audioChannelScaled[i][1] * 100);
  418. this.chart.stroke();
  419. }
  420. this.chart.strokeColor = new cc.Color(255,0,0,255);
  421. this.chart.moveTo(10, 100);
  422. this.chart.lineTo(10+this.audioChannelScaled.length, 100);
  423. this.chart.stroke();
  424. this.chart.moveTo(10, 499);
  425. this.chart.lineTo(10+this.audioChannelScaled.length, 495);
  426. this.chart.stroke();
  427. //console.log(this.audioSource.getCurrentTime());
  428. var seekX = this.audioSource.getCurrentTime() / this.audioSource.getDuration() * this.audioChannelScaled.length;
  429. this.chart.moveTo(10 + seekX, 0);
  430. this.chart.lineTo(10 + seekX, 200);
  431. this.chart.stroke();/** */
  432. }
  433. this.TestButton[0][0].name = "power";
  434. for(var i = this.Filter.frame.length-1;i>=0;--i){
  435. var io = this.Filter.frame[i];
  436. if(io.hit != 0){
  437. this.TestButton[0][1].name = io.hit;
  438. break;
  439. }
  440. }
  441. /*
  442. this.TestButton[1][12].name = this.Filter.angle;
  443. this.TestButton[3][12].name = this.Filter.punchCount;
  444. this.TestButton[2][12].name = this.Filter.leftRight;
  445. for(var i =0;i<this.TestButton.length;++i){
  446. for(var j =10;j>=0;--j){
  447. this.TestButton[i][j+1].name = this.TestButton[i][j].name;
  448. this.TestButton[i][j+1].button.normalColor = this.TestButton[i][j].button.normalColor;
  449. }
  450. }/* */
  451. }
  452. });