|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (C) 2000 Stefan Westerfeld
|
|
|
|
stefan@space.twc.de
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* arts.idl - MCOP port. What's missing currently in MCOP?
|
|
|
|
*
|
|
|
|
* - namespaces (module)
|
|
|
|
*/
|
|
|
|
|
|
|
|
module Arts { // analog real time synthesizer
|
|
|
|
|
|
|
|
enum AutoSuspendState { asNoSuspend, asSuspend, asSuspendStop, asSuspendMask = 0x3,
|
|
|
|
asProducer = 0x10, asConsumer = 0x20, asDirectionMask = 0x30 };
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The SynthModule interface is the base for all modules containing streams.
|
|
|
|
*
|
|
|
|
* There are two goals achieved by this interface. On one side, there is
|
|
|
|
* functionality which users of stream carrying modules want to use (which
|
|
|
|
* is: start streaming, stop streaming).
|
|
|
|
*
|
|
|
|
* On the other hand, there is functionality which the flow system will use
|
|
|
|
* to achieve these goals.
|
|
|
|
*/
|
|
|
|
interface SynthModule {
|
|
|
|
// interface for users of this module
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function starts the streaming (e.g. the module will start
|
|
|
|
* producing samples) - if you write a module, do not reimplement this,
|
|
|
|
* instead reimplement streamInit/streamStart
|
|
|
|
*/
|
|
|
|
void start();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function stops the streaming - if you write a plugin, do not
|
|
|
|
* reimplement this, instead reimplement streamEnd
|
|
|
|
*/
|
|
|
|
void stop();
|
|
|
|
|
|
|
|
// interface for people implementing modules
|
|
|
|
|
|
|
|
/**
|
|
|
|
* this is supposed to be the initialization every module passes after
|
|
|
|
* all attributes have been set up (e.g. you can see which file to open,
|
|
|
|
* how to initialize your filter coefficients or whatever)
|
|
|
|
*/
|
|
|
|
void streamInit();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* starts the I/O of the module
|
|
|
|
*/
|
|
|
|
void streamStart();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* stop the thing again, and free data possibly allocated in streamInit
|
|
|
|
*/
|
|
|
|
void streamEnd();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If you run a mixer desk (without anything connected), no calculations
|
|
|
|
* need to be done - since the output is silent anyway. For this reason,
|
|
|
|
* there exists this autosuspend attribute. It allows the flow system
|
|
|
|
* to detect the idle condition, and start suspending the calculations,
|
|
|
|
* until something "important" happens again.
|
|
|
|
*
|
|
|
|
* There are three possible values:
|
|
|
|
*
|
|
|
|
* @li asNoSuspend - this one is appropriate when you have a module that
|
|
|
|
* is active by itself
|
|
|
|
* @li asSuspend - this one is appropriate for modules that "do nothing"
|
|
|
|
* by themselves
|
|
|
|
* @li asSuspendStop - this one is for modules that should be stopped, when
|
|
|
|
* the system gets suspended, and restarted when the
|
|
|
|
* system will start again - an example for this is
|
|
|
|
* soundcard output
|
|
|
|
*
|
|
|
|
* A module should choose asSuspend (or asSuspendStop) only if the
|
|
|
|
* following conditions are true:
|
|
|
|
*
|
|
|
|
* @li given constant inputs (like 3.0 on all ports), the module will
|
|
|
|
* give constant output after some time
|
|
|
|
* @li given only 0.0 inputs, the module will give only 0.0 outputs
|
|
|
|
* after some time
|
|
|
|
* @li the module does not synchronize itself through signal flow (i.e.
|
|
|
|
* a midi sequence which "knows" when a second has passed through
|
|
|
|
* the signal flow breaks when suspension happens)
|
|
|
|
* @li the module can't be brought to do something with a method
|
|
|
|
* invocation (i.e. a module which starts generating noise for
|
|
|
|
* a second whenever the noise() method is called is not suspendable)
|
|
|
|
* @li the module has no internal state that changes over time when only
|
|
|
|
* constant inputs are given
|
|
|
|
*
|
|
|
|
* Typical examples for suspendable modules are arithmetic operations,
|
|
|
|
* filters, delay/hall/reverb.
|
|
|
|
*
|
|
|
|
* Typical examples for non-suspendable modules are sequences, midi stuff,
|
|
|
|
* oscillators, sample players,...
|
|
|
|
*
|
|
|
|
* To deal with modules which either input data from some external source
|
|
|
|
* (i.e. soundcard input) or output data to some external destination,
|
|
|
|
* (i.e. soundcard output) the following flags are available:
|
|
|
|
*
|
|
|
|
* @li asProducer - set this flag for modules which fulfill the conditions
|
|
|
|
* for a suspendable module, but produce non-zero output
|
|
|
|
* even when left alone
|
|
|
|
* @li asConsumer - set this flag for modules which write the data to
|
|
|
|
* some external destination - that is - definitely
|
|
|
|
* require constant input to be suspended
|
|
|
|
*
|
|
|
|
* The suspension algorithm will first divide the graph of modules into
|
|
|
|
* subgraphs of interconnected modules. A subgraph is suspendable if
|
|
|
|
* all of its modules are suspendable and the subgraph does not contain
|
|
|
|
* producer(s) and consumer(s) at the same time.
|
|
|
|
*
|
|
|
|
* Finally, our module graph is suspendable if all its subgraphs are.
|
|
|
|
*/
|
|
|
|
readonly attribute AutoSuspendState autoSuspend;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Plays a stream of audio data to the soundcard
|
|
|
|
*/
|
|
|
|
interface Synth_PLAY : SynthModule {
|
|
|
|
// attribute string channels;
|
|
|
|
default in audio stream invalue_left,invalue_right;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Records a stream of audio data from the soundcard
|
|
|
|
*/
|
|
|
|
interface Synth_RECORD : SynthModule {
|
|
|
|
// attribute string channels;
|
|
|
|
default out audio stream left,right;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A frequency generator
|
|
|
|
*
|
|
|
|
* This kind of object is used to create frequencies. Oscillators are connected
|
|
|
|
* at the output of this object
|
|
|
|
*/
|
|
|
|
interface Synth_FREQUENCY : SynthModule {
|
|
|
|
in audio stream frequency;
|
|
|
|
out audio stream pos;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A sine wave
|
|
|
|
*/
|
|
|
|
interface Synth_WAVE_SIN : SynthModule {
|
|
|
|
in audio stream pos;
|
|
|
|
out audio stream outvalue;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A module which mixes an arbitary number of audio streams
|
|
|
|
*/
|
|
|
|
interface Synth_MULTI_ADD : SynthModule {
|
|
|
|
in multi audio stream invalue;
|
|
|
|
out audio stream outvalue;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A module which adds two audio streams
|
|
|
|
*/
|
|
|
|
interface Synth_ADD : SynthModule {
|
|
|
|
default in audio stream invalue1,invalue2;
|
|
|
|
out audio stream outvalue;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Multiplies two audio streams
|
|
|
|
*/
|
|
|
|
interface Synth_MUL : SynthModule {
|
|
|
|
in audio stream invalue1,invalue2;
|
|
|
|
out audio stream outvalue;
|
|
|
|
default invalue1, invalue2;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This plays a wave file
|
|
|
|
*/
|
|
|
|
interface Synth_PLAY_WAV : SynthModule {
|
|
|
|
/**
|
|
|
|
* How fast should it be played? 1.0 = normal speed
|
|
|
|
*/
|
|
|
|
attribute float speed;
|
|
|
|
/**
|
|
|
|
* Which file should be played
|
|
|
|
*/
|
|
|
|
attribute string filename;
|
|
|
|
/**
|
|
|
|
* Is true as soon as the file is finished
|
|
|
|
*/
|
|
|
|
readonly attribute boolean finished;
|
|
|
|
|
|
|
|
out audio stream left, right;
|
|
|
|
default left, right;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* sends data to a bus - busses are dynamic N:M connections - all signals
|
|
|
|
* from all uplinks are mixed together, and sent to all downlinks
|
|
|
|
*/
|
|
|
|
interface Synth_BUS_UPLINK : SynthModule {
|
|
|
|
/**
|
|
|
|
* the name of the bus to use
|
|
|
|
*/
|
|
|
|
attribute string busname;
|
|
|
|
|
|
|
|
default in audio stream left,right;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* receives data from a bus - busses are dynamic N:M connections - all signals
|
|
|
|
* from all uplinks are mixed together, and sent to all downlinks
|
|
|
|
*/
|
|
|
|
interface Synth_BUS_DOWNLINK : SynthModule {
|
|
|
|
/**
|
|
|
|
* the name of the bus to use
|
|
|
|
*/
|
|
|
|
attribute string busname;
|
|
|
|
|
|
|
|
default out audio stream left,right;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Byte stream to audio conversion object
|
|
|
|
*
|
|
|
|
* Converts an asynchronous byte stream to a synchronous audio stream
|
|
|
|
*/
|
|
|
|
interface ByteStreamToAudio : SynthModule {
|
|
|
|
attribute long samplingRate;
|
|
|
|
attribute long channels;
|
|
|
|
attribute long bits;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* is conversion currently running, or is it stalled due to the fact
|
|
|
|
* that there is not enough input input?
|
|
|
|
*/
|
|
|
|
readonly attribute boolean running;
|
|
|
|
|
|
|
|
async in byte stream indata;
|
|
|
|
|
|
|
|
out audio stream left,right;
|
|
|
|
default left;
|
|
|
|
default right;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Audio to Byte stream conversion object
|
|
|
|
*
|
|
|
|
* Converts a synchronous audio stream to an asynchronous byte stream
|
|
|
|
*/
|
|
|
|
interface AudioToByteStream : SynthModule {
|
|
|
|
attribute long samplingRate;
|
|
|
|
attribute long channels;
|
|
|
|
attribute long bits;
|
|
|
|
|
|
|
|
async out byte stream outdata;
|
|
|
|
|
|
|
|
in audio stream left,right;
|
|
|
|
default left;
|
|
|
|
default right;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Base interface for all stereo effects
|
|
|
|
*/
|
|
|
|
interface StereoEffect : SynthModule {
|
|
|
|
default in audio stream inleft, inright;
|
|
|
|
default out audio stream outleft, outright;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* this is a simple clipping stereo volume control
|
|
|
|
*/
|
|
|
|
interface StereoVolumeControl : StereoEffect {
|
|
|
|
attribute float scaleFactor;
|
|
|
|
readonly attribute float currentVolumeLeft;
|
|
|
|
readonly attribute float currentVolumeRight;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A funny FFT scope
|
|
|
|
*/
|
|
|
|
interface StereoFFTScope : StereoEffect {
|
|
|
|
readonly attribute sequence<float> scope;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A stack of stereo effects
|
|
|
|
*/
|
|
|
|
interface StereoEffectStack : StereoEffect {
|
|
|
|
/**
|
|
|
|
* inserts an effect at the top side (= directly after the input)
|
|
|
|
*
|
|
|
|
* @returns an ID which can be used to remove the effect again
|
|
|
|
*/
|
|
|
|
long insertTop(StereoEffect effect, string name);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* inserts an effect at the bottom (= close to the output) side
|
|
|
|
*
|
|
|
|
* @returns an ID which can be used to remove the effect again
|
|
|
|
*/
|
|
|
|
long insertBottom(StereoEffect effect, string name);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* removes an effect again
|
|
|
|
*/
|
|
|
|
void remove(long ID);
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Audio Manager stuff
|
|
|
|
*/
|
|
|
|
|
|
|
|
enum AudioManagerDirection { amPlay, amRecord };
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Information structure for audio manager clients
|
|
|
|
*/
|
|
|
|
struct AudioManagerInfo {
|
|
|
|
long ID;
|
|
|
|
string destination;
|
|
|
|
|
|
|
|
AudioManagerDirection direction;
|
|
|
|
string title, autoRestoreID;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* an audio manager client
|
|
|
|
*/
|
|
|
|
interface AudioManagerClient {
|
|
|
|
readonly attribute long ID;
|
|
|
|
attribute AudioManagerDirection direction;
|
|
|
|
attribute string title, autoRestoreID;
|
|
|
|
|
|
|
|
void constructor(AudioManagerDirection direction, string title,
|
|
|
|
string autoRestoreID);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The audio manager interface
|
|
|
|
*/
|
|
|
|
interface AudioManager {
|
|
|
|
/**
|
|
|
|
* a list of destinations, where you can play/record data to/from
|
|
|
|
*/
|
|
|
|
readonly attribute sequence<string> destinations;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* a list of clients
|
|
|
|
*/
|
|
|
|
readonly attribute sequence<AudioManagerInfo> clients;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* this is incremented each time a change is made (i.e. new client attached)
|
|
|
|
* TODO: SHOULD GO AWAY WITH ATTRIBUTE WATCHING
|
|
|
|
*/
|
|
|
|
readonly attribute long changes;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* this is used to route a client to another destination
|
|
|
|
*/
|
|
|
|
void setDestination(long ID, string destination);
|
|
|
|
};
|
|
|
|
/**
|
|
|
|
* This is a virtual output port, which you use to play data. Where exactly
|
|
|
|
* this data gets played is managed by the audiomanager.
|
|
|
|
*
|
|
|
|
* Creation: there are two ways to initialize a Synth_AMAN_PLAY - one is
|
|
|
|
* to set title and autoRestoreID to sensible (non empty) values. The other
|
|
|
|
* is to pass an already initialized AudioManagerClient on the constructor.
|
|
|
|
*/
|
|
|
|
interface Synth_AMAN_PLAY : SynthModule {
|
|
|
|
attribute string title, autoRestoreID;
|
|
|
|
void constructor(AudioManagerClient client);
|
|
|
|
|
|
|
|
default in audio stream left, right;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is a virtual input port, which you use to record data. Where this
|
|
|
|
* data comes from is in turn managed by the audiomanager.
|
|
|
|
*
|
|
|
|
* Creation: there are two ways to initialize a Synth_AMAN_RECORD - one is
|
|
|
|
* to set title and autoRestoreID to sensible (non empty) values. The other
|
|
|
|
* is to pass an already initialized AudioManagerClient on the constructor.
|
|
|
|
*/
|
|
|
|
interface Synth_AMAN_RECORD : SynthModule {
|
|
|
|
attribute string title, autoRestoreID;
|
|
|
|
void constructor(AudioManagerClient client);
|
|
|
|
|
|
|
|
default out audio stream left, right;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Wraps a datahandle. That is an abstraction for a float value array
|
|
|
|
* which can be directly loaded data from a file or have some
|
|
|
|
* processing stages in between (caching, reversing, cropping...)
|
|
|
|
* which are hidden to this interface.
|
|
|
|
* In contrast to the underlying C++ API, this datahandle is already
|
|
|
|
* open()ed after creation, so you can access its information (like
|
|
|
|
* channelCount) without further action.
|
|
|
|
* A datahandle normally has one more important function: read() which
|
|
|
|
* is not wrapped in MCOP because of the overhead of the data
|
|
|
|
* transfer. (If there is need for sth. like that in the future,
|
|
|
|
* one could maybe find a solution.)
|
|
|
|
*/
|
|
|
|
interface DataHandle {
|
|
|
|
readonly attribute long bitDepth;
|
|
|
|
readonly attribute long channelCount;
|
|
|
|
readonly attribute long valueCount;
|
|
|
|
/**
|
|
|
|
* error code open() returned
|
|
|
|
*/
|
|
|
|
readonly attribute long errorNo;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents a datahandle which delivers the data from the underlying
|
|
|
|
* sourceDatahandle in reverse order.
|
|
|
|
*/
|
|
|
|
interface ReversedDataHandle : DataHandle {
|
|
|
|
void init(DataHandle sourceHandle);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents a datahandle which delivers an "inner" part of the data
|
|
|
|
* from the underlying sourceDatahandle. You can cut away parts at the
|
|
|
|
* start and/or the end with this.
|
|
|
|
*/
|
|
|
|
interface CroppedDataHandle : DataHandle {
|
|
|
|
void init(DataHandle sourceHandle,
|
|
|
|
long headCutValueCount,
|
|
|
|
long tailCutValueCount);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Represents a datahandle which delivers the data from the underlying
|
|
|
|
* sourceDatahandle without the "inner" part containing the values
|
|
|
|
* [cutOffset..cutOffset+cutValueCount-1], which will be cut away.
|
|
|
|
*/
|
|
|
|
interface CutDataHandle : DataHandle {
|
|
|
|
void init(DataHandle sourceHandle,
|
|
|
|
long cutOffset,
|
|
|
|
long cutValueCount);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* DataHandlePlay uses a gsl_wave_osc to play back data from a
|
|
|
|
* DataHandle using sophisticated anti-aliasing filtering and caching
|
|
|
|
* techniques. (Though not implemented at the time of writing this, it
|
|
|
|
* will be optimized for cases where the anti-aliasing is not needed
|
|
|
|
* because the mixerFrequency equals the current soundserver's.)
|
|
|
|
*/
|
|
|
|
interface DataHandlePlay : SynthModule {
|
|
|
|
/**
|
|
|
|
* Which data should be played?
|
|
|
|
*/
|
|
|
|
attribute DataHandle handle;
|
|
|
|
/**
|
|
|
|
* What is the normal mixer frequency the data from the handle
|
|
|
|
* should be played back at? (default: current mixing frequency
|
|
|
|
* of the soundserver, e.g. 44100)
|
|
|
|
*/
|
|
|
|
attribute float mixerFrequency;
|
|
|
|
/**
|
|
|
|
* Which channel of the datahandle should by played?
|
|
|
|
* (defaults to 0 = the first channel)
|
|
|
|
*/
|
|
|
|
attribute long channelIndex;
|
|
|
|
/**
|
|
|
|
* How fast should the data be played?
|
|
|
|
* (defaults to 1.0 = normal speed, see mixerFrequency)
|
|
|
|
*/
|
|
|
|
attribute float speed;
|
|
|
|
/**
|
|
|
|
* Current position while playing, in fact it's the index in the
|
|
|
|
* datahandle, so 0 <= pos < handle.valueCount
|
|
|
|
*/
|
|
|
|
attribute long pos;
|
|
|
|
/**
|
|
|
|
* Is true as soon as the file is finished
|
|
|
|
*/
|
|
|
|
readonly attribute boolean finished;
|
|
|
|
/**
|
|
|
|
* Can be used to pause and/or continue playing
|
|
|
|
*/
|
|
|
|
attribute boolean paused;
|
|
|
|
|
|
|
|
default out audio stream outvalue;
|
|
|
|
|
|
|
|
DataHandlePlay clone();
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* DataHandle which represents sample data loaded from a file. Note
|
|
|
|
* that the samples from all channels are interleaved, that is, the
|
|
|
|
* samples of the first channel in a stereo file are found at offsets
|
|
|
|
* 0,2,4,6,.. etc.
|
|
|
|
*/
|
|
|
|
interface WaveDataHandle : DataHandle {
|
|
|
|
/**
|
|
|
|
* Properties of the loaded sample data. Note that those
|
|
|
|
* properties are only available from a WaveDataHandle, but may be
|
|
|
|
* available from a DataHandle in the future.
|
|
|
|
*/
|
|
|
|
readonly attribute float mixerFrequency;
|
|
|
|
readonly attribute float oscillatorFrequency;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load the first wavechunk from a file and return true on
|
|
|
|
* success. A more specific error code is not available at the
|
|
|
|
* moment.
|
|
|
|
*/
|
|
|
|
boolean load(string filename);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load a specific wavechunk from a file and return true on
|
|
|
|
* success. A more specific error code is not available at the
|
|
|
|
* moment.
|
|
|
|
*/
|
|
|
|
boolean load(string filename,
|
|
|
|
long waveIndex, long chunkIndex);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return true if and only if a wavechunk was successfully loaded
|
|
|
|
* from a file.
|
|
|
|
*/
|
|
|
|
readonly attribute boolean isLoaded;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a DataHandlePlay object with the important attributes
|
|
|
|
* handle, mixerFrequency and channelCount already set to play
|
|
|
|
* this WaveDataHandle.
|
|
|
|
*/
|
|
|
|
DataHandlePlay createPlayer();
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|