Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update synth instance instead of spawning a new one? #71

Closed
hems opened this issue Nov 30, 2019 · 10 comments
Closed

update synth instance instead of spawning a new one? #71

hems opened this issue Nov 30, 2019 · 10 comments
Labels

Comments

@hems
Copy link

hems commented Nov 30, 2019

First of all, absolutely great work! Really impressive ! 🍺

On the example i'm trying to create i would like to have my SineOSC always playing and instead of spawning a new instance i would like to update the "freq" parameter..

For instance:

  sc.server.boot().then( async (server) => {
    const sine = server.synthDef(
      "sine",
      `
        SynthDef("sine", { arg out=0, freq=400;
          var zout;

          zout = SinOsc.ar([freq, freq], 0, 0.2);

          // zout = zout * EnvGen.kr( 
          //   Env.adsr(0, 0.1, 0, 0),
          //   doneAction: 2
          // );

          Out.ar(out, zout);
        });
      `,
    );

    const instance = await server.synth(sine, {
      freq: 440 * Math.random(),
      releaseTime: 0.001
    });

    setInterval(() => {
      instance.set("\freq", Math.random() * 100)
    }, 500);

  } )

Unfortunately, I'm getting an error: "Error: Unmatched type: req".

I'm sure i'm missing something.. What would be the right way to go about it?

Thank You!

@crucialfelix
Copy link
Owner

crucialfelix commented Nov 30, 2019 via email

@crucialfelix
Copy link
Owner

