Cabbage Logo
Back to Cabbage Site

How can I link Play/Stop buttons to trigger Score events?

I have an instr set up that runs in Csound Android. I’ve designed a front end in the Android version of Cabbage, I’ve set up everything but now want to bring in the instr.

The current Cabbage instr I have temporarily uses a trigger to activate a simple osc and LED but I would like it to activate a score event. It appears I probably should use event_i in a seperate instr to trigger the one I want to add. So essentially I’m starting with this:

instr 1
gkKickVol chnget"KickVol"
gkPlay chnget"Play"
gkStop chnget"Stop"
if trigger(gkPlay,0.5,0)==1 then
gkOnOff = 1
elseif trigger(gkStop,0.5,0)==1 then
gkOnOff = 0
endif

aSig oscil gkOnOff/2*gkKickVol, 440
outs aSig, aSig

;Metronome LED
kActive = 1
kNonActive = 0
if gkOnOff==1 then
chnset kActive,“LED”
elseif gkOnOff==0 then
chnset kNonActive,“LED”
endif
endin

This works fine. Now I need to alter this so that the Play and Stop buttons activate triggers in another instrument. This is the instr currently in a seperate csd:

sr = 44100 ksmps = 32 nchnls = 2 0dbfs = 1

giBPM init 0.01666667*92
giMeasure init 1/4
gaRvbSend init 0

instr Kick ; trigger Kick
ktrigger metro giBPMgiMeasurep4
schedkwhen ktrigger, 0, 0, 4, 0, 0.1, 0, p5
endin

Any suggestions as to how to link the Play/Stop buttons in the existing Cabbage instr to activate the Kick instr would be appreciated.

PS the above line for Kick should read giBPM times giMeasure etc. but for some odd reason I can not get it to show properly in this post. Is there a proper way to accomplish this? Will uploaded csd files show in this window?

You need to select the code and then press the </> button in the editor field.

Now to your question :slight_smile:

You can just use a conditional to test whether the instrument should play or not. If the kick instrument is always being triggered, to stop it from sounding you can just do something like this:

instr Kick
    kEnabled chnget "PlayKick"
    if kEnabled == 1 then
    ...
    endif
endin

I’m not sure I’ve answered your question, feel free to correct me if I misunderstood :+1:

