Cabbage Logo
Back to Cabbage Site

Iterate through samples with knob

Hi everyone,

I simply try to iterate to a set of samples in WAV format with the help of a Cabbage Knob (each position represents one sample).
I use diskin2 and sprinfk to find and start a sample. My problem is, that it does not update the sample and play it. Only the first sample is played and it does not count up on the others and iterate.
Here is what I got so far:

<Cabbage>
form caption("Test") size(350, 200), guiMode("queue"), colour(58, 110, 182), pluginId("sfi1")
rslider bounds(20, 8, 60, 60)  range(1, 12, 1, 1, 1), channel("samples"), text("sample")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 -m0d 
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1

instr 1

   kSliderValue cabbageGetValue "samples"
   
printk2 kSliderValue

if changed(kSliderValue) == 1 then
SSample sprintfk "0%d.wav", kSliderValue ; kSliderValue should replace the value in sprinfk to new sample for example knob position 5 = 05.WAV
endif

a1 diskin2 SSample
 
prints  SSample
   
outs a1, a1

endin

</CsInstruments>
<CsScore>
i1 0 z
</CsScore>
</CsoundSynthesizer>

Thanks!

This might be because the file argument to diskin2 is i-rate. You might have better results if you trigger a sample instrument to play each time the sample changes :thinking:

perfect @rorywalsh ! thank you again!

here is the working code for everyone to use:

<Cabbage>
form caption("Test") size(350, 200), guiMode("queue"), colour(58, 110, 182), pluginId("sfi1")
rslider bounds(20, 8, 60, 60)  range(1, 12, 1, 1, 1), channel("samples"), text("sample")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 -m0d 
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1

instr 1

   kSliderValue cabbageGetValue "samples"
   
    printk2 kSliderValue
    
    if changed(kSliderValue) == 1 then
    event "i", 2, 0, -1, chnget:k("samples")
    endif
    endin
    
    instr 2
    kSliderValue cabbageGetValue "samples"
    SSample sprintfk "0%d.wav", kSliderValue
    a1 diskin2 SSample
 
    prints  SSample
   
    outs a1, a1
endin

</CsInstruments>
<CsScore>
i1 0 z
</CsScore>
</CsoundSynthesizer>
1 Like

@rorywalsh I have another question according to this.

Is it possible to send values/strings with each position of a knob?

For example:
Knob in Position 1 prints “Text1”

I know combobox can do it but I don’t know how to do it for a knob.

I already tried to send knob data to combobox with:

kSliderValue cabbageGetValue “Q”
cabbageSetValue “GM”, kSliderValue

But that I can’t get the string/text value.

Thanks so far!

Use a label, and then update the text dynamically based on your slider position.

That should work. It does here:

<Cabbage>
form caption("Test") size(370, 280), guiMode("queue"), colour(58, 110, 182), pluginId("pn01")
rslider bounds(12, 8, 85, 79), channel("Q"), range(0, 2, 0, 1, 1), text("Q")
combobox bounds(102, 10, 100, 25), channel("GM"), items("One", "Two", "Three")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>

instr 1
    kQ, kTrig cabbageGetValue "Q"
    cabbageSetValue "GM", kQ
endin

</CsInstruments>
<CsScore>
i1 0 z
</CsScore>
</CsoundSynthesizer>

Thanks! yes, thats what I have as well.

I want to read the items from the Combobox back as strings to reuse the strings.

Something like:

SQ, ktrig cabbageGetValue “GM”
prints “%s’\n”, SQ

But this gives me nothing.

I think it might be easier to create a string array that matches the items in the combobox - or use cabbageGet with text to get all the items from the combobox:

<Cabbage>
form caption("Test") size(370, 280), guiMode("queue"), colour(58, 110, 182), pluginId("pn01")
rslider bounds(12, 8, 85, 79), channel("Q"), range(0, 2, 0, 1, 1), text("Q")
combobox bounds(102, 10, 100, 25), channel("GM"), items("One", "Two", "Three")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>

instr 1
    SItems[] cabbageGet "GM", "text"
    kQ, kTrig cabbageGetValue "Q"
    cabbageSetValue "GM", kQ
    printf "Selected String %s\n", kTrig, SItems[kQ]
endin

</CsInstruments>
<CsScore>
i1 0 z
</CsScore>
</CsoundSynthesizer>

thats it @rorywalsh thank you so much!

Do I have thinking wrong when doing this?

printf should be smiliar to sprintf, no?

    SItems[] cabbageGet "GM", "text"
    kQ, kTrig cabbageGetValue "Q"
    cabbageSetValue "GM", kQ
   ; printf "Selected String %s\n", kTrig, SItems[kQ]
     Sdst sprintf "%s", kTrig, SItems[kQ]

thanks!

More like sprintfk, sprintf only runs at i-time, i.e, it’s only ever called once, when an instrument starts.

sprintfk gives me this:

Sdst sprintfk "%s" kTrig #S0

INIT ERROR in instr 1 (opcode sprintfk) line 17: sprintfk: Not string type for %%s

https://csound.com/docs/manual/sprintfk.html

Hi @rorywalsh
I didn’t found a solution with things I tried so far.
What it misses that it takes the strings and give it to diskin2 - similiar to this non working snippet:

instr 1
    SItems[] cabbageGet "GM", "text"
    kQ, kTrig cabbageGetValue "Q"
    cabbageSetValue "GM", kQ
    ;printf "Selected String %s\n", kTrig, SItems[kQ]
    SSample sprintfk "%s" , kQ ; try to get the items from "GM" Channel as string i.e One.wav and give it to next opcode diskin2
    a1 diskin2 SSample
endin

thank you very much!

You should trigger a new instrument that will play the sample whenever a user selects Q. Use the event opcode. I know you can’t pass strings to event’s p-fields, but you can set a channel in instrument 1 to be the current file:

chnset SItems[kQ], "filename"

And then in your diskin2 instrument read:

SFilename chnget "filename"

Btw, is this for a synth or an effect? I mean is instrument 1 been triggered each time you press a note, or is it always on?

Btw, did you see this thread?

1 Like

Hi @rorywalsh

thanks for the links and snippets. I wil go through them now!

ok @rorywalsh what I really try to do is in the following shematic. Maybe it explains better my intention. It would help a lot on load specific samples in a folder with many samples:

image

Another Example would be:

image

With 3 Knobs I can change trough Category, Class and Name.

thanks for you time you already invested here.

That’s what that previous link shows.

So are you trying to sum samples together, and then write them to disk so that diskin can read them back? Seems like a lot of overheard. Why not just play back the summed samples directly?

No, I try to identify a specific sample with this and then load into diskin2.

Samples might have this convention:

Category, Class, Name could lead to the following sample for example:
DRUMS_SNARE_SNARETOP

With this I would go to diskin2.

So we have 3 dimensions which can be called with 3 knobs (for ex. CAT, Class, Name).

Yes, but are you trying to join three samples together, and then play that back with diskin? Or pick a sequence of samples and paly them back one after another?