SuperCollider Forum
May 21, 2013, 05:20:38 PM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: The SuperCollider forum is currently experiencing a rash of spambot registrations. New user requests may not be approved quickly as a result -- and if your email address looks like spam, it might not be approved at all. We are working to improve the security of the registration process, and to provide alternate means to contact the administrators to get a new account. Thanks for your patience.
 
   Home   Help Search Calendar Login Register  
Pages: [1]
  Print  
Author Topic: A little help needed with a home-brewed synth gate quantize  (Read 2694 times)
0 Members and 1 Guest are viewing this topic.
bitbutter
Newbie
*

Karma: 0
Posts: 20


View Profile
« on: August 29, 2008, 03:25:18 PM »

What I've been trying to do is set up one synth (metronome) that plays a regular impulse click, and write another synthdef (quantisedbeep) in such a way that when its told to start or stop playing (via set instructions sent to its gate), it waits until the following metronome click to start or stop the sound.

I thought i could do this by piping the metronome click to a specific audio bus, and referring to this same bus in the quantisedbeep synthdef. I thought i could use a resetable flipflop gate (SetResetFF) to listen to the combination of gate value and metronome bus and transform it into an appropriately quantized gate trigger. But with the configuration i thought would work, i get silence from the quantisedbeep synth. The SetResetFF routine seems to be the culprit. Code follows:

Code:
(
var metronome_bus;
s = Server.local;
s.reboot;
s.waitForBoot({

// A metronomic pulse that beeps should be quantized to.
SynthDef("metronome", { arg hz,metronome_bus_index;
var im=Impulse.ar(hz, 0.0, 1);
OffsetOut.ar(metronome_bus_index,im);
Out.ar(0,im);
}).send(s);

// Beeps to be synchronised with the metronome pulse
SynthDef("quantisedbeep", { arg gate=1,metronome_bus_index;

// quantize gate changes to snap to metronome pulses
var quantisedgate=SetResetFF.ar(
(In.ar(metronome_bus_index)),
(gate-1).abs
);

var env=Env.asr(0.005, 0.5, 0.005, 1, 'linear');
var env_gen=EnvGen.kr(env, gate: quantisedgate, doneAction: 2);
var sine = SinOsc.ar(900,0,0.5);
var note = (sine)*(env_gen);
Out.ar(0,note);
}).send(s);

SystemClock.sched(0.5,
{
m=Bus.audio(s);
t=Synth(\metronome,[\hz,1,\metronome_bus,m.index]);}
);

})
)

(
// Run this manually in between clicks. The note should begin on the following click.
s=Synth("quantisedbeep",[\metronome_bus_index,m.index]);
)

Can anyone see something obvious that i'm doing wrong here? thanks!
Logged
dewdrop_world
AdminGroup
Full Member
*

Karma: 9
Posts: 193



View Profile WWW
« Reply #1 on: September 02, 2008, 12:20:28 PM »

I was offline (out of town) for a few days so I missed this...

My thought is to use a timed trigger (Trig or Trig1) to hold the manual trigger's value for some amount of time. That would look like a square envelope -- jump up to some nonzero value, then jump back to 0. Multiplying that signal by the clock trigger gives you a single impulse trigger that is in sync with the clock. When the timed trigger falls back to 0, clock triggers would be suppressed.

The timed trigger should hold for just a bit less than the time between clock triggers.

Gotta run to a meeting... post if you have trouble and I can try to come up with a quick code example.

James
Logged

bitbutter
Newbie
*

Karma: 0
Posts: 20


View Profile
« Reply #2 on: September 10, 2008, 12:33:15 PM »

Hi James

Thanks for your suggestion. One of those rare periods without a computer nearby meant i couldn't try this out sooner. Here's my stab at implementing what you described. Your description makes sense to me, but I'm going wrong somewhere.

With the following code, the metronome ticks away, but when i run the line to generate a quantizedbleep synth, no beep is heard. I guess the gate isn't being opened properly (?). I'm using a SetResetFF toggle here with the idea of quantizing gate=0 messages too, as the next step.

Can you see where i'm going wrong?

Code:
(
var metronome_bus;
s = Server.local;
s.reboot;
s.waitForBoot({

// A metronomic pulse
SynthDef("metronome", { arg hz,metronome_bus;
var im=Impulse.ar(hz, 0.0, 1);
OffsetOut.ar(metronome_bus,im);
Out.ar(0,im);
}).send(s);

// Beeps should be quantized to be synchronised with the metronome pulse
SynthDef("quantisedbeep", { arg gate=1,metronome_bus;
var quantizedgate=SetResetFF.ar(
Trig.ar(gate,0.9)*(In.ar(metronome_bus)),
0
);
var env=Env.asr(0.005, 0.5, 0.005, 1, 'linear');
var env_gen=EnvGen.kr(env, gate: quantizedgate, doneAction: 2);
var sine = SinOsc.ar(900,0,0.5);
var note = (sine)*(env_gen);
Out.ar(0,note);
}).send(s);

SystemClock.sched(0.5,
{
m=Bus.audio(s);
t=Synth(\metronome,[\hz,1,\metronome_bus,m]);}
);

})
)

(
// Run this manually in between clicks. The note should begin on the following click.
s=Synth("quantisedbeep",[\metronome_bus,m]);
)
Logged
dewdrop_world
AdminGroup
Full Member
*

Karma: 9
Posts: 193



View Profile WWW
« Reply #3 on: September 11, 2008, 01:11:37 PM »

I think this is an order of execution problem -- by default, new synths are placed at the head of the target group. So, the quantizedbeep synth is trying to read the trigger from a later synth (metronome), but by design the In ugen is aware only of signals occurring earlier in the synthesis chain.

Try creating the quantizedbeep synth using addAction: \addToTail.

s=Synth("quantisedbeep",[\metronome_bus,m], addAction: \addToTail);

That will put the new synth at the tail of the group, after any other synths (including the metronome).

There's a help file on order of execution, linked in from the main help page, highly recommended reading.

Just a side note -- it's an unwritten convention that the interpreter variable "s" is usually reserved for the server. If you overwrite it with a synth, you'll be in for an unpleasant surprise if you do, for example, Buffer.alloc(s, 1024, 1) -- you could get around it by typing Buffer.alloc(Server.default, 1024, 1) but who wants to go to all that trouble? Smiley

James
Logged

bitbutter
Newbie
*

Karma: 0
Posts: 20


View Profile
« Reply #4 on: September 15, 2008, 09:56:49 AM »

Thanks very much James, that's exactly the information i needed. I read up about execution order. Here's the working test code:
Code:
(
var metronome_bus;
s = Server.local;
s.reboot;
s.waitForBoot({

// A metronomic pulse
SynthDef("metronome", { arg hz,metronome_bus;
var im=Impulse.ar(hz, 0.0, 1);
OffsetOut.ar(metronome_bus,im);
Out.ar(0,im);
}).send(s);

// Beep note on/note offs should be carried out on the next metronome tick
SynthDef("quantisedbeep", { arg gate=1,metronome_bus;
var quantizedgate=SetResetFF.ar(
Trig.ar(gate,0.9)*(In.ar(metronome_bus)),
Trig.ar((gate-1).abs,0.9)*(In.ar(metronome_bus))
);
var env=Env.asr(0.005, 0.5, 0.005, 1, 'linear');
var env_gen=EnvGen.kr(env, gate: quantizedgate, doneAction: 2);
var sine = SinOsc.ar(900,0,0.5);
var note = (sine)*(env_gen);
Out.ar(0,note);
}).send(s);

SystemClock.sched(0.5,
{
m=Bus.audio(s);
t=Synth(\metronome,[\hz,1,\metronome_bus,m]);}
);

})
)

(
// run these manually inbetween clicks. The note should begin or end on the following click.
x=Synth("quantisedbeep",[\metronome_bus,m], s, \addToTail);
x.set(\gate,0);
)
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.4 | SMF © 2006-2007, Simple Machines LLC Valid XHTML 1.0! Valid CSS!