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

3

9

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!

Mamiemamma answered 26/9, 2016 at 0:36 Comment(0)
S
4

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);
Splenectomy answered 26/9, 2016 at 0:46 Comment(3)
Thanks for the response Kevin. I use window.p5 = p5 to be able to load the library using es6 modules. With the latter I am making the library available in the window after using import p5 from '....'. I am able to use the rest of the functionality just like instance mode using p5 instead of p. Def not a javascript expert either, but I based this decision based on this project which seems to pull it off smoothly. Cheers!Divisible
I struggled for hours trying to get p5.js to work with es6 module syntax, until I found your answer, Kevin. Works great!Trothplight
I raised a similar issue here that follows a similar solution like what you proposed here... stackoverflow.com/questions/64887033/… I'm able to get function calls like .loadSound() to work but not constructor eg: .Envelope() do you know why?Pedalfer
T
1

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.

Transliterate answered 23/6, 2017 at 18:28 Comment(1)
I raised a similar issue here that follows a similar solution like what you proposed here... #64887533 I'm able to get function calls like .loadSound() to work but not constructor eg: .Envelope() do you know why?Pedalfer
C
1

I think I figured out our problems. You need to use p5.sound library from version 0.9.0 and place it in your project's directory. I explain more fully in my answer here:

How to import and utilize P5.Sound in Vue?

Cracked answered 24/5, 2020 at 17:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.