Web Audio playing back in Chrome but not Firefox - html

Firefox seems to be processing the audio but it won't play it back. This exact code works fine with Chrome. I'm seeing no errors from the console so I'm really at a loss. I'm thinking it has something to do with audioBuffer.getChannelData(0).set(audio); but I'm not sure. Anyone know why this audio won't play back in FF but will in Chrome? I'm running FF 27 right now.
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var init = 0;
var nextTime = 0;
var audioStack = [];
function toArrayBuffer(buffer) {
var ab = new ArrayBuffer(buffer.length);
var view = new Uint8Array(ab);
for (var i = 0; i < buffer.length; ++i) {
view[i] = buffer[i];
}
return ab;
}
socket.on('stream', function(data) {
audioStack.push(data);
//if ((init!=0) || (audioStack.length > 10)) { // make sure we put at least 10 chunks in the buffer before starting
init++;
scheduleBuffers();
//}
});
function scheduleBuffers() {
while (audioStack.length) {
var data = toArrayBuffer(audioStack.shift().data);
var audio = [];
audData = new Int16Array(data);
for (var i = 0; i < audData.length; i++) {
audio[i] = (audData[i]>0)?audData[i]/32767:audData[i]/32768; // convert buffer to within the range -1.0 -> +1.0
}
var source = context.createBufferSource();
var audioBuffer = context.createBuffer(1, audio.length , 44100);
source.buffer = audioBuffer;
audioBuffer.getChannelData(0).set(audio);
source.connect(context.destination);
if (nextTime == 0)
nextTime = context.currentTime + 0.05; /// add 50ms latency to work well across systems - tune this if you like
source.start(nextTime);
console.log('length: '+source.buffer.duration);
nextTime+=source.buffer.duration; // Make the next buffer wait the length of the last buffer before being played
};
}

Looking at this code:
source.buffer = audioBuffer;
audioBuffer.getChannelData(0).set(audio);
Can you try changing the order of these two lines? In other words, first set the channel data for audioBuffer and then assign it to source.buffer. Does that fix the problem for you?

Related

Merge or Use instance and Native render make no difference with Chrome plus Integrated Graphics Card [duplicate]

