Code Monkey home page Code Monkey logo

Comments (7)

SamiPerttu avatar SamiPerttu commented on May 19, 2024

Hi!

You can express it by using a branch:

let modulator = (sine_hz(1.0) + 1.0) * 0.5;
let synth = (saw_hz(100.0) | modulator >> (mul(3000.0) ^ mul(0.2))) >> moog();

In a generative spirit, a simple way to accomplish the same is a closure. However, in this case the deterministic pseudorandom phase system will assign different (random) initial phases for the two channels.

// Do not use this unless it is okay that frequency and Q have different phases!
let modulator = || (sine_hz(1.0) + 1.0) * 0.5;
let synth = (saw_hz(100.0) | modulator() * 3000.0 | modulator() * 0.2) >> moog();

Envelopes are not influenced by the pseudorandom phase system. A multichannel envelope is also fairly convenient:

let modulator = lfo(|t| {
    let m = (sin_hz(1.0, t) + 1.0) * 0.5;
    (m * 3000.0, m * 0.2)
});
let synth = (saw_hz(100.0) | modulator) >> moog();

As the modulator is consumed when used in an expression, it is not so simple to send it to different nodes altogether. I think duplicating the work by using a closure, maybe one that generates an envelope, is an okay way to get around this restriction:

let modulator = || lfo(|t| (sin_hz(1.0, t) + 1.0) * 0.5);
let synth = (saw_hz(100.0) | modulator() * 3000.0 | modulator() * 0.2) >> moog();

from fundsp.

vitreo12 avatar vitreo12 commented on May 19, 2024

Thanks for your answer!

I guess my main problem with the closure approaches is that we would actually be computing the modulator() sample twice, when only one sine would be sufficient. So, for this case, I would probably use your first example.

However, another question then pops to mind: would it be possible to "patch" the modulator to the inputs of two unrelated nodes?

from fundsp.

SamiPerttu avatar SamiPerttu commented on May 19, 2024

For two unrelated nodes, it's not possible - some mechanism is needed to coordinate the work done by the modulator in computing samples.

from fundsp.

vitreo12 avatar vitreo12 commented on May 19, 2024

I could probably solve it like this:

fn saw_moog(freq: f64, cutoff: f64, q: f64) -> An<impl AudioNode<Sample = f64, Inputs = U1, Outputs = U1>> {
    (saw_hz(freq) | pass() >> (mul(cutoff) ^ mul(q))) >> moog()
}

let modulator = (sine_hz(1.0) + 1.0) * 0.5;
let node = modulator >> (saw_moog(100.0, 3000.0, 0.4 ) ^ saw_moog(200.0, 1000.0, 0.2)) >> join::<U2>();

which I think is actually a very elegant way of expressing a DSP graph

from fundsp.

SamiPerttu avatar SamiPerttu commented on May 19, 2024

That's a nice way of expressing it! The join in the last line averages together the channels. If it's okay to sum instead, then it can be simplified a bit by using the bus operator:

let node = modulator >> (saw_moog(100.0, 3000.0, 0.4) & saw_moog(200.0, 1000.0, 0.2));

from fundsp.

vitreo12 avatar vitreo12 commented on May 19, 2024

This is even more elegant, thanks!

I have one more question: is there a way to achieve single sample feedback circuits? I see that there are the feedback and tick operators, but how would I feed the output of the feedback back to, for example, the frequency of the oscillator?

sine(440) ---> feedback ---> * 100
  ^                              |
  |                              |
   ------------------------------

from fundsp.

vitreo12 avatar vitreo12 commented on May 19, 2024

Something like this works (is it doing single sample feedback or block feedback?):

dc(440.0) >> feedback(sine() * 100.0) * 0.01;

Is there a way to get the output of the sine() instead of the feedback? This way I wouldn't have to scale the amplitude down.

EDIT:

I should read the docs a little better before posting, here's the solution:

dc(440.0) >> feedback2(sine(), mul(100.0));

from fundsp.

Related Issues (15)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.