1var app = angular.module('nb-mtrack', []) 2.directive('mtmeter', function() { 3 return { 4 restrict: 'AE', 5 scope: { src: '@', 6 }, 7 template: '<div><canvas style="width:150px;height:48px; background-color:#ca3; border-radius:5px;" ></canvas></div>', 8 link: function(scope, element, attrs) { 9console.log(" METER DIRECTIVE") ; 10 scope.canvas = element.find('canvas')[0]; 11 scope.context = scope.canvas.getContext('2d'); 12 scope.canvas.width = scope.canvas.clientWidth; 13 scope.canvas.height = scope.canvas.clientHeight; 14 15 scope.$watch('src', function(newValue) { 16 let c = scope.canvas; 17 let f = newValue; 18 19 var ctx = c.getContext("2d"); 20 let wid = c.width; 21 let hei = c.height; 22 ctx.width = wid; 23 ctx.hei = hei; 24 ctx.beginPath(); 25 ctx.rect(0, 0, wid, hei); 26 ctx.fillStyle = "#222"; 27 ctx.fill(); 28 29 ctx.beginPath(); 30 ctx.rect(0, 0, f * wid, hei); 31 ctx.fillStyle = "#090"; 32 ctx.fill(); 33/* 34 scope.context.fillStyle = '#000'; 35 scope.context.fillRect(0, 0, scope.canvas.width, scope.canvas.height); 36 scope.context.fillStyle = "#0A0"; 37 var y1 = 10; 38 var hei = 12; 39 var y3 = scope.canvas.height / 2;; 40 var y2 = scope.canvas.height - 10; 41 var x = newValue / 100 * (scope.canvas.width - 20); 42 scope.context.fillRect(5, y1, x, hei); 43 scope.context.fillRect(5, y1 + hei + 5, x, hei); 44 scope.context.lineStyle = "#000"; 45 for( var ii = 0; ii < 20; ii++) { 46 var x = 5 + (scope.canvas.width / 20 * ii); 47 scope.context.beginPath(); 48 scope.context.moveTo(x, 0); 49 scope.context.lineTo(x, scope.canvas.height); 50 scope.context.stroke(); 51 } 52*/ 53 54 55 //console.log("SRC CHANGED " + newValue); 56 }); 57 58 59 60 61 } 62 }; 63 }) 64.directive('mt_meter', function() { 65 return { 66 restrict: 'E', 67 replace: 'true', 68 scope: { 69 level:'@' 70 }, 71 template:"<div>Text Text<canvas></canvas></div>", 72 controller: function( scope ) { 73 }, 74 link: function(scope, element, attrs) { 75 scope.$watch('level', function(val) { 76 }); 77 } 78 79 } 80}) 81.directive('mt_timeline', function() { 82 return { 83 scope: { 84 level:"@level" 85 }, 86 template:"<canvas></canvas>", 87 controller: function( scope ) { 88 } 89 } 90}) 91.directive('mtrack', function() { 92 return { 93 controller: "nb-mtrack", 94 templateUrl: "template-mtrack.html" 95 }; 96}) 97.controller('nb-mtrack', function( $scope, $http, $sce, $window, $location) { 98 $scope.mtrack_mixer = {}; 99 $scope.mtrack_audio = {}; 100 $scope.mtrack_group = function() 101 { 102 if (!$scope.user.groups) return(0); 103 return ($scope.user.groups.includes("mtrack")); 104 105 } 106 //////////////////////////// RADIO 107 $scope.mtrack_radio_queue = []; 108 $scope.mtrack_radio_ready_queue = []; 109 $scope.mtrack_radio_context = null; 110 $scope.mtrack_radio_model = {}; 111 112 // Called from Player Radio Entry 113 $scope.mtrack_radio = function( s) 114 { 115 $scope.user_menu_select_bytag("mtrack", "radio"); 116 console.log("Radio playing is currently set to " + $scope.mtrack_radio_playing); 117 118 if ($scope.mtrack_radio_playing) { 119 $scope.mtrack_radio_stop(); 120 } 121 122 $scope.mtrack_radio_server = s; 123 $scope.mtrack_radio_play(); 124/* 125 $scope.socket.emit('radio', { 126 server: s 127 }); 128 $scope.mtrack_radio_playing = true; 129*/ 130 131 } 132 $scope.mtrack_radio_play = function() { 133 if ($scope.mtrack_radio_context == null) { 134 $scope.mtrack_radio_context = new AudioContext(); 135 } 136 $scope.mtrack_radio_playing = 1; 137 $scope.mtrack_radio_playing_ready = 0; 138 $scope.mtrack_radio_model.play_time = 0; 139 $scope.mtrack_radio_timer_obj = setInterval($scope.mtrack_radio_time, 100); 140 //$scope.mtrack_radio_time(); 141 $scope.radio_play_time = $scope.mtrack_radio_context.currentTime; 142 $scope.socket.emit('radio', { 143 server: $scope.mtrack_radio_server 144 }); 145 } 146 147 // 148 // Radio Idle Time 149 // 150 // 151 $scope.mtrack_radio_time = function() { 152/* 153 var nothing_to_do = 0; 154 155 if ($scope.mtrack_radio_queue.length == 0) nothing_to_do = 1; 156 if ($scope.mtrack_radio_ready_queue.length) { 157 } 158 if (nothing_to_do) { 159 return; 160 } 161*/ 162 163//console.log("RADIO _TIME " + $scope.mtrack_radio_queue.length + " " + $scope.mtrack_radio_ready_queue.length); 164// 165 let BUFFER_SECONDS = 60; 166 let anow = $scope.mtrack_radio_context.currentTime; 167 if ($scope.radio_play_time - anow < BUFFER_SECONDS) { 168 if ($scope.mtrack_radio_queue.length) { 169 // Main Radio Pull Queue 170 var idata = $scope.mtrack_radio_queue[0]; 171 $scope.mtrack_radio_queue.splice(0,1); 172 $scope.mtrack_radio_load(idata); 173 } 174 } 175 if (!$scope.mtrack_radio_playing_ready) { 176 if ($scope.mtrack_radio_ready_queue.length > 2) { 177 $scope.mtrack_radio_playing_ready = 1; 178 } 179 180 } 181 if ($scope.mtrack_radio_playing_ready) { 182 183 // Main Pull a ready interval 184 if ($scope.mtrack_radio_ready_queue.length) { 185 186 var pdata = $scope.mtrack_radio_ready_queue[0]; 187 $scope.mtrack_radio_ready_queue.splice(0,1); 188 $scope.mtrack_radio_model_and_play(pdata); 189 190 } 191 $scope.mtrack_radio_level_time(); 192 } 193 $scope.$apply(); 194 //console.log("READY TO PLAY"); 195 //console.log(idata); 196 197 } 198 199 200 var myLevelCalc = function(meter) { 201 var freqData = new Uint8Array(meter.frequencyBinCount); 202 meter.getByteFrequencyData(freqData); 203 204 // Put the raw frequency into the newly created array 205 var max = 0; 206 var offset = 0; 207 for (var i = 0; i < freqData.length - offset; i+=8) { 208 if (i == 0) { 209 max = freqData[i + offset]; 210 } 211 if (freqData[i + offset] > max) max = freqData[i + offset]; 212 }
213 var f = max / 255.; 214 if (f > 1) f = 1.; 215 return(f); 216 } 217 218 $scope.mtrack_radio_level_change = function(track) { 219 var f = track.gainval; 220 track.gain.value = f; 221 222 } 223 $scope.mtrack_radio_level_time = function() { 224 var model = $scope.mtrack_radio_model; 225 if (!model.tracks) return; 226 for(var ii = 0; ii < model.tracks.length;ii++) { 227 var val = myLevelCalc(model.tracks[ii].meter); 228 model.tracks[ii].levels = val; 229 } 230 231 } 232 233 // 234 // Radio all stop 235 $scope.mtrack_radio_all_off = function() { 236 console.log("All Off"); 237 var model = $scope.mtrack_radio_model; 238 if (!model || !model.tracks) return; 239 for (t = 0; t < model.tracks.length; t++) { 240 for (s = 0; s < model.tracks[t].sources.length; s++) { 241 console.log("Buffer source stop " + t + " " + s); 242 model.tracks[t].sources[s].buffer.stop(); 243 model.tracks[t].sources[s].buffer.disconnect( model.tracks[t].gain); 244 } 245 //scope.mtrack_audio.audioSource[i][k].disconnect($scope.mtrack_audio.audioGain[i]); 246 //$scope.mtrack_audio.audioSource[i][k].stop(0); 247 //scope.mtrack_audio.audioSource[i][k].disconnect($scope.mtrack_audio.audioGain[i]); 248 //m.pan.disconnect($scope.mtrack_radio_context.destination); 249 } 250 251 } 252 253 // 254 // Radio Render to Webaudio 255 // 256 // 257 $scope.mtrack_radio_model_track = function(item, play_time) { 258 var model = $scope.mtrack_radio_model; 259 var m = null; 260 261 console.log(model); 262 console.log(model.tracks); 263 console.log(model.tracks.length); 264 265 for (t = 0; t < model.tracks.length; t++) { 266 if(model.tracks[t].username == item.username && model.tracks[t].chan == item.chan) { 267 console.log("FOUND TRACK " + item.username + " " + item.chan); 268 m = model.tracks[t]; 269 } 270 } 271 if (m == null) { 272 console.log("CREATING TRACK " + item.username + " " + item.chan); 273 m = {}; 274 if ($scope.mtrack_radio_context == null) { 275 $scope.mtrack_radio_context = new AudioContext(); 276 } 277 m.chan = item.chan; 278 m.username = item.username; 279 280 m.gain = $scope.mtrack_radio_context.createGain(); 281 m.pan = $scope.mtrack_radio_context.createPanner(); 282 var x = 0; 283 var y = 0; 284 var z = 3.; 285 m.pan.panningModel = 'equalpower'; 286 m.pan.setPosition(0, 0, 0); 287 288 m.meter = $scope.mtrack_radio_context.createAnalyser(); 289 m.meter.smoothingTimeConstant = 0.3; 290 m.meter.fftSize = 128; 291 m.gain.connect(m.pan); 292 m.pan.connect($scope.mtrack_radio_context.destination); 293 m.gain.connect(m.meter); 294 model.tracks.push(m); 295 } 296 var buff = $scope.mtrack_radio_context.createBufferSource(); 297 buff.connect(m.gain); 298 buff.buffer = item.buffer; 299 buff.start(play_time); 300 m.buffer_source = buff; 301 if (!m.sources) { 302 m.sources = []; 303 } 304 let dur = 60 /item.bpm * item.bpi; 305 m.sources.push( { buffer:buff, start:play_time, dur:dur }); 306/* 307 m.source = []; 308 m.source[0] = $scope.mtrack_context.createBufferSource(); 309 m.source[0].connect(m.gain); 310 m.source[1] = $scope.mtrack_context.createBufferSource(); 311 m.audio.source[1].connect(m.gain); 312*/ 313 314 }; 315 // Radio Model and Play - Final 316 $scope.radio_play_time = 0; 317 $scope.mtrack_radio_model_and_play = function(idata) { 318 //$scope.mtrack_radio_model = null; 319 var m = $scope.mtrack_radio_model; 320 if (m == null) { 321 console.log("*************************** MODEL IS NULL"); 322 m = {}; 323 $scope.mtrack_radio_model = m; 324 } 325 //console.log("PLAYING TIME WAS " + m.play_time); 326 if (!m.play_time) { 327 m.play_time = 0; 328 } 329 //var id = idata. 330 m.interval = idata.interval; 331 m.bpi = idata.bpi; 332 m.bpm = idata.bpm; 333 m.server = idata.server; 334 console.log("PLAY 1"); 335 console.log(idata); 336 var dur = 60.0 / idata.bpm * idata.bpi; 337 338 if (m.tracks == null) { 339 m.tracks = []; 340 } 341 //console.log("PLAYING TIME " + m.play_time + " Dur is " + dur); 342 //console.log("PLAYING TIME " + $scope.radio_play_time + " Dur is " + dur + " Track=" + idata.list.length); 343 for(var ii = 0 ;ii < idata.list.length;ii++) { 344 var t; 345 //$scope.mtrack_radio_model_track(idata.list[ii], m.play_time); 346 $scope.mtrack_radio_model_track(idata.list[ii], $scope.radio_play_time); 347 } 348 m.play_time += dur; 349 $scope.radio_play_time += dur; 350 $scope.$apply(); 351 } 352 $scope.mtrack_radio_load = function(idata) { 353 idata.waiting = idata.list.length; 354 for(var ii =0; ii < idata.list.length;ii++) { 355 $scope.mtrack_radio_load_track(idata, idata.list[ii], function( track ) 356 { 357 idata.waiting --; 358 if (idata.waiting == 0) { 359 console.log("OMG WE HAVE ALL THE BUFFERS"); 360 $scope.mtrack_radio_ready_queue.push(idata); 361 362 } 363 }); 364 } 365 } 366 $scope.mtrack_read = function(buff, callback) { 367 var s = $scope.mtrack_song; 368 var url = "/mtrack?s=" + s + "&afile=" + buff.fname; 369console.log(url); 370 var request = new XMLHttpRequest(); 371 request.open('GET', url, true); 372 request.responseType = 'arraybuffer'; 373 request.onload = function() { 374 375 $scope.mtrack_context.decodeAudioData(request.response, function(buffer) { 376 console.log("YES"); 377 buff.buffer = buffer; 378 buff.status = "loaded"; 379 if (callback) { 380 callback(null, buff); 381 } 382 }, function(err) { 383 console.log("BAD error " + err); 384 if (callback) { 385 callback(err, buff); 386 } 387 }); 388 } 389 request.send(); 390 } 391 $scope.mtrack_radio_load_track = function(idata, track, cb) { 392 console.log("LOAD TRACK"); 393 console.log(idata); 394 console.log(track); 395 if ($scope.mtrack_radio_context == null) $scope.mtrack_radio_context = new AudioContext(); 396 var url = "/mradio?session=" + idata.session +"&server=" +idata.server + "&fname=" + track.fname; 397 if (track.arg4.indexOf("Video") > -1) { 398 console.log("ITS VIDEO"); 399 url = "/mradio?session=" + idata.session +"&video=1&server=" +idata.server + "&fname=" + track.fname; 400 track.isvideo = 1; 401 } ; 402 403 404 405 var request = new XMLHttpRequest(); 406 request.open('GET', url, true); 407 request.responseType = 'arraybuffer'; 408 request.onload = function() { 409 $scope.mtrack_radio_context.decodeAudioData(request.response, function(buffer) { 410 track.buffer = buffer; 411 if (cb) cb(track); 412 }); 413 } 414 request.send(); 415/* 416console.log(url); 417 $http( 418 { url: url, 419 method:"GET" 420 }).then(function(res) { 421 console.log("Success len = " + res.data.length); 422 var data = res.data; 423 $scope.mtrack_radio_context.decodeAudioData(data, function(buffer) { 424 console.log("Decoded Audio"); 425 //buff.buffer = buffer; 426 track.buffer = buffer; 427 if (cb) cb(track); 428 429 }) 430 431 }, function(err) { 432 track.error = err; 433 if (cb) cb(track); 434 }); 435*/ 436 437/* 438 439 if (res.data.error ) { 440 track.error = res.data.error; 441 if (cb) cb(track); 442 } else { 443 track.buffer = res.data; 444 if (cb) cb(track); 445 } 446 }, function(err) { 447 track.error = err; 448 if (cb) cb(track); 449 }); 450*/ 451 452 453 454 455 456 } 457 $scope.mtrack_radio_stop = function() { 458 $scope.socket.emit('radio', { 459 server: $scope.mtrack_radio_server, 460 cmd: "unsub" 461 }); 462 //$scope.mtrack_radio_stop(); 463 464 $scope.mtrack_radio_playing = 0; 465 $scope.mtrack_radio_all_off(); 466 467 clearInterval($scope.mtrack_radio_timer_obj); 468 } 469 var lastInterval = 0; 470 $scope.socket.on('interval', function(msg){ 471/* 472 if ($scope.mtrack_radio_playing == 0 ) { 473 return; 474 } 475*/ 476 console.log("Interval Event Received " + msg.interval + " channels " + msg.list.length); 477 console.log(msg); 478/* 479 if (msg.interval == lastInterval) { 480 console.log("Dup Event Received"); 481 } else { 482 $scope.mtrack_radio_queue.push(msg); 483 } 484*/ 485 486 $scope.mtrack_radio_queue.push(msg); 487 488 // Keep the queue Small 489 /* 490 if ($scope.mtrack_radio_queue.length > 2) { 491 console.log("I spliced the quue length now " + $scope.mtrack_radio_queue.length); 492 $scope.mtrack_radio_queue.splice(0,1); 493 } 494*/ 495 lastInterval = msg.interval; 496/* 497 if ($scope.mtrack_radio_queue.length > 3) { 498 console.log("Dropping interval " + $scope.mtrack_radio_queue[0].interval); 499 $scope.mtrack_radio_queue.splice(0,1); 500 } 501*/ 502 $scope.$apply(); 503 }); 504 505 $scope.mtrack_edit_radio = function( s) 506 { 507 //$scope.mtrack_radio(s); 508 $scope.mtrack_edit_song(s); 509 510 }
511 //////////////////////////// END RADIO 512 // 513 // 514 // 515 // Entry point for mtrack edit 516 // 517 // 518 // Main Timeline Reader Recalc Rebuild Reader Loader Master Facilitator 519 // 520 // 521 // 522 $scope.mtrack_edit_song = function( s) 523 { 524 $scope.user_menu_select_bytag("mtrack", "edit"); 525 if ($scope.mtrack_song == s) { 526 return; 527 } 528 if (s && s.indexOf(":") != -1) { 529 $scope.isradio = 1; 530 } else { 531 $scope.isradio = 0; 532 533 } 534 535 if ($scope.mtrack_playing) { 536 $scope.mtrack_play_pause(); 537 } 538 $scope.mtrack_song = s; 539 $http( {method:"GET", 540 url:"/mtrack?s=" + s 541 }).then(function(res) { 542 543 if (res.data.error ) { 544 console.log(res.data.error); 545 $scope.mtrack = null; 546 $scope.mtrack_timeline_rebuild(); 547 } else { 548 console.log("MTRACK RETURNED "); 549 console.log(res.data); 550 $scope.mtrack = res.data; 551 $scope.mtrack_timeline_rebuild(); 552 } 553 }, function(err) { 554 $scope.mtrack = null; 555 $scope.mtrack_timeline_rebuild(); 556 }); 557 558 } 559 let last_radio_update = 0; 560 $scope.mtrack_radio_update = function( ) 561 { 562 var ss = new Date().getTime(); 563 if (ss - last_radio_update < 30000) { 564 return(0); 565 } 566 last_radio_update = ss; 567 console.log("radio update called"); 568 console.log($scope.mtrack[$scope.mtrack.length -1]); 569 var last_session = $scope.mtrack[$scope.mtrack.length -1].session; 570 var last_interval = $scope.mtrack[$scope.mtrack.length -1].interval; 571 572 //$scope.user_menu_select_bytag("mtrack", "edit"); 573 var s = $scope.mtrack_song; 574 $http( {method:"GET", 575 url:"/mtrack?s=" + s 576 }).then(function(res) { 577 578 if (res.data.error ) { 579 console.log(res.data.error); 580 // $scope.mtrack = null; 581// $scope.mtrack_timeline_rebuild(); 582 } else { 583 console.log("MTRACK RETURNED "); 584 console.log(res.data); 585 let cnt = 0; 586 var mtrack_new = res.data; 587 for (var ii = 0 ; ii < mtrack_new.length; ii++) { 588 if (mtrack_new[ii].session != last_session || mtrack_new[ii].interval > last_interval) { 589 $scope.mtrack.push(mtrack_new[ii]); 590 cnt++; 591 } 592 } 593 console.log("Added " + cnt + " intervals"); 594 $scope.mtrack_timeline_radio_rebuild($scope.mtrack.length -cnt) ; 595 //console.log("New is " + new_session + " " + new_interval); 596 597 598 //$scope.mtrack_timeline_rebuild(); 599 } 600 }, function(err) { 601 //$scope.mtrack = null; 602 //$scope.mtrack_timeline_rebuild(); 603 }); 604 605 606 } 607 // 608 // Son of Main Timeline Recalc Rebuild Reader Loader Master Facilitator 609 // Takes mtrack and build tracklist 610 // 611 $scope.mtrack_timeline_radio_rebuild = function(start) 612 { 613console.log("MTRACK REBUILD " + start + " " + $scope.mtrack.length); 614 //var tracklist = $scope.tracklist; 615 var dur = $scope.mtrack_duration; 616 for (var ii = start; ii < $scope.mtrack.length; ii++) { 617 interval = $scope.mtrack[ii]; 618console.log(interval); 619 dur += (60 / interval.bpm * interval.bpi);
620 for(var utrack of interval.channels) { 621 var id = utrack.user + "-" + utrack.type + "-" + utrack.chan; 622 var fnd = 0; 623console.log("LOOKING FOR ID " + id); 624 for(var tt = 0; tt < $scope.tracklist.length; tt++) { 625 //for(var track of $scope.tracklist) { 626 if ($scope.tracklist[tt].id == id) { 627/* 628 for (var nn = $scope.tracklist[tt].last_interval ; nn < interval.interval;nn++ ) { 629 $scope.tracklist[tt].intervals.push({}); 630 } 631*/ 632console.log("PUSHING NEW INTERVAL"); 633console.log(utrack); 634 $scope.tracklist[tt].intervals.push(utrack); 635 fnd = 1; break; 636 break; 637 } 638 } 639 if (!fnd) { 640 var track = {}; 641 track.id = id; 642 track.type = utrack.type; 643 track.chan = utrack.chan; 644 track.user = utrack.user; 645 track.level = 0; 646 track.gain = 100; 647 track.pan = 0; 648 var ss = track.user.lastIndexOf("@"); 649 if (ss == -1) { 650 track.name = track.user; 651 track.ip = ""; 652 } else { 653 track.ip = track.user.substr(ss+1, track.user.length); 654 track.name = track.user.substr(0, ss); 655 } 656 //console.log(track); 657 track.intervals = []; 658 for (var nn =1 ; nn < interval.interval;nn++ ) { 659 track.intervals.push({}); 660 } 661 track.intervals.push(utrack); 662 track.last_interval = interval.interval;
663 track.uid = track_uid_cnt++; 664 $scope.mtrack_create_audio(track); 665 if (track.type == "audio") { 666 $scope.tracklist.push(track); 667 } else { 668 $scope.videolist.push(track); 669 } 670 } 671 672 } 673 674 } 675 console.log($scope.mtrack); 676 console.log($scope.tracklist); 677 $scope.mtrack_duration = dur; 678 679 680 } 681 var track_uid_cnt = 0; 682 $scope.mtrack_timeline_rebuild = function() 683 { 684console.log("TIMELINE REBUILD"); 685 let dur = 0; 686 //$scope.mtrack_audio_init(); 687 //console.log($scope.mtrack); 688 var tracklist = []; 689 var videolist = []; 690 track_uid_cnt = 0; 691 for(var interval of $scope.mtrack) { 692 dur += (60 / interval.bpm * interval.bpi); 693 for(var utrack of interval.channels) { 694 var id = utrack.user + "-" + utrack.type + "-" + utrack.chan; 695 var fnd = 0; 696 for(var track of tracklist) { 697 if (track.id == id) { 698 for (var nn =track.lst_interval ; nn < interval.interval;nn++ ) { 699 track.intervals.push({}); 700 } 701 track.intervals.push(utrack); 702 fnd = 1; break; 703 break; 704 } 705 } 706 if (!fnd) { 707 var track = {}; 708 track.id = id; 709 track.type = utrack.type; 710 track.chan = utrack.chan; 711 track.user = utrack.user; 712 track.level = 0; 713 track.gain = 100; 714 track.pan = 0; 715 var ss = track.user.lastIndexOf("@"); 716 if (ss == -1) { 717 track.name = track.user; 718 track.ip = ""; 719 } else { 720 track.ip = track.user.substr(ss+1, track.user.length); 721 track.name = track.user.substr(0, ss); 722 } 723 //console.log(track); 724 track.intervals = []; 725 for (var nn =1 ; nn < interval.interval;nn++ ) { 726 track.intervals.push({}); 727 } 728 track.intervals.push(utrack); 729 track.last_interval = interval.interval;
730 track.uid = track_uid_cnt++; 731 if (track.type == "audio") { 732 tracklist.push(track); 733 } else { 734 videolist.push(track); 735 } 736 } 737 738 } 739 $scope.mtrack_in = 0.0; 740 $scope.meta_in_trans = "none"; 741 $scope.meta_out_trans = "none"; 742 $scope.meta_share = "private"; 743 $scope.mtrack_out = dur; 744 $scope.metadata_lookup = $scope; 745 //console.log("Dur is " + dur); 746 } 747 $scope.mtrack_duration = dur; 748 $scope.mtrack_draw_timeline(); 749 $scope.tracklist = tracklist; 750 $scope.videolist = videolist; 751// $scope.tracklist.sort(); 752 753 $scope.tracklist.sort(function(a,b) { 754 if (a.id < b.id) return(-1); 755 if (a.id > b.id) return(1); 756 return(0); 757 }); 758 console.log($scope.tracklist); 759 760 $scope.mtrack_context = new AudioContext(); 761 // Wire up audio 762 for( var track of $scope.tracklist ) { 763 track.audio = {}; 764 track.audio.gain = $scope.mtrack_context.createGain(); 765 track.audio.pan = $scope.mtrack_context.createPanner(); 766 var x = 0; 767 var y = 0; 768 var z = 3.; 769 track.audio.pan.panningModel = 'equalpower'; 770 track.audio.pan.setPosition(0, 0, 0); 771 772 track.audio.meter = $scope.mtrack_context.createAnalyser(); 773 track.audio.meter.smoothingTimeConstant = 0.3; 774 track.audio.meter.fftSize = 128; 775/* 776 $scope.mtrack_audio.audioSource[i] = new Array(numSource); 777 $scope.mtrack_audio.audioLoaded[i] = new Array(numSource); 778 $scope.mtrack_audio.audioBuffer[i] = new Array(numSource); 779 780*/ 781 track.audio.gain.connect(track.audio.pan); 782 track.audio.pan.connect($scope.mtrack_context.destination); 783 track.audio.gain.connect(track.audio.meter); 784 785 track.audio.source = []; 786 track.audio.source[0] = $scope.mtrack_context.createBufferSource(); 787 track.audio.source[0].connect(track.audio.gain); 788 track.audio.source[1] = $scope.mtrack_context.createBufferSource(); 789 track.audio.source[1].connect(track.audio.gain); 790 track.audio.source[2] = $scope.mtrack_context.createBufferSource(); 791 track.audio.source[2].connect(track.audio.gain); 792 track.audio.source[3] = $scope.mtrack_context.createBufferSource(); 793 track.audio.source[3].connect(track.audio.gain); 794/* 795 for (var i = 0; i < appMixer.data.length; i++) { 796 if (appMixer.audioLoaded[i][appMixer.mixer.readBuffer] == 9) { 797 // console.log("Playing track " + i + " at time " + appMixer.playTime); 798 appMixer.audioSource[i][appMixer.mixer.readBuffer] = appMixer.audioContext.createBufferSource(); 799 appMixer.audioSource[i][appMixer.mixer.readBuffer].buffer = appMixer.audioBuffer[i][appMixer.mixer.readBuffer]; 800 intervalSize = appMixer.audioBuffer[i][appMixer.mixer.readBuffer].duration; 801 appMixer.audioSource[i][appMixer.mixer.readBuffer].loop = appMixer.loopMode; 802 appMixer.audioSource[i][appMixer.mixer.readBuffer].connect(appMixer.audioGain[i]); 803 //appMixer.audioSource[i][appMixer.mixer.readBuffer].noteOn(appMixer.playTime); 804 appMixer.audioSource[i][appMixer.mixer.readBuffer].start(appMixer.playTime); 805 } else { 806 // console.log("Skipping track " + i); 807 } 808 } 809*/ 810 811 } 812 813 setTimeout( function() { 814 $scope.mtrack_draw_timeline(); 815 }, 1000); 816 $scope.mtrack_ready(); 817 } 818 $scope.mtrack_create_audio = function(track) 819 { 820 track.audio = {}; 821 track.audio.gain = $scope.mtrack_context.createGain(); 822 track.audio.pan = $scope.mtrack_context.createPanner(); 823 var x = 0; 824 var y = 0; 825 var z = 3.; 826 track.audio.pan.panningModel = 'equalpower'; 827 track.audio.pan.setPosition(0, 0, 0); 828 829 track.audio.meter = $scope.mtrack_context.createAnalyser(); 830 track.audio.meter.smoothingTimeConstant = 0.3; 831 track.audio.meter.fftSize = 128; 832/* 833 $scope.mtrack_audio.audioSource[i] = new Array(numSource); 834 $scope.mtrack_audio.audioLoaded[i] = new Array(numSource); 835 $scope.mtrack_audio.audioBuffer[i] = new Array(numSource); 836 837*/ 838 track.audio.gain.connect(track.audio.pan); 839 track.audio.pan.connect($scope.mtrack_context.destination); 840 track.audio.gain.connect(track.audio.meter); 841 842 track.audio.source = []; 843 track.audio.source[0] = $scope.mtrack_context.createBufferSource(); 844 track.audio.source[0].connect(track.audio.gain); 845 track.audio.source[1] = $scope.mtrack_context.createBufferSource(); 846 track.audio.source[1].connect(track.audio.gain); 847 track.audio.source[2] = $scope.mtrack_context.createBufferSource(); 848 track.audio.source[2].connect(track.audio.gain); 849 track.audio.source[3] = $scope.mtrack_context.createBufferSource(); 850 track.audio.source[3].connect(track.audio.gain); 851 852 853 } 854 855 856 857 // 858 // Main Mtrack Param render 859 // 860 // 861 $scope.mtrack_audio_remix = function() { 862 let is_solo = 0; 863 console.log("Audio Remix"); 864 for(var tt = 0; tt < $scope.tracklist.length; tt++) { 865 if ($scope.tracklist[tt].solo) { 866 is_solo = 1; 867 break; 868 } 869 } 870 if (is_solo) {
871 for(var tt = 0; tt < $scope.tracklist.length; tt++) { 872 g = 0; 873 if ($scope.tracklist[tt].solo) { 874 g = 1; 875 } 876 if ($scope.tracklist[tt].mute) { 877 g = 0; 878 } 879 g *= ($scope.tracklist[tt].gain / 100); 880 console.log("TTSOLO " + tt + " " + g); 881 $scope.tracklist[tt].audio.gain.gain.value = g; 882 } 883 } else { 884 for(var tt = 0; tt < $scope.tracklist.length; tt++) { 885 g = 1; 886 if ($scope.tracklist[tt].mute) { 887 g = 0; 888 } 889 g *= ($scope.tracklist[tt].gain / 100); 890 console.log("TT " + tt + " " + g); 891 $scope.tracklist[tt].audio.gain.gain.value = g; 892 } 893 } 894 895 } 896 var can = document.getElementById("mtrack_seek"); 897 898 // 899 // mounse down in seek canvas 900 // 901 can.onmousedown = function(e) { 902 var rect = can.getBoundingClientRect(); 903 //var wid= can.width; 904 var wid= can.offsetWidth; 905 906 var p = (e.x - rect.left) / wid; 907 //console.log("wid is + " + can.width + " wid = " + wid + " got e.x = " + e.x + " rect.left is " +rect.left + " = " + (e.x - rect.left) + " Pp = " + p); 908//can.width; 909//200; 910 var ct = $scope.mtrack_duration * p; 911 $scope.mtrack_seek(ct); 912 //$location.search("time", $scope.audio.currentTime ); 913 914 915 }; 916 $scope.mtrack_seek = function( time ) { 917 let was_playing = 0; 918 if ($scope.mtrack_playing) { 919 was_playing = 1; 920 $scope.mtrack_play_pause(); 921 } 922 $scope.mtrack_play_time_currentTime = time; 923 $scope.mtrack_play_current_time = time; 924 if (was_playing) { 925 $scope.mtrack_play_pause(); 926 } 927/* 928 $scope.mtrack_play_pause(); 929 } 930*/ 931 $scope.mtrack_seek_update(); 932 $scope.mtrack_draw_timeline(); 933 $scope.$apply(); 934 console.log("MTRACK SEEK " + time); 935 } 936 $scope.mtrack_seek_update = function( ) { 937 var c = document.getElementById("mtrack_seek"); 938 var ctx = c.getContext("2d"); 939 var wid= c.width; 940 ctx.fillStyle = "#333"; 941 ctx.fillRect(0, 0, wid, 150); 942 ctx.fillStyle = "#36b"; 943 //$scope.mtrack_play_current_time = sofar; 944 ctx.fillRect(0, 0, wid * ($scope.mtrack_play_current_time / $scope.mtrack_duration), 150); 945 946 } 947 948 var drawit = function(c, start, stop) { 949 //console.log("Drawit " + start +" " + stop); 950 951 var wid = c.width; 952 var ctx = c.getContext("2d"); 953 var x1 = wid * (start / $scope.mtrack_duration); 954 var x2 = wid * (stop / $scope.mtrack_duration); 955 ctx.fillStyle = "#222"; 956 ctx.fillRect(0, 0, wid, 150); 957 ctx.fillStyle = "#522"; 958 ctx.fillRect(x1, 0, x2-x1, 150); 959 //ctx.fillStyle = "#36b"; 960 //$scope.mtrack_play_current_time = sofar; 961 //ctx.fillRect(0, 0, wid * ($scope.mtrack_play_current_time / $scope.mtrack_duration), 150); 962 } 963 964 965 mtrack_timeline_canvas_mouse = function(can, e) { 966 var rect = can.getBoundingClientRect(); 967 //var wid= can.width; 968 var wid= can.offsetWidth; 969 970 var p = (e.x - rect.left) / wid; 971 //console.log("wid is + " + can.width + " wid = " + wid + " got e.x = " + e.x + " rect.left is " +rect.left + " = " + (e.x - rect.left) + " Pp = " + p); 972//can.width; 973//200; 974 var ct = $scope.mtrack_duration * p; 975 $scope.mtrack_seek(ct); 976 //$location.search("time", $scope.audio.currentTime ); 977 978 979 }; 980 $scope.mtrack_draw_timeline = function( ) { 981 if (!$scope.tracklist) return; 982 for (var tt= 0;tt <$scope.tracklist.length;tt++) { 983 var cname = "mtrack_timeline_" + $scope.tracklist[tt].uid; 984 //console.log("cname = " + cname); 985 var c = document.getElementById(cname); 986 //console.log("Element " + c.width + " " + c.clientWidth); 987 c.width = c.clientWidth; 988 //c.height = c.style.height; 989 //var lw = c.style.width / c.width *5; 990 var lw = 2; 991 c.onmousedown = function(e) { 992 mtrack_timeline_canvas_mouse(c, e); 993 } 994 var ctx = c.getContext("2d"); 995 var wid = c.width; 996 //console.log($scope.tracklist[tt].intervals); 997 let start = -1; 998 let stop = -1; 999 let t = 0; 1000//console.log($scope.mtrack); 1001 for (var ii= 0;ii <$scope.tracklist[tt].intervals.length;ii++) { 1002 if ($scope.tracklist[tt].intervals[ii].fname) { 1003 if (start == -1) { 1004 start = t; 1005 } 1006 stop = t; 1007 } else { 1008 if (start != -1) { 1009 stop = t; 1010 drawit(c, start, stop); 1011 } 1012 } 1013if ( !$scope.mtrack[ii] ) { 1014 //console.log("II = " + ii + " No MTRACK") ; 1015} else { 1016 t += (60/ $scope.mtrack[ii].bpm * $scope.mtrack[ii].bpi); 1017} 1018 //console.log("T now " + t); 1019
1020 } 1021 if (start != -1) { 1022 stop = t; 1023 drawit(c, start, stop); 1024 } 1025 ctx.beginPath(); 1026 //var xx = $scope.mtrack_play_current_time; 1027 var xx = wid * ($scope.mtrack_play_current_time / $scope.mtrack_duration); 1028 xx = Math.ceil(xx) + 1; 1029 ctx.moveTo(xx, 0); 1030 ctx.lineTo(xx, 150); 1031 ctx.lineWidth = lw; 1032 ctx.strokeStyle = '#009900'; 1033 ctx.stroke(); 1034 xx = wid * ($scope.mtrack_in / $scope.mtrack_duration); 1035 xx = Math.ceil(xx) + 1; 1036 ctx.moveTo(xx, 0); 1037 ctx.lineTo(xx, 150); 1038 ctx.strokeStyle = '#90a0a0'; 1039 ctx.stroke(); 1040 xx = wid * ($scope.mtrack_out / $scope.mtrack_duration); 1041 xx = Math.ceil(xx) + 1; 1042 ctx.moveTo(xx, 0); 1043 ctx.lineTo(xx, 150); 1044 ctx.strokeStyle = '#00a090'; 1045 ctx.stroke(); 1046 } 1047 } 1048 1049 // 1050 // Main Play Idle Time 1051 // 1052 let BUFFER_SECONDS = 12; 1053 $scope.mtrack_play_current_time = 0; 1054 $scope.mtrack_play_update_time = function() { 1055 let anow = $scope.mtrack_context.currentTime; 1056 let sofar = (anow - $scope.mtrack_play_time_startCurrentTime); 1057 sofar += $scope.mtrack_play_time_startTime; 1058 $scope.mtrack_play_current_time = sofar; 1059 $scope.mtrack_seek_update(); 1060// + $scope.mtrack_play_time_startTime; 1061//Need to know start time relative to context.currentTime 1062 //console.log("SOFAR " + sofar); 1063 $scope.$apply(); 1064 1065 let now = new Date().getTime(); 1066 now = now - $scope.mtrack_play_time; 1067 now /= 1000; 1068 //console.log("Its Play Update Time Sec=" + now); 1069 //console.log("Anow " + anow); 1070 //console.log("Buffer time is " + $scope.mtrack_play_buffer_time); 1071 if ( ($scope.mtrack_play_buffer_time - anow) <= BUFFER_SECONDS ) 1072 { 1073 let interval = $scope.mtrack_play_time_interval; 1074 console.log("Its time for a buffer " + interval); 1075 console.log("Its Play Update Time Sec=" + now); 1076 console.log("Buffer time is " + $scope.mtrack_play_buffer_time); 1077 //console.log( $scope.tracklist[0].intervals[interval]); 1078 let bbpi = $scope.mtrack[interval].bpi; 1079 let bbpm = $scope.mtrack[interval].bpm; 1080 //let bbpm = $scope.tracklist[0].intervals[interval].bpm; 1081 let bsec = 60/ bbpm * bbpi; 1082 $scope.mtrack_play_time_interval++; 1083 $scope.mtrack_play_buffer_time += bsec; 1084 let mytime = $scope.mtrack_play_buffer_time; 1085 let myinterval = interval; 1086 $scope.mtrack_queue_one( $scope.mtrack_play_time_interval, mytime, function(interval, sec) { 1087 console.log("PLAYING INTERVAL " + myinterval + " At " + sec + " Sec"); 1088 $scope.mtrack_play_interval(interval, sec); 1089 }); 1090/* 1091 $scope.mtrack_queue_one( $scope.mtrack_play_time_interval, function(interval) { 1092 // Ready for playback; 1093 console.log("Ready For playback " + interval); 1094 $scope.mtrack_play_interval(interval, 0); 1095 1096 1097 }); 1098*/ 1099 } 1100 1101 //$scope.mtrack_play_time = 0; 1102 //$scope.mtrack_play_time_interval = 0; 1103 //$scope.mtrack_play_time_next_time = 0; 1104 for(var tt = 0; tt < $scope.tracklist.length; tt++) { 1105 let f = myLevelCalc($scope.tracklist[tt].audio.meter); 1106 1107 //console.log("mtrack_meter_" + $scope.tracklist[tt].uid); 1108 let elem = document.getElementById("mtrack_meter_" + $scope.tracklist[tt].uid); 1109 var ctx = elem.getContext("2d"); 1110 1111 let wid = elem.width; 1112 let hei = elem.height; 1113 ctx.width = wid; 1114 ctx.hei = hei; 1115 ctx.beginPath(); 1116 ctx.rect(0, 0, wid, hei); 1117 ctx.fillStyle = "#222"; 1118 ctx.fill(); 1119 1120 ctx.beginPath(); 1121 ctx.rect(0, 0, f * wid, hei); 1122 ctx.fillStyle = "#090"; 1123 ctx.fill(); 1124 1125 1126 //let f = $scope.mtrack_levelCalc(tt); 1127 if (f != 0) { 1128 //console.log("LEVEL " + tt + " = " + f); 1129 } 1130 } 1131 $scope.mtrack_draw_timeline(); 1132 $scope.mtrack_radio_update(); 1133 } 1134 1135 $scope.mtrack_play_time = 0; 1136 $scope.mtrack_play_time_interval = 0; 1137 $scope.mtrack_play_time_next_time = 0; 1138 $scope.mtrack_play_buffer_time = 0; 1139 $scope.mtrack_play_time_startTime = 0; 1140 $scope.mtrack_play_time_currentTime = 0; 1141 1142 // 1143 // Main Play and Stop 1144 // 1145 // 1146 $scope.mtrack_play_pause = function() { 1147 1148 if ($scope.mtrack_playing) { 1149 $scope.mtrack_playing = 0; 1150 $scope.mtrack_play_time_currentTime = $scope.mtrack_context.currentTime + $scope.mtrack_play_time_startTime; 1151 $scope.mtrack_play_time_currentTime = $scope.mtrack_play_time_startTime + ($scope.mtrack_context.currentTime - $scope.mtrack_play_time_startCurrentTime);
1152 clearInterval( $scope.mtrack_play_interval_timer); 1153 console.log("Stopping sources"); 1154 for(var tt=0; tt< $scope.tracklist.length;tt++) { 1155 for(var bb=0; bb< $scope.tracklist[tt].audio.source.length;bb++) { 1156 try { 1157 $scope.tracklist[tt].audio.source[bb].stop(); 1158 } catch(err) { 1159 } 1160 } 1161 } 1162 } else { 1163 //$scope.mtrack_context.resume(); 1164 $scope.mtrack_play_time = new Date().getTime(); 1165 $scope.mtrack_play_interval_timer = setInterval(function() { 1166 //console.log("MrStickies Interval Timer Called"); 1167 $scope.mtrack_play_update_time(); 1168 }, 100); 1169 1170 $scope.mtrack_playing = 1; 1171 $scope.mtrack_play_buffer_time =0; 1172 //$scope.mtrack_animate(); 1173/* 1174 $scope.mtrack_audio.playFrom(0); 1175*/ 1176// $scope.mtrack_play_start(0); 1177// 1178//Need to know start time relative to context.currentTime 1179 1180 // startTime is clip time 1181 $scope.mtrack_play_time_startTime = $scope.mtrack_play_time_currentTime + 1; 1182 // startCurrnetTime is context time 1183 $scope.mtrack_play_time_startCurrentTime = $scope.mtrack_context.currentTime + 1; 1184 // buffer_time = context time 1185 $scope.mtrack_play_buffer_time = $scope.mtrack_play_time_startCurrentTime ; 1186 let start_time = $scope.mtrack_play_time_startTime; 1187 let ttime = 0; 1188 $scope.mtrack_play_time_interval = 0; 1189 for (var nn = 0; nn < $scope.mtrack.length;nn++ ) { 1190 let bbpi = $scope.mtrack[nn].bpi; 1191 let bbpm = $scope.mtrack[nn].bpm; 1192 let bsec = 60/ bbpm * bbpi; 1193 let res = ttime + bsec; 1194 if (res > start_time) { 1195 $scope.mtrack_play_time_interval = nn; 1196 break; 1197 } 1198 ttime += bsec; 1199 } 1200 $scope.mtrack_queue_one( $scope.mtrack_play_time_interval, $scope.mtrack_play_buffer_time, function(interval, sec) { 1201 // Ready for playback; 1202 console.log("Ready For playback " + interval); 1203 $scope.mtrack_play_interval(interval, sec); 1204 1205 1206 }); 1207 } 1208 //$scope.mtrack_playing = !$scope.mtrack_playing; 1209 } 1210/* 1211 $scope.mtrack_play_start = function(interval) { 1212 } 1213 1214 $scope.mtrack_play_time = function() { 1215 1216 while(playing) { 1217 $scope.mtrack_queue_one( interval, function(interval) { 1218 // Ready for playback; 1219 console.log("Ready For playback " + interval); 1220 $scope.mtrack_play_interval(interval, 0); 1221 } 1222 1223 1224 } 1225 1226*/ 1227 function unlockAudioContext(audioCtx) { 1228 if (audioCtx.state !== 'suspended') return; 1229 const b = document.body; 1230 const events = ['touchstart','touchend', 'mousedown','keydown']; 1231 events.forEach(e => b.addEventListener(e, unlock, false)); 1232 function unlock() { audioCtx.resume().then(clean); } 1233 function clean() { events.forEach(e => b.removeEventListener(e, unlock)); } 1234 } 1235 // 1236 // Main Interval Play Routine 1237 // 1238 // 1239 // 1240 $scope.mtrack_play_interval = function(interval, sec) 1241 { 1242 //var context = new AudioContext(); 1243 var context = new (window.AudioContext || window.webkitAudioContext)(); 1244 unlockAudioContext(context); 1245 1246 1247 //console.log("Playing interval " + window.performance.memory); 1248 console.log("======================== Playing interval at time " + sec); 1249 1250 1251 1252 for(var tt = 0; tt < $scope.tracklist.length; tt++) { 1253 if ($scope.tracklist[tt].intervals.length > interval) { 1254 if ($scope.tracklist[tt].intervals[interval].fname) { 1255 var buff = $scope.tracklist[tt].intervals[interval].buff.buffer; 1256 //console.log("Playing " + $scope.tracklist[tt].intervals[interval].buff.id); 1257 if (buff) { 1258 //var which = interval % 2; 1259 var which = interval % $scope.tracklist[tt].audio.source.length; 1260 1261// $scope.tracklist[tt].audio.source[which].stop(0); 1262 $scope.tracklist[tt].audio.source[which].disconnect($scope.tracklist[tt].audio.gain); 1263 $scope.tracklist[tt].audio.source[which] = null; 1264 1265 $scope.tracklist[tt].audio.source[which] = $scope.mtrack_context.createBufferSource(); 1266 $scope.tracklist[tt].audio.source[which].connect($scope.tracklist[tt].audio.gain); 1267/* 1268 let bbpi = $scope.tracklist[tt].intervals[interval].bpi; 1269 let bbpm = $scope.tracklist[tt].intervals[interval].bpm; 1270 let bsec = bbpm / 60 * bbpi; 1271 $scope.mtrack_play_buffer_time = sec + bsec; 1272*/ 1273 1274 var source = $scope.tracklist[tt].audio.source[which]; 1275 source.buffer = buff; 1276 1277console.log("=============== SOURCE START " + sec); 1278 source.start(sec); // play the source now 1279 /* 1280 source.buffer = buff; 1281 source.connect(context.destination); 1282 source.start(0); // play the source now 1283 */ 1284 } 1285 1286 }} 1287 } 1288 1289 1290 1291 } 1292$scope.mtrack_audio.updateAudio = function () 1293{ 1294 var solo = 0; 1295 1296 for(var i = 0; i < $scope.mtrack_audio.data.length; i++) { 1297 // If we have one solo turn them all off 1298 if ($scope.mtrack_audio.chanParamValues[i]['solo']) { 1299 if ($scope.mtrack_audio.chanParamValues[i]['solo'].val == 1) { 1300 solo ++; 1301 } 1302 } 1303 } 1304 1305//console.log("Solo is " + solo); 1306 1307 for(var i = 0; i < $scope.mtrack_audio.data.length; i++) { 1308 var panp = $scope.mtrack_audio.chanParamValues[i]['pan']; 1309 var gainp = $scope.mtrack_audio.chanParamValues[i]['gain']; 1310 var gain = 1.; 1311 if (gainp) { 1312 gain = gainp.val; 1313 gain = $scope.mtrack_audio.easeInQuad(gain, 0, 100., 100.) ; 1314 gain = gain / 100.; 1315 } 1316 if ($scope.mtrack_audio.chanParamValues[i]['mute']) { 1317 if ($scope.mtrack_audio.chanParamValues[i]['mute'].val) { 1318 gain = 0; 1319 } 1320 } 1321 1322 if (solo) { 1323 if (!$scope.mtrack_audio.chanParamValues[i]['solo']) { 1324 gain = 0; 1325 } else { 1326 if ($scope.mtrack_audio.chanParamValues[i]['solo'].val == 0) { 1327 gain = 0; 1328 } 1329 } 1330 } 1331 $scope.mtrack_audio.audioGain[i].gain.value = gain; 1332 1333 $scope.mtrack_audio.audioPan[i].setPosition( panp.val /100. , 0, 1 - Math.abs(panp.val / 100.)); 1334 1335 //$scope.mtrack_audio.audioPan[track].setPosition( ui.value , 0, 1 - Math.abs( ui.value));; 1336 //$scope.mtrack_audio.audioPan[i].panningModel = 'equalpower'; 1337 //$scope.mtrack_audio.audioPan[i].setPosition(0,0,0); 1338 } 1339 if ($scope.mtrack_audio.masterParams) { 1340 var gainp = $scope.mtrack_audio.masterParams['gain']; 1341 var gain = 1.; 1342 if (gainp) { 1343 gain = gainp.val; 1344 gain = $scope.mtrack_audio.easeInQuad(gain, 0, 100., 100.) ; 1345 gain /= 100.; 1346 } 1347 $scope.mtrack_audio.masterGain.gain.value = gain; 1348 1349 } 1350 1351} 1352 1353 1354 1355 1356 $scope.mtrack_current_pos = 1; 1357 $scope.mtrack_queue_interval = 1; 1358 $scope.mtrack_queue_chan = 0; 1359 $scope.mtrack_read = function(buff, callback) { 1360 var s = $scope.mtrack_song; 1361 var url = "/mtrack?s=" + s + "&afile=" + buff.fname; 1362 // url += "&mp3file=1"; 1363console.log(url); 1364 var request = new XMLHttpRequest(); 1365 request.open('GET', url, true); 1366 request.responseType = 'arraybuffer'; 1367 request.onload = function() { 1368 1369 $scope.mtrack_context.decodeAudioData(request.response, function(buffer) { 1370 //console.log("YES"); 1371 buff.buffer = buffer; 1372 buff.status = "loaded"; 1373 if (callback) { 1374 callback(null, buff); 1375 } 1376 }, function(err) { 1377 console.log("BAD error " + err); 1378 if (callback) { 1379 callback(err, buff); 1380 } 1381 }); 1382 } 1383 request.send(); 1384 } 1385 $scope.mtrack_read_no = function(buff, callback) { 1386 var s = $scope.mtrack_song; 1387 //console.log("Mtrack read " + JSON.stringify(buff)); 1388 1389 //console.log("MTRACK " + s); 1390 $http( {method:"GET", 1391 url:"/mtrack?s=" + s + "@afile=" + buff.fname 1392 }).then(function(res) { 1393 if (res.data.error ) { 1394 console.log(res.data.error); 1395 if (callback) { 1396 callback(res.data.error, buff); 1397 } 1398 } else {
1399 console.log("Success"); 1400 console.log("Success len = " + res.data.length); 1401 buff.data = res.data; 1402 res.arrayBuffer().then(function(buffer) { 1403 buff.data = buffer; 1404 1405 $scope.mtrack_context.decodeAudioData(buff.data, function(buffer) { 1406 console.log("Decoded Audio"); 1407 buff.buffer = buffer; 1408 if (callback) { 1409 callback(res.data.error, buff); 1410 } 1411 }, function(err) { 1412 console.log(err); 1413 if (callback) { 1414 callback(err, null); 1415 } 1416 }) ; 1417 }); 1418 //$scope.mtrack = JSON.parse(res.data); 1419 } 1420 }, function(err) { 1421 if (callback) { 1422 callback(err, buff); 1423 } 1424 console.log(err); 1425 }); 1426 1427 } 1428 $scope.mtrack_queue_one = function(interval,sec, cb) { 1429 var interval_waiting = 0; 1430 for(var tt = 0; tt < $scope.tracklist.length; tt++) { 1431 if ($scope.tracklist[tt].intervals.length > interval) { 1432 if ($scope.tracklist[tt].intervals[interval].fname && $scope.tracklist[tt].type == "audio") { 1433 console.log($scope.tracklist[tt].intervals[interval].fname); 1434 var buff; 1435 if ($scope.tracklist[tt].intervals[interval].buff ) { 1436 buff = $scope.tracklist[tt].intervals[interval].buff ; 1437 } else { 1438 $scope.tracklist[tt].intervals[interval].buff = {}; 1439 buff = $scope.tracklist[tt].intervals[interval].buff ; 1440 } 1441 buff.fname = $scope.tracklist[tt].intervals[interval].fname; 1442 buff.id = $scope.tracklist[tt].id; 1443 buff.interval = interval; 1444 buff.user = $scope.tracklist[tt].user; 1445 buff.status = "start"; 1446 $scope.tracklist[tt].intervals[interval].buff = buff; 1447 interval_waiting++; 1448 $scope.mtrack_read(buff, function(err, buff){ 1449 if (err) { 1450 buff.error = err; 1451 interval_waiting--; 1452 buff.status = "error"; 1453 } else { 1454 //console.log("Buffer read " + buff.id); 1455 buff.status = "ready" 1456 interval_waiting--; 1457 buff.error = null; 1458 } 1459 if (interval_waiting == 0) { 1460 //console.log("Interval complete " + buff.interval); 1461 if (cb) { 1462 cb(buff.interval, sec); 1463 } 1464 } 1465 }); 1466 //console.log(buff); 1467 } 1468 } 1469 } 1470 1471 } 1472 $scope.mtrack_queue = function(cb) { 1473 for(var ii = $scope.mtrack_current_pos; ii <= $scope.mtrack.length; ii++) { 1474 for(var tt = 0; tt < $scope.tracklist.length; tt++) { 1475 if ($scope.tracklist[tt].intervals.length > ii) { 1476 if ($scope.tracklist[tt].intervals[ii -1].fname) { 1477 console.log($scope.tracklist[tt].intervals[ii -1].fname); 1478 var buff = {}; 1479 buff.fname = $scope.tracklist[tt].intervals[ii -1].fname; 1480 buff.id = $scope.tracklist[tt].id; 1481 buff.interval = ii; 1482 buff.user = $scope.tracklist[tt].user; 1483 buff.status = "start"; 1484 $scope.mtrack_read(buff); 1485 1486 } 1487 } 1488 } 1489 1490 } 1491/* 1492 while(1) { 1493 var buffer = mtrack_pool_get_buffer(); 1494 1495 if (!buffer) break; 1496 1497 } 1498*/ 1499/* 1500 while(var buffer = $scope.mtrack_buffer_get()) { 1501 console.log("Got buffer"); 1502 } 1503 1504*/ 1505 1506 } 1507 $scope.mtrack_queue_next = function(cb) { 1508 } 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 $scope.mtrack_audio_init = function() { 1522/* 1523 console.log("Initing Audio"); 1524 if ($scope.mtrack_context) return; 1525 $scope.mtrack_context = new AudioContext(); 1526 $scope.mtrack_source1 = $scope.mtrack_context.createBufferSource(); 1527 $scope.mtrack_source1Gain = $scope.mtrack_context.createGain(); 1528*/ 1529 1530 } 1531 $scope.mtrack_audio.stop = function() 1532 { 1533 if (!$scope.mtrack_audio.isPlaying) return(0); 1534 1535 $scope.mtrack_audio.isPlaying = 0; 1536 $scope.mtrack_mixer.playPos = $scope.mtrack_mixer.playPosCurrent; 1537 for (var i = 0; i < $scope.mtrack_audio.data.length; i++) 1538 { 1539 for (var k = 0; k < $scope.mtrack_mixer.numIntervals; k++) { 1540 if ( $scope.mtrack_audio.audioSource[i] && $scope.mtrack_audio.audioSource[i][k]) { 1541 1542 // console.log("Stopping " + i + " interval " + k); 1543 //appMixer.audioSource[i][k].noteOff(0); 1544 $scope.mtrack_audio.audioSource[i][k].stop(0); 1545 $scope.mtrack_audio.audioSource[i][k].disconnect($scope.mtrack_audio.audioGain[i]); 1546 $scope.mtrack_audio.audioSource[i][k] = 0; 1547 } else { 1548 } 1549 } 1550 } 1551 1552 } 1553 $scope.mtrack_audio.playInitControls = function() 1554 { 1555 1556 1557// console.log("Creating context and everything"); 1558// $scope.mtrack_audio.audioContext = new webkitAudioContext(); 1559 $scope.mtrack_audio.audioContext = new AudioContext(); 1560 1561// console.log("SAMPLE RATE is " + $scope.mtrack_audio.audioContext.sampleRate); 1562 $scope.mtrack_audio.masterGain = $scope.mtrack_audio.audioContext.createGain(); 1563 $scope.mtrack_audio.masterGain.connect($scope.mtrack_audio.audioContext.destination); 1564 $scope.mtrack_audio.masterLevel = $scope.mtrack_audio.audioContext.createAnalyser(); 1565 $scope.mtrack_audio.masterLevel.smoothingTimeConstant = 0.3; 1566 $scope.mtrack_audio.masterLevel.fftSize = 128; 1567 $scope.mtrack_audio.masterGain.connect($scope.mtrack_audio.masterLevel); 1568 1569 for (var i = 0; i < $scope.mtrack_audio.data.length; i++) 1570 { 1571 var gain = $scope.mtrack_audio.audioContext.createGain(); 1572 $scope.mtrack_audio.audioGain[i] = gain; 1573
1574 var pan = $scope.mtrack_audio.audioContext.createPanner(); 1575 var x = (i / $scope.mtrack_audio.data.length) * 20 - (100); 1576 var x = 0; 1577 var y = 0; 1578 var z = 3.; 1579 pan.panningModel = 'equalpower'; 1580 pan.setPosition(0, 0, 0); 1581 $scope.mtrack_audio.audioPan[i] = pan; 1582 // pan.maxDistance = 100; 1583 1584 var meter = $scope.mtrack_audio.audioContext.createAnalyser(); 1585 $scope.mtrack_audio.audioMeter[i] = meter; 1586 meter.smoothingTimeConstant = 0.3; 1587 meter.fftSize = 128; 1588 1589 var numSource = 2; 1590 numSource = $scope.mtrack_mixer.numIntervals; 1591 $scope.mtrack_audio.audioSource[i] = new Array(numSource); 1592 $scope.mtrack_audio.audioLoaded[i] = new Array(numSource); 1593 $scope.mtrack_audio.audioBuffer[i] = new Array(numSource); 1594 for (var k = 0; k < numSource ; k++) { 1595 $scope.mtrack_audio.audioLoaded[i][k] = 0; 1596 } 1597 gain.connect(pan); 1598 if ($scope.mtrack_audio.masterGain) { 1599 pan.connect($scope.mtrack_audio.masterGain); 1600 } else { 1601 pan.connect($scope.mtrack_audio.audioContext.destination); 1602 } 1603 gain.connect(meter); 1604 } 1605/* 1606 $scope.mtrack_audio.stop(); 1607 $scope.mtrack_audio.updateAudio(); 1608 $scope.mtrack_audio.playStartPos = $scope.mtrack_audio.playPos; 1609 $scope.mtrack_audio.isPlaying = 1; 1610 $scope.mtrack_audio.isCue = 1; 1611 1612 $scope.mtrack_audio.loadInterval($scope.mtrack_mixer.readBuffer); 1613 $scope.mtrack_audio.playLoop(); 1614*/ 1615 1616 1617 } 1618 1619 $scope.mtrack_audio.playFrom = function(start) 1620 { 1621 $scope.mtrack_mixer.readBuffer = Math.floor($scope.mtrack_mixer.playPos); 1622 $scope.mtrack_mixer.playBuffer = Math.floor($scope.mtrack_mixer.playPos); 1623 // console.log("PlayFrom " + start + " Pos = " + $scope.mtrack_mixer.readBuffer); 1624 if ($scope.mtrack_audio.audioContext == 0) { 1625 1626 1627// console.log("Creating context and everything"); 1628// $scope.mtrack_audio.audioContext = new webkitAudioContext(); 1629 $scope.mtrack_audio.audioContext = new AudioContext(); 1630 1631// console.log("SAMPLE RATE is " + $scope.mtrack_audio.audioContext.sampleRate); 1632 $scope.mtrack_audio.masterGain = $scope.mtrack_audio.audioContext.createGain(); 1633 $scope.mtrack_audio.masterGain.connect($scope.mtrack_audio.audioContext.destination); 1634 $scope.mtrack_audio.masterLevel = $scope.mtrack_audio.audioContext.createAnalyser(); 1635 $scope.mtrack_audio.masterLevel.smoothingTimeConstant = 0.3; 1636 $scope.mtrack_audio.masterLevel.fftSize = 128; 1637 $scope.mtrack_audio.masterGain.connect($scope.mtrack_audio.masterLevel); 1638 1639 for (var i = 0; i < $scope.mtrack_audio.data.length; i++) 1640 { 1641 var gain = $scope.mtrack_audio.audioContext.createGain(); 1642 $scope.mtrack_audio.audioGain[i] = gain; 1643 1644 var pan = $scope.mtrack_audio.audioContext.createPanner(); 1645 var x = (i / $scope.mtrack_audio.data.length) * 20 - (100); 1646 var x = 0; 1647 var y = 0; 1648 var z = 3.; 1649 pan.panningModel = 'equalpower'; 1650 pan.setPosition(0, 0, 0); 1651 $scope.mtrack_audio.audioPan[i] = pan; 1652 // pan.maxDistance = 100; 1653 1654 var meter = $scope.mtrack_audio.audioContext.createAnalyser(); 1655 $scope.mtrack_audio.audioMeter[i] = meter; 1656 meter.smoothingTimeConstant = 0.3; 1657 meter.fftSize = 128; 1658 1659 var numSource = 2; 1660 numSource = $scope.mtrack_mixer.numIntervals; 1661 $scope.mtrack_audio.audioSource[i] = new Array(numSource); 1662 $scope.mtrack_audio.audioLoaded[i] = new Array(numSource); 1663 $scope.mtrack_audio.audioBuffer[i] = new Array(numSource); 1664 for (var k = 0; k < numSource ; k++) { 1665 $scope.mtrack_audio.audioLoaded[i][k] = 0; 1666 } 1667 gain.connect(pan); 1668 if ($scope.mtrack_audio.masterGain) { 1669 pan.connect($scope.mtrack_audio.masterGain); 1670 } else { 1671 pan.connect($scope.mtrack_audio.audioContext.destination); 1672 } 1673 gain.connect(meter); 1674 } 1675 } 1676 $scope.mtrack_audio.stop(); 1677 $scope.mtrack_audio.updateAudio(); 1678 $scope.mtrack_audio.playStartPos = $scope.mtrack_audio.playPos; 1679 $scope.mtrack_audio.isPlaying = 1; 1680 $scope.mtrack_audio.isCue = 1; 1681 1682 $scope.mtrack_audio.loadInterval($scope.mtrack_mixer.readBuffer); 1683 $scope.mtrack_audio.playLoop(); 1684 1685 } 1686/* 1687 $scope.mtrack_animate = function() { 1688console.log("Mtrack_animate");
1689 $scope.mtrack_update(); 1690 if ($scope.mtrack_playing) { 1691 requestAnimFrame($scope.mtrack_animate); 1692 } 1693 } 1694*/ 1695 1696 $scope.mtrack_update = function() { 1697 console.log("Mtrack Update called"); 1698 //var mlevel = $scope.mtrack_levelCalc('master'); 1699 //var mlevel = $scope.mtrack_levelCalc(0); 1700 //console.log("Master Level " + mlevel); 1701 } 1702 $scope.mtrack_levelCalc = function(which) { 1703 var freqdata; 1704 which = "master"; 1705 if (which == 'master') { 1706 freqData = new Uint8Array($scope.mtrack.masterLevel.frequencyBinCount); 1707 $scope.mtrack.masterLevel.getByteFrequencyData(freqData); 1708 } else { 1709 var meter = $scope.tracklist[which].audio.meter; 1710/* 1711 var meter = $scope.mtrack_audio.audioMeter[which]; 1712*/ 1713 freqData = new Uint8Array(meter.frequencyBinCount); 1714 meter.getByteFrequencyData(freqData); 1715 } 1716 // Put the raw frequency into the newly created array 1717 var max = 0; 1718 var offset = 0; 1719 for (var i = 0; i < freqData.length - offset; i+=8) { 1720 if (i == 0) { 1721 max = freqData[i + offset]; 1722 } 1723 if (freqData[i + offset] > max) max = freqData[i + offset]; 1724 } 1725 var f = max / 255.; 1726 if (f > 1) f = 1.; 1727 return(f); 1728 } 1729 1730 1731 $scope.mtrack_audio.play = function() 1732 { 1733 if ($scope.mtrack_audio.isPlaying) { 1734 $scope.mtrack_audio.stop(); 1735 } 1736 if (!$scope.mtrack_mixer.playPos) { 1737 $scope.mtrack_mixer.playPos = 0; 1738 } 1739 $scope.mtrack_audio.playFrom($scope.mtrack_mixer.playPos); 1740 $scope.mtrack_audio.animate(); 1741 } 1742 $scope.metadata = [ 1743 { name:"meta_title", desc:"Title" }, 1744 { name:"meta_desc", desc:"Description", type:"textarea" }, 1745 { name:"mtrack_in", desc:"In Point" }, 1746 { name:"mtrack_out", desc:"Out Point" }, 1747 { name:"meta_in_trans", desc:"In/Transition", type:"menu", menu:[{name:"none", desc:"None"}, {name:"linear-1", desc:"1 Second Linear"} ] }, 1748 { name:"meta_out_trans", desc:"Out/Transition", type:"menu", menu:[{name:"none", desc:"None"}, {name:"linear-1", desc:"1 Second Linear"} ] }, 1749 { name:"meta_share", desc:"Sharing", type:"menu", menu:[{name:"private", desc:"Private"}, {name:"unlisted", desc:"Unlisted"}, {name:"public", desc:"Public"} ] }, 1750/* 1751 { name:"meta_in_trans", desc:"out/Transition", menu:[{name:"none", desc:"None"}, {name:"linear-1", "1 Second Linear"} ] }, 1752 1753 { name:"meta_public", desc:"Public/Private", menu:[{name:"public", desc:"Public"}, {name:"private", "Private"} ] } 1754 1755*/ 1756 1757 ]; 1758 1759 $scope.mtrack_ready = function() { 1760 1761/* 1762 setTimeout(function() { 1763 1764 var query = $location.search(); 1765 if (query.time) { 1766 $scope.mtrack_seek(query.time); 1767 } 1768 }, 1000); 1769*/ 1770 1771 } 1772 $scope.mtrack_render = function() { 1773 var query = $location.search(); 1774 $scope.render = {}; 1775 let ss = query.track.lastIndexOf("."); 1776 $scope.render.song = query.track.substr(0, ss); 1777 let list = []; 1778 for (var ii =0; ii < $scope.tracklist.length;ii++) { 1779 let obj = {} 1780 obj.id = $scope.tracklist[ii].id; 1781 obj.chan = $scope.tracklist[ii].chan; 1782 obj.type = $scope.tracklist[ii].type; 1783 obj.user = $scope.tracklist[ii].user; 1784 obj.gain = $scope.tracklist[ii].gain; 1785 list.push(obj); 1786 } 1787 $scope.render.tracklist = list; 1788 //$scope.render.metadata = $scope.metadata; 1789 let mdata = {}; 1790 for(var ii = 0;ii < $scope.metadata.length; ii++) { 1791 mdata[$scope.metadata[ii].name] = $scope[$scope.metadata[ii].name]; 1792 } 1793 $scope.render.metadata = mdata; 1794 $http({ 1795 url: '/mtrack', 1796 method: "POST", 1797 data: $scope.render 1798 }) 1799 .then(function(response) { 1800 // success 1801 }, 1802 function(response) { // optional 1803 // failed 1804 }); 1805 1806 } 1807 setTimeout( function() { 1808 var query = $location.search(); 1809 1810 if (query.page == "mtrack") { 1811 var s = query.track; 1812/* 1813 if (s && s.indexOf(":")) { 1814 return; 1815 } 1816*/ 1817 $scope.player_stop(); 1818// console.log("EDIT SONG " +s); 1819/* 1820 if (query.time) { 1821 $scope.mtrack_seek(query.time); 1822 } 1823*/ 1824 $scope.mtrack_edit_song(s); 1825 } 1826 }, 1000); 1827 1828 1829 1830 });
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.