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.
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.
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
This is fixed now.
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?
That tiny region is the current position. Think of it like a scrubber in a DAW, although it might be a little too wide
I thought this white line was the scrubber?
Dear God you’re right! I’ll get that sorted
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>
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
[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…
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.
Nice! I will test later today
Do I need to set the filepath to a state?
No. That should be auto saved by session.