summaryrefslogtreecommitdiffstats
path: root/flow/artsflow.idl
blob: a728bcc01e8f7fa05c66c10e507bf75bbf205d93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
    /*

    Copyright (C) 2000 Stefan Westerfeld
                       [email protected]

    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();
};

};