scriptProcessorNode.onaudioprocess not able to access global variables - javascript

I am building class around a scriptProcessorNode oscillator. I have wrapped my onaudioprocess event handler in a function Gendy.prototype.process. I can access global variables and functions from within this wrapper function, but they are not accessible from within the onaudioprocess function.
I devised a work around for the properties, to redefine them in the wrapper function, but this doesn't work when trying to call another method, a random walk method, with this.walk().
Here is my code:
Gendy.prototype.process = function(){
var point = 0;
var index = 0;
var y = 0;
var breakpoint = this.breakpoint;
var freq = this.freq;
var walk = this.walk();
this.scriptNode.onaudioprocess = function(audioProcessingEvent){
var outputBuffer = audioProcessingEvent.outputBuffer;
var outputData = outputBuffer.getChannelData(0);
for(var j = 0; j < outputData.length;j++){
// linearly interpolate between the new breakpoint positions
// get the interp point by comparing index to the x distance
var lerp = (index - breakpoint[point].x) / (breakpoint[point+1].x - breakpoint[point].x);
y = lerp * (breakpoint[point+1].y - breakpoint[point].y) + breakpoint[point].y;
if(point < breakpoint.length && index >= breakpoint[point+1].x) {
point++;
}
outputData[j] = y;
index+=freq;
if(index >= breakpoint[breakpoint.length-1].x){
index = 0;
point = 0;
walk();
}
}
}
}
This makes sound, but returns the errors:
Uncaught TypeError: walk is not a function
for few lines and then
Uncaught TypeError: undefined is not a function
forever.
Is this a bug with the scriptProcessorNode? Any insight would be appreciated!

no bug in scriptProcessorNode, the issue is the below line:
this.scriptNode.onaudioprocess = function(audioProcessingEvent){
the this varible inside the onaudioprocess would refer to this.scriptNode object by default, you can handle it in one of two ways:
Use bind( as you have done in your answer):
this.scriptNode.onaudioprocess = function(audioProcessingEvent){
...
}.bind(this)
use a local variable to hold the value of this, and use that local variable in place of this:
var self = this;
this.scriptNode.onaudioprocess = function(audioProcessingEvent){
...

I was able to access this from within the onaudioprocess function by attaching .bind(this) to it.
Here is the code:
Gendy.prototype.process = function(){
this.scriptNode.onaudioprocess = function(audioProcessingEvent){
var outputBuffer = audioProcessingEvent.outputBuffer;
var outputData = outputBuffer.getChannelData(0);
for(var j = 0; j < outputData.length;j++){
// linearly interpolate between the new breakpoint positions
// get the interp point by comparing index to the x distance
var lerp = (this.index - this.breakpoint[this.point].x) / (this.breakpoint[this.point+1].x - this.breakpoint[this.point].x);
this.y = lerp * (this.breakpoint[this.point+1].y - this.breakpoint[this.point].y) + this.breakpoint[this.point].y;
if(this.point < this.breakpoint.length && this.index >= this.breakpoint[this.point+1].x) {
this.point++;
}
outputData[j] = this.y;
this.index+=this.freq;
if(this.index >= this.breakpoint[this.breakpoint.length-1].x){
this.index = 0;
this.point = 0;
this.walk();
}
}
}.bind(this);
}

Related

Loop through array of images in javascript

I'm trying to loop through an array of images but can't seem to get past image 2.
The array should also loop back to 1 when the last image has passed...
var WorkArray = new Array('work/01.png', 'work/02.png', 'work/03.png', 'work/04.png');
var nelements = WorkArray.length;
preload_image_object = new Image();
var i = 0;
for(i=0; i<=nelements; i++) {
preload_image_object.src = WorkArray[i];
}
function cC() {
var nelements = WorkArray.length;
var i = 0;
for(i=0; i<=nelements; i++) {
nelements = WorkArray[i];
}
document.getElementById("work").style.backgroundImage="url('"+WorkArray[i]+"')";
}
You can save the current file and use modulo to run in cyclic manner.
It will look something like that:
var WorkArray = new Array('work/01.png', 'work/02.png', 'work/03.png', 'work/04.png');
var currentImage = 0
function nextImage(){
currentImage = (currentImage + 1) % WorkArray.length;
document.getElementById("work").style.backgroundImage="url('"+WorkArray[currentImage]+"')";
}
You are overwriting nelements with the current element of the loop:
nelements = WorkArray[i];
The following should fix your loops:
var WorkArray = new Array('work/01.png', 'work/02.png', 'work/03.png', 'work/04.png');
var preload_image_object = new Image();
/* Lets get rid of `nelements`, as its just confusing. Get the length here.
* If, for performace reasons you want to use elements, the best way is to reverse
* aka for(var i = WorkArray.length-1; i >= 0 ; i--)
* Also, its simpler to declare the var in your for-loop itself instead of outside of it.
*/
for(var i = 0; i <= WorkArray.length; i++){
preload_image_object.src = WorkArray[i];
}
Also, again for simplifications sake, your application of the background-image could be done inside your for loop as well, and can be made to look cleaner with some spaces and omitting the ' inside your url():
document.getElementById("work").style.backgroundImage = "url(" + WorkArray[i] + ")";

JavaScript: variable within an object is not defined

I'm having problems when trying to store a 2D-array in an object variable.
var prTClass = {
prT: Create2DArray(5,8),
setPriceT: function(i,j,price){
prT[i][j] = price;
},
...
}
Create2DArray() is not throwing any error, and the code is this:
function Create2DArray(rows,columns) {
var mat = [];
for(var x = 0; x < rows; x++){
mat[x] = [];
for(var y = 0; y < columns; y++){
mat[x][y] = 'X';
}
}
return mat;
}
The message error I'm getting is "Uncaught ReferenceError: prT is not defined".
I also tried to instantiate the variable with an init() function, like this:
prT: [],
init: function(){
this.prT=Create2DArray(5,8);
},
What's the problem? Thank you.
You're lacking this. You can never access prT as just prT. You must always access it as either this.prT from within the context of that object, or prTClass.prT from outside.

can't convert undefined to object in javascript

Update: I have added the fiddle. Please refer here. use web console for error.
I am writing a code for traveling salesman problem. Here is the code :
var ind =[]; //values selected
var cp =[];
var X;
var Y;
var tour = [];
// no values selected in the starting
for(j=0;j<friends_cnt;j++) {
ind[j] = 0;
}
// distances at i,i infinity
for(i=0;i<friends_cnt;i++) {
distance[i][i] = 9999999999999;
}
var k = 0;
var X = 0;
tour[k] = X;
ind[X] = 1;
var i =1;
while(i<friends_cnt && ind[i] === 0) {
var min = 9999999999999;
// finding minimum of the undeleted values
for(j=0;j<friends_cnt;j++) {
if(ind[j] === 0) {
if(distance[X][j] < min) {
min = distance[X][j];
Y = j; // y is the min city
}
}
}
k = k+1; // counter for the starting city
tour[k] = Y; //city added
ind[Y] = 1;
X = Y;
i++;
}
k = k+1;
tour[k] = tour[1];
for(var q=0;q<k+1;q++) {
console.log(tour[q]);
}
});
});
now here whenever i run my program, it shows an error
TypeError: can't convert undefined to object
in the line
var min = 9999999999999;
My question is that is this because JavaScript cant handle large numbers or something else ?
Javascript's max number is 1.7976931348623157e+308 (aka the var Number.MAX_VALUE), so that shouldn't be an issue.
If you are trying to access an object of an object, it won't work.
You have distance[X][j]. That tries to access key j of distance[X]. To fix this, define distance[X] as an object:
distance[X] = [];
Other example:
var distance = [];
distance[i]
//undefined;
distance[i][i]
//syntax error
distance[i] = [];
distance[i][i]
//undefined;
For 2D arrays, see this question.
The problem is actually here:
distance[i][i] = 9999999999999;
If distance is undefined or an empty array, that statement will fail. This should fix it:
var distance = []; // <-- this is missing from the top of your code
// ...
if (!distance[i]) {
distance[i] = [];
}
distance[i][i] = 9999999999999;
Try this for minimum number
var min = int.MinValue
For max number
var max = int.MaxValue
Edited
Refer Reference
Number.Max_Value
Number.Min_Value
UPDATED
If you see your code you have filled the ind[] from 0
for(j=0;j<friends_cnt;j++) {
ind[j] = 0;
}
and in your while condition you have set value of i from 1. So for the last element it may be throwing error

JavaScript TypeError with arrays and integers

So, I was having this problem with arrays in JavaScript.
I initialized some variables as shown here:
var world = new Array;
var monsters = new Array;
var items = new Array;
var x = 0;
var y = 0;
and tried to run this code on it:
while (y <= 49) { //generate world
world[x][y] = parseInt(Math.floor(Math.random()*2)); //0 = flatland, 1 = desert, 2 = mountain, 3 = swamp
x++;
if (x >= 49) {
x = 0;
y++;
}
}
x = 0;
y = 0;
but I get presented with this error:
"TypeError: can't convert undefined to object"
on the Math.random() line.
I've tried everything I can think of, but it still throws that error.
Any help will be greatly appreciated!
world[x][y] is not initialized. That's the problem. You need to intialize below the while statement
while (y <= 49) {
world[x] = new Array(); //add this
world[x] is not an array so you get an error when trying to assign a value to world[x][y], your method of filling the array seems strange to me, I'd do it this way
world = [];
for (x = 0; x <= 49; x++) { //generate world
world[x] = [];
for (y = 0; y <= 49; y++){
world[x][y] = parseInt(Math.floor(Math.random()*2)); //0 = flatland, 1 = desert, 2 = mountain, 3 = swamp
}
}
x = 0;
y = 0;
You are missing the (). World must be defined as a two dimensional array world[x] = new Array(); Using the [] notation is more convenient.

callback function within a loop

I am really struggling with concept of scope in my code.
I am simply trying to create a 'callback' function which will add a className to a variable. As it's inside a function, I am passing the global variable as parameters to the callback function using the concept of closure (still dont understand how closure works).
var ePressCuttingsArray = $(".cPressCuttings");
var eSelectedPressCuttingsArray = [];
var iIndexArray = [];
for (var i = 0; i < 7; i++) {
var iIndexArrayValue;
// two conditions being checked in while loop, if random no. is not in global array (iIndexArray) & i var is equal to eSelectedPress... array
while (jQuery.inArray(((iIndexArrayValue = Math.floor(Math.random() * 14) + 1), iIndexArray) === -1)
&& (i === eSelectedPressCuttingsArray.length))
{
// to push a value at a position from array ePressCut... into eSelectedPress... array
eSelectedPressCuttingsArray.push(ePressCuttingsArray[iIndexArrayValue]);
// run a function to addClass to the recently pushed value in eSelectedPress... array
(function (i) {
$(eSelectedPressCuttingsArray[i]).addClass("cPressCuttingsDisplay0" + i)
} (i) );
iIndexArray.push(iIndexArrayValue);
}
}
Could someone explain why the closure func. is not performing correctly, i.e. it always successfully add the className "cPressCuttingsDisplay00", but doesnt follow that up with a className of "cPressCuttingsDisplay01" for the next loop iteration.
You should be able to accomplish your goal by using a for loop:
var ePressCuttingsArray = $(".cPressCuttings").makeArray();
var eSelectedPressCuttingsArray = [];
for (var i = 0; i < 7; i++) {
var idx = Math.floor(Math.random() * ePressCuttingsArray.length);
var selectedItem = ePressCuttingsArray[idx];
selectedItem.addClass('cPressCuttingsDisplay0' + i);
eSelectedPressCuttingsArray.push(selectedItem);
ePressCuttingsArray.splice(idx, 1);
}

Categories

Resources