Hi Rory. I have a Csound instument that requires the score be triggered to start, it’s a Polyrhythms
drum kit, essentially a multi drum metronome that can be tweaked to play each drum in any subdivision wanted (ex. Kick 3 times a measure, snare 5 times and hats 7 etc.

I have set up Play And Stop buttons in Cabbage that function, I have tested them.

In Csound for Android there’s a Play button that starts the Score and script playing. In Cabbage, how can I use the Play and Stop buttons I set up to start and stop the score?

There are 5 score events like this:

i"Kick" 0 3600 8 .4 ; start drum machine, trigger instr

I want the Cabbage Play and Stop buttons to start and stop the Score when desired, Play should always restart the score from the beginning.

Ok, I almost have it. This code almost works:

<CsoundSynthesizer>                                                    
<CsOptions>                                                            
;-odac
-d -n                                                                  
</CsOptions>                                                           
<CsInstruments>  
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1

gkOnOff	  init	0

instr 1
gkPlay	  chnget"Play"
gkStop	  chnget"Stop"
    if trigger(gkPlay,0.5,0)==1 then
	 gkOnOff	=	1
    elseif trigger(gkStop,0.5,0)==1 then
	 gkOnOff	=	0
  endif

if gkOnOff==1 then
      	  event_i "i", 2, 0, 5
	elseif gkOnOff==0 then
      	  event_i "i", 2, 0, 0
	endif	
endin
	
instr 2
gkClick   chnget"Click"
gkPlay    chnget"Play"
gkStop	  chnget"Stop"
	if trigger(gkPlay,0.5,0)==1 then
	 gkOnOff	=	1
	elseif trigger(gkStop,0.5,0)==1 then
	 gkOnOff	=	0
	endif

aSig   oscil   gkOnOff/2*gkClick, 440
    outs aSig, aSig

;Metronome LED
kActive	=	1
kNonActive	=	0
	if gkOnOff==1 then
      	  chnset kActive,"LED"	  
	elseif gkOnOff==0 then
      	  chnset kNonActive, "LED"	 
	endif	
endin
</CsInstruments>
<CsScore>
i 1 0 3600
</CsScore>
</CsoundSynthesizer>

So the osc does play for 5 seconds. Of course it will later be be set to a higher value, this was just to test it to see if the osc was in fact starting sgain or just continued to play. If I set

event_i "i", 2, 0, 3600

instead of

event_i "i", 2, 0, 5

then I can’t tell if instr 2 is starting again or just continuing to play.

The problem now is when I press Play again nothing happens.

How can I change this so every time I press Play it triggers instr 2 to start again, but it must start at a 0 time so all drums start synchronized.

A little closer. Changed from event_i to schedulekwhen and moved that up to “if trigger” etc.

I can tell it starts over as the aEnv of instr 2 is now working. There are still 2 main issues:

  1. If I press Play it will play for 5 sec, but if I press Stop and then Play again before 5 sec has passed the env does not work. This is important because it means it is not resetting until p3 has finished which will be unacceptable for a polyrhythm app that needs to retrigger all drum instruments simultaneously.

  2. If Play is pressed before the csd has been loaded for 5 sec the aEnv does not work which would indicate that for some reason as soon as the csd is loaded it starts playing, it’s just not audible.

For the second schedulekwhen I used -2 for the instr number which I thought was supposed to turn off an instrument but I guess I was mistaken.

From the Csound manual on schedulekwhen:

kmaxnum – maximum number of simultaneous instances of instrument kinsnum allowed. If the number of existant instances of kinsnum is >= kmaxnum , no new event is generated. If kmaxnum is <= 0, it is not used to limit event generation. If the kinsnum is negative (to turn off an instrument), this test is bypassed.

I need to try to resolve this before bringing in the polyrhythm code or my brain might explode from TMI on the page at once :crazy_face:

P.S. I tried like 20 times to select all the code (like all the upper Cabbage code and there was no way this edit window was going to show it correctly. Even The 2 times I did manage to select all the code the </> did not function correctly. For that reason I have attached the csd as well.Poly.csd (3.4 KB)

<CsoundSynthesizer>                                                    
<CsOptions>                                                            
;-odac
-d -n                                                                  
</CsOptions>                                                           
<CsInstruments>  
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1
                                               
instr	1
; Play/Stop
	gkOnOff		init	0
; gkPlay    init 0
	gkPlay		 chnget	"Play"
	gkStop		 chnget	"Stop"
 gkClick  chnget"Click"
 
	if trigger(gkPlay,0.5,0)==1 then
	       gkOnOff	=	1
        schedkwhen  1,  0, 1,  2, 0, 5
	elseif trigger(gkStop,0.5,0)==1 then
	       gkOnOff	=	0
        schedkwhen  1,  0, 2,  -2, 0, 0
	endif

;   LED
kActive	=	1
kNonActive	=	0
	if gkOnOff==1 then
	       chnset kActive,"LED"	 
	 elseif gkOnOff==0 then
     	  chnset kNonActive,"LED"
        
	 endif	
endin

instr 2
aEnv   linseg     0, 2, 1, p3, 1, 0
aSig   oscil  gkOnOff/2*gkClick , 440
    outs aSig*aEnv, aSig*aEnv
endin

</CsInstruments>
<CsScore>
i 1 0 3600
</CsScore>
</CsoundSynthesizer>

event_i is for i-time operations only. If you want to use an event opcode that runs like schedkwhen, just use event. It seems a little much to use two buttons, one for on and one for off, when buttons are toggles anyway? I’ve simplified your code and pasted it below. Note I never had much luck with sending negative p3 values to the event opcodes, I usually use turnoff2 instead to kill and instance of an instrument. I’ve replaced the sounds in instr 2 with some printing info to help debug what’s happening.

<Cabbage>
form caption("Polyrhythms") size(615, 250), pluginID("bast"), guirefresh(64)
file(brushedsteel4.jpg)
image bounds(  0,  0,615,210), colour(140, 160, 180), shape("sharp"), outlinecolour("white"), line(4)

#define RSliderStyle # trackercolour(255,255,255),  trackerOutsideRadius(1),  colour(  0, 55,100), textcolour(0,0,0), outlinecolour(50,50,50)#

rslider bounds(45, 20, 70, 70),  text("BPM"), channel("Tempo"), range(20, 220, 120, 1, 1),  $RSliderStyle
rslider bounds(135, 20, 70, 70),  text("Click Vol"), channel("Click"), range(0, 1, .5, 1, .05),  $RSliderStyle
rslider bounds(225, 20, 70, 70),  text("Kick Vol"), channel("Kick"), range(0, 1, .5, 1, .05),  $RSliderStyle
rslider bounds(315, 20, 70, 70),  text("Snare Vol"), channel("Snare"), range(0, 1, .5, 1, .05),  $RSliderStyle
rslider bounds(405, 20, 70, 70),  text("HiHat Vol"), channel("HiHat"), range(0, 1, .5, 1, .05),  $RSliderStyle
rslider bounds(495 , 20, 70, 70),  text("Ride Vol"), channel("Ride"), range(0, 1, .5, 1, .05),  $RSliderStyle

; LEDS
checkbox bounds(168,  10,  5,  5), channel("LED1"),  value(0), colour("yellow"), shape("ellipse")
checkbox bounds(258,  10,  5,  5), channel("LED2"),  value(0), colour("yellow"), shape("ellipse")
checkbox bounds(348,  10,  5,  5), channel("LED3"),  value(0), colour("yellow"), shape("ellipse")
checkbox bounds(438,  10,  5,  5), channel("LED4"),  value(0), colour("yellow"), shape("ellipse")
checkbox bounds(528,  10,  5,  5), channel("LED5"),  value(0), colour("yellow"), shape("ellipse")

; Metronome and LED
label bounds( 40, 100, 80, 12), text("Metronome"), fontcolour("black"), FontColour("black")
;checkbox bounds( 74,115, 12, 12), channel("OnBeat"),  value(0)
checkbox bounds(68, 116, 20, 20), channel("LED"), value(0), colour(0, 155, 255 ), shape("ellipse")

; Play and Stop
button  bounds( 40,145, 80, 25), fontcolour:0(205,255,205), fontcolour:1(205,255,205), colour:0(0,150,0), colour:1(0,30,0), text("Play","Stop"), channel("Play"), latched(1), radiogroup(1), identchannel("PlayButton")
</Cabbage>                                                             

<CsoundSynthesizer>                                                    
<CsOptions>                                                            
;-odac
-d -n                                                                  
</CsOptions>                                                           
<CsInstruments>  
sr = 44100
ksmps = 32
nchnls = 2
0dbfs = 1
                                               
instr	1

	kPlay		 chnget	"Play"
	kStop		 chnget	"Stop"
    kClick  chnget"Click"
 
	if changed(kPlay)==1 then
	    if kPlay == 1  then 
	        event "i", 2, 0, 3600
	        chnset k(1),"LED"	 
	    else
	        turnoff2 2, 1, 1
	        chnset k(0),"LED"
	    endif
	endif

endin

instr 2
    prints "Started"
    if release() == 1 then
    printks "Ended", 1
    endif
endin

</CsInstruments>
<CsScore>
i 1 0 3600
</CsScore>
</CsoundSynthesizer>

p.s. I’m not sure why you are struggling to format the code? This is how I do it?

1 Like

First off, thank you!

So the problem here is I have no computer, it died and at this moment can’t afford a new one so everything is being done on an Android phone.
I’m using the old Cabbage for Android (therefore it only plays but has no console for debugging, editing etc.) and Csound for Android. Kinda sucks but it is what it is… at least it works. So to run you’re example with printks had to load it into Csound but it didn’t print. Why? No idea.

When I tried your code in Cabbage even the LED did not work. Again no idea why, maybe it doesn’t like functional syntax or something? I’ll have to experiment to see

I really hope that eventually DEVs start taking the Android OS a little more seriously at some point, the are several billion potential users out there that might be more inclined to use Csound if it weren’t so cumbersome in Android. And Cabbage has the only decent front end, the one in Csound is functional but… long story.

Nonetheless irrelevant, by simply switching my original (sloppy) code to use event instead of event_i - bingo. I feel kinda dumb now that I didn’t try that! And turnoff2? :+1:I just started coding for the first time in my life about a month ago and that’s Csound, but I had recently read the FLOSS bit about i vs k variable… so this has been yet another valuable learning experience.

As for getting code to show properly here, it’s because the phone sucks for selecting it. I have the same issue with other pages.

Thanks again :v:, inevitably I’ll be back with more noob questions!

Well, after some reading I figured out why your example wasn’t working for me, it’s because the button definition still had
radiogroup(1)
I deleted that and all is fine. This Csound stuff is finicky, one missing , or an extra . and the code doesn’t work! And for me the added difficulty is that Csound Android only debugs below
<CsoundSynthesizer>
It wants nothing to do with the upper Cabbage code.

Now I need a :beer: before I insanely work beyond my abilities and attempt to finish the Polythythms csd :stuck_out_tongue_winking_eye:

Gees, you’re doing this the had way for sure! Have you though about using the online Csound IDE to help? I think it might give better result than the Csound Android app? And yes, I must keep in mind that the version of Csound bundled with that old Cabbage Android app is quite old. You might be right about the functional stuff, it might not have been implemented in that version.

1 Like

Ok, here’s the beta.

2 small issues:

  1. I can’t figure out how to make the vslider values visible
  2. The ride doesn’t make any sound. It works in Csound for Android. If I paste the HiHat code in instead it works. Can you check that? Is it possible one of the opcodes I used didn’t work in that version of Cabbage maybe? The fact everything still runs would indicate there are no errors so I have no idea what’s going on there.

And a question you may or may not have the answer to offhand… will samples work for this?

For now I’ve just used synth drums (I borrowed and modified some from Iain and wrote others).

Cheers.
Polyrhythm.csd (8.2 KB)

You haven’t defined function table 1 for foscil is the error I get. If it works with Csound for Android then you must be declaring that function table. Also, you’re not using the “Ride” value at all, even though you are getting the value from that channel.

You can try putting in valueTextBox(1), but considering this is a much older version of Cabbage, you might try valuetextbox(1)

No, I don’t think so. Android is really awkward about loading samples. You can try it, but finding the right path to the samples might be difficult.

1 Like

You were correct, thank you, I forgot to add the ride f table. I sometimes have to have 2 versions, one that runs in Csound, to debug, edit and listen to, which can’t have widgets active in the code which is why the Ride channel value wasn’t yet hooked up.

And yes, it works great great with samples. No path necessary as long as they are in the CabbageFiles directory along with the csd.

I should have stated the vslider values are “visible” so to speak, but if you look carefully at the pic above you’ll see they are extremely faint. I simply could find no option to alter the colour. Not a big deal, I just opted to go with a semi-black background although if there is a solution would be nice to know for future reference.

And fyi, I really tightened up the sloppy code, at least to the best of my current abilities. Functional syntax also does work.

You’ve been super helpful, thanks for everything.

P.S. The SpookEPad you wrote that came with the Android beta is very cool.

That SpookEpad is based on an instrument @Oeyvind posted somewhere once upon a time. I just updated it and added a UI :slight_smile: