Subject: Re: [linux-audio-dev] Linux Audio plugin API's: where are we ?
From: James McCartney (asynth_AT_io.com)
Date: Wed Apr 05 2000 - 22:52:33 EEST
on 4/5/00 12:41 PM, Jim Coker at jcoker_AT_jguru.com wrote:
> James, you've mentioned before that you would like to add
> an API to SC to allow users to write their own unit generators
> for SC. How different would this API be from LADSPA
> or VST, other than the memory allocation and bounded
> start-up time issues?
That is an involved subject to get into here. SC plug ins are coming, so
better just to wait and see what it looks like. SC plugins are basically C++
objects and you override a few virtual methods. The API is quite different
from LADSPA. Other requirements of SC include allowing audio rate, control
rate or scalar data to be patched to any input, and subgraphs with different
block sizes.
Version 3 of SC which I am now working on is even more dynamic than version
2.
SC unit generators are quite simple to write for simple ugens though.
Here is a sawtooth generator which is about as simple as you can get.
It has 4 inputs: frequency, initial phase, mul, add. The last two inputs are
handled by the MulAddUnit superclass and have almost no overhead if they are
set to 1, 0 respectively.
Not shown here is a bit of glue code to place the C++ object in the
SuperCollider language object. In many cases you can just do a one line
template function call to do this.
There is more to the API than you can see here for such a simple ugen..
class LFSaw : public MulAddUnit
{
public:
LFSaw(World* inWorld, int inCalcRate, void* inClientData);
protected:
virtual void InputsChanged();
virtual void Reset();
private:
void next_a(int inNumSamples);
void next_k(int inNumSamples);
Samp mPhase, mFreqMul;
Input mIn[4];
};
LFSaw::LFSaw(World* inWorld, int inCalcRate, void* inClientData)
: MulAddUnit(inWorld, inCalcRate, inClientData), mPhase(0.f)
{
// The MulAdd superclass handles the multiply-add inputs.
MakeInputs(4, mIn); // create the inputs.
// Input 0 is frequency and responds at any rate, which is the default.
// So no SetReadRate call is necessary for it.
// Even though any rate is accepted, the initial phase input is only
// read upon a reset.
SetReadRate(1, read_Reset);
}
// Called at startup and any time an input gets repatched.
// Its responsibility is to choose a run function appropriate to the
// inputs.
void LFSaw::InputsChanged()
{
if (InputRate(0) == calc_FullRate) {
SetRunFunc((UnitFunc)&LFSaw::next_a);
} else {
SetRunFunc((UnitFunc)&LFSaw::next_k);
}
}
// Called at startup - all inputs have a valid first sample value
void LFSaw::Reset()
{
MulAddUnit::Reset();
mFreqMul = 2.f * SampleDur(); // calc freq multiplier
mPhase = ZIN0(1); // get initial phase
next_k(1); // calculate first output sample
// SC unit generators are required to provide their first output sample.
// This is so that linear interpolated control rate signals
// will have a starting value, and also useful for other reasons,
// like setting initial phase upon a reset..
// If you do not calculate an initial output value, it defaults to zero.
}
// run method for audio rate frequency input
void LFSaw::next_a(int inNumSamples)
{
Samp *out = ZOUT(0);
Samp *freq = ZIN(0);
Samp freqmul = mFreqMul;
Samp phase = mPhase;
// the LOOP and Zxx macros allow me to set compiler switches
// and recompile with either for or while loops or pre or post
// increment indexing as appropriate for the processor/compiler.
LOOP(inNumSamples,
Samp z = phase; // out must be written last for in place operation
phase += ZXP(freq) * freqmul;
if (phase >= 1.f) phase -= 2.f;
else if (phase <= -1.) phase += 2.f;
ZXP(out) = z;
);
mPhase = phase;
MulAdd(inNumSamples);
}
// run method for control rate or scalar frequency input
void LFSaw::next_k(int inNumSamples)
{
Samp *out = ZOUT(0);
Samp freq = ZIN0(0) * mFreqMul;
Samp phase = mPhase;
if (phase >= 0.f) {
LOOP(inNumSamples,
ZXP(out) = phase;
phase += freq;
if (phase >= 1.f) phase -= 2.f;
);
} else {
LOOP(inNumSamples,
ZXP(out) = phase;
phase += freq;
if (phase <= -1.f) phase += 2.f;
);
}
mPhase = phase;
MulAdd(inNumSamples);
}
--- james mccartney james_AT_audiosynth.com <http://www.audiosynth.com>
SuperCollider - a real time synthesis programming language for the PowerMac.
<ftp://www.audiosynth.com/pub/updates/SC2.2.7.sea.hqx>
This archive was generated by hypermail 2b28 : Thu Apr 06 2000 - 00:27:28 EEST