Search code examples
javascriptweb-audio-apip5.jstone.js

Tonejs sequencer does not recognise variables into an object


I am trying to build an object that contains a sequencer using p5.js, p5.sound library and tone.js

The problem is that my code does not recognise the variables written in one function that is inside one object.

All other functions inside class tr909 can recognise the variables that I declared in the class constructor, but the variable "sequence" doesn't recognise them.

As you can see below, tr909 class has sX and sY variables , but when I am in the function called sequence ( inside the tr909 class, on the bottom), this function won't recognise the variables anymore.

do you know why this happen?

thanks ! :)

 //object 
let tr9091;
let bL9091 = 16; //beat lenght

let posX9091 = 100; //positionX 909
let posY9091 = 220; //positionY 909

let sX9091 = 320; //sizeX of 909
let sY9091 = 60; //sizeY of 909

// var cellWidth = sX9091 / bL9091; //dont know why, if I put it in constructor of 909 object, sequence function does not recognise cellWidth

//Pre-load  audio files 
let hh909, clp909m, bd909;

let time;
let beatIndex;
var sX;
let sequence;
// var sX = 1;

function preload() {

  bd909 = loadSound('assets/bass_sample.mp3');
  hh909 = loadSound('assets/hh_sample.mp3');
  clp909 = loadSound('assets/clap_sample.mp3');

}

function setup() {
  createCanvas(600, 400);

  tr9091 = new tr909(bd909, hh909, clp909, bL9091, posX9091, posY9091, sX9091, sY9091);


}

function draw() {

}

function keyPressed() {
  if (key === ' ') {
    tr9091.clicked();
  }
}

function mousePressed() {
  tr9091.rectPressed();
}

class tr909 {

constructor(bd, hh, clp, beatLenght, pX, pY, sX, sY) {
    //variables 
    this.bd = bd;
    this.hh = hh;
    this.clp = clp;

    this.beatLenght = beatLenght;


    this.pX = pX; //positionX 909
    this.pY = pY; //positionY 909

    this.sX = sX; //sizeX 909
    this.sY = sY; //sizeY 909

    this.cellWidth = this.sX / this.beatLenght;


    //sequences
    this.bdPat = [1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0];
    this.hhPat = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
    this.clpPat = [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0];

    this.sPat = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];

    this.cursorPos = 0;

    //phrases
    this.bdPhrase = new p5.Phrase('bd', (time) => {
      this.bd.play(time)
    }, this.bdPat);

    this.hhPhrase = new p5.Phrase('hh', (time) => {
      this.hh.play(time)
    }, this.hhPat);

    this.clpPhrase = new p5.Phrase('clp', (time) => {
      this.clp.play(time)
    }, this.clpPat);


    //parts
    this.drums = new p5.Part();


    //adding phrase to parts
    this.drums.addPhrase(this.bdPhrase);
    this.drums.addPhrase(this.hhPhrase);
    this.drums.addPhrase(this.clpPhrase);

    this.drums.addPhrase('seq', this.sequence, this.sPat);



    //BPM
    let bpmCTRL;
    this.bpmCTRL = createSlider(30, 120, 120, 1);
    this.bpmCTRL.position(pX + 10, pY + 70);
    this.bpmCTRL.input(() => {
      this.drums.setBPM(this.bpmCTRL.value())
    });
    this.drums.setBPM('120');

    this.drawMatrix();

  } //final constructor


  clicked() { //play loop
    this.drums.loop();
  }

  rectPressed() {
    //Y mouse click inside the object 
    if ((mouseY > this.pY && mouseY < this.pY + this.sY) && (mouseX > this.pX && mouseX < this.pX + this.sX)) {
      this.rowClicked = floor(3 * (mouseY - this.pY) / this.sY);
      this.indexClicked = floor(16 * (mouseX - this.pX) / this.sX);

      if (this.rowClicked === 0) {
        console.log("firstrow " + this.indexClicked);
        this.bdPat[this.indexClicked] = +!this.bdPat[this.indexClicked];
      } else if (this.rowClicked === 1) {
        console.log("secondtrow");
        this.hhPat[this.indexClicked] = +!this.hhPat[this.indexClicked];
      } else if (this.rowClicked === 2) {
        console.log("thrtrow");
        this.clpPat[this.indexClicked] = +!this.clpPat[this.indexClicked];
      }
      this.drawMatrix();
    }
  }



//visual interface
  drawMatrix() {

    fill(80);
    stroke('gray');
    strokeWeight(2);
    rect(this.pX, this.pY, this.sX, this.sY);


    stroke('gray');
    strokeWeight(2);

    //vertical lines
    for (let i = 0; i < this.beatLenght; i++) {
      line(this.pX + i * this.cellWidth, this.pY, this.pX + i * this.cellWidth, this.pY + this.sY);
    }

    for (let i = 0; i < 4; i++) {
      line(this.pX, this.pY + i * this.sY / 3, this.pX + this.sX, this.pY + i * this.sY / 3);
    }

    //draw circles

    for (let i = 0; i < this.beatLenght; i++) {
      if (this.bdPat[i] === 1) {
        ellipse(this.pX + i * this.cellWidth + 0.5 * this.cellWidth, this.pY + this.sY / 6, 10);
      }
      if (this.hhPat[i] === 1) {
        ellipse(this.pX + i * this.cellWidth + 0.5 * this.cellWidth, this.pY + this.sY / 2, 10);
      }
      if (this.clpPat[i] === 1) {
        ellipse(this.pX + i * this.cellWidth + 0.5 * this.cellWidth, this.pY + this.sY * 5 / 6, 10);
      }
    }

  }

  sequence(time, beatIndex) {

    this.cellWidth = this.sX / this.beatLenght;

    stroke('red');
    fill(255, 0, 0, 30);
    rect(beatIndex * this.cellWidth, this.sX, this.cellWidth, this.sY);
    console.log(beatIndex);
  }


} //final object

Solution

  • Because here:

    this.drums = new p5.Part();
    //adding phrase to parts
    this.drums.addPhrase(this.bdPhrase);
    this.drums.addPhrase(this.hhPhrase);
    this.drums.addPhrase(this.clpPhrase);
    this.drums.addPhrase('seq', this.sequence, this.sPat);
    

    You pass it as a callback function. Check the first answer in this thread: How to access the correct `this` inside a callback?

    Either replace the argument this.sequence with:

    function(){ this.sequence() }.bind( this )
    

    or even shorter:

    this.sequence.bind(this);
    

    or like this:

    ()=>{ this.sequence() }
    

    or, when you want to pass in arguments or return value:

    (...args) => this.sequence(...args)