Cabbage Logo
Back to Cabbage Site

Does selecting a range in soundfiler produce a output?

Hello,

I notice that you can select a range in the soundfiler by left-clicking and dragging. Does this produce any output, or does it have no function? Just curious, since I stumbled upon it by accident.

image

Certainly does. The soundfiler widget takes two channels, which can be used to get the starting sample and region length. More details here: https://cabbageaudio.com/docs/soundfiler/#channel

Interesting! I tried to read the docs, but I didn’t get this info from there. Maybe include that info in that paragraph?

I think it might be bugged though. If you drag from start to end it works nice, but if you drag from end to start, it prints 0 for this example.

<Cabbage>
form caption("Stretch") size(600, 500), guiMode("queue"), pluginId("1287"), colour (0,100,0)
keyboard bounds(102, 380, 381, 95)

rslider bounds(378, 302, 60, 60) channel("Speed") range(0.001, 1, 1, 1, 0.001)
soundfiler bounds(110, 52, 300, 200), channel("Soundfiler1", "Soundfiler2"), colour(188, 188, 188), tableBackgroundColour(62, 71, 86), showScrubber(1), displayType("mono")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1

instr 98
    gSfile cabbageGet "LAST_FILE_DROPPED"

    if (changed(gSfile) == 1) then
        cabbageSet 1, "Soundfiler1", "file", gSfile
    endif
endin

instr 1
    iSpeed cabbageGetValue "Speed"
    iSoundfiler1 cabbageGetValue "Soundfiler1"
    iSoundfiler2 cabbageGetValue "Soundfiler2"
    
    printk 1, k(iSoundfiler2)

    // Table upload
    iSampleLength filelen    gSfile 
    iSr filesr    gSfile 
    iCh filenchnls  gSfile
    iTableSize = (iSampleLength*iSr)
    iSampleLengthFreq = (1/iSampleLength)

    if (iCh == 1) then
        iSoundFileL ftgen 0, 0, iTableSize, 1, gSfile, 0, 0, 1
    elseif (iCh == 2) then
        iSoundFileL ftgen 0, 0, iTableSize, 1, gSfile, 0, 0, 1
        iSoundFileR ftgen 0, 0, iTableSize, 1, gSfile, 0, 0, 2
    endif

    aTimeWarpLoopPhasor phasor iSampleLengthFreq * iSpeed

    cabbageSet metro(60), "Soundfiler", sprintfk("scrubberPosition(%d)", k(aTimeWarpLoopPhasor)*iTableSize)
endin
</CsInstruments>
<CsScore>
f0 z

i98 0 z
</CsScore>
</CsoundSynthesizer>

Thanks for the example code, I’ll take a look when I get a chance :slightly_smiling_face:

This is fixed now. :+1:

1 Like

Thank you, works great now.

I also notice that when you click the soundfiler to release the region, there’s still a tiny region visible. Wouldn’t it make more sense if it just disappeared, to avoid any confusion?

image

That tiny region is the current position. Think of it like a scrubber in a DAW, although it might be a little too wide :thinking:

I thought this white line was the scrubber?

image

Dear God you’re right! :rofl: I’ll get that sorted :+1:

Sorted now. In this example the scrubber is placed where the click takes place.

<Cabbage>
form caption("Soundfiler") size(600, 300), guiMode("queue"), pluginId("1287"), colour (0,100,0)
soundfiler bounds(0, 0, 500, 200), channel("Soundfiler1", "Soundfiler2"), file("C:/Users/rory/OneDrive/Csoundfiles/pianoMood.wav") colour(188, 188, 188), tableBackgroundColour(62, 71, 86), showScrubber(1), displayType("mono")
</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1


instr 1
    kSoundfiler1, kTrig1 cabbageGetValue "Soundfiler1"
    kSoundfiler2, kTrig2 cabbageGetValue "Soundfiler2"    
    printf "Start %d, duration in samples %d\n", kTrig1+kTrig2, kSoundfiler1, kSoundfiler2
    cabbageSet kTrig1, "Soundfiler1", "scrubberPosition", kSoundfiler1
endin
</CsInstruments>
<CsScore>
f0 z
i1 0 z
</CsScore>
</CsoundSynthesizer>
1 Like

Works great. I was wondering, has the soundfiler with region marking been tested with a preset-system? (presetbutton)

It seems to be missing the Soundfiler2 channel inside the .psts file. Also, Soundfiler1 contains the file path, not the regionStart number.

Would it make sense to have 3 channels, one for the file path, one for the region start, and one for the region length?

<Cabbage>
form caption("Stretch") size(600, 500), guiMode("queue"), pluginId("1287"), colour (0,100,0)
keyboard bounds(102, 380, 381, 95)
rslider bounds(378, 302, 60, 60) channel("Speed") range(0.001, 1, 1, 1, 0.001)
soundfiler bounds(110, 52, 300, 200), channel("Soundfiler1", "Soundfiler2"), colour(188, 188, 188), tableBackgroundColour(62, 71, 86), showScrubber(1), displayType("mono")

presetbutton bounds(24, 14, 120, 23), channel("PresetChannel"), colour:0(16, 19, 22, 255), fontColour(176, 176, 176), textColour(176, 176, 176), presetNameAsText(1), factoryFolder("#USER_APPLICATION_DATA_DIRECTORY/CabbageTest/Soundfiler/Presets/Factory", "*.psts"), userFolder("#USER_APPLICATION_DATA_DIRECTORY/CabbageTest/Soundfiler/Presets/User", "*.psts"), highlightedItemColour(200, 200, 200) highlightedTextColour(25, 25, 25), outlineColour(44, 47, 49), outlineThickness(1), corners(2)

</Cabbage>
<CsoundSynthesizer>
<CsOptions>
-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5
</CsOptions>
<CsInstruments>
; Initialize the global variables. 
ksmps = 32
nchnls = 2
0dbfs = 1

instr 98
    gSfile cabbageGet "LAST_FILE_DROPPED"

    if (changed(gSfile) == 1) then
        cabbageSet 1, "Soundfiler1", "file", gSfile
    endif
endin

instr 1
    iSpeed cabbageGetValue "Speed"
    iSoundfiler1 cabbageGetValue "Soundfiler1"
    iSoundfiler2 cabbageGetValue "Soundfiler2"
    
    printk 1, k(iSoundfiler1)

    // Table upload
    iSampleLength filelen    gSfile 
    iSr filesr    gSfile 
    iCh filenchnls  gSfile
    iTableSize = (iSampleLength*iSr)
    iSampleLengthFreq = (1/iSampleLength)

    if (iCh == 1) then
        iSoundFileL ftgen 0, 0, iTableSize, 1, gSfile, 0, 0, 1
    elseif (iCh == 2) then
        iSoundFileL ftgen 0, 0, iTableSize, 1, gSfile, 0, 0, 1
        iSoundFileR ftgen 0, 0, iTableSize, 1, gSfile, 0, 0, 2
    endif

    aTimeWarpLoopPhasor phasor iSampleLengthFreq * iSpeed

    cabbageSet metro(60), "Soundfiler", sprintfk("scrubberPosition(%d)", k(aTimeWarpLoopPhasor)*iTableSize)
endin
</CsInstruments>
<CsScore>
f0 z

i98 0 z
</CsScore>
</CsoundSynthesizer>

I am not sure, but I don’t recall giving it any attention.

That’s because back in the day, soundfiler’s didn’t have any channels. It seems I will need to revisit this then. Leave it with me :+1:

[edit] this is going to take a bit of work as each widget currently has only one value associated with it when it comes to presets. Could take a day or two…

1 Like

I’ve pushed a fix for this now, but didn’t have much time to really test it. I did however check the preset files and they are now saving the data correctly. The region seems to be recalled without a problem, and I’m also saving the scrubber position, which I wasn’t doing before.

The one issue for now is that the DAW session still doesn’t pick up this data. That’s the next thing to sort out but it will probably involve me consolidating the session state data and the preset data method, which will involve a bit of a rewrite. It will lead to code that is easier to maintain, but it’s going to take a little longer to get it done. And It won’t happen before Monday at the very earliest.

Thanks. Will it use 3 channels now? Do you have an example of the new implementation of soundfiler in the Cabbage-section?

Nothing changes for the end user. Just the internal way of saving things had been updated. But as you’ve already seen in other changes, this could cause some issues when people re-export and try to open an older daw session. There really isn’t a way around

Just an update on this. I am almost finished the internal rewrite. In a few more days I’ll be ready to push to the develop branch for testing. :+1:

1 Like

You can try now @hdale94 I just pushed some changes through.

Nice! I will test later today :grinning:

Do I need to set the filepath to a state?

No. That should be auto saved by session. :+1: