As promised, here is my proposed API for a re-entrant Csound library that I
think will support building a DirectSound (ActiveMovie) transform filter or
plugin. I will gladly receive comments.
As you can see, the API is actually something a little bit more than that.
It is an abstract interface to a generic Csound-like synthesizer, so it
could be implemented using either Csound, or any other software synthesizer
that is fast enough, like Cmix or perhaps a speeded-up SAOLC.
#ifndef ISYNTHESIZER_H
#define ISYNTHESIZER_H
// I S Y N T H E S I Z E R
// Copyright (c) 1998 by Michael Gogins. All rights reserved.
// A U T H O R
// Michael Gogins
// P U R P O S E
// Defines the public abstract interface to a generic software synthesizer.
// Designed to be subclassed by various implementations of the interface,
e.g. Csound.
// I M P L E M E N T A T I O N R E Q U I R E M E N T S
// All functions must return true for success or false for failure.
// All return values must be passed by reference in arguments.
// Synchronization must be controlled by timestamp, as follows:
// Input drivers must call the synthesizer's input callbacks (push
processing).
// As soon as any input callback has received a new timestamp
// (within the granularity of ksmps),
// the synthesizer must handle all the received input data,
// compute all the output data for the previous timestamp,
// and call all the output callbacks with the previous timestamp.
// Some implementations may not require or permit input or output callbacks,
// in which case they must create their own inputs and outputs according to
option settings.
class ISynthesizer
{
public:
// Initialization.
virtual long open()=0;
virtual long close()=0;
// Informational log callback.
// Actual messages are implementation-dependent.
typedef static long (LogCallback)(ISynthesizer *synthesizer, double
timestamp, const char *message);
virtual long setLogCallback(LogCallback *callback);
// Options.
// Actual names and values are implementation-dependent.
virtual long getOption(const char *option, const char **value)=0;
virtual long setOption(const char *option, const char *value)=0;
// Sets options in a batch, e.g. the Csound command line.
virtual long getOptions(const char **commandLine)=0;
virtual long setOptions(const char *commandLine)=0;
// Synthesizer data is stored as well-formed Extensible Markup Language.
// Some elements are implementation-dependent (ISynthesizer id ==
implementation).
// Other elements are fixed for all implementations. Element tags are:
//
//
//
//
//
// text datatext data, e.g. Csound
instrument definition
//
//
// text datatext
data
//
//
// text data, e.g. pfields for Csound
//
//
// binary
data
//
//
// binary
data
//
//
virtual long read(const char *xmlFilename)=0;
virtual long write(const char *xmlFilename)=0;
// Real-time control.
virtual long initialize()=0;
virtual long cue(double timestamp)=0;
virtual long play()=0;
virtual long stop()=0;
virtual long pause()=0;
virtual long resume()=0;
// The format of commands is implementation-dependent, but commands could
be text representations of events.
typedef static long (CommandIOCallback)(ISynthesizer *synthesizer, double
timestamp, const char *command);
virtual long getCommandInputCallback(CommandIOCallback **callback)=0;
virtual long setCommandOutputCallback(CommandIOCallback *callback)=0;
// The format of events is implementation-dependent, but events could be
extended MIDI:
// p1 == Instrument number (same as low-order nybble of MIDI status, or
channel, + 1).
// p2 == Time in seconds.
// p3 == Duration in seconds (can be 0).
// p4 == Status (same as high-order nybble of MIDI status, plus additional
implementation-dependent values).
// p5 == Pitch (same as MIDI data byte 1, or key number).
// p6 == Loudness (same as MIDI data byte 2, or key velocity).
// p7 == Phase (in radians).
// p8 == X dimension of spatial location (in meters, listener at 0).
// p9 == Y dimension of spatial location (in meters, listener at 0).
// p10 == Z dimension of spatial location (in meters, listener at 0).
typedef static long (EventIOCallback)(ISynthesizer *synthesizer, double
timestamp, long pfieldCount, double *pfields);
virtual long getEventInputCallback(long bus, EventIOCallback **callback)=0;
virtual long setEventOutputCallback(long bus, EventIOCallback *callback)=0;
// Exactly ksmps * nchnls samples per timestamp.
typedef static long (AudioIOCallback)(ISynthesizer *synthesizer, double
timestamp, double *samples);
virtual long getAudioInputCallback(long bus, AudioIOCallback **callback,
long *ksmps, long *nchnls)=0;
virtual long setAudioOutputCallback(long bus, AudioIOCallback *callback,
long ksmps, long nchnls)=0;
};
#endif