/* 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 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 destinations; /** * a list of clients */ readonly attribute sequence 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(); }; };