I am testing the FPS with my laptop using the Intel(R) Iris(R) Plus Graphics 655 card.
To test the threeJS example with Instance rendering and merge-drawcall rendering.
So I used both the QRCode_buffergeometry.json model and the suzanne_buffergeometry.json model.
for the QRCode_buffergeometry.json: vertex:12852, face: 4284
and for the suzanne_buffergeometry.json: vertex:1515 face: 967
Then the FPS for the suzanne_buffergeometry with 8000 count:
INSTANCE: 36
MERGED: 43
NATIVE: from 23 to 35 by rotation
for the QRCode_buffergeometry model with 8000 count:
INSTANCE: 9
MERGED: 15-17
NATIVE: 17-19
I am very confused with this performance.
1. As far as my understanding, with no matter if i use instance or merge-drawcall, the drawcall is fixed to be 1 and the total face number to draw is same, why merged-drawcall is better than instance? Since the face and vertex number are both same, I suppose what happened in the vertex shader for transform the vertex should be same too, so why merged is faster?
For the QRCode_buffergeometry model, native is almost same as merged, and better than instance, so I guess the CPU is not the bottle neck but the GPU is, however the final drawing data should be same, i mean eventually the face number to be draw should be same, why native is faster?, isn't that the instance is supposed to be the best way? I am pretty sure the camera's far and near is big enough, so there should not be any culling issue.
When I am trying to optimize some big scene, when should I pick merge? when to pick instance? and when maybe no doing anything is better?
Any help?
Thanks a lot~~~
Attached the code for the sample is here
body { margin: 0; }
<div id="container"></div>
<script type="module">
import * as THREE from 'https://cdn.jsdelivr.net/npm/three#0.112.1/build/three.module.js';
import Stats from 'https://cdn.jsdelivr.net/npm/three#0.112.1/examples/jsm/libs/stats.module.js';
import {
GUI
} from 'https://cdn.jsdelivr.net/npm/three#0.112.1/examples/jsm/libs/dat.gui.module.js';
import {
OrbitControls
} from 'https://cdn.jsdelivr.net/npm/three#0.112.1/examples/jsm/controls/OrbitControls.js';
import {
BufferGeometryUtils
} from 'https://cdn.jsdelivr.net/npm/three#0.112.1/examples/jsm/utils/BufferGeometryUtils.js';
var container, stats, gui, guiStatsEl;
var camera, controls, scene, renderer, material;
// gui
var Method = {
INSTANCED: 'INSTANCED',
MERGED: 'MERGED',
NAIVE: 'NAIVE'
};
var api = {
method: Method.INSTANCED,
mesh_number: 1,
count_per_mesh: 1000
};
var modelName = 'suzanne_buffergeometry.json';
var modelScale = (modelName === 'suzanne_buffergeometry.json' ? 1 : 0.01);
var modelVertex = (modelName === 'suzanne_buffergeometry.json' ? 1515 : 12852);
var modelFace = (modelName === 'suzanne_buffergeometry.json' ? 967 : 4284);
//
init();
initMesh();
animate();
//
function clean() {
var meshes = [];
scene.traverse(function(object) {
if (object.isMesh) meshes.push(object);
});
for (var i = 0; i < meshes.length; i++) {
var mesh = meshes[i];
mesh.material.dispose();
mesh.geometry.dispose();
scene.remove(mesh);
}
}
var randomizeMatrix = function() {
var position = new THREE.Vector3();
var rotation = new THREE.Euler();
var quaternion = new THREE.Quaternion();
var scale = new THREE.Vector3();
return function(matrix) {
position.x = Math.random() * 40 - 20;
position.y = Math.random() * 40 - 20;
position.z = Math.random() * 40 - 20;
rotation.x = Math.random() * 2 * Math.PI;
rotation.y = Math.random() * 2 * Math.PI;
rotation.z = Math.random() * 2 * Math.PI;
quaternion.setFromEuler(rotation);
scale.x = scale.y = scale.z = Math.random() * modelScale;
matrix.compose(position, quaternion, scale);
};
}();
function initMesh() {
clean();
console.time(api.method + ' (build)');
for (var i = 0; i < api.mesh_number; i++) {
// make instances
new THREE.BufferGeometryLoader()
.setPath('https://threejs.org/examples/models/json/')
.load(modelName, function(geometry) {
material = new THREE.MeshNormalMaterial();
geometry.computeVertexNormals();
switch (api.method) {
case Method.INSTANCED:
makeInstanced(geometry);
break;
case Method.MERGED:
makeMerged(geometry);
break;
case Method.NAIVE:
makeNaive(geometry);
break;
}
});
}
console.timeEnd(api.method + ' (build)');
var drawCalls = 0;
switch (api.method) {
case Method.INSTANCED:
case Method.MERGED:
drawCalls = api.mesh_number;
break;
case Method.NAIVE:
drawCalls = api.mesh_number * api.count_per_mesh;
break;
}
guiStatsEl.innerHTML = [
'<i>GPU draw calls</i>: ' + drawCalls,
'<i>Face Number</i>: ' + (modelFace * api.mesh_number * api.count_per_mesh),
'<i>Vertex Number</i>: ' + (modelVertex * api.mesh_number * api.count_per_mesh)
].join('<br/>');
}
function makeInstanced(geometry, idx) {
var matrix = new THREE.Matrix4();
var mesh = new THREE.InstancedMesh(geometry, material, api.count_per_mesh);
for (var i = 0; i < api.count_per_mesh; i++) {
randomizeMatrix(matrix);
mesh.setMatrixAt(i, matrix);
}
scene.add(mesh);
}
function makeMerged(geometry, idx) {
var instanceGeometry;
var geometries = [];
var matrix = new THREE.Matrix4();
for (var i = 0; i < api.count_per_mesh; i++) {
randomizeMatrix(matrix);
var instanceGeometry = geometry.clone();
instanceGeometry.applyMatrix(matrix);
geometries.push(instanceGeometry);
}
var mergedGeometry = BufferGeometryUtils.mergeBufferGeometries(geometries);
scene.add(new THREE.Mesh(mergedGeometry, material));
}
function makeNaive(geometry, idx) {
var matrix = new THREE.Matrix4();
for (var i = 0; i < api.count_per_mesh; i++) {
randomizeMatrix(matrix);
var mesh = new THREE.Mesh(geometry, material);
mesh.applyMatrix(matrix);
scene.add(mesh);
}
}
function init() {
var width = window.innerWidth;
var height = window.innerHeight;
// camera
camera = new THREE.PerspectiveCamera(70, width / height, 1, 100);
camera.position.z = 30;
// renderer
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
renderer.outputEncoding = THREE.sRGBEncoding;
container = document.getElementById('container');
container.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
// controls
controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
// stats
stats = new Stats();
container.appendChild(stats.dom);
// gui
gui = new GUI();
gui.add(api, 'method', Method).onChange(initMesh);
gui.add(api, 'count_per_mesh', 1, 20000).step(1).onChange(initMesh);
gui.add(api, 'mesh_number', 1, 200).step(1).onChange(initMesh);
var perfFolder = gui.addFolder('Performance');
guiStatsEl = document.createElement('li');
guiStatsEl.classList.add('gui-stats');
perfFolder.__ul.appendChild(guiStatsEl);
perfFolder.open();
// listeners
window.addEventListener('resize', onWindowResize, false);
Object.assign(window, {
scene
});
}
//
function onWindowResize() {
var width = window.innerWidth;
var height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
stats.update();
render();
}
function render() {
renderer.render(scene, camera);
}
//
function getGeometryByteLength(geometry) {
var total = 0;
if (geometry.index) total += geometry.index.array.byteLength;
for (var name in geometry.attributes) {
total += geometry.attributes[name].array.byteLength;
}
return total;
}
// Source: https://stackoverflow.com/a/18650828/1314762
function formatBytes(bytes, decimals) {
if (bytes === 0) return '0 bytes';
var k = 1024;
var dm = decimals < 0 ? 0 : decimals;
var sizes = ['bytes', 'KB', 'MB'];
var i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
</script>
This is only guesses
Three.js by default culls if things are outside the frustum.
We can turn this off with mesh.frustumCulled = false. I didn't notice a difference and this should show up in the draw count.
Three.js by default sorts opaque objects back to front.
This means everything else being equal, sorted will run faster
than unsorted because of the depth test. If I set the depth test
to always
material.depthFunc = THREE.AlwaysDepth
Then I seem to get slightly faster rendering with instanced vs native. Of course
everything else is not equal.
An issue in Chrome.
If I run in Firefox or Safari I get the expected results. Merged > Instanced > Native
It could be a bug or it could be they're working around a driver or
security issue that the other browsers are not. You'd have to ask.

Flash hangs when I execute this particular loop

Please do forgive me if this question is very stupid, but I couldn't figure out what to do, which is why I ask it.
Here, I declared a small white square as a movieclip symbol(Dot) and I wish to generate it after a specific gap on the entire screen.
So, when I execute this (test it) code on Flash CS6, it hangs. After that I will be forced to end the program without doing anything further.
import flash.ui.*;
stop();
Mouse.hide();
var ctX:int = 0,ctY:int = 0,done:Boolean = false;
var base:Object = MovieClip(root);
this.addEventListener(Event.ENTER_FRAME, eFrame);
function eFrame(event:Event):void
{
while (done == false)
{
var dots:Dot = new Dot ;
dots.x += (50 * ctX);
dots.y += (50 * ctY);
ctX++;
if (ctX == 11)
{
ctX = 0;
ctY++;
}
else if (ctX == 11 && ctY == 10)
{
done = true;
break;
}
stage.addChild(dots);
}
}
Thank you in advance.
I have attached a screenshot of the situation.
The loop will never finish because the condition for done=true is ctX==11, but ctX==11 causes ctX=0 in the first condition:
if (ctX == 11) // when ctX is 11
{
ctX = 0; // ctX is reset to 0
ctY++;
}
else if (ctX == 11 && ctY == 10) // so you will never have ctX=11 here
{
done = true;
break; // (Tip: you don't need `done` since `break` exits the loop)
}
You could fix this by swapping the conditions, but I think this use of a while loop is unnecessarily complex and fragile. Why not just use two for loops:
for (var ctX:int = 0; ctX < 11; ctX++) {
for (var ctY:int = 0; ctY < 11; ctY++) {
var dots:Dot = new Dot();
dots.x = (50 * ctX);
dots.y = (50 * ctY);
stage.addChild(dots);
}
}
This is much clearer and less fragile because the loops are fixed length.
You could even do it with one for loop and a little math, but you lose some clarity:
for (var i:int = 0; i < 11 * 11; i++) {
var dots:Dot = new Dot();
dots.x = (50 * (i % 11));
dots.y = (50 * int(i / 11));
stage.addChild(dots);
}

html5 drawing multiple canvas images

i've got a problem with canvas in html. I want to draw multiple canvas images.
I have created a loop which creates multiple canvas and then i want to draw in each canvas an image.
for (var i = 1; i <= playerStuff.MovingCards.length; i++){
$("#playersField").append("<canvas id='movingCardsField"+i+"' height='"+movingCardSizeY+"'\n\
width='"+movingCardSizeX+"'\n\
data='"+playerStuff.MovingCards[i-1].movePoints+"'></canvas>");
var imgObj = new Image();
var drawField = document.getElementById('movingCardsField'+i).getContext("2d");
imgObj.onload = function(){
drawField.drawImage(imgObj, 0,0);
};
imgObj.src = "./img/moveCards/"+playerStuff.MovingCards[i-1].name;
}
The result is that only the last canvas has a drawn image. What am I missing here?
Please dont use JQuery for this. In generally i'm not a friend of JQuery but thats my personally opinion,but here you should really dont useit, use the DOM its much more faster.
var playersField=document.getElementById("playersField");
var canvasElements=new Array ();
var canvasElement, drawField,imgObj;
var drawFields=new Array ();
for (var i = 0; i <= playerStuff.MovingCards.length; i++)
{
canvasElement=document.createElement ("canvas");
canvasElement.height=movingCardSizeY;
canvasElement.width=movingCardSizeX;
canvasElement.data=playerStuff.MovingCards[i-1].movePoints;
playersField.appendChild(canvasElement);
drawField=canvasElement.getContext("2d");
drawFields.push (drawField);
imgObj = new Image();
imgObj.src = "./img/moveCards/"+playerStuff.MovingCards[i-1].name;
imgObj.index=i;
imgObj.onload = function (){
drawFields[this.index].drawImage(this, 0,0);
};
that is becouse onload y asinchronous, when al the iterations of the for has ended, the onload is probably that has not been called. then drawField variable is the last element. to solve this in a fast way (but not the cleanest solution)
the scope of a varaible is not as it could be in c++ or other languages.
for (var i = 1; i <= playerStuff.MovingCards.length; i++){
(function(element) {
$("#playersField").append("<canvas id='movingCardsField"+i+"' height='"+movingCardSizeY+"'\n\
width='"+movingCardSizeX+"'\n\
data='"+element.movePoints+"'></canvas>");
var imgObj = new Image();
var drawField = document.getElementById('movingCardsField'+i).getContext("2d");
imgObj.onload = function(){
drawField.drawImage(imgObj, 0,0);
};
imgObj.src = "./img/moveCards/"+element.name;
})(playerStuff.MovingCards[i - 1]);
}
this may do the trick, more or less, I didn't check twice the code
btw is not very efficient also
this should be something better
var domElement = $("#playersField");
var canvasStart = "<canvas id='movingCardsField";
var canvasEnd = "' height='"+movingCardSizeY + "'width='" + movingCardSizeX + "' data='" + element.movePoints + "'></canvas>";
function createCanvas(element) {
var canvas = canvasStart + (i + 1) + canvasEnd;
domElement.append(canvas);
var imgObj = new Image();
var drawField = document.getElementById('movingCardsField' + (i + 1)).getContext("2d");
imgObj.onload = function() {
drawField.drawImage(imgObj, 0,0);
};
imgObj.src = "./img/moveCards/" + element.name;
}
for (var i = 0; i < playerStuff.MovingCards.length; i++) {
createCanvas(playerStuff.MovingCards[i]);
}

Flex string never cleared from the memory --> It is cleared eventually

I have this weird problem for a while and try to solve it to look up on the net for proper solution but still I am clueless.
When I check my application's memory usage with flex profiler (4.6) the portion of String keep increasing and eventually reach the point of crash.
And I pin pointed where this increasing occurs from my application's source code.
It is the local string variable that I passed to Json.decode(). It never cleared.
All the instance of the json string that I got from the socket server remains in the memory til app crashes even if profiler says there is 0 path to the String.
I don't know how to clear these Strings. It only keeps growing.
Please help me. I have been struggled with this for a week now.
Thanks for any support in advance.
portion of my source code that I think the source of the leak is as following.
protected function evtserverReseved(event:ProgressEvent):void{
var tmpArr:ByteArray = new ByteArray();
var tempByteArray:ByteArray = new ByteArray();
socEvtServer.readBytes(tmpArr, 0, socEvtServer.bytesAvailable);
tempByteArray.writeBytes(leftOverMessageNotify, 0, leftOverMessageNotify.length);
tempByteArray.writeBytes(tmpArr, 0, tmpArr.length);
leftOverMessageNotify = new ByteArray();
parseByteArray(tempByteArray);
}
private function parseByteArray(rawArray:ByteArray):void{
if(( rawArray[0] == 0x30 || rawArray[0] == 0x31 ) && rawArray[1] == 0x00 ){
var log:String = "";
for(var i:int=0; i<16; i++){
if(rawArray[i]==0){
}else{
log += rawArray[i]-48;
}
}
sizeOfFullListNotify = uint(log);
commonFunction.printLog("Event Server eventNotify sizeOfFullListNotify=" + sizeOfFullListNotify);
rawArray.position = 16;
}
var tempIdx:uint = rawArray.position;
var tempLength:uint = rawArray.length;
if(sizeOfFullListNotify <= tempLength - tempIdx){
var tempArray:ByteArray = new ByteArray();
var tempLeftOver:ByteArray = new ByteArray();
var j:uint;
for(j=0; j <sizeOfFullListNotify ; j++){
tempArray[j] = rawArray[j+tempIdx];
}
var euckrString:Object = tempArray.readMultiByte( tempArray.length,"euc-kr").replace(" ","").replace("\n","");
//commonFunction.printLog("Total memory=" + flash.system.System.totalMemory +", Free memory=" + flash.system.System.freeMemory + ", Event Server eventNotify JSON 수신 data size=" +euckrString.toString().length+ ", body=" + euckrString.toString() );
var ob:Object = com.adobe.serialization.json.JSON.decode(euckrString.toString());
commonFunction.printLog("Total memory=" + flash.system.System.totalMemory +", Free memory=" + flash.system.System.freeMemory + ", Event Server eventNotify JSON data size=" +euckrString.length+ ", body=" + euckrString );
if(ob.method != null){
//gridBox.DT_HOUSE.addItemAt(ob,0);
gridBox.DT_HOUSE.push(ob);
totlaReceivedList++;
}else if(!(ob.result is String)){
//confirm for registerEventNotify
commonFunction.printLog("confirm for registerEventNotify");
}
if(sizeOfFullListNotify < tempLength - tempIdx){
for(var k:uint=0; k <tempLength-tempIdx-sizeOfFullListNotify ; k++){
tempLeftOver[k] = rawArray[k+j+tempIdx];
}
parseByteArray(tempLeftOver);
}else{
//leftOverMessageNotify = new ByteArray();
}
}else{
//leftOverMessageNotify = rawArray;
for(var i:int = 0 ; i<rawArray.length ; i++){
leftOverMessageNotify[i] = rawArray[i];
}
rawArray = null;
}
}
var euckrString:Object(String) is the portion that never cleared from the memory.
It keeps stacking till crashes.

FFT and Convolution in AS3

I am trying to load a MP3, and a HRTF file (wav) and then by Convolution to produce another output audio signal but I am a bit stuck how to do it.
sound1 = new Sound;
sound1.addEventListener (Event.COMPLETE, completeHandler);
sound1.load (new URLRequest ("test.mp3"));
channel1 = sound1.play (0, int.MAX_VALUE);
function completeHandler (event:Event):void
{ bytes1 = new ByteArray;
samples1 = new <Number> [];
fft1 = new FFT;
addEventListener (Event.ENTER_FRAME, enterFrameHandler);
}
function enterFrameHandler (event:Event):void
{ // get bytes of 512 samples
bytes1.position = 0;
sound1.extract (bytes, 1024, channel1.position * 44.1);
// get samples of left or right channel
bytes1.position = 0;
while (bytes1.bytesAvailable > 0)
{ samples1 [int (bytes1.position / 8)] = bytes1.readFloat (); bytes1.readFloat();
}
// analyze samples1
fft1.analyze (samples1);
var limitHz:Number = 5000;
var i:int=0;
var n1:int = fft1.magnitudes.length * limitHz / (44100 / 2);
// And then here I should somehow multiply the signal1*signal2?
for (i = 0; i < n1; i++)
{ var sound1Mag:int = fft1.magnitudes [i];
var sound2Mag:int = fft2.magnitudes [i];
//......?????
}
}
Any help will be much appreciated.
OK, I edited to mention that the second file is not wav but a MP3 too (I converted the wav to MP3)