Tone.js icon indicating copy to clipboard operation
Tone.js copied to clipboard

Tone.Channel `send` and `receive`

Open stevebarakat opened this issue 3 years ago • 9 comments

When using a Tone.Channel's send and receive, is there a way to unsend? Similar to how connect and disconnect work?

stevebarakat avatar Jan 08 '23 12:01 stevebarakat

Channel.send() creates and returns a new Gain node, so it looks like calling .dispose() on that node will do the trick

jdanford avatar Jan 27 '23 22:01 jdanford

Yes, but I don't want to dispose it. I want to disconnect it so I can send it to a different channel.

With connect and disconnect you can connect a channel to a reverb then disconnect it from the reverb and connect it to a delay. That can be done on the fly, while the transport is playing. If I try to do that with send, I end up with the reverb and delay because there is no way to disconnect the reverb. Is there a way to re-create that node after it's disposed?

stevebarakat avatar Jan 28 '23 17:01 stevebarakat

Is there a reason you can't disconnect the returned node and call Channel.send() again with a different destination? I don't get the impression creating the Gain nodes is particularly expensive, or is there another issue?

Anyway, here's the whole method, so if you really want to reuse the returned node from the first send() call then you can disconnect it and connect it to the other bus, but that involves a private method so it's not best to rely on that.

send(name: string, volume: Decibels = 0): Gain<"decibels"> {
    const bus = this._getBus(name);
    const sendKnob = new Gain({
        context: this.context,
        units: "decibels",
        gain: volume,
    });
    this.connect(sendKnob);
    sendKnob.connect(bus);
    return sendKnob;
}

jdanford avatar Jan 30 '23 19:01 jdanford

@jdanford Do you mean doing channel.send.disconnect()?

stevebarakat avatar Jan 31 '23 01:01 stevebarakat

If you absolutely have to use the same node, something like this:

const sendNode = channel.send("reverb");
sendNode.disconnect();
const bus = channel._getBus("delay");
sendNode.connect(bus);

But if you don't want to rely on private methods that might change, this should do the trick:

const reverbSend = channel.send("reverb");
reverbSend.dispose();
const delaySend = channel.send("delay");

jdanford avatar Jan 31 '23 19:01 jdanford

Okay. I'll give that a shot and update you with the results. Thanks for the help!

stevebarakat avatar Feb 01 '23 20:02 stevebarakat

@jdanford When I try to do that I get a TypeScript error about dispose not being a property of reverbSend. Maybe I'm doing it wrong? I made a sandbox - https://stackblitz.com/edit/github-pxbyoa?file=src/components/Channels/ChannelStrip.tsx

stevebarakat avatar Feb 06 '23 18:02 stevebarakat

Okay so I don't have any experience with channels myself, I'm just reading the docs/code, but AFAICT they're for when your code is more spread out and you can't refer directly to other nodes. If you want to use channels, I think it would be something like this:

const reverb = new Reverb(3).toDestination();
const delay = new FeedbackDelay(5).toDestination();

const reverbChannel = new Channel({ volume: 0 });
const delayChannel = new Channel({ volume: 0 });

reverbChannel.connect(reverb);
delayChannel.connect(delay);

// assigns channel name, only needs to be called once
reverbChannel.receive("reverb");
delayChannel.receive("delay");

// keep this in state, a ref, etc.
let sendNode: GainNode | null = null;

// send to reverb
sendNode = channel.send("reverb"); 

// adjust send amount
sendNode.gain.value = 0.5;

// unsend to reverb, send to delay
sendNode.dispose();
sendNode = channel.send("delay");

// send nowhere
sendNode.dispose();
sendNode = null;

jdanford avatar Feb 07 '23 20:02 jdanford

Okay. I'll give that a shot. Thanks!

stevebarakat avatar Feb 07 '23 20:02 stevebarakat