Ergebnis 1 bis 7 von 7
  1. #1
    Avatar von xorg1990
    xorg1990 ist offline König
    registriert
    19-12-2013
    Beiträge
    835

    ‎OffscreenCanvas + WebWorker Problem

    Hi, habe noch ein größeres Problem.

    Ich erhalte immer diese Fehlermeldung: multiChannelAnalyser.js:115 Uncaught DOMException: Failed to execute 'postMessage' on 'Worker': An OffscreenCanvas could not be cloned because it was detached.


    Ok, ich kann also nur das OffScreencanvas einmal den webworker zuweisen.

    Aber wie bekomme ich meine FFT Daten in den worker, es gibt doch nur ein message event oder kann ich eigene events erstellen.

    z.B self.addEventListener('meinEigenesEvent', function(e) {}

    Aktuell ist der worker code so:
    Code:
    var workerID;
    
    self.addEventListener('message', function(e) {
    	if(e.data.workerID){
    		workerID = e.data.workerID;
    	}else{
    	let canvas = e.data.canvas;
      	let context = canvas.getContext("2d");
    	let  timeDomainData = e.data.fftTimeData;
    	let width = canvas.width;
    	let height = canvas.height;
    
    
      	  context.fillStyle = "rgba(51, 51, 51, 0.4)";
          context.fillRect(0, 0, width, height);
    
          context.strokeStyle = "#1abc9c";
          context.beginPath();
          for (let i = 0, imax = timeDomainData.length; i < imax; i++) {
            let x = linlin(i, 0, imax, 0, width);
            let y = linlin(timeDomainData[i], -1, 1, height, 0);
    
            context.lineTo(x, y);
          }
          context.stroke();
          context.commit();
      }
    });
    
    function linlin(value, inMin, inMax, outMin, outMax) {
          return (value - inMin) / (inMax - inMin) * (outMax - outMin) + outMin;
    }
    und aufgerufen wird er so
    Code:
      		function draw(){
      			for(let key in analysers){
      				let offscreen = spectrums[key];
      				let analyser =  analysers[key];
      				let worker = renderWorkers[key];
      				let TimeData = new Float32Array(analyser.frequencyBinCount)
      				analyser.getFloatTimeDomainData(TimeData);
      				worker.postMessage({workerID: null, canvas: offscreen, fftTimeData : TimeData}, [offscreen]);
      			}
      		}
    aussehen müsste der worker code in etwa so:

    Code:
        let context;
      let width;
      let height;
    
    self.addEventListener('message', function(e) {
    	if(e.data.workerID){
    		workerID = e.data.workerID;
    	}else if(e.data.workerID){
    	let canvas = e.data.canvas;
      context = canvas.getContext("2d");
    	width = canvas.width;
    	height = canvas.height;
      }else{
          let  timeDomainData = e.data.fftTimeData;
      	  context.fillStyle = "rgba(51, 51, 51, 0.4)";
          context.fillRect(0, 0, width, height);
    
          context.strokeStyle = "#1abc9c";
          context.beginPath();
          for (let i = 0, imax = timeDomainData.length; i < imax; i++) {
            let x = linlin(i, 0, imax, 0, width);
            let y = linlin(timeDomainData[i], -1, 1, height, 0);
    
            context.lineTo(x, y);
          }
          context.stroke();
          context.commit();
      }
    });
    Ein zweites Message event wäre mir lieber geht das?
    Geändert von xorg1990 (31-01-2018 um 15:26 Uhr)

  2. #2
    tsseh ist offline Foren-Gott
    registriert
    19-05-2008
    Beiträge
    5.631

    AW: ‎OffscreenCanvas + WebWorker Problem

    Zitat Zitat von xorg1990 Beitrag anzeigen
    Ich erhalte immer diese Fehlermeldung: multiChannelAnalyser.js:115 Uncaught DOMException: Failed to execute 'postMessage' on 'Worker': An OffscreenCanvas could not be cloned because it was detached.


    Ok, ich kann also nur das OffScreencanvas einmal den webworker zuweisen.
    ich würde vermuten überhaupt nicht, jedenfalls laut fehlermeldung.
    entweder du erzeugst das OffscreenCanvas erst im worker oder du clonst es nicht
    https://developer.mozilla.org/en-US/...rable_objects)

    Zitat Zitat von xorg1990 Beitrag anzeigen
    Aber wie bekomme ich meine FFT Daten in den worker, es gibt doch nur ein message event oder kann ich eigene events erstellen.
    ???
    über die data-eigenschaft des event-objekts, so wie du es machst, wo ist dein problem???

  3. #3
    Avatar von xorg1990
    xorg1990 ist offline König
    registriert
    19-12-2013
    Beiträge
    835

    AW: ‎OffscreenCanvas + WebWorker Problem

    Ich klone überhaupt nichts, ich erzeuge ganz normal ein canvas im dom und teile den worker das mit was mir transferControlToOffscreen() zurück gibt .

    Das steht in diesem Object let offscreen = spectrums[key];


    Das worker script schaut nun so aus:

    Code:
    var workerID;
    var context;
    var width;
    var height;
    self.addEventListener('message', function(e) {
    	if(e.data.workerID){
    		workerID = e.data.workerID;
    	}else if(e.data.canvas){
    	let canvas = e.data.canvas;
      	context = canvas.getContext("2d");
    	width = canvas.width;
    	height = canvas.height;
      }else{
          let  timeDomainData = e.data.fftTimeData;
      	  context.fillStyle = "rgba(51, 51, 51, 0.4)";
          context.fillRect(0, 0, width, height);
    
          context.strokeStyle = "#1abc9c";
          context.beginPath();
          for (let i = 0, imax = timeDomainData.length; i < imax; i++) {
            let x = linlin(i, 0, imax, 0, width);
            let y = linlin(timeDomainData[i], -1, 1, height, 0);
    
            context.lineTo(x, y);
          }
          context.stroke();
          context.commit();
      }
    });
    function linlin(value, inMin, inMax, outMin, outMax) {
          return (value - inMin) / (inMax - inMin) * (outMax - outMin) + outMin;
    }
    Was mich stört ist diser if Else baum:
    Code:
    	if(e.data.workerID){
    		workerID = e.data.workerID;
    	}else if(e.data.canvas){
    	let canvas = e.data.canvas;
      	context = canvas.getContext("2d");
    	width = canvas.width;
    	height = canvas.height;
      }else{
    Dafür hätte ich gerne separate onmessage funktionen im worker, geht das.

    Zum Beispiel: self.addEventListener('setWorkerID', function(e) {.....

    Wenn ich jeden key einzeln überprüfen muss ist dann extrem umständlich.

  4. #4
    tsseh ist offline Foren-Gott
    registriert
    19-05-2008
    Beiträge
    5.631

    AW: ‎OffscreenCanvas + WebWorker Problem

    Zitat Zitat von xorg1990 Beitrag anzeigen
    Ich klone überhaupt nichts, ich erzeuge ganz normal ein canvas im dom und teile den worker das mit was mir transferControlToOffscreen() zurück gibt .
    und alles was du einem worker sendest wird geklont
    https://developer.mozilla.org/en-US/...urther_details

    Zitat Zitat von xorg1990 Beitrag anzeigen
    Was mich stört ist diser if Else baum:
    Code:
    worker.postMessage({func: "workerID", data: {workerID: 99}});
    worker.postMessage({func: "onCanvas", data: {canvas: canvas, width = canvas.width}});
    Code:
    function onWorkerID(data)
    {
      
    }
    
    function onCanvas(data)
    {
      
    }
    
    this.addEventListener('message', function(e)
    {
      switch (e.data.func)
      {
      case "workerID";
         onWorkerID(e.data.data);
         break;
        case "onCanvas";
         // oder so auch ohne switch/case, dann aber fehleranfälliger
         this[e.data.func](e.data.data);
         break;
      default:
        // err
      }
    });
    - - - Aktualisiert - - -

    Zitat Zitat von tsseh Beitrag anzeigen
    oder du clonst es nicht
    ok, das hab ich übersehen
    Zitat Zitat von xorg1990 Beitrag anzeigen
    Code:
    worker.postMessage({workerID: null, canvas: offscreen, fftTimeData : TimeData}, [offscreen]);
    dann sollte das aber gehen

    - - - Aktualisiert - - -

    achso, dann ist aber die frage, wieso du schreibst
    Zitat Zitat von xorg1990 Beitrag anzeigen
    Ok, ich kann also nur das OffScreencanvas einmal den webworker zuweisen.
    das sind doch alles eigene OffScreencanvas?

  5. #5
    Avatar von xorg1990
    xorg1990 ist offline König
    registriert
    19-12-2013
    Beiträge
    835

    AW: ‎OffscreenCanvas + WebWorker Problem

    Code:
    function onWorkerID(data)
    {
      
    }
    
    function onCanvas(data)
    {
      
    }
    
    this.addEventListener('message', function(e)
    {
      switch (e.data.func)
      {
      case "workerID";
         onWorkerID(e.data.data);
         break;
        case "onCanvas";
         // oder so auch ohne switch/case, dann aber fehleranfälliger
         this[e.data.func](e.data.data);
         break;
      default:
        // err
      }
    });
    Hm ok, auch nicht so das was ich mir vorgestellt habe, aber immerhin. Dachte man kann direkt auf Funktionen in workern zugreifen.

    Zitat Zitat von tsseh
    das sind doch alles eigene OffScreencanvas?
    Ja sind es.

    Ich erstelle pro Audio Kanal mehrere canvas im dom, für jeden Kanal wird eine eigenes Spektrum gerendert im worker.
    Bei einer 7.1 Übertragung ist das eine menge an Daten. 8 mal FFT berechnen und rendern. Da kommt die ‎OffscreenCanvas wie gerufen.

    Hier mal spaß sichtshalber die komplette klasse, wenn du noch Verbesserungs ideen hast immer raus damit.
    Code:
    function multiChannelAnalyser(audioContext,Channels ,fftSize){//leanftBank alle boxen links, center  alle boxen front, rightbank alle boxen rechts
    		const numOfChannels = Channels;
    		const splitter = audioContext.createChannelSplitter(numOfChannels);
    		splitter.channelCountMode = "explicit";
    		splitter.channelCount = numOfChannels;
      		let analysers = {};
      		let renderWorkers = {};
    
    
      		for(let i=0; i<numOfChannels;i++){
      			let channelID;
      			switch(i){
      			  case 1://channel 1 right channel 
    		        generateCanvas("right");
    		        channelID = "right";
    		      break;
    		       case 2: //channel 2 center channel 
    		        generateCanvas("center");
    		        channelID = "center";
    		      break;
    		       case 3: //channel 3 LFE channel 
    		        generateCanvas("LFE");
    		        channelID = "LFE";
    		      break;
    		       case 4: //channel 4 links hinten
    		        generateCanvas("leftSourroundBack");
    		        channelID = "leftSourroundBack";
    		      break;
    		       case 5://channel 5 rechts hinten
    		        generateCanvas("rightSourroundBack");
    		        channelID = "rightSourroundBack";
    		      break;
    		       case 6://channel  6 links mitte
    		        generateCanvas("leftSourround");
    		        channelID = "leftSourround";
    		      break;
    		       case 7://channel  7 rechts mitte
    		         generateCanvas("rightSourround");
    		        channelID = "rightSourround";
    		      break;
    		      //channel 0 left channel 
    		       default: generateCanvas("left");
    		       channelID = "left";
      			}
    
       			analysers[channelID] = audioContext.createAnalyser();
      			analysers[channelID].fftSize = fftSize;
      			analysers[channelID].channelCountMode = "explicit";
      			analysers[channelID].channelCount = 1;
      			
      			splitter.connect(analysers[channelID], i, 0);//channel i zu channel 0
      		}
    
      		function generateCanvas(chStr){
      			//<canvas style="background-color: rgba(51, 51, 51, 0.4); width=320; height=160; id="'+chStr.trim()+'" width="320" height="160"
      			let canvas = $("<canvas></canvas>").css({
    					backgroundColor: "rgba(51, 51, 51, 0.4)"
      			}).attr({
      					id: chStr,
      				    width : 320,
    					height: 160
      			});
    
    			let worker = renderWorkers[chStr] = new Worker('workerRenderScript.js');
      			//renderWorkers[channelID].addEventListener('message', onMsg, false);
            	renderWorkers[chStr].addEventListener('error', onError, false);
            	renderWorkers[chStr].postMessage({workerID: chStr, fftTimeData : null});
            	
    
      			switch(chStr){
      			  case "right"://channel 1 right channel 
      			  		$("#centerBank").prepend(canvas);
    		      break;
    		       case "center": //channel 2 center channel 
    		        	$("#center_LFE").append(canvas);
    		      break;
    		       case "LFE": //channel 3 LFE channel
    		           $("#center_LFE").append(canvas);
    		      break;
    		       case "leftSourroundBack": //channel 4 links hinten
    		       		$("#leftBank").append(canvas);
    		      break;
    		       case "rightSourroundBack"://channel 5 rechts hinten
    		       		$("#rightBank").append(canvas);
    		      break;
    		       case "leftSourround"://channel  6 links mitte
    		       		$("#leftBank").append(canvas);
    		      break;
    		       case "rightSourround"://channel  7 rechts mitte
    		       		$("#rightBank").append(canvas);
    		      break;
    		      //channel 0 left channel 
    		       default: $("#centerBank").prepend(canvas);
      			}
      			let offscreen = document.querySelector("#"+chStr).transferControlToOffscreen();
      			worker.postMessage({workerID: null, canvas: offscreen, fftTimeData : null}, [offscreen]);
      		}
    
    /*
      		function createElementFromHTML(htmlString) {
    		  let div = document.createElement('div');
    		  div.innerHTML = htmlString.trim();
    		  // Change this to div.childNodes to support multiple top-level nodes
    		  return div.firstChild; 
    		}
    */
      		function connectSrc(src){
    			src.connect(splitter);
      		}
    
      		function draw(){
      			for(let key in analysers){
      				let analyser =  analysers[key];
      				let worker = renderWorkers[key];
      				let TimeData = new Float32Array(analyser.frequencyBinCount)
      				analyser.getFloatTimeDomainData(TimeData);
      				worker.postMessage({workerID: null, canvas: null, fftTimeData : TimeData});
      			}
      		}
    
      		function onError(e){
      			console.log("Worker Error:", e);
      		}
    
      		return {
      			connect : connectSrc,
      			draw : draw
      		};
    
      	}

  6. #6
    tsseh ist offline Foren-Gott
    registriert
    19-05-2008
    Beiträge
    5.631

    AW: ‎OffscreenCanvas + WebWorker Problem

    Zitat Zitat von xorg1990 Beitrag anzeigen
    Ja sind es.
    dann sollte doch aber alles gehen?

  7. #7
    Avatar von xorg1990
    xorg1990 ist offline König
    registriert
    19-12-2013
    Beiträge
    835

    AW: ‎OffscreenCanvas + WebWorker Problem

    Zitat Zitat von tsseh
    dann sollte doch aber alles gehen?
    Scheint noch ein wenig buggy zu sein die Offscren API:

    Gestern Abend lief alles jetzt hat Chrome kein bock mehr

    Bildschirmfoto von »2018-02-01 10-04-53«.png

    So wie er anfängt zu rendern.....aus

Ähnliche Themen

  1. Antworten: 0
    Letzter Beitrag: 12-07-2017, 08:02
  2. Antworten: 0
    Letzter Beitrag: 13-04-2017, 11:13
  3. Contao-Webworker (m/w)
    Von campusjaeger im Forum Jobs
    Antworten: 0
    Letzter Beitrag: 09-03-2016, 14:11
  4. WebWorker
    Von tröröö im Forum JavaScript
    Antworten: 11
    Letzter Beitrag: 23-02-2014, 12:43
  5. Antworten: 5
    Letzter Beitrag: 05-05-2012, 00:36

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •