Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using p5.sound.js in instance mode: 'p5.Amplitude() not a constructor'

I am using an npm, webpack, babel environment to write an application with p5.js. To be able to have the sketch as a module, I have the sketch in instance mode and import the library and add-ons as modules:

import p5 from 'p5';
import 'p5/lib/addons/p5.sound';
import 'p5/lib/addons/p5.dom';

Then I load them to the window inside my sketch:

const sketch = (p5) => {
   window.p5 = p5;
   ...
}
new p5(sketch);

When I try to use:

amp = new p5.Amplitude()

I get a 'p5.Amplitude is not a constructor' error. My prediction is that there is a conflict between naming the library p5 on the window and using the constructors from the library that use p5.something like p5.Amplitude, p5.Vector, p5.Soundfile. I have not been able to find a workaround to using these objects or constructors within instance mode. I am however able to use the methods from these objects that do not require a constructor. For example, loadSound() is a method of p5.Soundfile. The following works:

sound = p5.loadSound('assets/sound.wav)

but when I try console.log(p5.SoundFile) I get undefined.

I am lost!

like image 344
Julio Gudiño Avatar asked Sep 26 '16 00:09

Julio Gudiño


2 Answers

I'm not a JavaScript expert, but your syntax doesn't match the syntax on the instance mode page.

Specifically, what are you doing here?

const sketch = (p5) => {
   window.p5 = p5;
   ...
}
new p5(sketch);

Compare that to the syntax on the instance mode page:

var sketch = function (p) {
  var gray = 0; 

  p.setup = function () {
    p.createCanvas(600, 400);
  };

  p.draw = function () {
    p.background(gray);
    p.rect(p.width/2, p.height/2, 200, 200);
  };

  p.mousePressed = function () {
    gray = (gray + 16) % 256;
  };
};

new p5(sketch);

It looks like your code is redefining the p5 variable, which is going to cause the kinds of problems you're seeing. I would rewrite your code to no longer redefine the p5 variable, and use the syntax from the instance mode page instead:

var sketch = function(p) {
   //your code here
   //but don't change the p5 variable!
}
new p5(sketch);
like image 131
Kevin Workman Avatar answered Oct 15 '22 17:10

Kevin Workman


You're correct that you're overwriting the p5 class provided by the library with the instance that's provided to your code upon construction.

This should work:

import p5 from 'p5';
import 'p5/lib/addons/p5.sound';

const sketch = (p5) => {
   window.myp5 = p5;

   p5.setup = () => {
     //whatever
   };

   p5.draw = draw;
}

function draw() {
  //methods hang off the instance:
  const mysound = myp5.loadSound("/path/to/sound.mp3");
  //constructors hang off the class:
  const amp = new p5.Amplitude()
}
new p5(sketch);

Note that myp5 is available to the draw function because of the assignment at the beginning of the sketch function. Also note that you shouldn't need to import the addons.

like image 27
nvioli Avatar answered Oct 15 '22 19:10

nvioli