[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [sc-users] automated buffer -- How's that get in there?!?
Hi James (why pretend anyone else is still reading -- this must be
annoying... sorry everyone!)
Not at all, I think it's entirely on topic and probably pretty
educational.
This bit sets the watcher symbol to be universally recognized for use
by
routines, etc.
~watcher = NodeWatcher.newFrom(s);
Yep. It's mostly for efficiency. You could do NodeWatcher.newFrom(s)
every time but I think it's cleaner to do it once.
This bit uses the above nodewatcher to parse and categorize (and set?)
the
state of the buffers in the pool.
~stateManager = { |buffer, node, endState = \ready|
buffer.state = \busy; // don't let anyone else use this buffer
// below is to make sure the state changes when the
synth
stops
~watcher.register(node);
Updater(node, { |node, flag|
(flag == \n_end).if({
buffer.state = endState;
});
node.releaseDependants;
});
};
Yep. It does set the buffer states ... buffer.state = \something
These are my fake filters for which I have working replacements whose
names
must be registered for access in this global variable. I assume that I
should register (send.(s)) the synths to the server before doing this,
so
feasibly I'll have a list of synths that preceed the following.
Yes.
So this controls the playing and filtering of the soundfiles in
buffers, in
this case also controlling the recording process. The \recorder and
\player
synths would have to be registered previously with the filter
synthdefs. In
this case, you are using the weighted choose to record and play
soundfiles
%25 of the time (each) and %50 to filter the SFs.
Yes.
Could you describe what
is happening with the
~stateManager.value(buf1, node);
bit of code?
The ~stateManager environment variable holds a function whose job it is
to handle the buffer states. When you send the "value" message to a
function, it executes the function with the arguments in parentheses.
Rather than copy and paste the state manager code, I write it once and
call it in several places.
So, I dropped the above code into a file, added the pool definition at
the
beginning, dropped in a bunch of synths and after inserting some ')'s
and
'}'s places, everything registered with no errors. Of course, nothing
works
because I have no sound files. (and for other reasons, I'm sure)
I will need to record the sound files to the buffers myself,
independantly
from the above routine because the recordings will be time varying...
that
is, I'll make them when I have to : D.
So, to do this, I'll need to register a recording synth def...
something
like the following when I register the rest of my junk...
SynthDef(\recorder, { arg targetbufnum, outbus = 0;
var sig = AudioIn.ar(1);
RecordBuf.ar(sig, targetbufnum);
Out.ar(outbus, sig);
}).send(s);
(stole this bit and modified it so it won't work! Impressive, no?)
What about it isn't working?
One issue is that the Task I wrote assumes that the synths will release
themselves. Just add a line in there somewhere, it doesn't matter where
(just not before the variable declaration):
Line.kr(0, 1, BufDur.kr(targetbufnum), doneAction: 2);
So the recording will last exactly as long as there is space in the
buffer, and then will stop.
Then I'll need a way to parse the pool, etc, as with the routine. I've
nabbed the '\recorder' bit of code from the above routine and deleated
it so
nothing is accidentally thrown into a buffer, and I've started a
routine of
my own to handle the recordings only it doesn't seem like a routine is
the
best tool for the job.
Can you tell me if I'm making any sort of conceptual faux pas with the
"recorder" bit above?
I'm not clear on why the recorder needs to be in a separate routine,
but there shouldn't be any harm in doing it that way.
In addition, are there methods you find useful for collecting
information on
activities?... IOW, to see if anything is working? (like the
~pool.post;
above, which told me nothing, but more useful!)
Usually what I do is insert debugging statements into the routine
itself. Something like:
(
~rec = Routine({
var buf1, buf2, node;
n.do {
buf1 = ~pool.select({ |b| b.state == \empty
}).tryPerform(\choose);
buf1.debug("buffer selection");
buf1.notNil.if({
node = Synth(\recorder, [\targetbufnum,
buf1.buffer.bufnum]);
node.debug("started synth");
~stateManager.value(buf1, node);
});
}
})
)
Also you might add one to the state manager so that you get a printed
output when the Updater executes.
I must say that, despite my ongoing inability to grasp certain core
concepts
with the program, that I'm learning quite a bit, and having a blast!
(when
I'm not crying myself to sleep after bashing my face against my
disgusting
300-pound CRT out of frustration)
Patience! SuperCollider is not easy to learn, but (for me at least) the
power is worth it.
I know your site bio states that you received your PhD from Duke, did
you
study any of this sort of thing there? The "designing [your] own
software
for live algorithmic composition and performace" seems like you have a
history in programming as well?
Actually, I didn't get into any of this until about a year-and-a-half
after finishing. I taught myself programming when I was a kid (BASIC
and Pascal in junior high and C in high school). I never took computer
science classes so some of my code organization is quirky but I keep
getting better.
The line about designing my own software is partly marketing puffery,
but it's really true. Any time you write a piece in SuperCollider,
you're writing your own music software. Maybe people think calling them
"patches" is more modest, but I don't agree. Making a Max/PD patch is
still programming.
hjh
: H. James Harkins
: jamshark70@xxxxxxxxxxxxxxxxx
: http://www.dewdrop-world.net
.::!:.:.......:.::........:..!.::.::...:..:...:.:.:.:..:
"Come said the Muse,
Sing me a song no poet has yet chanted,
Sing me the universal." -- Whitman