To clarify a bit more (now that I'm not on mobile):

The Supercollider language has Symbols that are written as: \freq or 'freq'

In JavaScript you just want a simple string, and by writing \freq you got a 4 character string with an unprintable first character:

Screen Shot 2019-12-05 at 9 34 10 AM

Not quite ready, but this would be the dryadic version:

const { Synth } = require("supercolliderjs").dryads;

import { interval } from "baconjs";

const sy = Synth.fromSource(`|freq=400| SinOsc.ar([freq, freq], 0, 0.2)`);

const i = interval(500).map(() => {
  return { freq: Math.random() * 100 };
});

sy.setStream(i);

export default sy;

With all the Bacon stream functions: https://baconjs.github.io/api3/classes/eventstream.html

@hems
Copy link
Author

hems commented Dec 6, 2019

thanks for the example @crucialfelix !

Unfortunately, I'm having a hard time with the "set" function, here is a standalone version i baked together to illustrate.

const sc = require("supercolliderjs");

startLang = async () => {
  sc.lang.boot().then( async (lang) => {

    const pyr8 = await lang.interpret(`

      Server.default.options.outDevice_("Midas FW");
      Server.default.options.numOutputBusChannels(32);

    `);

  } )
}

startServer = async() => {

  sc.server.boot().then( async (server) => {
    const sine = server.synthDef(
      "sine",
      `
        SynthDef("sine", { arg out=0, freq=400;
          var zout;

          zout = SinOsc.ar([freq, freq], 0, 0.2);

          Out.ar(out, zout);
        });
      `,
    );

    const instance = await server.synth(sine, {
      //freq: 440 * Math.random(),
      //releaseTime: 0.001
    });

    setInterval(() => {
      instance.set("freq", Math.random() * 100)
    }, 500);

  } )
}

work = async () => {
  await startLang()

  await startServer()
}

work()

this will yield the error: "Unmatched type: freq", as you can see on this logs:

/Users/h/git/hz/supercolliderjs-tests/node_modules/@supercollider/server/lib/osc/msg.js:24
    throw new Error(`Unmatched type: ${pairs}`);
    ^

Error: Unmatched type: freq
    at flattenPairs (/Users/h/git/hz/supercolliderjs-tests/node_modules/@supercollider/server/lib/osc/msg.js:24:11)
    at Object.nodeSet (/Users/h/git/hz/supercolliderjs-tests/node_modules/@supercollider/server/lib/osc/msg.js:250:34)
    at Synth.set (/Users/h/git/hz/supercolliderjs-tests/node_modules/@supercollider/server-plus/lib/ServerPlus.js:44:43)
    at Timeout._onTimeout (/Users/h/git/hz/supercolliderjs-tests/src/test.js:43:16)
    at listOnTimeout (internal/timers.js:531:17)
    at processTimers (internal/timers.js:475:7)

@crucialfelix
Copy link
Owner

crucialfelix commented Dec 6, 2019

Ah, I should have looked more carefully.

   * synth.set({freq: 441, amp: 0.9});

It should take a {freq: 440}

Note that you can send many param changes at once.

I will make that throw a TypeError with a proper message.

  throw new TypeError(
    `Received ${typeof pairs} ${JSON.stringify(pairs)}.` + "Expected {key: value} or [[key, value],...]",
  );

that would post:

TypeError: Received string "freq". Expected {key: value} or [[key, value], ...]

@crucialfelix crucialfelix reopened this Dec 6, 2019
@crucialfelix
Copy link
Owner

I still need to fix the documentation generator. This is pretty useless: https://crucialfelix.github.io/supercolliderjs/packages/server-plus/docs/classes/_serverplus_.serverplus.html#synth

Because the Synth class that it returns is not exported, it's not in the docs.

And the formatting of that those TypeDocs is kind of ugly.

Most of the time I use VSCode so I can just option hover / option click on anything and I see docs. But it needs to be published too.

@hems
Copy link
Author

hems commented Dec 6, 2019

Most of the time I use VSCode so I can just option hover / option click on anything and I see docs. But it needs to be published too.

great.. it takes an object, i should have tried that!

Also, I was using vim so i didn't have those code navigation features, but considering you used typ script it makes sense to use VSCode to benefit from all the hints!

thank you once again, great work.

@hems
Copy link
Author

hems commented Dec 6, 2019

It worked!! 🍻

Another question I have - which perhaps should be in another issue - is there an easy way to sample the amplitude of that Sine so i could use to LFO some variables on my JS code?

Effectively I would then be modulating my JS code ( for instance a 3D object on WebGL ) with LFOs from Supercollider... So exciting!!

@hems
Copy link
Author

hems commented Dec 6, 2019

You triggering so many questions in my mind with this library : D

I have like 100 of them now

@crucialfelix
Copy link
Owner

I would expect VIM has a TypeScript / Language Server package. But VSCode has been killing it lately. I use the VIM bindings (not perfect).

With classic supercollider and my older crucial library I used to do a lot of polling and triggering. Inside a Patch you could do lfo.onTrig(scfunction)

There is Poll http://danielnouri.org/docs/SuperColliderHelp/UGens/Triggers/Poll.html which can send a trig back to the client.

The dryadic components will be able to support some really interesting cross communication like that. It would just come back as a stream and then you can filter or map that and plug it into other things.

Another use of Dryadic I've dreamed up is that the event/stream system can be connected to from any remote client via a websocket. So you can have a separate browser based app with webgl etc. and it can easily communicate back and forth with the node app. The web app can use Dryad classes and it messages back to the node app to update while playing.

I have like 100 of them now

Please let me know! At least I can figure out how to make the docs and development open enough that people can contribute and build things.

@hems
Copy link
Author

hems commented Dec 9, 2019

I would expect VIM has a TypeScript / Language Server package. But VSCode has been killing it lately. I use the VIM bindings (not perfect).

it does but indeed VSCode with a few tweaks is working pretty well..

With classic supercollider and my older crucial library I used to do a lot of polling and triggering. Inside a Patch you could do lfo.onTrig(scfunction)

There is Poll http://danielnouri.org/docs/SuperColliderHelp/UGens/Triggers/Poll.html which can send a trig back to the client.

yes that is super sweet! so basically we would set the "LFO" to be the "in" and a Pulse wave to be the "sampling rate" and wait for the messages on the client side with something similar to the OSCresponderNode...

The dryadic components will be able to support some really interesting cross communication like that. It would just come back as a stream and then you can filter or map that and plug it into other things.

that sound super amazing, i can't wait!

Another use of Dryadic I've dreamed up is that the event/stream system can be connected to from any remote client via a websocket. So you can have a separate browser based app with webgl etc. and it can easily communicate back and forth with the node app. The web app can use Dryad classes and it messages back to the node app to update while playing.

Yes, that's super sweet. Actually the code i'm writing right now have some WebGL elements moving on the screen and i wanted to make their rotation to be a function of SuperCollider's LFO's amplitude....

I have like 100 of them now

really looking forward to check this out..

Please let me know! At least I can figure out how to make the docs and development open enough that people can contribute and build things.

Great, ping me anytime you would like me to have a look or try something out. I don't have such a deep understanding of the supercollider server as you do, but hopefully i can be helpful by reviewing/trying out examples, giving feedback and hopefully writing some code.

once again thanks a lot for such awesome work!

☮️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants