I am using Eli Fieldsteel example code to load a sample library into Buffers. The sample library are packs from FreeSound, each pack has it folder name which will be loaded as a dictionary key. However, while some packs are being loaded properly, some do not. Here is the code:
(
s.options.memSize_(2.pow(20));
s.options.numBuffers_(4096); // the amount of sound files is ~1600
)
~path = PathName(thisProcess.nowExecutingPath).parentPath++"buffers/";
//3. define piece-specific functions
(
~makeBuffers = {
b = Dictionary.new;
PathName(~path).entries.do{
arg subfolder;
b.add(
subfolder.folderName.asSymbol ->
Array.fill(
subfolder.entries.size,
{
arg i;
postf("reading file % in folder '%' \n", i, subfolder.folderName);
Buffer.read(s, subfolder.entries[i].fullPath);
//Buffer.readChannel(s, subfolder.entries[i].fullPath, channels: [0]);
}
)
);
};
};
)
~makeBuffers.value();
I am getting the following error message when trying to play the b[\orchestra][1].play; above:
ERROR: a PlayBuf: wrong number of channels (nil)
PROTECTED CALL STACK:
MultiOutUGen:initOutputs 0000016CD7AA6540
arg this = a PlayBuf
arg numChannels = nil
arg rate = audio
a FunctionDef 0000016CD5697A80
sourceCode = "<an open Function>"
var player = nil
SynthDef:buildUgenGraph 0000016CD8B03900
arg this = SynthDef:temp__11
arg func = a Function
arg rates = nil
arg prependArgs = [ ]
var result = nil
var saveControlNames = [ ControlName P 0 i_out scalar 0 ]
a FunctionDef 0000016CD5765FC0
sourceCode = "<an open Function>"
arg i_out = an OutputProxy
var result = nil
var rate = nil
var env = nil
SynthDef:buildUgenGraph 0000016CD8B03900
arg this = SynthDef:temp__11
arg func = a Function
arg rates = nil
arg prependArgs = [ ]
var result = nil
var saveControlNames = nil
a FunctionDef 0000016CD8B01E80
sourceCode = "<an open Function>"
Function:prTry 0000016CD7464CC0
arg this = a Function
var result = nil
var thread = a Thread
var next = nil
var wasInProtectedFunc = false
CALL STACK:
Exception:reportError
arg this = <instance of Error>
Nil:handleError
arg this = nil
arg error = <instance of Error>
Thread:handleError
arg this = <instance of Thread>
arg error = <instance of Error>
Object:throw
arg this = <instance of Error>
Function:protect
arg this = <instance of Function>
arg handler = <instance of Function>
var result = <instance of Error>
SynthDef:build
arg this = <instance of SynthDef>
arg ugenGraphFunc = <instance of Function>
arg rates = nil
arg prependArgs = nil
Function:play
arg this = <instance of Function>
arg target = <instance of Group>
arg outbus = 0
arg fadeTime = 0.02
arg addAction = 'addToHead'
arg args = nil
var def = nil
var synth = nil
var server = <instance of Server>
var bytes = nil
var synthMsg = nil
Interpreter:interpretPrintCmdLine
arg this = <instance of Interpreter>
var res = nil
var func = <instance of Function>
var code = "b[\orchestra][10].play"
var doc = nil
var ideClass = <instance of Meta_ScIDE>
Process:interpretPrintCmdLine
arg this = <instance of Main>
^^ The preceding error dump is for ERROR: a PlayBuf: wrong number of channels (nil)
I’ve tried also Buffer.readChannels to load all of them as mono, but with no good result… How to solve? Is it something related to the assyncronous way that Buffer.read operates?
This way it won’t override whatever you have assigned to b and you can pass in the path, using it multiple times. It also returns the data, and allows nested folders, although only keys are assigned to the top level folder.
Use it like this:
Have you increased the server’s options object’s numBuffers? Help file says the default is 1024, but you’re trying to load over 1200. You’ll have to raise the limit.
Only to clarify a bit further: the problem is the Array.fill?
I don’t see where the overriding is occuring… Is the Dictionary’s b.add an override operation? If yes, I thought that it was only filling the each key once with a single call of Array.fill per key.
This is not working, so can I say that synchronization is not the issue then?
About this:
Yes, I’ve did it
but the only thing that solved the problem was the recursive search function.
This b does not exist inside the function, but globally. This overrides what ever the value was before.
In general, all the information that you need should be passed to a function through an argument, and all results should be returned through the function’s return. There are exceptions to this, but if you follow those rules it becomes easier to think about code.
But this wouldn’t be why it wasn’t working. If the code I posted works but the original doesn’t then I am unsure.
Nice piece of Code, thanks for sharing and sorry, for reopening the thread, I just wanted to go deeper into the code.
How would you go for avoiding no audio files to populate the event? Let’s say you have some folders in which there are text files or other metadata (reaper, Ableton).
Playing with your code, I came up with this (remove it from the event by looking for buffers), but there might be a more elegant way to do it.
There are many ways you could do this, but I think a list of acceptable file types is a good way to go. All you have to do is check the files types match before loading the buffer then use reject to get rid of the non buffers.