I can't seem to find any example code that shows a DigitalIn triggering a synth, can anyone help shine some light?

So far, I'm getting that SynthDefs can use a button to set amplitude etc, but what about triggering a Synth, emulating pressing a chord or hitting a key on a keyboard?

My understanding is that the DigitalIn runs on the server, but synth triggering happens in the language. This example uses SendReply to send a message back from the server to the language and use AnalogIn to control the language. You could do something similar with DigitalIn.

    8 days later

    Is there anything further on this, I can't seem to get the DigitalIn to actually change anything from a synth —

    giuliomoro My understanding is that the DigitalIn runs on the server, but synth triggering happens in the language. This example uses SendReply to send a message back from the server to the language and use AnalogIn to control the language. You could do something similar with DigitalIn.

    Have you tried the approach suggested here? I don't know much at all about Sc, but this should work?

      giuliomoro yeah i've tried, analogue things work fine, but when it comes to digital it doesn't seem to work with triggering sounds or changing the amp of anything — Is this worth making an issue on the bela supercollider repo?

      giuliomoro Nice, I spoke to some others about it, but since DigitalIn is a Bela specific ugen, there's no documentation about it's ability to control anything within supercollider on Bela

      Fair enough, however I think this can be generalized to a "vanilla" Supercollider question as: "How do I trigger a synth on the language in response to SendReply()message from the server?"

      For something to happen on the server completely: similar examples would be in the MouseButton UGen documentation. That is basically a digital input, running on the server, just like DigitalIn on Bela.

      For more complex situations, like instantiating a new synth, you will have to use SendReply, to send an OSC message to the language, and instantiate the synth from the OSCFunc that reacts to the SendReply.

      Or, alternatively: use the Pause UGen in the synth you want to start/stop and route the DigitalIn to that (e.g. via a bus).

      And feel free to post your code, it is much easier to give advice if we can see the code that you are using to attempt what you want to achieve.

      Wicked - there is no documentation of AnalogIn or DigitalIn, so knowing what they can actually do with examples is really needed:

      Code i'm trying:

      		// 1am anger.
      		SynthDef(\shh, {
      			arg out=~outBack, t_trig=0;
      			var sound, env;
      			sound = Mix(LFPulse.ar(110*[1,5/2],0.0,0.5,0.2));
      			env = EnvGen.ar(Env.perc(0.02,0.2), t_trig);
      			sound = Pan2.ar(sound * env,0.0);
      			Out.ar(out, sound);
      		}, [\tr]).add;
      
      
      		~buttonMonitor = {
      			var d0 = DigitalIn.kr(0); // Digital pin 0 - Button
      			var d1 = DigitalIn.kr(1); // Digital pin 1 - Button
      			var d2 = DigitalIn.kr(2); // Digital pin 2 - Button
      			var d3 = DigitalIn.kr(3); // Digital pin 3 - Button
      
      			SendReply.kr(Impulse.kr(10), '/buttonMonitor', [d0, d1, d2, d3]);
      		}.play;
      
      
      		~button1 = 0;
      		~button2 = 0;
      		~button3 = 0;
      		~button4 = 1;
      
      		// Listen to the buttons
      		OSCdef('listenToButtons', {
      			arg msg;
      			// Buttons
      			~button1 = msg[3].asInteger;
      			~button2 = msg[4].asInteger;
      			~button3 = msg[5].asInteger;
      			~button4 = msg[6].asInteger;
      
      			["Buttons: " ++ ~button1, ~button2, ~button3, ~button4 ].postln;
      		}, '/buttonMonitor');
      
      
      
      		{
      			q = Synth(\shh);
       			q.set(\t_trig, Pfunc({~button3}));
      		};

      Trying to get any 'button' to actually trigger a sound, nothing seems to work and it's an endless hole of errors in the console.

      Trying to also trigger one sound in a sequence of buffers, so each button is the next buffer number, which is as simple as saying, have a DigitalIn choose from an array of numbers.

      Also, MouseButton is almost nothing like DigitalIn, in the sense that DigitalIn(0) is pin D0, but what are the extra values I can pass through to this like this example:

      { SinOsc.ar(MouseButton.kr(440, 740, 2), 0, 0.1) }.play;

      How do you replace MouseButton with DigitalIn in this example?

        5 days later

        Ok, four days into the Expo and I'd really love to introduce buffers into the code, the synths are ok, but could be improved with samples.

        This is the code i'm running, I'm trying to get the analogin to chose the buffer number, but 'Index not integer' is my problem.

        I found a crude way to change sounds on the fly without the bela exploding, but it means running the ugens for digitalin and analogin right in the synthdef.

        SynthDef(\samplePlaying, {
        	arg atk=0, sus=0, rel=3, c1=1, c2=(-1),
        	buf=0, rate=1, spos=0, freq=440, rq=1, bpfmix=0,
        	pan=0, amp=1, out=0;
        	var sig, env, sound, sample, 
        buffersAvailable=[0,1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19];
        	sample = Select.ar( ((0.4).linlin(0.01, 1, 0, 19).nearestInList(buffersAvailable)), buffersAvailable);
        	sound = b[\drum_kit][1 * sample];
        	
        	env = EnvGen.kr(Env([0,1,1,0], [atk, sus, rel], [c1,0,c2]), gate: 1 );
        	sig = PlayBuf.ar(1, sound, rate*BufRateScale.ir(sound), startPos:spos);
        	sig = XFade2.ar(sig, BPF.ar(sig, freq, rq, 1/rq.sqrt), bpfmix*2-1);
        	sig = sig * amp;
        	sig = Pan2.ar(sig, pan, amp);
        	Out.ar(out, sig);
        }).send(s);

        Whats the approach I should be taking to trigger this synth when a button is pressed and to map a sensor to choosing a new buffer number?

        ok, I think the issue may be with using Impulse to send over the messages.

        What if you change the button monitor to:

        ~buttonMonitor = {
        			var d0 = DigitalIn.kr(0); // Digital pin 0 - Button
        			var d1 = DigitalIn.kr(1); // Digital pin 1 - Button
        			var d2 = DigitalIn.kr(2); // Digital pin 2 - Button
        			var d3 = DigitalIn.kr(3); // Digital pin 3 - Button
        
        			SendReply.kr(Changed.kr(d0+d1+d2+d3), '/buttonMonitor', [d0, d1, d2, d3]);
        		}.play;

        Then a message gets sent each time one of the DigitalIn values changes, and not 10 times per second. With 10 times per second you may miss a button change.

        I'm also not entirely sure how you use Pfunc in your code, Pfunc is something you'd normally use in Patterns and would allow you to access the button value in a running pattern sequence, but the timing of when the button is then read is determined by the pattern, not by when the button value changes.

        But I think for your application, I would look at Dseq and use the button input as a trigger for the Demand.kr ugen (the button input can of course first be sent to a bus with Out.kr, and then read into your synth with In.kr, this is normal routing on the server). See the Dseq helpfile.

        PS, I forgot to turn on 'following' for this thread, so I didn't get notifications when new messages appeared. I'm not a regular visitor to the forum, but when I see an email message (which is generated when putting @... in a reply) I will try and go to the forum if I have the time.

        PPS, and yes, it would be great if there was incredibly extensive documentation on how to use UGens. We put in a lot of volunteer effort into making SuperCollider run on Bela and writing the UGens, writing basic helpfiles, and then in making basic examples, which are available as example projects in Bela, see e.g. https://github.com/BelaPlatform/Bela/blob/master/examples/12-SuperCollider/2-digital-in/_main.scd. So it is not like there is no documentation at all.

        DigitalIn is a UGen that produces a 1 or a 0 based on a button press. From there on it is regular supercollider usage. Of course, since Bela's strength is running everything on the server, rather than in the language, that does require a different thinking than most usual SuperCollider programming. I'd love to write an extensive tutorial on this, but I'd need to find time for this. But this is hard: I'm working as a freelancer with a bunch of other (paid) projects on my plate right now.

        eyeversuseye
        MouseButton.kr( lag: 0 ) would be the same as DigitalIn.kr

        A replacement would be:
        { SinOsc.ar( DigitalIn.kr( 0 ).lag(2).range(440,740), 0, 0.1 ) }.play

        Absolutely, I understand that writing software that is open-sourced and non-paid is time consuming and doesn't put food on the table, so I really appreciate your help on this.

        I'll give Changed.ar a try with triggering.

        An alternative way of asking this question, is how do we use DigitalIn to create a new synth and destroy the previous one - the machine i've built has a turnwheel that triggers a button with every rotation. I tried loading a buffer of 20 samples to trigger a new sample with every button press, but the walls i've hit are too tall for me to pass

        I think you are already quite close, change the synthdef to:

        SynthDef(\samplePlaying, {
        	arg atk=0, sus=0, rel=3, c1=1, c2=(-1),
        	firstbuf=0, rate=1, spos=0, freq=440, rq=1, bpfmix=0,
        	pan=0, amp=1, out=0;
        	var sig, env, sound, sample;
            var trig;
            var buffersAvailable=(0..19);
        	var bufseq;
            trig = DigitalIn.kr( 0 );
        	bufseq = Dseq( buffersAvailable, inf );
        	sample = Demand.kr( trig, 0, bufseq ) + firstbuf; // firstbuf is the index of the first buffer
        	
        	env = EnvGen.kr(Env([0,1,1,0], [atk, sus, rel], [c1,0,c2]), trig );
        	sig = PlayBuf.ar(1, sample, rate*BufRateScale.ir(sound), trig, startPos:spos);
        	sig = XFade2.ar(sig, BPF.ar(sig, freq, rq, 1/rq.sqrt), bpfmix*2-1);
        	sig = sig * amp;
        	sig = Pan2.ar(sig, pan, amp);
        	Out.ar(out, sig);
        }).send(s);

        Not tested, but should be something along those lines.

        It assumes that you load the samples into 20 consequetive buffers and you can pass firstbuf as an argument to set the bufnum of the first buffer. The DigitalIn will trigger changing to a new buffer, and starting to play the buffer and retriggering the envelope.

          nescivi Almost, but the error:

          The preceding error dump is for ERROR: Primitive '_BasicAt' failed.
          Index not an Integer

          appears, as i can't seem to get this:

          sample = Select.ar( ((0.4).linlin(0.01, 1, 0, 19).nearestInList(buffersAvailable)), buffersAvailable);

          To be an integer, no matter what I've tried